libyang  1.0.253
YANG data modeling language library
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
Libyang.cpp
Go to the documentation of this file.
1 
15 #include <iostream>
16 #include <memory>
17 #include <stdexcept>
18 #include <vector>
19 
20 #include "Xml.hpp"
21 #include "Internal.hpp"
22 #include "Libyang.hpp"
23 #include "Tree_Data.hpp"
24 #include "Tree_Schema.hpp"
25 
26 extern "C" {
27 #include "libyang.h"
28 #include "tree_data.h"
29 #include "tree_schema.h"
30 #include "context.h"
31 }
32 
33 namespace libyang {
34 
35 Context::Context(ly_ctx *ctx, S_Deleter deleter):
36  ctx(ctx),
37  deleter(deleter)
38 {};
39 Context::Context(const char *search_dir, int options) {
40  ctx = ly_ctx_new(search_dir, options);
41  if (!ctx) {
42  check_libyang_error(nullptr);
43  }
44  deleter = std::make_shared<Deleter>(ctx);
45 }
46 Context::Context(const char *search_dir, const char *path, LYD_FORMAT format, int options) {
47  ctx = ly_ctx_new_ylpath(search_dir, path, format, options);
48  if (!ctx) {
49  check_libyang_error(nullptr);
50  }
51  deleter = std::make_shared<Deleter>(ctx);
52 }
53 Context::Context(const char *search_dir, LYD_FORMAT format, const char *data, int options) {
54  ctx = ly_ctx_new_ylmem(search_dir, data, format, options);
55  if (!ctx) {
56  check_libyang_error(nullptr);
57  }
58  deleter = std::make_shared<Deleter>(ctx);
59 }
61 int Context::set_searchdir(const char *search_dir) {
62  int ret = ly_ctx_set_searchdir(ctx, search_dir);
63  if (ret) {
64  check_libyang_error(ctx);
65  }
66  return ret;
67 }
68 S_Data_Node Context::info() {
69  struct lyd_node *new_node = ly_ctx_info(ctx);
70  if (!new_node) {
71  check_libyang_error(ctx);
72  return nullptr;
73  }
74 
75  S_Deleter new_deleter = std::make_shared<Deleter>(new_node, deleter);
76  return std::make_shared<Data_Node>(new_node, new_deleter);
77 }
78 S_Module Context::get_module(const char *name, const char *revision, int implemented) {
79  const struct lys_module *module = ly_ctx_get_module(ctx, name, revision, implemented);
80  return module ? std::make_shared<Module>((lys_module *) module, deleter) : nullptr;
81 }
82 S_Module Context::get_module_older(S_Module module) {
83  const struct lys_module *new_module = ly_ctx_get_module_older(ctx, module->module);
84  return new_module ? std::make_shared<Module>((lys_module *) new_module, deleter) : nullptr;
85 }
86 S_Module Context::load_module(const char *name, const char *revision) {
87  const struct lys_module *module = ly_ctx_load_module(ctx, name, revision);
88  if (!module) {
89  check_libyang_error(ctx);
90  }
91  return module ? std::make_shared<Module>((lys_module *) module, deleter) : nullptr;
92 }
93 S_Module Context::get_module_by_ns(const char *ns, const char *revision, int implemented) {
94  const struct lys_module *module = ly_ctx_get_module_by_ns(ctx, ns, revision, implemented);
95  return module ? std::make_shared<Module>((lys_module *) module, deleter) : nullptr;
96 }
97 std::vector<S_Module> Context::get_module_iter() {
98  const struct lys_module *mod = nullptr;
99  uint32_t i = 0;
100 
101  std::vector<S_Module> s_vector;
102 
103  while ((mod = ly_ctx_get_module_iter(ctx, &i))) {
104  if (mod == nullptr) {
105  break;
106  }
107  s_vector.push_back(std::make_shared<Module>((lys_module *) mod, deleter));
108  }
109 
110  return s_vector;
111 }
112 std::vector<S_Module> Context::get_disabled_module_iter() {
113  const struct lys_module *mod = nullptr;
114  uint32_t i = 0;
115 
116  std::vector<S_Module> s_vector;
117 
118  while ((mod = ly_ctx_get_disabled_module_iter(ctx, &i))) {
119  if (mod == nullptr) {
120  break;
121  }
122  s_vector.push_back(std::make_shared<Module>((lys_module *) mod, deleter));
123  }
124 
125  return s_vector;
126 }
128  return ly_ctx_clean(ctx, nullptr);
129 }
130 std::vector<std::string> Context::get_searchdirs() {
131  std::vector<std::string> s_vector;
132  const char * const *data = ly_ctx_get_searchdirs(ctx);
133  if (!data) {
134  return s_vector;
135  }
136 
137  int size = 0;
138  while (true) {
139  if (data[size] == nullptr) {
140  break;
141  }
142  s_vector.push_back(std::string(data[size]));
143  size++;
144  }
145 
146  return s_vector;
147 };
148 S_Submodule Context::get_submodule(const char *module, const char *revision, const char *submodule, const char *sub_revision) {
149  const struct lys_submodule *tmp_submodule = nullptr;
150 
151  tmp_submodule = ly_ctx_get_submodule(ctx, module, revision, submodule, sub_revision);
152 
153  return tmp_submodule ? std::make_shared<Submodule>((struct lys_submodule *) tmp_submodule, deleter) : nullptr;
154 }
155 S_Submodule Context::get_submodule2(S_Module main_module, const char *submodule) {
156  const struct lys_submodule *tmp_submodule = nullptr;
157 
158  tmp_submodule = ly_ctx_get_submodule2(main_module->module, submodule);
159 
160  return tmp_submodule ? std::make_shared<Submodule>((struct lys_submodule *) tmp_submodule, deleter) : nullptr;
161 }
162 S_Schema_Node Context::get_node(S_Schema_Node start, const char *data_path, int output) {
163  const struct lys_node *node = nullptr;
164 
165  node = ly_ctx_get_node(ctx, start ? start->node : NULL, data_path, output);
166 
167  return node ? std::make_shared<Schema_Node>((struct lys_node *) node, deleter) : nullptr;
168 }
169 S_Set Context::find_path(const char *schema_path) {
170  struct ly_set *set = ly_ctx_find_path(ctx, schema_path);
171  if (!set) {
172  return nullptr;
173  }
174 
175  S_Deleter new_deleter = std::make_shared<Deleter>(set, deleter);
176  return std::make_shared<Set>(set, new_deleter);
177 }
178 std::vector<S_Schema_Node> Context::data_instantiables(int options) {
179  std::vector<S_Schema_Node> s_vector;
180  struct lys_node *iter = NULL;
181  int i;
182 
183  for (i = 0; i < ctx->models.used; i++) {
184  while ((iter = (struct lys_node *)lys_getnext(iter, NULL, ctx->models.list[i], options))) {
185  s_vector.push_back(std::make_shared<Schema_Node>(iter, deleter));
186  }
187  }
188 
189  return s_vector;
190 }
191 S_Data_Node Context::parse_data_mem(const char *data, LYD_FORMAT format, int options) {
192  struct lyd_node *new_node = nullptr;
193 
194  new_node = lyd_parse_mem(ctx, data, format, options, NULL);
195  if (!new_node) {
196  check_libyang_error(ctx);
197  return nullptr;
198  }
199 
200  S_Deleter new_deleter = std::make_shared<Deleter>(new_node, deleter);
201  return std::make_shared<Data_Node>(new_node, new_deleter);
202 }
203 S_Data_Node Context::parse_data_fd(int fd, LYD_FORMAT format, int options) {
204  struct lyd_node *new_node = nullptr;
205 
206  new_node = lyd_parse_fd(ctx, fd, format, options, NULL);
207  if (!new_node) {
208  check_libyang_error(ctx);
209  return nullptr;
210  }
211 
212  S_Deleter new_deleter = std::make_shared<Deleter>(new_node, deleter);
213  return std::make_shared<Data_Node>(new_node, new_deleter);
214 }
215 
216 S_Module Context::parse_module_mem(const char *data, LYS_INFORMAT format) {
217  struct lys_module *module = nullptr;
218 
219  module = (struct lys_module *) lys_parse_mem(ctx, data, format);
220  if (!module) {
221  check_libyang_error(ctx);
222  return nullptr;
223  }
224 
225  S_Deleter new_deleter = std::make_shared<Deleter>(module, deleter);
226  return std::make_shared<Module>(module, new_deleter);
227 }
228 S_Module Context::parse_module_fd(int fd, LYS_INFORMAT format) {
229  struct lys_module *module = nullptr;
230 
231  module = (struct lys_module *) lys_parse_fd(ctx, fd, format);
232  if (!module) {
233  check_libyang_error(ctx);
234  return nullptr;
235  }
236 
237  S_Deleter new_deleter = std::make_shared<Deleter>(module, deleter);
238  return std::make_shared<Module>(module, new_deleter);
239 }
240 S_Module Context::parse_module_path(const char *path, LYS_INFORMAT format) {
241  struct lys_module *module = nullptr;
242 
243  module = (struct lys_module *) lys_parse_path(ctx, path, format);
244  if (!module) {
245  check_libyang_error(ctx);
246  return nullptr;
247  }
248 
249  S_Deleter new_deleter = std::make_shared<Deleter>(module, deleter);
250  return std::make_shared<Module>(module, new_deleter);
251 }
252 S_Data_Node Context::parse_data_path(const char *path, LYD_FORMAT format, int options) {
253  struct lyd_node *new_node = nullptr;
254 
255  new_node = lyd_parse_path(ctx, path, format, options, NULL);
256  if (!new_node) {
257  check_libyang_error(ctx);
258  return nullptr;
259  }
260 
261  S_Deleter new_deleter = std::make_shared<Deleter>(new_node, deleter);
262  return std::make_shared<Data_Node>(new_node, new_deleter);
263 }
264 S_Data_Node Context::parse_data_xml(S_Xml_Elem elem, int options) {
265  struct lyd_node *new_node = nullptr;
266 
267  if (!elem) {
268  throw std::invalid_argument("Elem can not be empty");
269  }
270 
271  new_node = lyd_parse_xml(ctx, &elem->elem, options, NULL);
272  if (!new_node) {
273  check_libyang_error(ctx);
274  return nullptr;
275  }
276 
277  S_Deleter new_deleter = std::make_shared<Deleter>(new_node, deleter);
278  return std::make_shared<Data_Node>(new_node, new_deleter);
279 }
280 
282 {
283  if (mod_missing_cb.empty()) {
284  ly_ctx_set_module_imp_clb(ctx, Context::cpp_mod_missing_cb, this);
285  }
286  mod_missing_cb.emplace_back(std::move(callback), std::move(deleter));
287 }
288 
289 const char* Context::cpp_mod_missing_cb(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev, void *user_data, LYS_INFORMAT *format, void (**free_module_data)(void*, void*))
290 {
291  Context *ctx = static_cast<Context*>(user_data);
292  for (const auto &x : ctx->mod_missing_cb) {
293  const auto &cb = x.first;
294  auto ret = cb(mod_name, mod_rev, submod_name, sub_rev);
295  if (ret.data) {
296  *format = ret.format;
297  if (x.second) {
298  ctx->mod_missing_deleter.push_back(&x.second);
299  *free_module_data = Context::cpp_mod_missing_deleter;
300  }
301  return ret.data;
302  }
303  if (ly_errno != LY_SUCCESS) {
304  // The C API docs say that we should not try any more callbacks
305  return nullptr;
306  }
307  }
308  return nullptr;
309 }
310 
311 void Context::cpp_mod_missing_deleter(void *data, void *user_data)
312 {
313  Context *ctx = static_cast<Context*>(user_data);
314  (*ctx->mod_missing_deleter.back())(data);
315  ctx->mod_missing_deleter.pop_back();
316 }
317 
318 
319 Error::Error(struct ly_err_item *eitem):
320  eitem(eitem)
321 {};
322 
323 std::vector<S_Error> get_ly_errors(S_Context context)
324 {
325  std::vector<S_Error> s_vector;
326  if (!context) {
327  return s_vector;
328  }
329 
330  struct ly_err_item *first_eitem = ly_err_first(context->ctx);
331  if (!first_eitem) {
332  return s_vector;
333  }
334 
335  struct ly_err_item *eitem = first_eitem;
336  while (eitem) {
337  s_vector.push_back(std::make_shared<Error>(eitem));
338  eitem = eitem->next;
339  }
340 
341  return s_vector;
342 }
343 
344 int set_log_options(int options)
345 {
346  return ly_log_options(options);
347 }
348 
349 LY_LOG_LEVEL set_log_verbosity(LY_LOG_LEVEL level)
350 {
351  return ly_verb(level);
352 }
353 
355  struct ly_set *set_new = ly_set_new();
356  if (!set_new) {
357  check_libyang_error(nullptr);
358  }
359 
360  set = set_new;
361  deleter = std::make_shared<Deleter>(set_new);
362 }
363 Set::Set(struct ly_set *set, S_Deleter deleter):
364  set(set),
365  deleter(deleter)
366 {};
368 std::vector<S_Data_Node> Set::data() {
369  std::vector<S_Data_Node> s_vector;
370 
371  unsigned int i;
372  for (i = 0; i < set->number; i++){
373  s_vector.push_back(std::make_shared<Data_Node>(set->set.d[i], deleter));
374  }
375 
376  return s_vector;
377 };
378 std::vector<S_Schema_Node> Set::schema() {
379  std::vector<S_Schema_Node> s_vector;
380 
381  unsigned int i;
382  for (i = 0; i < set->number; i++){
383  s_vector.push_back(std::make_shared<Schema_Node>(set->set.s[i], deleter));
384  }
385 
386  return s_vector;
387 };
388 S_Set Set::dup() {
389  ly_set *new_set = ly_set_dup(set);
390  if (!new_set) {
391  return nullptr;
392  }
393 
394  auto deleter = std::make_shared<Deleter>(new_set);
395  return std::make_shared<Set>(new_set, deleter);
396 }
397 int Set::add(S_Data_Node node, int options) {
398  if (!node) {
399  throw std::invalid_argument("Node can not be empty");
400  }
401  return ly_set_add(set, (void *) node->node, options);
402 }
403 int Set::add(S_Schema_Node node, int options) {
404  if (!node) {
405  throw std::invalid_argument("Node can not be empty");
406  }
407  return ly_set_add(set, (void *) node->node, options);
408 }
409 int Set::contains(S_Data_Node node) {
410  if (!node) {
411  return -1;
412  }
413  return ly_set_contains(set, (void *) node->node);
414 }
415 int Set::contains(S_Schema_Node node) {
416  if (!node) {
417  return -1;
418  }
419  return ly_set_contains(set, (void *) node->node);
420 }
421 int Set::clean() {
422  return ly_set_clean(set);
423 }
424 int Set::rm(S_Data_Node node) {
425  if (!node) {
426  throw std::invalid_argument("Node can not be empty");
427  }
428  return ly_set_rm(set, (void *) node->node);
429 }
430 int Set::rm(S_Schema_Node node) {
431  if (!node) {
432  throw std::invalid_argument("Node can not be empty");
433  }
434  return ly_set_rm(set, (void *) node->node);
435 }
436 int Set::rm_index(unsigned int index) {
437  return ly_set_rm_index(set, index);
438 }
439 
440 /* API for wrapping struct ly_ctx from libnetconf2 python bindings */
441 S_Context create_new_Context(struct ly_ctx *new_ctx) {
442  return new_ctx ? std::make_shared<Context>(new_ctx, nullptr) : nullptr;
443 }
444 
445 }
struct lyd_node * lyd_parse_fd(struct ly_ctx *ctx, int fd, LYD_FORMAT format, int options,...)
Read (and validate) data from the given file descriptor.
Common structure representing single YANG data statement describing.
Definition: tree_schema.h:1231
LY_LOG_LEVEL set_log_verbosity(LY_LOG_LEVEL level)
Definition: Libyang.cpp:349
S_Module get_module_by_ns(const char *ns, const char *revision=nullptr, int implemented=0)
Definition: Libyang.cpp:93
Error(struct ly_err_item *eitem)
Definition: Libyang.cpp:319
std::vector< const mod_missing_deleter_t * > mod_missing_deleter
Definition: Libyang.hpp:140
uint8_t implemented
Definition: tree_schema.h:692
Submodule schema node structure that can be included into a YANG module.
Definition: tree_schema.h:736
S_Module load_module(const char *name, const char *revision=nullptr)
Definition: Libyang.cpp:86
S_Set find_path(const char *schema_path)
Definition: Libyang.cpp:169
Class implementation for libyang C header xml.h.
struct lys_node * data
Definition: tree_schema.h:725
libyang representation of data model trees.
std::vector< S_Module > get_disabled_module_iter()
Definition: Libyang.cpp:112
struct lyd_node * lyd_parse_xml(struct ly_ctx *ctx, struct lyxml_elem **root, int options,...)
Parse (and validate) XML tree.
std::vector< std::pair< mod_missing_cb_t, mod_missing_deleter_t > > mod_missing_cb
Definition: Libyang.hpp:139
S_Data_Node parse_data_xml(S_Xml_Elem elem, int options=0)
Definition: Libyang.cpp:264
class for wrapping ly_ctx.
Definition: Libyang.hpp:43
S_Data_Node parse_data_path(const char *path, LYD_FORMAT format, int options=0)
Definition: Libyang.cpp:252
static void cpp_mod_missing_deleter(void *data, void *user_data)
Definition: Libyang.cpp:311
S_Data_Node parse_data_fd(int fd, LYD_FORMAT format, int options=0)
Definition: Libyang.cpp:203
S_Module parse_module_path(const char *path, LYS_INFORMAT format)
Definition: Libyang.cpp:240
libyang representation of data trees.
S_Submodule get_submodule2(S_Module main_module, const char *submodule=nullptr)
Definition: Libyang.cpp:155
int clean()
Definition: Libyang.cpp:421
Class implementation for libyang C header tree_schema.h.
LYD_FORMAT
Data input/output formats supported by libyang parser and printer functions.
Definition: tree_data.h:40
void add_missing_module_callback(const mod_missing_cb_t &callback, const mod_missing_deleter_t &deleter=mod_missing_deleter_t())
Add a missing include or import module callback.
Definition: Libyang.cpp:281
S_Data_Node parse_data_mem(const char *data, LYD_FORMAT format, int options=0)
Definition: Libyang.cpp:191
struct lys_node * lys_getnext(const struct lys_node *last, const struct lys_node *parent, const struct lys_module *module, int options)
Get next schema tree (sibling) node element that can be instantiated in a data tree. Returned node can be from an augment.
struct lyd_node * lyd_parse_path(struct ly_ctx *ctx, const char *path, LYD_FORMAT format, int options,...)
Read (and validate) data from the given file path.
std::vector< std::string > get_searchdirs()
Definition: Libyang.cpp:130
S_Module get_module(const char *name, const char *revision=nullptr, int implemented=0)
Definition: Libyang.cpp:78
std::function< mod_missing_cb_return(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev)> mod_missing_cb_t
Definition: Libyang.hpp:108
int add(S_Data_Node node, int options=0)
Definition: Libyang.cpp:397
std::vector< S_Schema_Node > schema()
Definition: Libyang.cpp:378
std::vector< S_Error > get_ly_errors(S_Context context)
Definition: Libyang.cpp:323
int contains(S_Data_Node node)
Definition: Libyang.cpp:409
LYS_INFORMAT
Schema input formats accepted by libyang parser functions.
Definition: tree_schema.h:187
std::function< void(void *)> mod_missing_deleter_t
Definition: Libyang.hpp:109
int set_log_options(int options)
Definition: Libyang.cpp:344
const char * ns
Definition: tree_schema.h:726
std::vector< S_Schema_Node > data_instantiables(int options)
Definition: Libyang.cpp:178
Context(struct ly_ctx *ctx, S_Deleter deleter)
Definition: Libyang.cpp:35
Main schema node structure representing YANG module.
Definition: tree_schema.h:673
struct lys_module * lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format)
Load a schema into the specified context.
S_Module get_module_older(S_Module module)
Definition: Libyang.cpp:82
Class implementation for libyang C header libyang.h.
S_Module parse_module_mem(const char *data, LYS_INFORMAT format)
Definition: Libyang.cpp:216
std::vector< S_Data_Node > data()
Definition: Libyang.cpp:368
S_Module parse_module_fd(int fd, LYS_INFORMAT format)
Definition: Libyang.cpp:228
std::vector< S_Module > get_module_iter()
Definition: Libyang.cpp:97
int rm(S_Data_Node node)
Definition: Libyang.cpp:424
Class implementation for libyang C header tree_data.h.
Generic structure for a data node, directly applicable to the data nodes defined as LYS_CONTAINER...
Definition: tree_data.h:183
struct lyd_node * lyd_parse_mem(struct ly_ctx *ctx, const char *data, LYD_FORMAT format, int options,...)
Parse (and validate) data from memory.
const char * name
Definition: tree_schema.h:675
S_Set dup()
Definition: Libyang.cpp:388
int set_searchdir(const char *search_dir)
Definition: Libyang.cpp:61
S_Schema_Node get_node(S_Schema_Node start, const char *data_path, int output=0)
Definition: Libyang.cpp:162
struct lys_module * lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format)
Load a schema into the specified context from a file.
S_Data_Node info()
Definition: Libyang.cpp:68
S_Submodule get_submodule(const char *module, const char *revision=nullptr, const char *submodule=nullptr, const char *sub_revision=nullptr)
Definition: Libyang.cpp:148
struct ly_ctx * ctx
Definition: tree_schema.h:674
S_Context create_new_Context(struct ly_ctx *ctx)
Definition: Libyang.cpp:441
int rm_index(unsigned int index)
Definition: Libyang.cpp:436
struct lys_module * lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format)
Read a schema from file descriptor into the specified context.
static const char * cpp_mod_missing_cb(const char *mod_name, const char *mod_rev, const char *submod_name, const char *sub_rev, void *user_data, LYS_INFORMAT *format, void(**free_module_data)(void *model_data, void *user_data))
Definition: Libyang.cpp:289