From 8536bbc5f88a4d2bb98d6875cf317154c263d473 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 29 Jan 2011 20:16:12 -0800 Subject: Some work on upb_msg, but it has a long way to go. --- core/upb_msg.c | 44 +++++++++++++++++++++++++++ core/upb_msg.h | 94 +++++++++++++++++++++++++--------------------------------- 2 files changed, 84 insertions(+), 54 deletions(-) (limited to 'core') diff --git a/core/upb_msg.c b/core/upb_msg.c index a0a5196..83191d2 100644 --- a/core/upb_msg.c +++ b/core/upb_msg.c @@ -53,6 +53,50 @@ void _upb_msg_free(upb_msg *msg, upb_msgdef *md) { free(msg); } +void upb_msg_recycle(upb_msg **_msg, upb_msgdef *md); + upb_msg *msg = *_msg; + if(msg && upb_atomic_only(&msg->refcount)) { + upb_msg_clear(msg); + } else { + upb_msg_unref(msg); + *_msg = upb_msg_new(); + } +} + +void upb_msg_appendval(upb_msg *msg, upb_fielddef *f, upb_value val) { + upb_valueptr ptr; + if (upb_isarray(f)) { + } +} + +INLINE upb_value upb_msg_getmutable(upb_msg *msg, upb_fielddef *f); + assert(upb_field_ismm(f)); + upb_valueptr p = _upb_msg_getptr(msg, f); + upb_valuetype_t type = upb_field_valuetype(f); + upb_value val = upb_value_read(p, type); + if (!upb_msg_has(msg, f)) { + upb_msg_sethas(msg, f); + val = upb_field_tryrecycle(p, val, f, type); + } + return val; +} + +INLINE void upb_msg_set(upb_msg *msg, upb_fielddef *f, upb_value val) { + upb_valueptr p = _upb_msg_getptr(msg, f); + upb_valuetype_t type = upb_field_valuetype(f); + if (upb_field_ismm(f)) { + _upb_field_unref(upb_value_read(p, type), f); + _upb_value_ref(val); + } + upb_msg_sethas(msg, f); + upb_value_write(p, val, upb_field_valuetype(f)); +} + +INLINE void upb_msg_sethas(upb_msg *msg, upb_fielddef *f) { + msg->data[f->field_index/8] |= (1 << (f->field_index % 8)); +} + + upb_array *upb_array_new(void) { upb_array *arr = malloc(sizeof(*arr)); upb_atomic_refcount_init(&arr->refcount, 1); diff --git a/core/upb_msg.h b/core/upb_msg.h index 2db67c0..815a7cb 100644 --- a/core/upb_msg.h +++ b/core/upb_msg.h @@ -45,17 +45,7 @@ struct _upb_array { upb_valueptr elements; }; -upb_array *upb_array_new(void); - -INLINE uint32_t upb_array_len(upb_array *a) { - return a->len; -} - void _upb_array_free(upb_array *a, upb_fielddef *f); -INLINE void upb_array_unref(upb_array *a, upb_fielddef *f) { - if (upb_atomic_unref(&a->refcount)) _upb_array_free(a, f); -} - INLINE upb_valueptr _upb_array_getptr(upb_array *a, upb_fielddef *f, uint32_t elem) { upb_valueptr p; @@ -63,6 +53,16 @@ INLINE upb_valueptr _upb_array_getptr(upb_array *a, upb_fielddef *f, 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; +} + INLINE upb_value upb_array_get(upb_array *a, upb_fielddef *f, uint32_t elem) { assert(elem < upb_array_len(a)); return upb_value_read(_upb_array_getptr(a, f, elem), f->type); @@ -93,6 +93,7 @@ INLINE void upb_array_resize(upb_array *a, upb_fielddef *f) { // Append an element to an array of string or submsg with the default value, // returning it. This will try to reuse previously allocated memory. INLINE upb_value upb_array_appendmutable(upb_array *a, upb_fielddef *f) { + assert(upb_elem_ismm(f)); upb_array_resize(a, f); upb_valueptr p = _upb_array_getptr(a, f, a->len++); @@ -110,8 +111,9 @@ struct _upb_msg { uint8_t data[4]; // We allocate the appropriate amount per message. }; -// Creates a new msg of the given type. -upb_msg *upb_msg_new(upb_msgdef *md); +// INTERNAL-ONLY FUNCTIONS. + +void _upb_msg_free(upb_msg *msg, upb_msgdef *md); // Returns a pointer to the given field. INLINE upb_valueptr _upb_msg_getptr(upb_msg *msg, upb_fielddef *f) { @@ -120,9 +122,14 @@ INLINE upb_valueptr _upb_msg_getptr(upb_msg *msg, upb_fielddef *f) { return p; } -void _upb_msg_free(upb_msg *msg, upb_msgdef *md); +// PUBLIC FUNCTIONS. + +// 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 (upb_atomic_unref(&msg->refcount)) _upb_msg_free(msg, 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 @@ -131,12 +138,26 @@ INLINE bool upb_msg_has(upb_msg *msg, upb_fielddef *f) { return (msg->data[f->field_index/8] & (1 << (f->field_index % 8))) != 0; } -INLINE void upb_msg_sethas(upb_msg *msg, upb_fielddef *f) { - msg->data[f->field_index/8] |= (1 << (f->field_index % 8)); +// 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); } +// Used to obtain an empty message of the given type, attempting to reuse the +// memory pointed to by msg if it has no other referents. +void upb_msg_recycle(upb_msg **_msg, upb_msgdef *md); + +// For a repeated field, appends the given scalar value (ie. not a message or +// array) to the field's array; for non-repeated fields, overwrites the +// existing value with this one. +// REQUIRES: !upb_issubmsg(f) +void upb_msg_appendval(upb_msg *msg, upb_fielddef *f, upb_value val); + +upb_msg *upb_msg_append_emptymsg(upb_msg *msg, upb_fielddef *f); + // Returns the current value of the given field if set, or the default value if -// not set. +// not set. The returned value is not mutable! (In practice this only matters +// for submessages and arrays). INLINE upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) { if (upb_msg_has(msg, f)) { return upb_value_read(_upb_msg_getptr(msg, f), f->type); @@ -148,47 +169,12 @@ INLINE upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) { // If the given string, submessage, or array is already set, returns it. // Otherwise sets it and returns an empty instance, attempting to reuse any // previously allocated memory. -INLINE upb_value upb_msg_getmutable(upb_msg *msg, upb_fielddef *f) { - assert(upb_field_ismm(f)); - upb_valueptr p = _upb_msg_getptr(msg, f); - upb_valuetype_t type = upb_field_valuetype(f); - upb_value val = upb_value_read(p, type); - if (!upb_msg_has(msg, f)) { - upb_msg_sethas(msg, f); - val = upb_field_tryrecycle(p, val, f, type); - } - return val; -} +INLINE upb_value upb_msg_getmutable(upb_msg *msg, upb_fielddef *f); // Sets the current value of the field. If this is a string, array, or // submessage field, releases a ref on the value (if any) that was previously // set. -INLINE void upb_msg_set(upb_msg *msg, upb_fielddef *f, upb_value val) { - upb_valueptr p = _upb_msg_getptr(msg, f); - upb_valuetype_t type = upb_field_valuetype(f); - if (upb_field_ismm(f)) { - _upb_field_unref(upb_value_read(p, type), f); - _upb_value_ref(val); - } - upb_msg_sethas(msg, f); - upb_value_write(p, val, upb_field_valuetype(f)); -} - -// 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); -} - -// A convenience function for decoding an entire protobuf all at once, without -// having to worry about setting up the appropriate objects. -void upb_msg_decodestr(upb_msg *msg, upb_msgdef *md, upb_string *str, - upb_status *status); - -// A convenience function for encoding an entire protobuf all at once. If an -// error occurs, the null string is returned and the status object contains -// the error. -void upb_msg_encodestr(upb_msg *msg, upb_msgdef *md, upb_string *str, - upb_status *status); +INLINE void upb_msg_set(upb_msg *msg, upb_fielddef *f, upb_value val); #ifdef __cplusplus } /* extern "C" */ -- cgit v1.2.3