1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
10 #include "../common/memory.h"
11 #include "../common/pattern.hh"
14 #include "Bitstring.hh"
15 #include "Hexstring.hh"
16 #include "Octetstring.hh"
17 #include "Charstring.hh"
18 #include "Universal_charstring.hh"
19 #include "String_struct.hh"
21 #include "Snapshot.hh"
22 #include "TitanLoggerApi.hh"
24 #include <openssl/bn.h>
30 #include <sys/types.h>
33 #define ERRMSG_BUFSIZE 512
35 // table to reverse the hex digits within an octet
36 // input: ABCDEFGH, output: DCBAHGFE
37 static const unsigned char nibble_reverse_table
[] =
39 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
40 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f,
41 0x80, 0x88, 0x84, 0x8c, 0x82, 0x8a, 0x86, 0x8e,
42 0x81, 0x89, 0x85, 0x8d, 0x83, 0x8b, 0x87, 0x8f,
43 0x40, 0x48, 0x44, 0x4c, 0x42, 0x4a, 0x46, 0x4e,
44 0x41, 0x49, 0x45, 0x4d, 0x43, 0x4b, 0x47, 0x4f,
45 0xc0, 0xc8, 0xc4, 0xcc, 0xc2, 0xca, 0xc6, 0xce,
46 0xc1, 0xc9, 0xc5, 0xcd, 0xc3, 0xcb, 0xc7, 0xcf,
47 0x20, 0x28, 0x24, 0x2c, 0x22, 0x2a, 0x26, 0x2e,
48 0x21, 0x29, 0x25, 0x2d, 0x23, 0x2b, 0x27, 0x2f,
49 0xa0, 0xa8, 0xa4, 0xac, 0xa2, 0xaa, 0xa6, 0xae,
50 0xa1, 0xa9, 0xa5, 0xad, 0xa3, 0xab, 0xa7, 0xaf,
51 0x60, 0x68, 0x64, 0x6c, 0x62, 0x6a, 0x66, 0x6e,
52 0x61, 0x69, 0x65, 0x6d, 0x63, 0x6b, 0x67, 0x6f,
53 0xe0, 0xe8, 0xe4, 0xec, 0xe2, 0xea, 0xe6, 0xee,
54 0xe1, 0xe9, 0xe5, 0xed, 0xe3, 0xeb, 0xe7, 0xef,
55 0x10, 0x18, 0x14, 0x1c, 0x12, 0x1a, 0x16, 0x1e,
56 0x11, 0x19, 0x15, 0x1d, 0x13, 0x1b, 0x17, 0x1f,
57 0x90, 0x98, 0x94, 0x9c, 0x92, 0x9a, 0x96, 0x9e,
58 0x91, 0x99, 0x95, 0x9d, 0x93, 0x9b, 0x97, 0x9f,
59 0x50, 0x58, 0x54, 0x5c, 0x52, 0x5a, 0x56, 0x5e,
60 0x51, 0x59, 0x55, 0x5d, 0x53, 0x5b, 0x57, 0x5f,
61 0xd0, 0xd8, 0xd4, 0xdc, 0xd2, 0xda, 0xd6, 0xde,
62 0xd1, 0xd9, 0xd5, 0xdd, 0xd3, 0xdb, 0xd7, 0xdf,
63 0x30, 0x38, 0x34, 0x3c, 0x32, 0x3a, 0x36, 0x3e,
64 0x31, 0x39, 0x35, 0x3d, 0x33, 0x3b, 0x37, 0x3f,
65 0xb0, 0xb8, 0xb4, 0xbc, 0xb2, 0xba, 0xb6, 0xbe,
66 0xb1, 0xb9, 0xb5, 0xbd, 0xb3, 0xbb, 0xb7, 0xbf,
67 0x70, 0x78, 0x74, 0x7c, 0x72, 0x7a, 0x76, 0x7e,
68 0x71, 0x79, 0x75, 0x7d, 0x73, 0x7b, 0x77, 0x7f,
69 0xf0, 0xf8, 0xf4, 0xfc, 0xf2, 0xfa, 0xf6, 0xfe,
70 0xf1, 0xf9, 0xf5, 0xfd, 0xf3, 0xfb, 0xf7, 0xff
73 // table to swap the hex digits within an octet
74 // input: ABCDEFGH, output: EFGHABCD
75 static const unsigned char nibble_swap_table
[] =
77 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
78 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
79 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
80 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1,
81 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
82 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2,
83 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
84 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3,
85 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
86 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4,
87 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
88 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5,
89 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
90 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6,
91 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
92 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7,
93 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
94 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8,
95 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
96 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9,
97 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
98 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
99 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b,
100 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb,
101 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c,
102 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc,
103 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d,
104 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd,
105 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e,
106 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe,
107 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f,
108 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff
111 // table to reverse the bits within an octet
112 // input: ABCDEFGH, output: HGFEDCBA
113 static const unsigned char bit_reverse_table
[] =
115 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
116 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
117 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
118 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
119 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
120 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
121 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
122 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
123 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
124 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
125 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
126 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
127 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
128 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
129 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
130 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
131 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
132 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
133 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
134 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
135 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
136 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
137 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
138 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
139 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
140 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
141 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
142 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
143 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
144 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
145 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
146 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
149 static const unsigned char UTF8_BOM
[] = {0xef, 0xbb, 0xbf};
150 static const unsigned char UTF16BE_BOM
[] = {0xfe, 0xff};
151 static const unsigned char UTF16LE_BOM
[] = {0xff, 0xfe};
152 static const unsigned char UTF32BE_BOM
[] = {0x00, 0x00, 0xfe, 0xff};
153 static const unsigned char UTF32LE_BOM
[] = {0xff, 0xfe, 0x00, 0x00};
155 // Functions for internal purposes
157 unsigned char char_to_hexdigit(char c
)
159 if (c
>= '0' && c
<= '9') return c
- '0';
160 else if (c
>= 'A' && c
<= 'F') return c
- 'A' + 10;
161 else if (c
>= 'a' && c
<= 'f') return c
- 'a' + 10;
165 char hexdigit_to_char(unsigned char hexdigit
)
167 if (hexdigit
< 10) return '0' + hexdigit
;
168 else if (hexdigit
< 16) return 'A' + hexdigit
- 10;
172 static boolean
is_whitespace(char c
)
187 static CharCoding::CharCodingType
is_ascii ( const OCTETSTRING
& ostr
)
189 const unsigned char nonASCII
= 1 << 7;// MSB is 1 in case of non ASCII character
190 CharCoding::CharCodingType ret
= CharCoding::ASCII
;
191 const unsigned char* strptr
= (const unsigned char*)ostr
;
192 for (int i
= 0; i
< ostr
.lengthof(); ++i
) {
193 if ( strptr
[i
] & nonASCII
) {
194 ret
= CharCoding::UNKNOWN
;
201 static CharCoding::CharCodingType
is_utf8 ( const OCTETSTRING
& ostr
)
203 const char MSB
= 1 << 7; // MSB is 1 in case of non ASCII character
204 const char MSBmin1
= 1 << 6; // 0100 0000
206 const unsigned char* strptr
= (const unsigned char*)ostr
;
207 // std::cout << "UTF-8 strptr" << strptr << std::endl;
208 while (ostr
.lengthof() > i
) {
209 if ( strptr
[i
] & MSB
) { // non ASCII char
210 // std::cout << "UTF-8 strptr[" << i << "]: " << std::hex << (int)strptr[i] << std::endl;
211 char maskUTF8
= 1 << 6; // 111x xxxx shows how many additional bytes are there
212 if (!(strptr
[i
] & maskUTF8
)) return CharCoding::UNKNOWN
; // accepted 11xxx xxxx but received 10xx xxxx
213 unsigned int noofUTF8
= 0; // 11xx xxxxx -> 2 bytes, 111x xxxxx -> 3 bytes , 1111 xxxxx -> 4 bytes in UTF-8
214 while (strptr
[i
] & maskUTF8
) {
216 maskUTF8
>>= 1; // shift right the mask
218 // the second and third (and so on) UTF-8 byte looks like 10xx xxxx
219 while (0 < noofUTF8
) {
221 //std::cout << "mask & strptr[" << i << "] " << std::hex << (int)strptr[i] << std::endl;
222 if (!(strptr
[i
] & MSB
) || (strptr
[i
] & MSBmin1
) || i
>= ostr
.lengthof()) { // if not like this: 10xx xxxx
223 return CharCoding::UNKNOWN
;
230 return CharCoding::UTF_8
;
233 // Additional predefined functions defined in Annex C of ES 101 873-1
237 CHARSTRING
int2char(int value
)
239 if (value
< 0 || value
> 127) TTCN_error("The argument of function "
240 "int2char() is %d, which is outside the allowed range 0 .. 127.",
242 return CHARSTRING((char)value
);
245 CHARSTRING
int2char(const INTEGER
& value
)
247 value
.must_bound("The argument of function int2char() is an unbound "
249 const int_val_t
& ivt
= value
.get_val();
250 if (ivt
< 0 || ivt
> 127) {
251 char *value_str
= ivt
.as_string();
252 TTCN_error("The argument of function int2char() is %s, "
253 "which is outside the allowed range 0 .. 127.", value_str
);
256 return CHARSTRING((char)((int)value
));
261 UNIVERSAL_CHARSTRING
int2unichar(int value
)
263 if (value
< 0 || value
> 2147483647) TTCN_error("The argument of function "
264 "int2unichar() is %d, which outside the allowed range 0 .. 2147483647.",
266 return UNIVERSAL_CHARSTRING(value
>> 24, (value
>> 16) & 0xFF,
267 (value
>> 8) & 0xFF, value
& 0xFF);
270 UNIVERSAL_CHARSTRING
int2unichar(const INTEGER
& value
)
272 value
.must_bound("The argument of function int2unichar() is an unbound "
274 const int_val_t
& ivt
= value
.get_val();
275 if (ivt
< 0 || ivt
> 2147483647) {
276 char *value_str
= ivt
.as_string();
277 TTCN_error("The argument of function int2unichar() is %s, "
278 "which outside the allowed range 0 .. 2147483647.", value_str
);
281 return int2unichar((int)value
);
286 BITSTRING
int2bit(const INTEGER
& value
, int length
)
288 value
.must_bound("The first argument (value) of function int2bit() is "
289 "an unbound integer value.");
290 int_val_t
tmp_value(value
.get_val());
292 char *value_str
= tmp_value
.as_string();
293 TTCN_error("The first argument (value) of function "
294 "int2bit() is a negative integer value: %s.", value_str
);
297 if (length
< 0) TTCN_error("The second argument (length) of function "
298 "int2bit() is a negative integer value: %d.", length
);
299 BITSTRING
ret_val(length
);
300 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
301 // clearing all bits in the result
302 memset(bits_ptr
, '\0', (length
+ 7) / 8);
303 // we are setting some bits to 1 so we may stop if there are no more 1 bits
305 for (int i
= length
- 1; tmp_value
!= 0 && i
>= 0; i
--) {
306 if ((tmp_value
& 1).get_val()) bits_ptr
[i
/ 8] |= (1 << (i
% 8));
309 if (tmp_value
!= 0) {
310 char *value_str
= value
.get_val().as_string(); // not tmp_value!
311 TTCN_error("The first argument of function int2bit(), which is %s, "
312 "does not fit in %d bit%s.", value_str
, length
,
313 length
> 1 ? "s" :"");
319 BITSTRING
int2bit(int value
, const INTEGER
& length
)
321 length
.must_bound("The second argument (length) of function int2bit() is "
322 "an unbound integer value.");
323 return int2bit(INTEGER(value
), (int)length
);
326 BITSTRING
int2bit(int value
, int length
)
328 return int2bit(INTEGER(value
), length
);
331 BITSTRING
int2bit(const INTEGER
& value
, const INTEGER
& length
)
333 value
.must_bound("The first argument (value) of function int2bit() is "
334 "an unbound integer value.");
335 length
.must_bound("The second argument (length) of function int2bit() is "
336 "an unbound integer value.");
337 return int2bit(value
, (int)length
);
342 HEXSTRING
int2hex(const INTEGER
& value
, int length
)
344 value
.must_bound("The first argument (value) of function int2hex() is "
345 "an unbound integer value.");
346 int_val_t
tmp_value(value
.get_val());
348 char *value_str
= tmp_value
.as_string();
349 TTCN_error("The first argument (value) of function int2hex() is a "
350 "negative integer value: %s.", value_str
);
353 if (length
< 0) TTCN_error("The second argument (length) of function "
354 "int2hex() is a negative integer value: %d.", length
);
355 HEXSTRING
ret_val(length
);
356 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
357 // clearing the unused bits in the last octet if necessary
358 if (length
% 2) nibbles_ptr
[length
/ 2] = '\0';
359 for (int i
= length
- 1; i
>= 0; i
--) {
360 if (i
% 2) nibbles_ptr
[i
/ 2] = (tmp_value
& 0xF).get_val() << 4;
361 else nibbles_ptr
[i
/ 2] |= (tmp_value
& 0xF).get_val();
364 if (tmp_value
!= 0) {
365 char *value_str
= value
.get_val().as_string(); // not tmp_value!
366 TTCN_error("The first argument of function int2hex(), which is %s, "
367 "does not fit in %d hexadecimal digit%s.", value_str
, length
,
368 length
> 1 ? "s" :"");
369 Free(value_str
); // ???
374 HEXSTRING
int2hex(int value
, const INTEGER
& length
)
376 length
.must_bound("The second argument (length) of function int2hex() is "
377 "an unbound integer value.");
378 return int2hex(INTEGER(value
), (int)length
);
381 HEXSTRING
int2hex(int value
, int length
)
383 return int2hex(INTEGER(value
), length
);
386 HEXSTRING
int2hex(const INTEGER
& value
, const INTEGER
& length
)
388 value
.must_bound("The first argument (value) of function int2hex() is "
389 "an unbound integer value.");
390 length
.must_bound("The second argument (length) of function int2hex() is "
391 "an unbound integer value.");
392 return int2hex(value
, (int)length
);
397 OCTETSTRING
int2oct(int value
, int length
)
399 if (value
< 0) TTCN_error("The first argument (value) of function "
400 "int2oct() is a negative integer value: %d.", value
);
401 if (length
< 0) TTCN_error("The second argument (length) of function "
402 "int2oct() is a negative integer value: %d.", length
);
403 OCTETSTRING
ret_val(length
);
404 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
405 unsigned int tmp_value
= value
;
406 for (int i
= length
- 1; i
>= 0; i
--) {
407 octets_ptr
[i
] = tmp_value
& 0xFF;
410 if (tmp_value
!= 0) {
411 TTCN_error("The first argument of function int2oct(), which is %d, "
412 "does not fit in %d octet%s.", value
, length
,
413 length
> 1 ? "s" :"");
418 OCTETSTRING
int2oct(int value
, const INTEGER
& length
)
420 length
.must_bound("The second argument (length) of function int2oct() is "
421 "an unbound integer value.");
422 return int2oct(value
, (int)length
);
425 OCTETSTRING
int2oct(const INTEGER
& value
, int length
)
427 value
.must_bound("The first argument (value) of function int2oct() is "
428 "an unbound integer value.");
429 const int_val_t
& value_int
= value
.get_val();
430 char *tmp_str
= value_int
.as_string();
431 CHARSTRING
value_str(tmp_str
);
433 if (value_int
.is_native()) {
434 return int2oct((int)value
, length
);
436 if (value_int
< 0) TTCN_error("The first argument (value) of function "
437 "int2oct() is a negative integer value: %s.",
438 (const char *)value_str
);
439 if (length
< 0) TTCN_error("The second argument (length) of function "
440 "int2oct() is a negative integer value: %d.", length
);
441 OCTETSTRING
ret_val(length
);
442 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
443 BIGNUM
*value_tmp
= BN_dup(value_int
.get_val_openssl());
444 int bytes
= BN_num_bytes(value_tmp
);
445 if (bytes
> length
) {
447 TTCN_error("The first argument of function int2oct(), which is %s, "
448 "does not fit in %d octet%s.", (const char *)value_str
, length
,
449 length
> 1 ? "s" : "");
451 for (int i
= length
- 1; i
>= 0; i
--) {
452 if (value_tmp
->top
) {
453 octets_ptr
[i
] = value_tmp
->d
[0] & 0xff;
454 BN_rshift(value_tmp
, value_tmp
, 8);
456 else { // we used up all of the bignum; zero the beginning and quit
457 memset(octets_ptr
, 0, i
+1);
467 OCTETSTRING
int2oct(const INTEGER
& value
, const INTEGER
& length
)
469 value
.must_bound("The first argument (value) of function int2oct() is an "
470 "unbound integer value.");
471 length
.must_bound("The second argument (length) of function int2oct() is "
472 "an unbound integer value.");
473 const int_val_t
& value_int
= value
.get_val();
474 if (value_int
.is_native()) return int2oct(value_int
.get_val(), (int)length
);
475 return int2oct(value
, (int)length
);
480 CHARSTRING
int2str(int value
)
483 int str_len
= snprintf(str_buf
, sizeof(str_buf
), "%d", value
);
484 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
485 TTCN_error("Internal error: system call snprintf() returned "
486 "unexpected status code %d when converting value %d in function "
487 "int2str().", str_len
, value
);
489 return CHARSTRING(str_len
, str_buf
);
492 CHARSTRING
int2str(const INTEGER
& value
)
494 value
.must_bound("The argument of function int2str() is an unbound "
496 char *value_tmp
= value
.get_val().as_string();
497 CHARSTRING
value_str(value_tmp
);
504 double int2float(int value
)
506 return (double)value
;
509 double int2float(const INTEGER
& value
)
511 value
.must_bound("The argument of function int2float() is an unbound "
513 return value
.get_val().to_real();
518 INTEGER
float2int(double value
)
520 if (value
>= (double)INT_MIN
&& value
<= (double)INT_MAX
) return (int)value
;
521 // DBL_MAX has 316 digits including the trailing 0-s on x86_64.
523 snprintf(buf
, 511, "%f", value
);
524 char *dot
= strchr(buf
, '.');
525 if (!dot
) TTCN_error("Conversion of float value `%f' to integer failed", value
);
526 else memset(dot
, 0, sizeof(buf
) - (dot
- buf
));
530 INTEGER
float2int(const FLOAT
& value
)
532 value
.must_bound("The argument of function float2int() is an unbound float "
534 return float2int((double)value
);
539 int char2int(char value
)
541 unsigned char uchar_value
= value
;
542 if (uchar_value
> 127) TTCN_error("The argument of function "
543 "char2int() contains a character with character code %u, which is "
544 "outside the allowed range 0 .. 127.", uchar_value
);
548 int char2int(const char *value
)
550 if (value
== NULL
) value
= "";
551 int value_length
= strlen(value
);
552 if (value_length
!= 1) TTCN_error("The length of the argument in function "
553 "char2int() must be exactly 1 instead of %d.", value_length
);
554 return char2int(value
[0]);
557 int char2int(const CHARSTRING
& value
)
559 value
.must_bound("The argument of function char2int() is an unbound "
560 "charstring value.");
561 int value_length
= value
.lengthof();
562 if (value_length
!= 1) TTCN_error("The length of the argument in function "
563 "char2int() must be exactly 1 instead of %d.", value_length
);
564 return char2int(((const char*)value
)[0]);
567 int char2int(const CHARSTRING_ELEMENT
& value
)
569 value
.must_bound("The argument of function char2int() is an unbound "
570 "charstring element.");
571 return char2int(value
.get_char());
576 OCTETSTRING
char2oct(const char *value
)
578 if (value
== NULL
) return OCTETSTRING(0, NULL
);
579 else return OCTETSTRING(strlen(value
), (const unsigned char*)value
);
582 OCTETSTRING
char2oct(const CHARSTRING
& value
)
584 value
.must_bound("The argument of function char2oct() is an unbound "
585 "charstring value.");
586 return OCTETSTRING(value
.lengthof(),
587 (const unsigned char*)(const char*)value
);
590 OCTETSTRING
char2oct(const CHARSTRING_ELEMENT
& value
)
592 value
.must_bound("The argument of function char2oct() is an unbound "
593 "charstring element.");
594 unsigned char octet
= value
.get_char();
595 return OCTETSTRING(1, &octet
);
598 // C.11 - unichar2int
600 int unichar2int(const universal_char
& value
)
602 if (value
.uc_group
> 127) TTCN_error("The argument of function "
603 "unichar2int() is the invalid quadruple char(%u, %u, %u, %u), the "
604 "first number of which is outside the allowed range 0 .. 127.",
605 value
.uc_group
, value
.uc_plane
, value
.uc_row
, value
.uc_cell
);
606 int result
= (value
.uc_group
<< 24) | (value
.uc_plane
<< 16) |
607 (value
.uc_row
<< 8) | value
.uc_cell
;
611 int unichar2int(const UNIVERSAL_CHARSTRING
& value
)
613 value
.must_bound("The argument of function unichar2int() is an unbound "
614 "universal charstring value.");
615 int value_length
= value
.lengthof();
616 if (value_length
!= 1) TTCN_error("The length of the argument in function "
617 "unichar2int() must be exactly 1 instead of %d.", value_length
);
618 return unichar2int(((const universal_char
*)value
)[0]);
621 int unichar2int(const UNIVERSAL_CHARSTRING_ELEMENT
& value
)
623 value
.must_bound("The argument of function unichar2int() is an unbound "
624 "universal charstring element.");
625 return unichar2int(value
.get_uchar());
630 INTEGER
bit2int(const BITSTRING
& value
)
632 value
.must_bound("The argument of function bit2int() is an unbound "
634 int n_bits
= value
.lengthof();
635 const unsigned char *bit_ptr
= (const unsigned char *)value
;
636 // skip the leading zero bits
638 for (start_index
= 0; start_index
< n_bits
; start_index
++)
639 if (bit_ptr
[start_index
/ 8] & (1 << (start_index
% 8))) break;
641 int_val_t
ret_val((RInt
)0);
642 for (int i
= start_index
; i
< n_bits
; i
++) {
644 if (bit_ptr
[i
/ 8] & (1 << (i
% 8))) ret_val
+= 1;
646 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
647 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
650 INTEGER
bit2int(const BITSTRING_ELEMENT
& value
)
652 value
.must_bound("The argument of function bit2int() is an unbound "
653 "bitstring element.");
654 return INTEGER(value
.get_bit() ? 1 : 0);
659 HEXSTRING
bit2hex(const BITSTRING
& value
)
661 value
.must_bound("The argument of function bit2hex() is an unbound "
663 int n_bits
= value
.lengthof();
664 int n_nibbles
= (n_bits
+ 3) / 4;
665 int padding_bits
= 4 * n_nibbles
- n_bits
;
666 const unsigned char *bits_ptr
= (const unsigned char *)value
;
667 HEXSTRING
ret_val(n_nibbles
);
668 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
669 memset(nibbles_ptr
, '\0', (n_nibbles
+ 1) / 2);
670 for (int i
= 0; i
< n_bits
; i
++) {
671 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) {
672 nibbles_ptr
[(i
+ padding_bits
) / 8] |= 0x80 >>
673 ((i
+ padding_bits
+ 4) % 8);
679 HEXSTRING
bit2hex(const BITSTRING_ELEMENT
& value
)
681 value
.must_bound("The argument of function bit2hex() is an unbound "
682 "bitstring element.");
683 unsigned char nibble
= value
.get_bit() ? 0x01 : 0x00;
684 return HEXSTRING(1, &nibble
);
689 OCTETSTRING
bit2oct(const BITSTRING
& value
)
691 value
.must_bound("The argument of function bit2oct() is an unbound "
693 int n_bits
= value
.lengthof();
694 int n_octets
= (n_bits
+ 7) / 8;
695 int padding_bits
= 8 * n_octets
- n_bits
;
696 const unsigned char *bits_ptr
= (const unsigned char *)value
;
697 OCTETSTRING
ret_val(n_octets
);
698 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
699 memset(octets_ptr
, '\0', n_octets
);
700 for (int i
= 0; i
< n_bits
; i
++) {
701 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) {
702 octets_ptr
[(i
+ padding_bits
) / 8] |= 0x80 >>
703 ((i
+ padding_bits
) % 8);
709 OCTETSTRING
bit2oct(const BITSTRING_ELEMENT
& value
)
711 value
.must_bound("The argument of function bit2oct() is an unbound "
712 "bitstring element.");
713 unsigned char octet
= value
.get_bit() ? 0x01 : 0x00;
714 return OCTETSTRING(1, &octet
);
719 CHARSTRING
bit2str(const BITSTRING
& value
)
721 value
.must_bound("The argument of function bit2str() is an unbound "
723 int n_bits
= value
.lengthof();
724 const unsigned char *bits_ptr
= (const unsigned char*)value
;
725 CHARSTRING
ret_val(n_bits
);
726 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
727 for (int i
= 0; i
< n_bits
; i
++) {
728 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) chars_ptr
[i
] = '1';
729 else chars_ptr
[i
] = '0';
734 CHARSTRING
bit2str(const BITSTRING_ELEMENT
& value
)
736 value
.must_bound("The argument of function bit2str() is an unbound "
737 "bitstring element.");
738 return CHARSTRING(value
.get_bit() ? '1' : '0');
743 INTEGER
hex2int(const HEXSTRING
& value
)
745 value
.must_bound("The argument of function hex2int() is an unbound "
747 int n_nibbles
= value
.lengthof();
748 const unsigned char *nibble_ptr
= (const unsigned char *)value
;
749 // skip the leading zero hex digits
751 for (start_index
= 0; start_index
< n_nibbles
; start_index
++) {
752 unsigned char mask
= start_index
% 2 ? 0xF0 : 0x0F;
753 if (nibble_ptr
[start_index
/ 2] & mask
) break;
756 int_val_t
ret_val((RInt
)0);
757 for (int i
= start_index
; i
< n_nibbles
; i
++) {
759 if (i
% 2) ret_val
+= nibble_ptr
[i
/ 2] >> 4;
760 else ret_val
+= nibble_ptr
[i
/ 2] & 0x0F;
762 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
763 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
766 INTEGER
hex2int(const HEXSTRING_ELEMENT
& value
)
768 value
.must_bound("The argument of function hex2int() is an unbound "
769 "hexstring element.");
770 return INTEGER(value
.get_nibble());
775 BITSTRING
hex2bit(const HEXSTRING
& value
)
777 value
.must_bound("The argument of function hex2bit() is an unbound "
779 int n_nibbles
= value
.lengthof();
780 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
781 BITSTRING
ret_val(4 * n_nibbles
);
782 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
783 int n_octets
= (n_nibbles
+ 1) / 2;
784 for (int i
= 0; i
< n_octets
; i
++) {
785 bits_ptr
[i
] = nibble_reverse_table
[nibbles_ptr
[i
]];
787 ret_val
.clear_unused_bits();
791 BITSTRING
hex2bit(const HEXSTRING_ELEMENT
& value
)
793 value
.must_bound("The argument of function hex2bit() is an unbound "
794 "hexstring element.");
795 unsigned char bits
= nibble_reverse_table
[value
.get_nibble()];
796 return BITSTRING(4, &bits
);
801 OCTETSTRING
hex2oct(const HEXSTRING
& value
)
803 value
.must_bound("The argument of function hex2oct() is an unbound "
805 int n_nibbles
= value
.lengthof();
806 int n_octets
= (n_nibbles
+ 1) / 2;
807 int padding_nibbles
= n_nibbles
% 2;
808 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
809 OCTETSTRING
ret_val(n_octets
);
810 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
811 if (padding_nibbles
> 0) octets_ptr
[0] = 0;
812 for (int i
= 0; i
< n_nibbles
; i
++) {
813 unsigned char hexdigit
;
814 if (i
% 2) hexdigit
= nibbles_ptr
[i
/ 2] >> 4;
815 else hexdigit
= nibbles_ptr
[i
/ 2] & 0x0F;
816 if ((i
+ padding_nibbles
) % 2)
817 octets_ptr
[(i
+ padding_nibbles
) / 2] |= hexdigit
;
818 else octets_ptr
[(i
+ padding_nibbles
) / 2] = hexdigit
<< 4;
823 OCTETSTRING
hex2oct(const HEXSTRING_ELEMENT
& value
)
825 value
.must_bound("The argument of function hex2oct() is an unbound "
826 "hexstring element.");
827 unsigned char octet
= value
.get_nibble();
828 return OCTETSTRING(1, &octet
);
833 CHARSTRING
hex2str(const HEXSTRING
& value
)
835 value
.must_bound("The argument of function hex2str() is an unbound "
837 int n_nibbles
= value
.lengthof();
838 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
839 CHARSTRING
ret_val(n_nibbles
);
840 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
841 for (int i
= 0; i
< n_nibbles
; i
++) {
842 unsigned char hexdigit
;
843 if (i
% 2) hexdigit
= nibbles_ptr
[i
/ 2] >> 4;
844 else hexdigit
= nibbles_ptr
[i
/ 2] & 0x0F;
845 chars_ptr
[i
] = hexdigit_to_char(hexdigit
);
850 CHARSTRING
hex2str(const HEXSTRING_ELEMENT
& value
)
852 value
.must_bound("The argument of function hex2str() is an unbound "
853 "hexstring element.");
854 return CHARSTRING(hexdigit_to_char(value
.get_nibble()));
859 INTEGER
oct2int(const OCTETSTRING
& value
)
861 value
.must_bound("The argument of function oct2int() is an unbound "
862 "octetstring value.");
863 int n_octets
= value
.lengthof();
864 const unsigned char *octet_ptr
= (const unsigned char *)value
;
866 for (start_index
= 0; start_index
< n_octets
; start_index
++)
867 if (octet_ptr
[start_index
]) break;
868 int_val_t
ret_val((RInt
)0);
869 for (int i
= start_index
; i
< n_octets
; i
++) {
871 ret_val
+= octet_ptr
[i
];
873 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
874 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
877 INTEGER
oct2int(const OCTETSTRING_ELEMENT
& value
)
879 value
.must_bound("The argument of function oct2int() is an unbound "
880 "octetstring element.");
881 return INTEGER(value
.get_octet());
886 BITSTRING
oct2bit(const OCTETSTRING
& value
)
888 value
.must_bound("The argument of function oct2bit() is an unbound "
889 "octetstring value.");
890 int n_octets
= value
.lengthof();
891 const unsigned char *octets_ptr
= (const unsigned char *)value
;
892 BITSTRING
ret_val(8 * n_octets
);
893 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
894 for (int i
= 0; i
< n_octets
; i
++) {
895 bits_ptr
[i
] = bit_reverse_table
[octets_ptr
[i
]];
900 BITSTRING
oct2bit(const OCTETSTRING_ELEMENT
& value
)
902 value
.must_bound("The argument of function oct2bit() is an unbound "
903 "octetstring element.");
904 unsigned char bits
= bit_reverse_table
[value
.get_octet()];
905 return BITSTRING(8, &bits
);
910 HEXSTRING
oct2hex(const OCTETSTRING
& value
)
912 value
.must_bound("The argument of function oct2hex() is an unbound "
913 "octetstring value.");
914 int n_octets
= value
.lengthof();
915 const unsigned char *octets_ptr
= (const unsigned char *)value
;
916 HEXSTRING
ret_val(2 * n_octets
);
917 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
918 for (int i
= 0; i
< n_octets
; i
++) {
919 nibbles_ptr
[i
] = nibble_swap_table
[octets_ptr
[i
]];
924 HEXSTRING
oct2hex(const OCTETSTRING_ELEMENT
& value
)
926 value
.must_bound("The argument of function oct2hex() is an unbound "
927 "octetstring element.");
928 unsigned char nibbles
= nibble_swap_table
[value
.get_octet()];
929 return HEXSTRING(2, &nibbles
);
934 CHARSTRING
oct2str(const OCTETSTRING
& value
)
936 value
.must_bound("The argument of function oct2str() is an unbound "
937 "octetstring value.");
938 int n_octets
= value
.lengthof();
939 const unsigned char *octets_ptr
= (const unsigned char *)value
;
940 CHARSTRING
ret_val(2 * n_octets
);
941 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
942 for (int i
= 0; i
< n_octets
; i
++) {
943 chars_ptr
[2 * i
] = hexdigit_to_char(octets_ptr
[i
] >> 4);
944 chars_ptr
[2 * i
+ 1] = hexdigit_to_char(octets_ptr
[i
] & 0x0F);
949 CHARSTRING
oct2str(const OCTETSTRING_ELEMENT
& value
)
951 value
.must_bound("The argument of function oct2str() is an unbound "
952 "octetstring element.");
953 unsigned char octet
= value
.get_octet();
955 result
[0] = hexdigit_to_char(octet
>> 4);
956 result
[1] = hexdigit_to_char(octet
& 0x0F);
957 return CHARSTRING(2, result
);
962 CHARSTRING
oct2char(const OCTETSTRING
& value
)
964 value
.must_bound("The argument of function oct2char() is an unbound "
965 "octetstring value.");
966 int value_length
= value
.lengthof();
967 const unsigned char *octets_ptr
= (const unsigned char*)value
;
968 for (int i
= 0; i
< value_length
; i
++) {
969 unsigned char octet
= octets_ptr
[i
];
970 if (octet
> 127) TTCN_error("The argument of function oct2char() "
971 "contains octet %02X at index %d, which is outside the allowed "
972 "range 00 .. 7F.", octet
, i
);
974 return CHARSTRING(value_length
, (const char*)octets_ptr
);
977 CHARSTRING
oct2char(const OCTETSTRING_ELEMENT
& value
)
979 value
.must_bound("The argument of function oct2char() is an unbound "
980 "octetstring element.");
981 unsigned char octet
= value
.get_octet();
982 if (octet
> 127) TTCN_error("The argument of function oct2char() "
983 "contains the octet %02X, which is outside the allowed range 00 .. 7F.",
985 return CHARSTRING((char)octet
);
988 UNIVERSAL_CHARSTRING
oct2unichar(const OCTETSTRING
& invalue
)
990 // default encoding is UTF-8
991 UNIVERSAL_CHARSTRING ucstr
;
992 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
993 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
994 ucstr
.decode_utf8(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF_8
, true);
995 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
999 UNIVERSAL_CHARSTRING
oct2unichar(const OCTETSTRING
& invalue
,
1000 const CHARSTRING
& string_encoding
)
1002 UNIVERSAL_CHARSTRING ucstr
;
1003 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
1004 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
1005 if ("UTF-8" == string_encoding
) {
1006 ucstr
.decode_utf8(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF_8
, true);
1008 else if ("UTF-16" == string_encoding
) {
1009 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16
);
1011 else if ("UTF-16BE" == string_encoding
) {
1012 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16BE
);
1014 else if ("UTF-16LE" == string_encoding
) {
1015 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16LE
);
1017 else if ("UTF-32" == string_encoding
) {
1018 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32
);
1020 else if ("UTF-32BE" == string_encoding
) {
1021 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32BE
);
1023 else if ("UTF-32LE" == string_encoding
) {
1024 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32LE
);
1026 else { TTCN_error("oct2unichar: Invalid parameter: %s", (const char*)string_encoding
);
1028 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
1034 INTEGER
str2int(const char *value
)
1036 return str2int(CHARSTRING(value
));
1039 INTEGER
str2int(const CHARSTRING
& value
)
1041 value
.must_bound("The argument of function str2int() is an unbound "
1042 "charstring value.");
1043 int value_len
= value
.lengthof();
1044 if (value_len
== 0) TTCN_error("The argument of function str2int() is an "
1045 "empty string, which does not represent a valid integer value.");
1046 const char *value_str
= value
;
1047 enum { S_INITIAL
, S_FIRST
, S_ZERO
, S_MORE
, S_END
, S_ERR
} state
= S_INITIAL
;
1048 // state: expected characters
1049 // S_INITIAL: +, -, first digit, leading whitespace
1050 // S_FIRST: first digit
1051 // S_ZERO, S_MORE: more digit(s), trailing whitespace
1052 // S_END: trailing whitespace
1053 // S_ERR: error was found, stop
1054 boolean leading_ws
= FALSE
, leading_zero
= FALSE
;
1055 for (int i
= 0; i
< value_len
; i
++) {
1056 char c
= value_str
[i
];
1059 if (c
== '+' || c
== '-') state
= S_FIRST
;
1060 else if (c
== '0') state
= S_ZERO
;
1061 else if (c
>= '1' && c
<= '9') state
= S_MORE
;
1062 else if (is_whitespace(c
)) leading_ws
= TRUE
;
1066 if (c
== '0') state
= S_ZERO
;
1067 else if (c
>= '1' && c
<= '9') state
= S_MORE
;
1071 if (c
>= '0' && c
<= '9') {
1072 leading_zero
= TRUE
;
1074 } else if (is_whitespace(c
)) state
= S_END
;
1078 if (c
>= '0' && c
<= '9') {}
1079 else if (is_whitespace(c
)) state
= S_END
;
1083 if (!is_whitespace(c
)) state
= S_ERR
;
1088 if (state
== S_ERR
) {
1089 TTCN_error_begin("The argument of function str2int(), which is ");
1091 TTCN_Logger::log_event_str(", does not represent a valid integer "
1092 "value. Invalid character `");
1093 TTCN_Logger::log_char_escaped(c
);
1094 TTCN_Logger::log_event("' was found at index %d.", i
);
1098 if (state
!= S_ZERO
&& state
!= S_MORE
&& state
!= S_END
) {
1099 TTCN_error_begin("The argument of function str2int(), which is ");
1101 TTCN_Logger::log_event_str(", does not represent a valid integer "
1102 "value. Premature end of the string.");
1106 TTCN_warning_begin("Leading whitespace was detected in the argument "
1107 "of function str2int(): ");
1109 TTCN_Logger::log_char('.');
1113 TTCN_warning_begin("Leading zero digit was detected in the argument "
1114 "of function str2int(): ");
1116 TTCN_Logger::log_char('.');
1119 if (state
== S_END
) {
1120 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1121 "of function str2int(): ");
1123 TTCN_Logger::log_char('.');
1126 return INTEGER(value_str
);
1129 INTEGER
str2int(const CHARSTRING_ELEMENT
& value
)
1131 value
.must_bound("The argument of function str2int() is an unbound "
1132 "charstring element.");
1133 char c
= value
.get_char();
1134 if (c
< '0' || c
> '9') {
1135 TTCN_error_begin("The argument of function str2int(), which is a "
1136 "charstring element containing character `");
1137 TTCN_Logger::log_char_escaped(c
);
1138 TTCN_Logger::log_event_str("', does not represent a valid integer "
1142 return INTEGER(c
- '0');
1147 OCTETSTRING
str2oct(const char *value
)
1149 if (value
== NULL
) return OCTETSTRING(0, NULL
);
1150 else return str2oct(CHARSTRING(value
));
1153 OCTETSTRING
str2oct(const CHARSTRING
& value
)
1155 value
.must_bound("The argument of function str2oct() is an unbound "
1156 "charstring value.");
1157 int value_len
= value
.lengthof();
1158 if (value_len
% 2) TTCN_error("The argument of function str2oct() must "
1159 "have even number of characters containing hexadecimal digits, but "
1160 "the length of the string is odd: %d.", value_len
);
1161 OCTETSTRING
ret_val(value_len
/ 2);
1162 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
1163 const char *chars_ptr
= value
;
1164 for (int i
= 0; i
< value_len
; i
++) {
1165 char c
= chars_ptr
[i
];
1166 unsigned char hex_digit
= char_to_hexdigit(c
);
1167 if (hex_digit
> 0x0F) {
1168 TTCN_error_begin("The argument of function str2oct() shall "
1169 "contain hexadecimal digits only, but character `");
1170 TTCN_Logger::log_char_escaped(c
);
1171 TTCN_Logger::log_event("' was found at index %d.", i
);
1174 if (i
% 2) octets_ptr
[i
/ 2] |= hex_digit
;
1175 else octets_ptr
[i
/ 2] = hex_digit
<< 4;
1182 double str2float(const char *value
)
1184 return str2float(CHARSTRING(value
));
1188 * leading zeros are allowed;
1189 * leading "+" sign before positive values is allowed;
1190 * "-0.0" is allowed;
1191 * no numbers after the dot in the decimal notation are allowed.
1193 double str2float(const CHARSTRING
& value
)
1195 value
.must_bound("The argument of function str2float() is an unbound "
1196 "charstring value.");
1197 int value_len
= value
.lengthof();
1198 if (value_len
== 0) TTCN_error("The argument of function str2float() is "
1199 "an empty string, which does not represent a valid float value.");
1200 const char *value_str
= value
;
1201 enum { S_INITIAL
, S_FIRST_M
, S_ZERO_M
, S_MORE_M
, S_FIRST_F
, S_MORE_F
,
1202 S_INITIAL_E
, S_FIRST_E
, S_ZERO_E
, S_MORE_E
, S_END
, S_ERR
}
1204 // state: expected characters
1205 // S_INITIAL: +, -, first digit of integer part in mantissa,
1206 // leading whitespace
1207 // S_FIRST_M: first digit of integer part in mantissa
1208 // S_ZERO_M, S_MORE_M: more digits of mantissa, decimal dot, E
1209 // S_FIRST_F: first digit of fraction
1210 // S_MORE_F: more digits of fraction, E, trailing whitespace
1211 // S_INITIAL_E: +, -, first digit of exponent
1212 // S_FIRST_E: first digit of exponent
1213 // S_ZERO_E, S_MORE_E: more digits of exponent, trailing whitespace
1214 // S_END: trailing whitespace
1215 // S_ERR: error was found, stop
1216 boolean leading_ws
= FALSE
, leading_zero
= FALSE
;
1217 for (int i
= 0; i
< value_len
; i
++) {
1218 char c
= value_str
[i
];
1221 if (c
== '+' || c
== '-') state
= S_FIRST_M
;
1222 else if (c
== '0') state
= S_ZERO_M
;
1223 else if (c
>= '1' && c
<= '9') state
= S_MORE_M
;
1224 else if (is_whitespace(c
)) leading_ws
= TRUE
;
1227 case S_FIRST_M
: // first mantissa digit
1228 if (c
== '0') state
= S_ZERO_M
;
1229 else if (c
>= '1' && c
<= '9') state
= S_MORE_M
;
1232 case S_ZERO_M
: // leading mantissa zero
1233 if (c
== '.') state
= S_FIRST_F
;
1234 else if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1235 else if (c
>= '0' && c
<= '9') {
1236 leading_zero
= TRUE
;
1238 } else state
= S_ERR
;
1241 if (c
== '.') state
= S_FIRST_F
;
1242 else if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1243 else if (c
>= '0' && c
<= '9') {}
1247 if (c
>= '0' && c
<= '9') state
= S_MORE_F
;
1251 if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1252 else if (c
>= '0' && c
<= '9') {}
1253 else if (is_whitespace(c
)) state
= S_END
;
1257 if (c
== '+' || c
== '-') state
= S_FIRST_E
;
1258 else if (c
== '0') state
= S_ZERO_E
;
1259 else if (c
>= '1' && c
<= '9') state
= S_MORE_E
;
1263 if (c
== '0') state
= S_ZERO_E
;
1264 else if (c
>= '1' && c
<= '9') state
= S_MORE_E
;
1268 if (c
>= '0' && c
<= '9') {
1269 leading_zero
= TRUE
;
1271 } else if (is_whitespace(c
)) state
= S_END
;
1275 if (c
>= '0' && c
<= '9') {}
1276 else if (is_whitespace(c
)) state
= S_END
;
1280 if (!is_whitespace(c
)) state
= S_ERR
;
1285 if (state
== S_ERR
) {
1286 TTCN_error_begin("The argument of function str2float(), which is ");
1288 TTCN_Logger::log_event_str(", does not represent a valid float "
1289 "value. Invalid character `");
1290 TTCN_Logger::log_char_escaped(c
);
1291 TTCN_Logger::log_event("' was found at index %d.", i
);
1303 // OK now (decimal dot missing after mantissa)
1306 // OK now (fraction part missing)
1309 TTCN_error_begin("The argument of function str2float(), which is ");
1311 TTCN_Logger::log_event_str(", does not represent a valid float value. "
1312 "Premature end of the string.");
1317 TTCN_warning_begin("Leading whitespace was detected in the argument "
1318 "of function str2float(): ");
1320 TTCN_Logger::log_char('.');
1324 TTCN_warning_begin("Leading zero digit was detected in the argument "
1325 "of function str2float(): ");
1327 TTCN_Logger::log_char('.');
1330 if (state
== S_END
) {
1331 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1332 "of function str2float(): ");
1334 TTCN_Logger::log_char('.');
1337 return atof(value_str
);
1342 CHARSTRING
regexp(const CHARSTRING
& instr
, const CHARSTRING
& expression
,
1345 instr
.must_bound("The first argument (instr) of function regexp() is an "
1346 "unbound charstring value.");
1347 expression
.must_bound("The second argument (expression) of function "
1348 "regexp() is an unbound charstring value.");
1349 if (groupno
< 0) TTCN_error("The third argument (groupno) of function "
1350 "regexp() is a negative integer value: %d.", groupno
);
1351 int instr_len
= instr
.lengthof();
1352 const char *instr_str
= instr
;
1353 for (int i
= 0; i
< instr_len
; i
++) {
1354 if (instr_str
[i
] == '\0') {
1355 TTCN_warning_begin("The first argument (instr) of function regexp(), "
1358 TTCN_Logger::log_event(", contains a character with zero character code "
1359 "at index %d. The rest of the string will be ignored during matching.",
1365 int expression_len
= expression
.lengthof();
1366 const char *expression_str
= expression
;
1367 for (int i
= 0; i
< expression_len
; i
++) {
1368 if (expression_str
[i
] == '\0') {
1369 TTCN_warning_begin("The second argument (expression) of function "
1370 "regexp(), which is ");
1372 TTCN_Logger::log_event(", contains a character with zero character code "
1373 "at index %d. The rest of the string will be ignored during matching.",
1379 char *posix_str
= TTCN_pattern_to_regexp(expression_str
);
1380 if (posix_str
== NULL
) {
1381 TTCN_error_begin("The second argument (expression) of function "
1382 "regexp(), which is ");
1384 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1387 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED
)) {
1388 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED
);
1389 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1390 CHARSTRING_template(STRING_PATTERN
, expression
).log();
1391 TTCN_Logger::log_event_str(" is: ");
1392 CHARSTRING(posix_str
).log();
1393 TTCN_Logger::end_event();
1395 regex_t posix_regexp
;
1396 int ret_val
= regcomp(&posix_regexp
, posix_str
, REG_EXTENDED
);
1399 char msg
[ERRMSG_BUFSIZE
];
1400 regerror(ret_val
, &posix_regexp
, msg
, sizeof(msg
));
1401 regfree(&posix_regexp
);
1402 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1403 "failed in function regexp() when trying to match with character "
1406 TTCN_Logger::log_event(". Error message: %s.", msg
);
1409 int re_nsub
= posix_regexp
.re_nsub
;
1411 regfree(&posix_regexp
);
1412 TTCN_error_begin("The character pattern in the second argument "
1413 "(expression) of function regexp() does not contain any groups: ");
1415 TTCN_Logger::log_char('.');
1418 if (groupno
>= re_nsub
) {
1419 regfree(&posix_regexp
);
1420 TTCN_error("The third argument (groupno) of function regexp() is too "
1421 "large: The requested group index is %d, but the pattern contains only "
1422 "%d group%s.", groupno
, re_nsub
, re_nsub
> 1 ? "s" : "");
1424 size_t nmatch
= groupno
+ 1;
1425 regmatch_t
*pmatch
= (regmatch_t
*)Malloc((nmatch
+ 1) * sizeof(*pmatch
));
1426 ret_val
= regexec(&posix_regexp
, instr
, nmatch
+ 1, pmatch
, 0);
1428 int begin_index
= pmatch
[nmatch
].rm_so
, end_index
= pmatch
[nmatch
].rm_eo
;
1430 regfree(&posix_regexp
);
1431 if (end_index
> instr_len
) TTCN_error("Internal error: The end index "
1432 "of the substring (%d) to be returned in function regexp() is greater "
1433 "than the length of the input string (%d).", end_index
, instr_len
);
1434 if (begin_index
> end_index
) TTCN_error("Internal error: The start index "
1435 "of the substring (%d) to be returned in function regexp() is greater "
1436 "than the end index (%d).", begin_index
, end_index
);
1437 return CHARSTRING(end_index
- begin_index
, instr_str
+ begin_index
);
1440 if (ret_val
!= REG_NOMATCH
) {
1441 char msg
[ERRMSG_BUFSIZE
];
1442 regerror(ret_val
, &posix_regexp
, msg
, ERRMSG_BUFSIZE
);
1443 regfree(&posix_regexp
);
1444 TTCN_error("Internal error: POSIX regular expression matching returned "
1445 "unexpected status code in function regexp(): %s.", msg
);
1446 } else regfree(&posix_regexp
);
1447 return CHARSTRING(0, NULL
);
1451 CHARSTRING
regexp(const CHARSTRING
& instr
, const CHARSTRING
& expression
,
1452 const INTEGER
& groupno
)
1454 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1455 "unbound integer value.");
1456 return regexp(instr
, expression
, (int)groupno
);
1459 /* Needed by regexp() */
1460 UNIVERSAL_CHARSTRING
convert_from_pattern_form(char* str
, int num
) {
1462 TTCN_error("Internal error: Cannot convert string from pattern form.");
1464 unsigned char c1
, c2
;
1465 universal_char
* const res
= new universal_char
[num
/8];
1466 unsigned char* ptr
= (unsigned char*)res
;
1468 while (index
< num
) {
1469 for (int j
= 0; j
< 4; j
++) {
1472 if (c1
>= 'A' && c1
<= 'P' && c2
>= 'A' && c2
<= 'P') {
1473 *(ptr
++) = ((c1
- 'A') << 4) | (c2
- 'A');
1475 TTCN_error("Internal error: Cannot convert string containing illegal "
1479 UNIVERSAL_CHARSTRING
retval(num
/ 8, res
);
1484 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1485 const UNIVERSAL_CHARSTRING
* expression_val
,
1486 const UNIVERSAL_CHARSTRING_template
* expression_tmpl
,
1489 if ( (expression_val
&& expression_tmpl
) ||
1490 (!expression_val
&& !expression_tmpl
) )
1491 TTCN_error("Internal error: regexp(): invalid parameters");
1492 instr
.must_bound("The first argument (instr) of function regexp() is an "
1493 "unbound charstring value.");
1495 expression_val
->must_bound("The second argument (expression) of function "
1496 "regexp() is an unbound universal charstring value.");
1498 if (!expression_tmpl
->is_bound())
1499 TTCN_error("The second argument (expression) of function "
1500 "regexp() is an unbound universal charstring template.");
1502 if (groupno
< 0) TTCN_error("The third argument (groupno) of function "
1503 "regexp() is a negative integer value: %d.", groupno
);
1505 int* user_groups
= 0;
1506 CHARSTRING expression_str
;
1508 expression_str
= expression_val
->get_stringRepr_for_pattern();
1510 expression_str
= expression_tmpl
->get_single_value();
1511 char *posix_str
= TTCN_pattern_to_regexp_uni((const char*)expression_str
,
1513 if (user_groups
== 0) {
1516 TTCN_error("Cannot find any groups in the second argument of regexp().");
1518 if (posix_str
== NULL
) {
1519 TTCN_error_begin("The second argument (expression) of function "
1520 "regexp(), which is ");
1521 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1522 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1525 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED
)) {
1526 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED
);
1527 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1528 CHARSTRING_template(STRING_PATTERN
, expression_str
).log();
1529 TTCN_Logger::log_event_str(" is: ");
1530 CHARSTRING(posix_str
).log();
1531 TTCN_Logger::end_event();
1534 regex_t posix_regexp
;
1535 int ret_val
= regcomp(&posix_regexp
, posix_str
, REG_EXTENDED
);
1538 char msg
[ERRMSG_BUFSIZE
];
1539 regerror(ret_val
, &posix_regexp
, msg
, sizeof(msg
));
1540 regfree(&posix_regexp
);
1541 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1542 "failed in function regexp() when trying to match with character "
1544 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1545 TTCN_Logger::log_event(". Error message: %s.", msg
);
1549 int re_nsub
= user_groups
[0];
1551 if (posix_regexp
.re_nsub
<= 0) {
1552 regfree(&posix_regexp
);
1553 TTCN_error_begin("The character pattern in the second argument "
1554 "(expression) of function regexp() does not contain any groups: ");
1555 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1556 TTCN_Logger::log_char('.');
1559 if (groupno
>= re_nsub
) {
1560 regfree(&posix_regexp
);
1561 TTCN_error("The third argument (groupno) of function regexp() is too "
1562 "large: The requested group index is %d, but the pattern contains only "
1563 "%d group%s.", groupno
, re_nsub
, re_nsub
> 1 ? "s" : "");
1565 if (groupno
> user_groups
[0]) {
1566 printf(" user_groups: %d\n", user_groups
[0]);
1567 TTCN_error("Error during parsing the pattern.");
1569 size_t nmatch
= (size_t)user_groups
[groupno
+1] + 1;
1570 regmatch_t
*pmatch
= (regmatch_t
*)Malloc((nmatch
+ 1) * sizeof(*pmatch
));
1574 char* instr_conv
= instr
.convert_to_regexp_form();
1575 int instr_len
= instr
.lengthof() * 8;
1577 ret_val
= regexec(&posix_regexp
, instr_conv
, nmatch
+ 1, pmatch
, 0);
1579 int begin_index
= pmatch
[nmatch
].rm_so
, end_index
= pmatch
[nmatch
].rm_eo
;
1581 regfree(&posix_regexp
);
1582 if (end_index
> instr_len
) TTCN_error("Internal error: The end index "
1583 "of the substring (%d) to be returned in function regexp() is greater "
1584 "than the length of the input string (%d).", end_index
, instr_len
);
1585 if (begin_index
> end_index
) TTCN_error("Internal error: The start index "
1586 "of the substring (%d) to be returned in function regexp() is greater "
1587 "than the end index (%d).", begin_index
, end_index
);
1588 UNIVERSAL_CHARSTRING res
= convert_from_pattern_form(
1589 instr_conv
+ begin_index
, end_index
- begin_index
);
1595 if (ret_val
!= REG_NOMATCH
) {
1596 char msg
[ERRMSG_BUFSIZE
];
1597 regerror(ret_val
, &posix_regexp
, msg
, ERRMSG_BUFSIZE
);
1598 regfree(&posix_regexp
);
1599 TTCN_error("Internal error: POSIX regular expression matching returned "
1600 "unexpected status code in function regexp(): %s.", msg
);
1601 } else regfree(&posix_regexp
);
1602 return UNIVERSAL_CHARSTRING(0, (const char*)NULL
);
1606 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1607 const UNIVERSAL_CHARSTRING
& expression
, int groupno
)
1609 return regexp(instr
, &expression
, NULL
, groupno
);
1612 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1613 const UNIVERSAL_CHARSTRING
& expression
, const INTEGER
& groupno
)
1615 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1616 "unbound integer value.");
1617 return regexp(instr
, expression
, (int)groupno
);
1620 // regexp() on templates
1622 CHARSTRING
regexp(const CHARSTRING_template
& instr
,
1623 const CHARSTRING_template
& expression
, int groupno
)
1625 if (!instr
.is_value())
1626 TTCN_error("The first argument of function regexp() is a "
1627 "template with non-specific value.");
1628 if (expression
.is_value())
1629 return regexp(instr
.valueof(), expression
.valueof(), groupno
);
1630 // pattern matching to specific value
1631 if (expression
.get_selection()==STRING_PATTERN
)
1632 return regexp(instr
.valueof(), expression
.get_single_value(), groupno
);
1633 TTCN_error("The second argument of function regexp() should be "
1634 "specific value or pattern matching template.");
1637 CHARSTRING
regexp(const CHARSTRING_template
& instr
,
1638 const CHARSTRING_template
& expression
, const INTEGER
& groupno
)
1640 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1641 "unbound integer value.");
1642 return regexp(instr
, expression
, (int)groupno
);
1645 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING_template
& instr
,
1646 const UNIVERSAL_CHARSTRING_template
& expression
, int groupno
)
1648 if (!instr
.is_value())
1649 TTCN_error("The first argument of function regexp() is a "
1650 "template with non-specific value.");
1651 if (expression
.is_value())
1652 return regexp(instr
.valueof(), expression
.valueof(), groupno
);
1653 // pattern matching to specific value
1654 if (expression
.get_selection()==STRING_PATTERN
)
1655 return regexp(instr
.valueof(), NULL
, &expression
, groupno
);
1656 TTCN_error("The second argument of function regexp() should be "
1657 "specific value or pattern matching template.");
1660 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING_template
& instr
,
1661 const UNIVERSAL_CHARSTRING_template
& expression
, const INTEGER
& groupno
)
1663 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1664 "unbound integer value.");
1665 return regexp(instr
, expression
, (int)groupno
);
1670 void check_substr_arguments(int value_length
, int idx
,
1671 int returncount
, const char *string_type
, const char *element_name
)
1673 if (idx
< 0) TTCN_error("The second argument (index) of function "
1674 "substr() is a negative integer value: %d.", idx
);
1675 if (idx
> value_length
) TTCN_error("The second argument (index) of "
1676 "function substr(), which is %d, is greater than the length of the "
1677 "%s value: %d.", idx
, string_type
, value_length
);
1678 if (returncount
< 0) TTCN_error("The third argument (returncount) of "
1679 "function substr() is a negative integer value: %d.", returncount
);
1680 if (idx
+ returncount
> value_length
) TTCN_error("The first argument of "
1681 "function substr(), the length of which is %d, does not have enough "
1682 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
1683 value_length
, element_name
, idx
, returncount
, element_name
,
1684 returncount
> 1 ? "s are" : " is",
1685 value_length
- idx
> 1 ? "are" : "is", value_length
- idx
);
1688 static void check_substr_arguments(int idx
, int returncount
,
1689 const char *string_type
, const char *element_name
)
1691 if (idx
< 0) TTCN_error("The second argument (index) of function "
1692 "substr() is a negative integer value: %d.", idx
);
1693 if (idx
> 1) TTCN_error("The second argument (index) of function "
1694 "substr(), which is %d, is greater than 1 (i.e. the length of the "
1695 "%s element).", idx
, string_type
);
1696 if (returncount
< 0) TTCN_error("The third argument (returncount) of "
1697 "function substr() is a negative integer value: %d.", returncount
);
1698 if (idx
+ returncount
> 1) TTCN_error("The first argument of function "
1699 "substr(), which is a%s %s element, does not have enough %ss starting "
1700 "at index %d: %d %s%s needed, but there is only %d.",
1701 string_type
[0] == 'o' ? "n" : "", string_type
, element_name
, idx
,
1702 returncount
, element_name
, returncount
> 1 ? "s are" : " is",
1706 BITSTRING
substr(const BITSTRING
& value
, int idx
, int returncount
)
1708 value
.must_bound("The first argument (value) of function substr() "
1709 "is an unbound bitstring value.");
1710 check_substr_arguments(value
.lengthof(), idx
, returncount
, "bitstring",
1713 BITSTRING
ret_val(returncount
);
1714 for (int i
= 0; i
< returncount
; i
++) {
1715 ret_val
.set_bit(i
, value
.get_bit(idx
+ i
));
1717 ret_val
.clear_unused_bits();
1720 return BITSTRING(returncount
, (const unsigned char*)value
+ idx
/ 8);
1724 BITSTRING
substr(const BITSTRING
& value
, int idx
, const INTEGER
& returncount
)
1726 returncount
.must_bound("The third argument (returncount) of function "
1727 "substr() is an unbound integer value.");
1728 return substr(value
, idx
, (int)returncount
);
1731 BITSTRING
substr(const BITSTRING
& value
, const INTEGER
& idx
, int returncount
)
1733 idx
.must_bound("The second argument (index) of function substr() "
1734 "is an unbound integer value.");
1735 return substr(value
, (int)idx
, returncount
);
1738 BITSTRING
substr(const BITSTRING
& value
, const INTEGER
& idx
,
1739 const INTEGER
& returncount
)
1741 idx
.must_bound("The second argument (index) of function substr() is an "
1742 "unbound integer value.");
1743 returncount
.must_bound("The third argument (returncount) of function "
1744 "substr() is an unbound integer value.");
1745 return substr(value
, (int)idx
, (int)returncount
);
1748 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, int idx
, int returncount
)
1750 value
.must_bound("The first argument (value) of function substr() "
1751 "is an unbound bitstring element.");
1752 check_substr_arguments(idx
, returncount
, "bitstring", "bit");
1753 if (returncount
== 0) return BITSTRING(0, NULL
);
1755 unsigned char bit
= value
.get_bit() ? 0x01 : 0x00;
1756 return BITSTRING(1, &bit
);
1760 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, int idx
,
1761 const INTEGER
& returncount
)
1763 returncount
.must_bound("The third argument (returncount) of function "
1764 "substr() is an unbound integer value.");
1765 return substr(value
, idx
, (int)returncount
);
1768 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1771 idx
.must_bound("The second argument (index) of function substr() "
1772 "is an unbound integer value.");
1773 return substr(value
, (int)idx
, returncount
);
1776 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1777 const INTEGER
& returncount
)
1779 idx
.must_bound("The second argument (index) of function substr() is an "
1780 "unbound integer value.");
1781 returncount
.must_bound("The third argument (returncount) of function "
1782 "substr() is an unbound integer value.");
1783 return substr(value
, (int)idx
, (int)returncount
);
1786 HEXSTRING
substr(const HEXSTRING
& value
, int idx
, int returncount
)
1788 value
.must_bound("The first argument (value) of function substr() "
1789 "is an unbound hexstring value.");
1790 check_substr_arguments(value
.lengthof(), idx
, returncount
, "hexstring",
1791 "hexadecimal digit");
1792 const unsigned char *src_ptr
= (const unsigned char*)value
;
1794 HEXSTRING
ret_val(returncount
);
1795 unsigned char *dst_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
1796 for (int i
= 0; i
< returncount
; i
++) {
1797 if (i
% 2) dst_ptr
[i
/ 2] |= (src_ptr
[(i
+ idx
) / 2] & 0x0F) << 4;
1798 else dst_ptr
[i
/ 2] = src_ptr
[(i
+ idx
) / 2] >> 4;
1801 } else return HEXSTRING(returncount
, src_ptr
+ idx
/ 2);
1804 HEXSTRING
substr(const HEXSTRING
& value
, int idx
, const INTEGER
& returncount
)
1806 returncount
.must_bound("The third argument (returncount) of function "
1807 "substr() is an unbound integer value.");
1808 return substr(value
, idx
, (int)returncount
);
1811 HEXSTRING
substr(const HEXSTRING
& value
, const INTEGER
& idx
, int returncount
)
1813 idx
.must_bound("The second argument (index) of function substr() "
1814 "is an unbound integer value.");
1815 return substr(value
, (int)idx
, returncount
);
1818 HEXSTRING
substr(const HEXSTRING
& value
, const INTEGER
& idx
,
1819 const INTEGER
& returncount
)
1821 idx
.must_bound("The second argument (index) of function substr() is an "
1822 "unbound integer value.");
1823 returncount
.must_bound("The third argument (returncount) of function "
1824 "substr() is an unbound integer value.");
1825 return substr(value
, (int)idx
, (int)returncount
);
1828 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, int idx
, int returncount
)
1830 value
.must_bound("The first argument (value) of function substr() "
1831 "is an unbound hexstring element.");
1832 check_substr_arguments(idx
, returncount
, "hexstring",
1833 "hexadecimal digit");
1834 if (returncount
== 0) return HEXSTRING(0, NULL
);
1836 unsigned char nibble
= value
.get_nibble();
1837 return HEXSTRING(1, &nibble
);
1841 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, int idx
,
1842 const INTEGER
& returncount
)
1844 returncount
.must_bound("The third argument (returncount) of function "
1845 "substr() is an unbound integer value.");
1846 return substr(value
, idx
, (int)returncount
);
1849 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1852 idx
.must_bound("The second argument (index) of function substr() "
1853 "is an unbound integer value.");
1854 return substr(value
, (int)idx
, returncount
);
1857 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1858 const INTEGER
& returncount
)
1860 idx
.must_bound("The second argument (index) of function substr() is an "
1861 "unbound integer value.");
1862 returncount
.must_bound("The third argument (returncount) of function "
1863 "substr() is an unbound integer value.");
1864 return substr(value
, (int)idx
, (int)returncount
);
1867 OCTETSTRING
substr(const OCTETSTRING
& value
, int idx
, int returncount
)
1869 value
.must_bound("The first argument (value) of function substr() "
1870 "is an unbound octetstring value.");
1871 check_substr_arguments(value
.lengthof(), idx
, returncount
, "octetstring",
1873 return OCTETSTRING(returncount
, (const unsigned char*)value
+ idx
);
1876 OCTETSTRING
substr(const OCTETSTRING
& value
, int idx
,
1877 const INTEGER
& returncount
)
1879 returncount
.must_bound("The third argument (returncount) of function "
1880 "substr() is an unbound integer value.");
1881 return substr(value
, idx
, (int)returncount
);
1884 OCTETSTRING
substr(const OCTETSTRING
& value
, const INTEGER
& idx
,
1887 idx
.must_bound("The second argument (index) of function substr() "
1888 "is an unbound integer value.");
1889 return substr(value
, (int)idx
, returncount
);
1892 OCTETSTRING
substr(const OCTETSTRING
& value
, const INTEGER
& idx
,
1893 const INTEGER
& returncount
)
1895 idx
.must_bound("The second argument (index) of function substr() is an "
1896 "unbound integer value.");
1897 returncount
.must_bound("The third argument (returncount) of function "
1898 "substr() is an unbound integer value.");
1899 return substr(value
, (int)idx
, (int)returncount
);
1902 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, int idx
, int returncount
)
1904 value
.must_bound("The first argument (value) of function substr() "
1905 "is an unbound octetstring element.");
1906 check_substr_arguments(idx
, returncount
, "octetstring", "octet");
1907 if (returncount
== 0) return OCTETSTRING(0, NULL
);
1909 unsigned char octet
= value
.get_octet();
1910 return OCTETSTRING(1, &octet
);
1914 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, int idx
,
1915 const INTEGER
& returncount
)
1917 returncount
.must_bound("The third argument (returncount) of function "
1918 "substr() is an unbound integer value.");
1919 return substr(value
, idx
, (int)returncount
);
1922 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1925 idx
.must_bound("The second argument (index) of function substr() "
1926 "is an unbound integer value.");
1927 return substr(value
, (int)idx
, returncount
);
1930 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1931 const INTEGER
& returncount
)
1933 idx
.must_bound("The second argument (index) of function substr() is an "
1934 "unbound integer value.");
1935 returncount
.must_bound("The third argument (returncount) of function "
1936 "substr() is an unbound integer value.");
1937 return substr(value
, (int)idx
, (int)returncount
);
1940 CHARSTRING
substr(const CHARSTRING
& value
, int idx
, int returncount
)
1942 value
.must_bound("The first argument (value) of function substr() "
1943 "is an unbound charstring value.");
1944 check_substr_arguments(value
.lengthof(), idx
, returncount
, "charstring",
1946 return CHARSTRING(returncount
, (const char*)value
+ idx
);
1949 CHARSTRING
substr(const CHARSTRING
& value
, int idx
,
1950 const INTEGER
& returncount
)
1952 returncount
.must_bound("The third argument (returncount) of function "
1953 "substr() is an unbound integer value.");
1954 return substr(value
, idx
, (int)returncount
);
1957 CHARSTRING
substr(const CHARSTRING
& value
, const INTEGER
& idx
,
1960 idx
.must_bound("The second argument (index) of function substr() "
1961 "is an unbound integer value.");
1962 return substr(value
, (int)idx
, returncount
);
1965 CHARSTRING
substr(const CHARSTRING
& value
, const INTEGER
& idx
,
1966 const INTEGER
& returncount
)
1968 idx
.must_bound("The second argument (index) of function substr() is an "
1969 "unbound integer value.");
1970 returncount
.must_bound("The third argument (returncount) of function "
1971 "substr() is an unbound integer value.");
1972 return substr(value
, (int)idx
, (int)returncount
);
1975 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, int idx
, int returncount
)
1977 value
.must_bound("The first argument (value) of function substr() "
1978 "is an unbound charstring element.");
1979 check_substr_arguments(idx
, returncount
, "charstring", "character");
1980 if (returncount
== 0) return CHARSTRING(0, NULL
);
1981 else return CHARSTRING(value
.get_char());
1984 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, int idx
,
1985 const INTEGER
& returncount
)
1987 returncount
.must_bound("The third argument (returncount) of function "
1988 "substr() is an unbound integer value.");
1989 return substr(value
, idx
, (int)returncount
);
1992 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1995 idx
.must_bound("The second argument (index) of function substr() "
1996 "is an unbound integer value.");
1997 return substr(value
, (int)idx
, returncount
);
2000 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, const INTEGER
& idx
,
2001 const INTEGER
& returncount
)
2003 idx
.must_bound("The second argument (index) of function substr() is an "
2004 "unbound integer value.");
2005 returncount
.must_bound("The third argument (returncount) of function "
2006 "substr() is an unbound integer value.");
2007 return substr(value
, (int)idx
, (int)returncount
);
2010 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2013 value
.must_bound("The first argument (value) of function substr() "
2014 "is an unbound universal charstring value.");
2015 check_substr_arguments(value
.lengthof(), idx
, returncount
,
2016 "universal charstring", "character");
2017 return UNIVERSAL_CHARSTRING(returncount
,
2018 (const universal_char
*)value
+ idx
);
2021 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2022 const INTEGER
& returncount
)
2024 returncount
.must_bound("The third argument (returncount) of function "
2025 "substr() is an unbound integer value.");
2026 return substr(value
, idx
, (int)returncount
);
2029 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
,
2030 const INTEGER
& idx
, int returncount
)
2032 idx
.must_bound("The second argument (index) of function substr() "
2033 "is an unbound integer value.");
2034 return substr(value
, (int)idx
, returncount
);
2037 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
,
2038 const INTEGER
& idx
, const INTEGER
& returncount
)
2040 idx
.must_bound("The second argument (index) of function substr() is an "
2041 "unbound integer value.");
2042 returncount
.must_bound("The third argument (returncount) of function "
2043 "substr() is an unbound integer value.");
2044 return substr(value
, (int)idx
, (int)returncount
);
2047 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2048 int idx
, int returncount
)
2050 value
.must_bound("The first argument (value) of function substr() "
2051 "is an unbound universal charstring element.");
2052 check_substr_arguments(idx
, returncount
, "universal charstring",
2054 if (returncount
== 0)
2055 return UNIVERSAL_CHARSTRING(0, (const universal_char
*)NULL
);
2056 else return UNIVERSAL_CHARSTRING(value
.get_uchar());
2059 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2060 int idx
, const INTEGER
& returncount
)
2062 returncount
.must_bound("The third argument (returncount) of function "
2063 "substr() is an unbound integer value.");
2064 return substr(value
, idx
, (int)returncount
);
2067 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2068 const INTEGER
& idx
, int returncount
)
2070 idx
.must_bound("The second argument (index) of function substr() "
2071 "is an unbound integer value.");
2072 return substr(value
, (int)idx
, returncount
);
2075 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2076 const INTEGER
& idx
, const INTEGER
& returncount
)
2078 idx
.must_bound("The second argument (index) of function substr() is an "
2079 "unbound integer value.");
2080 returncount
.must_bound("The third argument (returncount) of function "
2081 "substr() is an unbound integer value.");
2082 return substr(value
, (int)idx
, (int)returncount
);
2085 // substr() on templates
2086 BITSTRING
substr(const BITSTRING_template
& value
, int idx
, int returncount
)
2088 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2089 return substr(value
.valueof(), idx
, returncount
);
2092 BITSTRING
substr(const BITSTRING_template
& value
, int idx
, const INTEGER
& returncount
)
2094 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2095 return substr(value
.valueof(), idx
, returncount
);
2098 BITSTRING
substr(const BITSTRING_template
& value
, const INTEGER
& idx
, int returncount
)
2100 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2101 return substr(value
.valueof(), idx
, returncount
);
2104 BITSTRING
substr(const BITSTRING_template
& value
, const INTEGER
& idx
,
2105 const INTEGER
& returncount
)
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
);
2111 HEXSTRING
substr(const HEXSTRING_template
& value
, int idx
, int returncount
)
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
);
2117 HEXSTRING
substr(const HEXSTRING_template
& value
, int idx
, const INTEGER
& returncount
)
2119 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2120 return substr(value
.valueof(), idx
, returncount
);
2123 HEXSTRING
substr(const HEXSTRING_template
& value
, const INTEGER
& idx
, int returncount
)
2125 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2126 return substr(value
.valueof(), idx
, returncount
);
2129 HEXSTRING
substr(const HEXSTRING_template
& value
, const INTEGER
& idx
,
2130 const INTEGER
& returncount
)
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
);
2136 OCTETSTRING
substr(const OCTETSTRING_template
& value
, int idx
, int returncount
)
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
);
2142 OCTETSTRING
substr(const OCTETSTRING_template
& value
, int idx
,
2143 const INTEGER
& returncount
)
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
);
2149 OCTETSTRING
substr(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2152 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2153 return substr(value
.valueof(), idx
, returncount
);
2156 OCTETSTRING
substr(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2157 const INTEGER
& returncount
)
2159 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2160 return substr(value
.valueof(), idx
, returncount
);
2163 CHARSTRING
substr(const CHARSTRING_template
& value
, int idx
, int returncount
)
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
);
2169 CHARSTRING
substr(const CHARSTRING_template
& value
, int idx
,
2170 const INTEGER
& returncount
)
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
);
2176 CHARSTRING
substr(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2179 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2180 return substr(value
.valueof(), idx
, returncount
);
2183 CHARSTRING
substr(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2184 const INTEGER
& returncount
)
2186 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2187 return substr(value
.valueof(), idx
, returncount
);
2190 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
, int idx
,
2193 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2194 return substr(value
.valueof(), idx
, returncount
);
2197 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
, int idx
,
2198 const INTEGER
& returncount
)
2200 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2201 return substr(value
.valueof(), idx
, returncount
);
2204 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
,
2205 const INTEGER
& idx
, int returncount
)
2207 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2208 return substr(value
.valueof(), idx
, returncount
);
2211 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
,
2212 const INTEGER
& idx
, const INTEGER
& returncount
)
2214 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2215 return substr(value
.valueof(), idx
, returncount
);
2220 void check_replace_arguments(int value_length
, int idx
, int len
,
2221 const char *string_type
, const char *element_name
)
2223 if (idx
< 0) TTCN_error("The second argument (index) of function "
2224 "replace() is a negative integer value: %d.", idx
);
2225 if (idx
> value_length
) TTCN_error("The second argument (index) of "
2226 "function replace(), which is %d, is greater than the length of the "
2227 "%s value: %d.", idx
, string_type
, value_length
);
2228 if (len
< 0) TTCN_error("The third argument (len) of function replace() "
2229 "is a negative integer value: %d.", len
);
2230 if (len
> value_length
) TTCN_error("The third argument (len) of function "
2231 "replace(), which is %d, is greater than the length of the "
2232 "%s value: %d.", len
, string_type
, value_length
);
2233 if (idx
+ len
> value_length
) TTCN_error("The first argument of "
2234 "function replace(), the length of which is %d, does not have enough "
2235 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
2236 value_length
, element_name
, idx
, len
, element_name
,
2237 len
> 1 ? "s are" : " is", value_length
- idx
> 1 ? "are" : "is",
2238 value_length
- idx
);
2241 BITSTRING
replace(const BITSTRING
& value
, int idx
, int len
,
2242 const BITSTRING
& repl
)
2244 value
.must_bound("The first argument (value) of function replace() "
2245 "is an unbound bitstring value.");
2246 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2247 "unbound bitstring value.");
2248 check_replace_arguments(value
.lengthof(), idx
, len
, "bitstring", "bit");
2249 int value_len
= value
.lengthof();
2250 int repl_len
= repl
.lengthof();
2251 BITSTRING
ret_val(value_len
+ repl_len
- len
);
2252 for (int i
= 0; i
< idx
; i
++) ret_val
.set_bit(i
, value
.get_bit(i
));
2253 for (int i
= 0; i
< repl_len
; i
++)
2254 ret_val
.set_bit(i
+ idx
, repl
.get_bit(i
));
2255 for (int i
= 0; i
< value_len
- idx
- len
; i
++)
2256 ret_val
.set_bit(i
+ idx
+ repl_len
, value
.get_bit(idx
+ len
+ i
));
2260 BITSTRING
replace(const BITSTRING
& value
, int idx
, const INTEGER
& len
,
2261 const BITSTRING
& repl
)
2263 len
.must_bound("The third argument (len) of function replace() is an "
2264 "unbound integer value.");
2265 return replace(value
, idx
, (int)len
, repl
);
2268 BITSTRING
replace(const BITSTRING
& value
, const INTEGER
& idx
, int len
,
2269 const BITSTRING
& repl
)
2271 idx
.must_bound("The second argument (index) of function replace() is an "
2272 "unbound integer value.");
2273 return replace(value
, (int)idx
, len
, repl
);
2276 BITSTRING
replace(const BITSTRING
& value
, const INTEGER
& idx
,
2277 const INTEGER
& len
, const BITSTRING
& repl
)
2279 idx
.must_bound("The second argument (index) of function replace() is an "
2280 "unbound integer value.");
2281 len
.must_bound("The third argument (len) of function replace() is an "
2282 "unbound integer value.");
2283 return replace(value
, (int)idx
, (int)len
, repl
);
2286 HEXSTRING
replace(const HEXSTRING
& value
, int idx
, int len
,
2287 const HEXSTRING
& repl
)
2289 value
.must_bound("The first argument (value) of function replace() "
2290 "is an unbound hexstring value.");
2291 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2292 "unbound hexstring value.");
2293 check_replace_arguments(value
.lengthof(), idx
, len
, "hexstring",
2294 "hexadecimal digit");
2295 int value_len
= value
.lengthof();
2296 int repl_len
= repl
.lengthof();
2297 HEXSTRING
ret_val(value_len
+ repl_len
- len
);
2298 for (int i
= 0; i
< idx
; i
++)
2299 ret_val
.set_nibble(i
, value
.get_nibble(i
));
2300 for (int i
= 0; i
< repl_len
; i
++)
2301 ret_val
.set_nibble(idx
+ i
, repl
.get_nibble(i
));
2302 for (int i
= 0; i
< value_len
- idx
- len
; i
++)
2303 ret_val
.set_nibble(idx
+ i
+ repl_len
,
2304 value
.get_nibble(idx
+ i
+ len
));
2308 HEXSTRING
replace(const HEXSTRING
& value
, int idx
, const INTEGER
& len
,
2309 const HEXSTRING
& repl
)
2311 len
.must_bound("The third argument (len) of function replace() is an "
2312 "unbound integer value.");
2313 return replace(value
, idx
, (int)len
, repl
);
2316 HEXSTRING
replace(const HEXSTRING
& value
, const INTEGER
& idx
, int len
,
2317 const HEXSTRING
& repl
)
2319 idx
.must_bound("The second argument (index) of function replace() is an "
2320 "unbound integer value.");
2321 return replace(value
, (int)idx
, len
, repl
);
2324 HEXSTRING
replace(const HEXSTRING
& value
, const INTEGER
& idx
,
2325 const INTEGER
& len
, const HEXSTRING
& repl
)
2327 idx
.must_bound("The second argument (index) of function replace() is an "
2328 "unbound integer value.");
2329 len
.must_bound("The third argument (len) of function replace() is an "
2330 "unbound integer value.");
2331 return replace(value
, (int)idx
, (int)len
, repl
);
2334 OCTETSTRING
replace(const OCTETSTRING
& value
, int idx
, int len
,
2335 const OCTETSTRING
& repl
)
2337 value
.must_bound("The first argument (value) of function replace() "
2338 "is an unbound octetstring value.");
2339 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2340 "unbound octetstring value.");
2341 check_replace_arguments(value
.lengthof(), idx
, len
, "octetstring",
2343 int value_len
= value
.lengthof();
2344 int repl_len
= repl
.lengthof();
2345 OCTETSTRING
ret_val(value_len
+ repl_len
- len
);
2346 memcpy(ret_val
.val_ptr
->octets_ptr
, value
.val_ptr
->octets_ptr
, idx
);
2347 memcpy(ret_val
.val_ptr
->octets_ptr
+ idx
, repl
.val_ptr
->octets_ptr
,
2349 memcpy(ret_val
.val_ptr
->octets_ptr
+ idx
+ repl_len
,
2350 value
.val_ptr
->octets_ptr
+ idx
+ len
, value_len
- idx
- len
);
2354 OCTETSTRING
replace(const OCTETSTRING
& value
, int idx
, const INTEGER
& len
,
2355 const OCTETSTRING
& repl
)
2357 len
.must_bound("The third argument (len) of function replace() is an "
2358 "unbound integer value.");
2359 return replace(value
, idx
, (int)len
, repl
);
2362 OCTETSTRING
replace(const OCTETSTRING
& value
, const INTEGER
& idx
, int len
,
2363 const OCTETSTRING
& repl
)
2365 idx
.must_bound("The second argument (index) of function replace() is an "
2366 "unbound integer value.");
2367 return replace(value
, (int)idx
, len
, repl
);
2370 OCTETSTRING
replace(const OCTETSTRING
& value
, const INTEGER
& idx
,
2371 const INTEGER
& len
, const OCTETSTRING
& repl
)
2373 idx
.must_bound("The second argument (index) of function replace() is an "
2374 "unbound integer value.");
2375 len
.must_bound("The third argument (len) of function replace() is an "
2376 "unbound integer value.");
2377 return replace(value
, (int)idx
, (int)len
, repl
);
2380 CHARSTRING
replace(const CHARSTRING
& value
, int idx
, int len
,
2381 const CHARSTRING
& repl
)
2383 value
.must_bound("The first argument (value) of function replace() "
2384 "is an unbound charstring value.");
2385 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2386 "unbound charstring value.");
2387 check_replace_arguments(value
.lengthof(), idx
, len
, "charstring",
2389 int value_len
= value
.lengthof();
2390 int repl_len
= repl
.lengthof();
2391 CHARSTRING
ret_val(value_len
+ repl_len
- len
);
2392 /* According to http://gcc.gnu.org/ml/fortran/2007-05/msg00341.html it's
2393 worth using memcpy() instead of strncat(). There's no need to scan the
2394 strings for '\0'. */
2395 memcpy(ret_val
.val_ptr
->chars_ptr
, value
.val_ptr
->chars_ptr
, idx
);
2396 memcpy(ret_val
.val_ptr
->chars_ptr
+ idx
, repl
.val_ptr
->chars_ptr
,
2398 memcpy(ret_val
.val_ptr
->chars_ptr
+ idx
+ repl_len
,
2399 value
.val_ptr
->chars_ptr
+ idx
+ len
, value_len
- idx
- len
);
2403 CHARSTRING
replace(const CHARSTRING
& value
, int idx
, const INTEGER
& len
,
2404 const CHARSTRING
& repl
)
2406 len
.must_bound("The third argument (len) of function replace() is an "
2407 "unbound integer value.");
2408 return replace(value
, idx
, (int)len
, repl
);
2411 CHARSTRING
replace(const CHARSTRING
& value
, const INTEGER
& idx
, int len
,
2412 const CHARSTRING
& repl
)
2414 idx
.must_bound("The second argument (index) of function replace() is an "
2415 "unbound integer value.");
2416 return replace(value
, (int)idx
, len
, repl
);
2419 CHARSTRING
replace(const CHARSTRING
& value
, const INTEGER
& idx
,
2420 const INTEGER
& len
, const CHARSTRING
& repl
)
2422 idx
.must_bound("The second argument (index) of function replace() is an "
2423 "unbound integer value.");
2424 len
.must_bound("The third argument (len) of function replace() is an "
2425 "unbound integer value.");
2426 return replace(value
, (int)idx
, (int)len
, repl
);
2429 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2430 int len
, const UNIVERSAL_CHARSTRING
& repl
)
2432 value
.must_bound("The first argument (value) of function replace() "
2433 "is an unbound universal charstring value.");
2434 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2435 "unbound universal charstring value.");
2436 check_replace_arguments(value
.lengthof(), idx
, len
,
2437 "universal charstring", "character");
2438 int value_len
= value
.lengthof();
2439 int repl_len
= repl
.lengthof();
2440 UNIVERSAL_CHARSTRING
ret_val(value_len
+ repl_len
- len
);
2441 memcpy(ret_val
.val_ptr
->uchars_ptr
, value
.val_ptr
->uchars_ptr
,
2442 idx
* sizeof(universal_char
));
2443 memcpy(ret_val
.val_ptr
->uchars_ptr
+ idx
, repl
.val_ptr
->uchars_ptr
,
2444 repl_len
* sizeof(universal_char
));
2445 memcpy(ret_val
.val_ptr
->uchars_ptr
+ idx
+ repl_len
,
2446 value
.val_ptr
->uchars_ptr
+ idx
+ len
,
2447 (value_len
- idx
- len
) * sizeof(universal_char
));
2451 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2452 const INTEGER
& len
, const UNIVERSAL_CHARSTRING
& repl
)
2454 len
.must_bound("The third argument (len) of function replace() is an "
2455 "unbound integer value.");
2456 return replace(value
, idx
, (int)len
, repl
);
2459 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
,
2460 const INTEGER
& idx
, int len
, const UNIVERSAL_CHARSTRING
& repl
)
2462 idx
.must_bound("The second argument (index) of function replace() is an "
2463 "unbound integer value.");
2464 return replace(value
, (int)idx
, len
, repl
);
2467 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
,
2468 const INTEGER
& idx
, const INTEGER
& len
,
2469 const UNIVERSAL_CHARSTRING
& repl
)
2471 idx
.must_bound("The second argument (index) of function replace() is an "
2472 "unbound integer value.");
2473 len
.must_bound("The third argument (len) of function replace() is an "
2474 "unbound integer value.");
2475 return replace(value
, (int)idx
, (int)len
, repl
);
2478 // replace on templates
2480 BITSTRING
replace(const BITSTRING_template
& value
, int idx
, int len
,
2481 const BITSTRING_template
& repl
)
2483 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2484 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2485 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2488 BITSTRING
replace(const BITSTRING_template
& value
, int idx
, const INTEGER
& len
,
2489 const BITSTRING_template
& repl
)
2491 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2492 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2493 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2496 BITSTRING
replace(const BITSTRING_template
& value
, const INTEGER
& idx
, int len
,
2497 const BITSTRING_template
& repl
)
2499 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2500 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2501 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2504 BITSTRING
replace(const BITSTRING_template
& value
, const INTEGER
& idx
,
2505 const INTEGER
& len
, const BITSTRING_template
& repl
)
2507 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2508 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2509 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2512 HEXSTRING
replace(const HEXSTRING_template
& value
, int idx
, int len
,
2513 const HEXSTRING_template
& repl
)
2515 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2516 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2517 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2520 HEXSTRING
replace(const HEXSTRING_template
& value
, int idx
, const INTEGER
& len
,
2521 const HEXSTRING_template
& repl
)
2523 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2524 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2525 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2528 HEXSTRING
replace(const HEXSTRING_template
& value
, const INTEGER
& idx
, int len
,
2529 const HEXSTRING_template
& repl
)
2531 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2532 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2533 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2536 HEXSTRING
replace(const HEXSTRING_template
& value
, const INTEGER
& idx
,
2537 const INTEGER
& len
, const HEXSTRING_template
& repl
)
2539 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2540 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2541 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2544 OCTETSTRING
replace(const OCTETSTRING_template
& value
, int idx
, int len
,
2545 const OCTETSTRING_template
& repl
)
2547 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2548 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2549 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2552 OCTETSTRING
replace(const OCTETSTRING_template
& value
, int idx
, const INTEGER
& len
,
2553 const OCTETSTRING_template
& repl
)
2555 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2556 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2557 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2560 OCTETSTRING
replace(const OCTETSTRING_template
& value
, const INTEGER
& idx
, int len
,
2561 const OCTETSTRING_template
& repl
)
2563 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2564 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2565 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2568 OCTETSTRING
replace(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2569 const INTEGER
& len
, const OCTETSTRING_template
& repl
)
2571 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2572 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2573 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2576 CHARSTRING
replace(const CHARSTRING_template
& value
, int idx
, int len
,
2577 const CHARSTRING_template
& repl
)
2579 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2580 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2581 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2584 CHARSTRING
replace(const CHARSTRING_template
& value
, int idx
, const INTEGER
& len
,
2585 const CHARSTRING_template
& repl
)
2587 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2588 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2589 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2592 CHARSTRING
replace(const CHARSTRING_template
& value
, const INTEGER
& idx
, int len
,
2593 const CHARSTRING_template
& repl
)
2595 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2596 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2597 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2600 CHARSTRING
replace(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2601 const INTEGER
& len
, const CHARSTRING_template
& repl
)
2603 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2604 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2605 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2608 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, int idx
, int len
,
2609 const UNIVERSAL_CHARSTRING_template
& repl
)
2611 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2612 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2613 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2616 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, int idx
, const INTEGER
& len
,
2617 const UNIVERSAL_CHARSTRING_template
& repl
)
2619 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2620 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2621 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2624 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, const INTEGER
& idx
, int len
,
2625 const UNIVERSAL_CHARSTRING_template
& repl
)
2627 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2628 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2629 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2632 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, const INTEGER
& idx
,
2633 const INTEGER
& len
, const UNIVERSAL_CHARSTRING_template
& repl
)
2635 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2636 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2637 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2642 static boolean rnd_seed_set
= FALSE
;
2644 static void set_rnd_seed(double float_seed
)
2646 FLOAT::check_numeric(float_seed
, "The seed value of function rnd()");
2647 long integer_seed
= 0;
2648 const unsigned char *src_ptr
= (const unsigned char*)&float_seed
;
2649 unsigned char *dst_ptr
= (unsigned char*)&integer_seed
;
2650 for (size_t i
= 0; i
< sizeof(float_seed
); i
++) {
2651 dst_ptr
[i
% sizeof(integer_seed
)] ^= bit_reverse_table
[src_ptr
[i
]];
2652 dst_ptr
[(sizeof(float_seed
) - 1 - i
) % sizeof(integer_seed
)] ^=
2656 srand48(integer_seed
);
2657 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::seed
, float_seed
, integer_seed
);
2658 rnd_seed_set
= TRUE
;
2661 static double rnd_generate()
2664 ret_val
= drand48();
2665 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::read__out
, ret_val
, 0);
2671 if (!rnd_seed_set
) set_rnd_seed(TTCN_Snapshot::time_now());
2672 return rnd_generate();
2675 double rnd(double seed
)
2678 return rnd_generate();
2681 double rnd(const FLOAT
& seed
)
2683 seed
.must_bound("Initializing the random number generator with "
2684 "an unbound float value as seed.");
2685 set_rnd_seed((double)seed
);
2686 return rnd_generate();
2690 // Additional predefined functions defined in Annex B of ES 101 873-7
2692 // B.1 decomp - not implemented yet
2695 // Non-standard functions
2699 BITSTRING
str2bit(const char *value
)
2701 if (value
== NULL
) return BITSTRING(0, NULL
);
2702 else return str2bit(CHARSTRING(value
));
2705 BITSTRING
str2bit(const CHARSTRING
& value
)
2707 value
.must_bound("The argument of function str2bit() is an unbound "
2708 "charstring value.");
2709 int value_length
= value
.lengthof();
2710 const char *chars_ptr
= value
;
2711 BITSTRING
ret_val(value_length
);
2712 for (int i
= 0; i
< value_length
; i
++) {
2713 char c
= chars_ptr
[i
];
2716 ret_val
.set_bit(i
, FALSE
);
2719 ret_val
.set_bit(i
, TRUE
);
2722 TTCN_error_begin("The argument of function str2bit() shall "
2723 "contain characters `0' and `1' only, but character `");
2724 TTCN_Logger::log_char_escaped(c
);
2725 TTCN_Logger::log_event("' was found at index %d.", i
);
2729 ret_val
.clear_unused_bits();
2733 BITSTRING
str2bit(const CHARSTRING_ELEMENT
& value
)
2735 value
.must_bound("The argument of function str2bit() is an unbound "
2736 "charstring element.");
2737 char c
= value
.get_char();
2738 if (c
!= '0' && c
!= '1') {
2739 TTCN_error_begin("The argument of function str2bit() shall contain "
2740 "characters `0' and `1' only, but the given charstring element "
2741 "contains the character `");
2742 TTCN_Logger::log_char_escaped(c
);
2743 TTCN_Logger::log_event_str("'.");
2746 unsigned char bit
= c
== '1' ? 0x01 : 0x00;
2747 return BITSTRING(1, &bit
);
2752 HEXSTRING
str2hex(const char *value
)
2754 if (value
== NULL
) return HEXSTRING(0, NULL
);
2755 else return str2hex(CHARSTRING(value
));
2758 HEXSTRING
str2hex(const CHARSTRING
& value
)
2760 value
.must_bound("The argument of function str2hex() is an unbound "
2761 "charstring value.");
2762 int value_length
= value
.lengthof();
2763 const char *chars_ptr
= value
;
2764 HEXSTRING
ret_val(value_length
);
2765 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
2766 for (int i
= 0; i
< value_length
; i
++) {
2767 char c
= chars_ptr
[i
];
2768 unsigned char hex_digit
= char_to_hexdigit(c
);
2769 if (hex_digit
> 0x0F) {
2770 TTCN_error_begin("The argument of function str2hex() shall "
2771 "contain hexadecimal digits only, but character `");
2772 TTCN_Logger::log_char_escaped(c
);
2773 TTCN_Logger::log_event("' was found at index %d.", i
);
2776 if (i
% 2) nibbles_ptr
[i
/ 2] |= hex_digit
<< 4;
2777 else nibbles_ptr
[i
/ 2] = hex_digit
;
2782 HEXSTRING
str2hex(const CHARSTRING_ELEMENT
& value
)
2784 value
.must_bound("The argument of function str2hex() is an unbound "
2785 "charstring element.");
2786 char c
= value
.get_char();
2787 unsigned char hex_digit
= char_to_hexdigit(c
);
2788 if (hex_digit
> 0x0F) {
2789 TTCN_error_begin("The argument of function str2hex() shall contain "
2790 "only hexadecimal digits, but the given charstring element "
2791 "contains the character `");
2792 TTCN_Logger::log_char_escaped(c
);
2793 TTCN_Logger::log_event_str("'.");
2796 return HEXSTRING(1, &hex_digit
);
2801 CHARSTRING
float2str(double value
)
2803 bool f
= value
== 0.0
2804 || (value
> -MAX_DECIMAL_FLOAT
&& value
<= -MIN_DECIMAL_FLOAT
)
2805 || (value
>= MIN_DECIMAL_FLOAT
&& value
< MAX_DECIMAL_FLOAT
);
2806 // true if decimal representation possible (use %f format)
2808 int str_len
= snprintf(str_buf
, sizeof(str_buf
), f
? "%f" : "%e", value
);
2809 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
2810 TTCN_error("Internal error: system call snprintf() returned "
2811 "unexpected status code %d when converting value %g in function "
2812 "float2str().", str_len
, value
);
2814 return CHARSTRING(str_len
, str_buf
);
2817 CHARSTRING
float2str(const FLOAT
& value
)
2819 value
.must_bound("The argument of function float2str() is an unbound "
2821 return float2str((double)value
);
2826 CHARSTRING
unichar2char(const UNIVERSAL_CHARSTRING
& value
)
2828 value
.must_bound("The argument of function unichar2char() is an unbound "
2829 "universal charstring value.");
2830 int value_length
= value
.lengthof();
2831 const universal_char
*uchars_ptr
= value
;
2832 CHARSTRING
ret_val(value_length
);
2833 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
2834 for (int i
= 0; i
< value_length
; i
++) {
2835 const universal_char
& uchar
= uchars_ptr
[i
];
2836 if (uchar
.uc_group
!= 0 || uchar
.uc_plane
!= 0 || uchar
.uc_row
!= 0 ||
2837 uchar
.uc_cell
> 127) {
2838 TTCN_error("The characters in the argument of function "
2839 "unichar2char() shall be within the range char(0, 0, 0, 0) .. "
2840 "char(0, 0, 0, 127), but quadruple char(%u, %u, %u, %u) was "
2841 "found at index %d.", uchar
.uc_group
, uchar
.uc_plane
,
2842 uchar
.uc_row
, uchar
.uc_cell
, i
);
2844 chars_ptr
[i
] = uchar
.uc_cell
;
2849 CHARSTRING
unichar2char(const UNIVERSAL_CHARSTRING_ELEMENT
& value
)
2851 value
.must_bound("The argument of function unichar2char() is an unbound "
2852 "universal charstring element.");
2853 const universal_char
& uchar
= value
.get_uchar();
2854 if (uchar
.uc_group
!= 0 || uchar
.uc_plane
!= 0 || uchar
.uc_row
!= 0 ||
2855 uchar
.uc_cell
> 127) {
2856 TTCN_error("The characters in the argument of function unichar2char() "
2857 "shall be within the range char(0, 0, 0, 0) .. char(0, 0, 0, 127), "
2858 "but the given universal charstring element contains the quadruple "
2859 "char(%u, %u, %u, %u).", uchar
.uc_group
, uchar
.uc_plane
,
2860 uchar
.uc_row
, uchar
.uc_cell
);
2862 return CHARSTRING((char)uchar
.uc_cell
);
2865 OCTETSTRING
unichar2oct(const UNIVERSAL_CHARSTRING
& invalue
, const CHARSTRING
& string_encoding
)
2867 invalue
.must_bound("The argument of function unichar2oct() is an unbound "
2868 "universal charstring value.");
2869 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
2870 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
2872 if ("UTF-8" == string_encoding
) {
2873 invalue
.encode_utf8(buf
, false);
2875 else if ("UTF-8 BOM" == string_encoding
) {
2876 invalue
.encode_utf8(buf
, true);
2878 else if ("UTF-16" == string_encoding
) {
2879 invalue
.encode_utf16(buf
, CharCoding::UTF16
);
2881 else if ("UTF-16BE" == string_encoding
) {
2882 invalue
.encode_utf16(buf
, CharCoding::UTF16BE
);
2884 else if ("UTF-16LE" == string_encoding
) {
2885 invalue
.encode_utf16(buf
, CharCoding::UTF16LE
);
2887 else if ("UTF-32" == string_encoding
) {
2888 invalue
.encode_utf32(buf
, CharCoding::UTF32
);
2890 else if ("UTF-32BE" == string_encoding
) {
2891 invalue
.encode_utf32(buf
, CharCoding::UTF32BE
);
2892 } else if ("UTF-32LE" == string_encoding
) {
2893 invalue
.encode_utf32(buf
, CharCoding::UTF32LE
);
2896 TTCN_error("unichar2oct: Invalid parameter: %s", (const char*)string_encoding
);
2898 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
2899 return OCTETSTRING (buf
.get_len(), buf
.get_data());
2902 OCTETSTRING
unichar2oct(const UNIVERSAL_CHARSTRING
& invalue
)
2904 // no encoding parameter is default UTF-8
2905 invalue
.must_bound("The argument of function unichar2oct() is an unbound "
2906 "universal charstring value.");
2907 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
2908 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
2910 invalue
.encode_utf8(buf
, false);
2911 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
2912 return OCTETSTRING (buf
.get_len(), buf
.get_data());
2915 CHARSTRING
get_stringencoding(const OCTETSTRING
& encoded_value
)
2917 if (!encoded_value
.lengthof()) return CHARSTRING("<unknown>");
2918 unsigned int i
, j
, length
= encoded_value
.lengthof();
2919 const unsigned char* strptr
= (const unsigned char*)encoded_value
;
2920 for (i
= 0, j
= 0; UTF8_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF8_BOM
););
2921 if (i
== sizeof (UTF8_BOM
) && sizeof(UTF8_BOM
) <= length
) return "UTF-8";
2922 //UTF-32 shall be tested before UTF-16 !!!
2923 for (i
= 0, j
= 0; UTF32BE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF32BE_BOM
););
2924 if (i
== sizeof (UTF32BE_BOM
) && sizeof (UTF32BE_BOM
) <= length
) return "UTF-32BE";
2925 for (i
= 0, j
= 0; UTF32LE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF32LE_BOM
););
2926 if (i
== sizeof (UTF32LE_BOM
) && sizeof (UTF32LE_BOM
) <= length
) return "UTF-32LE";
2927 //UTF-32 shall be tested before UTF-16 !!!
2928 for (i
= 0, j
= 0; UTF16BE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF16BE_BOM
););
2929 if (i
== sizeof (UTF16BE_BOM
) && sizeof (UTF16BE_BOM
) <= length
) return "UTF-16BE";
2930 for (i
= 0, j
= 0; UTF16LE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF16LE_BOM
););
2931 if (i
== sizeof (UTF16LE_BOM
) && sizeof (UTF16LE_BOM
) <= length
) return "UTF-16LE";
2932 if (is_ascii (encoded_value
) == CharCoding::ASCII
) {
2935 else if (CharCoding::UTF_8
== is_utf8 (encoded_value
)) {
2942 // for internal purposes:
2943 // to obtain the name of the port when port array references are used
2944 // in connect/map/disconnect/unmap operations
2946 CHARSTRING
get_port_name(const char *port_name
, int array_index
)
2948 char *result_str
= mprintf("%s[%d]", port_name
, array_index
);
2949 CHARSTRING
ret_val(mstrlen(result_str
), result_str
);
2954 CHARSTRING
get_port_name(const char *port_name
, const INTEGER
& array_index
)
2956 array_index
.must_bound("Using an unbound integer value for indexing an "
2958 return get_port_name(port_name
, (int)array_index
);
2961 CHARSTRING
get_port_name(const CHARSTRING
& port_name
, int array_index
)
2963 port_name
.must_bound("Internal error: Using an unbound charstring value "
2964 "to obtain the name of a port.");
2965 return get_port_name((const char*)port_name
, array_index
);
2968 CHARSTRING
get_port_name(const CHARSTRING
& port_name
,
2969 const INTEGER
& array_index
)
2971 port_name
.must_bound("Internal error: Using an unbound charstring value "
2972 "to obtain the name of a port.");
2973 array_index
.must_bound("Using an unbound integer value for indexing an "
2975 return get_port_name((const char*)port_name
, (int)array_index
);
2978 OCTETSTRING
remove_bom(const OCTETSTRING
& encoded_value
)
2980 const unsigned char* str
= (const unsigned char*)encoded_value
;
2981 int length_of_BOM
= 0;
2982 if (0x00 == str
[0] && 0x00 == str
[1] && 0xFE == str
[2] && 0xFF == str
[3]) { // UTF-32BE
2985 else if (0xFF == str
[0] && 0xFE == str
[1] && 0x00 == str
[2] && 0x00 == str
[3]) { // UTF-32LE
2988 else if (0xFE == str
[0] && 0xFF == str
[1]) { // UTF-16BE
2991 else if (0xFF == str
[0] && 0xFE == str
[1]) { // UTF-16LE
2994 else if (0xEF == str
[0] && 0xBB == str
[1] && 0xBF == str
[2]) { // UTF-8
2998 return OCTETSTRING (encoded_value
); // no BOM found
3000 return OCTETSTRING (encoded_value
.lengthof() - length_of_BOM
, (str
+ length_of_BOM
));
3003 CHARSTRING
encode_base64(const OCTETSTRING
& msg
)
3005 const char *code_table
= {
3011 const char pad
= '=';
3012 const unsigned char *p_msg
= (const unsigned char *)msg
;
3013 int octets_left
= msg
.lengthof();
3014 char *output
= (char*)Malloc(((octets_left
*22)>>4) + 7);
3015 char *p_output
= output
;
3016 while(octets_left
>= 3) {
3017 *p_output
++ = code_table
[p_msg
[0] >> 2];
3018 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3019 *p_output
++ = code_table
[((p_msg
[1] << 2) | (p_msg
[2] >> 6)) & 0x3f];
3020 *p_output
++ = code_table
[p_msg
[2] & 0x3f];
3024 switch(octets_left
) {
3026 *p_output
++ = code_table
[p_msg
[0] >> 2];
3027 *p_output
++ = code_table
[(p_msg
[0] << 4) & 0x3f];
3032 *p_output
++ = code_table
[p_msg
[0] >> 2];
3033 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3034 *p_output
++ = code_table
[(p_msg
[1] << 2) & 0x3f];
3041 CHARSTRING
ret_val(output
);
3046 CHARSTRING
encode_base64(const OCTETSTRING
& msg
, bool use_linebreaks
)
3048 const char *code_table
= {
3054 const char pad
= '=';
3055 const unsigned char *p_msg
= (const unsigned char *)msg
;
3056 int octets_left
= msg
.lengthof();
3057 char *output
= (char*)Malloc(((octets_left
*22)>>4) + 7);
3058 char *p_output
= output
;
3060 while(octets_left
>= 3) {
3061 *p_output
++ = code_table
[p_msg
[0] >> 2];
3062 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3063 *p_output
++ = code_table
[((p_msg
[1] << 2) | (p_msg
[2] >> 6)) & 0x3f];
3064 *p_output
++ = code_table
[p_msg
[2] & 0x3f];
3066 if (use_linebreaks
&& n_4chars
>=19 && octets_left
!= 3) {
3074 switch(octets_left
) {
3076 *p_output
++ = code_table
[p_msg
[0] >> 2];
3077 *p_output
++ = code_table
[(p_msg
[0] << 4) & 0x3f];
3082 *p_output
++ = code_table
[p_msg
[0] >> 2];
3083 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3084 *p_output
++ = code_table
[(p_msg
[1] << 2) & 0x3f];
3091 CHARSTRING
ret_val(output
);
3097 OCTETSTRING
decode_base64(const CHARSTRING
& b64
)
3099 const unsigned char decode_table
[] = {
3100 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3101 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3102 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 62, 80, 80, 80, 63,
3103 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 80, 80, 80, 70, 80, 80,
3104 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
3105 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 80, 80, 80, 80, 80,
3106 80, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
3107 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 80, 80, 80, 80, 80
3109 const unsigned char *p_b64
= (const unsigned char *) ((const char *)b64
);
3110 int chars_left
= b64
.lengthof();
3111 unsigned char *output
= (unsigned char*)Malloc(((chars_left
>> 2) + 1) * 3);
3112 unsigned char *p_output
= output
;
3113 unsigned int bits
= 0;
3115 while(chars_left
--) {
3117 if (*p_b64
> 0 && (dec
= decode_table
[*p_b64
]) < 64) {
3122 *p_output
++ = (bits
>> (n_bits
- 8)) & 0xff;
3126 else if (*p_b64
== '=') {
3130 if (*p_b64
== '\r' && *(p_b64
+ 1) == '\n') {
3131 ++p_b64
; // skip \n too
3134 TTCN_error("Error: Invalid character in Base64 encoded data: 0x%02X", *p_b64
);
3139 OCTETSTRING
ret_val(p_output
- output
, output
);