parent
8978661a76
commit
afe911ea00
1 changed files with 0 additions and 188 deletions
@ -1,188 +0,0 @@ |
||||
/*
|
||||
* upb - a minimalist implementation of protocol buffers. |
||||
* |
||||
* Copyright (c) 2009 Joshua Haberman. See LICENSE for details. |
||||
*/ |
||||
|
||||
#include "upb_mm.h" |
||||
#include "upb_string.h" |
||||
#include "upb_array.h" |
||||
#include "upb_msg.h" |
||||
|
||||
static void upb_mm_destroy(union upb_value_ptr p, upb_mm_ptrtype type) |
||||
{ |
||||
if(*p.msg) { |
||||
union upb_mmptr mmptr = upb_mmptr_read(p, type); |
||||
upb_mm_unref(mmptr, type); |
||||
} |
||||
} |
||||
|
||||
static union upb_mmptr upb_mm_newptr(upb_mm_ptrtype type, |
||||
struct upb_fielddef *f) |
||||
{ |
||||
union upb_mmptr p = {NULL}; |
||||
switch(type) { |
||||
case UPB_MM_MSG_REF: p.msg = upb_msg_new(upb_downcast_msgdef(f->def)); |
||||
case UPB_MM_STR_REF: p.str = upb_string_new(); |
||||
case UPB_MM_ARR_REF: p.arr = upb_array_new(f); |
||||
default: assert(false); break; |
||||
} |
||||
return p; |
||||
} |
||||
|
||||
static struct upb_mm_ref *find_or_create_ref(struct upb_mm_ref *fromref, |
||||
struct upb_mm *mm, |
||||
union upb_mmptr p, upb_mm_ptrtype type, |
||||
bool *created) |
||||
{ |
||||
struct upb_mmhead *head = upb_mmhead_addr(p, type); |
||||
struct upb_mm_ref **ref = &head->refs; |
||||
while(*ref && (*ref)->mm <= mm) { |
||||
if((*ref)->mm == mm) { |
||||
*created = false; |
||||
return *ref; |
||||
} |
||||
ref = &((*ref)->next); |
||||
} |
||||
*created = true; |
||||
struct upb_mm_ref *newref = mm->newref_cb(fromref, p, type); |
||||
newref->p = p; |
||||
newref->type = type; |
||||
newref->mm = mm; |
||||
newref->next = *ref; |
||||
*ref = newref; |
||||
return newref; |
||||
} |
||||
|
||||
struct upb_mm_ref *upb_mm_getref(union upb_mmptr p, upb_mm_ptrtype type, |
||||
struct upb_mm *mm, bool *created) |
||||
{ |
||||
return find_or_create_ref(NULL, mm, p, type, created); |
||||
} |
||||
|
||||
struct upb_mm_ref *upb_mm_newmsg_ref(struct upb_msgdef *def, struct upb_mm *mm) |
||||
{ |
||||
struct upb_msg *msg = upb_msg_new(def); |
||||
union upb_mmptr mmptr = {.msg = msg}; |
||||
bool created; |
||||
struct upb_mm_ref *ref = find_or_create_ref(NULL, mm, mmptr, UPB_MM_MSG_REF, &created); |
||||
upb_mm_unref(mmptr, UPB_MM_MSG_REF); /* Shouldn't have any counted refs. */ |
||||
assert(created); |
||||
return ref; |
||||
} |
||||
|
||||
struct upb_mm_ref *upb_mm_getfieldref(struct upb_mm_ref *msgref, |
||||
struct upb_fielddef *f, |
||||
bool *refcreated) |
||||
{ |
||||
assert(upb_field_ismm(f)); |
||||
upb_mm_ptrtype ptrtype = upb_field_ptrtype(f); |
||||
struct upb_msg *msg = msgref->p.msg; |
||||
union upb_mmptr val; |
||||
union upb_value_ptr p = upb_msg_getptr(msg, f); |
||||
|
||||
/* Create the upb value if it doesn't already exist. */ |
||||
if(!upb_msg_isset(msg, f)) { |
||||
upb_msg_set(msg, f); |
||||
val = upb_mm_newptr(ptrtype, f); |
||||
upb_mmptr_write(p, val, ptrtype); |
||||
} else { |
||||
val = upb_mmptr_read(p, ptrtype); |
||||
} |
||||
|
||||
return find_or_create_ref(msgref, msgref->mm, val, ptrtype, refcreated); |
||||
} |
||||
|
||||
struct upb_mm_ref *upb_mm_getelemref(struct upb_mm_ref *arrref, upb_arraylen_t i, |
||||
bool *refcreated) |
||||
{ |
||||
struct upb_array *arr = arrref->p.arr; |
||||
struct upb_fielddef *f = arr->fielddef; |
||||
assert(upb_elem_ismm(f)); |
||||
assert(i < arr->len); |
||||
union upb_value_ptr p = upb_array_getelementptr(arr, i); |
||||
upb_mm_ptrtype type = upb_elem_ptrtype(f); |
||||
union upb_mmptr val = upb_mmptr_read(p, type); |
||||
return find_or_create_ref(arrref, arrref->mm, val, type, refcreated); |
||||
} |
||||
|
||||
void upb_mm_release(struct upb_mm_ref *ref) |
||||
{ |
||||
struct upb_mm_ref **ref_head = (void*)ref->p.msg; |
||||
struct upb_mm_ref **ref_elem = ref_head; |
||||
struct upb_mm *mm = ref->mm; |
||||
while(true) { |
||||
assert(*ref_elem); /* Client asserts r->mm is in the list. */ |
||||
if((*ref_elem)->mm == mm) { |
||||
*ref_elem = (*ref_elem)->next; /* Remove from the list. */ |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if(upb_mmhead_norefs(&ref->p.msg->mmhead)) { |
||||
/* Destroy the dynamic object. */ |
||||
switch(ref->type) { |
||||
case UPB_MM_MSG_REF: |
||||
upb_msg_destroy(ref->p.msg); |
||||
break; |
||||
case UPB_MM_ARR_REF: |
||||
upb_array_destroy(ref->p.arr); |
||||
break; |
||||
case UPB_MM_STR_REF: |
||||
upb_string_destroy(ref->p.str); |
||||
break; |
||||
default: assert(false); break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void upb_mm_msg_set(struct upb_mm_ref *from_msg_ref, struct upb_mm_ref *to_ref, |
||||
struct upb_fielddef *f) |
||||
{ |
||||
assert(upb_field_ismm(f)); |
||||
union upb_mmptr fromval = from_msg_ref->p; |
||||
union upb_mmptr toval = to_ref->p; |
||||
union upb_value_ptr field_p = upb_msg_getptr(fromval.msg, f); |
||||
upb_mm_ptrtype type = upb_field_ptrtype(f); |
||||
if(upb_msg_isset(fromval.msg, f)) { |
||||
union upb_mmptr existingval = upb_mmptr_read(field_p, type); |
||||
if(existingval.msg == toval.msg) |
||||
return; /* Setting to its existing value, do nothing. */ |
||||
upb_mm_unref(existingval, type); |
||||
} |
||||
upb_msg_set(fromval.msg, f); |
||||
upb_mmptr_write(field_p, toval, type); |
||||
upb_mm_ref(toval, type); |
||||
} |
||||
|
||||
void upb_mm_msgclear(struct upb_mm_ref *from_msg_ref, struct upb_fielddef *f) |
||||
{ |
||||
assert(upb_field_ismm(f)); |
||||
union upb_mmptr fromval = from_msg_ref->p; |
||||
upb_mm_ptrtype type = upb_field_ptrtype(f); |
||||
if(upb_msg_isset(fromval.msg, f)) { |
||||
union upb_value_ptr field_p = upb_msg_getptr(fromval.msg, f); |
||||
union upb_mmptr existingval = upb_mmptr_read(field_p, type); |
||||
upb_msg_unset(fromval.msg, f); |
||||
upb_mm_unref(existingval, type); |
||||
} |
||||
} |
||||
|
||||
void upb_mm_msgclear_all(struct upb_mm_ref *from) |
||||
{ |
||||
struct upb_msgdef *def = from->p.msg->def; |
||||
for(upb_field_count_t i = 0; i < def->num_fields; i++) { |
||||
struct upb_fielddef *f = &def->fields[i]; |
||||
if(!upb_field_ismm(f)) continue; |
||||
upb_mm_msgclear(from, f); |
||||
} |
||||
} |
||||
|
||||
void upb_mm_arr_set(struct upb_mm_ref *from, struct upb_mm_ref *to, |
||||
upb_arraylen_t i, upb_field_type_t type) |
||||
{ |
||||
(void)from; |
||||
(void)to; |
||||
(void)i; |
||||
(void)type; |
||||
} |
Loading…
Reference in new issue