BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file concat.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 * concat([string elem ...])
33 * concatv(list strings)
34 *
35 * Description:
36 * Concatenates zero or more strings. The result is available as the empty
37 * string variable. For concatv(), the strings are provided as a single
38 * list argument. For concat(), the strings are provided as arguments
39 * themselves.
40 */
41  
42 #include <misc/bsize.h>
43 #include <ncd/extra/NCDRefString.h>
44  
45 #include <ncd/module_common.h>
46  
47 #include <generated/blog_channel_ncd_concat.h>
48  
49 struct instance {
50 NCDModuleInst *i;
51 size_t length;
52 NCDRefString *refstr;
53 };
54  
55 static void new_concat_common (void *vo, NCDModuleInst *i, NCDValRef list)
56 {
57 ASSERT(NCDVal_IsList(list))
58 struct instance *o = vo;
59 o->i = i;
60  
61 size_t count = NCDVal_ListCount(list);
62 bsize_t result_size = bsize_fromsize(0);
63  
64 // check arguments and compute result size
65 for (size_t j = 0; j < count; j++) {
66 NCDValRef arg = NCDVal_ListGet(list, j);
67 if (!NCDVal_IsString(arg)) {
68 ModuleLog(i, BLOG_ERROR, "wrong type");
69 goto fail0;
70 }
71 result_size = bsize_add(result_size, bsize_fromsize(NCDVal_StringLength(arg)));
72 }
73 if (result_size.is_overflow) {
74 ModuleLog(i, BLOG_ERROR, "size overflow");
75 goto fail0;
76 }
77  
78 // allocate result
79 char *result_data;
80 o->refstr = NCDRefString_New(result_size.value, &result_data);
81 if (!o->refstr) {
82 ModuleLog(i, BLOG_ERROR, "NCDRefString_New failed");
83 goto fail0;
84 }
85  
86 // copy data to result
87 o->length = 0;
88 for (size_t j = 0; j < count; j++) {
89 NCDValRef arg = NCDVal_ListGet(list, j);
90 MemRef mr = NCDVal_StringMemRef(arg);
91 MemRef_CopyOut(mr, result_data + o->length);
92 o->length += mr.len;
93 }
94  
95 // signal up
96 NCDModuleInst_Backend_Up(o->i);
97 return;
98  
99 fail0:
100 NCDModuleInst_Backend_DeadError(i);
101 }
102  
103 static void func_new_concat (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
104 {
105 new_concat_common(vo, i, params->args);
106 }
107  
108 static void func_new_concatv (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
109 {
110 NCDValRef list_arg;
111 if (!NCDVal_ListRead(params->args, 1, &list_arg)) {
112 ModuleLog(i, BLOG_ERROR, "wrong arity");
113 goto fail0;
114 }
115 if (!NCDVal_IsList(list_arg)) {
116 ModuleLog(i, BLOG_ERROR, "wrong type");
117 goto fail0;
118 }
119  
120 new_concat_common(vo, i, list_arg);
121 return;
122  
123 fail0:
124 NCDModuleInst_Backend_DeadError(i);
125 }
126  
127 static void func_die (void *vo)
128 {
129 struct instance *o = vo;
130  
131 // release result reference
132 BRefTarget_Deref(NCDRefString_RefTarget(o->refstr));
133  
134 NCDModuleInst_Backend_Dead(o->i);
135 }
136  
137 static int func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
138 {
139 struct instance *o = vo;
140  
141 if (name == NCD_STRING_EMPTY) {
142 *out = NCDVal_NewExternalString(mem, NCDRefString_GetBuf(o->refstr), o->length, NCDRefString_RefTarget(o->refstr));
143 return 1;
144 }
145  
146 return 0;
147 }
148  
149 static struct NCDModule modules[] = {
150 {
151 .type = "concat",
152 .func_new2 = func_new_concat,
153 .func_die = func_die,
154 .func_getvar2 = func_getvar2,
155 .alloc_size = sizeof(struct instance)
156 }, {
157 .type = "concatv",
158 .func_new2 = func_new_concatv,
159 .func_die = func_die,
160 .func_getvar2 = func_getvar2,
161 .alloc_size = sizeof(struct instance)
162 }, {
163 .type = NULL
164 }
165 };
166  
167 const struct NCDModuleGroup ncdmodule_concat = {
168 .modules = modules
169 };