BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file substr.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * Synopsis:
32 * substr(string str, string start [, string max])
33 *
34 * Description:
35 * Extracts a substring from a string. The result is the longest substring which
36 * starts at the offset 'start' bytes into 'str', and is no longer than 'max' bytes.
37 * If 'max' is not provided, the result is the substring from the offset 'start' to
38 * the end. In any case, 'start' must not be greater than the length of 'str'.
39 */
40  
41 #include <stddef.h>
42 #include <string.h>
43 #include <limits.h>
44  
45 #include <ncd/module_common.h>
46  
47 #include <generated/blog_channel_ncd_substr.h>
48  
49 struct substr_instance {
50 NCDModuleInst *i;
51 MemRef data;
52 int is_external;
53 BRefTarget *external_ref_target;
54 };
55  
56 static void substr_func_new_common (void *vo, NCDModuleInst *i, MemRef data, int is_external, BRefTarget *external_ref_target)
57 {
58 struct substr_instance *o = vo;
59 o->i = i;
60  
61 o->data = data;
62 o->is_external = is_external;
63 o->external_ref_target = external_ref_target;
64  
65 NCDModuleInst_Backend_Up(i);
66 }
67  
68 static int substr_func_getvar (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
69 {
70 struct substr_instance *o = vo;
71  
72 if (name == NCD_STRING_EMPTY) {
73 if (o->is_external) {
74 *out = NCDVal_NewExternalString(mem, o->data.ptr, o->data.len, o->external_ref_target);
75 } else {
76 *out = NCDVal_NewStringBinMr(mem, o->data);
77 }
78 return 1;
79 }
80  
81 return 0;
82 }
83  
84 static void func_new_substr (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
85 {
86 NCDValRef str_arg;
87 NCDValRef start_arg;
88 NCDValRef max_arg = NCDVal_NewInvalid();
89 if (!NCDVal_ListRead(params->args, 2, &str_arg, &start_arg) &&
90 !NCDVal_ListRead(params->args, 3, &str_arg, &start_arg, &max_arg)
91 ) {
92 ModuleLog(i, BLOG_ERROR, "wrong arity");
93 goto fail0;
94 }
95 if (!NCDVal_IsString(str_arg)) {
96 ModuleLog(i, BLOG_ERROR, "wrong type");
97 goto fail0;
98 }
99  
100 uintmax_t start;
101 if (!ncd_read_uintmax(start_arg, &start) || start > SIZE_MAX) {
102 ModuleLog(i, BLOG_ERROR, "wrong size");
103 goto fail0;
104 }
105  
106 uintmax_t max = SIZE_MAX;
107 if (!NCDVal_IsInvalid(max_arg)) {
108 if (!ncd_read_uintmax(max_arg, &max) || max > SIZE_MAX) {
109 ModuleLog(i, BLOG_ERROR, "wrong max");
110 goto fail0;
111 }
112 }
113  
114 MemRef str = NCDVal_StringMemRef(str_arg);
115  
116 if (start > str.len) {
117 ModuleLog(i, BLOG_ERROR, "start is beyond the end of the string");
118 goto fail0;
119 }
120  
121 const char *sub_data = str.ptr + start;
122 size_t sub_length = str.len - start;
123 if (sub_length > max) {
124 sub_length = max;
125 }
126  
127 int is_external = 0;
128 BRefTarget *external_ref_target = NULL;
129  
130 if (NCDVal_IsExternalString(str_arg)) {
131 is_external = 1;
132 external_ref_target = NCDVal_ExternalStringTarget(str_arg);
133 }
134 else if (NCDVal_IsIdString(str_arg)) {
135 is_external = 1;
136 }
137  
138 substr_func_new_common(vo, i, MemRef_Make(sub_data, sub_length), is_external, external_ref_target);
139 return;
140  
141 fail0:
142 NCDModuleInst_Backend_DeadError(i);
143 }
144  
145 static struct NCDModule modules[] = {
146 {
147 .type = "substr",
148 .func_new2 = func_new_substr,
149 .func_getvar2 = substr_func_getvar,
150 .alloc_size = sizeof(struct substr_instance)
151 }, {
152 .type = NULL
153 }
154 };
155  
156 const struct NCDModuleGroup ncdmodule_substr = {
157 .modules = modules
158 };