cursor.h (7326B)
1 2 #ifndef CURSOR_H 3 #define CURSOR_H 4 5 #include <stdio.h> 6 #include <assert.h> 7 #include <string.h> 8 #include "hex.h" 9 10 #define unlikely(x) __builtin_expect((x),0) 11 #define likely(x) __builtin_expect((x),1) 12 13 struct cursor { 14 unsigned char *start; 15 unsigned char *p; 16 unsigned char *end; 17 }; 18 19 struct array { 20 struct cursor cur; 21 unsigned int elem_size; 22 }; 23 24 static inline void reset_cursor(struct cursor *cursor) 25 { 26 cursor->p = cursor->start; 27 } 28 29 static inline void wipe_cursor(struct cursor *cursor) 30 { 31 reset_cursor(cursor); 32 memset(cursor->start, 0, cursor->end - cursor->start); 33 } 34 35 static inline void make_cursor(unsigned char *start, unsigned char *end, struct cursor *cursor) 36 { 37 cursor->start = start; 38 cursor->p = start; 39 cursor->end = end; 40 } 41 42 static inline void make_array(struct array *a, unsigned char* start, unsigned char *end, unsigned int elem_size) 43 { 44 make_cursor(start, end, &a->cur); 45 a->elem_size = elem_size; 46 } 47 48 static inline int cursor_eof(struct cursor *c) 49 { 50 return c->p == c->end; 51 } 52 53 static inline void *cursor_malloc(struct cursor *mem, unsigned long size) 54 { 55 void *ret; 56 57 if (mem->p + size > mem->end) { 58 return NULL; 59 } 60 61 ret = mem->p; 62 mem->p += size; 63 64 return ret; 65 } 66 67 static inline void *cursor_alloc(struct cursor *mem, unsigned long size) 68 { 69 void *ret; 70 if (!(ret = cursor_malloc(mem, size))) { 71 return 0; 72 } 73 74 memset(ret, 0, size); 75 return ret; 76 } 77 78 static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size) 79 { 80 unsigned char *p; 81 if (!(p = cursor_alloc(mem, size))) { 82 return 0; 83 } 84 make_cursor(p, mem->p, slice); 85 return 1; 86 } 87 88 89 static inline void copy_cursor(struct cursor *src, struct cursor *dest) 90 { 91 dest->start = src->start; 92 dest->p = src->p; 93 dest->end = src->end; 94 } 95 96 static inline int pull_byte(struct cursor *cursor, unsigned char *c) 97 { 98 if (unlikely(cursor->p + 1 > cursor->end)) 99 return 0; 100 101 *c = *cursor->p; 102 cursor->p++; 103 104 return 1; 105 } 106 107 static inline int cursor_pull_c_str(struct cursor *cursor, const char **str) 108 { 109 *str = (const char*)cursor->p; 110 111 for (; cursor->p < cursor->end; cursor->p++) { 112 if (*cursor->p == 0) { 113 cursor->p++; 114 return 1; 115 } 116 } 117 118 return 0; 119 } 120 121 122 static inline int cursor_push_byte(struct cursor *cursor, unsigned char c) 123 { 124 if (unlikely(cursor->p + 1 > cursor->end)) { 125 return 0; 126 } 127 128 *cursor->p = c; 129 cursor->p++; 130 131 return 1; 132 } 133 134 static inline int cursor_pull(struct cursor *cursor, unsigned char *data, int len) 135 { 136 if (unlikely(cursor->p + len > cursor->end)) { 137 return 0; 138 } 139 140 memcpy(data, cursor->p, len); 141 cursor->p += len; 142 143 return 1; 144 } 145 146 static inline int pull_data_into_cursor(struct cursor *cursor, 147 struct cursor *dest, 148 unsigned char **data, 149 int len) 150 { 151 int ok; 152 153 if (unlikely(dest->p + len > dest->end)) { 154 printf("not enough room in dest buffer\n"); 155 return 0; 156 } 157 158 ok = cursor_pull(cursor, dest->p, len); 159 if (!ok) return 0; 160 161 *data = dest->p; 162 dest->p += len; 163 164 return 1; 165 } 166 167 static inline int cursor_dropn(struct cursor *cur, int size, int n) 168 { 169 if (n == 0) 170 return 1; 171 172 if (unlikely(cur->p - size*n < cur->start)) { 173 return 0; 174 } 175 176 cur->p -= size*n; 177 return 1; 178 } 179 180 static inline int cursor_drop(struct cursor *cur, int size) 181 { 182 return cursor_dropn(cur, size, 1); 183 } 184 185 static inline unsigned char *cursor_topn(struct cursor *cur, int len, int n) 186 { 187 n += 1; 188 if (unlikely(cur->p - len*n < cur->start)) { 189 return NULL; 190 } 191 return cur->p - len*n; 192 } 193 194 static inline unsigned char *cursor_top(struct cursor *cur, int len) 195 { 196 if (unlikely(cur->p - len < cur->start)) { 197 return NULL; 198 } 199 return cur->p - len; 200 } 201 202 static inline int cursor_top_int(struct cursor *cur, int *i) 203 { 204 unsigned char *p; 205 if (unlikely(!(p = cursor_top(cur, sizeof(*i))))) { 206 return 0; 207 } 208 *i = *((int*)p); 209 return 1; 210 } 211 212 static inline int cursor_pop(struct cursor *cur, unsigned char *data, int len) 213 { 214 if (unlikely(cur->p - len < cur->start)) { 215 return 0; 216 } 217 218 cur->p -= len; 219 memcpy(data, cur->p, len); 220 221 return 1; 222 } 223 224 static inline int cursor_push(struct cursor *cursor, unsigned char *data, int len) 225 { 226 if (unlikely(cursor->p + len >= cursor->end)) { 227 return 0; 228 } 229 230 if (cursor->p != data) 231 memcpy(cursor->p, data, len); 232 233 cursor->p += len; 234 235 return 1; 236 } 237 238 static inline int cursor_push_int(struct cursor *cursor, int i) 239 { 240 return cursor_push(cursor, (unsigned char*)&i, sizeof(i)); 241 } 242 243 static inline int cursor_len(struct cursor *cursor) 244 { 245 return cursor->p - cursor->start; 246 } 247 248 static inline size_t cursor_count(struct cursor *cursor, size_t elem_size) 249 { 250 return cursor_len(cursor)/elem_size; 251 } 252 253 static inline int cursor_pull_int(struct cursor *cursor, int *i) 254 { 255 return cursor_pull(cursor, (unsigned char*)i, sizeof(*i)); 256 } 257 258 static inline int cursor_pull_u16(struct cursor *cursor, uint16_t *i) 259 { 260 return cursor_pull(cursor, (unsigned char*)i, sizeof(*i)); 261 } 262 263 #define BSWAP_16(val) \ 264 ((((uint16_t)(val) & 0x00ff) << 8) \ 265 | (((uint16_t)(val) & 0xff00) >> 8)) 266 267 static inline uint16_t bswap_16(uint16_t val) 268 { 269 return BSWAP_16(val); 270 } 271 272 static inline int cursor_push_u16(struct cursor *cursor, unsigned short i) 273 { 274 return cursor_push(cursor, (unsigned char*)&i, sizeof(i)); 275 } 276 277 static int cursor_pull_b16(struct cursor *c, uint16_t *s) 278 { 279 if (!cursor_pull_u16(c, s)) 280 return 0; 281 282 // we assume little endian 283 *s = bswap_16(*s); 284 return 1; 285 } 286 287 static int cursor_push_b16(struct cursor *c, uint16_t s) 288 { 289 if (!cursor_push_u16(c, bswap_16(s))) 290 return 0; 291 return 1; 292 } 293 294 static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size) 295 { 296 unsigned char *p; 297 p = &cursor->start[elem_size * index]; 298 299 if (unlikely(p >= cursor->end)) 300 return NULL; 301 302 return (void*)p; 303 } 304 305 306 static inline int push_sized_str(struct cursor *cursor, const char *str, int len) 307 { 308 return cursor_push(cursor, (unsigned char*)str, len); 309 } 310 311 static inline int cursor_push_str(struct cursor *cursor, const char *str) 312 { 313 return cursor_push(cursor, (unsigned char*)str, strlen(str)); 314 } 315 316 static inline int cursor_push_c_str(struct cursor *cursor, const char *str) 317 { 318 return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0); 319 } 320 321 static inline int cursor_remaining_capacity(struct cursor *cursor) 322 { 323 return cursor->end - cursor->p; 324 } 325 326 static inline int cursor_push_hex(struct cursor *c, const void *buf, size_t bufsize) 327 { 328 int size; 329 size = hex_encode(buf, bufsize, (char *)c->p, c->end - c->p); 330 if (!size) 331 return 0; 332 c->p += bufsize * 2; 333 return 1; 334 } 335 336 337 #define max(a,b) ((a) > (b) ? (a) : (b)) 338 static inline void cursor_print_around(struct cursor *cur, int range) 339 { 340 unsigned char *c; 341 342 printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start); 343 344 c = max(cur->p - range, cur->start); 345 for (; c < cur->end && c < (cur->p + range); c++) { 346 printf("%02x", *c); 347 } 348 printf("\n"); 349 350 c = max(cur->p - range, cur->start); 351 for (; c < cur->end && c < (cur->p + range); c++) { 352 if (c == cur->p) { 353 printf("^"); 354 continue; 355 } 356 printf(" "); 357 } 358 printf("\n"); 359 } 360 #undef max 361 362 static inline int cursor_memset(struct cursor *cursor, unsigned char c, int n) 363 { 364 if (cursor->p + n >= cursor->end) 365 return 0; 366 367 memset(cursor->p, c, n); 368 cursor->p += n; 369 370 return 1; 371 } 372 373 374 static inline int cursor_align(struct cursor *cur, int bytes) { 375 size_t size = cur->p - cur->start; 376 int pad; 377 378 // pad to n-byte alignment 379 pad = ((size + (bytes-1)) & ~(bytes-1)) - size; 380 if (pad > 0 && !cursor_memset(cur, 0, pad)) 381 return 0; 382 383 return 1; 384 } 385 386 #endif