struct jx * nvpair_to_jx( struct nvpair *nv ) { struct jx *object = jx_object(0); char *key; char *value; struct jx *jvalue; long long integer_value; double double_value; nvpair_first_item(nv); while(nvpair_next_item(nv,&key,&value)) { if(!strcmp(value,"true")) { jvalue = jx_boolean(1); } else if(!strcmp(value,"false")) { jvalue = jx_boolean(0); } else if(!strcmp(value,"null")) { jvalue = jx_null(); } else if(string_is_integer(value,&integer_value)) { jvalue = jx_integer(integer_value); } else if(string_is_float(value,&double_value)) { jvalue = jx_double(double_value); } else if(value[0]=='[' || value[0]=='{') { jvalue = jx_parse_string(value); if(!jvalue) jvalue = jx_string(value); } else { jvalue = jx_string(value); } jx_insert(object,jx_string(key),jvalue); } return object; }
static struct jx * jx_eval_null( jx_operator_t op ) { switch(op) { case JX_OP_EQ: return jx_boolean(1); case JX_OP_NE: case JX_OP_LT: case JX_OP_LE: case JX_OP_GT: case JX_OP_GE: return jx_boolean(0); default: return jx_null(); } }
struct jx *jx_copy( struct jx *j ) { if(!j) return 0; switch(j->type) { case JX_NULL: return jx_null(); case JX_DOUBLE: return jx_double(j->u.double_value); case JX_BOOLEAN: return jx_boolean(j->u.boolean_value); case JX_INTEGER: return jx_integer(j->u.integer_value); case JX_SYMBOL: return jx_symbol(j->u.symbol_name); case JX_STRING: return jx_string(j->u.string_value); case JX_ARRAY: return jx_array(jx_item_copy(j->u.items)); case JX_OBJECT: return jx_object(jx_pair_copy(j->u.pairs)); case JX_OPERATOR: return jx_operator(j->u.oper.type,jx_copy(j->u.oper.left),jx_copy(j->u.oper.right)); case JX_FUNCTION: return jx_function(j->u.func.function, jx_copy(j->u.func.arguments)); case JX_ERROR: return jx_error(jx_copy(j->u.err)); } /* not reachable, but some compilers complain. */ return 0; }
struct jx * jx_parse( struct jx_parser *s ) { jx_token_t t = jx_scan(s); switch(t) { case JX_TOKEN_EOF: return 0; case JX_TOKEN_LBRACE: return jx_object(jx_parse_pair_list(s)); case JX_TOKEN_LBRACKET: return jx_array(jx_parse_item_list(s)); case JX_TOKEN_STRING: return jx_string(s->token); case JX_TOKEN_INTEGER: return jx_integer(s->integer_value); case JX_TOKEN_DOUBLE: return jx_double(s->double_value); case JX_TOKEN_TRUE: return jx_boolean(1); case JX_TOKEN_FALSE: return jx_boolean(0); case JX_TOKEN_NULL: return jx_null(); case JX_TOKEN_SYMBOL: if(s->strict_mode) { jx_parse_error(s,"symbols are not allowed in strict parsing mode"); return 0; } else { return jx_symbol(s->token); } case JX_TOKEN_RBRACE: case JX_TOKEN_RBRACKET: case JX_TOKEN_COMMA: case JX_TOKEN_COLON: case JX_TOKEN_ERROR: jx_parse_error(s,"unexpected token"); return 0; } /* We shouldn't get here, since all the token types should be handled above. But just in case... */ jx_parse_error(s,"parse error"); return 0; }
static struct jx * jx_eval_integer( jx_operator_t op, struct jx *left, struct jx *right ) { jx_int_t a = left ? left->u.integer_value : 0; jx_int_t b = right ? right->u.integer_value : 0; switch(op) { case JX_OP_EQ: return jx_boolean(a==b); case JX_OP_NE: return jx_boolean(a!=b); case JX_OP_LT: return jx_boolean(a<b); case JX_OP_LE: return jx_boolean(a<=b); case JX_OP_GT: return jx_boolean(a>b); case JX_OP_GE: return jx_boolean(a>=b); case JX_OP_ADD: return jx_integer(a+b); case JX_OP_SUB: return jx_integer(a-b); case JX_OP_MUL: return jx_integer(a*b); case JX_OP_DIV: if(b==0) return jx_null(); return jx_integer(a/b); case JX_OP_MOD: if(b==0) return jx_null(); return jx_integer(a%b); default: return jx_null(); } }
static struct jx * jx_eval_string( jx_operator_t op, struct jx *left, struct jx *right ) { const char *a = left ? left->u.string_value : ""; const char *b = right ? right->u.string_value : ""; switch(op) { case JX_OP_EQ: return jx_boolean(0==strcmp(a,b)); case JX_OP_NE: return jx_boolean(0!=strcmp(a,b)); case JX_OP_LT: return jx_boolean(strcmp(a,b)<0); case JX_OP_LE: return jx_boolean(strcmp(a,b)<=0); case JX_OP_GT: return jx_boolean(strcmp(a,b)>0); case JX_OP_GE: return jx_boolean(strcmp(a,b)>=0); case JX_OP_ADD: return jx_format("%s%s",a,b); default: return jx_null(); } }
static struct jx * jx_eval_double( jx_operator_t op, struct jx *left, struct jx *right ) { double a = left ? left->u.double_value : 0; double b = right ? right->u.double_value : 0; switch(op) { case JX_OP_EQ: return jx_boolean(a==b); break; case JX_OP_NE: return jx_boolean(a!=b); break; case JX_OP_LT: return jx_boolean(a<b); break; case JX_OP_LE: return jx_boolean(a<=b); break; case JX_OP_GT: return jx_boolean(a>b); break; case JX_OP_GE: return jx_boolean(a>=b); break; case JX_OP_ADD: return jx_double(a+b); break; case JX_OP_SUB: return jx_double(a-b); break; case JX_OP_MUL: return jx_double(a*b); break; case JX_OP_DIV: if(b==0) return jx_null(); return jx_double(a/b); case JX_OP_MOD: if(b==0) return jx_null(); return jx_double((jx_int_t)a%(jx_int_t)b); default: return jx_null(); } }
static struct jx * jx_eval_boolean( jx_operator_t op, struct jx *left, struct jx *right ) { int a = left ? left->u.boolean_value : 0; int b = right ? right->u.boolean_value : 0; switch(op) { case JX_OP_EQ: return jx_boolean(a==b); case JX_OP_NE: return jx_boolean(a!=b); case JX_OP_LT: return jx_boolean(a<b); case JX_OP_LE: return jx_boolean(a<=b); case JX_OP_GT: return jx_boolean(a>b); case JX_OP_GE: return jx_boolean(a>=b); case JX_OP_ADD: return jx_boolean(a|b); case JX_OP_MUL: return jx_boolean(a&b); case JX_OP_AND: return jx_boolean(a&&b); case JX_OP_OR: return jx_boolean(a||b); case JX_OP_NOT: return jx_boolean(!b); case JX_OP_LOOKUP: return jx_null(); default: return jx_boolean(0); } }
static struct jx * jx_eval_operator( struct jx_operator *o, struct jx *context ) { if(!o) return 0; struct jx *left = jx_eval(o->left,context); struct jx *right = jx_eval(o->right,context); if((left && right) && (left->type!=right->type) ) { if( left->type==JX_INTEGER && right->type==JX_DOUBLE) { struct jx *n = jx_double(left->u.integer_value); jx_delete(left); left = n; } else if( left->type==JX_DOUBLE && right->type==JX_INTEGER) { struct jx *n = jx_double(right->u.integer_value); jx_delete(right); right = n; } else if(o->type==JX_OP_EQ) { jx_delete(left); jx_delete(right); return jx_boolean(0); } else if(o->type==JX_OP_NE) { jx_delete(left); jx_delete(right); return jx_boolean(1); } else if(o->type==JX_OP_LOOKUP) { struct jx *r = jx_eval_lookup(left,right); jx_delete(left); jx_delete(right); return r; } else { jx_delete(left); jx_delete(right); return jx_null(); } } struct jx *result; switch(right->type) { case JX_NULL: result = jx_eval_null(o->type); break; case JX_BOOLEAN: result = jx_eval_boolean(o->type,left,right); break; case JX_INTEGER: result = jx_eval_integer(o->type,left,right); break; case JX_DOUBLE: result = jx_eval_double(o->type,left,right); break; case JX_STRING: result = jx_eval_string(o->type,left,right); break; default: result = jx_null(); break; } jx_delete(left); jx_delete(right); return result; }