in c/src/core/decoder.c [184:439]
static int pni_decoder_decode_value(pn_decoder_t *decoder, pn_data_t *data, uint8_t code)
{
int err;
conv_t conv;
pn_decimal128_t dec128;
pn_uuid_t uuid;
size_t size;
size_t count;
switch (code)
{
case PNE_NULL:
err = pn_data_put_null(data);
break;
case PNE_TRUE:
err = pn_data_put_bool(data, true);
break;
case PNE_FALSE:
err = pn_data_put_bool(data, false);
break;
case PNE_BOOLEAN:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_bool(data, pn_decoder_readf8(decoder) != 0);
break;
case PNE_UBYTE:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_ubyte(data, pn_decoder_readf8(decoder));
break;
case PNE_BYTE:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_byte(data, pn_decoder_readf8(decoder));
break;
case PNE_USHORT:
if (pn_decoder_remaining(decoder) < 2) return PN_UNDERFLOW;
err = pn_data_put_ushort(data, pn_decoder_readf16(decoder));
break;
case PNE_SHORT:
if (pn_decoder_remaining(decoder) < 2) return PN_UNDERFLOW;
err = pn_data_put_short(data, pn_decoder_readf16(decoder));
break;
case PNE_UINT:
if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
err = pn_data_put_uint(data, pn_decoder_readf32(decoder));
break;
case PNE_UINT0:
err = pn_data_put_uint(data, 0);
break;
case PNE_SMALLUINT:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_uint(data, pn_decoder_readf8(decoder));
break;
case PNE_SMALLINT:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_int(data, (int8_t)pn_decoder_readf8(decoder));
break;
case PNE_INT:
if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
err = pn_data_put_int(data, pn_decoder_readf32(decoder));
break;
case PNE_UTF32:
if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
err = pn_data_put_char(data, pn_decoder_readf32(decoder));
break;
case PNE_FLOAT:
if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
// XXX: this assumes the platform uses IEEE floats
conv.i = pn_decoder_readf32(decoder);
err = pn_data_put_float(data, conv.f);
break;
case PNE_DECIMAL32:
if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
err = pn_data_put_decimal32(data, pn_decoder_readf32(decoder));
break;
case PNE_ULONG:
if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
err = pn_data_put_ulong(data, pn_decoder_readf64(decoder));
break;
case PNE_LONG:
if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
err = pn_data_put_long(data, pn_decoder_readf64(decoder));
break;
case PNE_MS64:
if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
err = pn_data_put_timestamp(data, pn_decoder_readf64(decoder));
break;
case PNE_DOUBLE:
// XXX: this assumes the platform uses IEEE floats
if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
conv.l = pn_decoder_readf64(decoder);
err = pn_data_put_double(data, conv.d);
break;
case PNE_DECIMAL64:
if (pn_decoder_remaining(decoder) < 8) return PN_UNDERFLOW;
err = pn_data_put_decimal64(data, pn_decoder_readf64(decoder));
break;
case PNE_ULONG0:
err = pn_data_put_ulong(data, 0);
break;
case PNE_SMALLULONG:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_ulong(data, pn_decoder_readf8(decoder));
break;
case PNE_SMALLLONG:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
err = pn_data_put_long(data, (int8_t)pn_decoder_readf8(decoder));
break;
case PNE_DECIMAL128:
if (pn_decoder_remaining(decoder) < 16) return PN_UNDERFLOW;
pn_decoder_readf128(decoder, &dec128);
err = pn_data_put_decimal128(data, dec128);
break;
case PNE_UUID:
if (pn_decoder_remaining(decoder) < 16) return PN_UNDERFLOW;
pn_decoder_readf128(decoder, &uuid);
err = pn_data_put_uuid(data, uuid);
break;
case PNE_VBIN8:
case PNE_STR8_UTF8:
case PNE_SYM8:
case PNE_VBIN32:
case PNE_STR32_UTF8:
case PNE_SYM32:
switch (code & 0xF0)
{
case 0xA0:
if (!pn_decoder_remaining(decoder)) return PN_UNDERFLOW;
size = pn_decoder_readf8(decoder);
break;
case 0xB0:
if (pn_decoder_remaining(decoder) < 4) return PN_UNDERFLOW;
size = pn_decoder_readf32(decoder);
break;
default:
return PN_ARG_ERR;
}
if (pn_decoder_remaining(decoder) < size) return PN_UNDERFLOW;
{
char *start = (char *) decoder->position;
pn_bytes_t bytes = {size, start};
switch (code & 0x0F)
{
case 0x0:
err = pn_data_put_binary(data, bytes);
break;
case 0x1:
err = pn_data_put_string(data, bytes);
break;
case 0x3:
err = pn_data_put_symbol(data, bytes);
break;
default:
return PN_ARG_ERR;
}
}
decoder->position += size;
break;
case PNE_LIST0:
err = pn_data_put_list(data);
break;
case PNE_ARRAY8:
case PNE_ARRAY32:
case PNE_LIST8:
case PNE_LIST32:
case PNE_MAP8:
case PNE_MAP32: {
size_t min_expected_size = 0;
switch (code)
{
case PNE_ARRAY8:
min_expected_size += 1; // Array has a constructor of at least 1 byte
PN_FALLTHROUGH;
case PNE_LIST8:
case PNE_MAP8:
min_expected_size += 1; // All these types have a count
if (pn_decoder_remaining(decoder) < min_expected_size+1) return PN_UNDERFLOW;
size = pn_decoder_readf8(decoder);
// size must be at least big enough for count or count+constructor
if (size < min_expected_size) return PN_ARG_ERR;
if (pn_decoder_remaining(decoder) < size) return PN_UNDERFLOW;
count = pn_decoder_readf8(decoder);
break;
case PNE_ARRAY32:
min_expected_size += 1; // Array has a constructor of at least 1 byte
PN_FALLTHROUGH;
case PNE_LIST32:
case PNE_MAP32:
min_expected_size += 4; // All these types have a count
if (pn_decoder_remaining(decoder) < min_expected_size+4) return PN_UNDERFLOW;
size = pn_decoder_readf32(decoder);
// size must be at least big enough for count or count+constructor
if (size < min_expected_size) return PN_ARG_ERR;
if (pn_decoder_remaining(decoder) < size) return PN_UNDERFLOW;
count = pn_decoder_readf32(decoder);
break;
default:
return PN_ARG_ERR;
}
switch (code)
{
case PNE_ARRAY8:
case PNE_ARRAY32:
{
uint8_t next = *decoder->position;
bool described = (next == PNE_DESCRIPTOR);
err = pn_data_put_array(data, described, (pn_type_t) 0);
if (err) return err;
pn_data_enter(data);
uint8_t acode;
int e = pni_decoder_decode_type(decoder, data, &acode);
if (e) return e;
pn_type_t type = pn_code2type(acode);
if ((int)type < 0) return (int)type;
for (size_t i = 0; i < count; i++)
{
e = pni_decoder_decode_value(decoder, data, acode);
if (e) return e;
}
pn_data_exit(data);
pni_data_set_array_type(data, type);
}
return 0;
case PNE_LIST8:
case PNE_LIST32:
err = pn_data_put_list(data);
if (err) return err;
break;
case PNE_MAP8:
case PNE_MAP32:
err = pn_data_put_map(data);
if (err) return err;
break;
default:
return PN_ARG_ERR;
}
pn_data_enter(data);
for (size_t i = 0; i < count; i++)
{
int e = pni_decoder_single(decoder, data);
if (e) return e;
}
pn_data_exit(data);
return 0;
}
default:
return pn_error_format(pni_decoder_error(decoder), PN_ARG_ERR, "unrecognized typecode: %u", code);
}
return err;
}