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