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