static int json_print_string(struct lyout *out, const char *text) { unsigned int i, n; if (!text) { return 0; } ly_write(out, "\"", 1); for (i = n = 0; text[i]; i++) { if (text[i] < 0x20) { /* control character */ n += ly_print(out, "\\u%.4X"); } else { switch (text[i]) { case '"': n += ly_print(out, "\\\""); break; case '\\': n += ly_print(out, "\\\\"); break; default: ly_write(out, &text[i], 1); n++; } } } ly_write(out, "\"", 1); return n + 2; }
static int write_iff(struct lyout *out, const struct lys_module *module, struct lys_iffeature *expr, int prefix_kind, int *index_e, int *index_f) { int count = 0, brackets_flag = *index_e; uint8_t op; struct lys_module *mod; op = iff_getop(expr->expr, *index_e); (*index_e)++; switch (op) { case LYS_IFF_F: if (lys_main_module(expr->features[*index_f]->module) != lys_main_module(module)) { if (prefix_kind == 0) { count += ly_print(out, "%s:", transform_module_name2import_prefix(module, lys_main_module(expr->features[*index_f]->module)->name)); } else if (prefix_kind == 1) { count += ly_print(out, "%s:", lys_main_module(expr->features[*index_f]->module)->name); } else if (prefix_kind == 2) { count += ly_print(out, "%s:", lys_main_module(expr->features[*index_f]->module)->prefix); } else if (prefix_kind == 3) { mod = lys_main_module(expr->features[*index_f]->module); count += ly_print(out, "%s%s%s:", mod->name, mod->rev_size ? "@" : "", mod->rev_size ? mod->rev[0].date : ""); } } count += ly_print(out, expr->features[*index_f]->name); (*index_f)++; break; case LYS_IFF_NOT: count += ly_print(out, "not "); count += write_iff(out, module, expr, prefix_kind, index_e, index_f); break; case LYS_IFF_AND: if (brackets_flag) { /* AND need brackets only if previous op was not */ if (*index_e < 2 || iff_getop(expr->expr, *index_e - 2) != LYS_IFF_NOT) { brackets_flag = 0; } } /* falls through */ case LYS_IFF_OR: if (brackets_flag) { count += ly_print(out, "("); } count += write_iff(out, module, expr, prefix_kind, index_e, index_f); count += ly_print(out, " %s ", op == LYS_IFF_OR ? "or" : "and"); count += write_iff(out, module, expr, prefix_kind, index_e, index_f); if (brackets_flag) { count += ly_print(out, ")"); } } return count; }
static void json_print_attrs(struct lyout *out, int level, const struct lyd_node *node) { struct lyd_attr *attr; for (attr = node->attr; attr; attr = attr->next) { if (attr->module != node->schema->module) { ly_print(out, "%*s\"%s:%s\":", LEVEL, INDENT, attr->module->name, attr->name); } else { ly_print(out, "%*s\"%s\":", LEVEL, INDENT, attr->name); } json_print_string(out, attr->value ? attr->value : ""); ly_print(out, "%s", attr->next ? ",\n" : "\n"); } }
int json_print_data(struct lyout *out, const struct lyd_node *root, int options) { int level = 0; /* start */ ly_print(out, "{\n"); /* content */ json_print_nodes(out, level + 1, root, options & LYP_WITHSIBLINGS); /* end */ ly_print(out, "}\n"); return EXIT_SUCCESS; }
static void json_print_container(struct lyout *out, int level, const struct lyd_node *node) { const char *schema; if (!node->parent || nscmp(node, node->parent)) { /* print "namespace" */ schema = lys_node_module(node->schema)->name; ly_print(out, "%*s\"%s:%s\": {\n", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, "%*s\"%s\": {\n", LEVEL, INDENT, node->schema->name); } level++; if (node->attr) { ly_print(out, "%*s\"@\": {\n", LEVEL, INDENT); json_print_attrs(out, level + 1, node); ly_print(out, "%*s}%s", LEVEL, INDENT, node->child ? ",\n" : ""); } json_print_nodes(out, level, node->child, 1); level--; ly_print(out, "%*s}", LEVEL, INDENT); }
static void json_print_anyxml(struct lyout *out, int level, const struct lyd_node *node) { const char *schema = NULL; if (!node->parent || nscmp(node, node->parent)) { /* print "namespace" */ schema = lys_node_module(node->schema)->name; ly_print(out, "%*s\"%s:%s\": [null]", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, "%*s\"%s\": [null]", LEVEL, INDENT, node->schema->name); } /* print attributes as sibling leaf */ if (node->attr) { if (schema) { ly_print(out, ",\n%*s\"@%s:%s\": {\n", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, ",\n%*s\"@%s\": {\n", LEVEL, INDENT, node->schema->name); } json_print_attrs(out, level + 1, node); ly_print(out, "%*s}", LEVEL, INDENT); } }
int lys_print_target(struct lyout *out, const struct lys_module *module, const char *target_schema_path, void (*clb_print_typedef)(struct lyout*, const struct lys_tpdf*, int*), void (*clb_print_identity)(struct lyout*, const struct lys_ident*, int*), void (*clb_print_feature)(struct lyout*, const struct lys_feature*, int*), void (*clb_print_type)(struct lyout*, const struct lys_type*, int*), void (*clb_print_grouping)(struct lyout*, const struct lys_node*, int*), void (*clb_print_container)(struct lyout*, const struct lys_node*, int*), void (*clb_print_choice)(struct lyout*, const struct lys_node*, int*), void (*clb_print_leaf)(struct lyout*, const struct lys_node*, int*), void (*clb_print_leaflist)(struct lyout*, const struct lys_node*, int*), void (*clb_print_list)(struct lyout*, const struct lys_node*, int*), void (*clb_print_anydata)(struct lyout*, const struct lys_node*, int*), void (*clb_print_case)(struct lyout*, const struct lys_node*, int*), void (*clb_print_notif)(struct lyout*, const struct lys_node*, int*), void (*clb_print_rpc)(struct lyout*, const struct lys_node*, int*), void (*clb_print_action)(struct lyout*, const struct lys_node*, int*), void (*clb_print_input)(struct lyout*, const struct lys_node*, int*), void (*clb_print_output)(struct lyout*, const struct lys_node*, int*)) { int rc, i, f = 1; char *spec_target = NULL; struct lys_node *target = NULL; struct lys_tpdf *tpdf = NULL; uint8_t tpdf_size = 0; if ((target_schema_path[0] == '/') || !strncmp(target_schema_path, "type/", 5)) { rc = resolve_absolute_schema_nodeid((target_schema_path[0] == '/' ? target_schema_path : target_schema_path + 4), module, LYS_ANY & ~(LYS_USES | LYS_AUGMENT | LYS_GROUPING), (const struct lys_node **)&target); if (rc || !target) { LOGERR(module->ctx, LY_EINVAL, "Target %s could not be resolved.", (target_schema_path[0] == '/' ? target_schema_path : target_schema_path + 4)); return EXIT_FAILURE; } } else if (!strncmp(target_schema_path, "grouping/", 9)) { /* cut the data part off */ if ((spec_target = strchr(target_schema_path + 9, '/'))) { /* HACK only temporary */ spec_target[0] = '\0'; ++spec_target; } rc = resolve_absolute_schema_nodeid(target_schema_path + 8, module, LYS_GROUPING, (const struct lys_node **)&target); if (rc || !target) { ly_print(out, "Grouping %s not found.\n", target_schema_path + 8); return EXIT_FAILURE; } } else if (!strncmp(target_schema_path, "typedef/", 8)) { if ((spec_target = strrchr(target_schema_path + 8, '/'))) { /* schema node typedef */ /* HACK only temporary */ spec_target[0] = '\0'; ++spec_target; rc = resolve_absolute_schema_nodeid(target_schema_path + 7, module, LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION, (const struct lys_node **)&target); if (rc || !target) { /* perhaps it's in a grouping */ rc = resolve_absolute_schema_nodeid(target_schema_path + 7, module, LYS_GROUPING, (const struct lys_node **)&target); } if (!rc && target) { switch (target->nodetype) { case LYS_CONTAINER: tpdf = ((struct lys_node_container *)target)->tpdf; tpdf_size = ((struct lys_node_container *)target)->tpdf_size; break; case LYS_LIST: tpdf = ((struct lys_node_list *)target)->tpdf; tpdf_size = ((struct lys_node_list *)target)->tpdf_size; break; case LYS_NOTIF: tpdf = ((struct lys_node_notif *)target)->tpdf; tpdf_size = ((struct lys_node_notif *)target)->tpdf_size; break; case LYS_RPC: case LYS_ACTION: tpdf = ((struct lys_node_rpc_action *)target)->tpdf; tpdf_size = ((struct lys_node_rpc_action *)target)->tpdf_size; break; case LYS_GROUPING: tpdf = ((struct lys_node_grp *)target)->tpdf; tpdf_size = ((struct lys_node_grp *)target)->tpdf_size; break; default: LOGINT(module->ctx); return EXIT_FAILURE; } } } else { /* module typedef */ spec_target = (char *)target_schema_path + 8; tpdf = module->tpdf; tpdf_size = module->tpdf_size; } for (i = 0; i < tpdf_size; ++i) { if (!strcmp(tpdf[i].name, spec_target)) { clb_print_typedef(out, &tpdf[i], &f); break; } } /* HACK return previous hack */ --spec_target; spec_target[0] = '/'; if (i == tpdf_size) { ly_print(out, "Typedef %s not found.\n", target_schema_path); return EXIT_FAILURE; } return EXIT_SUCCESS; } else if (!strncmp(target_schema_path, "identity/", 9)) { target_schema_path += 9; for (i = 0; i < (signed)module->ident_size; ++i) { if (!strcmp(module->ident[i].name, target_schema_path)) { break; } } if (i == (signed)module->ident_size) { ly_print(out, "Identity %s not found.\n", target_schema_path); return EXIT_FAILURE; } clb_print_identity(out, &module->ident[i], &f); return EXIT_SUCCESS; } else if (!strncmp(target_schema_path, "feature/", 8)) { target_schema_path += 8; for (i = 0; i < module->features_size; ++i) { if (!strcmp(module->features[i].name, target_schema_path)) { break; } } if (i == module->features_size) { ly_print(out, "Feature %s not found.\n", target_schema_path); return EXIT_FAILURE; } clb_print_feature(out, &module->features[i], &f); return EXIT_SUCCESS; } else { ly_print(out, "Target could not be resolved.\n"); return EXIT_FAILURE; } if (!strncmp(target_schema_path, "type/", 5)) { if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) { LOGERR(module->ctx, LY_EINVAL, "Target is not a leaf or a leaf-list."); return EXIT_FAILURE; } clb_print_type(out, &((struct lys_node_leaf *)target)->type, &f); return EXIT_SUCCESS; } else if (!strncmp(target_schema_path, "grouping/", 9) && !spec_target) { clb_print_grouping(out, target, &f); return EXIT_SUCCESS; } /* find the node in the grouping */ if (spec_target) { rc = resolve_descendant_schema_nodeid(spec_target, target->child, LYS_NO_RPC_NOTIF_NODE, 0, (const struct lys_node **)&target); if (rc || !target) { ly_print(out, "Grouping %s child \"%s\" not found.\n", target_schema_path + 9, spec_target); return EXIT_FAILURE; } /* HACK return previous hack */ --spec_target; spec_target[0] = '/'; } switch (target->nodetype) { case LYS_CONTAINER: clb_print_container(out, target, &f); break; case LYS_CHOICE: clb_print_choice(out, target, &f); break; case LYS_LEAF: clb_print_leaf(out, target, &f); break; case LYS_LEAFLIST: clb_print_leaflist(out, target, &f); break; case LYS_LIST: clb_print_list(out, target, &f); break; case LYS_ANYXML: case LYS_ANYDATA: clb_print_anydata(out, target, &f); break; case LYS_CASE: clb_print_case(out, target, &f); break; case LYS_NOTIF: clb_print_notif(out, target, &f); break; case LYS_RPC: clb_print_rpc(out, target, &f); break; case LYS_ACTION: clb_print_action(out, target, &f); break; case LYS_INPUT: clb_print_input(out, target, &f); break; case LYS_OUTPUT: clb_print_output(out, target, &f); break; default: ly_print(out, "Nodetype %s not supported.\n", strnodetype(target->nodetype)); break; } return EXIT_SUCCESS; }
static void json_print_leaf(struct lyout *out, int level, const struct lyd_node *node, int onlyvalue) { struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node; const char *schema = NULL; if (!onlyvalue) { if (!node->parent || nscmp(node, node->parent)) { /* print "namespace" */ schema = lys_node_module(node->schema)->name; ly_print(out, "%*s\"%s:%s\": ", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, "%*s\"%s\": ", LEVEL, INDENT, node->schema->name); } } switch (leaf->value_type & LY_DATA_TYPE_MASK) { case LY_TYPE_BINARY: case LY_TYPE_STRING: case LY_TYPE_BITS: case LY_TYPE_ENUM: case LY_TYPE_IDENT: case LY_TYPE_INST: json_print_string(out, leaf->value_str ? leaf->value_str : ""); break; case LY_TYPE_BOOL: case LY_TYPE_DEC64: case LY_TYPE_INT8: case LY_TYPE_INT16: case LY_TYPE_INT32: case LY_TYPE_INT64: case LY_TYPE_UINT8: case LY_TYPE_UINT16: case LY_TYPE_UINT32: case LY_TYPE_UINT64: ly_print(out, "%s", leaf->value_str ? leaf->value_str : "null"); break; case LY_TYPE_LEAFREF: if (leaf->value.leafref) { json_print_leaf(out, level, leaf->value.leafref, 1); } else { ly_print(out, ""); } break; case LY_TYPE_EMPTY: ly_print(out, "[null]"); break; default: /* error */ ly_print(out, "\"(!error!)\""); } /* print attributes as sibling leafs */ if (!onlyvalue && node->attr) { if (schema) { ly_print(out, ",\n%*s\"@%s:%s\": {\n", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, ",\n%*s\"@%s\": {\n", LEVEL, INDENT, node->schema->name); } json_print_attrs(out, level + 1, node); ly_print(out, "%*s}", LEVEL, INDENT); } return; }
static void json_print_nodes(struct lyout *out, int level, const struct lyd_node *root, int withsiblings) { const struct lyd_node *node, *iter; LY_TREE_FOR(root, node) { switch (node->schema->nodetype) { case LYS_RPC: case LYS_NOTIF: case LYS_CONTAINER: if (node->prev->next) { /* print the previous comma */ ly_print(out, ",\n"); } json_print_container(out, level, node); break; case LYS_LEAF: if (node->prev->next) { /* print the previous comma */ ly_print(out, ",\n"); } json_print_leaf(out, level, node, 0); break; case LYS_LEAFLIST: case LYS_LIST: /* is it already printed? */ for (iter = node->prev; iter->next; iter = iter->prev) { if (iter == node) { continue; } if (iter->schema == node->schema) { /* the list has alread some previous instance and therefore it is already printed */ break; } } if (!iter->next) { if (node->prev->next) { /* print the previous comma */ ly_print(out, ",\n"); } /* print the list/leaflist */ json_print_leaf_list(out, level, node, node->schema->nodetype == LYS_LIST ? 1 : 0); } break; case LYS_ANYXML: if (node->prev->next) { /* print the previous comma */ ly_print(out, ",\n"); } json_print_anyxml(out, level, node); break; default: LOGINT; break; } if (!withsiblings) { break; } } ly_print(out, "\n"); }
static void json_print_leaf_list(struct lyout *out, int level, const struct lyd_node *node, int is_list) { const char *schema = NULL; const struct lyd_node *list = node; int flag_empty = 0, flag_attrs = 0; if (!list->child) { /* empty, e.g. in case of filter */ flag_empty = 1; } if (!node->parent || nscmp(node, node->parent)) { /* print "namespace" */ schema = lys_node_module(node->schema)->name; ly_print(out, "%*s\"%s:%s\":", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, "%*s\"%s\":", LEVEL, INDENT, node->schema->name); } if (flag_empty) { ly_print(out, " null"); return; } ly_print(out, " [\n"); if (!is_list) { ++level; } while (list) { if (is_list) { /* list print */ ++level; ly_print(out, "%*s{\n", LEVEL, INDENT); ++level; if (list->attr) { ly_print(out, "%*s\"@\": {\n", LEVEL, INDENT); json_print_attrs(out, level + 1, node); ly_print(out, "%*s}%s", LEVEL, INDENT, list->child ? ",\n" : ""); } json_print_nodes(out, level, list->child, 1); --level; ly_print(out, "%*s}", LEVEL, INDENT); --level; } else { /* leaf-list print */ ly_print(out, "%*s", LEVEL, INDENT); json_print_leaf(out, level, list, 1); if (list->attr) { flag_attrs = 1; } } for (list = list->next; list && list->schema != node->schema; list = list->next); if (list) { ly_print(out, ",\n"); } } if (!is_list) { --level; } ly_print(out, "\n%*s]", LEVEL, INDENT); /* attributes */ if (!is_list && flag_attrs) { if (schema) { ly_print(out, ",\n%*s\"@%s:%s\": [\n", LEVEL, INDENT, schema, node->schema->name); } else { ly_print(out, ",\n%*s\"@%s\": [\n", LEVEL, INDENT, node->schema->name); } level++; for (list = node; list; ) { if (list->attr) { ly_print(out, "%*s{ ", LEVEL, INDENT); json_print_attrs(out, 0, list); ly_print(out, "%*s}", LEVEL, INDENT); } else { ly_print(out, "%*snull", LEVEL, INDENT); } for (list = list->next; list && list->schema != node->schema; list = list->next); if (list) { ly_print(out, ",\n"); } } level--; ly_print(out, "\n%*s]", LEVEL, INDENT); } }