neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

mpack_core.c (17159B)


      1 #include <string.h>
      2 
      3 #include "mpack_core.h"
      4 
      5 #define UNUSED(p) (void)p;
      6 #define ADVANCE(buf, buflen) ((*buflen)--, (unsigned char)*((*buf)++))
      7 #define TLEN(val, range_start) ((mpack_uint32_t)(1 << (val - range_start)))
      8 #ifndef MIN
      9 # define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
     10 #endif
     11 
     12 static int mpack_rpending(const char **b, size_t *nl, mpack_tokbuf_t *tb);
     13 static int mpack_rvalue(mpack_token_type_t t, mpack_uint32_t l,
     14    const char **b, size_t *bl, mpack_token_t *tok);
     15 static int mpack_rblob(mpack_token_type_t t, mpack_uint32_t l,
     16    const char **b, size_t *bl, mpack_token_t *tok);
     17 static int mpack_wtoken(const mpack_token_t *tok, char **b, size_t *bl);
     18 static int mpack_wpending(char **b, size_t *bl, mpack_tokbuf_t *tb);
     19 static int mpack_wpint(char **b, size_t *bl, mpack_value_t v);
     20 static int mpack_wnint(char **b, size_t *bl, mpack_value_t v);
     21 static int mpack_wfloat(char **b, size_t *bl, const mpack_token_t *v);
     22 static int mpack_wstr(char **buf, size_t *buflen, mpack_uint32_t len);
     23 static int mpack_wbin(char **buf, size_t *buflen, mpack_uint32_t len);
     24 static int mpack_wext(char **buf, size_t *buflen, int type,
     25    mpack_uint32_t len);
     26 static int mpack_warray(char **buf, size_t *buflen, mpack_uint32_t len);
     27 static int mpack_wmap(char **buf, size_t *buflen, mpack_uint32_t len);
     28 static int mpack_w1(char **b, size_t *bl, mpack_uint32_t v);
     29 static int mpack_w2(char **b, size_t *bl, mpack_uint32_t v);
     30 static int mpack_w4(char **b, size_t *bl, mpack_uint32_t v);
     31 static mpack_value_t mpack_byte(unsigned char b);
     32 static int mpack_value(mpack_token_type_t t, mpack_uint32_t l,
     33    mpack_value_t v, mpack_token_t *tok);
     34 static int mpack_blob(mpack_token_type_t t, mpack_uint32_t l, int et,
     35    mpack_token_t *tok);
     36 
     37 MPACK_API void mpack_tokbuf_init(mpack_tokbuf_t *tokbuf)
     38 {
     39  tokbuf->ppos = 0;
     40  tokbuf->plen = 0;
     41  tokbuf->passthrough = 0;
     42 }
     43 
     44 MPACK_API int mpack_read(mpack_tokbuf_t *tokbuf, const char **buf,
     45    size_t *buflen, mpack_token_t *tok)
     46 {
     47  int status;
     48  size_t initial_ppos, ptrlen, advanced;
     49  const char *ptr, *ptr_save;
     50  assert(*buf);
     51  if (*buflen == 0) {
     52    return MPACK_EOF;
     53  }
     54 
     55  if (tokbuf->passthrough) {
     56    /* pass data from str/bin/ext directly as a MPACK_TOKEN_CHUNK, adjusting
     57     * *buf and *buflen */
     58    tok->type = MPACK_TOKEN_CHUNK;
     59    tok->data.chunk_ptr = *buf;
     60    tok->length = MIN((mpack_uint32_t)*buflen, tokbuf->passthrough);
     61    tokbuf->passthrough -= tok->length;
     62    *buf += tok->length;
     63    *buflen -= tok->length;
     64    goto done;
     65  }
     66 
     67  initial_ppos = tokbuf->ppos;
     68 
     69  if (tokbuf->plen) {
     70    if (!mpack_rpending(buf, buflen, tokbuf)) {
     71      return MPACK_EOF;
     72    }
     73    ptr = tokbuf->pending;
     74    ptrlen = tokbuf->ppos;
     75  } else {
     76    ptr = *buf;
     77    ptrlen = *buflen;
     78  }
     79 
     80  ptr_save = ptr;
     81 
     82  if ((status = mpack_rtoken(&ptr, &ptrlen, tok))) {
     83    if (status != MPACK_EOF) return MPACK_ERROR;
     84    /* need more data */
     85    assert(!tokbuf->plen);
     86    /* read the remainder of *buf to tokbuf->pending so it can be parsed
     87     * later with more data. only required when tokbuf->plen == 0 or else
     88     * it would have been done already. */
     89    tokbuf->plen = tok->length + 1;
     90    assert(tokbuf->plen <= sizeof(tokbuf->pending));
     91    tokbuf->ppos = 0;
     92    status = mpack_rpending(buf, buflen, tokbuf);
     93    assert(!status);
     94    return MPACK_EOF;
     95  }
     96 
     97  advanced = (size_t)(ptr - ptr_save) - initial_ppos;
     98  tokbuf->plen = tokbuf->ppos = 0;
     99  *buflen -= advanced; 
    100  *buf += advanced;
    101 
    102  if (tok->type > MPACK_TOKEN_MAP) {
    103    tokbuf->passthrough = tok->length;
    104  }
    105 
    106 done:
    107  return MPACK_OK;
    108 }
    109 
    110 MPACK_API int mpack_write(mpack_tokbuf_t *tokbuf, char **buf, size_t *buflen,
    111    const mpack_token_t *t)
    112 {
    113  int status;
    114  char *ptr;
    115  size_t ptrlen;
    116  mpack_token_t tok = tokbuf->plen ? tokbuf->pending_tok : *t;
    117  assert(*buf && *buflen);
    118 
    119  if (tok.type == MPACK_TOKEN_CHUNK) {
    120    size_t written, pending, count;
    121    if (!tokbuf->plen) tokbuf->ppos = 0;
    122    written = tokbuf->ppos;
    123    pending = tok.length - written;
    124    count = MIN(pending, *buflen);
    125    memcpy(*buf, tok.data.chunk_ptr + written, count);
    126    *buf += count;
    127    *buflen -= count;
    128    tokbuf->ppos += count;
    129    tokbuf->plen = count == pending ? 0 : tok.length;
    130    if (count == pending) {
    131      return MPACK_OK;
    132    } else {
    133      tokbuf->pending_tok = tok;
    134      return MPACK_EOF;
    135    }
    136  }
    137 
    138  if (tokbuf->plen) return mpack_wpending(buf, buflen, tokbuf);
    139 
    140  if (*buflen < MPACK_MAX_TOKEN_LEN) {
    141    ptr = tokbuf->pending;
    142    ptrlen = sizeof(tokbuf->pending);
    143  } else {
    144    ptr = *buf;
    145    ptrlen = *buflen;
    146  }
    147 
    148  if ((status = mpack_wtoken(&tok, &ptr, &ptrlen))) return status;
    149 
    150  if (*buflen < MPACK_MAX_TOKEN_LEN) {
    151    size_t toklen = sizeof(tokbuf->pending) - ptrlen;
    152    size_t write_cnt = MIN(toklen, *buflen);
    153    memcpy(*buf, tokbuf->pending, write_cnt);
    154    *buf += write_cnt;
    155    *buflen -= write_cnt;
    156    if (write_cnt < toklen) {
    157      assert(!*buflen);
    158      tokbuf->plen = toklen;
    159      tokbuf->ppos = write_cnt;
    160      tokbuf->pending_tok = tok;
    161      return MPACK_EOF;
    162    }
    163  } else {
    164    *buflen -= (size_t)(ptr - *buf);
    165    *buf = ptr;
    166  }
    167 
    168  return MPACK_OK;
    169 }
    170 
    171 int mpack_rtoken(const char **buf, size_t *buflen, mpack_token_t *tok)
    172 {
    173  if (*buflen == 0) {
    174    return MPACK_EOF;
    175  }
    176  unsigned char t = ADVANCE(buf, buflen);
    177  if (t < 0x80) {
    178    /* positive fixint */
    179    return mpack_value(MPACK_TOKEN_UINT, 1, mpack_byte(t), tok);
    180  } else if (t < 0x90) {
    181    /* fixmap */
    182    return mpack_blob(MPACK_TOKEN_MAP, t & 0xf, 0, tok);
    183  } else if (t < 0xa0) {
    184    /* fixarray */
    185    return mpack_blob(MPACK_TOKEN_ARRAY, t & 0xf, 0, tok);
    186  } else if (t < 0xc0) {
    187    /* fixstr */
    188    return mpack_blob(MPACK_TOKEN_STR, t & 0x1f, 0, tok);
    189  } else if (t < 0xe0) {
    190    switch (t) {
    191      case 0xc0:  /* nil */
    192        return mpack_value(MPACK_TOKEN_NIL, 0, mpack_byte(0), tok);
    193      case 0xc2:  /* false */
    194        return mpack_value(MPACK_TOKEN_BOOLEAN, 1, mpack_byte(0), tok);
    195      case 0xc3:  /* true */
    196        return mpack_value(MPACK_TOKEN_BOOLEAN, 1, mpack_byte(1), tok);
    197      case 0xc4:  /* bin 8 */
    198      case 0xc5:  /* bin 16 */
    199      case 0xc6:  /* bin 32 */
    200        return mpack_rblob(MPACK_TOKEN_BIN, TLEN(t, 0xc4), buf, buflen, tok);
    201      case 0xc7:  /* ext 8 */
    202      case 0xc8:  /* ext 16 */
    203      case 0xc9:  /* ext 32 */
    204        return mpack_rblob(MPACK_TOKEN_EXT, TLEN(t, 0xc7), buf, buflen, tok);
    205      case 0xca:  /* float 32 */
    206      case 0xcb:  /* float 64 */
    207        return mpack_rvalue(MPACK_TOKEN_FLOAT, TLEN(t, 0xc8), buf, buflen, tok);
    208      case 0xcc:  /* uint 8 */
    209      case 0xcd:  /* uint 16 */
    210      case 0xce:  /* uint 32 */
    211      case 0xcf:  /* uint 64 */
    212        return mpack_rvalue(MPACK_TOKEN_UINT, TLEN(t, 0xcc), buf, buflen, tok);
    213      case 0xd0:  /* int 8 */
    214      case 0xd1:  /* int 16 */
    215      case 0xd2:  /* int 32 */
    216      case 0xd3:  /* int 64 */
    217        return mpack_rvalue(MPACK_TOKEN_SINT, TLEN(t, 0xd0), buf, buflen, tok);
    218      case 0xd4:  /* fixext 1 */
    219      case 0xd5:  /* fixext 2 */
    220      case 0xd6:  /* fixext 4 */
    221      case 0xd7:  /* fixext 8 */
    222      case 0xd8:  /* fixext 16 */
    223        if (*buflen == 0) {
    224          /* require only one extra byte for the type code */
    225          tok->length = 1;
    226          return MPACK_EOF;
    227        }
    228        tok->length = TLEN(t, 0xd4);
    229        tok->type = MPACK_TOKEN_EXT;
    230        tok->data.ext_type = ADVANCE(buf, buflen);
    231        return MPACK_OK;
    232      case 0xd9:  /* str 8 */
    233      case 0xda:  /* str 16 */
    234      case 0xdb:  /* str 32 */
    235        return mpack_rblob(MPACK_TOKEN_STR, TLEN(t, 0xd9), buf, buflen, tok);
    236      case 0xdc:  /* array 16 */
    237      case 0xdd:  /* array 32 */
    238        return mpack_rblob(MPACK_TOKEN_ARRAY, TLEN(t, 0xdb), buf, buflen, tok);
    239      case 0xde:  /* map 16 */
    240      case 0xdf:  /* map 32 */
    241        return mpack_rblob(MPACK_TOKEN_MAP, TLEN(t, 0xdd), buf, buflen, tok);
    242      default:
    243        return MPACK_ERROR;
    244    }
    245  } else {
    246    /* negative fixint */
    247    return mpack_value(MPACK_TOKEN_SINT, 1, mpack_byte(t), tok);
    248  }
    249 }
    250 
    251 static int mpack_rpending(const char **buf, size_t *buflen,
    252    mpack_tokbuf_t *state)
    253 {
    254  size_t count;
    255  assert(state->ppos < state->plen);
    256  count = MIN(state->plen - state->ppos, *buflen);
    257  memcpy(state->pending + state->ppos, *buf, count);
    258  state->ppos += count;
    259  if (state->ppos < state->plen) {
    260    /* consume buffer since no token will be parsed yet. */
    261    *buf += *buflen;
    262    *buflen = 0;
    263    return 0;
    264  }
    265  return 1;
    266 }
    267 
    268 static int mpack_rvalue(mpack_token_type_t type, mpack_uint32_t remaining,
    269    const char **buf, size_t *buflen, mpack_token_t *tok)
    270 {
    271  if (*buflen < remaining) {
    272    tok->length = remaining;
    273    return MPACK_EOF;
    274  }
    275 
    276  mpack_value(type, remaining, mpack_byte(0), tok);
    277 
    278  while (remaining) {
    279    mpack_uint32_t byte = ADVANCE(buf, buflen), byte_idx, byte_shift;
    280    byte_idx = (mpack_uint32_t)--remaining;
    281    byte_shift = (byte_idx % 4) * 8;
    282    tok->data.value.lo |= byte << byte_shift;
    283    if (remaining == 4) {
    284      /* unpacked the first half of a 8-byte value, shift what was parsed to the
    285       * "hi" field and reset "lo" for the trailing 4 bytes. */
    286      tok->data.value.hi = tok->data.value.lo;
    287      tok->data.value.lo = 0;
    288    }
    289  }
    290 
    291  if (type == MPACK_TOKEN_SINT) {
    292    mpack_uint32_t hi = tok->data.value.hi;
    293    mpack_uint32_t lo = tok->data.value.lo;
    294    mpack_uint32_t msb = (tok->length == 8 && hi >> 31) ||
    295                         (tok->length == 4 && lo >> 31) ||
    296                         (tok->length == 2 && lo >> 15) ||
    297                         (tok->length == 1 && lo >> 7);
    298    if (!msb) {
    299      tok->type = MPACK_TOKEN_UINT;
    300    }
    301  }
    302 
    303  return MPACK_OK;
    304 }
    305 
    306 static int mpack_rblob(mpack_token_type_t type, mpack_uint32_t tlen,
    307    const char **buf, size_t *buflen, mpack_token_t *tok)
    308 {
    309  mpack_token_t l;
    310  mpack_uint32_t required = tlen + (type == MPACK_TOKEN_EXT ? 1 : 0);
    311 
    312  if (*buflen < required) {
    313    tok->length = required;
    314    return MPACK_EOF;
    315  }
    316 
    317  l.data.value.lo = 0;
    318  mpack_rvalue(MPACK_TOKEN_UINT, tlen, buf, buflen, &l);
    319  tok->type = type;
    320  tok->length = l.data.value.lo;
    321 
    322  if (type == MPACK_TOKEN_EXT) {
    323    tok->data.ext_type = ADVANCE(buf, buflen);
    324  }
    325 
    326  return MPACK_OK;
    327 }
    328 
    329 static int mpack_wtoken(const mpack_token_t *tok, char **buf,
    330    size_t *buflen)
    331 {
    332  switch (tok->type) {
    333    case MPACK_TOKEN_NIL:
    334      return mpack_w1(buf, buflen, 0xc0);
    335    case MPACK_TOKEN_BOOLEAN:
    336      return mpack_w1(buf, buflen, tok->data.value.lo ? 0xc3 : 0xc2);
    337    case MPACK_TOKEN_UINT:
    338      return mpack_wpint(buf, buflen, tok->data.value);
    339    case MPACK_TOKEN_SINT:
    340      return mpack_wnint(buf, buflen, tok->data.value);
    341    case MPACK_TOKEN_FLOAT:
    342      return mpack_wfloat(buf, buflen, tok);
    343    case MPACK_TOKEN_BIN:
    344      return mpack_wbin(buf, buflen, tok->length);
    345    case MPACK_TOKEN_STR:
    346      return mpack_wstr(buf, buflen, tok->length);
    347    case MPACK_TOKEN_EXT:
    348      return mpack_wext(buf, buflen, tok->data.ext_type, tok->length);
    349    case MPACK_TOKEN_ARRAY:
    350      return mpack_warray(buf, buflen, tok->length);
    351    case MPACK_TOKEN_MAP:
    352      return mpack_wmap(buf, buflen, tok->length);
    353    default:
    354      return MPACK_ERROR;
    355  }
    356 }
    357 
    358 static int mpack_wpending(char **buf, size_t *buflen, mpack_tokbuf_t *state)
    359 {
    360  size_t count;
    361  assert(state->ppos < state->plen);
    362  count = MIN(state->plen - state->ppos, *buflen);
    363  memcpy(*buf, state->pending + state->ppos, count);
    364  state->ppos += count;
    365  *buf += count;
    366  *buflen -= count;
    367  if (state->ppos == state->plen) {
    368    state->plen = 0;
    369    return MPACK_OK;
    370  }
    371  return MPACK_EOF;
    372 }
    373 
    374 static int mpack_wpint(char **buf, size_t *buflen, mpack_value_t val)
    375 {
    376  mpack_uint32_t hi = val.hi;
    377  mpack_uint32_t lo = val.lo;
    378 
    379  if (hi) {
    380    /* uint 64 */
    381    return mpack_w1(buf, buflen, 0xcf) ||
    382           mpack_w4(buf, buflen, hi)   ||
    383           mpack_w4(buf, buflen, lo);
    384  } else if (lo > 0xffff) {
    385    /* uint 32 */
    386    return mpack_w1(buf, buflen, 0xce) ||
    387           mpack_w4(buf, buflen, lo);
    388  } else if (lo > 0xff) {
    389    /* uint 16 */
    390    return mpack_w1(buf, buflen, 0xcd) ||
    391           mpack_w2(buf, buflen, lo);
    392  } else if (lo > 0x7f) {
    393    /* uint 8 */
    394    return mpack_w1(buf, buflen, 0xcc) ||
    395           mpack_w1(buf, buflen, lo);
    396  } else {
    397    return mpack_w1(buf, buflen, lo);
    398  }
    399 }
    400 
    401 static int mpack_wnint(char **buf, size_t *buflen, mpack_value_t val)
    402 {
    403  mpack_uint32_t hi = val.hi;
    404  mpack_uint32_t lo = val.lo;
    405 
    406  if (lo < 0x80000000) {
    407    /* int 64 */
    408    return mpack_w1(buf, buflen, 0xd3) ||
    409           mpack_w4(buf, buflen, hi)   ||
    410           mpack_w4(buf, buflen, lo);
    411  } else if (lo < 0xffff7fff) {
    412    /* int 32 */
    413    return mpack_w1(buf, buflen, 0xd2) ||
    414           mpack_w4(buf, buflen, lo);
    415  } else if (lo < 0xffffff7f) {
    416    /* int 16 */
    417    return mpack_w1(buf, buflen, 0xd1) ||
    418           mpack_w2(buf, buflen, lo);
    419  } else if (lo < 0xffffffe0) {
    420    /* int 8 */
    421    return mpack_w1(buf, buflen, 0xd0) ||
    422           mpack_w1(buf, buflen, lo);
    423  } else {
    424    /* negative fixint */
    425    return mpack_w1(buf, buflen, (mpack_uint32_t)(0x100 + lo));
    426  }
    427 }
    428 
    429 static int mpack_wfloat(char **buf, size_t *buflen,
    430    const mpack_token_t *tok)
    431 {
    432  if (tok->length == 4) {
    433    return mpack_w1(buf, buflen, 0xca) ||
    434           mpack_w4(buf, buflen, tok->data.value.lo);
    435  } else if (tok->length == 8) {
    436    return mpack_w1(buf, buflen, 0xcb) ||
    437           mpack_w4(buf, buflen, tok->data.value.hi) ||
    438           mpack_w4(buf, buflen, tok->data.value.lo);
    439  } else {
    440    return MPACK_ERROR;
    441  }
    442 }
    443 
    444 static int mpack_wstr(char **buf, size_t *buflen, mpack_uint32_t len)
    445 {
    446  if (len < 0x20) {
    447    return mpack_w1(buf, buflen, 0xa0 | len);
    448  } else if (len < 0x100) {
    449    return mpack_w1(buf, buflen, 0xd9) ||
    450           mpack_w1(buf, buflen, len);
    451  } else if (len < 0x10000) {
    452    return mpack_w1(buf, buflen, 0xda) ||
    453           mpack_w2(buf, buflen, len);
    454  } else {
    455    return mpack_w1(buf, buflen, 0xdb) ||
    456           mpack_w4(buf, buflen, len);
    457  }
    458 }
    459 
    460 static int mpack_wbin(char **buf, size_t *buflen, mpack_uint32_t len)
    461 {
    462  if (len < 0x100) {
    463    return mpack_w1(buf, buflen, 0xc4) ||
    464           mpack_w1(buf, buflen, len);
    465  } else if (len < 0x10000) {
    466    return mpack_w1(buf, buflen, 0xc5) ||
    467           mpack_w2(buf, buflen, len);
    468  } else {
    469    return mpack_w1(buf, buflen, 0xc6) ||
    470           mpack_w4(buf, buflen, len);
    471  }
    472 }
    473 
    474 static int mpack_wext(char **buf, size_t *buflen, int type,
    475    mpack_uint32_t len)
    476 {
    477  mpack_uint32_t t;
    478  assert(type >= 0 && type < 0x80);
    479  t = (mpack_uint32_t)type;
    480  switch (len) {
    481    case 1: mpack_w1(buf, buflen, 0xd4); return mpack_w1(buf, buflen, t);
    482    case 2: mpack_w1(buf, buflen, 0xd5); return mpack_w1(buf, buflen, t);
    483    case 4: mpack_w1(buf, buflen, 0xd6); return mpack_w1(buf, buflen, t);
    484    case 8: mpack_w1(buf, buflen, 0xd7); return mpack_w1(buf, buflen, t);
    485    case 16: mpack_w1(buf, buflen, 0xd8); return mpack_w1(buf, buflen, t);
    486    default:
    487      if (len < 0x100) {
    488        return mpack_w1(buf, buflen, 0xc7) ||
    489               mpack_w1(buf, buflen, len)  ||
    490               mpack_w1(buf, buflen, t);
    491      } else if (len < 0x10000) {
    492        return mpack_w1(buf, buflen, 0xc8) ||
    493               mpack_w2(buf, buflen, len)  ||
    494               mpack_w1(buf, buflen, t);
    495      } else {
    496        return mpack_w1(buf, buflen, 0xc9) ||
    497               mpack_w4(buf, buflen, len)  ||
    498               mpack_w1(buf, buflen, t);
    499      }
    500  }
    501 }
    502 
    503 static int mpack_warray(char **buf, size_t *buflen, mpack_uint32_t len)
    504 {
    505  if (len < 0x10) {
    506    return mpack_w1(buf, buflen, 0x90 | len);
    507  } else if (len < 0x10000) {
    508    return mpack_w1(buf, buflen, 0xdc) ||
    509           mpack_w2(buf, buflen, len);
    510  } else {
    511    return mpack_w1(buf, buflen, 0xdd) ||
    512           mpack_w4(buf, buflen, len);
    513  }
    514 }
    515 
    516 static int mpack_wmap(char **buf, size_t *buflen, mpack_uint32_t len)
    517 {
    518  if (len < 0x10) {
    519    return mpack_w1(buf, buflen, 0x80 | len);
    520  } else if (len < 0x10000) {
    521    return mpack_w1(buf, buflen, 0xde) ||
    522           mpack_w2(buf, buflen, len);
    523  } else {
    524    return mpack_w1(buf, buflen, 0xdf) ||
    525           mpack_w4(buf, buflen, len);
    526  }
    527 }
    528 
    529 static int mpack_w1(char **b, size_t *bl, mpack_uint32_t v)
    530 {
    531  (*bl)--;
    532  *(*b)++ = (char)(v & 0xff);
    533  return MPACK_OK;
    534 }
    535 
    536 static int mpack_w2(char **b, size_t *bl, mpack_uint32_t v)
    537 {
    538  *bl -= 2;
    539  *(*b)++ = (char)((v >> 8) & 0xff);
    540  *(*b)++ = (char)(v & 0xff);
    541  return MPACK_OK;
    542 }
    543 
    544 static int mpack_w4(char **b, size_t *bl, mpack_uint32_t v)
    545 {
    546  *bl -= 4;
    547  *(*b)++ = (char)((v >> 24) & 0xff);
    548  *(*b)++ = (char)((v >> 16) & 0xff);
    549  *(*b)++ = (char)((v >> 8) & 0xff);
    550  *(*b)++ = (char)(v & 0xff);
    551  return MPACK_OK;
    552 }
    553 
    554 static int mpack_value(mpack_token_type_t type, mpack_uint32_t length,
    555    mpack_value_t value, mpack_token_t *tok)
    556 {
    557  tok->type = type;
    558  tok->length = length;
    559  tok->data.value = value;
    560  return MPACK_OK;
    561 }
    562 
    563 static int mpack_blob(mpack_token_type_t type, mpack_uint32_t length,
    564    int ext_type, mpack_token_t *tok)
    565 {
    566  tok->type = type;
    567  tok->length = length;
    568  tok->data.ext_type = ext_type;
    569  return MPACK_OK;
    570 }
    571 
    572 static mpack_value_t mpack_byte(unsigned char byte)
    573 {
    574  mpack_value_t rv;
    575  rv.lo = byte;
    576  rv.hi = 0;
    577  return rv;
    578 }