095063fefdaef304b3329aa0663474abee75ac6a
[sim/e2-interface.git] / e2sim / asn1c / INTEGER.c
1 /*
2  * Copyright (c) 2003-2019 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <INTEGER.h>
8 #include <errno.h>
9 #include <inttypes.h>
10
11 /*
12  * INTEGER basic type description.
13  */
14 static const ber_tlv_tag_t asn_DEF_INTEGER_tags[] = {
15     (ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
16 };
17 asn_TYPE_operation_t asn_OP_INTEGER = {
18     INTEGER_free,
19 #if !defined(ASN_DISABLE_PRINT_SUPPORT)
20     INTEGER_print,
21 #else
22     0,
23 #endif  /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
24     INTEGER_compare,
25 #if !defined(ASN_DISABLE_BER_SUPPORT)
26     ber_decode_primitive,
27     INTEGER_encode_der,
28 #else
29     0,
30     0,
31 #endif  /* !defined(ASN_DISABLE_BER_SUPPORT) */
32 #if !defined(ASN_DISABLE_XER_SUPPORT)
33     INTEGER_decode_xer,
34     INTEGER_encode_xer,
35 #else
36     0,
37     0,
38 #endif  /* !defined(ASN_DISABLE_XER_SUPPORT) */
39 #if !defined(ASN_DISABLE_JER_SUPPORT)
40     INTEGER_encode_jer,
41 #else
42     0,
43 #endif  /* !defined(ASN_DISABLE_JER_SUPPORT) */
44 #if !defined(ASN_DISABLE_OER_SUPPORT)
45     INTEGER_decode_oer,  /* OER decoder */
46     INTEGER_encode_oer,  /* Canonical OER encoder */
47 #else
48     0,
49     0,
50 #endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
51 #if !defined(ASN_DISABLE_UPER_SUPPORT)
52     INTEGER_decode_uper,  /* Unaligned PER decoder */
53     INTEGER_encode_uper,  /* Unaligned PER encoder */
54 #else
55     0,
56     0,
57 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) */
58 #if !defined(ASN_DISABLE_APER_SUPPORT)
59     INTEGER_decode_aper,  /* Aligned PER decoder */
60     INTEGER_encode_aper,  /* Aligned PER encoder */
61 #else
62     0,
63     0,
64 #endif  /* !defined(ASN_DISABLE_APER_SUPPORT) */
65 #if !defined(ASN_DISABLE_RFILL_SUPPORT)
66     INTEGER_random_fill,
67 #else
68     0,
69 #endif  /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
70 0  /* Use generic outmost tag fetcher */
71 };
72 asn_TYPE_descriptor_t asn_DEF_INTEGER = {
73     "INTEGER",
74     "INTEGER",
75     &asn_OP_INTEGER,
76     asn_DEF_INTEGER_tags,
77     sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
78     asn_DEF_INTEGER_tags,       /* Same as above */
79     sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]),
80     {
81 #if !defined(ASN_DISABLE_OER_SUPPORT)
82         0,
83 #endif  /* !defined(ASN_DISABLE_OER_SUPPORT) */
84 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
85         0,
86 #endif  /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
87         asn_generic_no_constraint
88     },
89     0, 0,  /* No members */
90     0  /* No specifics */
91 };
92
93 /*
94  * INTEGER specific human-readable output.
95  */
96 ssize_t
97 INTEGER__dump(const asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) {
98     const asn_INTEGER_specifics_t *specs =
99         (const asn_INTEGER_specifics_t *)td->specifics;
100         char scratch[32];
101         uint8_t *buf = st->buf;
102         uint8_t *buf_end = st->buf + st->size;
103         intmax_t value;
104         ssize_t wrote = 0;
105         char *p;
106         int ret;
107
108         if(specs && specs->field_unsigned)
109                 ret = asn_INTEGER2umax(st, (uintmax_t *)&value);
110         else
111                 ret = asn_INTEGER2imax(st, &value);
112
113         /* Simple case: the integer size is small */
114         if(ret == 0) {
115                 const asn_INTEGER_enum_map_t *el;
116                 el = (value >= 0 || !specs || !specs->field_unsigned)
117                         ? INTEGER_map_value2enum(specs, value) : 0;
118                 if(el) {
119                         if(plainOrXER == 0)
120                                 return asn__format_to_callback(cb, app_key,
121                                         "%" ASN_PRIdMAX " (%s)", value, el->enum_name);
122                         else
123                                 return asn__format_to_callback(cb, app_key,
124                                         "<%s/>", el->enum_name);
125                 } else if(plainOrXER && specs && specs->strict_enumeration) {
126                         ASN_DEBUG("ASN.1 forbids dealing with "
127                                 "unknown value of ENUMERATED type");
128                         errno = EPERM;
129                         return -1;
130                 } else {
131             return asn__format_to_callback(cb, app_key,
132                                            (specs && specs->field_unsigned)
133                                                ? "%" ASN_PRIuMAX
134                                                : "%" ASN_PRIdMAX,
135                                            value);
136         }
137         } else if(plainOrXER && specs && specs->strict_enumeration) {
138                 /*
139                  * Here and earlier, we cannot encode the ENUMERATED values
140                  * if there is no corresponding identifier.
141                  */
142                 ASN_DEBUG("ASN.1 forbids dealing with "
143                         "unknown value of ENUMERATED type");
144                 errno = EPERM;
145                 return -1;
146         }
147
148         /* Output in the long xx:yy:zz... format */
149         /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */
150         for(p = scratch; buf < buf_end; buf++) {
151                 const char * const h2c = "0123456789ABCDEF";
152                 if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) {
153                         /* Flush buffer */
154                         if(cb(scratch, p - scratch, app_key) < 0)
155                                 return -1;
156                         wrote += p - scratch;
157                         p = scratch;
158                 }
159                 *p++ = h2c[*buf >> 4];
160                 *p++ = h2c[*buf & 0x0F];
161                 *p++ = 0x3a;    /* ":" */
162         }
163         if(p != scratch)
164                 p--;    /* Remove the last ":" */
165
166         wrote += p - scratch;
167         return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote;
168 }
169
170 static int
171 INTEGER__compar_value2enum(const void *kp, const void *am) {
172         long a = *(const long *)kp;
173         const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am;
174         long b = el->nat_value;
175         if(a < b) return -1;
176         else if(a == b) return 0;
177         else return 1;
178 }
179
180 const asn_INTEGER_enum_map_t *
181 INTEGER_map_value2enum(const asn_INTEGER_specifics_t *specs, long value) {
182         int count = specs ? specs->map_count : 0;
183         if(!count) return 0;
184         return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum,
185                 count, sizeof(specs->value2enum[0]),
186                 INTEGER__compar_value2enum);
187 }
188
189 static intmax_t
190 asn__integer_convert(const uint8_t *b, const uint8_t *end) {
191     uintmax_t value;
192
193     /* Perform the sign initialization */
194     /* Actually value = -(*b >> 7); gains nothing, yet unreadable! */
195     if((*b >> 7)) {
196         value = (uintmax_t)(-1);
197     } else {
198         value = 0;
199     }
200
201     /* Conversion engine */
202     for(; b < end; b++) {
203         value = (value << 8) | *b;
204     }
205
206     return value;
207 }
208
209 int
210 asn_INTEGER2imax(const INTEGER_t *iptr, intmax_t *lptr) {
211         uint8_t *b, *end;
212         size_t size;
213
214         /* Sanity checking */
215         if(!iptr || !iptr->buf || !lptr) {
216                 errno = EINVAL;
217                 return -1;
218         }
219
220         /* Cache the begin/end of the buffer */
221         b = iptr->buf;  /* Start of the INTEGER buffer */
222         size = iptr->size;
223         end = b + size; /* Where to stop */
224
225         if(size > sizeof(intmax_t)) {
226                 uint8_t *end1 = end - 1;
227                 /*
228                  * Slightly more advanced processing,
229                  * able to process INTEGERs with >sizeof(intmax_t) bytes
230                  * when the actual value is small, e.g. for intmax_t == int32_t
231                  * (0x0000000000abcdef INTEGER would yield a fine 0x00abcdef int32_t)
232                  */
233                 /* Skip out the insignificant leading bytes */
234                 for(; b < end1; b++) {
235                         switch(*b) {
236                                 case 0x00: if((b[1] & 0x80) == 0) continue; break;
237                                 case 0xff: if((b[1] & 0x80) != 0) continue; break;
238                         }
239                         break;
240                 }
241
242                 size = end - b;
243                 if(size > sizeof(intmax_t)) {
244                         /* Still cannot fit the sizeof(intmax_t) */
245                         errno = ERANGE;
246                         return -1;
247                 }
248         }
249
250         /* Shortcut processing of a corner case */
251         if(end == b) {
252                 *lptr = 0;
253                 return 0;
254         }
255
256         *lptr = asn__integer_convert(b, end);
257         return 0;
258 }
259
260 /* FIXME: negative INTEGER values are silently interpreted as large unsigned ones. */
261 int
262 asn_INTEGER2umax(const INTEGER_t *iptr, uintmax_t *lptr) {
263         uint8_t *b, *end;
264         uintmax_t value;
265         size_t size;
266
267         if(!iptr || !iptr->buf || !lptr) {
268                 errno = EINVAL;
269                 return -1;
270         }
271
272         b = iptr->buf;
273         size = iptr->size;
274         end = b + size;
275
276         /* If all extra leading bytes are zeroes, ignore them */
277         for(; size > sizeof(value); b++, size--) {
278                 if(*b) {
279                         /* Value won't fit into uintmax_t */
280                         errno = ERANGE;
281                         return -1;
282                 }
283         }
284
285         /* Conversion engine */
286         for(value = 0; b < end; b++)
287                 value = (value << 8) | *b;
288
289         *lptr = value;
290         return 0;
291 }
292
293 int
294 asn_umax2INTEGER(INTEGER_t *st, uintmax_t value) {
295     uint8_t *buf;
296     uint8_t *end;
297     uint8_t *b;
298     int shr;
299
300     if(value <= ((~(uintmax_t)0) >> 1)) {
301         return asn_imax2INTEGER(st, value);
302     }
303
304     buf = (uint8_t *)MALLOC(1 + sizeof(value));
305     if(!buf) return -1;
306
307     end = buf + (sizeof(value) + 1);
308     buf[0] = 0; /* INTEGERs are signed. 0-byte indicates positive. */
309     for(b = buf + 1, shr = (sizeof(value) - 1) * 8; b < end; shr -= 8, b++)
310         *b = (uint8_t)(value >> shr);
311
312     if(st->buf) FREEMEM(st->buf);
313     st->buf = buf;
314     st->size = 1 + sizeof(value);
315
316         return 0;
317 }
318
319 int
320 asn_imax2INTEGER(INTEGER_t *st, intmax_t value) {
321         uint8_t *buf, *bp;
322         uint8_t *p;
323         uint8_t *pstart;
324         uint8_t *pend1;
325         int littleEndian = 1;   /* Run-time detection */
326         int add;
327
328         if(!st) {
329                 errno = EINVAL;
330                 return -1;
331         }
332
333         buf = (uint8_t *)(long *)MALLOC(sizeof(value));
334         if(!buf) return -1;
335
336         if(*(char *)&littleEndian) {
337                 pstart = (uint8_t *)&value + sizeof(value) - 1;
338                 pend1 = (uint8_t *)&value;
339                 add = -1;
340         } else {
341                 pstart = (uint8_t *)&value;
342                 pend1 = pstart + sizeof(value) - 1;
343                 add = 1;
344         }
345
346         /*
347          * If the contents octet consists of more than one octet,
348          * then bits of the first octet and bit 8 of the second octet:
349          * a) shall not all be ones; and
350          * b) shall not all be zero.
351          */
352         for(p = pstart; p != pend1; p += add) {
353                 switch(*p) {
354                 case 0x00: if((*(p+add) & 0x80) == 0)
355                                 continue;
356                         break;
357                 case 0xff: if((*(p+add) & 0x80))
358                                 continue;
359                         break;
360                 }
361                 break;
362         }
363         /* Copy the integer body */
364         for(bp = buf, pend1 += add; p != pend1; p += add)
365                 *bp++ = *p;
366
367         if(st->buf) FREEMEM(st->buf);
368         st->buf = buf;
369         st->size = bp - buf;
370
371         return 0;
372 }
373
374 int
375 asn_INTEGER2long(const INTEGER_t *iptr, long *l) {
376     intmax_t v;
377     if(asn_INTEGER2imax(iptr, &v) == 0) {
378         if(v < LONG_MIN || v > LONG_MAX) {
379             errno = ERANGE;
380             return -1;
381         }
382         *l = v;
383         return 0;
384     } else {
385         return -1;
386     }
387 }
388
389 int
390 asn_INTEGER2ulong(const INTEGER_t *iptr, unsigned long *l) {
391     uintmax_t v;
392     if(asn_INTEGER2umax(iptr, &v) == 0) {
393         if(v > ULONG_MAX) {
394             errno = ERANGE;
395             return -1;
396         }
397         *l = v;
398         return 0;
399     } else {
400         return -1;
401     }
402 }
403
404 int
405 asn_long2INTEGER(INTEGER_t *st, long value) {
406     return asn_imax2INTEGER(st, value);
407 }
408
409 int
410 asn_ulong2INTEGER(INTEGER_t *st, unsigned long value) {
411     return asn_imax2INTEGER(st, value);
412 }
413
414
415 int
416 asn_uint642INTEGER(INTEGER_t *st, uint64_t value) {
417         uint8_t *buf;
418         uint8_t *end;
419         uint8_t *b;
420         int shr;
421
422         if(value <= INT64_MAX)
423                 return asn_int642INTEGER(st, value);
424
425         buf = (uint8_t *)MALLOC(1 + sizeof(value));
426         if(!buf) return -1;
427
428         end = buf + (sizeof(value) + 1);
429         buf[0] = 0;
430         for(b = buf + 1, shr = (sizeof(value)-1)*8; b < end; shr -= 8, b++)
431                 *b = (uint8_t)(value >> shr);
432
433         if(st->buf) FREEMEM(st->buf);
434         st->buf = buf;
435         st->size = 1 + sizeof(value);
436
437         return 0;
438 }
439
440 int
441 asn_int642INTEGER(INTEGER_t *st, int64_t value) {
442         uint8_t *buf, *bp;
443         uint8_t *p;
444         uint8_t *pstart;
445         uint8_t *pend1;
446         int littleEndian = 1;   /* Run-time detection */
447         int add;
448
449         if(!st) {
450                 errno = EINVAL;
451                 return -1;
452         }
453
454         buf = (uint8_t *)MALLOC(sizeof(value));
455         if(!buf) return -1;
456
457         if(*(char *)&littleEndian) {
458                 pstart = (uint8_t *)&value + sizeof(value) - 1;
459                 pend1 = (uint8_t *)&value;
460                 add = -1;
461         } else {
462                 pstart = (uint8_t *)&value;
463                 pend1 = pstart + sizeof(value) - 1;
464                 add = 1;
465         }
466
467         /*
468          * If the contents octet consists of more than one octet,
469          * then bits of the first octet and bit 8 of the second octet:
470          * a) shall not all be ones; and
471          * b) shall not all be zero.
472          */
473         for(p = pstart; p != pend1; p += add) {
474                 switch(*p) {
475                 case 0x00: if((*(p+add) & 0x80) == 0)
476                                 continue;
477                         break;
478                 case 0xff: if((*(p+add) & 0x80))
479                                 continue;
480                         break;
481                 }
482                 break;
483         }
484         /* Copy the integer body */
485         for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add)
486                 *bp++ = *p;
487
488         if(st->buf) FREEMEM(st->buf);
489         st->buf = buf;
490         st->size = bp - buf;
491
492         return 0;
493 }
494
495 /*
496  * Parse the number in the given string until the given *end position,
497  * returning the position after the last parsed character back using the
498  * same (*end) pointer.
499  * WARNING: This behavior is different from the standard strtol/strtoimax(3).
500  */
501 enum asn_strtox_result_e
502 asn_strtoimax_lim(const char *str, const char **end, intmax_t *intp) {
503     int sign = 1;
504     intmax_t value;
505
506     const intmax_t asn1_intmax_max = ((~(uintmax_t)0) >> 1);
507     const intmax_t upper_boundary = asn1_intmax_max / 10;
508     intmax_t last_digit_max = asn1_intmax_max % 10;
509
510     if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
511
512     switch(*str) {
513     case '-':
514         last_digit_max++;
515         sign = -1;
516         /* FALL THROUGH */
517     case '+':
518         str++;
519         if(str >= *end) {
520             *end = str;
521             return ASN_STRTOX_EXPECT_MORE;
522         }
523     }
524
525     for(value = 0; str < (*end); str++) {
526         if(*str >= 0x30 && *str <= 0x39) {
527             int d = *str - '0';
528             if(value < upper_boundary) {
529                 value = value * 10 + d;
530             } else if(value == upper_boundary) {
531                 if(d <= last_digit_max) {
532                     if(sign > 0) {
533                         value = value * 10 + d;
534                     } else {
535                         sign = 1;
536                         value = -value * 10 - d;
537                     }
538                     str += 1;
539                     if(str < *end) {
540                         // If digits continue, we're guaranteed out of range.
541                         *end = str;
542                         if(*str >= 0x30 && *str <= 0x39) {
543                             return ASN_STRTOX_ERROR_RANGE;
544                         } else {
545                             *intp = sign * value;
546                             return ASN_STRTOX_EXTRA_DATA;
547                         }
548                     }
549                     break;
550                 } else {
551                     *end = str;
552                     return ASN_STRTOX_ERROR_RANGE;
553                 }
554             } else {
555                 *end = str;
556                 return ASN_STRTOX_ERROR_RANGE;
557             }
558         } else {
559             *end = str;
560             *intp = sign * value;
561             return ASN_STRTOX_EXTRA_DATA;
562         }
563     }
564
565     *end = str;
566     *intp = sign * value;
567     return ASN_STRTOX_OK;
568 }
569
570 /*
571  * Parse the number in the given string until the given *end position,
572  * returning the position after the last parsed character back using the
573  * same (*end) pointer.
574  * WARNING: This behavior is different from the standard strtoul/strtoumax(3).
575  */
576 enum asn_strtox_result_e
577 asn_strtoumax_lim(const char *str, const char **end, uintmax_t *uintp) {
578     uintmax_t value;
579
580     const uintmax_t asn1_uintmax_max = ((~(uintmax_t)0));
581     const uintmax_t upper_boundary = asn1_uintmax_max / 10;
582     uintmax_t last_digit_max = asn1_uintmax_max % 10;
583
584     if(str >= *end) return ASN_STRTOX_ERROR_INVAL;
585
586     switch(*str) {
587     case '-':
588         return ASN_STRTOX_ERROR_INVAL;
589     case '+':
590         str++;
591         if(str >= *end) {
592             *end = str;
593             return ASN_STRTOX_EXPECT_MORE;
594         }
595     }
596
597     for(value = 0; str < (*end); str++) {
598         if(*str >= 0x30 && *str <= 0x39) {
599             unsigned int d = *str - '0';
600             if(value < upper_boundary) {
601                 value = value * 10 + d;
602             } else if(value == upper_boundary) {
603                 if(d <= last_digit_max) {
604                     value = value * 10 + d;
605                     str += 1;
606                     if(str < *end) {
607                         // If digits continue, we're guaranteed out of range.
608                         *end = str;
609                         if(*str >= 0x30 && *str <= 0x39) {
610                             return ASN_STRTOX_ERROR_RANGE;
611                         } else {
612                             *uintp = value;
613                             return ASN_STRTOX_EXTRA_DATA;
614                         }
615                     }
616                     break;
617                 } else {
618                     *end = str;
619                     return ASN_STRTOX_ERROR_RANGE;
620                 }
621             } else {
622                 *end = str;
623                 return ASN_STRTOX_ERROR_RANGE;
624             }
625         } else {
626             *end = str;
627             *uintp = value;
628             return ASN_STRTOX_EXTRA_DATA;
629         }
630     }
631
632     *end = str;
633     *uintp = value;
634     return ASN_STRTOX_OK;
635 }
636
637 enum asn_strtox_result_e
638 asn_strtol_lim(const char *str, const char **end, long *lp) {
639     intmax_t value;
640     switch(asn_strtoimax_lim(str, end, &value)) {
641     case ASN_STRTOX_ERROR_RANGE:
642         return ASN_STRTOX_ERROR_RANGE;
643     case ASN_STRTOX_ERROR_INVAL:
644         return ASN_STRTOX_ERROR_INVAL;
645     case ASN_STRTOX_EXPECT_MORE:
646         return ASN_STRTOX_EXPECT_MORE;
647     case ASN_STRTOX_OK:
648         if(value >= LONG_MIN && value <= LONG_MAX) {
649             *lp = value;
650             return ASN_STRTOX_OK;
651         } else {
652             return ASN_STRTOX_ERROR_RANGE;
653         }
654     case ASN_STRTOX_EXTRA_DATA:
655         if(value >= LONG_MIN && value <= LONG_MAX) {
656             *lp = value;
657             return ASN_STRTOX_EXTRA_DATA;
658         } else {
659             return ASN_STRTOX_ERROR_RANGE;
660         }
661     }
662
663     assert(!"Unreachable");
664     return ASN_STRTOX_ERROR_INVAL;
665 }
666
667 enum asn_strtox_result_e
668 asn_strtoul_lim(const char *str, const char **end, unsigned long *ulp) {
669     uintmax_t value;
670     switch(asn_strtoumax_lim(str, end, &value)) {
671     case ASN_STRTOX_ERROR_RANGE:
672         return ASN_STRTOX_ERROR_RANGE;
673     case ASN_STRTOX_ERROR_INVAL:
674         return ASN_STRTOX_ERROR_INVAL;
675     case ASN_STRTOX_EXPECT_MORE:
676         return ASN_STRTOX_EXPECT_MORE;
677     case ASN_STRTOX_OK:
678         if(value <= ULONG_MAX) {
679             *ulp = value;
680             return ASN_STRTOX_OK;
681         } else {
682             return ASN_STRTOX_ERROR_RANGE;
683         }
684     case ASN_STRTOX_EXTRA_DATA:
685         if(value <= ULONG_MAX) {
686             *ulp = value;
687             return ASN_STRTOX_EXTRA_DATA;
688         } else {
689             return ASN_STRTOX_ERROR_RANGE;
690         }
691     }
692
693     assert(!"Unreachable");
694     return ASN_STRTOX_ERROR_INVAL;
695 }
696
697 int
698 INTEGER_compare(const asn_TYPE_descriptor_t *td, const void *aptr,
699                      const void *bptr) {
700     const INTEGER_t *a = aptr;
701     const INTEGER_t *b = bptr;
702
703     (void)td;
704
705     if(a && b) {
706         if(a->size && b->size) {
707             int sign_a = (a->buf[0] & 0x80) ? -1 : 1;
708             int sign_b = (b->buf[0] & 0x80) ? -1 : 1;
709
710             if(sign_a < sign_b) return -1;
711             if(sign_a > sign_b) return 1;
712
713             /* The shortest integer wins, unless comparing negatives */
714             if(a->size < b->size) {
715                 return -1 * sign_a;
716             } else if(a->size > b->size) {
717                 return 1 * sign_b;
718             }
719
720             return sign_a * memcmp(a->buf, b->buf, a->size);
721         } else if(a->size) {
722             int sign = (a->buf[0] & 0x80) ? -1 : 1;
723             return (1) * sign;
724         } else if(b->size) {
725             int sign = (a->buf[0] & 0x80) ? -1 : 1;
726             return (-1) * sign;
727         } else {
728             return 0;
729         }
730     } else if(!a && !b) {
731         return 0;
732     } else if(!a) {
733         return -1;
734     } else {
735         return 1;
736     }
737
738 }