diff options
Diffstat (limited to 'core/upb_msg.h')
-rw-r--r-- | core/upb_msg.h | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/core/upb_msg.h b/core/upb_msg.h new file mode 100644 index 0000000..0569039 --- /dev/null +++ b/core/upb_msg.h @@ -0,0 +1,96 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2010-2011 Joshua Haberman. See LICENSE for details. + * + * Data structure for storing a message of protobuf data. Unlike Google's + * protobuf, upb_msg and upb_array are reference counted instead of having + * exclusive ownership of their fields. This is a better match for dynamic + * languages where statements like a.b = other_b are normal. + * + * upb's parsers and serializers could also be used to populate and serialize + * other kinds of message objects (even one generated by Google's protobuf). + */ + +#ifndef UPB_MSG_H +#define UPB_MSG_H + +#include "upb.h" +#include "upb_def.h" +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* upb_array ******************************************************************/ + +typedef uint32_t upb_arraylen_t; +struct _upb_array { + upb_atomic_refcount_t refcount; + upb_arraylen_t len; + upb_arraylen_t size; + upb_valueptr elements; +}; + +void _upb_array_free(upb_array *a, upb_fielddef *f); +INLINE upb_valueptr _upb_array_getptr(upb_array *a, upb_fielddef *f, + uint32_t elem) { + upb_valueptr p; + p._void = &a->elements.uint8[elem * upb_types[f->type].size]; + return p; +} + +upb_array *upb_array_new(void); + +INLINE void upb_array_unref(upb_array *a, upb_fielddef *f) { + if (upb_atomic_unref(&a->refcount)) _upb_array_free(a, f); +} + +INLINE uint32_t upb_array_len(upb_array *a) { + return a->len; +} + +/* upb_msg ********************************************************************/ + +struct _upb_msg { + upb_atomic_refcount_t refcount; + uint8_t data[4]; // We allocate the appropriate amount per message. +}; + +void _upb_msg_free(upb_msg *msg, upb_msgdef *md); + +INLINE upb_valueptr _upb_msg_getptr(upb_msg *msg, upb_fielddef *f) { + upb_valueptr p; + p._void = &msg->data[f->byte_offset]; + return p; +} + +// Creates a new msg of the given type. +upb_msg *upb_msg_new(upb_msgdef *md); + +// Unrefs the given message. +INLINE void upb_msg_unref(upb_msg *msg, upb_msgdef *md) { + if (msg && upb_atomic_unref(&msg->refcount)) _upb_msg_free(msg, md); +} + +// Tests whether the given field is explicitly set, or whether it will return a +// default. +INLINE bool upb_msg_has(upb_msg *msg, upb_fielddef *f) { + return (msg->data[f->field_index/8] & (1 << (f->field_index % 8))) != 0; +} + +// Unsets all field values back to their defaults. +INLINE void upb_msg_clear(upb_msg *msg, upb_msgdef *md) { + memset(msg->data, 0, md->set_flags_bytes); +} + +// Registers a set of handlers that will populate this msgdef. +void upb_msg_register_handlers(upb_msg *msg, upb_msgdef *md, + upb_handlers *handlers); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif |