blob: eb53e894acb21c7a2d25f9a4bc89e147119f7983 [file] [log] [blame]
Radek Krejci94ca54b2015-07-08 15:48:47 +02001/**
2 * @file printer/json.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief JSON printer for libyang data structure
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25#include <assert.h>
26
27#include "../common.h"
28#include "../tree.h"
29
30#define INDENT ""
31#define LEVEL (level*2)
32
33void json_print_node(FILE *f, int level, struct lyd_node *node);
34
35/* 0 - same, 1 - different */
36static int
37nscmp(struct lyd_node *node1, struct lyd_node *node2)
38{
39 struct ly_module *m1, *m2;
40
41 /* we have to cover submodules belonging to the same module */
42 if (node1->schema->module->type) {
43 m1 = ((struct ly_submodule *)node1->schema->module)->belongsto;
44 } else {
45 m1 = node1->schema->module;
46 }
47 if (node2->schema->module->type) {
48 m2 = ((struct ly_submodule *)node2->schema->module)->belongsto;
49 } else {
50 m2 = node2->schema->module;
51 }
52 if (m1 == m2) {
53 /* belongs to the same module */
54 return 0;
55 } else {
56 /* different modules */
57 return 1;
58 }
59}
60
61static void
62json_print_container(FILE *f, int level, struct lyd_node *node)
63{
64 const char *schema;
65 struct lyd_node *child;
66
67 if (!node->parent || nscmp(node, node->parent)) {
68 /* print "namespace" */
69 if (node->schema->module->type) {
70 /* submodule, get module */
71 schema = ((struct ly_submodule *)node->schema->module)->belongsto->name;
72 } else {
73 schema = node->schema->module->name;
74 }
75 fprintf(f, "%*s\"%s:%s\": {\n", LEVEL, INDENT, schema, node->schema->name);
76 } else {
77 fprintf(f, "%*s\"%s\": {\n", LEVEL, INDENT, node->schema->name);
78 }
79 LY_TREE_FOR(node->child, child) {
80 json_print_node(f, level + 1, child);
81 }
82 fprintf(f, "%*s}%s\n", LEVEL, INDENT, node->next ? "," : "");
83}
84
85static void
86json_print_list_internal(FILE *f, int level, struct lyd_node_list *list)
87{
88 struct lyd_node *child;
89
90 fprintf(f, "%*s{\n", LEVEL, INDENT);
91
Radek Krejci94ca54b2015-07-08 15:48:47 +020092 LY_TREE_FOR(list->child, child) {
93 json_print_node(f, level + 1, child);
94 }
95
96 fprintf(f, "%*s}%s\n", LEVEL, INDENT, list->lnext ? "," : "");
97}
98
99static void
100json_print_list(FILE *f, int level, struct lyd_node *node)
101{
102 const char *schema;
103 struct lyd_node_list *list = (struct lyd_node_list *)node;
104 struct lyd_node *iter;
105 char *delim = "";
106
107 if (list->lprev) {
108 /* this list is already printed */
109 return;
110 }
111
112 if (!node->parent || nscmp(node, node->parent)) {
113 /* print "namespace" */
114 if (node->schema->module->type) {
115 /* submodule, get module */
116 schema = ((struct ly_submodule *)node->schema->module)->belongsto->name;
117 } else {
118 schema = node->schema->module->name;
119 }
120 fprintf(f, "%*s\"%s:%s\": [\n", LEVEL, INDENT, schema, node->schema->name);
121 } else {
122 fprintf(f, "%*s\"%s\": [\n", LEVEL, INDENT, node->schema->name);
123 }
124
125 for(; list; list = list->lnext) {
126 json_print_list_internal(f, level + 1, list);
127 }
128 for (iter = node->next; iter; iter = iter->next) {
129 if (iter->schema != node->schema) {
130 delim = ",";
131 break;
132 }
133 }
134 fprintf(f, "%*s]%s\n", LEVEL, INDENT, delim);
135}
136
137static void
138json_print_leaf(FILE *f, int level, struct lyd_node *node)
139{
Radek Krejcie4748472015-07-08 18:00:22 +0200140 struct lyd_node_leaf *leaf = (struct lyd_node_leaf *)node;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200141 struct ly_mnode_leaf *sleaf = (struct ly_mnode_leaf *)node->schema;
142 struct ly_type *type;
Radek Krejci94ca54b2015-07-08 15:48:47 +0200143 const char *schema;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200144 int i;
Radek Krejci94ca54b2015-07-08 15:48:47 +0200145
146 if (!node->parent || nscmp(node, node->parent)) {
147 /* print "namespace" */
148 if (node->schema->module->type) {
149 /* submodule, get module */
150 schema = ((struct ly_submodule *)node->schema->module)->belongsto->name;
151 } else {
152 schema = node->schema->module->name;
153 }
Radek Krejcie4748472015-07-08 18:00:22 +0200154 fprintf(f, "%*s\"%s:%s\": ", LEVEL, INDENT, schema, node->schema->name);
Radek Krejci94ca54b2015-07-08 15:48:47 +0200155 } else {
Radek Krejcie4748472015-07-08 18:00:22 +0200156 fprintf(f, "%*s\"%s\": ", LEVEL, INDENT, node->schema->name);
Radek Krejci94ca54b2015-07-08 15:48:47 +0200157 }
Radek Krejcie4748472015-07-08 18:00:22 +0200158
159 switch (((struct ly_mnode_leaf *)leaf->schema)->type.base) {
160 case LY_TYPE_BINARY:
161 case LY_TYPE_STRING:
162 fprintf(f, "\"%s\"%s\n", leaf->value.string, node->next ? "," : "");
163 break;
Radek Krejci3e3affe2015-07-09 15:38:40 +0200164 case LY_TYPE_BITS:
165 fprintf(f, "\"");
166
167 /* locate bits structure with the bits definitions to get the array size */
168 for (type = &sleaf->type; type->der->type.der; type = &type->der->type);
169
170 /* print set bits */
171 for (i = 0; i < type->info.bits.count; i++) {
172 if (leaf->value.bit[i]) {
173 fprintf(f, "%s%s", i ? " " : "", leaf->value.bit[i]->name);
174 }
175 }
176 fprintf(f, "\"%s\n", node->next ? "," : "");
177 break;
178
Radek Krejcie4748472015-07-08 18:00:22 +0200179 default:
180 /* TODO */
181 fprintf(f, "%s%s\n", "\"TBD\"", node->next ? "," : "");
182 }
183
Radek Krejci94ca54b2015-07-08 15:48:47 +0200184}
185
186void
187json_print_node(FILE *f, int level, struct lyd_node *node)
188{
189 switch (node->schema->nodetype) {
190 case LY_NODE_LIST:
191 json_print_list(f, level, node);
192 break;
193 case LY_NODE_CONTAINER:
194 json_print_container(f, level, node);
195 break;
196 case LY_NODE_LEAF:
197 json_print_leaf(f, level, node);
198 break;
199 default:
200 /* TODO: remove when all node types are covered */
201 break;
202 }
203
204}
205
206int
207json_print_data(FILE *f, struct lyd_node *root)
208{
209 int level = 0;
210 struct lyd_node *node;
211
212 /* start */
213 fprintf(f, "{\n");
214
215 /* content */
216 LY_TREE_FOR(root, node) {
217 json_print_node(f, level + 1, node);
218 }
219
220 /* end */
221 fprintf(f, "}\n");
222
223 return EXIT_SUCCESS;
224}