summaryrefslogtreecommitdiff
path: root/core/upb_msg.h
diff options
context:
space:
mode:
Diffstat (limited to 'core/upb_msg.h')
-rw-r--r--core/upb_msg.h96
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
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback