void decode_decimal(pTHX_ unsigned char *input, STRLEN len, struct cc_type *type, SV *output) { union { unsigned char bytes[4]; int32_t scale; } bytes_or_scale; if (UNLIKELY(len < 5)) croak("decode_decimal: len < 5"); memcpy(bytes_or_scale.bytes, input, 4); bswap4(bytes_or_scale.bytes); bytes_or_scale.scale *= -1; decode_varint(aTHX_ input+4, len-4, type, output); if (bytes_or_scale.scale != 0) { char *sign; if (bytes_or_scale.scale > 0) { sign = "+"; } else { sign = ""; } sv_catpvf(output, "e%s%d", sign, bytes_or_scale.scale); } }
void decode_protobuf(char *buf, char *buf_end, yield_t yield) { while(buf < buf_end) { uint64_t key = decode_varint(buf, &buf); struct key_value_pair pair = { .field_number = key >> 3, .wire_type = key & 0x07 }; switch(pair.wire_type) { case WT_VARINT: /* varint */ pair.value.varint = decode_varint(buf, &buf); break; case WT_64BIT: /* 64 bit */ pair.value._64_bit = get_32_le(buf, &buf); buf += 4; pair.value._64_bit |= (uint64_t)get_32_le(buf, &buf) << 32; buf += 4; break; case WT_STRING: /* string */ pair.value.string.len = decode_varint(buf, &buf); pair.value.string.start = buf; buf += pair.value.string.len; break; case WT_32BIT: /* 32 bit */ pair.value._32_bit = get_32_le(buf, &buf); buf += 4; break; } yield(&pair); } } void yield_cb(struct key_value_pair *pair) { printf("Field number: %d, Wire type: %d\n", pair->field_number, pair->wire_type); }
/** * Convert a <code>CassDecimal<code/> object into a numerical string value * * @param byte_array Byte array to convert * @return String representation of numerical value */ static std::string to_string(CassDecimal decimal) { std::string byte_array = std::string(reinterpret_cast<const char *>(decimal.varint), decimal.varint_size); std::string integer_value = decode_varint(byte_array.c_str()); //Ensure the decimal has scale if (decimal.scale > 0) { unsigned int period_position = integer_value.size() - decimal.scale; return integer_value.substr(0, period_position) + "." + integer_value.substr(period_position); } return integer_value; }
// Decodes a 32-bit varint from the current buffer position. // Returns a status code as described in decoder.int.h. FORCEINLINE int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { uint64_t u64; int32_t ret = decode_varint(d, &u64); if (ret >= 0) return ret; if (u64 > UINT32_MAX) { seterr(d, "Unterminated 32-bit varint"); // TODO(haberman) guarantee that this function return is >= 0 somehow, // so we know this path will always be treated as error by our caller. // Right now the size_t -> int32_t can overflow and produce negative values. *u32 = 0; return upb_pbdecoder_suspend(d); } *u32 = u64; return DECODE_OK; }
/* 32bit compat */ void decode_time(pTHX_ unsigned char *input, STRLEN len, struct cc_type *type, SV *output) { int32_t nano, seconds, hours, minutes; char *txt; char workbuf[20]; STRLEN txt_len; decode_varint(aTHX_ input, len, type, output); /* output now contains a string represending the ns since midnight */ txt = SvPV(output, txt_len); if (txt_len > 14) { croak("decode_time: invalid value"); } if (txt_len <= 9) { memset(workbuf, 0, 20); memcpy(workbuf, txt, txt_len); seconds = 0; nano = atoi(workbuf); } else { memset(workbuf, 0, 20); memcpy(workbuf, txt+txt_len-9, 9); nano = atoi(workbuf); memset(workbuf, 0, 20); memcpy(workbuf, txt, txt_len-9); seconds = atoi(workbuf); } hours = seconds / 3600; minutes = (seconds % 3600) / 60; seconds = seconds % 60; sv_setpvf(output, "%d:%.2d:%.2d.%d", hours, minutes, seconds, nano); txt = SvPV(output, txt_len); while (txt[txt_len-1] == '0') txt_len--; if (txt[txt_len-1] == '.') txt_len--; SvCUR_set(output, txt_len); }
T pbf::get_svarint() { pbf_assert((has_wire_type(pbf_wire_type::varint) || has_wire_type(pbf_wire_type::length_delimited)) && "not a varint"); return static_cast<T>(decode_zigzag64(decode_varint(&m_data, m_end))); }
T pbf::get_varint() { return static_cast<T>(decode_varint(&m_data, m_end)); }
int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, int32_t fieldnum, uint8_t wire_type) { if (fieldnum >= 0) goto have_tag; while (true) { uint32_t tag; CHECK_RETURN(decode_v32(d, &tag)); wire_type = tag & 0x7; fieldnum = tag >> 3; have_tag: if (fieldnum == 0) { seterr(d, "Saw invalid field number (0)"); return upb_pbdecoder_suspend(d); } // TODO: deliver to unknown field callback. switch (wire_type) { case UPB_WIRE_TYPE_32BIT: CHECK_RETURN(skip(d, 4)); break; case UPB_WIRE_TYPE_64BIT: CHECK_RETURN(skip(d, 8)); break; case UPB_WIRE_TYPE_VARINT: { uint64_t u64; CHECK_RETURN(decode_varint(d, &u64)); break; } case UPB_WIRE_TYPE_DELIMITED: { uint32_t len; CHECK_RETURN(decode_v32(d, &len)); CHECK_RETURN(skip(d, len)); break; } case UPB_WIRE_TYPE_START_GROUP: CHECK_SUSPEND(pushtagdelim(d, -fieldnum)); break; case UPB_WIRE_TYPE_END_GROUP: if (fieldnum == -d->top->groupnum) { pop(d); } else if (fieldnum == d->top->groupnum) { return DECODE_ENDGROUP; } else { seterr(d, "Unmatched ENDGROUP tag."); return upb_pbdecoder_suspend(d); } break; default: seterr(d, "Invalid wire type"); return upb_pbdecoder_suspend(d); } if (d->top->groupnum >= 0) { return DECODE_OK; } if (d->ptr == d->delim_end) { seterr(d, "Enclosing submessage ended in the middle of value or group"); // Unlike most errors we notice during parsing, right now we have consumed // all of the user's input. // // There are three different options for how to handle this case: // // 1. decode() = short count, error = set // 2. decode() = full count, error = set // 3. decode() = full count, error NOT set, short count and error will // be reported on next call to decode() (or end()) // // (1) and (3) have the advantage that they preserve the invariant that an // error occurs iff decode() returns a short count. // // (2) and (3) have the advantage of reflecting the fact that all of the // bytes were in fact parsed (and possibly delivered to the unknown field // handler, in the future when that is supported). // // (3) requires extra state in the decode (a place to store the "permanent // error" that we should return for all subsequent attempts to decode). // But we likely want this anyway. // // Right now we do (1), thanks to the fact that we checkpoint *after* this // check. (3) may be a better choice long term; unclear at the moment. return upb_pbdecoder_suspend(d); } checkpoint(d); } }
/** * Convert a two's compliment byte array into a numerical string value * * @param byte_array Byte array to convert * @return String representation of numerical value */ static std::string to_string(const char *byte_array) { return decode_varint(byte_array); }
void decode_cell(pTHX_ unsigned char *input, STRLEN len, STRLEN *pos, struct cc_type *type, SV *output) { unsigned char *bytes; STRLEN bytes_len; if (unpack_bytes(aTHX_ input, len, pos, &bytes, &bytes_len) != 0) { sv_setsv(output, &PL_sv_undef); return; } switch (type->type_id) { case CC_TYPE_ASCII: case CC_TYPE_CUSTOM: case CC_TYPE_BLOB: decode_blob(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_BOOLEAN: decode_boolean(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_VARCHAR: case CC_TYPE_TEXT: decode_utf8(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_INET: decode_inet(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_SET: case CC_TYPE_LIST: decode_list(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_UUID: case CC_TYPE_TIMEUUID: decode_uuid(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_FLOAT: decode_float(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_DOUBLE: decode_double(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_DECIMAL: decode_decimal(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_VARINT: case CC_TYPE_BIGINT: case CC_TYPE_COUNTER: case CC_TYPE_TIMESTAMP: case CC_TYPE_SMALLINT: case CC_TYPE_TINYINT: case CC_TYPE_INT: decode_varint(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_DATE: decode_date(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_TIME: decode_time(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_MAP: decode_map(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_UDT: decode_udt(aTHX_ bytes, bytes_len, type, output); break; case CC_TYPE_TUPLE: decode_tuple(aTHX_ bytes, bytes_len, type, output); break; default: sv_setsv(output, &PL_sv_undef); warn("Decoder doesn't yet understand type %d, returning undef instead", type->type_id); break; } }