Add PB_LTYPE_UVARINT to fix encoding of negative int32 values.

Apparently int32 values that are negative must be cast into int64 first
before being encoded. Because uint32 still needs to be cast to uint64,
the cases for int32 and uint32 had to be separated.

Update issue 97
Status: FixedInGit
This commit is contained in:
Petteri Aimonen
2013-12-21 12:16:03 +02:00
parent 9cc19a5e99
commit ee5b12c537
3 changed files with 55 additions and 22 deletions

30
pb.h
View File

@@ -116,11 +116,6 @@
/* List of possible field types. These are used in the autogenerated code. /* List of possible field types. These are used in the autogenerated code.
* Least-significant 4 bits tell the scalar type * Least-significant 4 bits tell the scalar type
* Most-significant 4 bits specify repeated/required/packed etc. * Most-significant 4 bits specify repeated/required/packed etc.
*
* INT32 and UINT32 are treated the same, as are (U)INT64 and (S)FIXED*
* These types are simply casted to correct field type when they are
* assigned to the memory pointer.
* SINT* is different, though, because it is zig-zag coded.
*/ */
typedef uint8_t pb_type_t; typedef uint8_t pb_type_t;
@@ -128,32 +123,33 @@ typedef uint8_t pb_type_t;
/**** Field data types ****/ /**** Field data types ****/
/* Numeric types */ /* Numeric types */
#define PB_LTYPE_VARINT 0x00 /* int32, uint32, int64, uint64, bool, enum */ #define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */
#define PB_LTYPE_SVARINT 0x01 /* sint32, sint64 */ #define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */
#define PB_LTYPE_FIXED32 0x02 /* fixed32, sfixed32, float */ #define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */
#define PB_LTYPE_FIXED64 0x03 /* fixed64, sfixed64, double */ #define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */
#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */
/* Marker for last packable field type. */ /* Marker for last packable field type. */
#define PB_LTYPE_LAST_PACKABLE 0x03 #define PB_LTYPE_LAST_PACKABLE 0x04
/* Byte array with pre-allocated buffer. /* Byte array with pre-allocated buffer.
* data_size is the length of the allocated PB_BYTES_ARRAY structure. */ * data_size is the length of the allocated PB_BYTES_ARRAY structure. */
#define PB_LTYPE_BYTES 0x04 #define PB_LTYPE_BYTES 0x05
/* String with pre-allocated buffer. /* String with pre-allocated buffer.
* data_size is the maximum length. */ * data_size is the maximum length. */
#define PB_LTYPE_STRING 0x05 #define PB_LTYPE_STRING 0x06
/* Submessage /* Submessage
* submsg_fields is pointer to field descriptions */ * submsg_fields is pointer to field descriptions */
#define PB_LTYPE_SUBMESSAGE 0x06 #define PB_LTYPE_SUBMESSAGE 0x07
/* Extension pseudo-field /* Extension pseudo-field
* The field contains a pointer to pb_extension_t */ * The field contains a pointer to pb_extension_t */
#define PB_LTYPE_EXTENSION 0x07 #define PB_LTYPE_EXTENSION 0x08
/* Number of declared LTYPES */ /* Number of declared LTYPES */
#define PB_LTYPES_COUNT 8 #define PB_LTYPES_COUNT 9
#define PB_LTYPE_MASK 0x0F #define PB_LTYPE_MASK 0x0F
/**** Field repetition rules ****/ /**** Field repetition rules ****/
@@ -410,8 +406,8 @@ struct _pb_extension_t {
#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT #define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT
#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT #define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT
#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING #define PB_LTYPE_MAP_STRING PB_LTYPE_STRING
#define PB_LTYPE_MAP_UINT32 PB_LTYPE_VARINT #define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT
#define PB_LTYPE_MAP_UINT64 PB_LTYPE_VARINT #define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT
#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION #define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION
/* This is the actual macro used in field descriptions. /* This is the actual macro used in field descriptions.

View File

@@ -47,7 +47,8 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_exten
static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iterator_t *iter); static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iterator_t *iter);
static bool checkreturn find_extension_field(pb_field_iterator_t *iter); static bool checkreturn find_extension_field(pb_field_iterator_t *iter);
static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct);
static bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest);
static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest);
@@ -62,6 +63,7 @@ static bool checkreturn pb_skip_string(pb_istream_t *stream);
*/ */
static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = {
&pb_dec_varint, &pb_dec_varint,
&pb_dec_uvarint,
&pb_dec_svarint, &pb_dec_svarint,
&pb_dec_fixed32, &pb_dec_fixed32,
&pb_dec_fixed64, &pb_dec_fixed64,
@@ -823,8 +825,24 @@ bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, vo
switch (field->data_size) switch (field->data_size)
{ {
case 1: *(uint8_t*)dest = (uint8_t)value; break; case 1: *(int8_t*)dest = (int8_t)value; break;
case 2: *(uint16_t*)dest = (uint16_t)value; break; case 2: *(int16_t*)dest = (int16_t)value; break;
case 4: *(int32_t*)dest = (int32_t)value; break;
case 8: *(int64_t*)dest = (int64_t)value; break;
default: PB_RETURN_ERROR(stream, "invalid data_size");
}
return true;
}
bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
{
uint64_t value;
if (!pb_decode_varint(stream, &value))
return false;
switch (field->data_size)
{
case 4: *(uint32_t*)dest = (uint32_t)value; break; case 4: *(uint32_t*)dest = (uint32_t)value; break;
case 8: *(uint64_t*)dest = value; break; case 8: *(uint64_t*)dest = value; break;
default: PB_RETURN_ERROR(stream, "invalid data_size"); default: PB_RETURN_ERROR(stream, "invalid data_size");

View File

@@ -28,6 +28,7 @@ static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *fie
static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension);
static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData);
static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src);
static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src);
static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src);
@@ -40,6 +41,7 @@ static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t
*/ */
static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = {
&pb_enc_varint, &pb_enc_varint,
&pb_enc_uvarint,
&pb_enc_svarint, &pb_enc_svarint,
&pb_enc_fixed32, &pb_enc_fixed32,
&pb_enc_fixed64, &pb_enc_fixed64,
@@ -424,6 +426,7 @@ bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t
switch (PB_LTYPE(field->type)) switch (PB_LTYPE(field->type))
{ {
case PB_LTYPE_VARINT: case PB_LTYPE_VARINT:
case PB_LTYPE_UVARINT:
case PB_LTYPE_SVARINT: case PB_LTYPE_SVARINT:
wiretype = PB_WT_VARINT; wiretype = PB_WT_VARINT;
break; break;
@@ -505,13 +508,29 @@ bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fie
/* Field encoders */ /* Field encoders */
bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{
int64_t value = 0;
/* Cases 1 and 2 are for compilers that have smaller types for bool
* or enums. */
switch (field->data_size)
{
case 1: value = *(const int8_t*)src; break;
case 2: value = *(const int16_t*)src; break;
case 4: value = *(const int32_t*)src; break;
case 8: value = *(const int64_t*)src; break;
default: PB_RETURN_ERROR(stream, "invalid data_size");
}
return pb_encode_varint(stream, (uint64_t)value);
}
bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src)
{ {
uint64_t value = 0; uint64_t value = 0;
switch (field->data_size) switch (field->data_size)
{ {
case 1: value = *(const uint8_t*)src; break;
case 2: value = *(const uint16_t*)src; break;
case 4: value = *(const uint32_t*)src; break; case 4: value = *(const uint32_t*)src; break;
case 8: value = *(const uint64_t*)src; break; case 8: value = *(const uint64_t*)src; break;
default: PB_RETURN_ERROR(stream, "invalid data_size"); default: PB_RETURN_ERROR(stream, "invalid data_size");