Merge "implemented decmatch (artf724241)"
[deliverable/titan.core.git] / core / Addfunc.cc
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Delic, Adam
13 * Feher, Csaba
14 * Forstner, Matyas
15 * Kovacs, Ferenc
16 * Raduly, Csaba
17 * Szabo, Janos Zoltan – initial implementation
18 * Zalanyi, Balazs Andor
19 *
20 ******************************************************************************/
21 #include "Addfunc.hh"
22
23 #include "../common/memory.h"
24 #include "../common/pattern.hh"
25 #include "Integer.hh"
26 #include "Float.hh"
27 #include "Bitstring.hh"
28 #include "Hexstring.hh"
29 #include "Octetstring.hh"
30 #include "Charstring.hh"
31 #include "Universal_charstring.hh"
32 #include "String_struct.hh"
33 #include "Logger.hh"
34 #include "Snapshot.hh"
35 #include "TitanLoggerApi.hh"
36
37 #include <openssl/bn.h>
38
39 #include <limits.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <regex.h>
45
46 #define ERRMSG_BUFSIZE 512
47
48 // table to reverse the hex digits within an octet
49 // input: ABCDEFGH, output: DCBAHGFE
50 static const unsigned char nibble_reverse_table[] =
51 {
52 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
53 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f,
54 0x80, 0x88, 0x84, 0x8c, 0x82, 0x8a, 0x86, 0x8e,
55 0x81, 0x89, 0x85, 0x8d, 0x83, 0x8b, 0x87, 0x8f,
56 0x40, 0x48, 0x44, 0x4c, 0x42, 0x4a, 0x46, 0x4e,
57 0x41, 0x49, 0x45, 0x4d, 0x43, 0x4b, 0x47, 0x4f,
58 0xc0, 0xc8, 0xc4, 0xcc, 0xc2, 0xca, 0xc6, 0xce,
59 0xc1, 0xc9, 0xc5, 0xcd, 0xc3, 0xcb, 0xc7, 0xcf,
60 0x20, 0x28, 0x24, 0x2c, 0x22, 0x2a, 0x26, 0x2e,
61 0x21, 0x29, 0x25, 0x2d, 0x23, 0x2b, 0x27, 0x2f,
62 0xa0, 0xa8, 0xa4, 0xac, 0xa2, 0xaa, 0xa6, 0xae,
63 0xa1, 0xa9, 0xa5, 0xad, 0xa3, 0xab, 0xa7, 0xaf,
64 0x60, 0x68, 0x64, 0x6c, 0x62, 0x6a, 0x66, 0x6e,
65 0x61, 0x69, 0x65, 0x6d, 0x63, 0x6b, 0x67, 0x6f,
66 0xe0, 0xe8, 0xe4, 0xec, 0xe2, 0xea, 0xe6, 0xee,
67 0xe1, 0xe9, 0xe5, 0xed, 0xe3, 0xeb, 0xe7, 0xef,
68 0x10, 0x18, 0x14, 0x1c, 0x12, 0x1a, 0x16, 0x1e,
69 0x11, 0x19, 0x15, 0x1d, 0x13, 0x1b, 0x17, 0x1f,
70 0x90, 0x98, 0x94, 0x9c, 0x92, 0x9a, 0x96, 0x9e,
71 0x91, 0x99, 0x95, 0x9d, 0x93, 0x9b, 0x97, 0x9f,
72 0x50, 0x58, 0x54, 0x5c, 0x52, 0x5a, 0x56, 0x5e,
73 0x51, 0x59, 0x55, 0x5d, 0x53, 0x5b, 0x57, 0x5f,
74 0xd0, 0xd8, 0xd4, 0xdc, 0xd2, 0xda, 0xd6, 0xde,
75 0xd1, 0xd9, 0xd5, 0xdd, 0xd3, 0xdb, 0xd7, 0xdf,
76 0x30, 0x38, 0x34, 0x3c, 0x32, 0x3a, 0x36, 0x3e,
77 0x31, 0x39, 0x35, 0x3d, 0x33, 0x3b, 0x37, 0x3f,
78 0xb0, 0xb8, 0xb4, 0xbc, 0xb2, 0xba, 0xb6, 0xbe,
79 0xb1, 0xb9, 0xb5, 0xbd, 0xb3, 0xbb, 0xb7, 0xbf,
80 0x70, 0x78, 0x74, 0x7c, 0x72, 0x7a, 0x76, 0x7e,
81 0x71, 0x79, 0x75, 0x7d, 0x73, 0x7b, 0x77, 0x7f,
82 0xf0, 0xf8, 0xf4, 0xfc, 0xf2, 0xfa, 0xf6, 0xfe,
83 0xf1, 0xf9, 0xf5, 0xfd, 0xf3, 0xfb, 0xf7, 0xff
84 };
85
86 // table to swap the hex digits within an octet
87 // input: ABCDEFGH, output: EFGHABCD
88 static const unsigned char nibble_swap_table[] =
89 {
90 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
91 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
92 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
93 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1,
94 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
95 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2,
96 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
97 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3,
98 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
99 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4,
100 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
101 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5,
102 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
103 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6,
104 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
105 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7,
106 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
107 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8,
108 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
109 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9,
110 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
111 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
112 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b,
113 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb,
114 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c,
115 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc,
116 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d,
117 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd,
118 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e,
119 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe,
120 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f,
121 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff
122 };
123
124 // table to reverse the bits within an octet
125 // input: ABCDEFGH, output: HGFEDCBA
126 static const unsigned char bit_reverse_table[] =
127 {
128 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
129 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
130 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
131 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
132 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
133 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
134 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
135 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
136 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
137 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
138 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
139 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
140 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
141 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
142 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
143 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
144 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
145 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
146 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
147 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
148 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
149 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
150 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
151 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
152 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
153 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
154 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
155 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
156 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
157 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
158 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
159 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
160 };
161
162 static const unsigned char UTF8_BOM[] = {0xef, 0xbb, 0xbf};
163 static const unsigned char UTF16BE_BOM[] = {0xfe, 0xff};
164 static const unsigned char UTF16LE_BOM[] = {0xff, 0xfe};
165 static const unsigned char UTF32BE_BOM[] = {0x00, 0x00, 0xfe, 0xff};
166 static const unsigned char UTF32LE_BOM[] = {0xff, 0xfe, 0x00, 0x00};
167
168 // Functions for internal purposes
169
170 unsigned char char_to_hexdigit(char c)
171 {
172 if (c >= '0' && c <= '9') return c - '0';
173 else if (c >= 'A' && c <= 'F') return c - 'A' + 10;
174 else if (c >= 'a' && c <= 'f') return c - 'a' + 10;
175 else return 0xFF;
176 }
177
178 char hexdigit_to_char(unsigned char hexdigit)
179 {
180 if (hexdigit < 10) return '0' + hexdigit;
181 else if (hexdigit < 16) return 'A' + hexdigit - 10;
182 else return '\0';
183 }
184
185 static boolean is_whitespace(char c)
186 {
187 switch (c) {
188 case ' ':
189 case '\t':
190 case '\r':
191 case '\n':
192 case '\v':
193 case '\f':
194 return TRUE;
195 default:
196 return FALSE;
197 }
198 }
199
200 static CharCoding::CharCodingType is_ascii ( const OCTETSTRING& ostr )
201 {
202 const unsigned char nonASCII = 1 << 7;// MSB is 1 in case of non ASCII character
203 CharCoding::CharCodingType ret = CharCoding::ASCII;
204 const unsigned char* strptr = (const unsigned char*)ostr;
205 for (int i = 0; i < ostr.lengthof(); ++i) {
206 if ( strptr[i] & nonASCII) {
207 ret = CharCoding::UNKNOWN;
208 break;
209 }
210 }
211 return ret;
212 }
213
214 static CharCoding::CharCodingType is_utf8 ( const OCTETSTRING& ostr )
215 {
216 const char MSB = 1 << 7; // MSB is 1 in case of non ASCII character
217 const char MSBmin1 = 1 << 6; // 0100 0000
218 int i = 0;
219 const unsigned char* strptr = (const unsigned char*)ostr;
220 // std::cout << "UTF-8 strptr" << strptr << std::endl;
221 while (ostr.lengthof() > i) {
222 if ( strptr[i] & MSB) { // non ASCII char
223 // std::cout << "UTF-8 strptr[" << i << "]: " << std::hex << (int)strptr[i] << std::endl;
224 char maskUTF8 = 1 << 6; // 111x xxxx shows how many additional bytes are there
225 if (!(strptr[i] & maskUTF8)) return CharCoding::UNKNOWN; // accepted 11xxx xxxx but received 10xx xxxx
226 unsigned int noofUTF8 = 0; // 11xx xxxxx -> 2 bytes, 111x xxxxx -> 3 bytes , 1111 xxxxx -> 4 bytes in UTF-8
227 while (strptr[i] & maskUTF8) {
228 ++noofUTF8;
229 maskUTF8 >>= 1; // shift right the mask
230 }
231 // the second and third (and so on) UTF-8 byte looks like 10xx xxxx
232 while (0 < noofUTF8 ) {
233 ++i;
234 //std::cout << "mask & strptr[" << i << "] " << std::hex << (int)strptr[i] << std::endl;
235 if (!(strptr[i] & MSB) || (strptr[i] & MSBmin1) || i >= ostr.lengthof()) { // if not like this: 10xx xxxx
236 return CharCoding::UNKNOWN;
237 }
238 --noofUTF8;
239 }
240 }
241 ++i;
242 }
243 return CharCoding::UTF_8;
244 }
245
246 // Additional predefined functions defined in Annex C of ES 101 873-1
247
248 // C.1 - int2char
249
250 CHARSTRING int2char(int value)
251 {
252 if (value < 0 || value > 127) TTCN_error("The argument of function "
253 "int2char() is %d, which is outside the allowed range 0 .. 127.",
254 value);
255 return CHARSTRING((char)value);
256 }
257
258 CHARSTRING int2char(const INTEGER& value)
259 {
260 value.must_bound("The argument of function int2char() is an unbound "
261 "integer value.");
262 const int_val_t& ivt = value.get_val();
263 if (ivt < 0 || ivt > 127) {
264 char *value_str = ivt.as_string();
265 TTCN_error("The argument of function int2char() is %s, "
266 "which is outside the allowed range 0 .. 127.", value_str);
267 Free(value_str);
268 }
269 return CHARSTRING((char)((int)value));
270 }
271
272 // C.2 - int2unichar
273
274 UNIVERSAL_CHARSTRING int2unichar(int value)
275 {
276 if (value < 0 || value > 2147483647) TTCN_error("The argument of function "
277 "int2unichar() is %d, which outside the allowed range 0 .. 2147483647.",
278 value);
279 return UNIVERSAL_CHARSTRING(value >> 24, (value >> 16) & 0xFF,
280 (value >> 8) & 0xFF, value & 0xFF);
281 }
282
283 UNIVERSAL_CHARSTRING int2unichar(const INTEGER& value)
284 {
285 value.must_bound("The argument of function int2unichar() is an unbound "
286 "integer value.");
287 const int_val_t& ivt = value.get_val();
288 if (ivt < 0 || ivt > 2147483647) {
289 char *value_str = ivt.as_string();
290 TTCN_error("The argument of function int2unichar() is %s, "
291 "which outside the allowed range 0 .. 2147483647.", value_str);
292 Free(value_str);
293 }
294 return int2unichar((int)value);
295 }
296
297 // C.3 - int2bit
298
299 BITSTRING int2bit(const INTEGER& value, int length)
300 {
301 value.must_bound("The first argument (value) of function int2bit() is "
302 "an unbound integer value.");
303 int_val_t tmp_value(value.get_val());
304 if (tmp_value < 0) {
305 char *value_str = tmp_value.as_string();
306 TTCN_error("The first argument (value) of function "
307 "int2bit() is a negative integer value: %s.", value_str);
308 Free(value_str);
309 }
310 if (length < 0) TTCN_error("The second argument (length) of function "
311 "int2bit() is a negative integer value: %d.", length);
312 BITSTRING ret_val(length);
313 unsigned char *bits_ptr = ret_val.val_ptr->bits_ptr;
314 // clearing all bits in the result
315 memset(bits_ptr, '\0', (length + 7) / 8);
316 // we are setting some bits to 1 so we may stop if there are no more 1 bits
317 // in the input
318 for (int i = length - 1; tmp_value != 0 && i >= 0; i--) {
319 if ((tmp_value & 1).get_val()) bits_ptr[i / 8] |= (1 << (i % 8));
320 tmp_value >>= 1;
321 }
322 if (tmp_value != 0) {
323 char *value_str = value.get_val().as_string(); // not tmp_value!
324 TTCN_error("The first argument of function int2bit(), which is %s, "
325 "does not fit in %d bit%s.", value_str, length,
326 length > 1 ? "s" :"");
327 Free(value_str);
328 }
329 return ret_val;
330 }
331
332 BITSTRING int2bit(int value, const INTEGER& length)
333 {
334 length.must_bound("The second argument (length) of function int2bit() is "
335 "an unbound integer value.");
336 return int2bit(INTEGER(value), (int)length);
337 }
338
339 BITSTRING int2bit(int value, int length)
340 {
341 return int2bit(INTEGER(value), length);
342 }
343
344 BITSTRING int2bit(const INTEGER& value, const INTEGER& length)
345 {
346 value.must_bound("The first argument (value) of function int2bit() is "
347 "an unbound integer value.");
348 length.must_bound("The second argument (length) of function int2bit() is "
349 "an unbound integer value.");
350 return int2bit(value, (int)length);
351 }
352
353 // C.4 - int2hex
354
355 HEXSTRING int2hex(const INTEGER& value, int length)
356 {
357 value.must_bound("The first argument (value) of function int2hex() is "
358 "an unbound integer value.");
359 int_val_t tmp_value(value.get_val());
360 if (value < 0) {
361 char *value_str = tmp_value.as_string();
362 TTCN_error("The first argument (value) of function int2hex() is a "
363 "negative integer value: %s.", value_str);
364 Free(value_str);
365 }
366 if (length < 0) TTCN_error("The second argument (length) of function "
367 "int2hex() is a negative integer value: %d.", length);
368 HEXSTRING ret_val(length);
369 unsigned char *nibbles_ptr = ret_val.val_ptr->nibbles_ptr;
370 // clearing the unused bits in the last octet if necessary
371 if (length % 2) nibbles_ptr[length / 2] = '\0';
372 for (int i = length - 1; i >= 0; i--) {
373 if (i % 2) nibbles_ptr[i / 2] = (tmp_value & 0xF).get_val() << 4;
374 else nibbles_ptr[i / 2] |= (tmp_value & 0xF).get_val();
375 tmp_value >>= 4;
376 }
377 if (tmp_value != 0) {
378 char *value_str = value.get_val().as_string(); // not tmp_value!
379 TTCN_error("The first argument of function int2hex(), which is %s, "
380 "does not fit in %d hexadecimal digit%s.", value_str, length,
381 length > 1 ? "s" :"");
382 Free(value_str); // ???
383 }
384 return ret_val;
385 }
386
387 HEXSTRING int2hex(int value, const INTEGER& length)
388 {
389 length.must_bound("The second argument (length) of function int2hex() is "
390 "an unbound integer value.");
391 return int2hex(INTEGER(value), (int)length);
392 }
393
394 HEXSTRING int2hex(int value, int length)
395 {
396 return int2hex(INTEGER(value), length);
397 }
398
399 HEXSTRING int2hex(const INTEGER& value, const INTEGER& length)
400 {
401 value.must_bound("The first argument (value) of function int2hex() is "
402 "an unbound integer value.");
403 length.must_bound("The second argument (length) of function int2hex() is "
404 "an unbound integer value.");
405 return int2hex(value, (int)length);
406 }
407
408 // C.5 - int2oct
409
410 OCTETSTRING int2oct(int value, int length)
411 {
412 if (value < 0) TTCN_error("The first argument (value) of function "
413 "int2oct() is a negative integer value: %d.", value);
414 if (length < 0) TTCN_error("The second argument (length) of function "
415 "int2oct() is a negative integer value: %d.", length);
416 OCTETSTRING ret_val(length);
417 unsigned char *octets_ptr = ret_val.val_ptr->octets_ptr;
418 unsigned int tmp_value = value;
419 for (int i = length - 1; i >= 0; i--) {
420 octets_ptr[i] = tmp_value & 0xFF;
421 tmp_value >>= 8;
422 }
423 if (tmp_value != 0) {
424 TTCN_error("The first argument of function int2oct(), which is %d, "
425 "does not fit in %d octet%s.", value, length,
426 length > 1 ? "s" :"");
427 }
428 return ret_val;
429 }
430
431 OCTETSTRING int2oct(int value, const INTEGER& length)
432 {
433 length.must_bound("The second argument (length) of function int2oct() is "
434 "an unbound integer value.");
435 return int2oct(value, (int)length);
436 }
437
438 OCTETSTRING int2oct(const INTEGER& value, int length)
439 {
440 value.must_bound("The first argument (value) of function int2oct() is "
441 "an unbound integer value.");
442 const int_val_t& value_int = value.get_val();
443 char *tmp_str = value_int.as_string();
444 CHARSTRING value_str(tmp_str);
445 Free(tmp_str);
446 if (value_int.is_native()) {
447 return int2oct((int)value, length);
448 } else {
449 if (value_int < 0) TTCN_error("The first argument (value) of function "
450 "int2oct() is a negative integer value: %s.",
451 (const char *)value_str);
452 if (length < 0) TTCN_error("The second argument (length) of function "
453 "int2oct() is a negative integer value: %d.", length);
454 OCTETSTRING ret_val(length);
455 unsigned char *octets_ptr = ret_val.val_ptr->octets_ptr;
456 BIGNUM *value_tmp = BN_dup(value_int.get_val_openssl());
457 int bytes = BN_num_bytes(value_tmp);
458 if (bytes > length) {
459 BN_free(value_tmp);
460 TTCN_error("The first argument of function int2oct(), which is %s, "
461 "does not fit in %d octet%s.", (const char *)value_str, length,
462 length > 1 ? "s" : "");
463 } else {
464 unsigned char* tmp = (unsigned char*)Malloc(bytes * sizeof(unsigned char));
465 BN_bn2bin(value_tmp, tmp);
466 for (int i = length - 1; i >= 0; i--) {
467 if (bytes-length+i >= 0) {
468 octets_ptr[i] = tmp[bytes-length+i] & 0xff;
469 }
470 else { // we used up all of the bignum; zero the beginning and quit
471 memset(octets_ptr, 0, i+1);
472 break;
473 }
474 }
475 BN_free(value_tmp);
476 Free(tmp);
477 return ret_val;
478 }
479 }
480 }
481
482 OCTETSTRING int2oct(const INTEGER& value, const INTEGER& length)
483 {
484 value.must_bound("The first argument (value) of function int2oct() is an "
485 "unbound integer value.");
486 length.must_bound("The second argument (length) of function int2oct() is "
487 "an unbound integer value.");
488 const int_val_t& value_int = value.get_val();
489 if (value_int.is_native()) return int2oct(value_int.get_val(), (int)length);
490 return int2oct(value, (int)length);
491 }
492
493 // C.6 - int2str
494
495 CHARSTRING int2str(int value)
496 {
497 char str_buf[64];
498 int str_len = snprintf(str_buf, sizeof(str_buf), "%d", value);
499 if (str_len < 0 || str_len >= (int)sizeof(str_buf)) {
500 TTCN_error("Internal error: system call snprintf() returned "
501 "unexpected status code %d when converting value %d in function "
502 "int2str().", str_len, value);
503 }
504 return CHARSTRING(str_len, str_buf);
505 }
506
507 CHARSTRING int2str(const INTEGER& value)
508 {
509 value.must_bound("The argument of function int2str() is an unbound "
510 "integer value.");
511 char *value_tmp = value.get_val().as_string();
512 CHARSTRING value_str(value_tmp);
513 Free(value_tmp);
514 return value_str;
515 }
516
517 // C.7 - int2float
518
519 double int2float(int value)
520 {
521 return (double)value;
522 }
523
524 double int2float(const INTEGER& value)
525 {
526 value.must_bound("The argument of function int2float() is an unbound "
527 "integer value.");
528 return value.get_val().to_real();
529 }
530
531 // C.8 - float2int
532
533 INTEGER float2int(double value)
534 {
535 if (value >= (double)INT_MIN && value <= (double)INT_MAX) return (int)value;
536 // DBL_MAX has 316 digits including the trailing 0-s on x86_64.
537 char buf[512] = "";
538 snprintf(buf, 511, "%f", value);
539 char *dot = strchr(buf, '.');
540 if (!dot) TTCN_error("Conversion of float value `%f' to integer failed", value);
541 else memset(dot, 0, sizeof(buf) - (dot - buf));
542 return INTEGER(buf);
543 }
544
545 INTEGER float2int(const FLOAT& value)
546 {
547 value.must_bound("The argument of function float2int() is an unbound float "
548 "value.");
549 return float2int((double)value);
550 }
551
552 // C.9 - char2int
553
554 int char2int(char value)
555 {
556 unsigned char uchar_value = value;
557 if (uchar_value > 127) TTCN_error("The argument of function "
558 "char2int() contains a character with character code %u, which is "
559 "outside the allowed range 0 .. 127.", uchar_value);
560 return uchar_value;
561 }
562
563 int char2int(const char *value)
564 {
565 if (value == NULL) value = "";
566 int value_length = strlen(value);
567 if (value_length != 1) TTCN_error("The length of the argument in function "
568 "char2int() must be exactly 1 instead of %d.", value_length);
569 return char2int(value[0]);
570 }
571
572 int char2int(const CHARSTRING& value)
573 {
574 value.must_bound("The argument of function char2int() is an unbound "
575 "charstring value.");
576 int value_length = value.lengthof();
577 if (value_length != 1) TTCN_error("The length of the argument in function "
578 "char2int() must be exactly 1 instead of %d.", value_length);
579 return char2int(((const char*)value)[0]);
580 }
581
582 int char2int(const CHARSTRING_ELEMENT& value)
583 {
584 value.must_bound("The argument of function char2int() is an unbound "
585 "charstring element.");
586 return char2int(value.get_char());
587 }
588
589 // C.10 - char2oct
590
591 OCTETSTRING char2oct(const char *value)
592 {
593 if (value == NULL) return OCTETSTRING(0, NULL);
594 else return OCTETSTRING(strlen(value), (const unsigned char*)value);
595 }
596
597 OCTETSTRING char2oct(const CHARSTRING& value)
598 {
599 value.must_bound("The argument of function char2oct() is an unbound "
600 "charstring value.");
601 return OCTETSTRING(value.lengthof(),
602 (const unsigned char*)(const char*)value);
603 }
604
605 OCTETSTRING char2oct(const CHARSTRING_ELEMENT& value)
606 {
607 value.must_bound("The argument of function char2oct() is an unbound "
608 "charstring element.");
609 unsigned char octet = value.get_char();
610 return OCTETSTRING(1, &octet);
611 }
612
613 // C.11 - unichar2int
614
615 int unichar2int(const universal_char& value)
616 {
617 if (value.uc_group > 127) TTCN_error("The argument of function "
618 "unichar2int() is the invalid quadruple char(%u, %u, %u, %u), the "
619 "first number of which is outside the allowed range 0 .. 127.",
620 value.uc_group, value.uc_plane, value.uc_row, value.uc_cell);
621 int result = (value.uc_group << 24) | (value.uc_plane << 16) |
622 (value.uc_row << 8) | value.uc_cell;
623 return result;
624 }
625
626 int unichar2int(const UNIVERSAL_CHARSTRING& value)
627 {
628 value.must_bound("The argument of function unichar2int() is an unbound "
629 "universal charstring value.");
630 int value_length = value.lengthof();
631 if (value_length != 1) TTCN_error("The length of the argument in function "
632 "unichar2int() must be exactly 1 instead of %d.", value_length);
633 return unichar2int(((const universal_char*)value)[0]);
634 }
635
636 int unichar2int(const UNIVERSAL_CHARSTRING_ELEMENT& value)
637 {
638 value.must_bound("The argument of function unichar2int() is an unbound "
639 "universal charstring element.");
640 return unichar2int(value.get_uchar());
641 }
642
643 // C.12 - bit2int
644
645 INTEGER bit2int(const BITSTRING& value)
646 {
647 value.must_bound("The argument of function bit2int() is an unbound "
648 "bitstring value.");
649 int n_bits = value.lengthof();
650 const unsigned char *bit_ptr = (const unsigned char *)value;
651 // skip the leading zero bits
652 int start_index;
653 for (start_index = 0; start_index < n_bits; start_index++)
654 if (bit_ptr[start_index / 8] & (1 << (start_index % 8))) break;
655 // do the conversion
656 int_val_t ret_val((RInt)0);
657 for (int i = start_index; i < n_bits; i++) {
658 ret_val <<= 1;
659 if (bit_ptr[i / 8] & (1 << (i % 8))) ret_val += 1;
660 }
661 if (ret_val.is_native()) return INTEGER(ret_val.get_val());
662 else return INTEGER(BN_dup(ret_val.get_val_openssl()));
663 }
664
665 INTEGER bit2int(const BITSTRING_ELEMENT& value)
666 {
667 value.must_bound("The argument of function bit2int() is an unbound "
668 "bitstring element.");
669 return INTEGER(value.get_bit() ? 1 : 0);
670 }
671
672 // C.13 - bit2hex
673
674 HEXSTRING bit2hex(const BITSTRING& value)
675 {
676 value.must_bound("The argument of function bit2hex() is an unbound "
677 "bitstring value.");
678 int n_bits = value.lengthof();
679 int n_nibbles = (n_bits + 3) / 4;
680 int padding_bits = 4 * n_nibbles - n_bits;
681 const unsigned char *bits_ptr = (const unsigned char *)value;
682 HEXSTRING ret_val(n_nibbles);
683 unsigned char *nibbles_ptr = ret_val.val_ptr->nibbles_ptr;
684 memset(nibbles_ptr, '\0', (n_nibbles + 1) / 2);
685 for (int i = 0; i < n_bits; i++) {
686 if (bits_ptr[i / 8] & (1 << (i % 8))) {
687 nibbles_ptr[(i + padding_bits) / 8] |= 0x80 >>
688 ((i + padding_bits + 4) % 8);
689 }
690 }
691 return ret_val;
692 }
693
694 HEXSTRING bit2hex(const BITSTRING_ELEMENT& value)
695 {
696 value.must_bound("The argument of function bit2hex() is an unbound "
697 "bitstring element.");
698 unsigned char nibble = value.get_bit() ? 0x01 : 0x00;
699 return HEXSTRING(1, &nibble);
700 }
701
702 // C.14 - bit2oct
703
704 OCTETSTRING bit2oct(const BITSTRING& value)
705 {
706 value.must_bound("The argument of function bit2oct() is an unbound "
707 "bitstring value.");
708 int n_bits = value.lengthof();
709 int n_octets = (n_bits + 7) / 8;
710 int padding_bits = 8 * n_octets - n_bits;
711 const unsigned char *bits_ptr = (const unsigned char *)value;
712 OCTETSTRING ret_val(n_octets);
713 unsigned char *octets_ptr = ret_val.val_ptr->octets_ptr;
714 memset(octets_ptr, '\0', n_octets);
715 for (int i = 0; i < n_bits; i++) {
716 if (bits_ptr[i / 8] & (1 << (i % 8))) {
717 octets_ptr[(i + padding_bits) / 8] |= 0x80 >>
718 ((i + padding_bits) % 8);
719 }
720 }
721 return ret_val;
722 }
723
724 OCTETSTRING bit2oct(const BITSTRING_ELEMENT& value)
725 {
726 value.must_bound("The argument of function bit2oct() is an unbound "
727 "bitstring element.");
728 unsigned char octet = value.get_bit() ? 0x01 : 0x00;
729 return OCTETSTRING(1, &octet);
730 }
731
732 // C.15 - bit2str
733
734 CHARSTRING bit2str(const BITSTRING& value)
735 {
736 value.must_bound("The argument of function bit2str() is an unbound "
737 "bitstring value.");
738 int n_bits = value.lengthof();
739 const unsigned char *bits_ptr = (const unsigned char*)value;
740 CHARSTRING ret_val(n_bits);
741 char *chars_ptr = ret_val.val_ptr->chars_ptr;
742 for (int i = 0; i < n_bits; i++) {
743 if (bits_ptr[i / 8] & (1 << (i % 8))) chars_ptr[i] = '1';
744 else chars_ptr[i] = '0';
745 }
746 return ret_val;
747 }
748
749 CHARSTRING bit2str(const BITSTRING_ELEMENT& value)
750 {
751 value.must_bound("The argument of function bit2str() is an unbound "
752 "bitstring element.");
753 return CHARSTRING(value.get_bit() ? '1' : '0');
754 }
755
756 // C.16 - hex2int
757
758 INTEGER hex2int(const HEXSTRING& value)
759 {
760 value.must_bound("The argument of function hex2int() is an unbound "
761 "hexstring value.");
762 int n_nibbles = value.lengthof();
763 const unsigned char *nibble_ptr = (const unsigned char *)value;
764 // skip the leading zero hex digits
765 int start_index;
766 for (start_index = 0; start_index < n_nibbles; start_index++) {
767 unsigned char mask = start_index % 2 ? 0xF0 : 0x0F;
768 if (nibble_ptr[start_index / 2] & mask) break;
769 }
770 // do the conversion
771 int_val_t ret_val((RInt)0);
772 for (int i = start_index; i < n_nibbles; i++) {
773 ret_val <<= 4;
774 if (i % 2) ret_val += nibble_ptr[i / 2] >> 4;
775 else ret_val += nibble_ptr[i / 2] & 0x0F;
776 }
777 if (ret_val.is_native()) return INTEGER(ret_val.get_val());
778 else return INTEGER(BN_dup(ret_val.get_val_openssl()));
779 }
780
781 INTEGER hex2int(const HEXSTRING_ELEMENT& value)
782 {
783 value.must_bound("The argument of function hex2int() is an unbound "
784 "hexstring element.");
785 return INTEGER(value.get_nibble());
786 }
787
788 // C.17 - hex2bit
789
790 BITSTRING hex2bit(const HEXSTRING& value)
791 {
792 value.must_bound("The argument of function hex2bit() is an unbound "
793 "hexstring value.");
794 int n_nibbles = value.lengthof();
795 const unsigned char *nibbles_ptr = (const unsigned char *)value;
796 BITSTRING ret_val(4 * n_nibbles);
797 unsigned char *bits_ptr = ret_val.val_ptr->bits_ptr;
798 int n_octets = (n_nibbles + 1) / 2;
799 for (int i = 0; i < n_octets; i++) {
800 bits_ptr[i] = nibble_reverse_table[nibbles_ptr[i]];
801 }
802 ret_val.clear_unused_bits();
803 return ret_val;
804 }
805
806 BITSTRING hex2bit(const HEXSTRING_ELEMENT& value)
807 {
808 value.must_bound("The argument of function hex2bit() is an unbound "
809 "hexstring element.");
810 unsigned char bits = nibble_reverse_table[value.get_nibble()];
811 return BITSTRING(4, &bits);
812 }
813
814 // C.18 - hex2oct
815
816 OCTETSTRING hex2oct(const HEXSTRING& value)
817 {
818 value.must_bound("The argument of function hex2oct() is an unbound "
819 "hexstring value.");
820 int n_nibbles = value.lengthof();
821 int n_octets = (n_nibbles + 1) / 2;
822 int padding_nibbles = n_nibbles % 2;
823 const unsigned char *nibbles_ptr = (const unsigned char *)value;
824 OCTETSTRING ret_val(n_octets);
825 unsigned char *octets_ptr = ret_val.val_ptr->octets_ptr;
826 if (padding_nibbles > 0) octets_ptr[0] = 0;
827 for (int i = 0; i < n_nibbles; i++) {
828 unsigned char hexdigit;
829 if (i % 2) hexdigit = nibbles_ptr[i / 2] >> 4;
830 else hexdigit = nibbles_ptr[i / 2] & 0x0F;
831 if ((i + padding_nibbles) % 2)
832 octets_ptr[(i + padding_nibbles) / 2] |= hexdigit;
833 else octets_ptr[(i + padding_nibbles) / 2] = hexdigit << 4;
834 }
835 return ret_val;
836 }
837
838 OCTETSTRING hex2oct(const HEXSTRING_ELEMENT& value)
839 {
840 value.must_bound("The argument of function hex2oct() is an unbound "
841 "hexstring element.");
842 unsigned char octet = value.get_nibble();
843 return OCTETSTRING(1, &octet);
844 }
845
846 // C.19 - hex2str
847
848 CHARSTRING hex2str(const HEXSTRING& value)
849 {
850 value.must_bound("The argument of function hex2str() is an unbound "
851 "hexstring value.");
852 int n_nibbles = value.lengthof();
853 const unsigned char *nibbles_ptr = (const unsigned char *)value;
854 CHARSTRING ret_val(n_nibbles);
855 char *chars_ptr = ret_val.val_ptr->chars_ptr;
856 for (int i = 0; i < n_nibbles; i++) {
857 unsigned char hexdigit;
858 if (i % 2) hexdigit = nibbles_ptr[i / 2] >> 4;
859 else hexdigit = nibbles_ptr[i / 2] & 0x0F;
860 chars_ptr[i] = hexdigit_to_char(hexdigit);
861 }
862 return ret_val;
863 }
864
865 CHARSTRING hex2str(const HEXSTRING_ELEMENT& value)
866 {
867 value.must_bound("The argument of function hex2str() is an unbound "
868 "hexstring element.");
869 return CHARSTRING(hexdigit_to_char(value.get_nibble()));
870 }
871
872 // C.20 - oct2int
873
874 INTEGER oct2int(const OCTETSTRING& value)
875 {
876 value.must_bound("The argument of function oct2int() is an unbound "
877 "octetstring value.");
878 int n_octets = value.lengthof();
879 const unsigned char *octet_ptr = (const unsigned char *)value;
880 int start_index;
881 for (start_index = 0; start_index < n_octets; start_index++)
882 if (octet_ptr[start_index]) break;
883 int_val_t ret_val((RInt)0);
884 for (int i = start_index; i < n_octets; i++) {
885 ret_val <<= 8;
886 ret_val += octet_ptr[i];
887 }
888 if (ret_val.is_native()) return INTEGER(ret_val.get_val());
889 else return INTEGER(BN_dup(ret_val.get_val_openssl()));
890 }
891
892 INTEGER oct2int(const OCTETSTRING_ELEMENT& value)
893 {
894 value.must_bound("The argument of function oct2int() is an unbound "
895 "octetstring element.");
896 return INTEGER(value.get_octet());
897 }
898
899 // C.21 - oct2bit
900
901 BITSTRING oct2bit(const OCTETSTRING& value)
902 {
903 value.must_bound("The argument of function oct2bit() is an unbound "
904 "octetstring value.");
905 int n_octets = value.lengthof();
906 const unsigned char *octets_ptr = (const unsigned char *)value;
907 BITSTRING ret_val(8 * n_octets);
908 unsigned char *bits_ptr = ret_val.val_ptr->bits_ptr;
909 for (int i = 0; i < n_octets; i++) {
910 bits_ptr[i] = bit_reverse_table[octets_ptr[i]];
911 }
912 return ret_val;
913 }
914
915 BITSTRING oct2bit(const OCTETSTRING_ELEMENT& value)
916 {
917 value.must_bound("The argument of function oct2bit() is an unbound "
918 "octetstring element.");
919 unsigned char bits = bit_reverse_table[value.get_octet()];
920 return BITSTRING(8, &bits);
921 }
922
923 // C.22 - oct2hex
924
925 HEXSTRING oct2hex(const OCTETSTRING& value)
926 {
927 value.must_bound("The argument of function oct2hex() is an unbound "
928 "octetstring value.");
929 int n_octets = value.lengthof();
930 const unsigned char *octets_ptr = (const unsigned char *)value;
931 HEXSTRING ret_val(2 * n_octets);
932 unsigned char *nibbles_ptr = ret_val.val_ptr->nibbles_ptr;
933 for (int i = 0; i < n_octets; i++) {
934 nibbles_ptr[i] = nibble_swap_table[octets_ptr[i]];
935 }
936 return ret_val;
937 }
938
939 HEXSTRING oct2hex(const OCTETSTRING_ELEMENT& value)
940 {
941 value.must_bound("The argument of function oct2hex() is an unbound "
942 "octetstring element.");
943 unsigned char nibbles = nibble_swap_table[value.get_octet()];
944 return HEXSTRING(2, &nibbles);
945 }
946
947 // C.23 - oct2str
948
949 CHARSTRING oct2str(const OCTETSTRING& value)
950 {
951 value.must_bound("The argument of function oct2str() is an unbound "
952 "octetstring value.");
953 int n_octets = value.lengthof();
954 const unsigned char *octets_ptr = (const unsigned char *)value;
955 CHARSTRING ret_val(2 * n_octets);
956 char *chars_ptr = ret_val.val_ptr->chars_ptr;
957 for (int i = 0; i < n_octets; i++) {
958 chars_ptr[2 * i] = hexdigit_to_char(octets_ptr[i] >> 4);
959 chars_ptr[2 * i + 1] = hexdigit_to_char(octets_ptr[i] & 0x0F);
960 }
961 return ret_val;
962 }
963
964 CHARSTRING oct2str(const OCTETSTRING_ELEMENT& value)
965 {
966 value.must_bound("The argument of function oct2str() is an unbound "
967 "octetstring element.");
968 unsigned char octet = value.get_octet();
969 char result[2];
970 result[0] = hexdigit_to_char(octet >> 4);
971 result[1] = hexdigit_to_char(octet & 0x0F);
972 return CHARSTRING(2, result);
973 }
974
975 // C.24 - oct2char
976
977 CHARSTRING oct2char(const OCTETSTRING& value)
978 {
979 value.must_bound("The argument of function oct2char() is an unbound "
980 "octetstring value.");
981 int value_length = value.lengthof();
982 const unsigned char *octets_ptr = (const unsigned char*)value;
983 for (int i = 0; i < value_length; i++) {
984 unsigned char octet = octets_ptr[i];
985 if (octet > 127) TTCN_error("The argument of function oct2char() "
986 "contains octet %02X at index %d, which is outside the allowed "
987 "range 00 .. 7F.", octet, i);
988 }
989 return CHARSTRING(value_length, (const char*)octets_ptr);
990 }
991
992 CHARSTRING oct2char(const OCTETSTRING_ELEMENT& value)
993 {
994 value.must_bound("The argument of function oct2char() is an unbound "
995 "octetstring element.");
996 unsigned char octet = value.get_octet();
997 if (octet > 127) TTCN_error("The argument of function oct2char() "
998 "contains the octet %02X, which is outside the allowed range 00 .. 7F.",
999 octet);
1000 return CHARSTRING((char)octet);
1001 }
1002
1003 UNIVERSAL_CHARSTRING oct2unichar(const OCTETSTRING& invalue)
1004 {
1005 // default encoding is UTF-8
1006 UNIVERSAL_CHARSTRING ucstr;
1007 TTCN_EncDec::error_behavior_t err_behavior = TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR);
1008 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, TTCN_EncDec::EB_ERROR);
1009 ucstr.decode_utf8(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF_8, true);
1010 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, err_behavior);
1011 return ucstr;
1012 }
1013
1014 UNIVERSAL_CHARSTRING oct2unichar(const OCTETSTRING& invalue,
1015 const CHARSTRING& string_encoding)
1016 {
1017 UNIVERSAL_CHARSTRING ucstr;
1018 TTCN_EncDec::error_behavior_t err_behavior = TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR);
1019 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, TTCN_EncDec::EB_ERROR);
1020 if ("UTF-8" == string_encoding) {
1021 ucstr.decode_utf8(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF_8, true);
1022 }
1023 else if ("UTF-16" == string_encoding) {
1024 ucstr.decode_utf16(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF16);
1025 }
1026 else if ("UTF-16BE" == string_encoding) {
1027 ucstr.decode_utf16(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF16BE);
1028 }
1029 else if ("UTF-16LE" == string_encoding) {
1030 ucstr.decode_utf16(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF16LE);
1031 }
1032 else if ("UTF-32" == string_encoding) {
1033 ucstr.decode_utf32(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF32);
1034 }
1035 else if ("UTF-32BE" == string_encoding) {
1036 ucstr.decode_utf32(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF32BE);
1037 }
1038 else if ("UTF-32LE" == string_encoding) {
1039 ucstr.decode_utf32(invalue.lengthof(), (const unsigned char *)invalue, CharCoding::UTF32LE);
1040 }
1041 else { TTCN_error("oct2unichar: Invalid parameter: %s", (const char*)string_encoding);
1042 }
1043 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, err_behavior);
1044 return ucstr;
1045 }
1046
1047 // C.25 - str2int
1048
1049 INTEGER str2int(const char *value)
1050 {
1051 return str2int(CHARSTRING(value));
1052 }
1053
1054 INTEGER str2int(const CHARSTRING& value)
1055 {
1056 value.must_bound("The argument of function str2int() is an unbound "
1057 "charstring value.");
1058 int value_len = value.lengthof();
1059 if (value_len == 0) TTCN_error("The argument of function str2int() is an "
1060 "empty string, which does not represent a valid integer value.");
1061 const char *value_str = value;
1062 enum { S_INITIAL, S_FIRST, S_ZERO, S_MORE, S_END, S_ERR } state = S_INITIAL;
1063 // state: expected characters
1064 // S_INITIAL: +, -, first digit, leading whitespace
1065 // S_FIRST: first digit
1066 // S_ZERO, S_MORE: more digit(s), trailing whitespace
1067 // S_END: trailing whitespace
1068 // S_ERR: error was found, stop
1069 boolean leading_ws = FALSE, leading_zero = FALSE;
1070 for (int i = 0; i < value_len; i++) {
1071 char c = value_str[i];
1072 switch (state) {
1073 case S_INITIAL:
1074 if (c == '+' || c == '-') state = S_FIRST;
1075 else if (c == '0') state = S_ZERO;
1076 else if (c >= '1' && c <= '9') state = S_MORE;
1077 else if (is_whitespace(c)) leading_ws = TRUE;
1078 else state = S_ERR;
1079 break;
1080 case S_FIRST:
1081 if (c == '0') state = S_ZERO;
1082 else if (c >= '1' && c <= '9') state = S_MORE;
1083 else state = S_ERR;
1084 break;
1085 case S_ZERO:
1086 if (c >= '0' && c <= '9') {
1087 leading_zero = TRUE;
1088 state = S_MORE;
1089 } else if (is_whitespace(c)) state = S_END;
1090 else state = S_ERR;
1091 break;
1092 case S_MORE:
1093 if (c >= '0' && c <= '9') {}
1094 else if (is_whitespace(c)) state = S_END;
1095 else state = S_ERR;
1096 break;
1097 case S_END:
1098 if (!is_whitespace(c)) state = S_ERR;
1099 break;
1100 default:
1101 break;
1102 }
1103 if (state == S_ERR) {
1104 TTCN_error_begin("The argument of function str2int(), which is ");
1105 value.log();
1106 TTCN_Logger::log_event_str(", does not represent a valid integer "
1107 "value. Invalid character `");
1108 TTCN_Logger::log_char_escaped(c);
1109 TTCN_Logger::log_event("' was found at index %d.", i);
1110 TTCN_error_end();
1111 }
1112 }
1113 if (state != S_ZERO && state != S_MORE && state != S_END) {
1114 TTCN_error_begin("The argument of function str2int(), which is ");
1115 value.log();
1116 TTCN_Logger::log_event_str(", does not represent a valid integer "
1117 "value. Premature end of the string.");
1118 TTCN_error_end();
1119 }
1120 if (leading_ws) {
1121 TTCN_warning_begin("Leading whitespace was detected in the argument "
1122 "of function str2int(): ");
1123 value.log();
1124 TTCN_Logger::log_char('.');
1125 TTCN_warning_end();
1126 }
1127 if (leading_zero) {
1128 TTCN_warning_begin("Leading zero digit was detected in the argument "
1129 "of function str2int(): ");
1130 value.log();
1131 TTCN_Logger::log_char('.');
1132 TTCN_warning_end();
1133 }
1134 if (state == S_END) {
1135 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1136 "of function str2int(): ");
1137 value.log();
1138 TTCN_Logger::log_char('.');
1139 TTCN_warning_end();
1140 }
1141 return INTEGER(value_str);
1142 }
1143
1144 INTEGER str2int(const CHARSTRING_ELEMENT& value)
1145 {
1146 value.must_bound("The argument of function str2int() is an unbound "
1147 "charstring element.");
1148 char c = value.get_char();
1149 if (c < '0' || c > '9') {
1150 TTCN_error_begin("The argument of function str2int(), which is a "
1151 "charstring element containing character `");
1152 TTCN_Logger::log_char_escaped(c);
1153 TTCN_Logger::log_event_str("', does not represent a valid integer "
1154 "value.");
1155 TTCN_error_end();
1156 }
1157 return INTEGER(c - '0');
1158 }
1159
1160 // C.26 - str2oct
1161
1162 OCTETSTRING str2oct(const char *value)
1163 {
1164 if (value == NULL) return OCTETSTRING(0, NULL);
1165 else return str2oct(CHARSTRING(value));
1166 }
1167
1168 OCTETSTRING str2oct(const CHARSTRING& value)
1169 {
1170 value.must_bound("The argument of function str2oct() is an unbound "
1171 "charstring value.");
1172 int value_len = value.lengthof();
1173 if (value_len % 2) TTCN_error("The argument of function str2oct() must "
1174 "have even number of characters containing hexadecimal digits, but "
1175 "the length of the string is odd: %d.", value_len);
1176 OCTETSTRING ret_val(value_len / 2);
1177 unsigned char *octets_ptr = ret_val.val_ptr->octets_ptr;
1178 const char *chars_ptr = value;
1179 for (int i = 0; i < value_len; i++) {
1180 char c = chars_ptr[i];
1181 unsigned char hex_digit = char_to_hexdigit(c);
1182 if (hex_digit > 0x0F) {
1183 TTCN_error_begin("The argument of function str2oct() shall "
1184 "contain hexadecimal digits only, but character `");
1185 TTCN_Logger::log_char_escaped(c);
1186 TTCN_Logger::log_event("' was found at index %d.", i);
1187 TTCN_error_end();
1188 }
1189 if (i % 2) octets_ptr[i / 2] |= hex_digit;
1190 else octets_ptr[i / 2] = hex_digit << 4;
1191 }
1192 return ret_val;
1193 }
1194
1195 // C.27 - str2float
1196
1197 double str2float(const char *value)
1198 {
1199 return str2float(CHARSTRING(value));
1200 }
1201
1202 /*
1203 * leading zeros are allowed;
1204 * leading "+" sign before positive values is allowed;
1205 * "-0.0" is allowed;
1206 * no numbers after the dot in the decimal notation are allowed.
1207 */
1208 double str2float(const CHARSTRING& value)
1209 {
1210 value.must_bound("The argument of function str2float() is an unbound "
1211 "charstring value.");
1212 int value_len = value.lengthof();
1213 if (value_len == 0) TTCN_error("The argument of function str2float() is "
1214 "an empty string, which does not represent a valid float value.");
1215 const char *value_str = value;
1216 enum { S_INITIAL, S_FIRST_M, S_ZERO_M, S_MORE_M, S_FIRST_F, S_MORE_F,
1217 S_INITIAL_E, S_FIRST_E, S_ZERO_E, S_MORE_E, S_END, S_ERR }
1218 state = S_INITIAL;
1219 // state: expected characters
1220 // S_INITIAL: +, -, first digit of integer part in mantissa,
1221 // leading whitespace
1222 // S_FIRST_M: first digit of integer part in mantissa
1223 // S_ZERO_M, S_MORE_M: more digits of mantissa, decimal dot, E
1224 // S_FIRST_F: first digit of fraction
1225 // S_MORE_F: more digits of fraction, E, trailing whitespace
1226 // S_INITIAL_E: +, -, first digit of exponent
1227 // S_FIRST_E: first digit of exponent
1228 // S_ZERO_E, S_MORE_E: more digits of exponent, trailing whitespace
1229 // S_END: trailing whitespace
1230 // S_ERR: error was found, stop
1231 boolean leading_ws = FALSE, leading_zero = FALSE;
1232 for (int i = 0; i < value_len; i++) {
1233 char c = value_str[i];
1234 switch (state) {
1235 case S_INITIAL:
1236 if (c == '+' || c == '-') state = S_FIRST_M;
1237 else if (c == '0') state = S_ZERO_M;
1238 else if (c >= '1' && c <= '9') state = S_MORE_M;
1239 else if (is_whitespace(c)) leading_ws = TRUE;
1240 else state = S_ERR;
1241 break;
1242 case S_FIRST_M: // first mantissa digit
1243 if (c == '0') state = S_ZERO_M;
1244 else if (c >= '1' && c <= '9') state = S_MORE_M;
1245 else state = S_ERR;
1246 break;
1247 case S_ZERO_M: // leading mantissa zero
1248 if (c == '.') state = S_FIRST_F;
1249 else if (c == 'E' || c == 'e') state = S_INITIAL_E;
1250 else if (c >= '0' && c <= '9') {
1251 leading_zero = TRUE;
1252 state = S_MORE_M;
1253 } else state = S_ERR;
1254 break;
1255 case S_MORE_M:
1256 if (c == '.') state = S_FIRST_F;
1257 else if (c == 'E' || c == 'e') state = S_INITIAL_E;
1258 else if (c >= '0' && c <= '9') {}
1259 else state = S_ERR;
1260 break;
1261 case S_FIRST_F:
1262 if (c >= '0' && c <= '9') state = S_MORE_F;
1263 else state = S_ERR;
1264 break;
1265 case S_MORE_F:
1266 if (c == 'E' || c == 'e') state = S_INITIAL_E;
1267 else if (c >= '0' && c <= '9') {}
1268 else if (is_whitespace(c)) state = S_END;
1269 else state = S_ERR;
1270 break;
1271 case S_INITIAL_E:
1272 if (c == '+' || c == '-') state = S_FIRST_E;
1273 else if (c == '0') state = S_ZERO_E;
1274 else if (c >= '1' && c <= '9') state = S_MORE_E;
1275 else state = S_ERR;
1276 break;
1277 case S_FIRST_E:
1278 if (c == '0') state = S_ZERO_E;
1279 else if (c >= '1' && c <= '9') state = S_MORE_E;
1280 else state = S_ERR;
1281 break;
1282 case S_ZERO_E:
1283 if (c >= '0' && c <= '9') {
1284 leading_zero = TRUE;
1285 state = S_MORE_E;
1286 } else if (is_whitespace(c)) state = S_END;
1287 else state = S_ERR;
1288 break;
1289 case S_MORE_E:
1290 if (c >= '0' && c <= '9') {}
1291 else if (is_whitespace(c)) state = S_END;
1292 else state = S_ERR;
1293 break;
1294 case S_END:
1295 if (!is_whitespace(c)) state = S_ERR;
1296 break;
1297 default:
1298 break;
1299 }
1300 if (state == S_ERR) {
1301 TTCN_error_begin("The argument of function str2float(), which is ");
1302 value.log();
1303 TTCN_Logger::log_event_str(", does not represent a valid float "
1304 "value. Invalid character `");
1305 TTCN_Logger::log_char_escaped(c);
1306 TTCN_Logger::log_event("' was found at index %d.", i);
1307 TTCN_error_end();
1308 }
1309 }
1310 switch (state) {
1311 case S_MORE_F:
1312 case S_ZERO_E:
1313 case S_MORE_E:
1314 // OK, originally
1315 break;
1316 case S_ZERO_M:
1317 case S_MORE_M:
1318 // OK now (decimal dot missing after mantissa)
1319 break;
1320 case S_FIRST_F:
1321 // OK now (fraction part missing)
1322 break;
1323 default:
1324 TTCN_error_begin("The argument of function str2float(), which is ");
1325 value.log();
1326 TTCN_Logger::log_event_str(", does not represent a valid float value. "
1327 "Premature end of the string.");
1328 TTCN_error_end();
1329 break;
1330 }
1331 if (leading_ws) {
1332 TTCN_warning_begin("Leading whitespace was detected in the argument "
1333 "of function str2float(): ");
1334 value.log();
1335 TTCN_Logger::log_char('.');
1336 TTCN_warning_end();
1337 }
1338 if (leading_zero) {
1339 TTCN_warning_begin("Leading zero digit was detected in the argument "
1340 "of function str2float(): ");
1341 value.log();
1342 TTCN_Logger::log_char('.');
1343 TTCN_warning_end();
1344 }
1345 if (state == S_END) {
1346 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1347 "of function str2float(): ");
1348 value.log();
1349 TTCN_Logger::log_char('.');
1350 TTCN_warning_end();
1351 }
1352 return atof(value_str);
1353 }
1354
1355 // C.33 - regexp
1356
1357 CHARSTRING regexp(const CHARSTRING& instr, const CHARSTRING& expression,
1358 int groupno)
1359 {
1360 instr.must_bound("The first argument (instr) of function regexp() is an "
1361 "unbound charstring value.");
1362 expression.must_bound("The second argument (expression) of function "
1363 "regexp() is an unbound charstring value.");
1364 if (groupno < 0) TTCN_error("The third argument (groupno) of function "
1365 "regexp() is a negative integer value: %d.", groupno);
1366 int instr_len = instr.lengthof();
1367 const char *instr_str = instr;
1368 for (int i = 0; i < instr_len; i++) {
1369 if (instr_str[i] == '\0') {
1370 TTCN_warning_begin("The first argument (instr) of function regexp(), "
1371 "which is ");
1372 instr.log();
1373 TTCN_Logger::log_event(", contains a character with zero character code "
1374 "at index %d. The rest of the string will be ignored during matching.",
1375 i);
1376 TTCN_warning_end();
1377 break;
1378 }
1379 }
1380 int expression_len = expression.lengthof();
1381 const char *expression_str = expression;
1382 for (int i = 0; i < expression_len; i++) {
1383 if (expression_str[i] == '\0') {
1384 TTCN_warning_begin("The second argument (expression) of function "
1385 "regexp(), which is ");
1386 expression.log();
1387 TTCN_Logger::log_event(", contains a character with zero character code "
1388 "at index %d. The rest of the string will be ignored during matching.",
1389 i);
1390 TTCN_warning_end();
1391 break;
1392 }
1393 }
1394 char *posix_str = TTCN_pattern_to_regexp(expression_str);
1395 if (posix_str == NULL) {
1396 TTCN_error_begin("The second argument (expression) of function "
1397 "regexp(), which is ");
1398 expression.log();
1399 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1400 TTCN_error_end();
1401 }
1402 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED)) {
1403 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED);
1404 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1405 CHARSTRING_template(STRING_PATTERN, expression).log();
1406 TTCN_Logger::log_event_str(" is: ");
1407 CHARSTRING(posix_str).log();
1408 TTCN_Logger::end_event();
1409 }
1410 regex_t posix_regexp;
1411 int ret_val = regcomp(&posix_regexp, posix_str, REG_EXTENDED);
1412 Free(posix_str);
1413 if (ret_val != 0) {
1414 char msg[ERRMSG_BUFSIZE];
1415 regerror(ret_val, &posix_regexp, msg, sizeof(msg));
1416 regfree(&posix_regexp);
1417 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1418 "failed in function regexp() when trying to match with character "
1419 "pattern ");
1420 expression.log();
1421 TTCN_Logger::log_event(". Error message: %s.", msg);
1422 TTCN_error_end();
1423 }
1424 int re_nsub = posix_regexp.re_nsub;
1425 if (re_nsub <= 0) {
1426 regfree(&posix_regexp);
1427 TTCN_error_begin("The character pattern in the second argument "
1428 "(expression) of function regexp() does not contain any groups: ");
1429 expression.log();
1430 TTCN_Logger::log_char('.');
1431 TTCN_error_end();
1432 }
1433 if (groupno >= re_nsub) {
1434 regfree(&posix_regexp);
1435 TTCN_error("The third argument (groupno) of function regexp() is too "
1436 "large: The requested group index is %d, but the pattern contains only "
1437 "%d group%s.", groupno, re_nsub, re_nsub > 1 ? "s" : "");
1438 }
1439 size_t nmatch = groupno + 1;
1440 regmatch_t *pmatch = (regmatch_t*)Malloc((nmatch + 1) * sizeof(*pmatch));
1441 ret_val = regexec(&posix_regexp, instr, nmatch + 1, pmatch, 0);
1442 if (ret_val == 0) {
1443 int begin_index = pmatch[nmatch].rm_so, end_index = pmatch[nmatch].rm_eo;
1444 Free(pmatch);
1445 regfree(&posix_regexp);
1446 if (end_index > instr_len) TTCN_error("Internal error: The end index "
1447 "of the substring (%d) to be returned in function regexp() is greater "
1448 "than the length of the input string (%d).", end_index, instr_len);
1449 if (begin_index > end_index) TTCN_error("Internal error: The start index "
1450 "of the substring (%d) to be returned in function regexp() is greater "
1451 "than the end index (%d).", begin_index, end_index);
1452 return CHARSTRING(end_index - begin_index, instr_str + begin_index);
1453 } else {
1454 Free(pmatch);
1455 if (ret_val != REG_NOMATCH) {
1456 char msg[ERRMSG_BUFSIZE];
1457 regerror(ret_val, &posix_regexp, msg, ERRMSG_BUFSIZE);
1458 regfree(&posix_regexp);
1459 TTCN_error("Internal error: POSIX regular expression matching returned "
1460 "unexpected status code in function regexp(): %s.", msg);
1461 } else regfree(&posix_regexp);
1462 return CHARSTRING(0, NULL);
1463 }
1464 }
1465
1466 CHARSTRING regexp(const CHARSTRING& instr, const CHARSTRING& expression,
1467 const INTEGER& groupno)
1468 {
1469 groupno.must_bound("The third argument (groupno) of function regexp() is an "
1470 "unbound integer value.");
1471 return regexp(instr, expression, (int)groupno);
1472 }
1473
1474 /* Needed by regexp() */
1475 UNIVERSAL_CHARSTRING convert_from_pattern_form(char* str, int num) {
1476 if (num % 8 != 0)
1477 TTCN_error("Internal error: Cannot convert string from pattern form.");
1478
1479 unsigned char c1, c2;
1480 universal_char * const res = new universal_char[num/8];
1481 unsigned char* ptr = (unsigned char*)res;
1482 int index = 0;
1483 while (index < num) {
1484 for (int j = 0; j < 4; j++) {
1485 c1 = str[index++];
1486 c2 = str[index++];
1487 if (c1 >= 'A' && c1 <= 'P' && c2 >= 'A' && c2 <= 'P') {
1488 *(ptr++) = ((c1 - 'A') << 4) | (c2 - 'A');
1489 } else
1490 TTCN_error("Internal error: Cannot convert string containing illegal "
1491 "character.");
1492 }
1493 }
1494 UNIVERSAL_CHARSTRING retval(num / 8, res);
1495 delete[] res;
1496 return retval;
1497 }
1498
1499 UNIVERSAL_CHARSTRING regexp(const UNIVERSAL_CHARSTRING& instr,
1500 const UNIVERSAL_CHARSTRING* expression_val,
1501 const UNIVERSAL_CHARSTRING_template* expression_tmpl,
1502 int groupno)
1503 {
1504 if ( (expression_val && expression_tmpl) ||
1505 (!expression_val && !expression_tmpl) )
1506 TTCN_error("Internal error: regexp(): invalid parameters");
1507 instr.must_bound("The first argument (instr) of function regexp() is an "
1508 "unbound charstring value.");
1509 if (expression_val)
1510 expression_val->must_bound("The second argument (expression) of function "
1511 "regexp() is an unbound universal charstring value.");
1512 else {
1513 if (!expression_tmpl->is_bound())
1514 TTCN_error("The second argument (expression) of function "
1515 "regexp() is an unbound universal charstring template.");
1516 }
1517 if (groupno < 0) TTCN_error("The third argument (groupno) of function "
1518 "regexp() is a negative integer value: %d.", groupno);
1519
1520 int* user_groups = 0;
1521 CHARSTRING expression_str;
1522 if (expression_val)
1523 expression_str = expression_val->get_stringRepr_for_pattern();
1524 else
1525 expression_str = expression_tmpl->get_single_value();
1526 char *posix_str = TTCN_pattern_to_regexp_uni((const char*)expression_str,
1527 &user_groups);
1528 if (user_groups == 0) {
1529 Free(user_groups);
1530 Free(posix_str);
1531 TTCN_error("Cannot find any groups in the second argument of regexp().");
1532 }
1533 if (posix_str == NULL) {
1534 TTCN_error_begin("The second argument (expression) of function "
1535 "regexp(), which is ");
1536 if (expression_val) expression_val->log(); else expression_tmpl->log();
1537 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1538 TTCN_error_end();
1539 }
1540 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED)) {
1541 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED);
1542 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1543 CHARSTRING_template(STRING_PATTERN, expression_str).log();
1544 TTCN_Logger::log_event_str(" is: ");
1545 CHARSTRING(posix_str).log();
1546 TTCN_Logger::end_event();
1547 }
1548
1549 regex_t posix_regexp;
1550 int ret_val = regcomp(&posix_regexp, posix_str, REG_EXTENDED);
1551 Free(posix_str);
1552 if (ret_val != 0) {
1553 char msg[ERRMSG_BUFSIZE];
1554 regerror(ret_val, &posix_regexp, msg, sizeof(msg));
1555 regfree(&posix_regexp);
1556 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1557 "failed in function regexp() when trying to match with character "
1558 "pattern ");
1559 if (expression_val) expression_val->log(); else expression_tmpl->log();
1560 TTCN_Logger::log_event(". Error message: %s.", msg);
1561 TTCN_error_end();
1562 }
1563
1564 int re_nsub = user_groups[0];
1565
1566 if (posix_regexp.re_nsub <= 0) {
1567 regfree(&posix_regexp);
1568 TTCN_error_begin("The character pattern in the second argument "
1569 "(expression) of function regexp() does not contain any groups: ");
1570 if (expression_val) expression_val->log(); else expression_tmpl->log();
1571 TTCN_Logger::log_char('.');
1572 TTCN_error_end();
1573 }
1574 if (groupno >= re_nsub) {
1575 regfree(&posix_regexp);
1576 TTCN_error("The third argument (groupno) of function regexp() is too "
1577 "large: The requested group index is %d, but the pattern contains only "
1578 "%d group%s.", groupno, re_nsub, re_nsub > 1 ? "s" : "");
1579 }
1580 if (groupno > user_groups[0]) {
1581 printf(" user_groups: %d\n", user_groups[0]);
1582 TTCN_error("Error during parsing the pattern.");
1583 }
1584 size_t nmatch = (size_t)user_groups[groupno+1] + 1;
1585 regmatch_t *pmatch = (regmatch_t*)Malloc((nmatch + 1) * sizeof(*pmatch));
1586
1587 Free(user_groups);
1588
1589 char* instr_conv = instr.convert_to_regexp_form();
1590 int instr_len = instr.lengthof() * 8;
1591
1592 ret_val = regexec(&posix_regexp, instr_conv, nmatch + 1, pmatch, 0);
1593 if (ret_val == 0) {
1594 int begin_index = pmatch[nmatch].rm_so, end_index = pmatch[nmatch].rm_eo;
1595 Free(pmatch);
1596 regfree(&posix_regexp);
1597 if (end_index > instr_len) TTCN_error("Internal error: The end index "
1598 "of the substring (%d) to be returned in function regexp() is greater "
1599 "than the length of the input string (%d).", end_index, instr_len);
1600 if (begin_index > end_index) TTCN_error("Internal error: The start index "
1601 "of the substring (%d) to be returned in function regexp() is greater "
1602 "than the end index (%d).", begin_index, end_index);
1603 UNIVERSAL_CHARSTRING res = convert_from_pattern_form(
1604 instr_conv + begin_index, end_index - begin_index);
1605 Free(instr_conv);
1606 return res;
1607 } else {
1608 Free(instr_conv);
1609 Free(pmatch);
1610 if (ret_val != REG_NOMATCH) {
1611 char msg[ERRMSG_BUFSIZE];
1612 regerror(ret_val, &posix_regexp, msg, ERRMSG_BUFSIZE);
1613 regfree(&posix_regexp);
1614 TTCN_error("Internal error: POSIX regular expression matching returned "
1615 "unexpected status code in function regexp(): %s.", msg);
1616 } else regfree(&posix_regexp);
1617 return UNIVERSAL_CHARSTRING(0, (const char*)NULL);
1618 }
1619 }
1620
1621 UNIVERSAL_CHARSTRING regexp(const UNIVERSAL_CHARSTRING& instr,
1622 const UNIVERSAL_CHARSTRING& expression, int groupno)
1623 {
1624 return regexp(instr, &expression, NULL, groupno);
1625 }
1626
1627 UNIVERSAL_CHARSTRING regexp(const UNIVERSAL_CHARSTRING& instr,
1628 const UNIVERSAL_CHARSTRING& expression, const INTEGER& groupno)
1629 {
1630 groupno.must_bound("The third argument (groupno) of function regexp() is an "
1631 "unbound integer value.");
1632 return regexp(instr, expression, (int)groupno);
1633 }
1634
1635 // regexp() on templates
1636
1637 CHARSTRING regexp(const CHARSTRING_template& instr,
1638 const CHARSTRING_template& expression, int groupno)
1639 {
1640 if (!instr.is_value())
1641 TTCN_error("The first argument of function regexp() is a "
1642 "template with non-specific value.");
1643 if (expression.is_value())
1644 return regexp(instr.valueof(), expression.valueof(), groupno);
1645 // pattern matching to specific value
1646 if (expression.get_selection()==STRING_PATTERN)
1647 return regexp(instr.valueof(), expression.get_single_value(), groupno);
1648 TTCN_error("The second argument of function regexp() should be "
1649 "specific value or pattern matching template.");
1650 }
1651
1652 CHARSTRING regexp(const CHARSTRING_template& instr,
1653 const CHARSTRING_template& expression, const INTEGER& groupno)
1654 {
1655 groupno.must_bound("The third argument (groupno) of function regexp() is an "
1656 "unbound integer value.");
1657 return regexp(instr, expression, (int)groupno);
1658 }
1659
1660 UNIVERSAL_CHARSTRING regexp(const UNIVERSAL_CHARSTRING_template& instr,
1661 const UNIVERSAL_CHARSTRING_template& expression, int groupno)
1662 {
1663 if (!instr.is_value())
1664 TTCN_error("The first argument of function regexp() is a "
1665 "template with non-specific value.");
1666 if (expression.is_value())
1667 return regexp(instr.valueof(), expression.valueof(), groupno);
1668 // pattern matching to specific value
1669 if (expression.get_selection()==STRING_PATTERN)
1670 return regexp(instr.valueof(), NULL, &expression, groupno);
1671 TTCN_error("The second argument of function regexp() should be "
1672 "specific value or pattern matching template.");
1673 }
1674
1675 UNIVERSAL_CHARSTRING regexp(const UNIVERSAL_CHARSTRING_template& instr,
1676 const UNIVERSAL_CHARSTRING_template& expression, const INTEGER& groupno)
1677 {
1678 groupno.must_bound("The third argument (groupno) of function regexp() is an "
1679 "unbound integer value.");
1680 return regexp(instr, expression, (int)groupno);
1681 }
1682
1683 // C.34 - substr
1684
1685 void check_substr_arguments(int value_length, int idx,
1686 int returncount, const char *string_type, const char *element_name)
1687 {
1688 if (idx < 0) TTCN_error("The second argument (index) of function "
1689 "substr() is a negative integer value: %d.", idx);
1690 if (idx > value_length) TTCN_error("The second argument (index) of "
1691 "function substr(), which is %d, is greater than the length of the "
1692 "%s value: %d.", idx, string_type, value_length);
1693 if (returncount < 0) TTCN_error("The third argument (returncount) of "
1694 "function substr() is a negative integer value: %d.", returncount);
1695 if (idx + returncount > value_length) TTCN_error("The first argument of "
1696 "function substr(), the length of which is %d, does not have enough "
1697 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
1698 value_length, element_name, idx, returncount, element_name,
1699 returncount > 1 ? "s are" : " is",
1700 value_length - idx > 1 ? "are" : "is", value_length - idx);
1701 }
1702
1703 static void check_substr_arguments(int idx, int returncount,
1704 const char *string_type, const char *element_name)
1705 {
1706 if (idx < 0) TTCN_error("The second argument (index) of function "
1707 "substr() is a negative integer value: %d.", idx);
1708 if (idx > 1) TTCN_error("The second argument (index) of function "
1709 "substr(), which is %d, is greater than 1 (i.e. the length of the "
1710 "%s element).", idx, string_type);
1711 if (returncount < 0) TTCN_error("The third argument (returncount) of "
1712 "function substr() is a negative integer value: %d.", returncount);
1713 if (idx + returncount > 1) TTCN_error("The first argument of function "
1714 "substr(), which is a%s %s element, does not have enough %ss starting "
1715 "at index %d: %d %s%s needed, but there is only %d.",
1716 string_type[0] == 'o' ? "n" : "", string_type, element_name, idx,
1717 returncount, element_name, returncount > 1 ? "s are" : " is",
1718 1 - idx);
1719 }
1720
1721 BITSTRING substr(const BITSTRING& value, int idx, int returncount)
1722 {
1723 value.must_bound("The first argument (value) of function substr() "
1724 "is an unbound bitstring value.");
1725 check_substr_arguments(value.lengthof(), idx, returncount, "bitstring",
1726 "bit");
1727 if (idx % 8) {
1728 BITSTRING ret_val(returncount);
1729 for (int i = 0; i < returncount; i++) {
1730 ret_val.set_bit(i, value.get_bit(idx + i));
1731 }
1732 ret_val.clear_unused_bits();
1733 return ret_val;
1734 } else {
1735 return BITSTRING(returncount, (const unsigned char*)value + idx / 8);
1736 }
1737 }
1738
1739 BITSTRING substr(const BITSTRING& value, int idx, const INTEGER& returncount)
1740 {
1741 returncount.must_bound("The third argument (returncount) of function "
1742 "substr() is an unbound integer value.");
1743 return substr(value, idx, (int)returncount);
1744 }
1745
1746 BITSTRING substr(const BITSTRING& value, const INTEGER& idx, int returncount)
1747 {
1748 idx.must_bound("The second argument (index) of function substr() "
1749 "is an unbound integer value.");
1750 return substr(value, (int)idx, returncount);
1751 }
1752
1753 BITSTRING substr(const BITSTRING& value, const INTEGER& idx,
1754 const INTEGER& returncount)
1755 {
1756 idx.must_bound("The second argument (index) of function substr() is an "
1757 "unbound integer value.");
1758 returncount.must_bound("The third argument (returncount) of function "
1759 "substr() is an unbound integer value.");
1760 return substr(value, (int)idx, (int)returncount);
1761 }
1762
1763 BITSTRING substr(const BITSTRING_ELEMENT& value, int idx, int returncount)
1764 {
1765 value.must_bound("The first argument (value) of function substr() "
1766 "is an unbound bitstring element.");
1767 check_substr_arguments(idx, returncount, "bitstring", "bit");
1768 if (returncount == 0) return BITSTRING(0, NULL);
1769 else {
1770 unsigned char bit = value.get_bit() ? 0x01 : 0x00;
1771 return BITSTRING(1, &bit);
1772 }
1773 }
1774
1775 BITSTRING substr(const BITSTRING_ELEMENT& value, int idx,
1776 const INTEGER& returncount)
1777 {
1778 returncount.must_bound("The third argument (returncount) of function "
1779 "substr() is an unbound integer value.");
1780 return substr(value, idx, (int)returncount);
1781 }
1782
1783 BITSTRING substr(const BITSTRING_ELEMENT& value, const INTEGER& idx,
1784 int returncount)
1785 {
1786 idx.must_bound("The second argument (index) of function substr() "
1787 "is an unbound integer value.");
1788 return substr(value, (int)idx, returncount);
1789 }
1790
1791 BITSTRING substr(const BITSTRING_ELEMENT& value, const INTEGER& idx,
1792 const INTEGER& returncount)
1793 {
1794 idx.must_bound("The second argument (index) of function substr() is an "
1795 "unbound integer value.");
1796 returncount.must_bound("The third argument (returncount) of function "
1797 "substr() is an unbound integer value.");
1798 return substr(value, (int)idx, (int)returncount);
1799 }
1800
1801 HEXSTRING substr(const HEXSTRING& value, int idx, int returncount)
1802 {
1803 value.must_bound("The first argument (value) of function substr() "
1804 "is an unbound hexstring value.");
1805 check_substr_arguments(value.lengthof(), idx, returncount, "hexstring",
1806 "hexadecimal digit");
1807 const unsigned char *src_ptr = (const unsigned char*)value;
1808 if (idx % 2) {
1809 HEXSTRING ret_val(returncount);
1810 unsigned char *dst_ptr = ret_val.val_ptr->nibbles_ptr;
1811 for (int i = 0; i < returncount; i++) {
1812 if (i % 2) dst_ptr[i / 2] |= (src_ptr[(i + idx) / 2] & 0x0F) << 4;
1813 else dst_ptr[i / 2] = src_ptr[(i + idx) / 2] >> 4;
1814 }
1815 return ret_val;
1816 } else return HEXSTRING(returncount, src_ptr + idx / 2);
1817 }
1818
1819 HEXSTRING substr(const HEXSTRING& value, int idx, const INTEGER& returncount)
1820 {
1821 returncount.must_bound("The third argument (returncount) of function "
1822 "substr() is an unbound integer value.");
1823 return substr(value, idx, (int)returncount);
1824 }
1825
1826 HEXSTRING substr(const HEXSTRING& value, const INTEGER& idx, int returncount)
1827 {
1828 idx.must_bound("The second argument (index) of function substr() "
1829 "is an unbound integer value.");
1830 return substr(value, (int)idx, returncount);
1831 }
1832
1833 HEXSTRING substr(const HEXSTRING& value, const INTEGER& idx,
1834 const INTEGER& returncount)
1835 {
1836 idx.must_bound("The second argument (index) of function substr() is an "
1837 "unbound integer value.");
1838 returncount.must_bound("The third argument (returncount) of function "
1839 "substr() is an unbound integer value.");
1840 return substr(value, (int)idx, (int)returncount);
1841 }
1842
1843 HEXSTRING substr(const HEXSTRING_ELEMENT& value, int idx, int returncount)
1844 {
1845 value.must_bound("The first argument (value) of function substr() "
1846 "is an unbound hexstring element.");
1847 check_substr_arguments(idx, returncount, "hexstring",
1848 "hexadecimal digit");
1849 if (returncount == 0) return HEXSTRING(0, NULL);
1850 else {
1851 unsigned char nibble = value.get_nibble();
1852 return HEXSTRING(1, &nibble);
1853 }
1854 }
1855
1856 HEXSTRING substr(const HEXSTRING_ELEMENT& value, int idx,
1857 const INTEGER& returncount)
1858 {
1859 returncount.must_bound("The third argument (returncount) of function "
1860 "substr() is an unbound integer value.");
1861 return substr(value, idx, (int)returncount);
1862 }
1863
1864 HEXSTRING substr(const HEXSTRING_ELEMENT& value, const INTEGER& idx,
1865 int returncount)
1866 {
1867 idx.must_bound("The second argument (index) of function substr() "
1868 "is an unbound integer value.");
1869 return substr(value, (int)idx, returncount);
1870 }
1871
1872 HEXSTRING substr(const HEXSTRING_ELEMENT& value, const INTEGER& idx,
1873 const INTEGER& returncount)
1874 {
1875 idx.must_bound("The second argument (index) of function substr() is an "
1876 "unbound integer value.");
1877 returncount.must_bound("The third argument (returncount) of function "
1878 "substr() is an unbound integer value.");
1879 return substr(value, (int)idx, (int)returncount);
1880 }
1881
1882 OCTETSTRING substr(const OCTETSTRING& value, int idx, int returncount)
1883 {
1884 value.must_bound("The first argument (value) of function substr() "
1885 "is an unbound octetstring value.");
1886 check_substr_arguments(value.lengthof(), idx, returncount, "octetstring",
1887 "octet");
1888 return OCTETSTRING(returncount, (const unsigned char*)value + idx);
1889 }
1890
1891 OCTETSTRING substr(const OCTETSTRING& value, int idx,
1892 const INTEGER& returncount)
1893 {
1894 returncount.must_bound("The third argument (returncount) of function "
1895 "substr() is an unbound integer value.");
1896 return substr(value, idx, (int)returncount);
1897 }
1898
1899 OCTETSTRING substr(const OCTETSTRING& value, const INTEGER& idx,
1900 int returncount)
1901 {
1902 idx.must_bound("The second argument (index) of function substr() "
1903 "is an unbound integer value.");
1904 return substr(value, (int)idx, returncount);
1905 }
1906
1907 OCTETSTRING substr(const OCTETSTRING& value, const INTEGER& idx,
1908 const INTEGER& returncount)
1909 {
1910 idx.must_bound("The second argument (index) of function substr() is an "
1911 "unbound integer value.");
1912 returncount.must_bound("The third argument (returncount) of function "
1913 "substr() is an unbound integer value.");
1914 return substr(value, (int)idx, (int)returncount);
1915 }
1916
1917 OCTETSTRING substr(const OCTETSTRING_ELEMENT& value, int idx, int returncount)
1918 {
1919 value.must_bound("The first argument (value) of function substr() "
1920 "is an unbound octetstring element.");
1921 check_substr_arguments(idx, returncount, "octetstring", "octet");
1922 if (returncount == 0) return OCTETSTRING(0, NULL);
1923 else {
1924 unsigned char octet = value.get_octet();
1925 return OCTETSTRING(1, &octet);
1926 }
1927 }
1928
1929 OCTETSTRING substr(const OCTETSTRING_ELEMENT& value, int idx,
1930 const INTEGER& returncount)
1931 {
1932 returncount.must_bound("The third argument (returncount) of function "
1933 "substr() is an unbound integer value.");
1934 return substr(value, idx, (int)returncount);
1935 }
1936
1937 OCTETSTRING substr(const OCTETSTRING_ELEMENT& value, const INTEGER& idx,
1938 int returncount)
1939 {
1940 idx.must_bound("The second argument (index) of function substr() "
1941 "is an unbound integer value.");
1942 return substr(value, (int)idx, returncount);
1943 }
1944
1945 OCTETSTRING substr(const OCTETSTRING_ELEMENT& value, const INTEGER& idx,
1946 const INTEGER& returncount)
1947 {
1948 idx.must_bound("The second argument (index) of function substr() is an "
1949 "unbound integer value.");
1950 returncount.must_bound("The third argument (returncount) of function "
1951 "substr() is an unbound integer value.");
1952 return substr(value, (int)idx, (int)returncount);
1953 }
1954
1955 CHARSTRING substr(const CHARSTRING& value, int idx, int returncount)
1956 {
1957 value.must_bound("The first argument (value) of function substr() "
1958 "is an unbound charstring value.");
1959 check_substr_arguments(value.lengthof(), idx, returncount, "charstring",
1960 "character");
1961 return CHARSTRING(returncount, (const char*)value + idx);
1962 }
1963
1964 CHARSTRING substr(const CHARSTRING& value, int idx,
1965 const INTEGER& returncount)
1966 {
1967 returncount.must_bound("The third argument (returncount) of function "
1968 "substr() is an unbound integer value.");
1969 return substr(value, idx, (int)returncount);
1970 }
1971
1972 CHARSTRING substr(const CHARSTRING& value, const INTEGER& idx,
1973 int returncount)
1974 {
1975 idx.must_bound("The second argument (index) of function substr() "
1976 "is an unbound integer value.");
1977 return substr(value, (int)idx, returncount);
1978 }
1979
1980 CHARSTRING substr(const CHARSTRING& value, const INTEGER& idx,
1981 const INTEGER& returncount)
1982 {
1983 idx.must_bound("The second argument (index) of function substr() is an "
1984 "unbound integer value.");
1985 returncount.must_bound("The third argument (returncount) of function "
1986 "substr() is an unbound integer value.");
1987 return substr(value, (int)idx, (int)returncount);
1988 }
1989
1990 CHARSTRING substr(const CHARSTRING_ELEMENT& value, int idx, int returncount)
1991 {
1992 value.must_bound("The first argument (value) of function substr() "
1993 "is an unbound charstring element.");
1994 check_substr_arguments(idx, returncount, "charstring", "character");
1995 if (returncount == 0) return CHARSTRING(0, NULL);
1996 else return CHARSTRING(value.get_char());
1997 }
1998
1999 CHARSTRING substr(const CHARSTRING_ELEMENT& value, int idx,
2000 const INTEGER& returncount)
2001 {
2002 returncount.must_bound("The third argument (returncount) of function "
2003 "substr() is an unbound integer value.");
2004 return substr(value, idx, (int)returncount);
2005 }
2006
2007 CHARSTRING substr(const CHARSTRING_ELEMENT& value, const INTEGER& idx,
2008 int returncount)
2009 {
2010 idx.must_bound("The second argument (index) of function substr() "
2011 "is an unbound integer value.");
2012 return substr(value, (int)idx, returncount);
2013 }
2014
2015 CHARSTRING substr(const CHARSTRING_ELEMENT& value, const INTEGER& idx,
2016 const INTEGER& returncount)
2017 {
2018 idx.must_bound("The second argument (index) of function substr() is an "
2019 "unbound integer value.");
2020 returncount.must_bound("The third argument (returncount) of function "
2021 "substr() is an unbound integer value.");
2022 return substr(value, (int)idx, (int)returncount);
2023 }
2024
2025 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING& value, int idx,
2026 int returncount)
2027 {
2028 value.must_bound("The first argument (value) of function substr() "
2029 "is an unbound universal charstring value.");
2030 check_substr_arguments(value.lengthof(), idx, returncount,
2031 "universal charstring", "character");
2032 return UNIVERSAL_CHARSTRING(returncount,
2033 (const universal_char*)value + idx);
2034 }
2035
2036 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING& value, int idx,
2037 const INTEGER& returncount)
2038 {
2039 returncount.must_bound("The third argument (returncount) of function "
2040 "substr() is an unbound integer value.");
2041 return substr(value, idx, (int)returncount);
2042 }
2043
2044 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING& value,
2045 const INTEGER& idx, int returncount)
2046 {
2047 idx.must_bound("The second argument (index) of function substr() "
2048 "is an unbound integer value.");
2049 return substr(value, (int)idx, returncount);
2050 }
2051
2052 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING& value,
2053 const INTEGER& idx, const INTEGER& returncount)
2054 {
2055 idx.must_bound("The second argument (index) of function substr() is an "
2056 "unbound integer value.");
2057 returncount.must_bound("The third argument (returncount) of function "
2058 "substr() is an unbound integer value.");
2059 return substr(value, (int)idx, (int)returncount);
2060 }
2061
2062 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_ELEMENT& value,
2063 int idx, int returncount)
2064 {
2065 value.must_bound("The first argument (value) of function substr() "
2066 "is an unbound universal charstring element.");
2067 check_substr_arguments(idx, returncount, "universal charstring",
2068 "character");
2069 if (returncount == 0)
2070 return UNIVERSAL_CHARSTRING(0, (const universal_char*)NULL);
2071 else return UNIVERSAL_CHARSTRING(value.get_uchar());
2072 }
2073
2074 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_ELEMENT& value,
2075 int idx, const INTEGER& returncount)
2076 {
2077 returncount.must_bound("The third argument (returncount) of function "
2078 "substr() is an unbound integer value.");
2079 return substr(value, idx, (int)returncount);
2080 }
2081
2082 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_ELEMENT& value,
2083 const INTEGER& idx, int returncount)
2084 {
2085 idx.must_bound("The second argument (index) of function substr() "
2086 "is an unbound integer value.");
2087 return substr(value, (int)idx, returncount);
2088 }
2089
2090 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_ELEMENT& value,
2091 const INTEGER& idx, const INTEGER& returncount)
2092 {
2093 idx.must_bound("The second argument (index) of function substr() is an "
2094 "unbound integer value.");
2095 returncount.must_bound("The third argument (returncount) of function "
2096 "substr() is an unbound integer value.");
2097 return substr(value, (int)idx, (int)returncount);
2098 }
2099
2100 // substr() on templates
2101 BITSTRING substr(const BITSTRING_template& value, int idx, int returncount)
2102 {
2103 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2104 return substr(value.valueof(), idx, returncount);
2105 }
2106
2107 BITSTRING substr(const BITSTRING_template& value, int idx, const INTEGER& returncount)
2108 {
2109 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2110 return substr(value.valueof(), idx, returncount);
2111 }
2112
2113 BITSTRING substr(const BITSTRING_template& value, const INTEGER& idx, int returncount)
2114 {
2115 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2116 return substr(value.valueof(), idx, returncount);
2117 }
2118
2119 BITSTRING substr(const BITSTRING_template& value, const INTEGER& idx,
2120 const INTEGER& returncount)
2121 {
2122 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2123 return substr(value.valueof(), idx, returncount);
2124 }
2125
2126 HEXSTRING substr(const HEXSTRING_template& value, int idx, int returncount)
2127 {
2128 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2129 return substr(value.valueof(), idx, returncount);
2130 }
2131
2132 HEXSTRING substr(const HEXSTRING_template& value, int idx, const INTEGER& returncount)
2133 {
2134 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2135 return substr(value.valueof(), idx, returncount);
2136 }
2137
2138 HEXSTRING substr(const HEXSTRING_template& value, const INTEGER& idx, int returncount)
2139 {
2140 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2141 return substr(value.valueof(), idx, returncount);
2142 }
2143
2144 HEXSTRING substr(const HEXSTRING_template& value, const INTEGER& idx,
2145 const INTEGER& returncount)
2146 {
2147 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2148 return substr(value.valueof(), idx, returncount);
2149 }
2150
2151 OCTETSTRING substr(const OCTETSTRING_template& value, int idx, int returncount)
2152 {
2153 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2154 return substr(value.valueof(), idx, returncount);
2155 }
2156
2157 OCTETSTRING substr(const OCTETSTRING_template& value, int idx,
2158 const INTEGER& returncount)
2159 {
2160 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2161 return substr(value.valueof(), idx, returncount);
2162 }
2163
2164 OCTETSTRING substr(const OCTETSTRING_template& value, const INTEGER& idx,
2165 int returncount)
2166 {
2167 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2168 return substr(value.valueof(), idx, returncount);
2169 }
2170
2171 OCTETSTRING substr(const OCTETSTRING_template& value, const INTEGER& idx,
2172 const INTEGER& returncount)
2173 {
2174 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2175 return substr(value.valueof(), idx, returncount);
2176 }
2177
2178 CHARSTRING substr(const CHARSTRING_template& value, int idx, int returncount)
2179 {
2180 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2181 return substr(value.valueof(), idx, returncount);
2182 }
2183
2184 CHARSTRING substr(const CHARSTRING_template& value, int idx,
2185 const INTEGER& returncount)
2186 {
2187 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2188 return substr(value.valueof(), idx, returncount);
2189 }
2190
2191 CHARSTRING substr(const CHARSTRING_template& value, const INTEGER& idx,
2192 int returncount)
2193 {
2194 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2195 return substr(value.valueof(), idx, returncount);
2196 }
2197
2198 CHARSTRING substr(const CHARSTRING_template& value, const INTEGER& idx,
2199 const INTEGER& returncount)
2200 {
2201 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2202 return substr(value.valueof(), idx, returncount);
2203 }
2204
2205 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_template& value, int idx,
2206 int returncount)
2207 {
2208 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2209 return substr(value.valueof(), idx, returncount);
2210 }
2211
2212 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_template& value, int idx,
2213 const INTEGER& returncount)
2214 {
2215 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2216 return substr(value.valueof(), idx, returncount);
2217 }
2218
2219 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_template& value,
2220 const INTEGER& idx, int returncount)
2221 {
2222 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2223 return substr(value.valueof(), idx, returncount);
2224 }
2225
2226 UNIVERSAL_CHARSTRING substr(const UNIVERSAL_CHARSTRING_template& value,
2227 const INTEGER& idx, const INTEGER& returncount)
2228 {
2229 if (!value.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2230 return substr(value.valueof(), idx, returncount);
2231 }
2232
2233 // C.35 - replace
2234
2235 void check_replace_arguments(int value_length, int idx, int len,
2236 const char *string_type, const char *element_name)
2237 {
2238 if (idx < 0) TTCN_error("The second argument (index) of function "
2239 "replace() is a negative integer value: %d.", idx);
2240 if (idx > value_length) TTCN_error("The second argument (index) of "
2241 "function replace(), which is %d, is greater than the length of the "
2242 "%s value: %d.", idx, string_type, value_length);
2243 if (len < 0) TTCN_error("The third argument (len) of function replace() "
2244 "is a negative integer value: %d.", len);
2245 if (len > value_length) TTCN_error("The third argument (len) of function "
2246 "replace(), which is %d, is greater than the length of the "
2247 "%s value: %d.", len, string_type, value_length);
2248 if (idx + len > value_length) TTCN_error("The first argument of "
2249 "function replace(), the length of which is %d, does not have enough "
2250 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
2251 value_length, element_name, idx, len, element_name,
2252 len > 1 ? "s are" : " is", value_length - idx > 1 ? "are" : "is",
2253 value_length - idx);
2254 }
2255
2256 BITSTRING replace(const BITSTRING& value, int idx, int len,
2257 const BITSTRING& repl)
2258 {
2259 value.must_bound("The first argument (value) of function replace() "
2260 "is an unbound bitstring value.");
2261 repl.must_bound("The fourth argument (repl) of function replace() is an "
2262 "unbound bitstring value.");
2263 check_replace_arguments(value.lengthof(), idx, len, "bitstring", "bit");
2264 int value_len = value.lengthof();
2265 int repl_len = repl.lengthof();
2266 BITSTRING ret_val(value_len + repl_len - len);
2267 for (int i = 0; i < idx; i++) ret_val.set_bit(i, value.get_bit(i));
2268 for (int i = 0; i < repl_len; i++)
2269 ret_val.set_bit(i + idx, repl.get_bit(i));
2270 for (int i = 0; i < value_len - idx - len; i++)
2271 ret_val.set_bit(i + idx + repl_len, value.get_bit(idx + len + i));
2272 return ret_val;
2273 }
2274
2275 BITSTRING replace(const BITSTRING& value, int idx, const INTEGER& len,
2276 const BITSTRING& repl)
2277 {
2278 len.must_bound("The third argument (len) of function replace() is an "
2279 "unbound integer value.");
2280 return replace(value, idx, (int)len, repl);
2281 }
2282
2283 BITSTRING replace(const BITSTRING& value, const INTEGER& idx, int len,
2284 const BITSTRING& repl)
2285 {
2286 idx.must_bound("The second argument (index) of function replace() is an "
2287 "unbound integer value.");
2288 return replace(value, (int)idx, len, repl);
2289 }
2290
2291 BITSTRING replace(const BITSTRING& value, const INTEGER& idx,
2292 const INTEGER& len, const BITSTRING& repl)
2293 {
2294 idx.must_bound("The second argument (index) of function replace() is an "
2295 "unbound integer value.");
2296 len.must_bound("The third argument (len) of function replace() is an "
2297 "unbound integer value.");
2298 return replace(value, (int)idx, (int)len, repl);
2299 }
2300
2301 HEXSTRING replace(const HEXSTRING& value, int idx, int len,
2302 const HEXSTRING& repl)
2303 {
2304 value.must_bound("The first argument (value) of function replace() "
2305 "is an unbound hexstring value.");
2306 repl.must_bound("The fourth argument (repl) of function replace() is an "
2307 "unbound hexstring value.");
2308 check_replace_arguments(value.lengthof(), idx, len, "hexstring",
2309 "hexadecimal digit");
2310 int value_len = value.lengthof();
2311 int repl_len = repl.lengthof();
2312 HEXSTRING ret_val(value_len + repl_len - len);
2313 for (int i = 0; i < idx; i++)
2314 ret_val.set_nibble(i, value.get_nibble(i));
2315 for (int i = 0; i < repl_len; i++)
2316 ret_val.set_nibble(idx + i, repl.get_nibble(i));
2317 for (int i = 0; i < value_len - idx - len; i++)
2318 ret_val.set_nibble(idx + i + repl_len,
2319 value.get_nibble(idx + i + len));
2320 return ret_val;
2321 }
2322
2323 HEXSTRING replace(const HEXSTRING& value, int idx, const INTEGER& len,
2324 const HEXSTRING& repl)
2325 {
2326 len.must_bound("The third argument (len) of function replace() is an "
2327 "unbound integer value.");
2328 return replace(value, idx, (int)len, repl);
2329 }
2330
2331 HEXSTRING replace(const HEXSTRING& value, const INTEGER& idx, int len,
2332 const HEXSTRING& repl)
2333 {
2334 idx.must_bound("The second argument (index) of function replace() is an "
2335 "unbound integer value.");
2336 return replace(value, (int)idx, len, repl);
2337 }
2338
2339 HEXSTRING replace(const HEXSTRING& value, const INTEGER& idx,
2340 const INTEGER& len, const HEXSTRING& repl)
2341 {
2342 idx.must_bound("The second argument (index) of function replace() is an "
2343 "unbound integer value.");
2344 len.must_bound("The third argument (len) of function replace() is an "
2345 "unbound integer value.");
2346 return replace(value, (int)idx, (int)len, repl);
2347 }
2348
2349 OCTETSTRING replace(const OCTETSTRING& value, int idx, int len,
2350 const OCTETSTRING& repl)
2351 {
2352 value.must_bound("The first argument (value) of function replace() "
2353 "is an unbound octetstring value.");
2354 repl.must_bound("The fourth argument (repl) of function replace() is an "
2355 "unbound octetstring value.");
2356 check_replace_arguments(value.lengthof(), idx, len, "octetstring",
2357 "octet");
2358 int value_len = value.lengthof();
2359 int repl_len = repl.lengthof();
2360 OCTETSTRING ret_val(value_len + repl_len - len);
2361 memcpy(ret_val.val_ptr->octets_ptr, value.val_ptr->octets_ptr, idx);
2362 memcpy(ret_val.val_ptr->octets_ptr + idx, repl.val_ptr->octets_ptr,
2363 repl_len);
2364 memcpy(ret_val.val_ptr->octets_ptr + idx + repl_len,
2365 value.val_ptr->octets_ptr + idx + len, value_len - idx - len);
2366 return ret_val;
2367 }
2368
2369 OCTETSTRING replace(const OCTETSTRING& value, int idx, const INTEGER& len,
2370 const OCTETSTRING& repl)
2371 {
2372 len.must_bound("The third argument (len) of function replace() is an "
2373 "unbound integer value.");
2374 return replace(value, idx, (int)len, repl);
2375 }
2376
2377 OCTETSTRING replace(const OCTETSTRING& value, const INTEGER& idx, int len,
2378 const OCTETSTRING& repl)
2379 {
2380 idx.must_bound("The second argument (index) of function replace() is an "
2381 "unbound integer value.");
2382 return replace(value, (int)idx, len, repl);
2383 }
2384
2385 OCTETSTRING replace(const OCTETSTRING& value, const INTEGER& idx,
2386 const INTEGER& len, const OCTETSTRING& repl)
2387 {
2388 idx.must_bound("The second argument (index) of function replace() is an "
2389 "unbound integer value.");
2390 len.must_bound("The third argument (len) of function replace() is an "
2391 "unbound integer value.");
2392 return replace(value, (int)idx, (int)len, repl);
2393 }
2394
2395 CHARSTRING replace(const CHARSTRING& value, int idx, int len,
2396 const CHARSTRING& repl)
2397 {
2398 value.must_bound("The first argument (value) of function replace() "
2399 "is an unbound charstring value.");
2400 repl.must_bound("The fourth argument (repl) of function replace() is an "
2401 "unbound charstring value.");
2402 check_replace_arguments(value.lengthof(), idx, len, "charstring",
2403 "character");
2404 int value_len = value.lengthof();
2405 int repl_len = repl.lengthof();
2406 CHARSTRING ret_val(value_len + repl_len - len);
2407 /* According to http://gcc.gnu.org/ml/fortran/2007-05/msg00341.html it's
2408 worth using memcpy() instead of strncat(). There's no need to scan the
2409 strings for '\0'. */
2410 memcpy(ret_val.val_ptr->chars_ptr, value.val_ptr->chars_ptr, idx);
2411 memcpy(ret_val.val_ptr->chars_ptr + idx, repl.val_ptr->chars_ptr,
2412 repl_len);
2413 memcpy(ret_val.val_ptr->chars_ptr + idx + repl_len,
2414 value.val_ptr->chars_ptr + idx + len, value_len - idx - len);
2415 return ret_val;
2416 }
2417
2418 CHARSTRING replace(const CHARSTRING& value, int idx, const INTEGER& len,
2419 const CHARSTRING& repl)
2420 {
2421 len.must_bound("The third argument (len) of function replace() is an "
2422 "unbound integer value.");
2423 return replace(value, idx, (int)len, repl);
2424 }
2425
2426 CHARSTRING replace(const CHARSTRING& value, const INTEGER& idx, int len,
2427 const CHARSTRING& repl)
2428 {
2429 idx.must_bound("The second argument (index) of function replace() is an "
2430 "unbound integer value.");
2431 return replace(value, (int)idx, len, repl);
2432 }
2433
2434 CHARSTRING replace(const CHARSTRING& value, const INTEGER& idx,
2435 const INTEGER& len, const CHARSTRING& repl)
2436 {
2437 idx.must_bound("The second argument (index) of function replace() is an "
2438 "unbound integer value.");
2439 len.must_bound("The third argument (len) of function replace() is an "
2440 "unbound integer value.");
2441 return replace(value, (int)idx, (int)len, repl);
2442 }
2443
2444 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING& value, int idx,
2445 int len, const UNIVERSAL_CHARSTRING& repl)
2446 {
2447 value.must_bound("The first argument (value) of function replace() "
2448 "is an unbound universal charstring value.");
2449 repl.must_bound("The fourth argument (repl) of function replace() is an "
2450 "unbound universal charstring value.");
2451 check_replace_arguments(value.lengthof(), idx, len,
2452 "universal charstring", "character");
2453 int value_len = value.lengthof();
2454 int repl_len = repl.lengthof();
2455 UNIVERSAL_CHARSTRING ret_val(value_len + repl_len - len);
2456 memcpy(ret_val.val_ptr->uchars_ptr, value.val_ptr->uchars_ptr,
2457 idx * sizeof(universal_char));
2458 memcpy(ret_val.val_ptr->uchars_ptr + idx, repl.val_ptr->uchars_ptr,
2459 repl_len * sizeof(universal_char));
2460 memcpy(ret_val.val_ptr->uchars_ptr + idx + repl_len,
2461 value.val_ptr->uchars_ptr + idx + len,
2462 (value_len - idx - len) * sizeof(universal_char));
2463 return ret_val;
2464 }
2465
2466 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING& value, int idx,
2467 const INTEGER& len, const UNIVERSAL_CHARSTRING& repl)
2468 {
2469 len.must_bound("The third argument (len) of function replace() is an "
2470 "unbound integer value.");
2471 return replace(value, idx, (int)len, repl);
2472 }
2473
2474 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING& value,
2475 const INTEGER& idx, int len, const UNIVERSAL_CHARSTRING& repl)
2476 {
2477 idx.must_bound("The second argument (index) of function replace() is an "
2478 "unbound integer value.");
2479 return replace(value, (int)idx, len, repl);
2480 }
2481
2482 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING& value,
2483 const INTEGER& idx, const INTEGER& len,
2484 const UNIVERSAL_CHARSTRING& repl)
2485 {
2486 idx.must_bound("The second argument (index) of function replace() is an "
2487 "unbound integer value.");
2488 len.must_bound("The third argument (len) of function replace() is an "
2489 "unbound integer value.");
2490 return replace(value, (int)idx, (int)len, repl);
2491 }
2492
2493 // replace on templates
2494
2495 BITSTRING replace(const BITSTRING_template& value, int idx, int len,
2496 const BITSTRING_template& repl)
2497 {
2498 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2499 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2500 return replace(value.valueof(), idx, len, repl.valueof());
2501 }
2502
2503 BITSTRING replace(const BITSTRING_template& value, int idx, const INTEGER& len,
2504 const BITSTRING_template& repl)
2505 {
2506 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2507 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2508 return replace(value.valueof(), idx, len, repl.valueof());
2509 }
2510
2511 BITSTRING replace(const BITSTRING_template& value, const INTEGER& idx, int len,
2512 const BITSTRING_template& repl)
2513 {
2514 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2515 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2516 return replace(value.valueof(), idx, len, repl.valueof());
2517 }
2518
2519 BITSTRING replace(const BITSTRING_template& value, const INTEGER& idx,
2520 const INTEGER& len, const BITSTRING_template& repl)
2521 {
2522 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2523 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2524 return replace(value.valueof(), idx, len, repl.valueof());
2525 }
2526
2527 HEXSTRING replace(const HEXSTRING_template& value, int idx, int len,
2528 const HEXSTRING_template& repl)
2529 {
2530 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2531 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2532 return replace(value.valueof(), idx, len, repl.valueof());
2533 }
2534
2535 HEXSTRING replace(const HEXSTRING_template& value, int idx, const INTEGER& len,
2536 const HEXSTRING_template& repl)
2537 {
2538 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2539 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2540 return replace(value.valueof(), idx, len, repl.valueof());
2541 }
2542
2543 HEXSTRING replace(const HEXSTRING_template& value, const INTEGER& idx, int len,
2544 const HEXSTRING_template& repl)
2545 {
2546 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2547 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2548 return replace(value.valueof(), idx, len, repl.valueof());
2549 }
2550
2551 HEXSTRING replace(const HEXSTRING_template& value, const INTEGER& idx,
2552 const INTEGER& len, const HEXSTRING_template& repl)
2553 {
2554 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2555 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2556 return replace(value.valueof(), idx, len, repl.valueof());
2557 }
2558
2559 OCTETSTRING replace(const OCTETSTRING_template& value, int idx, int len,
2560 const OCTETSTRING_template& repl)
2561 {
2562 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2563 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2564 return replace(value.valueof(), idx, len, repl.valueof());
2565 }
2566
2567 OCTETSTRING replace(const OCTETSTRING_template& value, int idx, const INTEGER& len,
2568 const OCTETSTRING_template& repl)
2569 {
2570 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2571 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2572 return replace(value.valueof(), idx, len, repl.valueof());
2573 }
2574
2575 OCTETSTRING replace(const OCTETSTRING_template& value, const INTEGER& idx, int len,
2576 const OCTETSTRING_template& repl)
2577 {
2578 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2579 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2580 return replace(value.valueof(), idx, len, repl.valueof());
2581 }
2582
2583 OCTETSTRING replace(const OCTETSTRING_template& value, const INTEGER& idx,
2584 const INTEGER& len, const OCTETSTRING_template& repl)
2585 {
2586 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2587 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2588 return replace(value.valueof(), idx, len, repl.valueof());
2589 }
2590
2591 CHARSTRING replace(const CHARSTRING_template& value, int idx, int len,
2592 const CHARSTRING_template& repl)
2593 {
2594 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2595 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2596 return replace(value.valueof(), idx, len, repl.valueof());
2597 }
2598
2599 CHARSTRING replace(const CHARSTRING_template& value, int idx, const INTEGER& len,
2600 const CHARSTRING_template& repl)
2601 {
2602 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2603 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2604 return replace(value.valueof(), idx, len, repl.valueof());
2605 }
2606
2607 CHARSTRING replace(const CHARSTRING_template& value, const INTEGER& idx, int len,
2608 const CHARSTRING_template& repl)
2609 {
2610 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2611 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2612 return replace(value.valueof(), idx, len, repl.valueof());
2613 }
2614
2615 CHARSTRING replace(const CHARSTRING_template& value, const INTEGER& idx,
2616 const INTEGER& len, const CHARSTRING_template& repl)
2617 {
2618 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2619 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2620 return replace(value.valueof(), idx, len, repl.valueof());
2621 }
2622
2623 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING_template& value, int idx, int len,
2624 const UNIVERSAL_CHARSTRING_template& repl)
2625 {
2626 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2627 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2628 return replace(value.valueof(), idx, len, repl.valueof());
2629 }
2630
2631 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING_template& value, int idx, const INTEGER& len,
2632 const UNIVERSAL_CHARSTRING_template& repl)
2633 {
2634 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2635 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2636 return replace(value.valueof(), idx, len, repl.valueof());
2637 }
2638
2639 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING_template& value, const INTEGER& idx, int len,
2640 const UNIVERSAL_CHARSTRING_template& repl)
2641 {
2642 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2643 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2644 return replace(value.valueof(), idx, len, repl.valueof());
2645 }
2646
2647 UNIVERSAL_CHARSTRING replace(const UNIVERSAL_CHARSTRING_template& value, const INTEGER& idx,
2648 const INTEGER& len, const UNIVERSAL_CHARSTRING_template& repl)
2649 {
2650 if (!value.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2651 if (!repl.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2652 return replace(value.valueof(), idx, len, repl.valueof());
2653 }
2654
2655 // C.36 - rnd
2656
2657 static boolean rnd_seed_set = FALSE;
2658
2659 static void set_rnd_seed(double float_seed)
2660 {
2661 FLOAT::check_numeric(float_seed, "The seed value of function rnd()");
2662 long integer_seed = 0;
2663 const unsigned char *src_ptr = (const unsigned char*)&float_seed;
2664 unsigned char *dst_ptr = (unsigned char*)&integer_seed;
2665 for (size_t i = 0; i < sizeof(float_seed); i++) {
2666 dst_ptr[i % sizeof(integer_seed)] ^= bit_reverse_table[src_ptr[i]];
2667 dst_ptr[(sizeof(float_seed) - 1 - i) % sizeof(integer_seed)] ^=
2668 src_ptr[i];
2669 }
2670
2671 srand48(integer_seed);
2672 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::seed, float_seed, integer_seed);
2673 rnd_seed_set = TRUE;
2674 }
2675
2676 static double rnd_generate()
2677 {
2678 double ret_val;
2679 ret_val = drand48();
2680 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::read__out, ret_val, 0);
2681 return ret_val;
2682 }
2683
2684 double rnd()
2685 {
2686 if (!rnd_seed_set) set_rnd_seed(TTCN_Snapshot::time_now());
2687 return rnd_generate();
2688 }
2689
2690 double rnd(double seed)
2691 {
2692 set_rnd_seed(seed);
2693 return rnd_generate();
2694 }
2695
2696 double rnd(const FLOAT& seed)
2697 {
2698 seed.must_bound("Initializing the random number generator with "
2699 "an unbound float value as seed.");
2700 set_rnd_seed((double)seed);
2701 return rnd_generate();
2702 }
2703
2704
2705 // Additional predefined functions defined in Annex B of ES 101 873-7
2706
2707 // B.1 decomp - not implemented yet
2708
2709
2710 // Non-standard functions
2711
2712 // str2bit
2713
2714 BITSTRING str2bit(const char *value)
2715 {
2716 if (value == NULL) return BITSTRING(0, NULL);
2717 else return str2bit(CHARSTRING(value));
2718 }
2719
2720 BITSTRING str2bit(const CHARSTRING& value)
2721 {
2722 value.must_bound("The argument of function str2bit() is an unbound "
2723 "charstring value.");
2724 int value_length = value.lengthof();
2725 const char *chars_ptr = value;
2726 BITSTRING ret_val(value_length);
2727 for (int i = 0; i < value_length; i++) {
2728 char c = chars_ptr[i];
2729 switch (c) {
2730 case '0':
2731 ret_val.set_bit(i, FALSE);
2732 break;
2733 case '1':
2734 ret_val.set_bit(i, TRUE);
2735 break;
2736 default:
2737 TTCN_error_begin("The argument of function str2bit() shall "
2738 "contain characters `0' and `1' only, but character `");
2739 TTCN_Logger::log_char_escaped(c);
2740 TTCN_Logger::log_event("' was found at index %d.", i);
2741 TTCN_error_end();
2742 }
2743 }
2744 ret_val.clear_unused_bits();
2745 return ret_val;
2746 }
2747
2748 BITSTRING str2bit(const CHARSTRING_ELEMENT& value)
2749 {
2750 value.must_bound("The argument of function str2bit() is an unbound "
2751 "charstring element.");
2752 char c = value.get_char();
2753 if (c != '0' && c != '1') {
2754 TTCN_error_begin("The argument of function str2bit() shall contain "
2755 "characters `0' and `1' only, but the given charstring element "
2756 "contains the character `");
2757 TTCN_Logger::log_char_escaped(c);
2758 TTCN_Logger::log_event_str("'.");
2759 TTCN_error_end();
2760 }
2761 unsigned char bit = c == '1' ? 0x01 : 0x00;
2762 return BITSTRING(1, &bit);
2763 }
2764
2765 // str2hex
2766
2767 HEXSTRING str2hex(const char *value)
2768 {
2769 if (value == NULL) return HEXSTRING(0, NULL);
2770 else return str2hex(CHARSTRING(value));
2771 }
2772
2773 HEXSTRING str2hex(const CHARSTRING& value)
2774 {
2775 value.must_bound("The argument of function str2hex() is an unbound "
2776 "charstring value.");
2777 int value_length = value.lengthof();
2778 const char *chars_ptr = value;
2779 HEXSTRING ret_val(value_length);
2780 unsigned char *nibbles_ptr = ret_val.val_ptr->nibbles_ptr;
2781 for (int i = 0; i < value_length; i++) {
2782 char c = chars_ptr[i];
2783 unsigned char hex_digit = char_to_hexdigit(c);
2784 if (hex_digit > 0x0F) {
2785 TTCN_error_begin("The argument of function str2hex() shall "
2786 "contain hexadecimal digits only, but character `");
2787 TTCN_Logger::log_char_escaped(c);
2788 TTCN_Logger::log_event("' was found at index %d.", i);
2789 TTCN_error_end();
2790 }
2791 if (i % 2) nibbles_ptr[i / 2] |= hex_digit << 4;
2792 else nibbles_ptr[i / 2] = hex_digit;
2793 }
2794 return ret_val;
2795 }
2796
2797 HEXSTRING str2hex(const CHARSTRING_ELEMENT& value)
2798 {
2799 value.must_bound("The argument of function str2hex() is an unbound "
2800 "charstring element.");
2801 char c = value.get_char();
2802 unsigned char hex_digit = char_to_hexdigit(c);
2803 if (hex_digit > 0x0F) {
2804 TTCN_error_begin("The argument of function str2hex() shall contain "
2805 "only hexadecimal digits, but the given charstring element "
2806 "contains the character `");
2807 TTCN_Logger::log_char_escaped(c);
2808 TTCN_Logger::log_event_str("'.");
2809 TTCN_error_end();
2810 }
2811 return HEXSTRING(1, &hex_digit);
2812 }
2813
2814 // float2str
2815
2816 CHARSTRING float2str(double value)
2817 {
2818 bool f = value == 0.0
2819 || (value > -MAX_DECIMAL_FLOAT && value <= -MIN_DECIMAL_FLOAT)
2820 || (value >= MIN_DECIMAL_FLOAT && value < MAX_DECIMAL_FLOAT);
2821 // true if decimal representation possible (use %f format)
2822 char str_buf[64];
2823 int str_len = snprintf(str_buf, sizeof(str_buf), f ? "%f" : "%e", value);
2824 if (str_len < 0 || str_len >= (int)sizeof(str_buf)) {
2825 TTCN_error("Internal error: system call snprintf() returned "
2826 "unexpected status code %d when converting value %g in function "
2827 "float2str().", str_len, value);
2828 }
2829 return CHARSTRING(str_len, str_buf);
2830 }
2831
2832 CHARSTRING float2str(const FLOAT& value)
2833 {
2834 value.must_bound("The argument of function float2str() is an unbound "
2835 "float value.");
2836 return float2str((double)value);
2837 }
2838
2839 // unichar2char
2840
2841 CHARSTRING unichar2char(const UNIVERSAL_CHARSTRING& value)
2842 {
2843 value.must_bound("The argument of function unichar2char() is an unbound "
2844 "universal charstring value.");
2845 int value_length = value.lengthof();
2846 const universal_char *uchars_ptr = value;
2847 CHARSTRING ret_val(value_length);
2848 char *chars_ptr = ret_val.val_ptr->chars_ptr;
2849 for (int i = 0; i < value_length; i++) {
2850 const universal_char& uchar = uchars_ptr[i];
2851 if (uchar.uc_group != 0 || uchar.uc_plane != 0 || uchar.uc_row != 0 ||
2852 uchar.uc_cell > 127) {
2853 TTCN_error("The characters in the argument of function "
2854 "unichar2char() shall be within the range char(0, 0, 0, 0) .. "
2855 "char(0, 0, 0, 127), but quadruple char(%u, %u, %u, %u) was "
2856 "found at index %d.", uchar.uc_group, uchar.uc_plane,
2857 uchar.uc_row, uchar.uc_cell, i);
2858 }
2859 chars_ptr[i] = uchar.uc_cell;
2860 }
2861 return ret_val;
2862 }
2863
2864 CHARSTRING unichar2char(const UNIVERSAL_CHARSTRING_ELEMENT& value)
2865 {
2866 value.must_bound("The argument of function unichar2char() is an unbound "
2867 "universal charstring element.");
2868 const universal_char& uchar = value.get_uchar();
2869 if (uchar.uc_group != 0 || uchar.uc_plane != 0 || uchar.uc_row != 0 ||
2870 uchar.uc_cell > 127) {
2871 TTCN_error("The characters in the argument of function unichar2char() "
2872 "shall be within the range char(0, 0, 0, 0) .. char(0, 0, 0, 127), "
2873 "but the given universal charstring element contains the quadruple "
2874 "char(%u, %u, %u, %u).", uchar.uc_group, uchar.uc_plane,
2875 uchar.uc_row, uchar.uc_cell);
2876 }
2877 return CHARSTRING((char)uchar.uc_cell);
2878 }
2879
2880 OCTETSTRING unichar2oct(const UNIVERSAL_CHARSTRING& invalue, const CHARSTRING& string_encoding)
2881 {
2882 invalue.must_bound("The argument of function unichar2oct() is an unbound "
2883 "universal charstring value.");
2884 TTCN_EncDec::error_behavior_t err_behavior = TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR);
2885 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, TTCN_EncDec::EB_ERROR);
2886 TTCN_Buffer buf;
2887 if ("UTF-8" == string_encoding) {
2888 invalue.encode_utf8(buf, false);
2889 }
2890 else if ("UTF-8 BOM" == string_encoding) {
2891 invalue.encode_utf8(buf, true);
2892 }
2893 else if ("UTF-16" == string_encoding) {
2894 invalue.encode_utf16(buf, CharCoding::UTF16);
2895 }
2896 else if ("UTF-16BE" == string_encoding) {
2897 invalue.encode_utf16(buf, CharCoding::UTF16BE);
2898 }
2899 else if ("UTF-16LE" == string_encoding) {
2900 invalue.encode_utf16(buf, CharCoding::UTF16LE);
2901 }
2902 else if ("UTF-32" == string_encoding) {
2903 invalue.encode_utf32(buf, CharCoding::UTF32);
2904 }
2905 else if ("UTF-32BE" == string_encoding) {
2906 invalue.encode_utf32(buf, CharCoding::UTF32BE);
2907 } else if ("UTF-32LE" == string_encoding) {
2908 invalue.encode_utf32(buf, CharCoding::UTF32LE);
2909 }
2910 else {
2911 TTCN_error("unichar2oct: Invalid parameter: %s", (const char*)string_encoding);
2912 }
2913 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, err_behavior);
2914 return OCTETSTRING (buf.get_len(), buf.get_data());
2915 }
2916
2917 OCTETSTRING unichar2oct(const UNIVERSAL_CHARSTRING& invalue)
2918 {
2919 // no encoding parameter is default UTF-8
2920 invalue.must_bound("The argument of function unichar2oct() is an unbound "
2921 "universal charstring value.");
2922 TTCN_EncDec::error_behavior_t err_behavior = TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR);
2923 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, TTCN_EncDec::EB_ERROR);
2924 TTCN_Buffer buf;
2925 invalue.encode_utf8(buf, false);
2926 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR, err_behavior);
2927 return OCTETSTRING (buf.get_len(), buf.get_data());
2928 }
2929
2930 CHARSTRING get_stringencoding(const OCTETSTRING& encoded_value)
2931 {
2932 if (!encoded_value.lengthof()) return CHARSTRING("<unknown>");
2933 unsigned int i, j, length = encoded_value.lengthof();
2934 const unsigned char* strptr = (const unsigned char*)encoded_value;
2935 for (i = 0, j = 0; UTF8_BOM[i++] == strptr[j++] && i < sizeof (UTF8_BOM););
2936 if (i == sizeof (UTF8_BOM) && sizeof(UTF8_BOM) <= length) return "UTF-8";
2937 //UTF-32 shall be tested before UTF-16 !!!
2938 for (i = 0, j = 0; UTF32BE_BOM[i++] == strptr[j++] && i < sizeof (UTF32BE_BOM););
2939 if (i == sizeof (UTF32BE_BOM) && sizeof (UTF32BE_BOM) <= length ) return "UTF-32BE";
2940 for (i = 0, j = 0; UTF32LE_BOM[i++] == strptr[j++] && i < sizeof (UTF32LE_BOM););
2941 if (i == sizeof (UTF32LE_BOM) && sizeof (UTF32LE_BOM) <= length) return "UTF-32LE";
2942 //UTF-32 shall be tested before UTF-16 !!!
2943 for (i = 0, j = 0; UTF16BE_BOM[i++] == strptr[j++] && i < sizeof (UTF16BE_BOM););
2944 if (i == sizeof (UTF16BE_BOM) && sizeof (UTF16BE_BOM) <= length) return "UTF-16BE";
2945 for (i = 0, j = 0; UTF16LE_BOM[i++] == strptr[j++] && i < sizeof (UTF16LE_BOM););
2946 if (i == sizeof (UTF16LE_BOM) && sizeof (UTF16LE_BOM) <= length) return "UTF-16LE";
2947 if (is_ascii (encoded_value) == CharCoding::ASCII) {
2948 return "ASCII";
2949 }
2950 else if (CharCoding::UTF_8 == is_utf8 (encoded_value)) {
2951 return "UTF-8";
2952 } else {
2953 return "<unknown>";
2954 }
2955 }
2956
2957 // for internal purposes:
2958 // to obtain the name of the port when port array references are used
2959 // in connect/map/disconnect/unmap operations
2960
2961 CHARSTRING get_port_name(const char *port_name, int array_index)
2962 {
2963 char *result_str = mprintf("%s[%d]", port_name, array_index);
2964 CHARSTRING ret_val(mstrlen(result_str), result_str);
2965 Free(result_str);
2966 return ret_val;
2967 }
2968
2969 CHARSTRING get_port_name(const char *port_name, const INTEGER& array_index)
2970 {
2971 array_index.must_bound("Using an unbound integer value for indexing an "
2972 "array of ports.");
2973 return get_port_name(port_name, (int)array_index);
2974 }
2975
2976 CHARSTRING get_port_name(const CHARSTRING& port_name, int array_index)
2977 {
2978 port_name.must_bound("Internal error: Using an unbound charstring value "
2979 "to obtain the name of a port.");
2980 return get_port_name((const char*)port_name, array_index);
2981 }
2982
2983 CHARSTRING get_port_name(const CHARSTRING& port_name,
2984 const INTEGER& array_index)
2985 {
2986 port_name.must_bound("Internal error: Using an unbound charstring value "
2987 "to obtain the name of a port.");
2988 array_index.must_bound("Using an unbound integer value for indexing an "
2989 "array of ports.");
2990 return get_port_name((const char*)port_name, (int)array_index);
2991 }
2992
2993 OCTETSTRING remove_bom(const OCTETSTRING& encoded_value)
2994 {
2995 const unsigned char* str = (const unsigned char*)encoded_value;
2996 int length_of_BOM = 0;
2997 if (0x00 == str[0] && 0x00 == str[1] && 0xFE == str[2] && 0xFF == str[3]) { // UTF-32BE
2998 length_of_BOM = 4;
2999 }
3000 else if (0xFF == str[0] && 0xFE == str[1] && 0x00 == str[2] && 0x00 == str[3]) { // UTF-32LE
3001 length_of_BOM = 4;
3002 }
3003 else if (0xFE == str[0] && 0xFF == str[1]) { // UTF-16BE
3004 length_of_BOM = 2;
3005 }
3006 else if (0xFF == str[0] && 0xFE == str[1]) { // UTF-16LE
3007 length_of_BOM = 2;
3008 }
3009 else if (0xEF == str[0] && 0xBB == str[1] && 0xBF == str[2]) { // UTF-8
3010 length_of_BOM = 3;
3011 }
3012 else {
3013 return OCTETSTRING (encoded_value); // no BOM found
3014 }
3015 return OCTETSTRING (encoded_value.lengthof() - length_of_BOM, (str + length_of_BOM));
3016 }
3017
3018 CHARSTRING encode_base64(const OCTETSTRING& msg)
3019 {
3020 const char *code_table = {
3021 "ABCDEFGHIJKLMNOP"
3022 "QRSTUVWXYZabcdef"
3023 "ghijklmnopqrstuv"
3024 "wxyz0123456789+/"
3025 };
3026 const char pad = '=';
3027 const unsigned char *p_msg = (const unsigned char *)msg;
3028 int octets_left = msg.lengthof();
3029 char *output = (char*)Malloc(((octets_left*22)>>4) + 7);
3030 char *p_output = output;
3031 while(octets_left >= 3) {
3032 *p_output++ = code_table[p_msg[0] >> 2];
3033 *p_output++ = code_table[((p_msg[0] << 4) | (p_msg[1] >> 4)) & 0x3f];
3034 *p_output++ = code_table[((p_msg[1] << 2) | (p_msg[2] >> 6)) & 0x3f];
3035 *p_output++ = code_table[p_msg[2] & 0x3f];
3036 p_msg += 3;
3037 octets_left -= 3;
3038 }
3039 switch(octets_left) {
3040 case 1:
3041 *p_output++ = code_table[p_msg[0] >> 2];
3042 *p_output++ = code_table[(p_msg[0] << 4) & 0x3f];
3043 *p_output++ = pad;
3044 *p_output++ = pad;
3045 break;
3046 case 2:
3047 *p_output++ = code_table[p_msg[0] >> 2];
3048 *p_output++ = code_table[((p_msg[0] << 4) | (p_msg[1] >> 4)) & 0x3f];
3049 *p_output++ = code_table[(p_msg[1] << 2) & 0x3f];
3050 *p_output++ = pad;
3051 break;
3052 default:
3053 break;
3054 }
3055 *p_output = '\0';
3056 CHARSTRING ret_val(output);
3057 Free(output);
3058 return ret_val;
3059 }
3060
3061 CHARSTRING encode_base64(const OCTETSTRING& msg, bool use_linebreaks)
3062 {
3063 const char *code_table = {
3064 "ABCDEFGHIJKLMNOP"
3065 "QRSTUVWXYZabcdef"
3066 "ghijklmnopqrstuv"
3067 "wxyz0123456789+/"
3068 };
3069 const char pad = '=';
3070 const unsigned char *p_msg = (const unsigned char *)msg;
3071 int octets_left = msg.lengthof();
3072 char *output = (char*)Malloc(((octets_left*22)>>4) + 7);
3073 char *p_output = output;
3074 int n_4chars = 0;
3075 while(octets_left >= 3) {
3076 *p_output++ = code_table[p_msg[0] >> 2];
3077 *p_output++ = code_table[((p_msg[0] << 4) | (p_msg[1] >> 4)) & 0x3f];
3078 *p_output++ = code_table[((p_msg[1] << 2) | (p_msg[2] >> 6)) & 0x3f];
3079 *p_output++ = code_table[p_msg[2] & 0x3f];
3080 n_4chars++;
3081 if (use_linebreaks && n_4chars>=19 && octets_left != 3) {
3082 *p_output++ = '\r';
3083 *p_output++ = '\n';
3084 n_4chars = 0;
3085 }
3086 p_msg += 3;
3087 octets_left -= 3;
3088 }
3089 switch(octets_left) {
3090 case 1:
3091 *p_output++ = code_table[p_msg[0] >> 2];
3092 *p_output++ = code_table[(p_msg[0] << 4) & 0x3f];
3093 *p_output++ = pad;
3094 *p_output++ = pad;
3095 break;
3096 case 2:
3097 *p_output++ = code_table[p_msg[0] >> 2];
3098 *p_output++ = code_table[((p_msg[0] << 4) | (p_msg[1] >> 4)) & 0x3f];
3099 *p_output++ = code_table[(p_msg[1] << 2) & 0x3f];
3100 *p_output++ = pad;
3101 break;
3102 default:
3103 break;
3104 }
3105 *p_output = '\0';
3106 CHARSTRING ret_val(output);
3107 Free(output);
3108 return ret_val;
3109 }
3110
3111
3112 OCTETSTRING decode_base64(const CHARSTRING& b64)
3113 {
3114 const unsigned char decode_table[] = {
3115 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3116 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3117 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 62, 80, 80, 80, 63,
3118 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 80, 80, 80, 70, 80, 80,
3119 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
3120 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 80, 80, 80, 80, 80,
3121 80, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
3122 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 80, 80, 80, 80, 80
3123 };
3124 const unsigned char *p_b64 = (const unsigned char *) ((const char *)b64);
3125 int chars_left = b64.lengthof();
3126 unsigned char *output = (unsigned char*)Malloc(((chars_left >> 2) + 1) * 3);
3127 unsigned char *p_output = output;
3128 unsigned int bits = 0;
3129 size_t n_bits = 0;
3130 while(chars_left--) {
3131 unsigned char dec;
3132 if (*p_b64 > 0 && (dec = decode_table[*p_b64]) < 64) {
3133 bits <<= 6;
3134 bits |= dec;
3135 n_bits += 6;
3136 if (n_bits >= 8) {
3137 *p_output++ = (bits >> (n_bits - 8)) & 0xff;
3138 n_bits-= 8;
3139 }
3140 }
3141 else if (*p_b64 == '=') {
3142 break;
3143 }
3144 else {
3145 if (*p_b64 == '\r' && *(p_b64 + 1) == '\n') {
3146 ++p_b64; // skip \n too
3147 }
3148 else {
3149 TTCN_error("Error: Invalid character in Base64 encoded data: 0x%02X", *p_b64);
3150 }
3151 }
3152 ++p_b64;
3153 }
3154 OCTETSTRING ret_val(p_output - output, output);
3155 Free(output);
3156 return ret_val;
3157 }
3158
This page took 0.119924 seconds and 5 git commands to generate.