blob: 10e5a043386974cbb71c28245830f8e5f5d3c61a [file] [log] [blame]
Radek Krejci0e67ac42018-07-25 15:46:37 +02001/**
2 * @file printer/info.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema JSON printer for libyang data model structure
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _GNU_SOURCE
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include <assert.h>
20
21#include "common.h"
22#include "printer.h"
23#include "tree_schema.h"
24#include "resolve.h"
25
26#define INDENT_LEN 2
27
28static const char *
29jsons_nodetype_str(LYS_NODE value) {
30 switch (value) {
31 case LYS_CONTAINER: return "container";
32 case LYS_CHOICE: return "choice";
33 case LYS_LEAF: return "leaf";
34 case LYS_LEAFLIST: return "leaf-list";
35 case LYS_LIST: return "list";
36 case LYS_ANYXML: return "anyxml";
37 case LYS_CASE: return "case";
38 case LYS_NOTIF: return "notification";
39 case LYS_RPC: return "rpc";
40 case LYS_INPUT: return "input";
41 case LYS_OUTPUT: return "output";
42 case LYS_ACTION: return "action";
43 case LYS_ANYDATA: return "anydata";
44 default: return NULL;
45 }
46}
47
48/* shared with printer_json.c */
49int json_print_string(struct lyout *out, const char *text);
50
Radek Krejci40cb8d72018-08-03 12:19:41 +020051static void jsons_print_data(struct lyout *out, const struct lys_module *mod, struct lys_node *data, int *first);
52static void jsons_print_notifs(struct lyout *out, struct lys_node *data, int *first);
Radek Krejci8aa90c92018-08-13 15:00:54 +020053static void jsons_print_actions(struct lyout *out, struct lys_node *data, int *first);
Radek Krejci40cb8d72018-08-03 12:19:41 +020054
Radek Krejci0e67ac42018-07-25 15:46:37 +020055static void
56jsons_print_text(struct lyout *out, const char *label, const char *arg, const char *text, int closeit, int *first)
57{
58 if (!text) {
59 return;
60 }
61 ly_print(out, "%s\"%s\":{\"%s\":", (first && (*first)) ? "" : ",", label, arg);
62 json_print_string(out, text);
63 if (closeit) {
64 ly_print(out, "}");
65 }
66 if (first) {
67 (*first) = 0;
68 }
69}
70
71static void
72jsons_print_object(struct lyout *out, const char *label, const char *arg, const char *val, int closeit, int *first)
73{
74 if (!val) {
75 return;
76 }
77
78 ly_print(out, "%s\"%s\":{\"%s\":\"%s\"%s", (first && (*first)) ? "" : ",", label, arg, val, closeit ? "}" : "");
79
80 if (first) {
81 (*first) = 0;
82 }
83}
84
85static void
86jsons_print_status(struct lyout *out, uint16_t flags, int *first)
87{
88 const char *str;
89
90 if (flags & LYS_STATUS_MASK) {
91 if (flags & LYS_STATUS_OBSLT) {
92 str = "obsolete";
93 } else if (flags & LYS_STATUS_DEPRC) {
94 str = "deprecated";
95 } else {
96 str = "current";
97 }
98 jsons_print_object(out, "status", "value", str, 1, first);
99 }
100}
101
102static void
103jsons_print_config(struct lyout *out, uint16_t flags, int *first)
104{
105 const char *str = NULL;
106
107 if (flags & LYS_CONFIG_MASK) {
108 if (flags & LYS_CONFIG_R) {
109 str = "false";
110 } else if (flags & LYS_CONFIG_W) {
111 str = "true";
112 }
113 jsons_print_object(out, "config", "value", str, 1, first);
114 }
115}
116
117static void
118jsons_print_mand(struct lyout *out, uint16_t flags, int *first)
119{
Radek Krejcif3678702018-08-31 09:25:57 +0200120 const char *str = NULL;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200121
122 if (flags & LYS_MAND_MASK) {
123 if (flags & LYS_MAND_TRUE) {
124 str = "true";
125 } else if (flags & LYS_MAND_FALSE) {
126 str = "false";
127 }
128 jsons_print_object(out, "mandatory", "value", str, 1, first);
129 }
130}
131
132static void
133jsons_print_ordering(struct lyout *out, uint16_t flags, int *first)
134{
135 if (flags & LYS_USERORDERED) {
136 jsons_print_object(out, "ordered-by", "value", "user", 1, first);
137 } else {
138 jsons_print_object(out, "ordered-by", "value", "system", 1, first);
139 }
140}
141
142static void
143jsons_print_iffeatures(struct lyout *out, const struct lys_module *module,
144 struct lys_iffeature *iff, uint8_t iff_size, int *first)
145{
146 int i;
147
148 if (!iff_size) {
149 return;
150 }
151
152 ly_print(out, "%s\"if-features\":[", (first && (*first)) ? "" : ",");
153 for (i = 0; i < iff_size; ++i) {
154 ly_print(out, "%s\"", i ? "," : "");
Radek Krejci8aa90c92018-08-13 15:00:54 +0200155 ly_print_iffeature(out, module, &iff[i], 3);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200156 ly_print(out, "\"");
157 }
158 ly_print(out, "]");
Radek Krejci8aa90c92018-08-13 15:00:54 +0200159 if (first) {
160 (*first) = 0;
161 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200162}
163
164static void
165jsons_print_when(struct lyout *out, const struct lys_when *when, int *first)
166{
167 if (!when) {
168 return;
169 }
Radek Krejci40cb8d72018-08-03 12:19:41 +0200170 jsons_print_text(out, "when", "condition", when->cond, 0, first);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200171 jsons_print_text(out, "description", "text", when->dsc, 1, NULL);
172 jsons_print_text(out, "reference", "text", when->ref, 1, NULL);
173 ly_print(out, "}");
174}
175
176static void
177jsons_print_typerestr(struct lyout *out, const struct lys_restr *restr, const char *label, int *first)
178{
179 int pattern = 0;
180
181 if (!restr) {
182 return;
183 }
184 if (restr->expr[0] == 0x06 || restr->expr[0] == 0x15) {
185 pattern = 1;
186 }
187
188 if (label) {
Radek Krejci362fbe72018-08-03 16:05:21 +0200189 jsons_print_text(out, label, "value", pattern ? &restr->expr[1] : restr->expr, 0, first);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200190 } else {
Radek Krejci362fbe72018-08-03 16:05:21 +0200191 ly_print(out, "%s{\"%s\":", (first && (*first)) ? "" : ",", "value");
192 json_print_string(out, pattern ? &restr->expr[1] : restr->expr);
193 }
194 if (pattern && restr->expr[0] == 0x15) {
195 jsons_print_object(out, "modifier", "value", "invert-match", 1, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200196 }
197 jsons_print_text(out, "description", "text", restr->dsc, 1, NULL);
198 jsons_print_text(out, "reference", "text", restr->ref, 1, NULL);
199 jsons_print_object(out, "error-app-tag", "value", restr->eapptag, 1, NULL);
200 jsons_print_text(out, "error-message", "value", restr->emsg, 1, NULL);
201 ly_print(out, "}");
202 if (first) {
203 (*first) = 0;
204 }
205}
206
207static void
208jsons_print_musts(struct lyout *out, const struct lys_restr *must, uint8_t must_size, int *first)
209{
210 int i, f;
211
212 if (!must_size) {
213 return;
214 }
215
216 ly_print(out, "%s\"musts\":[", (first && (*first)) ? "" : ",");
217 f = 1;
218 for (i = 0; i < must_size; ++i) {
219 jsons_print_typerestr(out, &must[i], NULL, &f);
220 }
221 ly_print(out, "]");
222}
223
224static void
Radek Krejci362fbe72018-08-03 16:05:21 +0200225jsons_print_type_(struct lyout *out, const struct lys_type *type, int with_label, int *first)
Radek Krejci0e67ac42018-07-25 15:46:37 +0200226{
227 unsigned int i;
228 int f;
Radek Krejci362fbe72018-08-03 16:05:21 +0200229 struct lys_module *mod;
Radek Krejciabdce472018-08-23 17:02:56 +0200230 struct lys_node *node;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200231
232 if (!type) {
233 return;
234 }
235
Radek Krejci362fbe72018-08-03 16:05:21 +0200236 if (with_label) {
237 ly_print(out, "%s\"type\":{", (first && (*first)) ? "" : ",");
238 } else {
239 ly_print(out, "%s{", (first && (*first)) ? "" : ",");
240 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200241
242 switch (type->base) {
243 case LY_TYPE_BINARY:
244 ly_print(out, "\"basetype\":\"binary\"");
245 jsons_print_typerestr(out, type->info.binary.length, "length", NULL);
246 break;
247 case LY_TYPE_BITS:
248 ly_print(out, "\"basetype\":\"bits\"");
249 ly_print(out, ",\"bits\":[");
250 for (i = 0; i < type->info.bits.count; ++i) {
251 ly_print(out, "%s{\"position\":\"%u\",\"name\":\"%s\"", i ? "," : "",
252 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
253 jsons_print_text(out, "description", "text", type->info.bits.bit[i].dsc, 1, NULL);
254 jsons_print_text(out, "reference", "text", type->info.bits.bit[i].ref, 1, NULL);
255 jsons_print_status(out, type->info.bits.bit[i].flags, NULL);
256 jsons_print_iffeatures(out, type->parent->module,
257 type->info.bits.bit[i].iffeature, type->info.bits.bit[i].iffeature_size, NULL);
258 ly_print(out, "}");
259 }
260 ly_print(out, "]");
261 break;
262 case LY_TYPE_BOOL:
263 ly_print(out, "\"basetype\":\"boolean\"");
264 break;
265 case LY_TYPE_DEC64:
266 ly_print(out, "\"basetype\":\"decimal64\"");
267 jsons_print_typerestr(out, type->info.dec64.range, "range", NULL);
268 ly_print(out, ",\"fraction-digits\":{\"value\":\"%u\"}", type->info.dec64.dig);
269 break;
270 case LY_TYPE_EMPTY:
271 ly_print(out, "\"basetype\":\"empty\"");
272 break;
273 case LY_TYPE_ENUM:
274 ly_print(out, "\"basetype\":\"enumeration\"");
275 ly_print(out, ",\"enums\":[");
Radek Krejci8aa90c92018-08-13 15:00:54 +0200276 for (i = 0; i < type->info.enums.count; ++i) {
Radek Krejci0e67ac42018-07-25 15:46:37 +0200277 ly_print(out, "%s{\"value\":\"%d\",\"name\":\"%s\"", i ? "," : "",
278 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
279 jsons_print_text(out, "description", "text", type->info.enums.enm[i].dsc, 1, NULL);
280 jsons_print_text(out, "reference", "text", type->info.enums.enm[i].ref, 1, NULL);
281 jsons_print_status(out, type->info.enums.enm[i].flags, NULL);
282 jsons_print_iffeatures(out, type->parent->module,
283 type->info.enums.enm[i].iffeature, type->info.enums.enm[i].iffeature_size, NULL);
284 ly_print(out, "}");
285 }
286 ly_print(out, "]");
287 break;
288 case LY_TYPE_IDENT:
289 ly_print(out, "\"basetype\":\"identityref\"");
290 if (type->info.ident.count) {
291 ly_print(out, ",\"bases\":[");
292 for (i = 0; i < type->info.ident.count; ++i) {
Radek Krejci362fbe72018-08-03 16:05:21 +0200293 mod = type->info.ident.ref[i]->module;
294 ly_print(out, "%s\"%s%s%s:%s\"", i ? "," : "",
295 mod->name, mod->rev_size ? "@" : "", mod->rev_size ? mod->rev[0].date : "",
296 type->info.ident.ref[i]->name);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200297 }
Radek Krejci362fbe72018-08-03 16:05:21 +0200298 ly_print(out, "]");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200299 }
300 break;
301 case LY_TYPE_INST:
302 ly_print(out, "\"basetype\":\"instance-identifier\"");
Radek Krejci362fbe72018-08-03 16:05:21 +0200303 if (type->info.inst.req) {
304 jsons_print_object(out, "require-instance", "value", type->info.inst.req == -1 ? "false" : "true", 1, NULL);
305 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200306 break;
307 case LY_TYPE_INT8:
308 ly_print(out, "\"basetype\":\"int8\"");
309 goto int_range;
310 case LY_TYPE_INT16:
311 ly_print(out, "\"basetype\":\"int16\"");
312 goto int_range;
313 case LY_TYPE_INT32:
314 ly_print(out, "\"basetype\":\"int32\"");
315 goto int_range;
316 case LY_TYPE_INT64:
317 ly_print(out, "\"basetype\":\"int64\"");
318 goto int_range;
319 case LY_TYPE_UINT8:
320 ly_print(out, "\"basetype\":\"uint8\"");
321 goto int_range;
322 case LY_TYPE_UINT16:
323 ly_print(out, "\"basetype\":\"uint16\"");
324 goto int_range;
325 case LY_TYPE_UINT32:
326 ly_print(out, "\"basetype\":\"uint32\"");
327 goto int_range;
328 case LY_TYPE_UINT64:
329 ly_print(out, "\"basetype\":\"uint64\"");
330
331int_range:
332 jsons_print_typerestr(out, type->info.num.range, "range", NULL);
333 break;
334 case LY_TYPE_LEAFREF:
335 ly_print(out, "\"basetype\":\"leafref\"");
Radek Krejciabdce472018-08-23 17:02:56 +0200336 jsons_print_text(out, "path", "value", type->info.lref.path, 0, NULL);
337 for (node = (struct lys_node*)type->info.lref.target; node && node->parent; node = lys_parent(node));
338 if (node) {
339 mod = node->module;
340 ly_print(out, ",\"target-schema\":\"%s%s%s\"", mod->name, mod->rev_size ? "@" : "", mod->rev_size ? mod->rev[0].date : "");
341 }
342 ly_print(out, "}");
Radek Krejci362fbe72018-08-03 16:05:21 +0200343 if (type->info.lref.req) {
344 jsons_print_object(out, "require-instance", "value", type->info.lref.req == -1 ? "false" : "true", 1, NULL);
345 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200346 break;
347 case LY_TYPE_STRING:
348 ly_print(out, "\"basetype\":\"string\"");
349 jsons_print_typerestr(out, type->info.str.length, "length", NULL);
350 if (type->info.str.pat_count) {
351 ly_print(out, ",\"patterns\":[");
352 f = 1;
353 for (i = 0; i < type->info.str.pat_count; ++i) {
354 jsons_print_typerestr(out, &type->info.str.patterns[i], NULL, &f);
355 }
356 ly_print(out, "]");
357 }
358
359 break;
360 case LY_TYPE_UNION:
361 ly_print(out, "\"basetype\":\"union\"");
Radek Krejci362fbe72018-08-03 16:05:21 +0200362 ly_print(out, ",\"types\":[");
363 f = 1;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200364 for (i = 0; i < type->info.uni.count; ++i) {
Radek Krejci362fbe72018-08-03 16:05:21 +0200365 jsons_print_type_(out, &type->info.uni.types[i], 0, &f);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200366 }
Radek Krejci362fbe72018-08-03 16:05:21 +0200367 ly_print(out, "]");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200368 break;
369 default:
370 /* unused outside libyang, we never should be here */
371 LOGINT(type->parent->module->ctx);
372 break;
373 }
374
375 if (type->der) {
376 ly_print(out, ",\"derived-from\":");
Radek Krejci362fbe72018-08-03 16:05:21 +0200377 if (type->der->module) {
378 mod = type->der->module;
379 ly_print(out, "\"%s%s%s:%s\"",
380 mod->name, mod->rev_size ? "@" : "", mod->rev_size ? mod->rev[0].date : "",
381 type->der->name);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200382 } else {
383 ly_print(out, "\"%s\"", type->der->name);
384 }
385 }
386 ly_print(out, "}");
Radek Krejci362fbe72018-08-03 16:05:21 +0200387 if (first) {
388 (*first) = 0;
389 }
390}
391
392static void
393jsons_print_type(struct lyout *out, const struct lys_type *type, int *first)
394{
395 return jsons_print_type_(out, type, 1, first);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200396}
397
398static void
399jsons_print_typedef(struct lyout *out, const struct lys_tpdf *tpdf, int *first)
400{
401 int f;
402
403 ly_print(out, "%s\"%s\":{", (first && (*first)) ? "" : ",", tpdf->name);
404 f = 1;
405 jsons_print_type(out, &tpdf->type, &f);
406 jsons_print_text(out, "description", "text", tpdf->dsc, 1, NULL);
407 jsons_print_text(out, "reference", "text", tpdf->ref, 1, NULL);
408 jsons_print_status(out, tpdf->flags, NULL);
409 jsons_print_object(out, "units", "name", tpdf->units, 1, NULL);
410 jsons_print_object(out, "default", "value", tpdf->dflt, 1, NULL);
411 ly_print(out, "}");
412
413 if (first) {
414 (*first) = 0;
415 }
416}
417
418static void
419jsons_print_typedefs(struct lyout *out, const struct lys_tpdf *tpdf, uint8_t tpdf_size, int *first)
420{
421 int i;
422
423 if (!tpdf_size) {
424 return;
425 }
426
427 ly_print(out, "%s\"typedefs\":[", (first && (*first)) ? "" : ",");
428 for (i = 0; i < tpdf_size; ++i) {
429 ly_print(out, "%s\"%s\"", i ? "," : "", tpdf[i].name);
430 }
431 ly_print(out, "]");
432 if (first) {
433 (*first) = 0;
434 }
435}
436
437static void
438jsons_print_min(struct lyout *out, uint32_t min, int *first)
439{
440 ly_print(out, "%s\"min-elements\":{\"value\":%u}", (first && (*first)) ? "" : ",", min);
441}
442
443static void
444jsons_print_max(struct lyout *out, uint32_t max, int *first)
445{
446 ly_print(out, "%s\"max-elements\":{\"value\":%u}", (first && (*first)) ? "" : ",", max);
447}
448
449static void
450jsons_print_uniques(struct lyout *out, const struct lys_unique *unique, uint8_t unique_size, int *first)
451{
452 int i, j;
453
454 if (!unique_size) {
455 return;
456 }
457
458 ly_print(out, "%s\"uniques\":[", (first && (*first)) ? "" : ",");
459 for (i = 0; i < unique_size; ++i) {
460 ly_print(out, "%s[", i ? "," : "");
461 for (j = 0; j < unique[i].expr_size; ++j) {
462 ly_print(out, "%s\"%s\"", j ? "," : "", unique[i].expr[j]);
463 }
464 ly_print(out, "]");
465 }
466 ly_print(out, "]");
467 if (first) {
468 (*first) = 0;
469 }
470}
471
472static void
473jsons_print_defaults(struct lyout *out, const char **dflts, uint8_t dflts_size, int *first)
474{
475 int i;
476
477 if (!dflts_size) {
478 return;
479 }
480
481 ly_print(out, "%s\"defaults\":[", (first && (*first)) ? "" : ",");
482 for (i = 0; i < dflts_size; ++i) {
483 ly_print(out, "%s\"%s\"", i ? "," : "", dflts[i]);
484 }
485 ly_print(out, "]");
486 if (first) {
487 (*first) = 0;
488 }
489}
490
491static void
492jsons_print_revisions(struct lyout *out, const struct lys_revision *rev, uint8_t rev_size, int *first)
493{
494 int i, f;
495
496 if (!rev_size) {
497 return;
498 }
499
500 ly_print(out, "%s\"revision\":{", (first && (*first)) ? "" : ",");
501 for (i = 0; i < rev_size; ++i) {
502 ly_print(out, "%s\"%s\":{", i ? "," : "", rev[i].date);
503 f = 1;
504 jsons_print_text(out, "description", "text", rev[i].dsc, 1, &f);
505 jsons_print_text(out, "reference", "text", rev[i].ref, 1, &f);
506 ly_print(out, "}");
507 }
508 ly_print(out, "}");
509 if (first) {
510 (*first) = 0;
511 }
512}
513
514static void
515jsons_print_imports_(struct lyout *out, const struct lys_submodule *submodule,
516 const struct lys_import *imp, uint8_t imp_size, char **label)
517{
518 int i, j = 1, f;
Radek Krejcib5f7ed12018-08-02 08:18:48 +0200519 char *str;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200520
521 if (imp_size && (*label)) {
522 ly_print(out, *label);
523 free(*label);
524 (*label) = NULL;
525 j = 0;
526 }
527 for (i = 0; i < imp_size; ++i) {
528 ly_print(out, "%s\"%s%s%s\":{", i + j ? "," : "", imp[i].module->name,
529 imp[i].rev[0] ? "@" : "", imp[i].rev);
530 f = 1;
531 jsons_print_object(out, "prefix", "value", imp[i].prefix, 1, &f);
532 jsons_print_text(out, "description", "text", imp[i].dsc, 1, &f);
533 jsons_print_text(out, "reference", "text", imp[i].ref, 1, &f);
534 if (submodule) {
535 ly_print(out, ",\"from-submodule\":\"%s%s%s\"", submodule->name,
536 submodule->rev_size ? "@" : "", submodule->rev_size ? submodule->rev[0].date : "");
537 }
Michal Vasko501a84b2018-08-17 10:31:04 +0200538 if (asprintf(&str, "%s%s%s", imp[i].module->name, imp[i].module->rev_size ? "@" : "", imp[i].module->rev_size ? imp[i].module->rev[0].date : "") == -1) {
539 LOGMEM(NULL);
540 return;
541 }
Radek Krejcib5f7ed12018-08-02 08:18:48 +0200542 jsons_print_text(out, "resolves-to", "module", str, 1, &f);
543 free(str);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200544 ly_print(out, "}");
545 }
546}
547
548static void
549jsons_print_imports(struct lyout *out, const struct lys_module *mod, int *first)
550{
551 char *str;
552
553 if (!mod->imp_size && !mod->inc_size) {
554 return;
555 }
556
Michal Vasko501a84b2018-08-17 10:31:04 +0200557 if (asprintf(&str, "%s\"import\":{", (first && (*first)) ? "" : ",") == -1) {
558 LOGMEM(mod->ctx);
559 return;
560 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200561 jsons_print_imports_(out, NULL, mod->imp, mod->imp_size, &str);
562 /* FIXME key duplication in case multiple submodules imports the same module,
563 * but the question is if it is needed to print imports even from submodules -
564 * similar code should be then added even for typedefs or identities
565 for (i = 0; i < mod->inc_size; ++i) {
566 jsons_print_imports_(out, mod->inc[i].submodule, mod->inc[i].submodule->imp, mod->inc[i].submodule->imp_size, &str);
567 }
568 */
569 if (str) {
570 free(str);
571 } else {
572 ly_print(out, "}");
573 }
574 if (first) {
575 (*first) = 0;
576 }
577}
578
579static void
580jsons_print_includes(struct lyout *out, const struct lys_include *inc, uint8_t inc_size, int *first)
581{
582 int i, f;
583
584 if (!inc_size) {
585 return;
586 }
587
588 ly_print(out, "%s\"include\":{", (first && (*first)) ? "" : ",");
589 for (i = 0; i < inc_size; ++i) {
590 ly_print(out, "%s\"%s%s%s\":{", i ? "," : "", inc[i].submodule->name,
591 inc[i].rev[0] ? "@" : "", inc[i].rev);
592 f = 1;
593 jsons_print_text(out, "description", "text", inc[i].dsc, 1, &f);
594 jsons_print_text(out, "reference", "text", inc[i].ref, 1, &f);
595 ly_print(out, "}");
596 }
597 ly_print(out, "}");
598 if (first) {
599 (*first) = 0;
600 }
601}
602
603static void
604jsons_print_augment(struct lyout *out, const struct lys_node_augment *aug, uint8_t aug_size, int *first)
605{
606 int i, f;
607
608 if (!aug_size) {
609 return;
610 }
611
612 ly_print(out, "%s\"augment\":{", (first && (*first)) ? "" : ",");
613 for (i = 0; i < aug_size; ++i) {
614 ly_print(out, "%s\"%s\":{", i ? "," : "", aug[i].target_name);
615 f = 1;
616 jsons_print_text(out, "description", "text", aug[i].dsc, 1, &f);
617 jsons_print_text(out, "reference", "text", aug[i].ref, 1, &f);
618 jsons_print_status(out, aug[i].flags, &f);
619 jsons_print_iffeatures(out, aug[i].module, aug[i].iffeature, aug[i].iffeature_size, &f);
620 jsons_print_when(out, aug[i].when, &f);
Radek Krejci40cb8d72018-08-03 12:19:41 +0200621 jsons_print_data(out, aug->module, aug->child, &f);
Radek Krejci8aa90c92018-08-13 15:00:54 +0200622 jsons_print_actions(out, aug->child, &f);
Radek Krejci40cb8d72018-08-03 12:19:41 +0200623 jsons_print_notifs(out, aug->child, &f);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200624 ly_print(out, "}");
625 }
626 ly_print(out, "}");
627 if (first) {
628 (*first) = 0;
629 }
630
631 if (first) {
632 ly_print(out, "\n");
633 }
634}
635
636static void
637jsons_print_deviation(struct lyout *out, const struct lys_deviation *dev, uint8_t dev_size, int *first)
638{
639 int i, j, f, f2;
640
641 if (!dev_size) {
642 return;
643 }
644
645 ly_print(out, "%s\"deviations\":{", (first && (*first)) ? "" : ",");
646 for (i = 0; i < dev_size; ++i) {
647 ly_print(out, "%s\"%s\":{", i ? "," : "", dev[i].target_name);
648 f = 1;
649 jsons_print_text(out, "description", "text", dev[i].dsc, 1, &f);
650 jsons_print_text(out, "reference", "text", dev[i].ref, 1, &f);
651 if (dev[i].deviate_size) {
Radek Krejcib3c271a2018-08-02 08:15:54 +0200652 ly_print(out, "%s\"deviates\":[", f ? "" : ",");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200653 f = 0;
654 f2 = 1;
655 for (j = 0; j < dev[i].deviate_size; ++j) {
656 ly_print(out, "%s{", j ? "" : ",");
657 jsons_print_config(out, dev[i].deviate[j].flags, &f2);
658 jsons_print_defaults(out, dev[i].deviate[j].dflt, dev[i].deviate[j].dflt_size, &f2);
659 jsons_print_mand(out, dev[i].deviate[j].flags, &f2);
660 if (dev[i].deviate[j].min_set) {
661 ly_print(out, "%s\"min-elements\":{\"value\":%u}", f2 ? "" : ",", dev[i].deviate[j].min);
662 f2 = 0;
663 }
664 if (dev[i].deviate[j].max_set) {
665 ly_print(out, "%s\"max-elements\":{\"value\":%u}", f2 ? "" : ",", dev[i].deviate[j].max);
666 f2 = 0;
667 }
668 jsons_print_musts(out, dev[i].deviate[j].must, dev[i].deviate[j].must_size, &f2);
669 jsons_print_type(out, dev[i].deviate[j].type, &f2);
670 jsons_print_uniques(out, dev[i].deviate[j].unique, dev[i].deviate[j].unique_size, &f2);
671 jsons_print_text(out, "units", "name", dev[i].deviate[j].units, 1, &f2);
672 ly_print(out, "}");
673 }
674 ly_print(out, "]");
675 }
676 ly_print(out, "}");
677 }
678 ly_print(out, "}");
679 if (first) {
680 (*first) = 0;
681 }
682}
683
684static void
685jsons_print_identity(struct lyout *out, const struct lys_ident *ident, int *first)
686{
687 int f = 1, j;
Radek Krejci40cb8d72018-08-03 12:19:41 +0200688 struct lys_module *mod;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200689
690 ly_print(out, "%s\"%s\":{", (first && (*first)) ? "" : ",", ident->name);
691 if (ident->base_size) {
Radek Krejcib3c271a2018-08-02 08:15:54 +0200692 ly_print(out, "\"bases\":[");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200693 f = 0;
694 for (j = 0; j < ident->base_size; ++j) {
Radek Krejci40cb8d72018-08-03 12:19:41 +0200695 mod = ident->base[j]->module;
696 ly_print(out, "%s\"%s%s%s:%s\"", j ? "," : "",
697 mod->name, mod->rev_size ? "@" : "", mod->rev_size ? mod->rev[0].date : "",
698 ident->base[j]->name);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200699 }
700 ly_print(out, "]");
701 }
702 jsons_print_text(out, "description", "text", ident->dsc, 1, &f);
703 jsons_print_text(out, "reference", "text", ident->ref, 1, &f);
704 jsons_print_status(out, ident->flags, &f);
705 jsons_print_iffeatures(out, ident->module, ident->iffeature, ident->iffeature_size, &f);
706
707 ly_print(out, "}");
708 if (first) {
709 (*first) = 0;
710 }
711}
712
713static void
714jsons_print_identities(struct lyout *out, const struct lys_ident *ident, uint16_t ident_size, int *first)
715{
716 int i;
717
718 if (!ident_size) {
719 return;
720 }
721
722 ly_print(out, "%s\"identities\":[", (first && (*first)) ? "" : ",");
723 for (i = 0; i < ident_size; ++i) {
724 ly_print(out, "%s\"%s\"", i ? "," : "", ident[i].name);
725 }
726 ly_print(out, "]");
727 if (first) {
728 (*first) = 0;
729 }
730}
731
732static void
733jsons_print_feature(struct lyout *out, const struct lys_feature *feat, int *first)
734{
735 int f = 1;
736 unsigned int j;
737
738 ly_print(out, "%s\"%s\":{", (first && (*first)) ? "" : ",", feat->name);
739 jsons_print_text(out, "description", "text", feat->dsc, 1, &f);
740 jsons_print_text(out, "reference", "text", feat->ref, 1, &f);
741 jsons_print_status(out, feat->flags, &f);
742 jsons_print_iffeatures(out, feat->module, feat->iffeature, feat->iffeature_size, &f);
743 if (feat->depfeatures && feat->depfeatures->number) {
Radek Krejcib3c271a2018-08-02 08:15:54 +0200744 ly_print(out, "%s\"depending-features\":[", f ? "" : ",");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200745 for (j = 0; j < feat->depfeatures->number; ++j) {
746 ly_print(out, "%s\"%s\"", j ? "," : "", ((struct lys_feature*)(feat->depfeatures->set.g[j]))->name);
747 }
748 ly_print(out, "]");
749 }
750 ly_print(out, "}");
751 if (first) {
752 (*first) = 0;
753 }
754}
755
756static void
757jsons_print_features(struct lyout *out, const struct lys_feature *feat, uint8_t feat_size, int *first)
758{
Radek Krejci96e51aa2018-08-14 12:55:32 +0200759 int i;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200760
761 if (!feat_size) {
762 return;
763 }
764
Radek Krejci96e51aa2018-08-14 12:55:32 +0200765 ly_print(out, "%s\"features\":[", (first && (*first)) ? "" : ",");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200766 for (i = 0; i < feat_size; ++i) {
Radek Krejci96e51aa2018-08-14 12:55:32 +0200767 ly_print(out, "%s\"%s\"", i ? "," : "", feat[i].name);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200768 }
Radek Krejci96e51aa2018-08-14 12:55:32 +0200769 ly_print(out, "]");
Radek Krejci0e67ac42018-07-25 15:46:37 +0200770 if (first) {
771 (*first) = 0;
772 }
773}
774
775static void
776jsons_print_data_(struct lyout *out, const struct lys_module *mod, struct lys_node *data, int *first)
777{
778 struct lys_node *node;
Radek Krejci8aa90c92018-08-13 15:00:54 +0200779 int mask = LYS_CONTAINER | LYS_CHOICE | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML | LYS_CASE | LYS_USES | LYS_ANYDATA;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200780
781 LY_TREE_FOR(data, node) {
782 if (!(node->nodetype & mask)) {
783 continue;
784 }
785 if (node->nodetype & (LYS_USES)) {
786 jsons_print_data_(out, mod, node->child, first);
787 } else if (lys_main_module(mod) == lys_main_module(node->module)) {
788 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
789 if (node->module->type) {
790 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
791 }
792 ly_print(out, "}");
793 } else {
euikook7b339f32020-11-16 15:35:52 +0900794 ly_print(out, "%s\"%s:%s\":{\"nodetype\":\"%s\"}",
795 (first && (*first)) ? "" : ",",
796 lys_main_module(node->module)->name, node->name,
Radek Krejci0e67ac42018-07-25 15:46:37 +0200797 jsons_nodetype_str(node->nodetype));
798 (*first) = 0;
799 }
800 }
801}
802
803static void
804jsons_print_data(struct lyout *out, const struct lys_module *mod, struct lys_node *data, int *first)
805{
806 int f;
807
808 ly_print(out, "%s\"data\":{", (first && (*first)) ? "" : ",");
809 f = 1;
810 jsons_print_data_(out, mod, data, &f);
811 ly_print(out, "}");
Radek Krejci40cb8d72018-08-03 12:19:41 +0200812 if (first) {
813 (*first) = 0;
814 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200815}
816
817static void
Radek Krejci8aa90c92018-08-13 15:00:54 +0200818jsons_print_nodes_uses_(struct lyout *out, struct lys_node *data, const char *label, int mask, int *top_first, int *first)
Radek Krejci0e67ac42018-07-25 15:46:37 +0200819{
Radek Krejci0e67ac42018-07-25 15:46:37 +0200820 struct lys_node *node;
Radek Krejci0e67ac42018-07-25 15:46:37 +0200821 LY_TREE_FOR(data, node) {
Radek Krejci8aa90c92018-08-13 15:00:54 +0200822 if (!(node->nodetype & mask)) {
Radek Krejci0e67ac42018-07-25 15:46:37 +0200823 continue;
824 }
Radek Krejci8aa90c92018-08-13 15:00:54 +0200825 if (node->nodetype & (LYS_USES)) {
826 jsons_print_nodes_uses_(out, node->child, label, mask, top_first, first);
827 } else {
Radek Krejci870702f2018-08-17 10:52:03 +0200828 if (*first) {
Radek Krejci8aa90c92018-08-13 15:00:54 +0200829 ly_print(out, "%s\"%s\":[", (top_first && (*top_first)) ? "" : ",", label);
830 }
Radek Krejci870702f2018-08-17 10:52:03 +0200831 ly_print(out, "%s\"%s\"", (*first) ? "" : ",", node->name);
Radek Krejci8aa90c92018-08-13 15:00:54 +0200832 (*first) = 0;
833 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200834 }
Radek Krejci8aa90c92018-08-13 15:00:54 +0200835}
836
837static void
838jsons_print_nodes_(struct lyout *out, struct lys_node *data, const char *label, int mask, int *first)
839{
840 int f = 1;
841 struct lys_node *node;
842
843 LY_TREE_FOR(data, node) {
844 if (!(node->nodetype & mask)) {
845 continue;
846 }
847 if (node->nodetype & (LYS_USES)) {
848 jsons_print_nodes_uses_(out, node->child, label, mask, first, &f);
849 } else {
850 if (f) {
851 ly_print(out, "%s\"%s\":[", (first && (*first)) ? "" : ",", label);
852 }
853 ly_print(out, "%s\"%s\"", f ? "" : ",", node->name);
854 f = 0;
855 }
Radek Krejci0e67ac42018-07-25 15:46:37 +0200856 }
Radek Krejci8aa90c92018-08-13 15:00:54 +0200857 if (!f) {
858 ly_print(out, "]");
859 if (first) {
860 (*first) = 0;
861 }
862 }
863}
864
865static void
866jsons_print_groupings(struct lyout *out, struct lys_node *data, int *first)
867{
868 jsons_print_nodes_(out, data, "groupings", LYS_GROUPING, first);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200869}
870
871static void
872jsons_print_rpcs(struct lyout *out, struct lys_node *data, int *first)
873{
Radek Krejci8aa90c92018-08-13 15:00:54 +0200874 jsons_print_nodes_(out, data, "rpcs", LYS_RPC, first);
875}
Radek Krejci0e67ac42018-07-25 15:46:37 +0200876
Radek Krejci8aa90c92018-08-13 15:00:54 +0200877static void
878jsons_print_actions(struct lyout *out, struct lys_node *data, int *first)
879{
880 jsons_print_nodes_(out, data, "actions", LYS_ACTION, first);
881}
882
883static void
884jsons_print_notifs(struct lyout *out, struct lys_node *data, int *first)
885{
886 jsons_print_nodes_(out, data, "notifications", LYS_NOTIF, first);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200887}
888
889static void
890jsons_print_module(struct lyout *out, const struct lys_module *module)
891{
892 ly_print(out, "{\"%s\":{", module->name);
893 ly_print(out, "\"namespace\":\"%s\"", module->ns);
894 ly_print(out, ",\"prefix\":\"%s\"", module->prefix);
895 jsons_print_text(out, "description", "text", module->dsc, 1, NULL);
896 jsons_print_text(out, "reference", "text", module->ref, 1, NULL);
897 jsons_print_text(out, "organization", "text", module->org, 1, NULL);
898 jsons_print_text(out, "contact", "text", module->contact, 1, NULL);
899 jsons_print_object(out, "yang-version", "value", (module->version == LYS_VERSION_1_1) ? "1.1" : "1.0", 1, NULL);
900 /* TODO deviated-by */
901
902 jsons_print_revisions(out, module->rev, module->rev_size, NULL);
903 jsons_print_includes(out, module->inc, module->inc_size, NULL);
904 jsons_print_imports(out, module, NULL);
905 jsons_print_typedefs(out, module->tpdf, module->tpdf_size, NULL);
906 jsons_print_identities(out, module->ident, module->ident_size, NULL);
907 jsons_print_features(out, module->features, module->features_size, NULL);
908 jsons_print_augment(out, module->augment, module->augment_size, NULL);
909 jsons_print_deviation(out, module->deviation, module->deviation_size, NULL);
910
911 jsons_print_groupings(out, module->data, NULL);
912 jsons_print_data(out, module, module->data, NULL);
913 jsons_print_rpcs(out, module->data, NULL);
Radek Krejci40cb8d72018-08-03 12:19:41 +0200914 jsons_print_notifs(out, module->data, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200915
916 /* close the module */
917 ly_print(out, "}}");
918}
919
920static void
921jsons_print_submodule(struct lyout *out, const struct lys_submodule *module)
922{
923 ly_print(out, "{\"%s\":{", module->name);
924 ly_print(out, "\"belongs-to\":\"%s\"", module->belongsto->name);
925 jsons_print_text(out, "description", "text", module->dsc, 1, NULL);
926 jsons_print_text(out, "reference", "text", module->ref, 1, NULL);
927 jsons_print_text(out, "organization", "text", module->org, 1, NULL);
928 jsons_print_text(out, "contact", "text", module->contact, 1, NULL);
929 jsons_print_object(out, "yang-version", "value", (module->version == LYS_VERSION_1_1) ? "1.1" : "1.0", 1, NULL);
930 /* TODO deviated-by */
931
932 jsons_print_revisions(out, module->rev, module->rev_size, NULL);
933 jsons_print_includes(out, module->inc, module->inc_size, NULL);
934 jsons_print_imports(out, (struct lys_module *)module, NULL);
935 jsons_print_typedefs(out, module->tpdf, module->tpdf_size, NULL);
936 jsons_print_identities(out, module->ident, module->ident_size, NULL);
937 jsons_print_features(out, module->features, module->features_size, NULL);
938 jsons_print_augment(out, module->augment, module->augment_size, NULL);
939 jsons_print_deviation(out, module->deviation, module->deviation_size, NULL);
940
Radek Krejci0e67ac42018-07-25 15:46:37 +0200941 /* close the module */
942 ly_print(out, "}}");
943}
944
945static void
946jsons_print_container(struct lyout *out, const struct lys_node *node, int *first)
947{
948 struct lys_node_container *cont = (struct lys_node_container *)node;
949
950 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
951 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
952 if (node->module->type) {
953 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
954 }
955 jsons_print_text(out, "description", "text", cont->dsc, 1, NULL);
956 jsons_print_text(out, "reference", "text", cont->ref, 1, NULL);
957 jsons_print_config(out, cont->flags, NULL);
958 jsons_print_status(out, cont->flags, NULL);
959 jsons_print_text(out, "presence", "value", cont->presence, 1, NULL);
960 jsons_print_iffeatures(out, cont->module, cont->iffeature, cont->iffeature_size, NULL);
961 jsons_print_when(out, cont->when, NULL);
962 jsons_print_musts(out, cont->must, cont->must_size, NULL);
963 jsons_print_typedefs(out, cont->tpdf, cont->tpdf_size, NULL);
964
965 jsons_print_groupings(out, cont->child, NULL);
966 jsons_print_data(out, cont->module, cont->child, NULL);
Radek Krejci8aa90c92018-08-13 15:00:54 +0200967 jsons_print_actions(out, cont->child, NULL);
Radek Krejci40cb8d72018-08-03 12:19:41 +0200968 jsons_print_notifs(out, cont->child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +0200969 ly_print(out, "}");
970}
971
972static void
973jsons_print_choice(struct lyout *out, const struct lys_node *node, int *first)
974{
975 struct lys_node_choice *choice = (struct lys_node_choice *)node;
976
977 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
978 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
979 if (node->module->type) {
980 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
981 }
982 jsons_print_text(out, "description", "text", choice->dsc, 1, NULL);
983 jsons_print_text(out, "reference", "text", choice->ref, 1, NULL);
984 jsons_print_config(out, choice->flags, NULL);
985 jsons_print_status(out, choice->flags, NULL);
986 jsons_print_mand(out, choice->flags, NULL);
987 if (choice->dflt) {
988 jsons_print_defaults(out, &choice->dflt->name, 1, NULL);
989 }
990 jsons_print_iffeatures(out, choice->module, choice->iffeature, choice->iffeature_size, NULL);
991 jsons_print_when(out, choice->when, NULL);
992
993 jsons_print_data(out, choice->module, choice->child, NULL);
994 ly_print(out, "}");
995}
996
997static void
998jsons_print_leaf(struct lyout *out, const struct lys_node *node, int *first)
999{
1000 struct lys_node_leaf *leaf = (struct lys_node_leaf *)node;
1001
1002 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1003 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1004 if (node->module->type) {
1005 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1006 }
1007 jsons_print_text(out, "description", "text", leaf->dsc, 1, NULL);
1008 jsons_print_text(out, "reference", "text", leaf->ref, 1, NULL);
1009 jsons_print_status(out, leaf->flags, NULL);
1010 jsons_print_config(out, leaf->flags, NULL);
1011 jsons_print_mand(out, leaf->flags, NULL);
1012 jsons_print_type(out, &leaf->type, NULL);
1013 jsons_print_text(out, "units", "name", leaf->units, 1, NULL);
1014 if (leaf->dflt) {
1015 jsons_print_defaults(out, &leaf->dflt, 1, NULL);
1016 }
1017 jsons_print_iffeatures(out, leaf->module, leaf->iffeature, leaf->iffeature_size, NULL);
1018 jsons_print_when(out, leaf->when, NULL);
1019 jsons_print_musts(out, leaf->must, leaf->must_size, NULL);
1020 ly_print(out, "}");
1021}
1022
1023static void
1024jsons_print_leaflist(struct lyout *out, const struct lys_node *node, int *first)
1025{
1026 struct lys_node_leaflist *llist = (struct lys_node_leaflist *)node;
1027
1028 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1029 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1030 if (node->module->type) {
1031 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1032 }
1033 jsons_print_text(out, "description", "text", llist->dsc, 1, NULL);
1034 jsons_print_text(out, "reference", "text", llist->ref, 1, NULL);
1035 jsons_print_status(out, llist->flags, NULL);
1036 jsons_print_config(out, llist->flags, NULL);
1037 jsons_print_ordering(out, llist->flags, NULL);
1038 jsons_print_type(out, &llist->type, NULL);
1039 jsons_print_text(out, "units", "name", llist->units, 1, NULL);
1040 jsons_print_defaults(out, llist->dflt, llist->dflt_size, NULL);
1041 if (llist->min) {
1042 jsons_print_min(out, llist->min, NULL);
1043 }
1044 if (llist->max) {
1045 jsons_print_max(out, llist->max, NULL);
1046 }
1047 jsons_print_iffeatures(out, llist->module, llist->iffeature, llist->iffeature_size, NULL);
1048 jsons_print_when(out, llist->when, NULL);
1049 jsons_print_musts(out, llist->must, llist->must_size, NULL);
1050 ly_print(out, "}");
1051}
1052
1053static void
1054jsons_print_list(struct lyout *out, const struct lys_node *node, int *first)
1055{
1056 uint8_t i;
1057 struct lys_node_list *list = (struct lys_node_list *)node;
1058
1059 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1060 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1061 if (node->module->type) {
1062 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1063 }
1064 jsons_print_text(out, "description", "text", list->dsc, 1, NULL);
1065 jsons_print_text(out, "reference", "text", list->ref, 1, NULL);
1066 jsons_print_status(out, list->flags, NULL);
1067 jsons_print_config(out, list->flags, NULL);
1068 jsons_print_ordering(out, list->flags, NULL);
1069 if (list->min) {
1070 jsons_print_min(out, list->min, NULL);
1071 }
1072 if (list->max) {
1073 jsons_print_max(out, list->max, NULL);
1074 }
1075 jsons_print_iffeatures(out, list->module, list->iffeature, list->iffeature_size, NULL);
1076 jsons_print_when(out, list->when, NULL);
1077 jsons_print_musts(out, list->must, list->must_size, NULL);
1078 ly_print(out, ",\"keys\":[");
1079 for (i = 0; i < list->keys_size; ++i) {
1080 ly_print(out, "%s\"%s\"", i ? "," : "", list->keys[i]->name);
1081 }
1082 ly_print(out, "]");
1083 jsons_print_uniques(out, list->unique, list->unique_size, NULL);
1084 jsons_print_typedefs(out, list->tpdf, list->tpdf_size, NULL);
1085
1086 jsons_print_groupings(out, list->child, NULL);
1087 jsons_print_data(out, list->module, list->child, NULL);
Radek Krejci8aa90c92018-08-13 15:00:54 +02001088 jsons_print_actions(out, list->child, NULL);
Radek Krejci40cb8d72018-08-03 12:19:41 +02001089 jsons_print_notifs(out, list->child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +02001090 ly_print(out, "}");
1091}
1092
1093static void
1094jsons_print_anydata(struct lyout *out, const struct lys_node *node, int *first)
1095{
1096 struct lys_node_anydata *any = (struct lys_node_anydata *)node;
1097
Michal Vaskob3d6d192018-11-05 10:02:10 +01001098 if (!lys_parent(node) && !strcmp(node->name, "config") && !strcmp(node->module->name, "ietf-netconf")) {
1099 /* node added by libyang, not actually in the model */
1100 return;
1101 }
1102
Radek Krejci0e67ac42018-07-25 15:46:37 +02001103 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1104 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1105 if (node->module->type) {
1106 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1107 }
1108 jsons_print_text(out, "description", "text", any->dsc, 1, NULL);
1109 jsons_print_text(out, "reference", "text", any->ref, 1, NULL);
1110 jsons_print_config(out, any->flags, NULL);
1111 jsons_print_status(out, any->flags, NULL);
1112 jsons_print_mand(out, any->flags, NULL);
1113 jsons_print_iffeatures(out, any->module, any->iffeature, any->iffeature_size, NULL);
1114 jsons_print_when(out, any->when, NULL);
1115 jsons_print_musts(out, any->must, any->must_size, NULL);
1116
1117 /* TODO print content */
1118
1119 ly_print(out, "}");
1120}
1121
1122static void
1123jsons_print_grouping(struct lyout *out, const struct lys_node *node, int *first)
1124{
1125 struct lys_node_grp *group = (struct lys_node_grp *)node;
1126
1127 jsons_print_object(out, node->name, "module", lys_main_module(node->module)->name, 0, first);
1128 if (node->module->type) {
1129 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1130 }
1131 jsons_print_text(out, "description", "text", group->dsc, 1, NULL);
1132 jsons_print_text(out, "reference", "text", group->ref, 1, NULL);
1133 jsons_print_status(out, group->flags, NULL);
1134 jsons_print_typedefs(out, group->tpdf, group->tpdf_size, NULL);
1135
1136 jsons_print_groupings(out, group->child, NULL);
1137 jsons_print_data(out, group->module, group->child, NULL);
Radek Krejci8aa90c92018-08-13 15:00:54 +02001138 jsons_print_actions(out, group->child, NULL);
Radek Krejci40cb8d72018-08-03 12:19:41 +02001139 jsons_print_notifs(out, group->child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +02001140 ly_print(out, "}");
1141}
1142
1143static void
1144jsons_print_case(struct lyout *out, const struct lys_node *node, int *first)
1145{
1146 struct lys_node_case *cas = (struct lys_node_case *)node;
1147
1148 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1149 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1150 if (node->module->type) {
1151 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1152 }
1153 jsons_print_text(out, "description", "text", cas->dsc, 1, NULL);
1154 jsons_print_text(out, "reference", "text", cas->ref, 1, NULL);
1155 jsons_print_config(out, cas->flags, NULL);
1156 jsons_print_status(out, cas->flags, NULL);
1157 jsons_print_iffeatures(out, cas->module, cas->iffeature, cas->iffeature_size, NULL);
1158 jsons_print_when(out, cas->when, NULL);
1159
1160 jsons_print_data(out, cas->module, cas->child, NULL);
1161 ly_print(out, "}");
1162}
1163
1164static void
1165jsons_print_input(struct lyout *out, const struct lys_node *node, int *first)
1166{
1167 struct lys_node_inout *input = (struct lys_node_inout *)node;
1168
1169 jsons_print_object(out, "input", "module", lys_main_module(node->module)->name, 0, first);
1170 jsons_print_typedefs(out, input->tpdf, input->tpdf_size, NULL);
1171 jsons_print_musts(out, input->must, input->must_size, NULL);
1172 jsons_print_groupings(out, input->child, NULL);
1173 jsons_print_data(out, input->module, input->child, NULL);
1174 ly_print(out, "}");
1175}
1176
1177static void
1178jsons_print_output(struct lyout *out, const struct lys_node *node, int *first)
1179{
1180 struct lys_node_inout *output = (struct lys_node_inout *)node;
1181
1182 jsons_print_object(out, "output", "module", lys_main_module(node->module)->name, 0, first);
1183 jsons_print_typedefs(out, output->tpdf, output->tpdf_size, NULL);
1184 jsons_print_musts(out, output->must, output->must_size, NULL);
1185 jsons_print_groupings(out, output->child, NULL);
1186 jsons_print_data(out, output->module, output->child, NULL);
1187 ly_print(out, "}");
1188}
1189
1190static void
1191jsons_print_notif(struct lyout *out, const struct lys_node *node, int *first)
1192{
1193 struct lys_node_notif *ntf = (struct lys_node_notif *)node;
1194
1195 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1196 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1197 if (node->module->type) {
1198 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1199 }
1200 jsons_print_text(out, "description", "text", ntf->dsc, 1, NULL);
1201 jsons_print_text(out, "reference", "text", ntf->ref, 1, NULL);
1202 jsons_print_status(out, ntf->flags, NULL);
1203 jsons_print_iffeatures(out, ntf->module, ntf->iffeature, ntf->iffeature_size, NULL);
1204 jsons_print_typedefs(out, ntf->tpdf, ntf->tpdf_size, NULL);
1205 jsons_print_musts(out, ntf->must, ntf->must_size, NULL);
1206
1207 jsons_print_groupings(out, ntf->child, NULL);
1208 jsons_print_data(out, ntf->module, ntf->child, NULL);
1209 ly_print(out, "}");
1210}
1211
1212static void
Radek Krejci0e67ac42018-07-25 15:46:37 +02001213jsons_print_rpc(struct lyout *out, const struct lys_node *node, int *first)
1214{
1215 const struct lys_node *child;
1216 struct lys_node_rpc_action *rpc = (struct lys_node_rpc_action *)node;
1217
1218 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1219 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1220 if (node->module->type) {
1221 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1222 }
1223 jsons_print_text(out, "description", "text", rpc->dsc, 1, NULL);
1224 jsons_print_text(out, "reference", "text", rpc->ref, 1, NULL);
1225 jsons_print_status(out, rpc->flags, NULL);
1226 jsons_print_iffeatures(out, rpc->module, rpc->iffeature, rpc->iffeature_size, NULL);
1227 jsons_print_typedefs(out, rpc->tpdf, rpc->tpdf_size, NULL);
1228 jsons_print_groupings(out, rpc->child, NULL);
1229
Radek Krejci8aa90c92018-08-13 15:00:54 +02001230 LY_TREE_FOR(node->child, child) {
1231 if (!(child->nodetype & LYS_INPUT)) {
Radek Krejci0e67ac42018-07-25 15:46:37 +02001232 continue;
1233 }
Radek Krejci8aa90c92018-08-13 15:00:54 +02001234 jsons_print_input(out, child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +02001235 break;
1236 }
1237
Radek Krejci8aa90c92018-08-13 15:00:54 +02001238 LY_TREE_FOR(node->child, child) {
1239 if (!(child->nodetype & LYS_OUTPUT)) {
Radek Krejci0e67ac42018-07-25 15:46:37 +02001240 continue;
1241 }
Radek Krejci8aa90c92018-08-13 15:00:54 +02001242 jsons_print_output(out, child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +02001243 break;
1244 }
1245 ly_print(out, "}");
1246}
1247
1248static void
1249jsons_print_action(struct lyout *out, const struct lys_node *node, int *first)
1250{
1251 const struct lys_node *child;
1252 struct lys_node_rpc_action *act = (struct lys_node_rpc_action *)node;
1253
1254 jsons_print_object(out, node->name, "nodetype", jsons_nodetype_str(node->nodetype), 0, first);
1255 ly_print(out, ",\"module\":\"%s\"", lys_main_module(node->module)->name);
1256 if (node->module->type) {
1257 ly_print(out, ",\"included-from\":\"%s\"", node->module->name);
1258 }
1259 jsons_print_text(out, "description", "text", act->dsc, 1, NULL);
1260 jsons_print_text(out, "reference", "text", act->ref, 1, NULL);
1261 jsons_print_status(out, act->flags, NULL);
1262 jsons_print_iffeatures(out, act->module, act->iffeature, act->iffeature_size, NULL);
1263 jsons_print_typedefs(out, act->tpdf, act->tpdf_size, NULL);
1264 jsons_print_groupings(out, act->child, NULL);
1265
Radek Krejci8aa90c92018-08-13 15:00:54 +02001266 LY_TREE_FOR(node->child, child) {
1267 if (!(child->nodetype & LYS_INPUT)) {
Radek Krejci0e67ac42018-07-25 15:46:37 +02001268 continue;
1269 }
Radek Krejci8aa90c92018-08-13 15:00:54 +02001270 jsons_print_input(out, child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +02001271 break;
1272 }
1273
Radek Krejci8aa90c92018-08-13 15:00:54 +02001274 LY_TREE_FOR(node->child, child) {
1275 if (!(child->nodetype & LYS_OUTPUT)) {
Radek Krejci0e67ac42018-07-25 15:46:37 +02001276 continue;
1277 }
Radek Krejci8aa90c92018-08-13 15:00:54 +02001278 jsons_print_output(out, child, NULL);
Radek Krejci0e67ac42018-07-25 15:46:37 +02001279 break;
1280 }
1281 ly_print(out, "}");
1282}
1283
1284int
1285jsons_print_model(struct lyout *out, const struct lys_module *module, const char *target_schema_path)
1286{
1287 int rc = EXIT_SUCCESS;
1288
1289 if (!target_schema_path) {
1290 if (module->type == 0) {
1291 jsons_print_module(out, module);
1292 } else {
1293 jsons_print_submodule(out, (struct lys_submodule *)module);
1294 }
1295 } else {
1296 ly_print(out, "{");
1297 rc = lys_print_target(out, module, target_schema_path,
1298 jsons_print_typedef,
1299 jsons_print_identity,
1300 jsons_print_feature,
1301 jsons_print_type,
1302 jsons_print_grouping,
1303 jsons_print_container,
1304 jsons_print_choice,
1305 jsons_print_leaf,
1306 jsons_print_leaflist,
1307 jsons_print_list,
1308 jsons_print_anydata,
1309 jsons_print_case,
1310 jsons_print_notif,
1311 jsons_print_rpc,
1312 jsons_print_action,
1313 jsons_print_input,
1314 jsons_print_output);
1315 ly_print(out, "}");
1316 }
1317 ly_print_flush(out);
1318
1319 return rc;
1320}