blob: 852b485bf6d58910ecd32922cef3ac850b96669a [file] [log] [blame]
Radek Krejci86d106e2018-10-18 09:53:19 +02001/**
2 * @file tree_schema_helpers.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Parsing and validation helper functions
5 *
6 * Copyright (c) 2015 - 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#define _XOPEN_SOURCE
15
16#include <ctype.h>
17#include <limits.h>
18#include <time.h>
19
20#include "libyang.h"
21#include "common.h"
22#include "tree_schema_internal.h"
23
24LY_ERR
25lysp_check_prefix(struct ly_parser_ctx *ctx, struct lysp_module *module, const char **value)
26{
27 struct lysp_import *i;
28
29 if (module->prefix && &module->prefix != value && !strcmp(module->prefix, *value)) {
30 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
31 "Prefix \"%s\" already used as module prefix.", *value);
32 return LY_EEXIST;
33 }
34 if (module->imports) {
35 LY_ARRAY_FOR(module->imports, struct lysp_import, i) {
36 if (i->prefix && &i->prefix != value && !strcmp(i->prefix, *value)) {
37 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
38 "Prefix \"%s\" already used to import \"%s\" module.", *value, i->name);
39 return LY_EEXIST;
40 }
41 }
42 }
43 return LY_SUCCESS;
44}
45
46LY_ERR
47lysp_check_date(struct ly_ctx *ctx, const char *date, int date_len, const char *stmt)
48{
49 int i;
50 struct tm tm, tm_;
51 char *r;
52
53 LY_CHECK_ARG_RET(ctx, date, LY_EINVAL);
54 LY_CHECK_ERR_RET(date_len != LY_REV_SIZE - 1, LOGARG(ctx, date_len), LY_EINVAL);
55
56 /* check format */
57 for (i = 0; i < date_len; i++) {
58 if (i == 4 || i == 7) {
59 if (date[i] != '-') {
60 goto error;
61 }
62 } else if (!isdigit(date[i])) {
63 goto error;
64 }
65 }
66
67 /* check content, e.g. 2018-02-31 */
68 memset(&tm, 0, sizeof tm);
69 r = strptime(date, "%Y-%m-%d", &tm);
70 if (!r || r != &date[LY_REV_SIZE - 1]) {
71 goto error;
72 }
73 memcpy(&tm_, &tm, sizeof tm);
74 mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
75 if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
76 /* checking days is enough, since other errors
77 * have been checked by strptime() */
78 goto error;
79 }
80
81 return LY_SUCCESS;
82
83error:
84 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, date_len, date, stmt);
85 return LY_EINVAL;
86}
87
88void
89lysp_sort_revisions(struct lysp_revision *revs)
90{
91 uint8_t i, r;
92 struct lysp_revision rev;
93
94 for (i = 1, r = 0; revs && i < LY_ARRAY_SIZE(revs); i++) {
95 if (strcmp(LY_ARRAY_INDEX(revs, i, struct lysp_revision)->rev,
96 LY_ARRAY_INDEX(revs, r, struct lysp_revision)->rev) > 0) {
97 r = i;
98 }
99 }
100
101 if (r) {
102 /* the newest revision is not on position 0, switch them */
103 memcpy(&rev, LY_ARRAY_INDEX(revs, 0), sizeof rev);
104 memcpy(LY_ARRAY_INDEX(revs, 0), LY_ARRAY_INDEX(revs, r), sizeof rev);
105 memcpy(LY_ARRAY_INDEX(revs, r), &rev, sizeof rev);
106 }
107}