summaryrefslogtreecommitdiff
path: root/upb
diff options
context:
space:
mode:
Diffstat (limited to 'upb')
-rw-r--r--upb/bytestream.h13
-rw-r--r--upb/def.c129
-rw-r--r--upb/def.h58
-rw-r--r--upb/descriptor.c4
-rw-r--r--upb/msg.h9
-rw-r--r--upb/upb.h2
6 files changed, 149 insertions, 66 deletions
diff --git a/upb/bytestream.h b/upb/bytestream.h
index 2a6f7d2..6090d6a 100644
--- a/upb/bytestream.h
+++ b/upb/bytestream.h
@@ -119,16 +119,17 @@ typedef struct _upb_strref {
// the actual pointers).
const char *ptr;
- // Bytesrc from which this string data comes. This is only guaranteed to be
- // alive from inside the callback; however if the handler knows more about
- // its type and how to prolong its life, it may do so.
- upb_bytesrc *bytesrc;
+ // Length of the string.
+ uint32_t len;
// Offset in the bytesrc that represents the beginning of this string.
uint32_t stream_offset;
- // Length of the string.
- uint32_t len;
+ // Bytesrc from which this string data comes. May be NULL if ptr is set. If
+ // non-NULL, the bytesrc is only guaranteed to be alive from inside the
+ // callback; however if the handler knows more about its type and how to
+ // prolong its life, it may do so.
+ upb_bytesrc *bytesrc;
// Possibly add optional members here like start_line, start_column, etc.
} upb_strref;
diff --git a/upb/def.c b/upb/def.c
index 889eeea..f3f012b 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -38,9 +38,14 @@ static void upb_msgdef_free(upb_msgdef *m);
static void upb_enumdef_free(upb_enumdef *e);
static void upb_unresolveddef_free(struct _upb_unresolveddef *u);
-#ifndef NDEBUG
-static bool upb_def_ismutable(upb_def *def) { return def->symtab == NULL; }
-#endif
+bool upb_def_ismutable(upb_def *def) { return def->symtab == NULL; }
+
+bool upb_def_setfqname(upb_def *def, const char *fqname) {
+ assert(upb_def_ismutable(def));
+ free(def->fqname);
+ def->fqname = strdup(fqname);
+ return true; // TODO: check for acceptable characters.
+}
static void upb_def_free(upb_def *def) {
switch (def->type) {
@@ -73,7 +78,7 @@ void upb_def_ref(upb_def *def) {
static void upb_def_movetosymtab(upb_def *d, upb_symtab *s) {
assert(upb_atomic_read(&d->refcount) > 0);
d->symtab = s;
- if (!upb_atomic_unref(&d->refcount)) upb_symtab_ref(s);
+ upb_symtab_ref(s);
upb_msgdef *m = upb_dyncast_msgdef(d);
if (m) upb_inttable_compact(&m->itof);
}
@@ -216,6 +221,7 @@ upb_fielddef *upb_fielddef_new() {
f->hasbit = 0;
f->offset = 0;
f->number = 0; // not a valid field number.
+ f->hasdefault = false;
f->name = NULL;
f->accessor = NULL;
upb_value_setfielddef(&f->fval, f);
@@ -260,6 +266,17 @@ upb_fielddef *upb_fielddef_dup(upb_fielddef *f) {
return f;
}
+bool upb_fielddef_ismutable(upb_fielddef *f) {
+ return !f->msgdef || upb_def_ismutable(UPB_UPCAST(f->msgdef));
+}
+
+upb_def *upb_fielddef_subdef(upb_fielddef *f) {
+ if (upb_hassubdef(f) && !upb_fielddef_ismutable(f))
+ return f->def;
+ else
+ return NULL;
+}
+
static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) {
assert(upb_dyncast_unresolveddef(f->def));
upb_def_unref(f->def);
@@ -286,25 +303,30 @@ static bool upb_fielddef_resolve(upb_fielddef *f, upb_def *def, upb_status *s) {
return true;
}
-void upb_fielddef_setnumber(upb_fielddef *f, int32_t number) {
+bool upb_fielddef_setnumber(upb_fielddef *f, int32_t number) {
assert(f->msgdef == NULL);
f->number = number;
+ return true;
}
-void upb_fielddef_setname(upb_fielddef *f, const char *name) {
+bool upb_fielddef_setname(upb_fielddef *f, const char *name) {
assert(f->msgdef == NULL);
f->name = strdup(name);
+ return true;
}
-void upb_fielddef_settype(upb_fielddef *f, uint8_t type) {
+bool upb_fielddef_settype(upb_fielddef *f, uint8_t type) {
assert(!f->finalized);
f->type = type;
+ return true;
}
-void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label) {
+bool upb_fielddef_setlabel(upb_fielddef *f, uint8_t label) {
assert(!f->finalized);
f->label = label;
+ return true;
}
+
void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) {
assert(!f->finalized);
// TODO: string ownership?
@@ -322,9 +344,10 @@ void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl)
f->accessor = vtbl;
}
-void upb_fielddef_settypename(upb_fielddef *f, const char *name) {
+bool upb_fielddef_settypename(upb_fielddef *f, const char *name) {
upb_def_unref(f->def);
f->def = UPB_UPCAST(upb_unresolveddef_new(name));
+ return true;
}
// Returns an ordering of fields based on:
@@ -363,8 +386,8 @@ upb_msgdef *upb_msgdef_new() {
upb_strtable_init(&m->ntof, 4, sizeof(upb_ntof_ent));
m->size = 0;
m->hasbit_bytes = 0;
- m->extension_start = 0;
- m->extension_end = 0;
+ m->extstart = 0;
+ m->extend = 0;
return m;
}
@@ -382,11 +405,12 @@ upb_msgdef *upb_msgdef_dup(upb_msgdef *m) {
upb_msgdef *newm = upb_msgdef_new();
newm->size = m->size;
newm->hasbit_bytes = m->hasbit_bytes;
- newm->extension_start = m->extension_start;
- newm->extension_end = m->extension_end;
+ newm->extstart = m->extstart;
+ newm->extend = m->extend;
upb_msg_iter i;
- for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i))
+ for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
upb_msgdef_addfield(newm, upb_fielddef_dup(upb_msg_iter_field(i)));
+ }
return newm;
}
@@ -400,28 +424,38 @@ void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes) {
m->hasbit_bytes = bytes;
}
-void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start) {
+bool upb_msgdef_setextrange(upb_msgdef *m, uint32_t start, uint32_t end) {
assert(upb_def_ismutable(UPB_UPCAST(m)));
- m->extension_start = start;
+ if (start == 0 && end == 0) {
+ // Clearing the extension range -- ok to fall through.
+ } else if (start >= end || start < 1 || end > UPB_MAX_FIELDNUMBER) {
+ return false;
+ }
+ m->extstart = start;
+ m->extend = start;
+ return true;
}
-void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end) {
- assert(upb_def_ismutable(UPB_UPCAST(m)));
- m->extension_end = end;
-}
+bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef **fields, int n) {
+ // Check constraints for all fields before performing any action.
+ for (int i = 0; i < n; i++) {
+ upb_fielddef *f = fields[i];
+ assert(upb_atomic_read(&f->refcount) > 0);
+ if (f->name == NULL || f->number == 0 ||
+ upb_msgdef_itof(m, f->number) || upb_msgdef_ntof(m, f->name))
+ return false;
+ }
-bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f) {
- assert(upb_atomic_read(&f->refcount) > 0);
- if (!upb_atomic_unref(&f->refcount)) upb_msgdef_ref(m);
- if (upb_msgdef_itof(m, f->number) || upb_msgdef_ntof(m, f->name)) {
- upb_fielddef_unref(f);
- return false;
+ // Constraint checks ok, perform the action.
+ for (int i = 0; i < n; i++) {
+ upb_fielddef *f = fields[i];
+ upb_msgdef_ref(m);
+ assert(f->msgdef == NULL);
+ f->msgdef = m;
+ upb_itof_ent itof_ent = {0, f};
+ upb_inttable_insert(&m->itof, f->number, &itof_ent);
+ upb_strtable_insert(&m->ntof, f->name, &f);
}
- assert(f->msgdef == NULL);
- f->msgdef = m;
- upb_itof_ent itof_ent = {0, f};
- upb_inttable_insert(&m->itof, f->number, &itof_ent);
- upb_strtable_insert(&m->ntof, f->name, &f);
return true;
}
@@ -608,7 +642,7 @@ bool upb_symtab_dfs(upb_def *def, upb_def **open_defs, int n,
open_defs[n++] = def;
for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) {
upb_fielddef *f = upb_msg_iter_field(i);
- if (!upb_hasdef(f)) continue;
+ if (!upb_hassubdef(f)) continue;
needcopy |= upb_symtab_dfs(f->def, open_defs, n, addtab);
}
}
@@ -664,7 +698,36 @@ bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status) {
upb_msg_iter j;
for(j = upb_msg_begin(m); !upb_msg_done(j); j = upb_msg_next(m, j)) {
upb_fielddef *f = upb_msg_iter_field(j);
- if(!upb_hasdef(f)) continue; // No resolving necessary.
+ if (f->type == 0) {
+ upb_status_setf(status, UPB_ERROR, "Field type was not set.");
+ return false;
+ }
+
+ // Set default default if none was set explicitly.
+ if (!f->hasdefault) {
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE(DOUBLE): upb_value_setdouble(&f->defaultval, 0); break;
+ case UPB_TYPE(FLOAT): upb_value_setfloat(&f->defaultval, 0); break;
+ case UPB_TYPE(UINT64):
+ case UPB_TYPE(FIXED64): upb_value_setuint64(&f->defaultval, 0); break;
+ case UPB_TYPE(INT64):
+ case UPB_TYPE(SFIXED64):
+ case UPB_TYPE(SINT64): upb_value_setint64(&f->defaultval, 0); break;
+ case UPB_TYPE(INT32):
+ case UPB_TYPE(SINT32):
+ case UPB_TYPE(ENUM):
+ case UPB_TYPE(SFIXED32): upb_value_setint32(&f->defaultval, 0); break;
+ case UPB_TYPE(UINT32):
+ case UPB_TYPE(FIXED32): upb_value_setuint32(&f->defaultval, 0); break;
+ case UPB_TYPE(BOOL): upb_value_setbool(&f->defaultval, false); break;
+ case UPB_TYPE(STRING):
+ case UPB_TYPE(BYTES):
+ case UPB_TYPE(GROUP):
+ case UPB_TYPE(MESSAGE): break; // do nothing for now.
+ }
+ }
+
+ if (!upb_hassubdef(f)) continue; // No resolving necessary.
const char *name = upb_downcast_unresolveddef(f->def)->name;
// Resolve from either the addtab (pending adds) or symtab (existing
diff --git a/upb/def.h b/upb/def.h
index 2b9eac4..a487a3c 100644
--- a/upb/def.h
+++ b/upb/def.h
@@ -14,6 +14,10 @@
* These defs are mutable (and not thread-safe) when first created.
* Once they are added to a defbuilder (and later its symtab) they become
* immutable.
+ *
+ * TODO: consider making thread-safe even when first created by using mutexes
+ * internally. Would also have to change any methods returning pointers to
+ * return copies instead.
*/
#ifndef UPB_DEF_H_
@@ -58,6 +62,11 @@ void upb_def_ref(upb_def *def);
void upb_def_unref(upb_def *def);
upb_def *upb_def_dup(upb_def *def);
+// A def is mutable until it has been added to a symtab.
+bool upb_def_ismutable(upb_def *def);
+INLINE const char *upb_def_fqname(upb_def *def) { return def->fqname; }
+bool upb_def_setfqname(upb_def *def, const char *fqname); // Only if mutable.
+
#define UPB_UPCAST(ptr) (&(ptr)->base)
@@ -77,6 +86,8 @@ typedef struct _upb_fielddef {
uint8_t label; // Use UPB_LABEL() constants.
int16_t hasbit;
uint16_t offset;
+ bool hasdefault;
+ bool active;
int32_t number;
char *name;
upb_value defaultval; // Only meaningful for non-repeated scalars and strings.
@@ -89,6 +100,9 @@ void upb_fielddef_ref(upb_fielddef *f);
void upb_fielddef_unref(upb_fielddef *f);
upb_fielddef *upb_fielddef_dup(upb_fielddef *f);
+// A fielddef is mutable until its msgdef has been added to a symtab.
+bool upb_fielddef_ismutable(upb_fielddef *f);
+
// Read accessors. May be called any time.
INLINE uint8_t upb_fielddef_type(upb_fielddef *f) { return f->type; }
INLINE uint8_t upb_fielddef_label(upb_fielddef *f) { return f->label; }
@@ -113,18 +127,18 @@ upb_def *upb_fielddef_subdef(upb_fielddef *f);
// Write accessors. "Number" and "name" must be set before the fielddef is
// added to a msgdef. For the moment we do not allow these to be set once
// the fielddef is added to a msgdef -- this could be relaxed in the future.
-void upb_fielddef_setnumber(upb_fielddef *f, int32_t number);
-void upb_fielddef_setname(upb_fielddef *f, const char *name);
+bool upb_fielddef_setnumber(upb_fielddef *f, int32_t number);
+bool upb_fielddef_setname(upb_fielddef *f, const char *name);
// These writers may be called at any time prior to being put in a symtab.
-void upb_fielddef_settype(upb_fielddef *f, uint8_t type);
-void upb_fielddef_setlabel(upb_fielddef *f, uint8_t label);
+bool upb_fielddef_settype(upb_fielddef *f, uint8_t type);
+bool upb_fielddef_setlabel(upb_fielddef *f, uint8_t label);
void upb_fielddef_setdefault(upb_fielddef *f, upb_value value);
void upb_fielddef_setfval(upb_fielddef *f, upb_value fval);
void upb_fielddef_setaccessor(upb_fielddef *f, struct _upb_accessor_vtbl *vtbl);
// The name of the message or enum this field is referring to. Must be found
-// at name resolution time (when the symtabtxn is committed to the symtab).
-void upb_fielddef_settypename(upb_fielddef *f, const char *name);
+// at name resolution time (when upb_symtab_add() is called).
+bool upb_fielddef_settypename(upb_fielddef *f, const char *name);
// A variety of tests about the type of a field.
INLINE bool upb_issubmsgtype(upb_fieldtype_t type) {
@@ -141,7 +155,7 @@ INLINE bool upb_isstring(upb_fielddef *f) { return upb_isstringtype(f->type); }
INLINE bool upb_isseq(upb_fielddef *f) { return f->label == UPB_LABEL(REPEATED); }
// Does the type of this field imply that it should contain an associated def?
-INLINE bool upb_hasdef(upb_fielddef *f) {
+INLINE bool upb_hassubdef(upb_fielddef *f) {
return upb_issubmsg(f) || f->type == UPB_TYPE(ENUM);
}
@@ -160,8 +174,7 @@ typedef struct _upb_msgdef {
uint16_t size;
uint8_t hasbit_bytes;
// The range of tag numbers used to store extensions.
- uint32_t extension_start;
- uint32_t extension_end;
+ uint32_t extstart, extend;
} upb_msgdef;
// Hash table entries for looking up fields by name or number.
@@ -170,7 +183,6 @@ typedef struct {
upb_fielddef *f;
} upb_itof_ent;
typedef struct {
- upb_strtable_entry e;
upb_fielddef *f;
} upb_ntof_ent;
@@ -189,25 +201,23 @@ INLINE uint16_t upb_msgdef_size(upb_msgdef *m) { return m->size; }
INLINE uint8_t upb_msgdef_hasbit_bytes(upb_msgdef *m) {
return m->hasbit_bytes;
}
-INLINE uint32_t upb_msgdef_extension_start(upb_msgdef *m) {
- return m->extension_start;
-}
-INLINE uint32_t upb_msgdef_extension_end(upb_msgdef *m) {
- return m->extension_end;
-}
+INLINE uint32_t upb_msgdef_extstart(upb_msgdef *m) { return m->extstart; }
+INLINE uint32_t upb_msgdef_extend(upb_msgdef *m) { return m->extend; }
// Write accessors. May only be called before the msgdef is in a symtab.
void upb_msgdef_setsize(upb_msgdef *m, uint16_t size);
void upb_msgdef_sethasbit_bytes(upb_msgdef *m, uint16_t bytes);
-void upb_msgdef_setextension_start(upb_msgdef *m, uint32_t start);
-void upb_msgdef_setextension_end(upb_msgdef *m, uint32_t end);
+bool upb_msgdef_setextrange(upb_msgdef *m, uint32_t start, uint32_t end);
-// Adds a fielddef to a msgdef, and passes a ref on the field to the msgdef.
+// Adds a fielddef to a msgdef. Caller retains its ref on the fielddef.
// May only be done before the msgdef is in a symtab. The fielddef's name and
// number must be set, and the message may not already contain any field with
-// this name or number -- if it does, the fielddef is unref'd and false is
-// returned. The fielddef may not already belong to another message.
-bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f);
+// this name or number, and this fielddef may not be part of another message,
+// otherwise false is returned and no action is performed.
+bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef **f, int n);
+INLINE bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f) {
+ return upb_msgdef_addfields(m, &f, 1);
+}
// Sets the layout of all fields according to default rules:
// 1. Hasbits for required fields come first, then optional fields.
@@ -374,8 +384,8 @@ upb_def **upb_symtab_getdefs(upb_symtab *s, int *n, upb_deftype_t type);
// Adds the given defs to the symtab, resolving all symbols. Only one def per
// name may be in the list, but defs can replace existing defs in the symtab.
// The entire operation either succeeds or fails. If the operation fails, the
-// symtab is unchanged, false is returned, and status indicates the error. A
-// ref on the defs is passed to the symtab iff the operation succeeds.
+// symtab is unchanged, false is returned, and status indicates the error. The
+// caller retains its ref on all defs in all cases.
bool upb_symtab_add(upb_symtab *s, upb_def **defs, int n, upb_status *status);
// Frees defs that are no longer active in the symtab and are no longer
diff --git a/upb/descriptor.c b/upb/descriptor.c
index 568a0d2..fbaef29 100644
--- a/upb/descriptor.c
+++ b/upb/descriptor.c
@@ -367,11 +367,13 @@ static void upb_fielddef_endmsg(void *_r, upb_status *status) {
upb_fielddef *f = r->f;
// TODO: verify that all required fields were present.
assert(f->number != -1 && f->name != NULL);
- assert((f->def != NULL) == upb_hasdef(f));
+ assert((f->def != NULL) == upb_hassubdef(f));
// Field was successfully read, add it as a field of the msgdef.
upb_msgdef *m = upb_descreader_top(r);
upb_msgdef_addfield(m, f);
+ upb_fielddef_unref(f);
+ r->f = NULL;
char *dstr = r->default_string;
r->default_string = NULL;
upb_value val;
diff --git a/upb/msg.h b/upb/msg.h
index 625d805..ac9e877 100644
--- a/upb/msg.h
+++ b/upb/msg.h
@@ -92,12 +92,17 @@ INLINE bool upb_msg_has(void *m, upb_fielddef *f) {
return f->accessor && f->accessor->has(m, f->fval);
}
-// May only be called for fields that are known to be set.
+// May only be called for fields that have accessors.
INLINE upb_value upb_msg_get(void *m, upb_fielddef *f) {
- assert(upb_msg_has(m, f));
+ assert(f->accessor);
return f->accessor->get(m, f->fval);
}
+INLINE void upb_msg_set(void *m, upb_fielddef *f, upb_value val) {
+ assert(f->accessor);
+ f->accessor->set(m, f->fval, val);
+}
+
INLINE void *upb_seq_begin(void *s, upb_fielddef *f) {
assert(f->accessor);
return f->accessor->seqbegin(s);
diff --git a/upb/upb.h b/upb/upb.h
index 0c49597..633fd00 100644
--- a/upb/upb.h
+++ b/upb/upb.h
@@ -64,6 +64,8 @@ INLINE size_t upb_align_up(size_t val, size_t align) {
// An individual string or array is unaffected by this 16k byte limit.
#define UPB_MAX_FIELDS (2048)
+#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
+
// Nested type names are separated by periods.
#define UPB_SYMBOL_SEPARATOR '.'
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback