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
44typedef 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
66typedef 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
88static inline msgpack_type bytes_internal_to_msgpack_type(uint8_t type, uint32_t len);
89
90static inline const uint8_t *msgpack_sz_table(const uint8_t *buf, const uint8_t * const end, uint32_t *count, bool *has_nonstorage);
91static inline const uint8_t *msgpack_sz_internal(const uint8_t *buf, const uint8_t * const end, uint32_t count, bool *has_nonstorage);
92
93static inline uint64_t extract_uint64(const uint8_t *ptr, int i);
94static inline uint64_t extract_neg_int64(const uint8_t *ptr, int i);
95static inline void cmp_parse_container(parse_meta *meta, uint32_t count);
96static 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
127uint32_t
128msgpack_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
145msgpack_cmp_t
146msgpack_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
179msgpack_cmp_t
180msgpack_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
202static inline msgpack_type
203bytes_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
220static inline const uint8_t *
221msgpack_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
362static inline const uint8_t *
363msgpack_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
378static inline uint64_t
379extract_uint64(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
385static inline uint64_t
386extract_neg_int64(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
392static inline void
393cmp_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
441static inline void
442msgpack_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
730static inline msgpack_cmp_t
731msgpack_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