1 | /* |
2 | * msgpack_in.c |
3 | * |
4 | * Copyright (C) 2019 Aerospike, Inc. |
5 | * |
6 | * Portions may be licensed to Aerospike, Inc. under one or more contributor |
7 | * license agreements. |
8 | * |
9 | * This program is free software: you can redistribute it and/or modify it under |
10 | * the terms of the GNU Affero General Public License as published by the Free |
11 | * Software Foundation, either version 3 of the License, or (at your option) any |
12 | * later version. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
16 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
17 | * details. |
18 | * |
19 | * You should have received a copy of the GNU Affero General Public License |
20 | * along with this program. If not, see http://www.gnu.org/licenses/ |
21 | */ |
22 | |
23 | #include "base/msgpack_in.h" |
24 | |
25 | #include <stdbool.h> |
26 | #include <stdint.h> |
27 | #include <string.h> |
28 | |
29 | #include "aerospike/as_types.h" |
30 | #include "citrusleaf/alloc.h" |
31 | #include "citrusleaf/cf_byte_order.h" |
32 | |
33 | #include "fault.h" |
34 | |
35 | |
36 | //========================================================== |
37 | // Typedefs & constants. |
38 | // |
39 | |
40 | #define CMP_EXT_TYPE 0xFF |
41 | #define CMP_WILDCARD 0x00 |
42 | #define CMP_INF 0x01 |
43 | |
44 | typedef enum { |
45 | TYPE_ERROR, |
46 | TYPE_NIL, |
47 | TYPE_FALSE, |
48 | TYPE_TRUE, |
49 | TYPE_NEGINT, |
50 | TYPE_INT, |
51 | TYPE_STRING, |
52 | TYPE_LIST, |
53 | TYPE_MAP, |
54 | TYPE_BYTES, |
55 | TYPE_DOUBLE, |
56 | TYPE_GEOJSON, |
57 | |
58 | TYPE_EXT, |
59 | // Non-storage types, need to be after storage types. |
60 | TYPE_CMP_WILDCARD, // not a storage type |
61 | TYPE_CMP_INF, // not a storage type, must be last (biggest value) |
62 | |
63 | MSGPACK_TYPE_COUNT |
64 | } msgpack_type; |
65 | |
66 | typedef struct { |
67 | const uint8_t *buf; |
68 | const uint8_t * const end; |
69 | |
70 | union { |
71 | const uint8_t *data; |
72 | uint64_t i_num; |
73 | double d_num; |
74 | }; |
75 | |
76 | uint32_t remain; |
77 | uint32_t len; |
78 | msgpack_type type; |
79 | bool has_nonstorage; |
80 | |
81 | } parse_meta; |
82 | |
83 | |
84 | //========================================================== |
85 | // Forward declarations. |
86 | // |
87 | |
88 | static inline msgpack_type bytes_internal_to_msgpack_type(uint8_t type, uint32_t len); |
89 | |
90 | static inline const uint8_t *msgpack_sz_table(const uint8_t *buf, const uint8_t * const end, uint32_t *count, bool *has_nonstorage); |
91 | static inline const uint8_t *msgpack_sz_internal(const uint8_t *buf, const uint8_t * const end, uint32_t count, bool *has_nonstorage); |
92 | |
93 | static inline uint64_t extract_uint64(const uint8_t *ptr, int i); |
94 | static inline uint64_t extract_neg_int64(const uint8_t *ptr, int i); |
95 | static inline void cmp_parse_container(parse_meta *meta, uint32_t count); |
96 | static inline msgpack_cmp_t msgpack_cmp_internal(parse_meta *meta0, parse_meta *meta1); |
97 | |
98 | |
99 | //========================================================== |
100 | // Macros. |
101 | // |
102 | |
103 | #define MSGPACK_CMP_RETURN(__p0, __p1) \ |
104 | if ((__p0) > (__p1)) { \ |
105 | return MSGPACK_CMP_GREATER; \ |
106 | } \ |
107 | else if ((__p0) < (__p1)) { \ |
108 | return MSGPACK_CMP_LESS; \ |
109 | } |
110 | |
111 | #define SZ_PARSE_BUF_CHECK(__buf, __end, __sz) \ |
112 | if ((__buf) + (__sz) > (__end)) { \ |
113 | return NULL; \ |
114 | } |
115 | |
116 | #define CMP_PARSE_BUF_CHECK(__m, __sz) \ |
117 | if ((__m)->buf + (__sz) > (__m)->end) { \ |
118 | (__m)->buf = NULL; \ |
119 | return; \ |
120 | } |
121 | |
122 | |
123 | //========================================================== |
124 | // Public API. |
125 | // |
126 | |
127 | uint32_t |
128 | msgpack_sz_rep(msgpack_in *mp, uint32_t rep_count) |
129 | { |
130 | const uint8_t * const start = mp->buf + mp->offset; |
131 | const uint8_t * const buf = msgpack_sz_internal(start, mp->buf + mp->buf_sz, |
132 | rep_count, &mp->has_nonstorage); |
133 | |
134 | if (buf == NULL) { |
135 | return 0; |
136 | } |
137 | |
138 | uint32_t sz = buf - start; |
139 | |
140 | mp->offset += sz; |
141 | |
142 | return sz; |
143 | } |
144 | |
145 | msgpack_cmp_t |
146 | msgpack_cmp(msgpack_in *mp0, msgpack_in *mp1) |
147 | { |
148 | parse_meta meta0 = { |
149 | .buf = mp0->buf + mp0->offset, |
150 | .end = mp0->buf + mp0->buf_sz, |
151 | .remain = 1 |
152 | }; |
153 | |
154 | parse_meta meta1 = { |
155 | .buf = mp1->buf + mp1->offset, |
156 | .end = mp1->buf + mp1->buf_sz, |
157 | .remain = 1 |
158 | }; |
159 | |
160 | msgpack_cmp_t ret = msgpack_cmp_internal(&meta0, &meta1); |
161 | |
162 | meta0.buf = msgpack_sz_internal(meta0.buf, meta0.end, meta0.remain, |
163 | &meta0.has_nonstorage); |
164 | meta1.buf = msgpack_sz_internal(meta1.buf, meta1.end, meta1.remain, |
165 | &meta1.has_nonstorage); |
166 | |
167 | if (meta0.buf == NULL || meta1.buf == NULL) { |
168 | return MSGPACK_CMP_ERROR; |
169 | } |
170 | |
171 | mp0->has_nonstorage = meta0.has_nonstorage; |
172 | mp1->has_nonstorage = meta1.has_nonstorage; |
173 | mp0->offset = meta0.buf - mp0->buf; |
174 | mp1->offset = meta1.buf - mp1->buf; |
175 | |
176 | return ret; |
177 | } |
178 | |
179 | msgpack_cmp_t |
180 | msgpack_cmp_peek(const msgpack_in *mp0, const msgpack_in *mp1) |
181 | { |
182 | parse_meta meta0 = { |
183 | .buf = mp0->buf + mp0->offset, |
184 | .end = mp0->buf + mp0->buf_sz, |
185 | .remain = 1 |
186 | }; |
187 | |
188 | parse_meta meta1 = { |
189 | .buf = mp1->buf + mp1->offset, |
190 | .end = mp1->buf + mp1->buf_sz, |
191 | .remain = 1 |
192 | }; |
193 | |
194 | return msgpack_cmp_internal(&meta0, &meta1); |
195 | } |
196 | |
197 | |
198 | //========================================================== |
199 | // Local helpers. |
200 | // |
201 | |
202 | static inline msgpack_type |
203 | bytes_internal_to_msgpack_type(uint8_t type, uint32_t len) |
204 | { |
205 | if (len == 0) { |
206 | return TYPE_BYTES; |
207 | } |
208 | |
209 | if (type == AS_BYTES_STRING) { |
210 | return TYPE_STRING; |
211 | } |
212 | else if (type == AS_BYTES_GEOJSON) { |
213 | return TYPE_GEOJSON; |
214 | } |
215 | |
216 | // All other types are considered BYTES. |
217 | return TYPE_BYTES; |
218 | } |
219 | |
220 | static inline const uint8_t * |
221 | msgpack_sz_table(const uint8_t *buf, const uint8_t * const end, uint32_t *count, |
222 | bool *has_nonstorage) |
223 | { |
224 | SZ_PARSE_BUF_CHECK(buf, end, 1); |
225 | |
226 | uint8_t b = *buf++; |
227 | |
228 | switch (b) { |
229 | case 0xc0: // nil |
230 | case 0xc3: // boolean true |
231 | case 0xc2: // boolean false |
232 | return buf; |
233 | |
234 | case 0xd0: // signed 8 bit integer |
235 | case 0xcc: // unsigned 8 bit integer |
236 | return buf + 1; |
237 | |
238 | case 0xd1: // signed 16 bit integer |
239 | case 0xcd: // unsigned 16 bit integer |
240 | return buf + 2; |
241 | |
242 | case 0xca: // float |
243 | case 0xd2: // signed 32 bit integer |
244 | case 0xce: // unsigned 32 bit integer |
245 | return buf + 4; |
246 | |
247 | case 0xcb: // double |
248 | case 0xd3: // signed 64 bit integer |
249 | case 0xcf: // unsigned 64 bit integer |
250 | return buf + 8; |
251 | |
252 | case 0xc4: |
253 | case 0xd9: // string/raw bytes with 8 bit header |
254 | SZ_PARSE_BUF_CHECK(buf, end, 1); |
255 | return buf + 1 + *buf; |
256 | |
257 | case 0xc5: |
258 | case 0xda: // string/raw bytes with 16 bit header |
259 | SZ_PARSE_BUF_CHECK(buf, end, 2); |
260 | return buf + 2 + cf_swap_from_be16(*(uint16_t *)buf); |
261 | |
262 | case 0xc6: |
263 | case 0xdb: // string/raw bytes with 32 bit header |
264 | SZ_PARSE_BUF_CHECK(buf, end, 4); |
265 | return buf + 4 + cf_swap_from_be32(*(uint32_t *)buf); |
266 | |
267 | case 0xdc: // list with 16 bit header |
268 | SZ_PARSE_BUF_CHECK(buf, end, 2); |
269 | *count += cf_swap_from_be16(*(uint16_t *)buf); |
270 | return buf + 2; |
271 | case 0xdd: { // list with 32 bit header |
272 | SZ_PARSE_BUF_CHECK(buf, end, 4); |
273 | *count += cf_swap_from_be32(*(uint32_t *)buf); |
274 | return buf + 4; |
275 | } |
276 | case 0xde: // map with 16 bit header |
277 | SZ_PARSE_BUF_CHECK(buf, end, 2); |
278 | *count += 2 * cf_swap_from_be16(*(uint16_t *)buf); |
279 | return buf + 2; |
280 | case 0xdf: // map with 32 bit header |
281 | SZ_PARSE_BUF_CHECK(buf, end, 4); |
282 | *count += 2 * cf_swap_from_be32(*(uint32_t *)buf); |
283 | return buf + 4; |
284 | |
285 | case 0xd4: // fixext 1 |
286 | SZ_PARSE_BUF_CHECK(buf, end, 1); |
287 | |
288 | if (*buf == CMP_EXT_TYPE) { |
289 | *has_nonstorage = true; |
290 | } |
291 | |
292 | return buf + 1 + 1; |
293 | case 0xd5: // fixext 2 |
294 | SZ_PARSE_BUF_CHECK(buf, end, 1); |
295 | |
296 | if (*buf == CMP_EXT_TYPE) { |
297 | *has_nonstorage = true; |
298 | } |
299 | |
300 | return buf + 1 + 2; |
301 | case 0xd6: // fixext 4 |
302 | return buf + 1 + 4; |
303 | case 0xd7: // fixext 8 |
304 | return buf + 1 + 8; |
305 | case 0xd8: // fixext 16 |
306 | return buf + 1 + 16; |
307 | case 0xc7: // ext 8 |
308 | SZ_PARSE_BUF_CHECK(buf, end, 2); |
309 | |
310 | if (*(buf + 1) == CMP_EXT_TYPE && *buf < 4 && *buf != 0) { |
311 | *has_nonstorage = true; |
312 | } |
313 | |
314 | return buf + 1 + 1 + *buf; |
315 | case 0xc8: { // ext 16 |
316 | SZ_PARSE_BUF_CHECK(buf, end, 3); |
317 | |
318 | uint32_t len = cf_swap_from_be16(*(uint16_t *)buf); |
319 | |
320 | if (*(buf + 2) == CMP_EXT_TYPE && len < 4 && len != 0) { |
321 | *has_nonstorage = true; |
322 | } |
323 | |
324 | return buf + 2 + 1 + len; |
325 | } |
326 | case 0xc9: { // ext 32 |
327 | SZ_PARSE_BUF_CHECK(buf, end, 5); |
328 | |
329 | uint32_t len = cf_swap_from_be32(*(uint32_t *)buf); |
330 | |
331 | if (*(buf + 4) == CMP_EXT_TYPE && len < 4 && len != 0) { |
332 | *has_nonstorage = true; |
333 | } |
334 | |
335 | return buf + 4 + 1 + len; |
336 | } |
337 | default: |
338 | break; |
339 | } |
340 | |
341 | if (b < 0x80 || b >= 0xe0) { // 8 bit combined integer |
342 | return buf; |
343 | } |
344 | |
345 | if ((b & 0xe0) == 0xa0) { // raw bytes with 8 bit combined header |
346 | return buf + (b & 0x1f); |
347 | } |
348 | |
349 | if ((b & 0xf0) == 0x80) { // map with 8 bit combined header |
350 | *count += 2 * (b & 0x0f); |
351 | return buf; |
352 | } |
353 | |
354 | if ((b & 0xf0) == 0x90) { // list with 8 bit combined header |
355 | *count += b & 0x0f; |
356 | return buf; |
357 | } |
358 | |
359 | return NULL; |
360 | } |
361 | |
362 | static inline const uint8_t * |
363 | msgpack_sz_internal(const uint8_t *buf, const uint8_t * const end, |
364 | uint32_t count, bool *has_nonstorage) |
365 | { |
366 | for (uint32_t i = 0; i < count; i++) { |
367 | buf = msgpack_sz_table(buf, end, &count, has_nonstorage); |
368 | |
369 | if (buf > end || buf == NULL) { |
370 | cf_warning(AS_PARTICLE, "msgpack_sz_internal: invalid at i %u count %u" , i, count); |
371 | return NULL; |
372 | } |
373 | } |
374 | |
375 | return buf; |
376 | } |
377 | |
378 | static inline uint64_t |
379 | (const uint8_t *ptr, int i) |
380 | { |
381 | const uint64_t *p64 = (const uint64_t *)(ptr - 8 + (1 << i)); |
382 | return cf_swap_from_be64(*p64) & ((~0ULL) >> (64 - 8 * (1 << i))); // little endian mask |
383 | } |
384 | |
385 | static inline uint64_t |
386 | (const uint8_t *ptr, int i) |
387 | { |
388 | const uint64_t *p64 = (const uint64_t *)(ptr - 8 + (1 << i)); |
389 | return cf_swap_from_be64(*p64) | ~((~0ULL) >> (64 - 8 * (1 << i))); // little endian mask |
390 | } |
391 | |
392 | static inline void |
393 | cmp_parse_container(parse_meta *meta, uint32_t count) |
394 | { |
395 | if (meta->len == 0) { |
396 | return; |
397 | } |
398 | |
399 | const uint8_t *buf = meta->buf; |
400 | uint8_t type; |
401 | |
402 | CMP_PARSE_BUF_CHECK(meta, 1); |
403 | |
404 | switch (*buf++) { |
405 | case 0xd4: |
406 | case 0xd5: |
407 | case 0xd6: |
408 | case 0xd7: |
409 | case 0xd8: |
410 | CMP_PARSE_BUF_CHECK(meta, 1); |
411 | type = *buf; |
412 | break; |
413 | case 0xc7: |
414 | CMP_PARSE_BUF_CHECK(meta, 2); |
415 | type = *(buf + 1); |
416 | break; |
417 | case 0xc8: |
418 | CMP_PARSE_BUF_CHECK(meta, 3); |
419 | type = *(buf + 2); |
420 | break; |
421 | case 0xc9: |
422 | CMP_PARSE_BUF_CHECK(meta, 5); |
423 | type = *(buf + 4); |
424 | break; |
425 | default: |
426 | // not an ext type |
427 | return; |
428 | } |
429 | |
430 | if (type == CMP_EXT_TYPE) { |
431 | // non-storage type |
432 | return; |
433 | } |
434 | |
435 | // skip meta elements |
436 | meta->buf = msgpack_sz_internal(meta->buf, meta->end, count, |
437 | &meta->has_nonstorage); |
438 | meta->len -= count; |
439 | } |
440 | |
441 | static inline void |
442 | msgpack_cmp_parse(parse_meta *meta) |
443 | { |
444 | CMP_PARSE_BUF_CHECK(meta, 1); |
445 | |
446 | uint8_t b = *meta->buf++; |
447 | |
448 | switch (b) { |
449 | case 0xc0: // nil |
450 | meta->type = TYPE_NIL; |
451 | return; |
452 | case 0xc3: // boolean true |
453 | meta->type = TYPE_TRUE; |
454 | return; |
455 | case 0xc2: // boolean false |
456 | meta->type = TYPE_FALSE; |
457 | return; |
458 | |
459 | case 0xd0: // signed 8 bit integer |
460 | CMP_PARSE_BUF_CHECK(meta, 1); |
461 | |
462 | if ((*meta->buf & 0x80) != 0) { |
463 | meta->i_num = (uint64_t)(int8_t)*meta->buf; |
464 | meta->buf++; |
465 | meta->type = TYPE_NEGINT; |
466 | return; |
467 | } |
468 | // no break |
469 | case 0xcc: // unsigned 8 bit integer |
470 | CMP_PARSE_BUF_CHECK(meta, 1); |
471 | meta->i_num = (uint64_t)*meta->buf; |
472 | meta->buf++; |
473 | meta->type = TYPE_INT; |
474 | return; |
475 | |
476 | case 0xd1: // signed 16 bit integer |
477 | case 0xd2: // signed 32 bit integer |
478 | case 0xd3: // signed 64 bit integer |
479 | b &= 0x0f; |
480 | CMP_PARSE_BUF_CHECK(meta, 1 << b); |
481 | |
482 | if ((*meta->buf & 0x80) != 0) { |
483 | meta->i_num = extract_neg_int64(meta->buf, b); |
484 | meta->buf += 1 << b; |
485 | meta->type = TYPE_NEGINT; |
486 | return; |
487 | } |
488 | |
489 | meta->i_num = extract_uint64(meta->buf, b); |
490 | meta->buf += 1 << b; |
491 | meta->type = TYPE_INT; |
492 | return; |
493 | |
494 | case 0xcd: // unsigned 16 bit integer |
495 | case 0xce: // unsigned 32 bit integer |
496 | case 0xcf: // unsigned 64 bit integer |
497 | b -= 0xcc; |
498 | CMP_PARSE_BUF_CHECK(meta, 1 << b); |
499 | |
500 | meta->i_num = extract_uint64(meta->buf, b); |
501 | meta->buf += 1 << b; |
502 | meta->type = TYPE_INT; |
503 | return; |
504 | |
505 | case 0xca: { // float |
506 | CMP_PARSE_BUF_CHECK(meta, 4); |
507 | |
508 | uint32_t i = cf_swap_from_be32(*(uint32_t *)meta->buf); |
509 | |
510 | meta->d_num = (double)*(float *)&i; |
511 | meta->buf += 4; |
512 | meta->type = TYPE_DOUBLE; |
513 | break; |
514 | } |
515 | case 0xcb: { // double |
516 | CMP_PARSE_BUF_CHECK(meta, 8); |
517 | |
518 | uint64_t i = cf_swap_from_be64(*(uint64_t *)meta->buf); |
519 | |
520 | meta->d_num = *(double *)&i; |
521 | meta->buf += 8; |
522 | meta->type = TYPE_DOUBLE; |
523 | return; |
524 | } |
525 | |
526 | case 0xc4: |
527 | case 0xd9: // string/raw bytes with 8 bit header |
528 | CMP_PARSE_BUF_CHECK(meta, 1); |
529 | meta->data = meta->buf + 1; |
530 | meta->len = *meta->buf; |
531 | meta->buf += 1 + meta->len; |
532 | CMP_PARSE_BUF_CHECK(meta, 0); |
533 | meta->type = bytes_internal_to_msgpack_type(*meta->data, meta->len); |
534 | return; |
535 | |
536 | case 0xc5: |
537 | case 0xda: // string/raw bytes with 16 bit header |
538 | CMP_PARSE_BUF_CHECK(meta, 2); |
539 | meta->data = meta->buf + 2; |
540 | meta->len = cf_swap_from_be16(*(uint16_t *)meta->buf); |
541 | meta->buf += 2 + meta->len; |
542 | CMP_PARSE_BUF_CHECK(meta, 0); |
543 | meta->type = bytes_internal_to_msgpack_type(*meta->data, meta->len); |
544 | return; |
545 | |
546 | case 0xc6: |
547 | case 0xdb: // string/raw bytes with 32 bit header |
548 | CMP_PARSE_BUF_CHECK(meta, 4); |
549 | meta->data = meta->buf + 4; |
550 | meta->len = cf_swap_from_be32(*(uint32_t *)meta->buf); |
551 | meta->buf += 4 + meta->len; |
552 | CMP_PARSE_BUF_CHECK(meta, 0); |
553 | meta->type = bytes_internal_to_msgpack_type(*meta->data, meta->len); |
554 | return; |
555 | |
556 | case 0xdc: { // list with 16 bit header |
557 | CMP_PARSE_BUF_CHECK(meta, 2); |
558 | meta->len = cf_swap_from_be16(*(uint16_t *)meta->buf); |
559 | meta->buf += 2; |
560 | meta->type = TYPE_LIST; |
561 | cmp_parse_container(meta, 1); |
562 | return; |
563 | } |
564 | case 0xdd: { // list with 32 bit header |
565 | CMP_PARSE_BUF_CHECK(meta, 4); |
566 | meta->len = cf_swap_from_be32(*(uint32_t *)meta->buf); |
567 | meta->buf += 4; |
568 | meta->type = TYPE_LIST; |
569 | cmp_parse_container(meta, 1); |
570 | return; |
571 | } |
572 | case 0xde: // map with 16 bit header |
573 | CMP_PARSE_BUF_CHECK(meta, 2); |
574 | meta->len = 2 * cf_swap_from_be16(*(uint16_t *)meta->buf); |
575 | meta->buf += 2; |
576 | meta->type = TYPE_MAP; |
577 | cmp_parse_container(meta, 2); |
578 | return; |
579 | case 0xdf: // map with 32 bit header |
580 | CMP_PARSE_BUF_CHECK(meta, 4); |
581 | meta->len = 2 * cf_swap_from_be32(*(uint32_t *)meta->buf); |
582 | meta->buf += 4; |
583 | meta->type = TYPE_MAP; |
584 | cmp_parse_container(meta, 2); |
585 | return; |
586 | |
587 | case 0xd4: // fixext 1 |
588 | meta->len = 1; |
589 | |
590 | if (*meta->buf++ == CMP_EXT_TYPE) { |
591 | meta->has_nonstorage = true; |
592 | |
593 | if (*meta->buf == CMP_WILDCARD) { |
594 | meta->buf++; |
595 | meta->type = TYPE_CMP_WILDCARD; |
596 | return; |
597 | } |
598 | |
599 | if (*meta->buf == CMP_INF) { |
600 | meta->buf++; |
601 | meta->type = TYPE_CMP_INF; |
602 | return; |
603 | } |
604 | } |
605 | |
606 | meta->data = meta->buf; |
607 | meta->type = TYPE_EXT; |
608 | meta->buf++; |
609 | return; |
610 | case 0xd5: // fixext 2 |
611 | meta->len = 2; |
612 | |
613 | if (*meta->buf++ == CMP_EXT_TYPE) { |
614 | meta->has_nonstorage = true; |
615 | } |
616 | |
617 | meta->data = meta->buf; |
618 | meta->buf += 2; |
619 | meta->type = TYPE_EXT; |
620 | return; |
621 | case 0xd6: // fixext 4 |
622 | meta->len = 4; |
623 | meta->data = ++meta->buf; |
624 | meta->buf += 4; |
625 | meta->type = TYPE_EXT; |
626 | return; |
627 | case 0xd7: // fixext 8 |
628 | meta->len = 8; |
629 | meta->data = ++meta->buf; |
630 | meta->buf += 8; |
631 | meta->type = TYPE_EXT; |
632 | return; |
633 | case 0xd8: // fixext 16 |
634 | meta->len = 16; |
635 | meta->data = ++meta->buf; |
636 | meta->buf += 16; |
637 | meta->type = TYPE_EXT; |
638 | return; |
639 | case 0xc7: // ext 8 |
640 | meta->len = *meta->buf++; |
641 | |
642 | if (*meta->buf++ == CMP_EXT_TYPE && meta->len < 4 && meta->len != 0) { |
643 | meta->has_nonstorage = true; |
644 | |
645 | if (meta->len == 1) { |
646 | if (*meta->buf == CMP_WILDCARD) { |
647 | meta->buf++; |
648 | meta->type = TYPE_CMP_WILDCARD; |
649 | return; |
650 | } |
651 | |
652 | if (*meta->buf == CMP_INF) { |
653 | meta->buf++; |
654 | meta->type = TYPE_CMP_INF; |
655 | return; |
656 | } |
657 | } |
658 | } |
659 | |
660 | meta->data = meta->buf; |
661 | meta->buf += meta->len; |
662 | meta->type = TYPE_EXT; |
663 | return; |
664 | case 0xc8: { // ext 16 |
665 | meta->len = cf_swap_from_be16(*(uint16_t *)meta->buf); |
666 | meta->buf += 2; |
667 | |
668 | if (*meta->buf++ == CMP_EXT_TYPE && meta->len < 4 && meta->len != 0) { |
669 | meta->has_nonstorage = true; |
670 | } |
671 | |
672 | meta->buf += meta->len; |
673 | meta->type = TYPE_EXT; |
674 | return; |
675 | } |
676 | case 0xc9: { // ext 32 |
677 | meta->len = cf_swap_from_be32(*(uint32_t *)meta->buf); |
678 | meta->buf += 4; |
679 | |
680 | if (*meta->buf++ == CMP_EXT_TYPE && meta->len < 4 && meta->len != 0) { |
681 | meta->has_nonstorage = true; |
682 | } |
683 | |
684 | meta->buf += meta->len; |
685 | meta->type = TYPE_EXT; |
686 | return; |
687 | } |
688 | |
689 | default: |
690 | break; |
691 | } |
692 | |
693 | if (b < 0x80) { // 8 bit combined unsigned integer |
694 | meta->i_num = b; |
695 | meta->type = TYPE_INT; |
696 | return; |
697 | } |
698 | if (b >= 0xe0) { // 8 bit combined negative integer |
699 | meta->i_num = (uint64_t)(int8_t)b; |
700 | meta->type = TYPE_NEGINT; |
701 | return; |
702 | } |
703 | |
704 | if ((b & 0xe0) == 0xa0) { // raw bytes with 8 bit combined header |
705 | meta->data = meta->buf; |
706 | meta->len = b & 0x1f; |
707 | meta->buf += meta->len; |
708 | CMP_PARSE_BUF_CHECK(meta, 0); |
709 | meta->type = bytes_internal_to_msgpack_type(*meta->data, meta->len); |
710 | return; |
711 | } |
712 | |
713 | if ((b & 0xf0) == 0x80) { // map with 8 bit combined header |
714 | meta->len = 2 * (b & 0x0f); |
715 | meta->type = TYPE_MAP; |
716 | cmp_parse_container(meta, 2); |
717 | return; |
718 | } |
719 | |
720 | if ((b & 0xf0) == 0x90) { // list with 8 bit combined header |
721 | meta->len = b & 0x0f; |
722 | meta->type = TYPE_LIST; |
723 | cmp_parse_container(meta, 1); |
724 | return; |
725 | } |
726 | |
727 | meta->type = TYPE_ERROR; |
728 | } |
729 | |
730 | static inline msgpack_cmp_t |
731 | msgpack_cmp_internal(parse_meta *meta0, parse_meta *meta1) |
732 | { |
733 | uint32_t min_count = 1; |
734 | msgpack_cmp_t end_result = MSGPACK_CMP_EQUAL; |
735 | |
736 | for (uint32_t i = 0; i < min_count; i++) { |
737 | meta0->remain--; |
738 | meta1->remain--; |
739 | |
740 | msgpack_cmp_parse(meta0); |
741 | msgpack_cmp_parse(meta1); |
742 | |
743 | if (meta0->buf == NULL || meta0->type == TYPE_ERROR || |
744 | meta0->buf > meta0->end || |
745 | meta1->buf == NULL || meta1->type == TYPE_ERROR || |
746 | meta1->buf > meta1->end) { |
747 | return MSGPACK_CMP_ERROR; |
748 | } |
749 | |
750 | if (meta0->type != meta1->type) { |
751 | if (meta0->type == TYPE_LIST || meta0->type == TYPE_MAP) { |
752 | meta0->remain += meta0->len; |
753 | } |
754 | |
755 | if (meta1->type == TYPE_LIST || meta1->type == TYPE_MAP) { |
756 | meta1->remain += meta1->len; |
757 | } |
758 | } |
759 | |
760 | if (meta0->type == TYPE_CMP_WILDCARD || |
761 | meta1->type == TYPE_CMP_WILDCARD) { |
762 | return MSGPACK_CMP_EQUAL; |
763 | } |
764 | |
765 | MSGPACK_CMP_RETURN(meta0->type, meta1->type); |
766 | |
767 | switch (meta0->type) { |
768 | case TYPE_NIL: |
769 | case TYPE_FALSE: |
770 | case TYPE_TRUE: |
771 | break; |
772 | case TYPE_NEGINT: |
773 | case TYPE_INT: |
774 | MSGPACK_CMP_RETURN(meta0->i_num, meta1->i_num); |
775 | break; |
776 | |
777 | case TYPE_EXT: |
778 | case TYPE_STRING: |
779 | case TYPE_BYTES: |
780 | case TYPE_GEOJSON: { |
781 | size_t len = (meta0->len < meta1->len) ? meta0->len : meta1->len; |
782 | int cmp = memcmp(meta0->data, meta1->data, len); |
783 | |
784 | MSGPACK_CMP_RETURN(cmp, 0); |
785 | MSGPACK_CMP_RETURN(meta0->len, meta1->len); |
786 | |
787 | break; |
788 | } |
789 | |
790 | case TYPE_LIST: |
791 | if (meta0->len == meta1->len) { |
792 | meta0->remain += meta0->len; |
793 | meta1->remain += meta1->len; |
794 | min_count += meta0->len; |
795 | break; |
796 | } |
797 | |
798 | min_count = meta0->len; |
799 | end_result = MSGPACK_CMP_LESS; |
800 | |
801 | if (min_count > meta1->len) { |
802 | min_count = meta1->len; |
803 | end_result = MSGPACK_CMP_GREATER; |
804 | } |
805 | |
806 | meta0->remain += meta0->len; |
807 | meta1->remain += meta1->len; |
808 | min_count += i + 1; |
809 | |
810 | break; |
811 | case TYPE_MAP: |
812 | meta0->remain += meta0->len; |
813 | meta1->remain += meta1->len; |
814 | MSGPACK_CMP_RETURN(meta0->len, meta1->len); |
815 | min_count += meta0->len; |
816 | break; |
817 | |
818 | case TYPE_DOUBLE: |
819 | MSGPACK_CMP_RETURN(meta0->d_num, meta1->d_num); |
820 | break; |
821 | |
822 | default: |
823 | break; |
824 | } |
825 | } |
826 | |
827 | return end_result; |
828 | } |
829 | |