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