From 14624e34d82468773516a4ff3eb3a4d6bc030658 Mon Sep 17 00:00:00 2001 From: Joshua Haberman <joshua@reverberate.org> Date: Sun, 1 Mar 2009 14:01:29 -0800 Subject: [PATCH] Added the first iteration of pbstruct. --- pbstruct.c | 11 ++++++ pbstruct.h | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 pbstruct.c create mode 100644 pbstruct.h diff --git a/pbstruct.c b/pbstruct.c new file mode 100644 index 0000000000..97e0a9f840 --- /dev/null +++ b/pbstruct.c @@ -0,0 +1,11 @@ +/* + * pbstream - a stream-oriented implementation of protocol buffers. + * + * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. + */ + +#include <stddef.h> +#include "pbstruct.h" + +#define alignof(t) offsetof(struct { char c; t x; }, x) + diff --git a/pbstruct.h b/pbstruct.h new file mode 100644 index 0000000000..9b12ce3d41 --- /dev/null +++ b/pbstruct.h @@ -0,0 +1,100 @@ +/* + * pbstream - a stream-oriented implementation of protocol buffers. + * + * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. + * + * pbstruct is an efficient, compact, self-describing format for storing + * pb messages in-memory. It can be used when parsing a protobuf into + * a structure is desired, but both the parsing and emitting modules can + * be used without ever using pbstruct. + */ + +#include <stdbool.h> +#include <stdint.h> + +typedef enum pbstruct_type { + PBSTRUCT_TYPE_DOUBLE = 1, + PBSTRUCT_TYPE_FLOAT = 2, + PBSTRUCT_TYPE_INT32 = 3, + PBSTRUCT_TYPE_UINT32 = 4, + PBSTRUCT_TYPE_INT64 = 5, + PBSTRUCT_TYPE_UINT64 = 6, + PBSTRUCT_TYPE_BOOL = 7, + + /* For these types, the main struct contains a pointer to the real data. */ + PBSTRUCT_TYPE_BYTES = 8, + PBSTRUCT_TYPE_STRING = 9, + PBSTRUCT_TYPE_SUBSTRUCT = 10, + + /* The array types are just like the primitive types, except the main struct + * contains a pointer to an array of the primitive type. */ + PBSTRUCT_ARRAY = 16, /* Not itself a real type. */ + PBSTRUCT_TYPE_DOUBLE_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_DOUBLE, + PBSTRUCT_TYPE_FLOAT_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_FLOAT, + PBSTRUCT_TYPE_INT32_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_INT32, + PBSTRUCT_TYPE_UINT32_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_UINT32, + PBSTRUCT_TYPE_INT64_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_INT64, + PBSTRUCT_TYPE_UINT64_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_UINT64, + PBSTRUCT_TYPE_BOOL_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_BOOL, + PBSTRUCT_TYPE_BYTES_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_BYTES, + PBSTRUCT_TYPE_STRING_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_STRING, + PBSTRUCT_TYPE_SUBSTRUCT_ARRAY = PBSTRUCT_ARRAY | PBSTRUCT_TYPE_SUBSTRUCT, +} pbstruct_type_t; + +struct pbstruct_field { + char *name; + pbstruct_type_t type; + ptrdiff_t byte_offset; + ptrdiff_t isset_byte_offset; + uint8_t isset_byte_mask; +}; + +struct pbstruct_delimited { + size_t len; + char data[]; +}; + +struct pbstruct_definition { + char *name; + size_t struct_size; + int num_fields; + int num_required_fields; + struct pbstruct_field fields[]; +}; + +struct pbstruct { + struct pbstruct_definition *definition; + uint8_t data[]; +}; + +struct pbstruct* pbstruct_new(struct pbstruct_definition *definition); +/* Deletes any sub-structs also. */ +struct pbstruct* pbstruct_delete(struct pbstruct_definition *definition); + +bool pbstruct_is_set(struct pbstruct *s, struct pbstruct_field *f) { + return s->data[f->isset_byte_offset] & f->isset_byte_mask; +} + +/* These do no existence checks or type checks. */ +#define DEFINE_GETTERS(ctype, name) \ + ctype pbstruct_get_ ## name(struct pbstruct *s, struct pbstruct_field *f) { \ + /* TODO: make sure the compiler knows this is an aligned access. */ \ + return *(ctype*)(s->data + f->byte_offset); \ + } \ + ctype *pbstruct_get_ ## name ## _array(struct pbstruct *s, \ + struct pbstruct_field *f) { \ + /* TODO: make sure the compiler knows this is an aligned access. */ \ + return *(ctype**)(s->data + f->byte_offset); \ + } + +DEFINE_GETTERS(double, double); +DEFINE_GETTERS(float, float); +DEFINE_GETTERS(int32_t, int32); +DEFINE_GETTERS(int64_t, int64); +DEFINE_GETTERS(uint32_t, uint32); +DEFINE_GETTERS(uint64_t, uint64); +DEFINE_GETTERS(bool, bool); +DEFINE_GETTERS(struct pbstruct_delimited*, bytes); +DEFINE_GETTERS(struct pbstruct_delimited*, string); +DEFINE_GETTERS(struct pbstruct*, substruct); +