Reorganize the field decoder interface.
This makes the field decoding functions more intuitive to use. The old interface is still present if you specify NANOPB_INTERNALS. Update issue 2 Status: FixedInGit
This commit is contained in:
@@ -320,16 +320,6 @@ In addition to EOF, the pb_decode implementation supports terminating a message
|
|||||||
|
|
||||||
For optional fields, this function applies the default value and sets *has_<field>* to false if the field is not present.
|
For optional fields, this function applies the default value and sets *has_<field>* to false if the field is not present.
|
||||||
|
|
||||||
pb_decode_varint
|
|
||||||
----------------
|
|
||||||
Read and decode a varint_ encoded integer. ::
|
|
||||||
|
|
||||||
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
|
||||||
|
|
||||||
:stream: Input stream to read from. 1-10 bytes will be read.
|
|
||||||
:dest: Storage for the decoded integer. Value is undefined on error.
|
|
||||||
:returns: True on success, false if value exceeds uint64_t range or an IO error happens.
|
|
||||||
|
|
||||||
pb_skip_varint
|
pb_skip_varint
|
||||||
--------------
|
--------------
|
||||||
Skip a varint_ encoded integer without decoding it. ::
|
Skip a varint_ encoded integer without decoding it. ::
|
||||||
@@ -373,48 +363,41 @@ Remove the data for a field from the stream, without actually decoding it::
|
|||||||
:wire_type: Type of field to skip.
|
:wire_type: Type of field to skip.
|
||||||
:returns: True on success, false on IO error.
|
:returns: True on success, false on IO error.
|
||||||
|
|
||||||
.. sidebar:: Field decoders
|
.. sidebar:: Decoding fields manually
|
||||||
|
|
||||||
The functions with names beginning with *pb_dec_* are called field decoders. Each PB_LTYPE has an own field decoder, which handles translating from Protocol Buffers data to C data.
|
The functions with names beginning with *pb_decode_* are used when dealing with callback fields. The typical reason for using callbacks is to have an array of unlimited size. In that case, `pb_decode`_ will call your callback function repeatedly, which can then store the values into e.g. filesystem in the order received in.
|
||||||
|
|
||||||
Each field decoder reads and decodes a single value. For arrays, the decoder is called repeatedly.
|
For decoding numeric (including enumerated and boolean) values, use `pb_decode_varint`_, `pb_decode_svarint`_, `pb_decode_fixed32`_ and `pb_decode_fixed64`_. They take a pointer to a 32- or 64-bit C variable, which you may then cast to smaller datatype for storage.
|
||||||
|
|
||||||
You can use the decoders from your callbacks. Just be aware that the pb_field_t passed to the callback is not directly compatible
|
For decoding strings and bytes fields, the length has already been decoded. You can therefore check the total length in *stream->state* and read the data using `pb_read`_.
|
||||||
with the *varint* field decoders. Instead, you must create a new pb_field_t structure and set the data_size according to the data type
|
|
||||||
you pass to *dest*, e.g. *field.data_size = sizeof(int);*. Other fields in the *pb_field_t* don't matter.
|
|
||||||
|
|
||||||
The field decoder interface is a bit messy as a result of the interface required inside the nanopb library.
|
Finally, for decoding submessages in a callback, simply use `pb_decode`_ and pass it the *SubMessage_fields* descriptor array.
|
||||||
Eventually they may be replaced by separate wrapper functions with a more friendly interface.
|
|
||||||
|
|
||||||
pb_dec_varint
|
pb_decode_varint
|
||||||
-------------
|
----------------
|
||||||
Field decoder for PB_LTYPE_VARINT. ::
|
Read and decode a varint_ encoded integer. ::
|
||||||
|
|
||||||
bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
||||||
|
|
||||||
:stream: Input stream to read from. 1-10 bytes will be read.
|
:stream: Input stream to read from. 1-10 bytes will be read.
|
||||||
:field: Field description structure. Only *field->data_size* matters.
|
:dest: Storage for the decoded integer. Value is undefined on error.
|
||||||
:dest: Pointer to destination integer. Must have size of *field->data_size* bytes.
|
:returns: True on success, false if value exceeds uint64_t range or an IO error happens.
|
||||||
:returns: True on success, false on IO errors or if `pb_decode_varint`_ fails.
|
|
||||||
|
|
||||||
This function first calls `pb_decode_varint`_. It then copies the first bytes of the 64-bit result value to *dest*, or on big endian architectures, the last bytes.
|
pb_decode_svarint
|
||||||
|
-----------------
|
||||||
|
Similar to `pb_decode_varint`_, except that it performs zigzag-decoding on the value. This corresponds to the Protocol Buffers *sint32* and *sint64* datatypes. ::
|
||||||
|
|
||||||
pb_dec_svarint
|
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
|
||||||
--------------
|
|
||||||
Field decoder for PB_LTYPE_SVARINT. Similar to `pb_dec_varint`_, except that it performs zigzag-decoding on the value. ::
|
|
||||||
|
|
||||||
bool pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
(parameters are the same as `pb_decode_varint`_)
|
||||||
|
|
||||||
(parameters are the same as `pb_dec_varint`_)
|
pb_decode_fixed32
|
||||||
|
-----------------
|
||||||
|
Decode a *fixed32*, *sfixed32* or *float* value. ::
|
||||||
|
|
||||||
pb_dec_fixed32
|
bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
|
||||||
--------------
|
|
||||||
Field decoder for PB_LTYPE_FIXED32. ::
|
|
||||||
|
|
||||||
bool pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
|
||||||
|
|
||||||
:stream: Input stream to read from. 4 bytes will be read.
|
:stream: Input stream to read from. 4 bytes will be read.
|
||||||
:field: Not used.
|
|
||||||
:dest: Pointer to destination *int32_t*, *uint32_t* or *float*.
|
:dest: Pointer to destination *int32_t*, *uint32_t* or *float*.
|
||||||
:returns: True on success, false on IO errors.
|
:returns: True on success, false on IO errors.
|
||||||
|
|
||||||
@@ -422,9 +405,9 @@ This function reads 4 bytes from the input stream.
|
|||||||
On big endian architectures, it then reverses the order of the bytes.
|
On big endian architectures, it then reverses the order of the bytes.
|
||||||
Finally, it writes the bytes to *dest*.
|
Finally, it writes the bytes to *dest*.
|
||||||
|
|
||||||
pb_dec_fixed64
|
pb_decode_fixed64
|
||||||
--------------
|
-----------------
|
||||||
Field decoder for PB_LTYPE_FIXED64. ::
|
Decode a *fixed64*, *sfixed64* or *double* value. ::
|
||||||
|
|
||||||
bool pb_dec_fixed(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_dec_fixed(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
||||||
|
|
||||||
@@ -433,53 +416,16 @@ Field decoder for PB_LTYPE_FIXED64. ::
|
|||||||
:dest: Pointer to destination *int64_t*, *uint64_t* or *double*.
|
:dest: Pointer to destination *int64_t*, *uint64_t* or *double*.
|
||||||
:returns: True on success, false on IO errors.
|
:returns: True on success, false on IO errors.
|
||||||
|
|
||||||
Same as `pb_dec_fixed32`_, except this reads 8 bytes.
|
Same as `pb_decode_fixed32`_, except this reads 8 bytes.
|
||||||
|
|
||||||
pb_dec_bytes
|
pb_make_string_substream
|
||||||
------------
|
------------------------
|
||||||
Field decoder for PB_LTYPE_BYTES. Reads a length-prefixed block of bytes. ::
|
Decode the length for a field with wire type *PB_WT_STRING* and create a substream for reading the data. ::
|
||||||
|
|
||||||
bool pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||||
|
|
||||||
**Note:** This is an internal function that is not useful in decoder callbacks. To read bytes fields in callbacks, use
|
:stream: Original input stream to read the length and data from.
|
||||||
*stream->bytes_left* and `pb_read`_.
|
:substream: New substream that has limited length. Filled in by the function.
|
||||||
|
:returns: True on success, false if reading the length fails.
|
||||||
:stream: Input stream to read from.
|
|
||||||
:field: Field description structure. Only *field->data_size* matters.
|
|
||||||
:dest: Pointer to a structure similar to pb_bytes_array_t.
|
|
||||||
:returns: True on success, false on IO error or if length exceeds the array size.
|
|
||||||
|
|
||||||
This function expects a pointer to a structure with a *size_t* field at start, and a variable sized byte array after it. It will deduce the maximum size of the array from *field->data_size*.
|
|
||||||
|
|
||||||
pb_dec_string
|
|
||||||
-------------
|
|
||||||
Field decoder for PB_LTYPE_STRING. Reads a length-prefixed string. ::
|
|
||||||
|
|
||||||
bool pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
|
||||||
|
|
||||||
**Note:** This is an internal function that is not useful in decoder callbacks. To read string fields in callbacks, use
|
|
||||||
*stream->bytes_left* and `pb_read`_.
|
|
||||||
|
|
||||||
:stream: Input stream to read from.
|
|
||||||
:field: Field description structure. Only *field->data_size* matters.
|
|
||||||
:dest: Pointer to a character array of size *field->data_size*.
|
|
||||||
:returns: True on success, false on IO error or if length exceeds the array size.
|
|
||||||
|
|
||||||
This function null-terminates the string when successful. On error, the contents of the destination array is undefined.
|
|
||||||
|
|
||||||
pb_dec_submessage
|
|
||||||
-----------------
|
|
||||||
Field decoder for PB_LTYPE_SUBMESSAGE. Calls `pb_decode`_ to perform the actual decoding. ::
|
|
||||||
|
|
||||||
bool pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
|
||||||
|
|
||||||
**Note:** This is an internal function that is not useful in decoder callbacks. To read submessage fields in callbacks, use
|
|
||||||
`pb_decode`_ directly.
|
|
||||||
|
|
||||||
:stream: Input stream to read from.
|
|
||||||
:field: Field description structure. Only *field->ptr* matters.
|
|
||||||
:dest: Pointer to the destination structure.
|
|
||||||
:returns: True on success, false on IO error or if `pb_decode`_ fails.
|
|
||||||
|
|
||||||
The *field->ptr* should be a pointer to *pb_field_t* array describing the submessage.
|
|
||||||
|
|
||||||
|
This function uses `pb_decode_varint`_ to read an integer from the stream. This is interpreted as a number of bytes, and the substream is set up so that its `bytes_left` is initially the same as the length. The substream has a wrapper callback that in turn reads from the parent stream.
|
||||||
|
|||||||
@@ -44,10 +44,11 @@ const pb_field_t* decode_unionmessage_type(pb_istream_t *stream)
|
|||||||
|
|
||||||
bool decode_unionmessage_contents(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
|
bool decode_unionmessage_contents(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
|
||||||
{
|
{
|
||||||
pb_field_t field = {}; /* NB: Could get rid of this wrapper by fixing issue #2. */
|
pb_istream_t substream;
|
||||||
field.ptr = fields;
|
if (!pb_make_string_substream(stream, &substream))
|
||||||
|
return false;
|
||||||
|
|
||||||
return pb_dec_submessage(stream, &field, dest_struct);
|
return pb_decode(&substream, fields, dest_struct);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
|||||||
137
pb_decode.c
137
pb_decode.c
@@ -11,6 +11,7 @@
|
|||||||
#define checkreturn __attribute__((warn_unused_result))
|
#define checkreturn __attribute__((warn_unused_result))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NANOPB_INTERNALS
|
||||||
#include "pb.h"
|
#include "pb.h"
|
||||||
#include "pb_decode.h"
|
#include "pb_decode.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -192,7 +193,7 @@ static bool substream_callback(pb_istream_t *stream, uint8_t *buf, size_t count)
|
|||||||
return pb_read(parent, buf, count);
|
return pb_read(parent, buf, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool checkreturn make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
|
bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream)
|
||||||
{
|
{
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
if (!pb_decode_varint32(stream, &size))
|
if (!pb_decode_varint32(stream, &size))
|
||||||
@@ -294,7 +295,7 @@ static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_t
|
|||||||
/* Packed array */
|
/* Packed array */
|
||||||
size_t *size = (size_t*)iter->pSize;
|
size_t *size = (size_t*)iter->pSize;
|
||||||
pb_istream_t substream;
|
pb_istream_t substream;
|
||||||
if (!make_string_substream(stream, &substream))
|
if (!pb_make_string_substream(stream, &substream))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (substream.bytes_left && *size < iter->current->array_size)
|
while (substream.bytes_left && *size < iter->current->array_size)
|
||||||
@@ -329,7 +330,7 @@ static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_t
|
|||||||
{
|
{
|
||||||
pb_istream_t substream;
|
pb_istream_t substream;
|
||||||
|
|
||||||
if (!make_string_substream(stream, &substream))
|
if (!pb_make_string_substream(stream, &substream))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (substream.bytes_left)
|
while (substream.bytes_left)
|
||||||
@@ -467,78 +468,104 @@ bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void
|
|||||||
|
|
||||||
/* Field decoders */
|
/* Field decoders */
|
||||||
|
|
||||||
/* Copy destsize bytes from src so that values are casted properly.
|
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest)
|
||||||
* On little endian machine, copy first n bytes of src
|
|
||||||
* On big endian machine, copy last n bytes of src
|
|
||||||
* srcsize must always be larger than destsize
|
|
||||||
*/
|
|
||||||
static void endian_copy(void *dest, void *src, size_t destsize, size_t srcsize)
|
|
||||||
{
|
{
|
||||||
#ifdef __BIG_ENDIAN__
|
uint64_t value;
|
||||||
memcpy(dest, (char*)src + (srcsize - destsize), destsize);
|
if (!pb_decode_varint(stream, &value))
|
||||||
#else
|
return false;
|
||||||
UNUSED(srcsize);
|
|
||||||
memcpy(dest, src, destsize);
|
if (value & 1)
|
||||||
#endif
|
*dest = ~(value >> 1);
|
||||||
|
else
|
||||||
|
*dest = value >> 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pb_decode_fixed32(pb_istream_t *stream, void *dest)
|
||||||
|
{
|
||||||
|
#ifdef __BIG_ENDIAN__
|
||||||
|
uint8_t *bytes = (uint8_t*)dest;
|
||||||
|
uint8_t lebytes[4];
|
||||||
|
|
||||||
|
if (!pb_read(stream, lebytes, 4))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bytes[0] = lebytes[3];
|
||||||
|
bytes[1] = lebytes[2];
|
||||||
|
bytes[2] = lebytes[1];
|
||||||
|
bytes[3] = lebytes[0];
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return pb_read(stream, (uint8_t*)dest, 4);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pb_decode_fixed64(pb_istream_t *stream, void *dest)
|
||||||
|
{
|
||||||
|
#ifdef __BIG_ENDIAN__
|
||||||
|
uint8_t *bytes = (uint8_t*)dest;
|
||||||
|
uint8_t lebytes[8];
|
||||||
|
|
||||||
|
if (!pb_read(stream, lebytes, 8))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bytes[0] = lebytes[7];
|
||||||
|
bytes[1] = lebytes[6];
|
||||||
|
bytes[2] = lebytes[5];
|
||||||
|
bytes[3] = lebytes[4];
|
||||||
|
bytes[4] = lebytes[3];
|
||||||
|
bytes[5] = lebytes[2];
|
||||||
|
bytes[6] = lebytes[1];
|
||||||
|
bytes[7] = lebytes[0];
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return pb_read(stream, (uint8_t*)dest, 8);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
||||||
{
|
{
|
||||||
uint64_t temp;
|
uint64_t value;
|
||||||
bool status = pb_decode_varint(stream, &temp);
|
bool status = pb_decode_varint(stream, &value);
|
||||||
endian_copy(dest, &temp, field->data_size, sizeof(temp));
|
|
||||||
|
switch (field->data_size)
|
||||||
|
{
|
||||||
|
case 1: *(uint8_t*)dest = value; break;
|
||||||
|
case 2: *(uint16_t*)dest = value; break;
|
||||||
|
case 4: *(uint32_t*)dest = value; break;
|
||||||
|
case 8: *(uint64_t*)dest = value; break;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
||||||
{
|
{
|
||||||
uint64_t temp;
|
int64_t value;
|
||||||
bool status = pb_decode_varint(stream, &temp);
|
bool status = pb_decode_svarint(stream, &value);
|
||||||
temp = (temp >> 1) ^ -(int64_t)(temp & 1);
|
|
||||||
endian_copy(dest, &temp, field->data_size, sizeof(temp));
|
switch (field->data_size)
|
||||||
|
{
|
||||||
|
case 4: *(int32_t*)dest = value; break;
|
||||||
|
case 8: *(int64_t*)dest = value; break;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
||||||
{
|
{
|
||||||
#ifdef __BIG_ENDIAN__
|
|
||||||
uint8_t bytes[4] = {0};
|
|
||||||
bool status = pb_read(stream, bytes, 4);
|
|
||||||
if (status) {
|
|
||||||
uint8_t *d = (uint8_t*)dest;
|
|
||||||
d[0] = bytes[3];
|
|
||||||
d[1] = bytes[2];
|
|
||||||
d[2] = bytes[1];
|
|
||||||
d[3] = bytes[0];
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
#else
|
|
||||||
UNUSED(field);
|
UNUSED(field);
|
||||||
return pb_read(stream, (uint8_t*)dest, 4);
|
return pb_decode_fixed32(stream, dest);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
||||||
{
|
{
|
||||||
#ifdef __BIG_ENDIAN__
|
|
||||||
uint8_t bytes[8] = {0};
|
|
||||||
bool status = pb_read(stream, bytes, 8);
|
|
||||||
if (status) {
|
|
||||||
uint8_t *d = (uint8_t*)dest;
|
|
||||||
d[0] = bytes[7];
|
|
||||||
d[1] = bytes[6];
|
|
||||||
d[2] = bytes[5];
|
|
||||||
d[3] = bytes[4];
|
|
||||||
d[4] = bytes[3];
|
|
||||||
d[5] = bytes[2];
|
|
||||||
d[6] = bytes[1];
|
|
||||||
d[7] = bytes[0];
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
#else
|
|
||||||
UNUSED(field);
|
UNUSED(field);
|
||||||
return pb_read(stream, (uint8_t*)dest, 8);
|
return pb_decode_fixed64(stream, dest);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest)
|
||||||
@@ -577,7 +604,7 @@ bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field
|
|||||||
{
|
{
|
||||||
pb_istream_t substream;
|
pb_istream_t substream;
|
||||||
|
|
||||||
if (!make_string_substream(stream, &substream))
|
if (!pb_make_string_substream(stream, &substream))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (field->ptr == NULL)
|
if (field->ptr == NULL)
|
||||||
|
|||||||
34
pb_decode.h
34
pb_decode.h
@@ -44,20 +44,38 @@ bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struc
|
|||||||
* You may want to use these from your caller or callbacks.
|
* You may want to use these from your caller or callbacks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Decode the tag for the next field in the stream. Gives the wire type and
|
||||||
|
* field tag. At end of the message, returns false and sets eof to true. */
|
||||||
bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
|
bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof);
|
||||||
|
|
||||||
|
/* Skip the field payload data, given the wire type. */
|
||||||
bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
|
bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type);
|
||||||
|
|
||||||
|
/* Decode an integer in the varint format. This works for bool, enum, int32,
|
||||||
|
* int64, uint32 and uint64 field types. */
|
||||||
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest);
|
||||||
|
|
||||||
bool pb_skip_varint(pb_istream_t *stream);
|
/* Decode an integer in the zig-zagged svarint format. This works for sint32
|
||||||
bool pb_skip_string(pb_istream_t *stream);
|
* and sint64. */
|
||||||
|
bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest);
|
||||||
|
|
||||||
/* --- Field decoders ---
|
/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to
|
||||||
* Each decoder takes stream and field description, and a pointer to the field
|
* a 4-byte wide C variable. */
|
||||||
* in the destination struct (dest = struct_addr + field->data_offset).
|
bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
|
||||||
* For arrays, these functions are called repeatedly.
|
|
||||||
|
/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to
|
||||||
|
* a 8-byte wide C variable. */
|
||||||
|
bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
|
||||||
|
|
||||||
|
/* Make a limited-length substream for reading a PB_WT_STRING field. */
|
||||||
|
bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||||
|
|
||||||
|
/* --- Internal functions ---
|
||||||
|
* These functions are not terribly useful for the average library user, but
|
||||||
|
* are exported to make the unit testing and extending nanopb easier.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef NANOPB_INTERNALS
|
||||||
bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
||||||
bool pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
||||||
bool pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
||||||
@@ -67,4 +85,8 @@ bool pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
|||||||
bool pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
||||||
bool pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
bool pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest);
|
||||||
|
|
||||||
|
bool pb_skip_varint(pb_istream_t *stream);
|
||||||
|
bool pb_skip_string(pb_istream_t *stream);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#define NANOPB_INTERNALS
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "pb_decode.h"
|
#include "pb_decode.h"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ bool print_int32(pb_istream_t *stream, const pb_field_t *field, void *arg)
|
|||||||
bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void *arg)
|
bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void *arg)
|
||||||
{
|
{
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
if (!pb_dec_fixed32(stream, NULL, &value))
|
if (!pb_decode_fixed32(stream, &value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
printf((char*)arg, (long)value);
|
printf((char*)arg, (long)value);
|
||||||
@@ -47,7 +47,7 @@ bool print_fixed32(pb_istream_t *stream, const pb_field_t *field, void *arg)
|
|||||||
bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void *arg)
|
bool print_fixed64(pb_istream_t *stream, const pb_field_t *field, void *arg)
|
||||||
{
|
{
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
if (!pb_dec_fixed64(stream, NULL, &value))
|
if (!pb_decode_fixed64(stream, &value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
printf((char*)arg, (long long)value);
|
printf((char*)arg, (long long)value);
|
||||||
|
|||||||
Reference in New Issue
Block a user