static heim_object_t parse_value(struct parse_ctx *ctx) { size_t len; heim_object_t o; if (white_spaces(ctx)) return NULL; if (*ctx->p == '"') { return parse_string(ctx); } else if (*ctx->p == '{') { if (ctx->depth-- == 1) { ctx->error = heim_error_create(EINVAL, "JSON object too deep"); return NULL; } o = parse_dict(ctx); ctx->depth++; return o; } else if (*ctx->p == '[') { if (ctx->depth-- == 1) { ctx->error = heim_error_create(EINVAL, "JSON object too deep"); return NULL; } o = parse_array(ctx); ctx->depth++; return o; } else if (is_number(*ctx->p) || *ctx->p == '-') { return parse_number(ctx); } len = ctx->pend - ctx->p; if ((ctx->flags & HEIM_JSON_F_NO_C_NULL) == 0 && len >= 6 && memcmp(ctx->p, "<NULL>", 6) == 0) { ctx->p += 6; return heim_null_create(); } else if (len >= 4 && memcmp(ctx->p, "null", 4) == 0) { ctx->p += 4; return heim_null_create(); } else if (len >= 4 && strncasecmp((char *)ctx->p, "true", 4) == 0) { ctx->p += 4; return heim_bool_create(1); } else if (len >= 5 && strncasecmp((char *)ctx->p, "false", 5) == 0) { ctx->p += 5; return heim_bool_create(0); } ctx->error = heim_error_create(EINVAL, "unknown char %c at %lu line %lu", (char)*ctx->p, (unsigned long)(ctx->p - ctx->pstart), ctx->lineno); return NULL; }
static heim_object_t parse_value(struct parse_ctx *ctx) { size_t len; if (white_spaces(ctx)) return NULL; if (*ctx->p == '"') { return parse_string(ctx); } else if (*ctx->p == '{') { return parse_dict(ctx); } else if (*ctx->p == '[') { return parse_array(ctx); } else if (is_number(*ctx->p) || *ctx->p == '-') { return parse_number(ctx); } len = ctx->pend - ctx->p; if (len >= 4 && memcmp(ctx->p, "null", 4) == 0) { ctx->p += 4; return heim_null_create(); } else if (len >= 4 && strncasecmp((char *)ctx->p, "true", 4) == 0) { ctx->p += 4; return heim_bool_create(1); } else if (len >= 5 && strncasecmp((char *)ctx->p, "false", 5) == 0) { ctx->p += 5; return heim_bool_create(0); } ctx->error = heim_error_create(EINVAL, "unknown char %c at %lu line %lu", (char)*ctx->p, (unsigned long)(ctx->p - ctx->pstart), ctx->lineno); return NULL; }
static int base2json(heim_object_t obj, struct twojson *j) { heim_tid_t type; int first = 0; if (obj == NULL) { if (j->flags & HEIM_JSON_F_CNULL2JSNULL) { obj = heim_null_create(); } else if (j->flags & HEIM_JSON_F_NO_C_NULL) { return EINVAL; } else { indent(j); j->out(j->ctx, "<NULL>\n"); /* This is NOT valid JSON! */ return 0; } } type = heim_get_tid(obj); switch (type) { case HEIM_TID_ARRAY: indent(j); j->out(j->ctx, "[\n"); j->indent++; first = j->first; j->first = 1; heim_array_iterate_f(obj, j, array2json); j->indent--; if (!j->first) j->out(j->ctx, "\n"); indent(j); j->out(j->ctx, "]\n"); j->first = first; break; case HEIM_TID_DICT: indent(j); j->out(j->ctx, "{\n"); j->indent++; first = j->first; j->first = 1; heim_dict_iterate_f(obj, j, dict2json); j->indent--; if (!j->first) j->out(j->ctx, "\n"); indent(j); j->out(j->ctx, "}\n"); j->first = first; break; case HEIM_TID_STRING: indent(j); j->out(j->ctx, "\""); j->out(j->ctx, heim_string_get_utf8(obj)); j->out(j->ctx, "\""); break; case HEIM_TID_DATA: { heim_dict_t d; heim_string_t v; const heim_octet_string *data; char *b64 = NULL; int ret; if (j->flags & HEIM_JSON_F_NO_DATA) return EINVAL; /* JSON doesn't do binary */ data = heim_data_get_data(obj); ret = base64_encode(data->data, data->length, &b64); if (ret < 0 || b64 == NULL) return ENOMEM; if (j->flags & HEIM_JSON_F_NO_DATA_DICT) { indent(j); j->out(j->ctx, "\""); j->out(j->ctx, b64); /* base64-encode; hope there's no aliasing */ j->out(j->ctx, "\""); free(b64); } else { /* * JSON has no way to represent binary data, therefore the * following is a Heimdal-specific convention. * * We encode binary data as a dict with a single very magic * key with a base64-encoded value. The magic key includes * a uuid, so we're not likely to alias accidentally. */ d = heim_dict_create(2); if (d == NULL) { free(b64); return ENOMEM; } v = heim_string_ref_create(b64, free); if (v == NULL) { free(b64); heim_release(d); return ENOMEM; } ret = heim_dict_set_value(d, heim_tid_data_uuid_key, v); heim_release(v); if (ret) { heim_release(d); return ENOMEM; } ret = base2json(d, j); heim_release(d); if (ret) return ret; } break; } case HEIM_TID_NUMBER: { char num[32]; indent(j); snprintf(num, sizeof (num), "%d", heim_number_get_int(obj)); j->out(j->ctx, num); break; } case HEIM_TID_NULL: indent(j); j->out(j->ctx, "null"); break; case HEIM_TID_BOOL: indent(j); j->out(j->ctx, heim_bool_val(obj) ? "true" : "false"); break; default: return 1; } return 0; }