bool upb_array_set(upb_array *arr, size_t i, upb_msgval val) { size_t element_size = upb_msgval_sizeof(arr->type); UPB_ASSERT(i <= arr->len); if (i == arr->len) { /* Extending the array. */ if (i == arr->size) { /* Need to reallocate. */ size_t new_size = UPB_MAX(arr->size * 2, 8); size_t new_bytes = new_size * element_size; size_t old_bytes = arr->size * element_size; upb_alloc *alloc = upb_arena_alloc(arr->arena); upb_msgval *new_data = upb_realloc(alloc, arr->data, old_bytes, new_bytes); if (!new_data) { return false; } arr->data = new_data; arr->size = new_size; } arr->len = i + 1; } upb_msgval_write(arr->data, i * element_size, val, element_size); return true; }
bool upb_deflist_push(upb_deflist *l, upb_def *d) { if(++l->len >= l->size) { size_t new_size = UPB_MAX(l->size, 4); new_size *= 2; l->defs = realloc(l->defs, new_size * sizeof(void *)); if (!l->defs) return false; l->size = new_size; } l->defs[l->len - 1] = d; return true; }
void upb_msgdef_layout(upb_msgdef *m) { // Create an ordering over the fields, but only include fields with accessors. upb_fielddef **sorted_fields = malloc(sizeof(upb_fielddef*) * upb_msgdef_numfields(m)); int n = 0; upb_msg_iter i; 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 (f->accessor) sorted_fields[n++] = f; } m->hasbit_bytes = upb_div_round_up(n, 8); m->size = m->hasbit_bytes; // + header_size? // Assign hasbits. qsort(sorted_fields, n, sizeof(*sorted_fields), upb_fielddef_cmphasbit); for (int i = 0; i < n; i++) { upb_fielddef *f = sorted_fields[i]; f->hasbit = i; } // Assign value offsets. qsort(sorted_fields, n, sizeof(*sorted_fields), upb_fielddef_cmpval); size_t max_align = 0; for (int i = 0; i < n; i++) { upb_fielddef *f = sorted_fields[i]; const upb_type_info *type_info = &upb_types[f->type]; size_t size = type_info->size; size_t align = type_info->align; if (upb_isseq(f)) { size = sizeof(void*); align = alignof(void*); } // General alignment rules are: each member must be at an address that is a // multiple of that type's alignment. Also, the size of the structure as a // whole must be a multiple of the greatest alignment of any member. f->offset = upb_align_up(m->size, align); m->size = f->offset + size; max_align = UPB_MAX(max_align, align); } if (max_align > 0) m->size = upb_align_up(m->size, max_align); free(sorted_fields); }
void *upb_pipeline_alloc(upb_pipeline *p, size_t bytes) { void *mem = align_up(p->bump_top); if (!mem || mem > p->bump_limit || p->bump_limit - mem < bytes) { size_t size = regionsize(UPB_MAX(BLOCK_SIZE, bytes)); struct region *r; if (!p->realloc || !(r = p->realloc(p->ud, NULL, size))) { return NULL; } r->prev = p->region_head; p->region_head = r; p->bump_limit = (char*)r + size; mem = &r->data[0]; assert(p->bump_limit > mem); assert(p->bump_limit - mem >= bytes); } p->bump_top = mem + bytes; p->last_alloc = mem; return mem; }
int upb_vrprintf(char **buf, size_t *size, size_t ofs, const char *fmt, va_list args) { // Try once without reallocating. We have to va_copy because we might have // to call vsnprintf again. uint32_t len = *size - ofs; va_list args_copy; va_copy(args_copy, args); uint32_t true_len = vsnprintf(*buf + ofs, len, fmt, args_copy); va_end(args_copy); // Resize to be the correct size. if (true_len >= len) { // Need to print again, because some characters were truncated. vsnprintf // will not write the entire string unless you give it space to store the // NULL terminator also. while (*size < (ofs + true_len + 1)) *size = UPB_MAX(*size * 2, 2); char *newbuf = realloc(*buf, *size); if (!newbuf) return -1; vsnprintf(newbuf + ofs, true_len + 1, fmt, args); *buf = newbuf; } return true_len; }
static bool upb_msglayout_init(const upb_msgdef *m, upb_msglayout *l, upb_msgfactory *factory) { upb_msg_field_iter it; upb_msg_oneof_iter oit; size_t hasbit; size_t submsg_count = 0; const upb_msglayout **submsgs; upb_msglayout_field *fields; for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* f = upb_msg_iter_field(&it); if (upb_fielddef_issubmsg(f)) { submsg_count++; } } memset(l, 0, sizeof(*l)); fields = upb_gmalloc(upb_msgdef_numfields(m) * sizeof(*fields)); submsgs = upb_gmalloc(submsg_count * sizeof(*submsgs)); if ((!fields && upb_msgdef_numfields(m)) || (!submsgs && submsg_count)) { /* OOM. */ upb_gfree(fields); upb_gfree(submsgs); return false; } l->field_count = upb_msgdef_numfields(m); l->fields = fields; l->submsgs = submsgs; /* Allocate data offsets in three stages: * * 1. hasbits. * 2. regular fields. * 3. oneof fields. * * OPT: There is a lot of room for optimization here to minimize the size. */ /* Allocate hasbits and set basic field attributes. */ submsg_count = 0; for (upb_msg_field_begin(&it, m), hasbit = 0; !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* f = upb_msg_iter_field(&it); upb_msglayout_field *field = &fields[upb_fielddef_index(f)]; field->number = upb_fielddef_number(f); field->descriptortype = upb_fielddef_descriptortype(f); field->label = upb_fielddef_label(f); if (upb_fielddef_issubmsg(f)) { const upb_msglayout *sub_layout = upb_msgfactory_getlayout(factory, upb_fielddef_msgsubdef(f)); field->submsg_index = submsg_count++; submsgs[field->submsg_index] = sub_layout; } if (upb_fielddef_haspresence(f) && !upb_fielddef_containingoneof(f)) { field->presence = (hasbit++); } else { field->presence = 0; } } /* Account for space used by hasbits. */ l->size = div_round_up(hasbit, 8); /* Allocate non-oneof fields. */ for (upb_msg_field_begin(&it, m); !upb_msg_field_done(&it); upb_msg_field_next(&it)) { const upb_fielddef* f = upb_msg_iter_field(&it); size_t field_size = upb_msg_fielddefsize(f); size_t index = upb_fielddef_index(f); if (upb_fielddef_containingoneof(f)) { /* Oneofs are handled separately below. */ continue; } fields[index].offset = upb_msglayout_place(l, field_size); } /* Allocate oneof fields. Each oneof field consists of a uint32 for the case * and space for the actual data. */ for (upb_msg_oneof_begin(&oit, m); !upb_msg_oneof_done(&oit); upb_msg_oneof_next(&oit)) { const upb_oneofdef* o = upb_msg_iter_oneof(&oit); upb_oneof_iter fit; size_t case_size = sizeof(uint32_t); /* Could potentially optimize this. */ size_t field_size = 0; uint32_t case_offset; uint32_t data_offset; /* Calculate field size: the max of all field sizes. */ for (upb_oneof_begin(&fit, o); !upb_oneof_done(&fit); upb_oneof_next(&fit)) { const upb_fielddef* f = upb_oneof_iter_field(&fit); field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f)); } /* Align and allocate case offset. */ case_offset = upb_msglayout_place(l, case_size); data_offset = upb_msglayout_place(l, field_size); for (upb_oneof_begin(&fit, o); !upb_oneof_done(&fit); upb_oneof_next(&fit)) { const upb_fielddef* f = upb_oneof_iter_field(&fit); fields[upb_fielddef_index(f)].offset = data_offset; fields[upb_fielddef_index(f)].presence = ~case_offset; } } /* Size of the entire structure should be a multiple of its greatest * alignment. TODO: track overall alignment for real? */ l->size = align_up(l->size, 8); return true; }