yin parser CHANGE use binary search in get_record
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 400efeb..1fdcbeb 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -243,11 +243,21 @@
* @return Pointer to desired record on success, NULL if element is not in the array.
*/
struct yin_subelement *
-get_record(enum yang_keyword type, size_t array_size, struct yin_subelement *array)
+get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
{
- for (size_t i = 0; i < array_size; ++i) {
- if (array[i].type == type) {
- return &array[i];
+ signed char left = 0, right = array_size - 1, middle;
+
+ while (left <= right) {
+ middle = left + (right - left) / 2;
+
+ if (array[middle].type == type) {
+ return &array[middle];
+ }
+
+ if (array[middle].type < type) {
+ left = middle + 1;
+ } else {
+ right = middle - 1;
}
}
@@ -256,9 +266,9 @@
LY_ERR
yin_check_subelem_mandatory_constraint(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info,
- size_t subelem_info_size, enum yang_keyword current_element)
+ signed char subelem_info_size, enum yang_keyword current_element)
{
- for (size_t i = 0; i < subelem_info_size; ++i) {
+ for (signed char i = 0; i < subelem_info_size; ++i) {
/* if there is element that is mandatory and isn't parsed log error and rturn LY_EVALID */
if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Missing mandatory subelement %s of %s element.",
@@ -272,9 +282,9 @@
LY_ERR
yin_check_subelem_first_constraint(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info,
- size_t subelem_info_size, enum yang_keyword current_element, struct yin_subelement *exp_first)
+ signed char subelem_info_size, enum yang_keyword current_element, struct yin_subelement *exp_first)
{
- for (size_t i = 0; i < subelem_info_size; ++i) {
+ for (signed char i = 0; i < subelem_info_size; ++i) {
if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Subelement %s of %s element must be defined as first subelement.",
ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
@@ -285,6 +295,22 @@
return LY_SUCCESS;
}
+/* TODO add something like ifdef NDEBUG around this function, this is supposed to be checked only in debug mode */
+bool
+is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
+{
+ enum yang_keyword current = YANG_NONE; /* 0 */
+
+ for (signed char i = 0; i < subelem_info_size; ++i) {
+ if (subelem_info[i].type <= current) {
+ return false;
+ }
+ current = subelem_info[i].type;
+ }
+
+ return true;
+}
+
/**
* @brief Generic function for content parsing
*
@@ -299,7 +325,7 @@
* @return LY_ERR values.
*/
LY_ERR
-yin_parse_content(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
+yin_parse_content(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, signed char subelem_info_size,
const char **data, enum yang_keyword current_element, const char **text_content, struct lysp_ext_instance **exts)
{
LY_ERR ret = LY_SUCCESS;
@@ -310,6 +336,7 @@
struct yin_arg_record *subelem_attrs = NULL;
enum yang_keyword kw = YANG_NONE;
struct yin_subelement *subelem_info_rec = NULL;
+ assert(is_ordered(subelem_info, subelem_info_size));
if (xml_ctx->status == LYXML_ELEM_CONTENT) {
ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
@@ -639,8 +666,8 @@
{
assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
- struct yin_subelement subelems[2] = {{YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST},
- {YANG_CUSTOM, NULL, 0}};
+ struct yin_subelement subelems[2] = {{YANG_CUSTOM, NULL, 0},
+ {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}};
return yin_parse_content(xml_ctx, subelems, 2, data, elem_type, NULL, exts);
}
@@ -680,8 +707,8 @@
/* allocate new element in sized array for import */
LY_ARRAY_NEW_RET(xml_ctx->ctx, mod->imports, imp, LY_EMEM);
- struct yin_subelement subelems[5] = {{YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
- {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
+ struct yin_subelement subelems[5] = {{YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
+ {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
{YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
{YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
{YANG_CUSTOM, NULL, 0}};
@@ -980,14 +1007,15 @@
LY_ERR
yin_parse_mod(struct lyxml_context *xml_ctx, struct yin_arg_record **mod_args, const char **data, struct lysp_module **mod)
{
- struct yin_subelement subelems[9] = {{YANG_DESCRIPTION, &(*mod)->mod->dsc, YIN_SUBELEM_UNIQUE},
- {YANG_IMPORT, *mod, 0},
- {YANG_ORGANIZATION, &(*mod)->mod->org, YIN_SUBELEM_UNIQUE},
+ struct yin_subelement subelems[9] = {
{YANG_CONTACT, &(*mod)->mod->contact, YIN_SUBELEM_UNIQUE},
+ {YANG_DESCRIPTION, &(*mod)->mod->dsc, YIN_SUBELEM_UNIQUE},
+ {YANG_EXTENSION, &(*mod)->exts, 0},
+ {YANG_IMPORT, *mod, 0},
+ {YANG_NAMESPACE, &(*mod)->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
+ {YANG_ORGANIZATION, &(*mod)->mod->org, YIN_SUBELEM_UNIQUE},
{YANG_PREFIX, &(*mod)->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
{YANG_REFERENCE, &(*mod)->mod->ref, YIN_SUBELEM_UNIQUE},
- {YANG_NAMESPACE, &(*mod)->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
- {YANG_EXTENSION, &(*mod)->exts, 0},
{YANG_CUSTOM, NULL, 0}};
LY_CHECK_RET(yin_parse_attribute(xml_ctx, mod_args, YIN_ARG_NAME, &(*mod)->mod->name, YIN_ARG_MANDATORY, YANG_MODULE));
diff --git a/src/parser_yin.h b/src/parser_yin.h
index cfdfef0..7c2ca65 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -128,7 +128,7 @@
* @param[in] exts Extension instance to add to. Can be null if element cannot have extension as subelement.
* @return LY_ERR values.
*/
-LY_ERR yin_parse_content(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
+LY_ERR yin_parse_content(struct lyxml_context *xml_ctx, struct yin_subelement *subelem_info, signed char subelem_info_size,
const char **data, enum yang_keyword current_element, const char **text_content,
struct lysp_ext_instance **exts);
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index a87551b..a752914 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -679,9 +679,9 @@
lyxml_get_element(st->xml_ctx, &data, &prefix.value, &prefix.len, &name.value, &name.len);
yin_load_attributes(st->xml_ctx, &data, &attrs);
- struct yin_subelement subelems[3] = {{YANG_CUSTOM, NULL, 0},
- {YIN_TEXT, &value, 0},
- {YANG_EXTENSION, &ext_def, 0}};
+ struct yin_subelement subelems[3] = {{YANG_EXTENSION, &ext_def, 0},
+ {YANG_CUSTOM, NULL, 0},
+ {YIN_TEXT, &value, 0}};
ret = yin_parse_content(st->xml_ctx, subelems, 3, &data, YANG_ACTION, NULL, &exts);
assert_int_equal(ret, LY_SUCCESS);
assert_string_equal(exts->name, "custom");