static struct jx_pair * jx_parse_pair_list( struct jx_parser *s ) { jx_token_t t = jx_scan(s); if(t==JX_TOKEN_RBRACE) { // empty list return 0; } jx_unscan(s,t); struct jx_pair *p = jx_pair(0,0,0); p->key = jx_parse(s); if(!p->key) { // error set by deeper layer jx_pair_delete(p); return 0; } if(s->strict_mode) { if(p->key->type!=JX_STRING) { jx_parse_error(s,"key-value pair must have a string as the key"); jx_pair_delete(p); return 0; } } t = jx_scan(s); if(t!=JX_TOKEN_COLON) { jx_parse_error(s,"key-value pair must be separated by a colon"); jx_pair_delete(p); return 0; } p->value = jx_parse(s); if(!p->value) { // error set by deeper layer jx_pair_delete(p); return 0; } t = jx_scan(s); if(t==JX_TOKEN_COMMA) { p->next = jx_parse_pair_list(s); } else if(t==JX_TOKEN_RBRACE) { p->next = 0; } else { jx_parse_error(s,"key-value pairs missing a comma or closing brace"); jx_pair_delete(p); return 0; } return p; }
void jx_delete( struct jx *j ) { if(!j) return; switch(j->type) { case JX_DOUBLE: case JX_BOOLEAN: case JX_INTEGER: case JX_NULL: break; case JX_SYMBOL: free(j->u.symbol_name); break; case JX_STRING: free(j->u.string_value); break; case JX_ARRAY: jx_item_delete(j->u.items); break; case JX_OBJECT: jx_pair_delete(j->u.pairs); break; case JX_OPERATOR: jx_delete(j->u.oper.left); jx_delete(j->u.oper.right); break; case JX_FUNCTION: jx_delete(j->u.func.arguments); break; case JX_ERROR: jx_delete(j->u.err); break; } free(j); }
struct jx * jx_remove( struct jx *object, struct jx *key ) { if(!object || object->type!=JX_OBJECT) return 0; struct jx_pair *p; struct jx_pair *last = 0; for(p=object->u.pairs;p;p=p->next) { if(jx_equals(key,p->key)) { struct jx *value = p->value; if(last) { last->next = p->next; } else { object->u.pairs = p->next; } p->value = 0; p->next = 0; jx_pair_delete(p); return value; } last = p; } return 0; }
void jx_pair_delete( struct jx_pair *pair ) { if(!pair) return; jx_delete(pair->key); jx_delete(pair->value); jx_pair_delete(pair->next); free(pair); }