blob: 912ee13b38479db0d3d79e2fb6512b6381fa156b [file] [log] [blame]
Michal Vasko1324b6c2018-09-07 11:16:23 +02001/**
2 * @file common.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief common internal definitions for libyang
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 */
Michal Vasko841d1a92018-09-07 15:40:31 +020014#define _XOPEN_SOURCE
Michal Vasko1324b6c2018-09-07 11:16:23 +020015
16#include <stdlib.h>
Michal Vasko841d1a92018-09-07 15:40:31 +020017#include <stdio.h>
18#include <ctype.h>
19#include <string.h>
20#include <time.h>
21
Michal Vasko58257712018-09-12 11:11:38 +020022#include "common.h"
Michal Vasko841d1a92018-09-07 15:40:31 +020023#include "tree_schema.h"
Michal Vasko1324b6c2018-09-07 11:16:23 +020024
Radek Krejcic59bc972018-09-17 16:13:06 +020025const char *const ly_stmt_list[] = {
26 [YANG_ACTION] = "action",
27 [YANG_ANYDATA] = "anydata",
28 [YANG_ANYXML] = "anyxml",
29 [YANG_ARGUMENT] = "argument",
30 [YANG_AUGMENT] = "augment",
31 [YANG_BASE] = "base",
32 [YANG_BELONGS_TO] = "belongs-to",
33 [YANG_BIT] = "bit",
34 [YANG_CASE] = "case",
35 [YANG_CHOICE] = "choice",
36 [YANG_CONFIG] = "config",
37 [YANG_CONTACT] = "contact",
38 [YANG_CONTAINER] = "container",
39 [YANG_CUSTOM] = "<extension-instance>",
40 [YANG_DEFAULT] = "default",
41 [YANG_DESCRIPTION] = "description",
42 [YANG_DEVIATE] = "deviate",
43 [YANG_DEVIATION] = "deviation",
44 [YANG_ENUM] = "enum",
45 [YANG_ERROR_APP_TAG] = "error-app-tag",
46 [YANG_ERROR_MESSAGE] = "error-message",
47 [YANG_EXTENSION] = "extension",
48 [YANG_FEATURE] = "feature",
49 [YANG_FRACTION_DIGITS] = "fraction-digits",
50 [YANG_GROUPING] = "grouping",
51 [YANG_IDENTITY] = "identitiy",
52 [YANG_IF_FEATURE] = "if-feature",
53 [YANG_IMPORT] = "import",
54 [YANG_INCLUDE] = "include",
55 [YANG_INPUT] = "input",
56 [YANG_KEY] = "key",
57 [YANG_LEAF] = "leaf",
58 [YANG_LEAF_LIST] = "leaf-list",
59 [YANG_LENGTH] = "length",
60 [YANG_LIST] = "list",
61 [YANG_MANDATORY] = "mandatory",
62 [YANG_MAX_ELEMENTS] = "max-elements",
63 [YANG_MIN_ELEMENTS] = "min-elements",
64 [YANG_MODIFIER] = "modifier",
65 [YANG_MODULE] = "module",
66 [YANG_MUST] = "must",
67 [YANG_NAMESPACE] = "namespace",
68 [YANG_NOTIFICATION] = "notification",
69 [YANG_ORDERED_BY] = "ordered-by",
70 [YANG_ORGANIZATION] = "organization",
71 [YANG_OUTPUT] = "output",
72 [YANG_PATH] = "path",
73 [YANG_PATTERN] = "pattern",
74 [YANG_POSITION] = "position",
75 [YANG_PREFIX] = "prefix",
76 [YANG_PRESENCE] = "presence",
77 [YANG_RANGE] = "range",
78 [YANG_REFERENCE] = "reference",
79 [YANG_REFINE] = "refine",
80 [YANG_REQUIRE_INSTANCE] = "require-instance",
81 [YANG_REVISION] = "revision",
82 [YANG_REVISION_DATE] = "revision-date",
83 [YANG_RPC] = "rpc",
84 [YANG_STATUS] = "status",
85 [YANG_SUBMODULE] = "submodule",
86 [YANG_TYPE] = "type",
87 [YANG_TYPEDEF] = "typedef",
88 [YANG_UNIQUE] = "unique",
89 [YANG_UNITS] = "units",
90 [YANG_USES] = "uses",
91 [YANG_VALUE] = "value",
92 [YANG_WHEN] = "when",
93 [YANG_YANG_VERSION] = "yang-version",
94 [YANG_YIN_ELEMENT] = "yin-element",
95 [YANG_SEMICOLON] = ";",
96 [YANG_LEFT_BRACE] = "{",
97 [YANG_RIGHT_BRACE] = "}",
98};
99
100const char *const lyext_substmt_list[] = {
101 [LYEXT_SUBSTMT_ARGUMENT] = "argument",
102 [LYEXT_SUBSTMT_BASE] = "base",
103 [LYEXT_SUBSTMT_BELONGSTO] = "belongs-to",
104 [LYEXT_SUBSTMT_CONTACT] = "contact",
105 [LYEXT_SUBSTMT_DEFAULT] = "default",
106 [LYEXT_SUBSTMT_DESCRIPTION] = "description",
107 [LYEXT_SUBSTMT_ERRTAG] = "error-app-tag",
108 [LYEXT_SUBSTMT_ERRMSG] = "error-message",
109 [LYEXT_SUBSTMT_KEY] = "key",
110 [LYEXT_SUBSTMT_NAMESPACE] = "namespace",
111 [LYEXT_SUBSTMT_ORGANIZATION] = "organization",
112 [LYEXT_SUBSTMT_PATH] = "path",
113 [LYEXT_SUBSTMT_PREFIX] = "prefix",
114 [LYEXT_SUBSTMT_PRESENCE] = "presence",
115 [LYEXT_SUBSTMT_REFERENCE] = "reference",
116 [LYEXT_SUBSTMT_REVISIONDATE] = "revision-date",
117 [LYEXT_SUBSTMT_UNITS] = "units",
118 [LYEXT_SUBSTMT_VALUE] = "value",
119 [LYEXT_SUBSTMT_VERSION] = "yang-version",
120 [LYEXT_SUBSTMT_MODIFIER] = "modifier",
121 [LYEXT_SUBSTMT_REQINSTANCE] = "require-instance",
122 [LYEXT_SUBSTMT_YINELEM] = "yin-element",
123 [LYEXT_SUBSTMT_CONFIG] = "config",
124 [LYEXT_SUBSTMT_MANDATORY] = "mandatory",
125 [LYEXT_SUBSTMT_ORDEREDBY] = "ordered-by",
126 [LYEXT_SUBSTMT_STATUS] = "status",
127 [LYEXT_SUBSTMT_FRACDIGITS] = "fraction-digits",
128 [LYEXT_SUBSTMT_MAX] = "max-elements",
129 [LYEXT_SUBSTMT_MIN] = "min-elements",
130 [LYEXT_SUBSTMT_POSITION] = "position",
131 [LYEXT_SUBSTMT_UNIQUE] = "unique",
132 [LYEXT_SUBSTMT_IFFEATURE] = "if-feature",
133};
134
135const char *const ly_devmod_list[] = {
136 [LYS_DEV_NOT_SUPPORTED] = "not-supported",
137 [LYS_DEV_ADD] = "add",
138 [LYS_DEV_DELETE] = "delete",
139 [LYS_DEV_REPLACE] = "replace",
140};
141
Michal Vasko1324b6c2018-09-07 11:16:23 +0200142void *
143ly_realloc(void *ptr, size_t size)
144{
145 void *new_mem;
146
147 new_mem = realloc(ptr, size);
148 if (!new_mem) {
149 free(ptr);
150 }
151
152 return new_mem;
153}
Michal Vasko841d1a92018-09-07 15:40:31 +0200154
Radek Krejcib416be62018-10-01 14:51:45 +0200155LY_ERR
156ly_getutf8(const char **input, unsigned int *utf8_char, size_t *bytes_read)
157{
158 unsigned int c, len;
159 int aux;
160 int i;
161
162 c = (*input)[0];
163 LY_CHECK_RET(!c, LY_EINVAL);
164
165 if (!(c & 0x80)) {
166 /* one byte character */
167 len = 1;
168
169 if (c < 0x20 && c != 0x9 && c != 0xa && c != 0xd) {
170 return LY_EINVAL;
171 }
172 } else if ((c & 0xe0) == 0xc0) {
173 /* two bytes character */
174 len = 2;
175
176 aux = (*input)[1];
177 if ((aux & 0xc0) != 0x80) {
178 return LY_EINVAL;
179 }
180 c = ((c & 0x1f) << 6) | (aux & 0x3f);
181
182 if (c < 0x80) {
183 return LY_EINVAL;
184 }
185 } else if ((c & 0xf0) == 0xe0) {
186 /* three bytes character */
187 len = 3;
188
189 c &= 0x0f;
190 for (i = 1; i <= 2; i++) {
191 aux = (*input)[i];
192 if ((aux & 0xc0) != 0x80) {
193 return LY_EINVAL;
194 }
195
196 c = (c << 6) | (aux & 0x3f);
197 }
198
199 if (c < 0x800 || (c > 0xd7ff && c < 0xe000) || c > 0xfffd) {
200 return LY_EINVAL;
201 }
202 } else if ((c & 0xf8) == 0xf0) {
203 /* four bytes character */
204 len = 4;
205
206 c &= 0x07;
207 for (i = 1; i <= 3; i++) {
208 aux = (*input)[i];
209 if ((aux & 0xc0) != 0x80) {
210 return LY_EINVAL;
211 }
212
213 c = (c << 6) | (aux & 0x3f);
214 }
215
216 if (c < 0x1000 || c > 0x10ffff) {
217 return LY_EINVAL;
218 }
219 } else {
220 return LY_EINVAL;
221 }
222
223 (*utf8_char) = c;
224 (*input) += len;
225 if (bytes_read) {
226 (*bytes_read) = len;
227 }
228 return LY_SUCCESS;
229}
230
Radek Krejcid972c252018-09-25 13:23:39 +0200231size_t
232LY_VCODE_INSTREXP_len(const char *str)
233{
234 size_t len = 0;
235 if (!str) {
236 return len;
237 } else if (!str[0]) {
238 return 1;
239 }
240 for (len = 1; len < LY_VCODE_INSTREXP_MAXLEN && str[len]; ++len);
241 return len;
242}
243
Radek Krejcif345c012018-09-19 11:12:59 +0200244LY_ERR
Michal Vasko58257712018-09-12 11:11:38 +0200245lysp_check_date(struct ly_ctx *ctx, const char *date, int date_len, const char *stmt)
Michal Vasko841d1a92018-09-07 15:40:31 +0200246{
247 int i;
248 struct tm tm, tm_;
249 char *r;
250
Radek Krejcif345c012018-09-19 11:12:59 +0200251 LY_CHECK_ARG_RET(ctx, date, LY_EINVAL);
252 LY_CHECK_ERR_RET(date_len != LY_REV_SIZE - 1, LOGARG(ctx, date_len), LY_EINVAL);
Michal Vasko841d1a92018-09-07 15:40:31 +0200253
254 /* check format */
255 for (i = 0; i < date_len; i++) {
256 if (i == 4 || i == 7) {
257 if (date[i] != '-') {
258 goto error;
259 }
260 } else if (!isdigit(date[i])) {
261 goto error;
262 }
263 }
264
265 /* check content, e.g. 2018-02-31 */
266 memset(&tm, 0, sizeof tm);
267 r = strptime(date, "%Y-%m-%d", &tm);
268 if (!r || r != &date[LY_REV_SIZE - 1]) {
269 goto error;
270 }
271 memcpy(&tm_, &tm, sizeof tm);
272 mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
273 if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
274 /* checking days is enough, since other errors
275 * have been checked by strptime() */
276 goto error;
277 }
278
Radek Krejcif345c012018-09-19 11:12:59 +0200279 return LY_SUCCESS;
Michal Vasko841d1a92018-09-07 15:40:31 +0200280
281error:
Michal Vasko58257712018-09-12 11:11:38 +0200282 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, date_len, date, stmt);
Radek Krejcif345c012018-09-19 11:12:59 +0200283 return LY_EINVAL;
Michal Vasko841d1a92018-09-07 15:40:31 +0200284}