Some work on upb_msg, but it has a long way to go.

pull/13171/head
Joshua Haberman 14 years ago
parent d98db7cb56
commit 8536bbc5f8
  1. 44
      core/upb_msg.c
  2. 94
      core/upb_msg.h

@ -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);

@ -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" */

Loading…
Cancel
Save