Create a message descriptor type.

This replaces the sentinel at the end of the pb_field_t
array for each message type.

git-svn-id: https://svn.kapsi.fi/jpa/nanopb-dev@1007 e3a754e5-d11d-0410-8d38-ebb782a927b9
This commit is contained in:
Michael Poole
2011-11-13 18:10:11 +00:00
committed by Petteri Aimonen
parent dcf43a6416
commit 43b8e20744
17 changed files with 127 additions and 101 deletions

View File

@@ -74,7 +74,7 @@ This is the way to get the size of the message without storing it anywhere::
Person myperson = ...;
pb_ostream_t sizestream = {0};
pb_encode(&sizestream, Person_fields, &myperson);
pb_encode(&sizestream, Person_msg, &myperson);
printf("Encoded size is %d\n", sizestream.bytes_written);
**Example 2:**
@@ -221,10 +221,10 @@ This callback reads multiple integers and prints them::
return true;
}
Field description array
=======================
Message descriptor
==================
For using the *pb_encode* and *pb_decode* functions, you need an array of pb_field_t constants describing the structure you wish to encode. This description is usually autogenerated from .proto file.
For using the *pb_encode* and *pb_decode* functions, you need a message descriptor describing the structure you wish to encode. This description is usually autogenerated from .proto file.
For example this submessage in the Person.proto file::
@@ -235,20 +235,27 @@ For example this submessage in the Person.proto file::
}
}
generates this field description array for the structure *Person_PhoneNumber*::
generates these declarations and definitions for the structure *Person_PhoneNumber*::
typedef PB_MSG_STRUCT(2) Person_PhoneNumber_msg_t;
extern const Person_PhoneNumber_msg_t Person_PhoneNumber_real_msg;
#define Person_PhoneNumber_msg ((const pb_message_t*)&Person_PhoneNumber_real_msg)
const Person_PhoneNumber_msg_t Person_PhoneNumber_real_msg = {
2,
{
const pb_field_t Person_PhoneNumber_fields[3] = {
{1, PB_HTYPE_REQUIRED | PB_LTYPE_STRING,
offsetof(Person_PhoneNumber, number), 0,
pb_membersize(Person_PhoneNumber, number), 0, 0},
{2, PB_HTYPE_OPTIONAL | PB_LTYPE_VARINT,
pb_delta(Person_PhoneNumber, type, number),
pb_delta_end(Person_PhoneNumber, type, number),
pb_delta(Person_PhoneNumber, has_type, type),
pb_membersize(Person_PhoneNumber, type), 0,
&Person_PhoneNumber_type_default},
PB_LAST_FIELD
}
};

View File

@@ -27,7 +27,7 @@ So a typical project might include these files:
- pb_encode.h and pb_encode.c (needed for encoding messages)
2) Protocol description (you can have many):
- person.proto (just an example)
- person.pb.c (autogenerated, contains initializers for const arrays)
- person.pb.c (autogenerated, contains initializers for message descriptors)
- person.pb.h (autogenerated, contains type declarations)
Features and limitations
@@ -74,14 +74,16 @@ You should now have in *message.pb.h*::
int32_t value;
} Example;
extern const pb_field_t Example_fields[2];
typedef PB_MSG_STRUCT(1) Example_msg_t;
extern const Example_msg_t Example_real_msg;
#define Example_msg ((const pb_message_t*)&Example_real_msg)
Now in your main program do this to encode a message::
Example mymessage = {42};
uint8_t buffer[10];
pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
pb_encode(&stream, Example_fields, &mymessage);
pb_encode(&stream, Example_msg, &mymessage);
After that, buffer will contain the encoded message.
The number of bytes in the message is stored in *stream.bytes_written*.

View File

@@ -140,14 +140,14 @@ pb_encode
---------
Encodes the contents of a structure as a protocol buffers message and writes it to output stream. ::
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
bool pb_encode(pb_ostream_t *stream, const pb_message_t *msg, const void *src_struct);
:stream: Output stream to write to.
:fields: A field description array, usually autogenerated.
:msg: A message descriptor, usually autogenerated.
:src_struct: Pointer to the data that will be serialized.
:returns: True on success, false on IO error, on detectable errors in field description, or if a field encoder returns false.
Normally pb_encode simply walks through the fields description array and serializes each field in turn. However, submessages must be serialized twice: first to calculate their size and then to actually write them to output. This causes some constraints for callback fields, which must return the same data on every call.
Normally pb_encode simply walks through the fields description array inside the message descriptor and serializes each field in turn. However, submessages must be serialized twice: first to calculate their size and then to actually write them to output. This causes some constraints for callback fields, which must return the same data on every call.
pb_encode_varint
----------------
@@ -289,7 +289,7 @@ Field encoder for PB_LTYPE_SUBMESSAGE. Calls `pb_encode`_ to perform the actual
bool pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src);
:stream: Output stream to write to.
:field: Field description structure. The *ptr* field must be a pointer to a field description array for the submessage.
:field: Field description structure. The *ptr* field must be a pointer to a valid *pb_message_t* descriptor for the submessage.
:src: Pointer to the structure where submessage data is.
:returns: True on success, false on IO errors, pb_encode errors or if submessage size changes between calls.
@@ -355,10 +355,10 @@ pb_decode
---------
Read and decode all fields of a structure. Reads until EOF on input stream. ::
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
bool pb_decode(pb_istream_t *stream, const pb_message_t *msg, void *dest_struct);
:stream: Input stream to read from.
:fields: A field description array. Usually autogenerated.
:msg: A message descriptor. Usually autogenerated.
:dest_struct: Pointer to structure where data will be stored.
:returns: True on success, false on IO error, on detectable errors in field description, if a field encoder returns false or if a required field is missing.
@@ -459,5 +459,5 @@ Field decoder for PB_LTYPE_SUBMESSAGE. Calls `pb_decode`_ to perform the actual
: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.
The *field->ptr* should be a pointer to *pb_message_t* describing the submessage.