/* * 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 #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