blob: 912ee13b38479db0d3d79e2fb6512b6381fa156b [file] [log] [blame]
/**
* @file common.c
* @author Michal Vasko <mvasko@cesnet.cz>
* @brief common internal definitions for libyang
*
* Copyright (c) 2018 CESNET, z.s.p.o.
*
* This source code is licensed under BSD 3-Clause License (the "License").
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "common.h"
#include "tree_schema.h"
const char *const ly_stmt_list[] = {
[YANG_ACTION] = "action",
[YANG_ANYDATA] = "anydata",
[YANG_ANYXML] = "anyxml",
[YANG_ARGUMENT] = "argument",
[YANG_AUGMENT] = "augment",
[YANG_BASE] = "base",
[YANG_BELONGS_TO] = "belongs-to",
[YANG_BIT] = "bit",
[YANG_CASE] = "case",
[YANG_CHOICE] = "choice",
[YANG_CONFIG] = "config",
[YANG_CONTACT] = "contact",
[YANG_CONTAINER] = "container",
[YANG_CUSTOM] = "<extension-instance>",
[YANG_DEFAULT] = "default",
[YANG_DESCRIPTION] = "description",
[YANG_DEVIATE] = "deviate",
[YANG_DEVIATION] = "deviation",
[YANG_ENUM] = "enum",
[YANG_ERROR_APP_TAG] = "error-app-tag",
[YANG_ERROR_MESSAGE] = "error-message",
[YANG_EXTENSION] = "extension",
[YANG_FEATURE] = "feature",
[YANG_FRACTION_DIGITS] = "fraction-digits",
[YANG_GROUPING] = "grouping",
[YANG_IDENTITY] = "identitiy",
[YANG_IF_FEATURE] = "if-feature",
[YANG_IMPORT] = "import",
[YANG_INCLUDE] = "include",
[YANG_INPUT] = "input",
[YANG_KEY] = "key",
[YANG_LEAF] = "leaf",
[YANG_LEAF_LIST] = "leaf-list",
[YANG_LENGTH] = "length",
[YANG_LIST] = "list",
[YANG_MANDATORY] = "mandatory",
[YANG_MAX_ELEMENTS] = "max-elements",
[YANG_MIN_ELEMENTS] = "min-elements",
[YANG_MODIFIER] = "modifier",
[YANG_MODULE] = "module",
[YANG_MUST] = "must",
[YANG_NAMESPACE] = "namespace",
[YANG_NOTIFICATION] = "notification",
[YANG_ORDERED_BY] = "ordered-by",
[YANG_ORGANIZATION] = "organization",
[YANG_OUTPUT] = "output",
[YANG_PATH] = "path",
[YANG_PATTERN] = "pattern",
[YANG_POSITION] = "position",
[YANG_PREFIX] = "prefix",
[YANG_PRESENCE] = "presence",
[YANG_RANGE] = "range",
[YANG_REFERENCE] = "reference",
[YANG_REFINE] = "refine",
[YANG_REQUIRE_INSTANCE] = "require-instance",
[YANG_REVISION] = "revision",
[YANG_REVISION_DATE] = "revision-date",
[YANG_RPC] = "rpc",
[YANG_STATUS] = "status",
[YANG_SUBMODULE] = "submodule",
[YANG_TYPE] = "type",
[YANG_TYPEDEF] = "typedef",
[YANG_UNIQUE] = "unique",
[YANG_UNITS] = "units",
[YANG_USES] = "uses",
[YANG_VALUE] = "value",
[YANG_WHEN] = "when",
[YANG_YANG_VERSION] = "yang-version",
[YANG_YIN_ELEMENT] = "yin-element",
[YANG_SEMICOLON] = ";",
[YANG_LEFT_BRACE] = "{",
[YANG_RIGHT_BRACE] = "}",
};
const char *const lyext_substmt_list[] = {
[LYEXT_SUBSTMT_ARGUMENT] = "argument",
[LYEXT_SUBSTMT_BASE] = "base",
[LYEXT_SUBSTMT_BELONGSTO] = "belongs-to",
[LYEXT_SUBSTMT_CONTACT] = "contact",
[LYEXT_SUBSTMT_DEFAULT] = "default",
[LYEXT_SUBSTMT_DESCRIPTION] = "description",
[LYEXT_SUBSTMT_ERRTAG] = "error-app-tag",
[LYEXT_SUBSTMT_ERRMSG] = "error-message",
[LYEXT_SUBSTMT_KEY] = "key",
[LYEXT_SUBSTMT_NAMESPACE] = "namespace",
[LYEXT_SUBSTMT_ORGANIZATION] = "organization",
[LYEXT_SUBSTMT_PATH] = "path",
[LYEXT_SUBSTMT_PREFIX] = "prefix",
[LYEXT_SUBSTMT_PRESENCE] = "presence",
[LYEXT_SUBSTMT_REFERENCE] = "reference",
[LYEXT_SUBSTMT_REVISIONDATE] = "revision-date",
[LYEXT_SUBSTMT_UNITS] = "units",
[LYEXT_SUBSTMT_VALUE] = "value",
[LYEXT_SUBSTMT_VERSION] = "yang-version",
[LYEXT_SUBSTMT_MODIFIER] = "modifier",
[LYEXT_SUBSTMT_REQINSTANCE] = "require-instance",
[LYEXT_SUBSTMT_YINELEM] = "yin-element",
[LYEXT_SUBSTMT_CONFIG] = "config",
[LYEXT_SUBSTMT_MANDATORY] = "mandatory",
[LYEXT_SUBSTMT_ORDEREDBY] = "ordered-by",
[LYEXT_SUBSTMT_STATUS] = "status",
[LYEXT_SUBSTMT_FRACDIGITS] = "fraction-digits",
[LYEXT_SUBSTMT_MAX] = "max-elements",
[LYEXT_SUBSTMT_MIN] = "min-elements",
[LYEXT_SUBSTMT_POSITION] = "position",
[LYEXT_SUBSTMT_UNIQUE] = "unique",
[LYEXT_SUBSTMT_IFFEATURE] = "if-feature",
};
const char *const ly_devmod_list[] = {
[LYS_DEV_NOT_SUPPORTED] = "not-supported",
[LYS_DEV_ADD] = "add",
[LYS_DEV_DELETE] = "delete",
[LYS_DEV_REPLACE] = "replace",
};
void *
ly_realloc(void *ptr, size_t size)
{
void *new_mem;
new_mem = realloc(ptr, size);
if (!new_mem) {
free(ptr);
}
return new_mem;
}
LY_ERR
ly_getutf8(const char **input, unsigned int *utf8_char, size_t *bytes_read)
{
unsigned int c, len;
int aux;
int i;
c = (*input)[0];
LY_CHECK_RET(!c, LY_EINVAL);
if (!(c & 0x80)) {
/* one byte character */
len = 1;
if (c < 0x20 && c != 0x9 && c != 0xa && c != 0xd) {
return LY_EINVAL;
}
} else if ((c & 0xe0) == 0xc0) {
/* two bytes character */
len = 2;
aux = (*input)[1];
if ((aux & 0xc0) != 0x80) {
return LY_EINVAL;
}
c = ((c & 0x1f) << 6) | (aux & 0x3f);
if (c < 0x80) {
return LY_EINVAL;
}
} else if ((c & 0xf0) == 0xe0) {
/* three bytes character */
len = 3;
c &= 0x0f;
for (i = 1; i <= 2; i++) {
aux = (*input)[i];
if ((aux & 0xc0) != 0x80) {
return LY_EINVAL;
}
c = (c << 6) | (aux & 0x3f);
}
if (c < 0x800 || (c > 0xd7ff && c < 0xe000) || c > 0xfffd) {
return LY_EINVAL;
}
} else if ((c & 0xf8) == 0xf0) {
/* four bytes character */
len = 4;
c &= 0x07;
for (i = 1; i <= 3; i++) {
aux = (*input)[i];
if ((aux & 0xc0) != 0x80) {
return LY_EINVAL;
}
c = (c << 6) | (aux & 0x3f);
}
if (c < 0x1000 || c > 0x10ffff) {
return LY_EINVAL;
}
} else {
return LY_EINVAL;
}
(*utf8_char) = c;
(*input) += len;
if (bytes_read) {
(*bytes_read) = len;
}
return LY_SUCCESS;
}
size_t
LY_VCODE_INSTREXP_len(const char *str)
{
size_t len = 0;
if (!str) {
return len;
} else if (!str[0]) {
return 1;
}
for (len = 1; len < LY_VCODE_INSTREXP_MAXLEN && str[len]; ++len);
return len;
}
LY_ERR
lysp_check_date(struct ly_ctx *ctx, const char *date, int date_len, const char *stmt)
{
int i;
struct tm tm, tm_;
char *r;
LY_CHECK_ARG_RET(ctx, date, LY_EINVAL);
LY_CHECK_ERR_RET(date_len != LY_REV_SIZE - 1, LOGARG(ctx, date_len), LY_EINVAL);
/* check format */
for (i = 0; i < date_len; i++) {
if (i == 4 || i == 7) {
if (date[i] != '-') {
goto error;
}
} else if (!isdigit(date[i])) {
goto error;
}
}
/* check content, e.g. 2018-02-31 */
memset(&tm, 0, sizeof tm);
r = strptime(date, "%Y-%m-%d", &tm);
if (!r || r != &date[LY_REV_SIZE - 1]) {
goto error;
}
memcpy(&tm_, &tm, sizeof tm);
mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
/* checking days is enough, since other errors
* have been checked by strptime() */
goto error;
}
return LY_SUCCESS;
error:
LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, date_len, date, stmt);
return LY_EINVAL;
}