summaryrefslogtreecommitdiff
path: root/pbstream.h
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-02-25 17:39:49 -0800
committerJoshua Haberman <joshua@reverberate.org>2009-02-25 17:39:49 -0800
commit73978bfc74666fb13c6e65f8c9c4cec90de24236 (patch)
treebcb2559a29894e831405a3f359d8f2cdba6c8d98 /pbstream.h
parent1aa1627fc1ccf0e22d87d2b71ad356a1150190f2 (diff)
API cleanup.
Diffstat (limited to 'pbstream.h')
-rw-r--r--pbstream.h104
1 files changed, 51 insertions, 53 deletions
diff --git a/pbstream.h b/pbstream.h
index 9277843..2713974 100644
--- a/pbstream.h
+++ b/pbstream.h
@@ -41,9 +41,8 @@ typedef enum pbstream_wire_type {
typedef int32_t pbstream_field_number_t;
/* A deserialized value as described in a .proto file. */
-struct pbstream_field_descriptor;
struct pbstream_value {
- struct pbstream_field_descriptor *field_descriptor;
+ struct pbstream_field *field;
union {
double _double;
float _float;
@@ -60,6 +59,7 @@ struct pbstream_value {
} v;
};
+/* A tag occurs before each value on-the-wire. */
struct pbstream_tag {
pbstream_field_number_t field_number;
pbstream_wire_type_t wire_type;
@@ -79,30 +79,47 @@ struct pbstream_wire_value {
} v;
};
-/* The definition of a field as defined in a pbstream (within a message).
- * For example:
- * required int32 a = 1;
- */
-struct pbstream_field_descriptor {
+/* Definition of a single field in a message. */
+struct pbstream_field {
pbstream_field_number_t field_number;
pbstream_type_t type;
- struct pbstream_message_descriptor *message; /* if type == MESSAGE */
+ struct pbstream_fieldset *fieldset; /* if type == MESSAGE */
+};
+
+/* The set of fields corresponding to a message definition. */
+struct pbstream_fieldset {
+ /* TODO: a hybrid array/hashtable structure. */
+ int num_fields;
+ struct pbstream_field fields[];
};
-/* A message as defined by the "message" construct in a .proto file. */
-typedef int pbstream_fieldset_t; /* TODO */
-struct pbstream_message_descriptor {
- pbstream_fieldset_t fieldset;
+struct pbstream_parse_stack_frame {
+ struct pbstream_fieldset *fieldset;
+ size_t end_offset; /* unknown for the top frame, so we set to SIZE_MAX */
};
-/* Callback for when an error occurred.
- * The description is a static buffer which the client must not free. The
- * offset is the location in the input where the error was detected (this
- * offset is relative to the beginning of the stream). If is_fatal is true,
- * parsing cannot continue. */
+/* The stream parser's state. */
+struct pbstream_parse_state {
+ size_t offset;
+ void *user_data;
+ struct pbstream_parse_stack_frame *base, *top, *limit;
+};
+
+/* Call this once before parsing to initialize the data structures.
+ * message_type can be NULL, in which case all fields will be reported as
+ * unknown. */
+void pbstream_init_parser(
+ struct pbstream_parse_state *state,
+ struct pbstream_fieldset *toplevel_fieldset,
+ void *user_data);
+
+/* Status as returned by pbstream_parse(). Status codes <0 are fatal errors
+ * that cannot be recovered. Status codes >0 are unusual but nonfatal events,
+ * which nonetheless must be handled differently since they do not return data
+ * in val. */
typedef enum pbstream_status {
PBSTREAM_STATUS_OK = 0,
- PBSTREAM_STATUS_SUBMESSAGE_END = 1,
+ PBSTREAM_STATUS_SUBMESSAGE_END = 1, // No data is stored in val or wv.
/** FATAL ERRORS: these indicate corruption, and cannot be recovered. */
@@ -117,45 +134,26 @@ typedef enum pbstream_status {
/** NONFATAL ERRORS: the input was invalid, but we can continue if desired. */
- // A value was encountered that was not defined in the .proto file.
+ // A value was encountered that was not defined in the .proto file. The
+ // unknown value is stored in wv.
PBSTREAM_ERROR_UNKNOWN_VALUE = 2,
- // A field was encoded with the wrong wire type.
+ // A field was encoded with the wrong wire type. The wire value is stored in
+ // wv.
PBSTREAM_ERROR_MISMATCHED_TYPE = 3,
} pbstream_status_t;
struct pbstream_parse_state;
-struct pbstream_parse_stack_frame {
- struct pbstream_message_descriptor *message_descriptor;
- size_t end_offset; /* unknown for the top frame, so we set to SIZE_MAX */
-};
-
-/* The stream parser's state. */
-struct pbstream_parse_state {
- size_t offset;
- void *user_data;
- struct pbstream_parse_stack_frame *base, *top, *limit;
-};
-
-/* Call this once before parsing to initialize the data structures.
- * message_type can be NULL, in which case all fields will be reported as
- * unknown. */
-void pbstream_init_parser(
- struct pbstream_parse_state *state,
- struct pbstream_message_descriptor *message_descriptor,
- void *user_data);
-
-/* Call this to parse as much of buf as possible, calling callbacks as
- * appropriate. buf need not be a complete pbstream. Returns the number of
- * bytes consumed. In subsequent calls, buf should point to the first byte not
- * consumed by previous calls.
+/* The main parsing function. Parses the next value from buf, storing the
+ * parsed value in val. If val is of type PBSTREAM_TYPE_MESSAGE, then a
+ * submessage was entered.
*
- * If need_more_bytes is non-zero when parse() returns, this indicates that the
- * beginning of a string or sub-message was recognized, but not all bytes of
- * the string were in memory. The string will not be successfully parsed (and
- * thus parsing of the pbstream cannot proceed) unless need_more_bytes more
- * data is available upon the next call to parse. The caller may need to
- * increase its buffer size. */
-
-pbstream_status_t pbstream_parse(struct pbstream_parse_state *state,
- char *buf, int buf_len, int buf_offset);
+ * IMPORTANT NOTE: for efficiency, the parsing routines do not do bounds checks,
+ * and may read as much as far as buf+10. So the caller must ensure that buf is
+ * not within 10 bytes of unmapped memory, or the program will segfault. Clients
+ * are encouraged to overallocate their buffers by ten bytes to compensate. */
+pbstream_status_t pbstream_parse_field(struct pbstream_parse_state *s,
+ char *buf,
+ pbstream_field_number_t *fieldnum,
+ struct pbstream_value *val,
+ struct pbstream_wire_value *wv);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback