summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2009-12-29 19:41:51 -0800
committerJoshua Haberman <joshua@reverberate.org>2009-12-29 19:41:51 -0800
commit3f0d126b2a35952e97555378f7ea5d370e1c424e (patch)
tree69e9de6e157c6b8b5a93085da4f94eb47276ecfe
parentcc396257679698852380822bc6bfb61d33244172 (diff)
Only remaining undefined symbol is upb_msg_parsestr.
-rw-r--r--Makefile2
-rw-r--r--src/upb_data.c96
-rw-r--r--src/upb_data.h48
-rw-r--r--src/upb_text.c45
4 files changed, 130 insertions, 61 deletions
diff --git a/Makefile b/Makefile
index d7b67a1..0fd7f65 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ clean:
# The core library (src/libupb.a)
SRC=src/upb.c src/upb_parse.c src/upb_table.c src/upb_def.c src/upb_data.c \
- descriptor/descriptor.c
+ descriptor/descriptor.c src/upb_text.c
# Override the optimization level for upb_def.o, because it is not in the
# critical path but gets very large when -O3 is used.
src/upb_def.o: src/upb_def.c
diff --git a/src/upb_data.c b/src/upb_data.c
index b654fac..0f58556 100644
--- a/src/upb_data.c
+++ b/src/upb_data.c
@@ -8,10 +8,6 @@
#include "upb_data.h"
#include "upb_def.h"
-INLINE void data_init(upb_data *d, int flags) {
- d->v = flags;
-}
-
static uint32_t round_up_to_pow2(uint32_t v)
{
/* cf. http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
@@ -25,6 +21,28 @@ static uint32_t round_up_to_pow2(uint32_t v)
return v;
}
+/* upb_data *******************************************************************/
+
+static void data_elem_unref(void *d, struct upb_fielddef *f) {
+ if(f->type == UPB_TYPE(MESSAGE) || f->type == UPB_TYPE(GROUP)) {
+ upb_msg_unref((upb_msg*)d, upb_downcast_msgdef(f->def));
+ } else if(f->type == UPB_TYPE(STRING) || f->type == UPB_TYPE(BYTES)) {
+ upb_string_unref((upb_string*)d);
+ }
+}
+
+static void data_unref(void *d, struct upb_fielddef *f) {
+ if(upb_isarray(f)) {
+ upb_array_unref((upb_array*)d, f);
+ } else {
+ data_elem_unref(d, f);
+ }
+}
+
+INLINE void data_init(upb_data *d, int flags) {
+ d->v = flags;
+}
+
static void check_not_frozen(upb_data *d) {
// On one hand I am reluctant to put abort() calls in a low-level library
// that are enabled in a production build. On the other hand, this is a bug
@@ -50,6 +68,9 @@ static void string_set_bytesize(upb_string *s, upb_strlen_t newsize) {
}
}
+
+/* upb_string *******************************************************************/
+
upb_string *upb_string_new() {
upb_string *s = malloc(sizeof(upb_refcounted_string));
data_init(&s->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
@@ -76,6 +97,43 @@ void upb_string_resize(upb_string *s, upb_strlen_t byte_len) {
s->common.byte_len = byte_len;
}
+upb_string *upb_strreadfile(const char *filename) {
+ FILE *f = fopen(filename, "rb");
+ if(!f) return false;
+ if(fseek(f, 0, SEEK_END) != 0) goto error;
+ long size = ftell(f);
+ if(size < 0) goto error;
+ if(fseek(f, 0, SEEK_SET) != 0) goto error;
+ upb_string *s = upb_string_new();
+ char *buf = upb_string_getrwbuf(s, size);
+ if(fread(buf, size, 1, f) != 1) goto error;
+ fclose(f);
+ return s;
+
+error:
+ fclose(f);
+ return NULL;
+}
+
+
+/* upb_array ******************************************************************/
+
+// ONLY handles refcounted arrays for the moment.
+void _upb_array_free(upb_array *a, struct upb_fielddef *f)
+{
+ if(upb_elem_ismm(f)) {
+ for(upb_arraylen_t i = 0; i < a->refcounted.size; i++) {
+ union upb_value_ptr p = _upb_array_getptr(a, f, i);
+ data_elem_unref(p._void, f);
+ }
+ }
+ if(a->refcounted.size != 0) free(a->common.elements._void);
+ free(a);
+}
+
+
+/* upb_msg ********************************************************************/
+
upb_msg *upb_msg_new(struct upb_msgdef *md) {
upb_msg *msg = malloc(md->size);
memset(msg, 0, md->size);
@@ -83,28 +141,16 @@ upb_msg *upb_msg_new(struct upb_msgdef *md) {
return msg;
}
-#if 0
-void upb_msg_destroy(struct upb_msg *msg) {
- for(upb_field_count_t i = 0; i < msg->def->num_fields; i++) {
- struct upb_fielddef *f = &msg->def->fields[i];
- if(!upb_msg_isset(msg, f) || !upb_field_ismm(f)) continue;
- upb_mm_destroy(upb_msg_getptr(msg, f), upb_field_ptrtype(f));
+// ONLY handles refcounted messages for the moment.
+void _upb_msg_free(upb_msg *msg, struct upb_msgdef *md)
+{
+ for(int i = 0; i < md->num_fields; i++) {
+ struct upb_fielddef *f = &md->fields[i];
+ union upb_value_ptr p = _upb_msg_getptr(msg, f);
+ if(!upb_field_ismm(f) || !p._void) continue;
+ data_unref(p._void, f);
}
- upb_def_unref(UPB_UPCAST(msg->def));
+ upb_def_unref(UPB_UPCAST(md));
free(msg);
}
-void upb_array_destroy(struct upb_array *arr)
-{
- if(upb_elem_ismm(arr->fielddef)) {
- upb_arraylen_t i;
- /* Unref elements. */
- for(i = 0; i < arr->size; i++) {
- union upb_value_ptr p = upb_array_getelementptr(arr, i);
- upb_mm_destroy(p, upb_elem_ptrtype(arr->fielddef));
- }
- }
- if(arr->size != 0) free(arr->elements._void);
- free(arr);
-}
-#endif
diff --git a/src/upb_data.h b/src/upb_data.h
index 471272f..e5980ce 100644
--- a/src/upb_data.h
+++ b/src/upb_data.h
@@ -378,12 +378,29 @@ typedef struct type ## _array { \
// empty. Caller owns one ref on it.
upb_array *upb_array_new(void);
-INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
- int elem) {
+// INTERNAL-ONLY:
+// Frees the given message and releases references on members.
+void _upb_array_free(upb_array *a, struct upb_fielddef *f);
+
+// INTERNAL-ONLY:
+// Returns a pointer to the given elem.
+INLINE union upb_value_ptr _upb_array_getptr(upb_array *a,
+ struct upb_fielddef *f, int elem) {
assert(elem < upb_array_len(a));
size_t type_size = upb_type_info[f->type].size;
union upb_value_ptr p = {._void = &a->common.elements.uint8[elem * type_size]};
- return upb_value_read(p, f->type);
+ return p;
+}
+
+INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
+ int elem) {
+ return upb_value_read(_upb_array_getptr(a, f, elem), f->type);
+}
+
+// The caller releases a ref on the given array, which it must previously have
+// owned a ref on.
+INLINE void upb_array_unref(upb_array *a, struct upb_fielddef *f) {
+ if(_upb_data_unref(&a->common.base)) _upb_array_free(a, f);
}
#if 0
@@ -392,10 +409,6 @@ INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
// were incompatible with src's.
INLINE upb_array *upb_array_getref(upb_array *src, int ref_flags);
-// The caller releases a ref on the given array, which it must previously have
-// owned a ref on.
-INLINE void upb_array_unref(upb_array *a, struct upb_fielddef *f);
-
// Sets the given element in the array to val. The current length of the array
// must be greater than elem. If the field type is dynamic, the array will
// take a ref on val and release a ref on what was previously in the array.
@@ -429,20 +442,33 @@ struct upb_msg {
// Creates a new msg of the given type.
upb_msg *upb_msg_new(struct upb_msgdef *md);
+// INTERNAL-ONLY:
+// Frees the given message and releases references on members.
+void _upb_msg_free(upb_msg *msg, struct upb_msgdef *md);
+
+// INTERNAL-ONLY:
+// Returns a pointer to the given field.
+INLINE union upb_value_ptr _upb_msg_getptr(upb_msg *msg, struct upb_fielddef *f) {
+ union upb_value_ptr p = {._void = &msg->data[f->byte_offset]};
+ return p;
+}
+
+// Releases a references on msg.
+INLINE void upb_msg_unref(upb_msg *msg, struct upb_msgdef *md) {
+ if(_upb_data_unref(&msg->base)) _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, struct upb_fielddef *f) {
return msg->data[f->field_index/8] % (1 << (f->field_index % 8));
}
-void upb_msg_unref(upb_msg *msg, struct upb_msgdef *md);
-
// Returns the current value if set, or the default value if not set, of the
// specified field. The caller does *not* own a ref.
INLINE union upb_value upb_msg_get(upb_msg *msg, struct upb_fielddef *f) {
if(upb_msg_has(msg, f)) {
- union upb_value_ptr p = {._void = &msg->data[f->byte_offset]};
- return upb_value_read(p, f->type);
+ return upb_value_read(_upb_msg_getptr(msg, f), f->type);
} else {
return f->default_value;
}
diff --git a/src/upb_text.c b/src/upb_text.c
index 103468c..17efa9f 100644
--- a/src/upb_text.c
+++ b/src/upb_text.c
@@ -7,9 +7,7 @@
#include <inttypes.h>
#include "descriptor.h"
#include "upb_text.h"
-#include "upb_string.h"
-#include "upb_msg.h"
-#include "upb_array.h"
+#include "upb_data.h"
void upb_text_printval(upb_field_type_t type, union upb_value val, FILE *file)
{
@@ -51,7 +49,7 @@ static void print_indent(struct upb_text_printer *p, FILE *stream)
}
void upb_text_printfield(struct upb_text_printer *p,
- struct upb_string *name,
+ upb_string *name,
upb_field_type_t valtype, union upb_value val,
FILE *stream)
{
@@ -65,7 +63,7 @@ void upb_text_printfield(struct upb_text_printer *p,
}
void upb_text_push(struct upb_text_printer *p,
- struct upb_string *submsg_type,
+ upb_string *submsg_type,
FILE *stream)
{
print_indent(p, stream);
@@ -82,49 +80,48 @@ void upb_text_pop(struct upb_text_printer *p,
fprintf(stream, "}\n");
}
-static void printval(struct upb_text_printer *printer, union upb_value_ptr p,
+static void printval(struct upb_text_printer *printer, union upb_value v,
struct upb_fielddef *f,
FILE *stream);
-static void printmsg(struct upb_text_printer *printer, struct upb_msg *msg,
- FILE *stream)
+static void printmsg(struct upb_text_printer *printer,
+ upb_msg *msg, struct upb_msgdef *md, FILE *stream)
{
- struct upb_msgdef *m = msg->def;
- for(upb_field_count_t i = 0; i < m->num_fields; i++) {
- struct upb_fielddef *f = &m->fields[i];
- if(!upb_msg_isset(msg, f)) continue;
- union upb_value_ptr p = upb_msg_getptr(msg, f);
+ for(upb_field_count_t i = 0; i < md->num_fields; i++) {
+ struct upb_fielddef *f = &md->fields[i];
+ if(!upb_msg_has(msg, f)) continue;
+ union upb_value v = upb_msg_get(msg, f);
if(upb_isarray(f)) {
- struct upb_array *arr = *p.arr;
- for(uint32_t j = 0; j < arr->len; j++) {
- union upb_value_ptr elem_p = upb_array_getelementptr(arr, j);
- printval(printer, elem_p, f, stream);
+ upb_array *arr = v.arr;
+ for(uint32_t j = 0; j < upb_array_len(arr); j++) {
+ union upb_value elem = upb_array_get(arr, f, j);
+ printval(printer, elem, f, stream);
}
} else {
- printval(printer, p, f, stream);
+ printval(printer, v, f, stream);
}
}
}
-static void printval(struct upb_text_printer *printer, union upb_value_ptr p,
+static void printval(struct upb_text_printer *printer, union upb_value v,
struct upb_fielddef *f,
FILE *stream)
{
if(upb_issubmsg(f)) {
upb_text_push(printer, f->name, stream);
- printmsg(printer, *p.msg, stream);
+ printmsg(printer, v.msg, upb_downcast_msgdef(f->def), stream);
upb_text_pop(printer, stream);
} else {
- upb_text_printfield(printer, f->name, f->type,
- upb_value_read(p, f->type), stream);
+ upb_text_printfield(printer, f->name, f->type, v, stream);
}
}
-void upb_msg_print(struct upb_msg *msg, bool single_line, FILE *stream)
+void upb_msg_print(upb_msg *msg, struct upb_msgdef *md, bool single_line,
+ FILE *stream)
{
struct upb_text_printer printer;
upb_text_printer_init(&printer, single_line);
- printmsg(&printer, msg, stream);
+ printmsg(&printer, msg, md, stream);
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback