1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
17 * Szabo, Janos Zoltan – initial implementation
18 * Zalanyi, Balazs Andor
20 ******************************************************************************/
23 #include "../common/memory.h"
24 #include "../common/pattern.hh"
27 #include "Bitstring.hh"
28 #include "Hexstring.hh"
29 #include "Octetstring.hh"
30 #include "Charstring.hh"
31 #include "Universal_charstring.hh"
32 #include "String_struct.hh"
34 #include "Snapshot.hh"
35 #include "TitanLoggerApi.hh"
37 #include <openssl/bn.h>
43 #include <sys/types.h>
46 #define ERRMSG_BUFSIZE 512
48 // table to reverse the hex digits within an octet
49 // input: ABCDEFGH, output: DCBAHGFE
50 static const unsigned char nibble_reverse_table
[] =
52 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
53 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f,
54 0x80, 0x88, 0x84, 0x8c, 0x82, 0x8a, 0x86, 0x8e,
55 0x81, 0x89, 0x85, 0x8d, 0x83, 0x8b, 0x87, 0x8f,
56 0x40, 0x48, 0x44, 0x4c, 0x42, 0x4a, 0x46, 0x4e,
57 0x41, 0x49, 0x45, 0x4d, 0x43, 0x4b, 0x47, 0x4f,
58 0xc0, 0xc8, 0xc4, 0xcc, 0xc2, 0xca, 0xc6, 0xce,
59 0xc1, 0xc9, 0xc5, 0xcd, 0xc3, 0xcb, 0xc7, 0xcf,
60 0x20, 0x28, 0x24, 0x2c, 0x22, 0x2a, 0x26, 0x2e,
61 0x21, 0x29, 0x25, 0x2d, 0x23, 0x2b, 0x27, 0x2f,
62 0xa0, 0xa8, 0xa4, 0xac, 0xa2, 0xaa, 0xa6, 0xae,
63 0xa1, 0xa9, 0xa5, 0xad, 0xa3, 0xab, 0xa7, 0xaf,
64 0x60, 0x68, 0x64, 0x6c, 0x62, 0x6a, 0x66, 0x6e,
65 0x61, 0x69, 0x65, 0x6d, 0x63, 0x6b, 0x67, 0x6f,
66 0xe0, 0xe8, 0xe4, 0xec, 0xe2, 0xea, 0xe6, 0xee,
67 0xe1, 0xe9, 0xe5, 0xed, 0xe3, 0xeb, 0xe7, 0xef,
68 0x10, 0x18, 0x14, 0x1c, 0x12, 0x1a, 0x16, 0x1e,
69 0x11, 0x19, 0x15, 0x1d, 0x13, 0x1b, 0x17, 0x1f,
70 0x90, 0x98, 0x94, 0x9c, 0x92, 0x9a, 0x96, 0x9e,
71 0x91, 0x99, 0x95, 0x9d, 0x93, 0x9b, 0x97, 0x9f,
72 0x50, 0x58, 0x54, 0x5c, 0x52, 0x5a, 0x56, 0x5e,
73 0x51, 0x59, 0x55, 0x5d, 0x53, 0x5b, 0x57, 0x5f,
74 0xd0, 0xd8, 0xd4, 0xdc, 0xd2, 0xda, 0xd6, 0xde,
75 0xd1, 0xd9, 0xd5, 0xdd, 0xd3, 0xdb, 0xd7, 0xdf,
76 0x30, 0x38, 0x34, 0x3c, 0x32, 0x3a, 0x36, 0x3e,
77 0x31, 0x39, 0x35, 0x3d, 0x33, 0x3b, 0x37, 0x3f,
78 0xb0, 0xb8, 0xb4, 0xbc, 0xb2, 0xba, 0xb6, 0xbe,
79 0xb1, 0xb9, 0xb5, 0xbd, 0xb3, 0xbb, 0xb7, 0xbf,
80 0x70, 0x78, 0x74, 0x7c, 0x72, 0x7a, 0x76, 0x7e,
81 0x71, 0x79, 0x75, 0x7d, 0x73, 0x7b, 0x77, 0x7f,
82 0xf0, 0xf8, 0xf4, 0xfc, 0xf2, 0xfa, 0xf6, 0xfe,
83 0xf1, 0xf9, 0xf5, 0xfd, 0xf3, 0xfb, 0xf7, 0xff
86 // table to swap the hex digits within an octet
87 // input: ABCDEFGH, output: EFGHABCD
88 static const unsigned char nibble_swap_table
[] =
90 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
91 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
92 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
93 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1,
94 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
95 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2,
96 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
97 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3,
98 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
99 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4,
100 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
101 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5,
102 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
103 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6,
104 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
105 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7,
106 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
107 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8,
108 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
109 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9,
110 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
111 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
112 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b,
113 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb,
114 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c,
115 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc,
116 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d,
117 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd,
118 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e,
119 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe,
120 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f,
121 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff
124 // table to reverse the bits within an octet
125 // input: ABCDEFGH, output: HGFEDCBA
126 static const unsigned char bit_reverse_table
[] =
128 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
129 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
130 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
131 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
132 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
133 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
134 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
135 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
136 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
137 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
138 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
139 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
140 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
141 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
142 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
143 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
144 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
145 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
146 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
147 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
148 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
149 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
150 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
151 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
152 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
153 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
154 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
155 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
156 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
157 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
158 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
159 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
162 static const unsigned char UTF8_BOM
[] = {0xef, 0xbb, 0xbf};
163 static const unsigned char UTF16BE_BOM
[] = {0xfe, 0xff};
164 static const unsigned char UTF16LE_BOM
[] = {0xff, 0xfe};
165 static const unsigned char UTF32BE_BOM
[] = {0x00, 0x00, 0xfe, 0xff};
166 static const unsigned char UTF32LE_BOM
[] = {0xff, 0xfe, 0x00, 0x00};
168 // Functions for internal purposes
170 unsigned char char_to_hexdigit(char c
)
172 if (c
>= '0' && c
<= '9') return c
- '0';
173 else if (c
>= 'A' && c
<= 'F') return c
- 'A' + 10;
174 else if (c
>= 'a' && c
<= 'f') return c
- 'a' + 10;
178 char hexdigit_to_char(unsigned char hexdigit
)
180 if (hexdigit
< 10) return '0' + hexdigit
;
181 else if (hexdigit
< 16) return 'A' + hexdigit
- 10;
185 static boolean
is_whitespace(char c
)
200 static CharCoding::CharCodingType
is_ascii ( const OCTETSTRING
& ostr
)
202 const unsigned char nonASCII
= 1 << 7;// MSB is 1 in case of non ASCII character
203 CharCoding::CharCodingType ret
= CharCoding::ASCII
;
204 const unsigned char* strptr
= (const unsigned char*)ostr
;
205 for (int i
= 0; i
< ostr
.lengthof(); ++i
) {
206 if ( strptr
[i
] & nonASCII
) {
207 ret
= CharCoding::UNKNOWN
;
214 static CharCoding::CharCodingType
is_utf8 ( const OCTETSTRING
& ostr
)
216 const char MSB
= 1 << 7; // MSB is 1 in case of non ASCII character
217 const char MSBmin1
= 1 << 6; // 0100 0000
219 const unsigned char* strptr
= (const unsigned char*)ostr
;
220 // std::cout << "UTF-8 strptr" << strptr << std::endl;
221 while (ostr
.lengthof() > i
) {
222 if ( strptr
[i
] & MSB
) { // non ASCII char
223 // std::cout << "UTF-8 strptr[" << i << "]: " << std::hex << (int)strptr[i] << std::endl;
224 char maskUTF8
= 1 << 6; // 111x xxxx shows how many additional bytes are there
225 if (!(strptr
[i
] & maskUTF8
)) return CharCoding::UNKNOWN
; // accepted 11xxx xxxx but received 10xx xxxx
226 unsigned int noofUTF8
= 0; // 11xx xxxxx -> 2 bytes, 111x xxxxx -> 3 bytes , 1111 xxxxx -> 4 bytes in UTF-8
227 while (strptr
[i
] & maskUTF8
) {
229 maskUTF8
>>= 1; // shift right the mask
231 // the second and third (and so on) UTF-8 byte looks like 10xx xxxx
232 while (0 < noofUTF8
) {
234 //std::cout << "mask & strptr[" << i << "] " << std::hex << (int)strptr[i] << std::endl;
235 if (!(strptr
[i
] & MSB
) || (strptr
[i
] & MSBmin1
) || i
>= ostr
.lengthof()) { // if not like this: 10xx xxxx
236 return CharCoding::UNKNOWN
;
243 return CharCoding::UTF_8
;
246 // Additional predefined functions defined in Annex C of ES 101 873-1
250 CHARSTRING
int2char(int value
)
252 if (value
< 0 || value
> 127) TTCN_error("The argument of function "
253 "int2char() is %d, which is outside the allowed range 0 .. 127.",
255 return CHARSTRING((char)value
);
258 CHARSTRING
int2char(const INTEGER
& value
)
260 value
.must_bound("The argument of function int2char() is an unbound "
262 const int_val_t
& ivt
= value
.get_val();
263 if (ivt
< 0 || ivt
> 127) {
264 char *value_str
= ivt
.as_string();
265 TTCN_error("The argument of function int2char() is %s, "
266 "which is outside the allowed range 0 .. 127.", value_str
);
269 return CHARSTRING((char)((int)value
));
274 UNIVERSAL_CHARSTRING
int2unichar(int value
)
276 if (value
< 0 || value
> 2147483647) TTCN_error("The argument of function "
277 "int2unichar() is %d, which outside the allowed range 0 .. 2147483647.",
279 return UNIVERSAL_CHARSTRING(value
>> 24, (value
>> 16) & 0xFF,
280 (value
>> 8) & 0xFF, value
& 0xFF);
283 UNIVERSAL_CHARSTRING
int2unichar(const INTEGER
& value
)
285 value
.must_bound("The argument of function int2unichar() is an unbound "
287 const int_val_t
& ivt
= value
.get_val();
288 if (ivt
< 0 || ivt
> 2147483647) {
289 char *value_str
= ivt
.as_string();
290 TTCN_error("The argument of function int2unichar() is %s, "
291 "which outside the allowed range 0 .. 2147483647.", value_str
);
294 return int2unichar((int)value
);
299 BITSTRING
int2bit(const INTEGER
& value
, int length
)
301 value
.must_bound("The first argument (value) of function int2bit() is "
302 "an unbound integer value.");
303 int_val_t
tmp_value(value
.get_val());
305 char *value_str
= tmp_value
.as_string();
306 TTCN_error("The first argument (value) of function "
307 "int2bit() is a negative integer value: %s.", value_str
);
310 if (length
< 0) TTCN_error("The second argument (length) of function "
311 "int2bit() is a negative integer value: %d.", length
);
312 BITSTRING
ret_val(length
);
313 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
314 // clearing all bits in the result
315 memset(bits_ptr
, '\0', (length
+ 7) / 8);
316 // we are setting some bits to 1 so we may stop if there are no more 1 bits
318 for (int i
= length
- 1; tmp_value
!= 0 && i
>= 0; i
--) {
319 if ((tmp_value
& 1).get_val()) bits_ptr
[i
/ 8] |= (1 << (i
% 8));
322 if (tmp_value
!= 0) {
323 char *value_str
= value
.get_val().as_string(); // not tmp_value!
324 TTCN_error("The first argument of function int2bit(), which is %s, "
325 "does not fit in %d bit%s.", value_str
, length
,
326 length
> 1 ? "s" :"");
332 BITSTRING
int2bit(int value
, const INTEGER
& length
)
334 length
.must_bound("The second argument (length) of function int2bit() is "
335 "an unbound integer value.");
336 return int2bit(INTEGER(value
), (int)length
);
339 BITSTRING
int2bit(int value
, int length
)
341 return int2bit(INTEGER(value
), length
);
344 BITSTRING
int2bit(const INTEGER
& value
, const INTEGER
& length
)
346 value
.must_bound("The first argument (value) of function int2bit() is "
347 "an unbound integer value.");
348 length
.must_bound("The second argument (length) of function int2bit() is "
349 "an unbound integer value.");
350 return int2bit(value
, (int)length
);
355 HEXSTRING
int2hex(const INTEGER
& value
, int length
)
357 value
.must_bound("The first argument (value) of function int2hex() is "
358 "an unbound integer value.");
359 int_val_t
tmp_value(value
.get_val());
361 char *value_str
= tmp_value
.as_string();
362 TTCN_error("The first argument (value) of function int2hex() is a "
363 "negative integer value: %s.", value_str
);
366 if (length
< 0) TTCN_error("The second argument (length) of function "
367 "int2hex() is a negative integer value: %d.", length
);
368 HEXSTRING
ret_val(length
);
369 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
370 // clearing the unused bits in the last octet if necessary
371 if (length
% 2) nibbles_ptr
[length
/ 2] = '\0';
372 for (int i
= length
- 1; i
>= 0; i
--) {
373 if (i
% 2) nibbles_ptr
[i
/ 2] = (tmp_value
& 0xF).get_val() << 4;
374 else nibbles_ptr
[i
/ 2] |= (tmp_value
& 0xF).get_val();
377 if (tmp_value
!= 0) {
378 char *value_str
= value
.get_val().as_string(); // not tmp_value!
379 TTCN_error("The first argument of function int2hex(), which is %s, "
380 "does not fit in %d hexadecimal digit%s.", value_str
, length
,
381 length
> 1 ? "s" :"");
382 Free(value_str
); // ???
387 HEXSTRING
int2hex(int value
, const INTEGER
& length
)
389 length
.must_bound("The second argument (length) of function int2hex() is "
390 "an unbound integer value.");
391 return int2hex(INTEGER(value
), (int)length
);
394 HEXSTRING
int2hex(int value
, int length
)
396 return int2hex(INTEGER(value
), length
);
399 HEXSTRING
int2hex(const INTEGER
& value
, const INTEGER
& length
)
401 value
.must_bound("The first argument (value) of function int2hex() is "
402 "an unbound integer value.");
403 length
.must_bound("The second argument (length) of function int2hex() is "
404 "an unbound integer value.");
405 return int2hex(value
, (int)length
);
410 OCTETSTRING
int2oct(int value
, int length
)
412 if (value
< 0) TTCN_error("The first argument (value) of function "
413 "int2oct() is a negative integer value: %d.", value
);
414 if (length
< 0) TTCN_error("The second argument (length) of function "
415 "int2oct() is a negative integer value: %d.", length
);
416 OCTETSTRING
ret_val(length
);
417 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
418 unsigned int tmp_value
= value
;
419 for (int i
= length
- 1; i
>= 0; i
--) {
420 octets_ptr
[i
] = tmp_value
& 0xFF;
423 if (tmp_value
!= 0) {
424 TTCN_error("The first argument of function int2oct(), which is %d, "
425 "does not fit in %d octet%s.", value
, length
,
426 length
> 1 ? "s" :"");
431 OCTETSTRING
int2oct(int value
, const INTEGER
& length
)
433 length
.must_bound("The second argument (length) of function int2oct() is "
434 "an unbound integer value.");
435 return int2oct(value
, (int)length
);
438 OCTETSTRING
int2oct(const INTEGER
& value
, int length
)
440 value
.must_bound("The first argument (value) of function int2oct() is "
441 "an unbound integer value.");
442 const int_val_t
& value_int
= value
.get_val();
443 char *tmp_str
= value_int
.as_string();
444 CHARSTRING
value_str(tmp_str
);
446 if (value_int
.is_native()) {
447 return int2oct((int)value
, length
);
449 if (value_int
< 0) TTCN_error("The first argument (value) of function "
450 "int2oct() is a negative integer value: %s.",
451 (const char *)value_str
);
452 if (length
< 0) TTCN_error("The second argument (length) of function "
453 "int2oct() is a negative integer value: %d.", length
);
454 OCTETSTRING
ret_val(length
);
455 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
456 BIGNUM
*value_tmp
= BN_dup(value_int
.get_val_openssl());
457 int bytes
= BN_num_bytes(value_tmp
);
458 if (bytes
> length
) {
460 TTCN_error("The first argument of function int2oct(), which is %s, "
461 "does not fit in %d octet%s.", (const char *)value_str
, length
,
462 length
> 1 ? "s" : "");
464 for (int i
= length
- 1; i
>= 0; i
--) {
465 if (value_tmp
->top
) {
466 octets_ptr
[i
] = value_tmp
->d
[0] & 0xff;
467 BN_rshift(value_tmp
, value_tmp
, 8);
469 else { // we used up all of the bignum; zero the beginning and quit
470 memset(octets_ptr
, 0, i
+1);
480 OCTETSTRING
int2oct(const INTEGER
& value
, const INTEGER
& length
)
482 value
.must_bound("The first argument (value) of function int2oct() is an "
483 "unbound integer value.");
484 length
.must_bound("The second argument (length) of function int2oct() is "
485 "an unbound integer value.");
486 const int_val_t
& value_int
= value
.get_val();
487 if (value_int
.is_native()) return int2oct(value_int
.get_val(), (int)length
);
488 return int2oct(value
, (int)length
);
493 CHARSTRING
int2str(int value
)
496 int str_len
= snprintf(str_buf
, sizeof(str_buf
), "%d", value
);
497 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
498 TTCN_error("Internal error: system call snprintf() returned "
499 "unexpected status code %d when converting value %d in function "
500 "int2str().", str_len
, value
);
502 return CHARSTRING(str_len
, str_buf
);
505 CHARSTRING
int2str(const INTEGER
& value
)
507 value
.must_bound("The argument of function int2str() is an unbound "
509 char *value_tmp
= value
.get_val().as_string();
510 CHARSTRING
value_str(value_tmp
);
517 double int2float(int value
)
519 return (double)value
;
522 double int2float(const INTEGER
& value
)
524 value
.must_bound("The argument of function int2float() is an unbound "
526 return value
.get_val().to_real();
531 INTEGER
float2int(double value
)
533 if (value
>= (double)INT_MIN
&& value
<= (double)INT_MAX
) return (int)value
;
534 // DBL_MAX has 316 digits including the trailing 0-s on x86_64.
536 snprintf(buf
, 511, "%f", value
);
537 char *dot
= strchr(buf
, '.');
538 if (!dot
) TTCN_error("Conversion of float value `%f' to integer failed", value
);
539 else memset(dot
, 0, sizeof(buf
) - (dot
- buf
));
543 INTEGER
float2int(const FLOAT
& value
)
545 value
.must_bound("The argument of function float2int() is an unbound float "
547 return float2int((double)value
);
552 int char2int(char value
)
554 unsigned char uchar_value
= value
;
555 if (uchar_value
> 127) TTCN_error("The argument of function "
556 "char2int() contains a character with character code %u, which is "
557 "outside the allowed range 0 .. 127.", uchar_value
);
561 int char2int(const char *value
)
563 if (value
== NULL
) value
= "";
564 int value_length
= strlen(value
);
565 if (value_length
!= 1) TTCN_error("The length of the argument in function "
566 "char2int() must be exactly 1 instead of %d.", value_length
);
567 return char2int(value
[0]);
570 int char2int(const CHARSTRING
& value
)
572 value
.must_bound("The argument of function char2int() is an unbound "
573 "charstring value.");
574 int value_length
= value
.lengthof();
575 if (value_length
!= 1) TTCN_error("The length of the argument in function "
576 "char2int() must be exactly 1 instead of %d.", value_length
);
577 return char2int(((const char*)value
)[0]);
580 int char2int(const CHARSTRING_ELEMENT
& value
)
582 value
.must_bound("The argument of function char2int() is an unbound "
583 "charstring element.");
584 return char2int(value
.get_char());
589 OCTETSTRING
char2oct(const char *value
)
591 if (value
== NULL
) return OCTETSTRING(0, NULL
);
592 else return OCTETSTRING(strlen(value
), (const unsigned char*)value
);
595 OCTETSTRING
char2oct(const CHARSTRING
& value
)
597 value
.must_bound("The argument of function char2oct() is an unbound "
598 "charstring value.");
599 return OCTETSTRING(value
.lengthof(),
600 (const unsigned char*)(const char*)value
);
603 OCTETSTRING
char2oct(const CHARSTRING_ELEMENT
& value
)
605 value
.must_bound("The argument of function char2oct() is an unbound "
606 "charstring element.");
607 unsigned char octet
= value
.get_char();
608 return OCTETSTRING(1, &octet
);
611 // C.11 - unichar2int
613 int unichar2int(const universal_char
& value
)
615 if (value
.uc_group
> 127) TTCN_error("The argument of function "
616 "unichar2int() is the invalid quadruple char(%u, %u, %u, %u), the "
617 "first number of which is outside the allowed range 0 .. 127.",
618 value
.uc_group
, value
.uc_plane
, value
.uc_row
, value
.uc_cell
);
619 int result
= (value
.uc_group
<< 24) | (value
.uc_plane
<< 16) |
620 (value
.uc_row
<< 8) | value
.uc_cell
;
624 int unichar2int(const UNIVERSAL_CHARSTRING
& value
)
626 value
.must_bound("The argument of function unichar2int() is an unbound "
627 "universal charstring value.");
628 int value_length
= value
.lengthof();
629 if (value_length
!= 1) TTCN_error("The length of the argument in function "
630 "unichar2int() must be exactly 1 instead of %d.", value_length
);
631 return unichar2int(((const universal_char
*)value
)[0]);
634 int unichar2int(const UNIVERSAL_CHARSTRING_ELEMENT
& value
)
636 value
.must_bound("The argument of function unichar2int() is an unbound "
637 "universal charstring element.");
638 return unichar2int(value
.get_uchar());
643 INTEGER
bit2int(const BITSTRING
& value
)
645 value
.must_bound("The argument of function bit2int() is an unbound "
647 int n_bits
= value
.lengthof();
648 const unsigned char *bit_ptr
= (const unsigned char *)value
;
649 // skip the leading zero bits
651 for (start_index
= 0; start_index
< n_bits
; start_index
++)
652 if (bit_ptr
[start_index
/ 8] & (1 << (start_index
% 8))) break;
654 int_val_t
ret_val((RInt
)0);
655 for (int i
= start_index
; i
< n_bits
; i
++) {
657 if (bit_ptr
[i
/ 8] & (1 << (i
% 8))) ret_val
+= 1;
659 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
660 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
663 INTEGER
bit2int(const BITSTRING_ELEMENT
& value
)
665 value
.must_bound("The argument of function bit2int() is an unbound "
666 "bitstring element.");
667 return INTEGER(value
.get_bit() ? 1 : 0);
672 HEXSTRING
bit2hex(const BITSTRING
& value
)
674 value
.must_bound("The argument of function bit2hex() is an unbound "
676 int n_bits
= value
.lengthof();
677 int n_nibbles
= (n_bits
+ 3) / 4;
678 int padding_bits
= 4 * n_nibbles
- n_bits
;
679 const unsigned char *bits_ptr
= (const unsigned char *)value
;
680 HEXSTRING
ret_val(n_nibbles
);
681 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
682 memset(nibbles_ptr
, '\0', (n_nibbles
+ 1) / 2);
683 for (int i
= 0; i
< n_bits
; i
++) {
684 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) {
685 nibbles_ptr
[(i
+ padding_bits
) / 8] |= 0x80 >>
686 ((i
+ padding_bits
+ 4) % 8);
692 HEXSTRING
bit2hex(const BITSTRING_ELEMENT
& value
)
694 value
.must_bound("The argument of function bit2hex() is an unbound "
695 "bitstring element.");
696 unsigned char nibble
= value
.get_bit() ? 0x01 : 0x00;
697 return HEXSTRING(1, &nibble
);
702 OCTETSTRING
bit2oct(const BITSTRING
& value
)
704 value
.must_bound("The argument of function bit2oct() is an unbound "
706 int n_bits
= value
.lengthof();
707 int n_octets
= (n_bits
+ 7) / 8;
708 int padding_bits
= 8 * n_octets
- n_bits
;
709 const unsigned char *bits_ptr
= (const unsigned char *)value
;
710 OCTETSTRING
ret_val(n_octets
);
711 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
712 memset(octets_ptr
, '\0', n_octets
);
713 for (int i
= 0; i
< n_bits
; i
++) {
714 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) {
715 octets_ptr
[(i
+ padding_bits
) / 8] |= 0x80 >>
716 ((i
+ padding_bits
) % 8);
722 OCTETSTRING
bit2oct(const BITSTRING_ELEMENT
& value
)
724 value
.must_bound("The argument of function bit2oct() is an unbound "
725 "bitstring element.");
726 unsigned char octet
= value
.get_bit() ? 0x01 : 0x00;
727 return OCTETSTRING(1, &octet
);
732 CHARSTRING
bit2str(const BITSTRING
& value
)
734 value
.must_bound("The argument of function bit2str() is an unbound "
736 int n_bits
= value
.lengthof();
737 const unsigned char *bits_ptr
= (const unsigned char*)value
;
738 CHARSTRING
ret_val(n_bits
);
739 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
740 for (int i
= 0; i
< n_bits
; i
++) {
741 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) chars_ptr
[i
] = '1';
742 else chars_ptr
[i
] = '0';
747 CHARSTRING
bit2str(const BITSTRING_ELEMENT
& value
)
749 value
.must_bound("The argument of function bit2str() is an unbound "
750 "bitstring element.");
751 return CHARSTRING(value
.get_bit() ? '1' : '0');
756 INTEGER
hex2int(const HEXSTRING
& value
)
758 value
.must_bound("The argument of function hex2int() is an unbound "
760 int n_nibbles
= value
.lengthof();
761 const unsigned char *nibble_ptr
= (const unsigned char *)value
;
762 // skip the leading zero hex digits
764 for (start_index
= 0; start_index
< n_nibbles
; start_index
++) {
765 unsigned char mask
= start_index
% 2 ? 0xF0 : 0x0F;
766 if (nibble_ptr
[start_index
/ 2] & mask
) break;
769 int_val_t
ret_val((RInt
)0);
770 for (int i
= start_index
; i
< n_nibbles
; i
++) {
772 if (i
% 2) ret_val
+= nibble_ptr
[i
/ 2] >> 4;
773 else ret_val
+= nibble_ptr
[i
/ 2] & 0x0F;
775 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
776 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
779 INTEGER
hex2int(const HEXSTRING_ELEMENT
& value
)
781 value
.must_bound("The argument of function hex2int() is an unbound "
782 "hexstring element.");
783 return INTEGER(value
.get_nibble());
788 BITSTRING
hex2bit(const HEXSTRING
& value
)
790 value
.must_bound("The argument of function hex2bit() is an unbound "
792 int n_nibbles
= value
.lengthof();
793 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
794 BITSTRING
ret_val(4 * n_nibbles
);
795 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
796 int n_octets
= (n_nibbles
+ 1) / 2;
797 for (int i
= 0; i
< n_octets
; i
++) {
798 bits_ptr
[i
] = nibble_reverse_table
[nibbles_ptr
[i
]];
800 ret_val
.clear_unused_bits();
804 BITSTRING
hex2bit(const HEXSTRING_ELEMENT
& value
)
806 value
.must_bound("The argument of function hex2bit() is an unbound "
807 "hexstring element.");
808 unsigned char bits
= nibble_reverse_table
[value
.get_nibble()];
809 return BITSTRING(4, &bits
);
814 OCTETSTRING
hex2oct(const HEXSTRING
& value
)
816 value
.must_bound("The argument of function hex2oct() is an unbound "
818 int n_nibbles
= value
.lengthof();
819 int n_octets
= (n_nibbles
+ 1) / 2;
820 int padding_nibbles
= n_nibbles
% 2;
821 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
822 OCTETSTRING
ret_val(n_octets
);
823 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
824 if (padding_nibbles
> 0) octets_ptr
[0] = 0;
825 for (int i
= 0; i
< n_nibbles
; i
++) {
826 unsigned char hexdigit
;
827 if (i
% 2) hexdigit
= nibbles_ptr
[i
/ 2] >> 4;
828 else hexdigit
= nibbles_ptr
[i
/ 2] & 0x0F;
829 if ((i
+ padding_nibbles
) % 2)
830 octets_ptr
[(i
+ padding_nibbles
) / 2] |= hexdigit
;
831 else octets_ptr
[(i
+ padding_nibbles
) / 2] = hexdigit
<< 4;
836 OCTETSTRING
hex2oct(const HEXSTRING_ELEMENT
& value
)
838 value
.must_bound("The argument of function hex2oct() is an unbound "
839 "hexstring element.");
840 unsigned char octet
= value
.get_nibble();
841 return OCTETSTRING(1, &octet
);
846 CHARSTRING
hex2str(const HEXSTRING
& value
)
848 value
.must_bound("The argument of function hex2str() is an unbound "
850 int n_nibbles
= value
.lengthof();
851 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
852 CHARSTRING
ret_val(n_nibbles
);
853 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
854 for (int i
= 0; i
< n_nibbles
; i
++) {
855 unsigned char hexdigit
;
856 if (i
% 2) hexdigit
= nibbles_ptr
[i
/ 2] >> 4;
857 else hexdigit
= nibbles_ptr
[i
/ 2] & 0x0F;
858 chars_ptr
[i
] = hexdigit_to_char(hexdigit
);
863 CHARSTRING
hex2str(const HEXSTRING_ELEMENT
& value
)
865 value
.must_bound("The argument of function hex2str() is an unbound "
866 "hexstring element.");
867 return CHARSTRING(hexdigit_to_char(value
.get_nibble()));
872 INTEGER
oct2int(const OCTETSTRING
& value
)
874 value
.must_bound("The argument of function oct2int() is an unbound "
875 "octetstring value.");
876 int n_octets
= value
.lengthof();
877 const unsigned char *octet_ptr
= (const unsigned char *)value
;
879 for (start_index
= 0; start_index
< n_octets
; start_index
++)
880 if (octet_ptr
[start_index
]) break;
881 int_val_t
ret_val((RInt
)0);
882 for (int i
= start_index
; i
< n_octets
; i
++) {
884 ret_val
+= octet_ptr
[i
];
886 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
887 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
890 INTEGER
oct2int(const OCTETSTRING_ELEMENT
& value
)
892 value
.must_bound("The argument of function oct2int() is an unbound "
893 "octetstring element.");
894 return INTEGER(value
.get_octet());
899 BITSTRING
oct2bit(const OCTETSTRING
& value
)
901 value
.must_bound("The argument of function oct2bit() is an unbound "
902 "octetstring value.");
903 int n_octets
= value
.lengthof();
904 const unsigned char *octets_ptr
= (const unsigned char *)value
;
905 BITSTRING
ret_val(8 * n_octets
);
906 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
907 for (int i
= 0; i
< n_octets
; i
++) {
908 bits_ptr
[i
] = bit_reverse_table
[octets_ptr
[i
]];
913 BITSTRING
oct2bit(const OCTETSTRING_ELEMENT
& value
)
915 value
.must_bound("The argument of function oct2bit() is an unbound "
916 "octetstring element.");
917 unsigned char bits
= bit_reverse_table
[value
.get_octet()];
918 return BITSTRING(8, &bits
);
923 HEXSTRING
oct2hex(const OCTETSTRING
& value
)
925 value
.must_bound("The argument of function oct2hex() is an unbound "
926 "octetstring value.");
927 int n_octets
= value
.lengthof();
928 const unsigned char *octets_ptr
= (const unsigned char *)value
;
929 HEXSTRING
ret_val(2 * n_octets
);
930 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
931 for (int i
= 0; i
< n_octets
; i
++) {
932 nibbles_ptr
[i
] = nibble_swap_table
[octets_ptr
[i
]];
937 HEXSTRING
oct2hex(const OCTETSTRING_ELEMENT
& value
)
939 value
.must_bound("The argument of function oct2hex() is an unbound "
940 "octetstring element.");
941 unsigned char nibbles
= nibble_swap_table
[value
.get_octet()];
942 return HEXSTRING(2, &nibbles
);
947 CHARSTRING
oct2str(const OCTETSTRING
& value
)
949 value
.must_bound("The argument of function oct2str() is an unbound "
950 "octetstring value.");
951 int n_octets
= value
.lengthof();
952 const unsigned char *octets_ptr
= (const unsigned char *)value
;
953 CHARSTRING
ret_val(2 * n_octets
);
954 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
955 for (int i
= 0; i
< n_octets
; i
++) {
956 chars_ptr
[2 * i
] = hexdigit_to_char(octets_ptr
[i
] >> 4);
957 chars_ptr
[2 * i
+ 1] = hexdigit_to_char(octets_ptr
[i
] & 0x0F);
962 CHARSTRING
oct2str(const OCTETSTRING_ELEMENT
& value
)
964 value
.must_bound("The argument of function oct2str() is an unbound "
965 "octetstring element.");
966 unsigned char octet
= value
.get_octet();
968 result
[0] = hexdigit_to_char(octet
>> 4);
969 result
[1] = hexdigit_to_char(octet
& 0x0F);
970 return CHARSTRING(2, result
);
975 CHARSTRING
oct2char(const OCTETSTRING
& value
)
977 value
.must_bound("The argument of function oct2char() is an unbound "
978 "octetstring value.");
979 int value_length
= value
.lengthof();
980 const unsigned char *octets_ptr
= (const unsigned char*)value
;
981 for (int i
= 0; i
< value_length
; i
++) {
982 unsigned char octet
= octets_ptr
[i
];
983 if (octet
> 127) TTCN_error("The argument of function oct2char() "
984 "contains octet %02X at index %d, which is outside the allowed "
985 "range 00 .. 7F.", octet
, i
);
987 return CHARSTRING(value_length
, (const char*)octets_ptr
);
990 CHARSTRING
oct2char(const OCTETSTRING_ELEMENT
& value
)
992 value
.must_bound("The argument of function oct2char() is an unbound "
993 "octetstring element.");
994 unsigned char octet
= value
.get_octet();
995 if (octet
> 127) TTCN_error("The argument of function oct2char() "
996 "contains the octet %02X, which is outside the allowed range 00 .. 7F.",
998 return CHARSTRING((char)octet
);
1001 UNIVERSAL_CHARSTRING
oct2unichar(const OCTETSTRING
& invalue
)
1003 // default encoding is UTF-8
1004 UNIVERSAL_CHARSTRING ucstr
;
1005 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
1006 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
1007 ucstr
.decode_utf8(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF_8
, true);
1008 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
1012 UNIVERSAL_CHARSTRING
oct2unichar(const OCTETSTRING
& invalue
,
1013 const CHARSTRING
& string_encoding
)
1015 UNIVERSAL_CHARSTRING ucstr
;
1016 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
1017 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
1018 if ("UTF-8" == string_encoding
) {
1019 ucstr
.decode_utf8(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF_8
, true);
1021 else if ("UTF-16" == string_encoding
) {
1022 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16
);
1024 else if ("UTF-16BE" == string_encoding
) {
1025 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16BE
);
1027 else if ("UTF-16LE" == string_encoding
) {
1028 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16LE
);
1030 else if ("UTF-32" == string_encoding
) {
1031 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32
);
1033 else if ("UTF-32BE" == string_encoding
) {
1034 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32BE
);
1036 else if ("UTF-32LE" == string_encoding
) {
1037 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32LE
);
1039 else { TTCN_error("oct2unichar: Invalid parameter: %s", (const char*)string_encoding
);
1041 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
1047 INTEGER
str2int(const char *value
)
1049 return str2int(CHARSTRING(value
));
1052 INTEGER
str2int(const CHARSTRING
& value
)
1054 value
.must_bound("The argument of function str2int() is an unbound "
1055 "charstring value.");
1056 int value_len
= value
.lengthof();
1057 if (value_len
== 0) TTCN_error("The argument of function str2int() is an "
1058 "empty string, which does not represent a valid integer value.");
1059 const char *value_str
= value
;
1060 enum { S_INITIAL
, S_FIRST
, S_ZERO
, S_MORE
, S_END
, S_ERR
} state
= S_INITIAL
;
1061 // state: expected characters
1062 // S_INITIAL: +, -, first digit, leading whitespace
1063 // S_FIRST: first digit
1064 // S_ZERO, S_MORE: more digit(s), trailing whitespace
1065 // S_END: trailing whitespace
1066 // S_ERR: error was found, stop
1067 boolean leading_ws
= FALSE
, leading_zero
= FALSE
;
1068 for (int i
= 0; i
< value_len
; i
++) {
1069 char c
= value_str
[i
];
1072 if (c
== '+' || c
== '-') state
= S_FIRST
;
1073 else if (c
== '0') state
= S_ZERO
;
1074 else if (c
>= '1' && c
<= '9') state
= S_MORE
;
1075 else if (is_whitespace(c
)) leading_ws
= TRUE
;
1079 if (c
== '0') state
= S_ZERO
;
1080 else if (c
>= '1' && c
<= '9') state
= S_MORE
;
1084 if (c
>= '0' && c
<= '9') {
1085 leading_zero
= TRUE
;
1087 } else if (is_whitespace(c
)) state
= S_END
;
1091 if (c
>= '0' && c
<= '9') {}
1092 else if (is_whitespace(c
)) state
= S_END
;
1096 if (!is_whitespace(c
)) state
= S_ERR
;
1101 if (state
== S_ERR
) {
1102 TTCN_error_begin("The argument of function str2int(), which is ");
1104 TTCN_Logger::log_event_str(", does not represent a valid integer "
1105 "value. Invalid character `");
1106 TTCN_Logger::log_char_escaped(c
);
1107 TTCN_Logger::log_event("' was found at index %d.", i
);
1111 if (state
!= S_ZERO
&& state
!= S_MORE
&& state
!= S_END
) {
1112 TTCN_error_begin("The argument of function str2int(), which is ");
1114 TTCN_Logger::log_event_str(", does not represent a valid integer "
1115 "value. Premature end of the string.");
1119 TTCN_warning_begin("Leading whitespace was detected in the argument "
1120 "of function str2int(): ");
1122 TTCN_Logger::log_char('.');
1126 TTCN_warning_begin("Leading zero digit was detected in the argument "
1127 "of function str2int(): ");
1129 TTCN_Logger::log_char('.');
1132 if (state
== S_END
) {
1133 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1134 "of function str2int(): ");
1136 TTCN_Logger::log_char('.');
1139 return INTEGER(value_str
);
1142 INTEGER
str2int(const CHARSTRING_ELEMENT
& value
)
1144 value
.must_bound("The argument of function str2int() is an unbound "
1145 "charstring element.");
1146 char c
= value
.get_char();
1147 if (c
< '0' || c
> '9') {
1148 TTCN_error_begin("The argument of function str2int(), which is a "
1149 "charstring element containing character `");
1150 TTCN_Logger::log_char_escaped(c
);
1151 TTCN_Logger::log_event_str("', does not represent a valid integer "
1155 return INTEGER(c
- '0');
1160 OCTETSTRING
str2oct(const char *value
)
1162 if (value
== NULL
) return OCTETSTRING(0, NULL
);
1163 else return str2oct(CHARSTRING(value
));
1166 OCTETSTRING
str2oct(const CHARSTRING
& value
)
1168 value
.must_bound("The argument of function str2oct() is an unbound "
1169 "charstring value.");
1170 int value_len
= value
.lengthof();
1171 if (value_len
% 2) TTCN_error("The argument of function str2oct() must "
1172 "have even number of characters containing hexadecimal digits, but "
1173 "the length of the string is odd: %d.", value_len
);
1174 OCTETSTRING
ret_val(value_len
/ 2);
1175 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
1176 const char *chars_ptr
= value
;
1177 for (int i
= 0; i
< value_len
; i
++) {
1178 char c
= chars_ptr
[i
];
1179 unsigned char hex_digit
= char_to_hexdigit(c
);
1180 if (hex_digit
> 0x0F) {
1181 TTCN_error_begin("The argument of function str2oct() shall "
1182 "contain hexadecimal digits only, but character `");
1183 TTCN_Logger::log_char_escaped(c
);
1184 TTCN_Logger::log_event("' was found at index %d.", i
);
1187 if (i
% 2) octets_ptr
[i
/ 2] |= hex_digit
;
1188 else octets_ptr
[i
/ 2] = hex_digit
<< 4;
1195 double str2float(const char *value
)
1197 return str2float(CHARSTRING(value
));
1201 * leading zeros are allowed;
1202 * leading "+" sign before positive values is allowed;
1203 * "-0.0" is allowed;
1204 * no numbers after the dot in the decimal notation are allowed.
1206 double str2float(const CHARSTRING
& value
)
1208 value
.must_bound("The argument of function str2float() is an unbound "
1209 "charstring value.");
1210 int value_len
= value
.lengthof();
1211 if (value_len
== 0) TTCN_error("The argument of function str2float() is "
1212 "an empty string, which does not represent a valid float value.");
1213 const char *value_str
= value
;
1214 enum { S_INITIAL
, S_FIRST_M
, S_ZERO_M
, S_MORE_M
, S_FIRST_F
, S_MORE_F
,
1215 S_INITIAL_E
, S_FIRST_E
, S_ZERO_E
, S_MORE_E
, S_END
, S_ERR
}
1217 // state: expected characters
1218 // S_INITIAL: +, -, first digit of integer part in mantissa,
1219 // leading whitespace
1220 // S_FIRST_M: first digit of integer part in mantissa
1221 // S_ZERO_M, S_MORE_M: more digits of mantissa, decimal dot, E
1222 // S_FIRST_F: first digit of fraction
1223 // S_MORE_F: more digits of fraction, E, trailing whitespace
1224 // S_INITIAL_E: +, -, first digit of exponent
1225 // S_FIRST_E: first digit of exponent
1226 // S_ZERO_E, S_MORE_E: more digits of exponent, trailing whitespace
1227 // S_END: trailing whitespace
1228 // S_ERR: error was found, stop
1229 boolean leading_ws
= FALSE
, leading_zero
= FALSE
;
1230 for (int i
= 0; i
< value_len
; i
++) {
1231 char c
= value_str
[i
];
1234 if (c
== '+' || c
== '-') state
= S_FIRST_M
;
1235 else if (c
== '0') state
= S_ZERO_M
;
1236 else if (c
>= '1' && c
<= '9') state
= S_MORE_M
;
1237 else if (is_whitespace(c
)) leading_ws
= TRUE
;
1240 case S_FIRST_M
: // first mantissa digit
1241 if (c
== '0') state
= S_ZERO_M
;
1242 else if (c
>= '1' && c
<= '9') state
= S_MORE_M
;
1245 case S_ZERO_M
: // leading mantissa zero
1246 if (c
== '.') state
= S_FIRST_F
;
1247 else if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1248 else if (c
>= '0' && c
<= '9') {
1249 leading_zero
= TRUE
;
1251 } else state
= S_ERR
;
1254 if (c
== '.') state
= S_FIRST_F
;
1255 else if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1256 else if (c
>= '0' && c
<= '9') {}
1260 if (c
>= '0' && c
<= '9') state
= S_MORE_F
;
1264 if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1265 else if (c
>= '0' && c
<= '9') {}
1266 else if (is_whitespace(c
)) state
= S_END
;
1270 if (c
== '+' || c
== '-') state
= S_FIRST_E
;
1271 else if (c
== '0') state
= S_ZERO_E
;
1272 else if (c
>= '1' && c
<= '9') state
= S_MORE_E
;
1276 if (c
== '0') state
= S_ZERO_E
;
1277 else if (c
>= '1' && c
<= '9') state
= S_MORE_E
;
1281 if (c
>= '0' && c
<= '9') {
1282 leading_zero
= TRUE
;
1284 } else if (is_whitespace(c
)) state
= S_END
;
1288 if (c
>= '0' && c
<= '9') {}
1289 else if (is_whitespace(c
)) state
= S_END
;
1293 if (!is_whitespace(c
)) state
= S_ERR
;
1298 if (state
== S_ERR
) {
1299 TTCN_error_begin("The argument of function str2float(), which is ");
1301 TTCN_Logger::log_event_str(", does not represent a valid float "
1302 "value. Invalid character `");
1303 TTCN_Logger::log_char_escaped(c
);
1304 TTCN_Logger::log_event("' was found at index %d.", i
);
1316 // OK now (decimal dot missing after mantissa)
1319 // OK now (fraction part missing)
1322 TTCN_error_begin("The argument of function str2float(), which is ");
1324 TTCN_Logger::log_event_str(", does not represent a valid float value. "
1325 "Premature end of the string.");
1330 TTCN_warning_begin("Leading whitespace was detected in the argument "
1331 "of function str2float(): ");
1333 TTCN_Logger::log_char('.');
1337 TTCN_warning_begin("Leading zero digit was detected in the argument "
1338 "of function str2float(): ");
1340 TTCN_Logger::log_char('.');
1343 if (state
== S_END
) {
1344 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1345 "of function str2float(): ");
1347 TTCN_Logger::log_char('.');
1350 return atof(value_str
);
1355 CHARSTRING
regexp(const CHARSTRING
& instr
, const CHARSTRING
& expression
,
1358 instr
.must_bound("The first argument (instr) of function regexp() is an "
1359 "unbound charstring value.");
1360 expression
.must_bound("The second argument (expression) of function "
1361 "regexp() is an unbound charstring value.");
1362 if (groupno
< 0) TTCN_error("The third argument (groupno) of function "
1363 "regexp() is a negative integer value: %d.", groupno
);
1364 int instr_len
= instr
.lengthof();
1365 const char *instr_str
= instr
;
1366 for (int i
= 0; i
< instr_len
; i
++) {
1367 if (instr_str
[i
] == '\0') {
1368 TTCN_warning_begin("The first argument (instr) of function regexp(), "
1371 TTCN_Logger::log_event(", contains a character with zero character code "
1372 "at index %d. The rest of the string will be ignored during matching.",
1378 int expression_len
= expression
.lengthof();
1379 const char *expression_str
= expression
;
1380 for (int i
= 0; i
< expression_len
; i
++) {
1381 if (expression_str
[i
] == '\0') {
1382 TTCN_warning_begin("The second argument (expression) of function "
1383 "regexp(), which is ");
1385 TTCN_Logger::log_event(", contains a character with zero character code "
1386 "at index %d. The rest of the string will be ignored during matching.",
1392 char *posix_str
= TTCN_pattern_to_regexp(expression_str
);
1393 if (posix_str
== NULL
) {
1394 TTCN_error_begin("The second argument (expression) of function "
1395 "regexp(), which is ");
1397 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1400 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED
)) {
1401 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED
);
1402 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1403 CHARSTRING_template(STRING_PATTERN
, expression
).log();
1404 TTCN_Logger::log_event_str(" is: ");
1405 CHARSTRING(posix_str
).log();
1406 TTCN_Logger::end_event();
1408 regex_t posix_regexp
;
1409 int ret_val
= regcomp(&posix_regexp
, posix_str
, REG_EXTENDED
);
1412 char msg
[ERRMSG_BUFSIZE
];
1413 regerror(ret_val
, &posix_regexp
, msg
, sizeof(msg
));
1414 regfree(&posix_regexp
);
1415 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1416 "failed in function regexp() when trying to match with character "
1419 TTCN_Logger::log_event(". Error message: %s.", msg
);
1422 int re_nsub
= posix_regexp
.re_nsub
;
1424 regfree(&posix_regexp
);
1425 TTCN_error_begin("The character pattern in the second argument "
1426 "(expression) of function regexp() does not contain any groups: ");
1428 TTCN_Logger::log_char('.');
1431 if (groupno
>= re_nsub
) {
1432 regfree(&posix_regexp
);
1433 TTCN_error("The third argument (groupno) of function regexp() is too "
1434 "large: The requested group index is %d, but the pattern contains only "
1435 "%d group%s.", groupno
, re_nsub
, re_nsub
> 1 ? "s" : "");
1437 size_t nmatch
= groupno
+ 1;
1438 regmatch_t
*pmatch
= (regmatch_t
*)Malloc((nmatch
+ 1) * sizeof(*pmatch
));
1439 ret_val
= regexec(&posix_regexp
, instr
, nmatch
+ 1, pmatch
, 0);
1441 int begin_index
= pmatch
[nmatch
].rm_so
, end_index
= pmatch
[nmatch
].rm_eo
;
1443 regfree(&posix_regexp
);
1444 if (end_index
> instr_len
) TTCN_error("Internal error: The end index "
1445 "of the substring (%d) to be returned in function regexp() is greater "
1446 "than the length of the input string (%d).", end_index
, instr_len
);
1447 if (begin_index
> end_index
) TTCN_error("Internal error: The start index "
1448 "of the substring (%d) to be returned in function regexp() is greater "
1449 "than the end index (%d).", begin_index
, end_index
);
1450 return CHARSTRING(end_index
- begin_index
, instr_str
+ begin_index
);
1453 if (ret_val
!= REG_NOMATCH
) {
1454 char msg
[ERRMSG_BUFSIZE
];
1455 regerror(ret_val
, &posix_regexp
, msg
, ERRMSG_BUFSIZE
);
1456 regfree(&posix_regexp
);
1457 TTCN_error("Internal error: POSIX regular expression matching returned "
1458 "unexpected status code in function regexp(): %s.", msg
);
1459 } else regfree(&posix_regexp
);
1460 return CHARSTRING(0, NULL
);
1464 CHARSTRING
regexp(const CHARSTRING
& instr
, const CHARSTRING
& expression
,
1465 const INTEGER
& groupno
)
1467 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1468 "unbound integer value.");
1469 return regexp(instr
, expression
, (int)groupno
);
1472 /* Needed by regexp() */
1473 UNIVERSAL_CHARSTRING
convert_from_pattern_form(char* str
, int num
) {
1475 TTCN_error("Internal error: Cannot convert string from pattern form.");
1477 unsigned char c1
, c2
;
1478 universal_char
* const res
= new universal_char
[num
/8];
1479 unsigned char* ptr
= (unsigned char*)res
;
1481 while (index
< num
) {
1482 for (int j
= 0; j
< 4; j
++) {
1485 if (c1
>= 'A' && c1
<= 'P' && c2
>= 'A' && c2
<= 'P') {
1486 *(ptr
++) = ((c1
- 'A') << 4) | (c2
- 'A');
1488 TTCN_error("Internal error: Cannot convert string containing illegal "
1492 UNIVERSAL_CHARSTRING
retval(num
/ 8, res
);
1497 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1498 const UNIVERSAL_CHARSTRING
* expression_val
,
1499 const UNIVERSAL_CHARSTRING_template
* expression_tmpl
,
1502 if ( (expression_val
&& expression_tmpl
) ||
1503 (!expression_val
&& !expression_tmpl
) )
1504 TTCN_error("Internal error: regexp(): invalid parameters");
1505 instr
.must_bound("The first argument (instr) of function regexp() is an "
1506 "unbound charstring value.");
1508 expression_val
->must_bound("The second argument (expression) of function "
1509 "regexp() is an unbound universal charstring value.");
1511 if (!expression_tmpl
->is_bound())
1512 TTCN_error("The second argument (expression) of function "
1513 "regexp() is an unbound universal charstring template.");
1515 if (groupno
< 0) TTCN_error("The third argument (groupno) of function "
1516 "regexp() is a negative integer value: %d.", groupno
);
1518 int* user_groups
= 0;
1519 CHARSTRING expression_str
;
1521 expression_str
= expression_val
->get_stringRepr_for_pattern();
1523 expression_str
= expression_tmpl
->get_single_value();
1524 char *posix_str
= TTCN_pattern_to_regexp_uni((const char*)expression_str
,
1526 if (user_groups
== 0) {
1529 TTCN_error("Cannot find any groups in the second argument of regexp().");
1531 if (posix_str
== NULL
) {
1532 TTCN_error_begin("The second argument (expression) of function "
1533 "regexp(), which is ");
1534 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1535 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1538 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED
)) {
1539 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED
);
1540 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1541 CHARSTRING_template(STRING_PATTERN
, expression_str
).log();
1542 TTCN_Logger::log_event_str(" is: ");
1543 CHARSTRING(posix_str
).log();
1544 TTCN_Logger::end_event();
1547 regex_t posix_regexp
;
1548 int ret_val
= regcomp(&posix_regexp
, posix_str
, REG_EXTENDED
);
1551 char msg
[ERRMSG_BUFSIZE
];
1552 regerror(ret_val
, &posix_regexp
, msg
, sizeof(msg
));
1553 regfree(&posix_regexp
);
1554 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1555 "failed in function regexp() when trying to match with character "
1557 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1558 TTCN_Logger::log_event(". Error message: %s.", msg
);
1562 int re_nsub
= user_groups
[0];
1564 if (posix_regexp
.re_nsub
<= 0) {
1565 regfree(&posix_regexp
);
1566 TTCN_error_begin("The character pattern in the second argument "
1567 "(expression) of function regexp() does not contain any groups: ");
1568 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1569 TTCN_Logger::log_char('.');
1572 if (groupno
>= re_nsub
) {
1573 regfree(&posix_regexp
);
1574 TTCN_error("The third argument (groupno) of function regexp() is too "
1575 "large: The requested group index is %d, but the pattern contains only "
1576 "%d group%s.", groupno
, re_nsub
, re_nsub
> 1 ? "s" : "");
1578 if (groupno
> user_groups
[0]) {
1579 printf(" user_groups: %d\n", user_groups
[0]);
1580 TTCN_error("Error during parsing the pattern.");
1582 size_t nmatch
= (size_t)user_groups
[groupno
+1] + 1;
1583 regmatch_t
*pmatch
= (regmatch_t
*)Malloc((nmatch
+ 1) * sizeof(*pmatch
));
1587 char* instr_conv
= instr
.convert_to_regexp_form();
1588 int instr_len
= instr
.lengthof() * 8;
1590 ret_val
= regexec(&posix_regexp
, instr_conv
, nmatch
+ 1, pmatch
, 0);
1592 int begin_index
= pmatch
[nmatch
].rm_so
, end_index
= pmatch
[nmatch
].rm_eo
;
1594 regfree(&posix_regexp
);
1595 if (end_index
> instr_len
) TTCN_error("Internal error: The end index "
1596 "of the substring (%d) to be returned in function regexp() is greater "
1597 "than the length of the input string (%d).", end_index
, instr_len
);
1598 if (begin_index
> end_index
) TTCN_error("Internal error: The start index "
1599 "of the substring (%d) to be returned in function regexp() is greater "
1600 "than the end index (%d).", begin_index
, end_index
);
1601 UNIVERSAL_CHARSTRING res
= convert_from_pattern_form(
1602 instr_conv
+ begin_index
, end_index
- begin_index
);
1608 if (ret_val
!= REG_NOMATCH
) {
1609 char msg
[ERRMSG_BUFSIZE
];
1610 regerror(ret_val
, &posix_regexp
, msg
, ERRMSG_BUFSIZE
);
1611 regfree(&posix_regexp
);
1612 TTCN_error("Internal error: POSIX regular expression matching returned "
1613 "unexpected status code in function regexp(): %s.", msg
);
1614 } else regfree(&posix_regexp
);
1615 return UNIVERSAL_CHARSTRING(0, (const char*)NULL
);
1619 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1620 const UNIVERSAL_CHARSTRING
& expression
, int groupno
)
1622 return regexp(instr
, &expression
, NULL
, groupno
);
1625 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1626 const UNIVERSAL_CHARSTRING
& expression
, const INTEGER
& groupno
)
1628 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1629 "unbound integer value.");
1630 return regexp(instr
, expression
, (int)groupno
);
1633 // regexp() on templates
1635 CHARSTRING
regexp(const CHARSTRING_template
& instr
,
1636 const CHARSTRING_template
& expression
, int groupno
)
1638 if (!instr
.is_value())
1639 TTCN_error("The first argument of function regexp() is a "
1640 "template with non-specific value.");
1641 if (expression
.is_value())
1642 return regexp(instr
.valueof(), expression
.valueof(), groupno
);
1643 // pattern matching to specific value
1644 if (expression
.get_selection()==STRING_PATTERN
)
1645 return regexp(instr
.valueof(), expression
.get_single_value(), groupno
);
1646 TTCN_error("The second argument of function regexp() should be "
1647 "specific value or pattern matching template.");
1650 CHARSTRING
regexp(const CHARSTRING_template
& instr
,
1651 const CHARSTRING_template
& expression
, const INTEGER
& groupno
)
1653 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1654 "unbound integer value.");
1655 return regexp(instr
, expression
, (int)groupno
);
1658 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING_template
& instr
,
1659 const UNIVERSAL_CHARSTRING_template
& expression
, int groupno
)
1661 if (!instr
.is_value())
1662 TTCN_error("The first argument of function regexp() is a "
1663 "template with non-specific value.");
1664 if (expression
.is_value())
1665 return regexp(instr
.valueof(), expression
.valueof(), groupno
);
1666 // pattern matching to specific value
1667 if (expression
.get_selection()==STRING_PATTERN
)
1668 return regexp(instr
.valueof(), NULL
, &expression
, groupno
);
1669 TTCN_error("The second argument of function regexp() should be "
1670 "specific value or pattern matching template.");
1673 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING_template
& instr
,
1674 const UNIVERSAL_CHARSTRING_template
& expression
, const INTEGER
& groupno
)
1676 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1677 "unbound integer value.");
1678 return regexp(instr
, expression
, (int)groupno
);
1683 void check_substr_arguments(int value_length
, int idx
,
1684 int returncount
, const char *string_type
, const char *element_name
)
1686 if (idx
< 0) TTCN_error("The second argument (index) of function "
1687 "substr() is a negative integer value: %d.", idx
);
1688 if (idx
> value_length
) TTCN_error("The second argument (index) of "
1689 "function substr(), which is %d, is greater than the length of the "
1690 "%s value: %d.", idx
, string_type
, value_length
);
1691 if (returncount
< 0) TTCN_error("The third argument (returncount) of "
1692 "function substr() is a negative integer value: %d.", returncount
);
1693 if (idx
+ returncount
> value_length
) TTCN_error("The first argument of "
1694 "function substr(), the length of which is %d, does not have enough "
1695 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
1696 value_length
, element_name
, idx
, returncount
, element_name
,
1697 returncount
> 1 ? "s are" : " is",
1698 value_length
- idx
> 1 ? "are" : "is", value_length
- idx
);
1701 static void check_substr_arguments(int idx
, int returncount
,
1702 const char *string_type
, const char *element_name
)
1704 if (idx
< 0) TTCN_error("The second argument (index) of function "
1705 "substr() is a negative integer value: %d.", idx
);
1706 if (idx
> 1) TTCN_error("The second argument (index) of function "
1707 "substr(), which is %d, is greater than 1 (i.e. the length of the "
1708 "%s element).", idx
, string_type
);
1709 if (returncount
< 0) TTCN_error("The third argument (returncount) of "
1710 "function substr() is a negative integer value: %d.", returncount
);
1711 if (idx
+ returncount
> 1) TTCN_error("The first argument of function "
1712 "substr(), which is a%s %s element, does not have enough %ss starting "
1713 "at index %d: %d %s%s needed, but there is only %d.",
1714 string_type
[0] == 'o' ? "n" : "", string_type
, element_name
, idx
,
1715 returncount
, element_name
, returncount
> 1 ? "s are" : " is",
1719 BITSTRING
substr(const BITSTRING
& value
, int idx
, int returncount
)
1721 value
.must_bound("The first argument (value) of function substr() "
1722 "is an unbound bitstring value.");
1723 check_substr_arguments(value
.lengthof(), idx
, returncount
, "bitstring",
1726 BITSTRING
ret_val(returncount
);
1727 for (int i
= 0; i
< returncount
; i
++) {
1728 ret_val
.set_bit(i
, value
.get_bit(idx
+ i
));
1730 ret_val
.clear_unused_bits();
1733 return BITSTRING(returncount
, (const unsigned char*)value
+ idx
/ 8);
1737 BITSTRING
substr(const BITSTRING
& value
, int idx
, const INTEGER
& returncount
)
1739 returncount
.must_bound("The third argument (returncount) of function "
1740 "substr() is an unbound integer value.");
1741 return substr(value
, idx
, (int)returncount
);
1744 BITSTRING
substr(const BITSTRING
& value
, const INTEGER
& idx
, int returncount
)
1746 idx
.must_bound("The second argument (index) of function substr() "
1747 "is an unbound integer value.");
1748 return substr(value
, (int)idx
, returncount
);
1751 BITSTRING
substr(const BITSTRING
& value
, const INTEGER
& idx
,
1752 const INTEGER
& returncount
)
1754 idx
.must_bound("The second argument (index) of function substr() is an "
1755 "unbound integer value.");
1756 returncount
.must_bound("The third argument (returncount) of function "
1757 "substr() is an unbound integer value.");
1758 return substr(value
, (int)idx
, (int)returncount
);
1761 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, int idx
, int returncount
)
1763 value
.must_bound("The first argument (value) of function substr() "
1764 "is an unbound bitstring element.");
1765 check_substr_arguments(idx
, returncount
, "bitstring", "bit");
1766 if (returncount
== 0) return BITSTRING(0, NULL
);
1768 unsigned char bit
= value
.get_bit() ? 0x01 : 0x00;
1769 return BITSTRING(1, &bit
);
1773 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, int idx
,
1774 const INTEGER
& returncount
)
1776 returncount
.must_bound("The third argument (returncount) of function "
1777 "substr() is an unbound integer value.");
1778 return substr(value
, idx
, (int)returncount
);
1781 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1784 idx
.must_bound("The second argument (index) of function substr() "
1785 "is an unbound integer value.");
1786 return substr(value
, (int)idx
, returncount
);
1789 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1790 const INTEGER
& returncount
)
1792 idx
.must_bound("The second argument (index) of function substr() is an "
1793 "unbound integer value.");
1794 returncount
.must_bound("The third argument (returncount) of function "
1795 "substr() is an unbound integer value.");
1796 return substr(value
, (int)idx
, (int)returncount
);
1799 HEXSTRING
substr(const HEXSTRING
& value
, int idx
, int returncount
)
1801 value
.must_bound("The first argument (value) of function substr() "
1802 "is an unbound hexstring value.");
1803 check_substr_arguments(value
.lengthof(), idx
, returncount
, "hexstring",
1804 "hexadecimal digit");
1805 const unsigned char *src_ptr
= (const unsigned char*)value
;
1807 HEXSTRING
ret_val(returncount
);
1808 unsigned char *dst_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
1809 for (int i
= 0; i
< returncount
; i
++) {
1810 if (i
% 2) dst_ptr
[i
/ 2] |= (src_ptr
[(i
+ idx
) / 2] & 0x0F) << 4;
1811 else dst_ptr
[i
/ 2] = src_ptr
[(i
+ idx
) / 2] >> 4;
1814 } else return HEXSTRING(returncount
, src_ptr
+ idx
/ 2);
1817 HEXSTRING
substr(const HEXSTRING
& value
, int idx
, const INTEGER
& returncount
)
1819 returncount
.must_bound("The third argument (returncount) of function "
1820 "substr() is an unbound integer value.");
1821 return substr(value
, idx
, (int)returncount
);
1824 HEXSTRING
substr(const HEXSTRING
& value
, const INTEGER
& idx
, int returncount
)
1826 idx
.must_bound("The second argument (index) of function substr() "
1827 "is an unbound integer value.");
1828 return substr(value
, (int)idx
, returncount
);
1831 HEXSTRING
substr(const HEXSTRING
& value
, const INTEGER
& idx
,
1832 const INTEGER
& returncount
)
1834 idx
.must_bound("The second argument (index) of function substr() is an "
1835 "unbound integer value.");
1836 returncount
.must_bound("The third argument (returncount) of function "
1837 "substr() is an unbound integer value.");
1838 return substr(value
, (int)idx
, (int)returncount
);
1841 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, int idx
, int returncount
)
1843 value
.must_bound("The first argument (value) of function substr() "
1844 "is an unbound hexstring element.");
1845 check_substr_arguments(idx
, returncount
, "hexstring",
1846 "hexadecimal digit");
1847 if (returncount
== 0) return HEXSTRING(0, NULL
);
1849 unsigned char nibble
= value
.get_nibble();
1850 return HEXSTRING(1, &nibble
);
1854 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, int idx
,
1855 const INTEGER
& returncount
)
1857 returncount
.must_bound("The third argument (returncount) of function "
1858 "substr() is an unbound integer value.");
1859 return substr(value
, idx
, (int)returncount
);
1862 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1865 idx
.must_bound("The second argument (index) of function substr() "
1866 "is an unbound integer value.");
1867 return substr(value
, (int)idx
, returncount
);
1870 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1871 const INTEGER
& returncount
)
1873 idx
.must_bound("The second argument (index) of function substr() is an "
1874 "unbound integer value.");
1875 returncount
.must_bound("The third argument (returncount) of function "
1876 "substr() is an unbound integer value.");
1877 return substr(value
, (int)idx
, (int)returncount
);
1880 OCTETSTRING
substr(const OCTETSTRING
& value
, int idx
, int returncount
)
1882 value
.must_bound("The first argument (value) of function substr() "
1883 "is an unbound octetstring value.");
1884 check_substr_arguments(value
.lengthof(), idx
, returncount
, "octetstring",
1886 return OCTETSTRING(returncount
, (const unsigned char*)value
+ idx
);
1889 OCTETSTRING
substr(const OCTETSTRING
& value
, int idx
,
1890 const INTEGER
& returncount
)
1892 returncount
.must_bound("The third argument (returncount) of function "
1893 "substr() is an unbound integer value.");
1894 return substr(value
, idx
, (int)returncount
);
1897 OCTETSTRING
substr(const OCTETSTRING
& value
, const INTEGER
& idx
,
1900 idx
.must_bound("The second argument (index) of function substr() "
1901 "is an unbound integer value.");
1902 return substr(value
, (int)idx
, returncount
);
1905 OCTETSTRING
substr(const OCTETSTRING
& value
, const INTEGER
& idx
,
1906 const INTEGER
& returncount
)
1908 idx
.must_bound("The second argument (index) of function substr() is an "
1909 "unbound integer value.");
1910 returncount
.must_bound("The third argument (returncount) of function "
1911 "substr() is an unbound integer value.");
1912 return substr(value
, (int)idx
, (int)returncount
);
1915 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, int idx
, int returncount
)
1917 value
.must_bound("The first argument (value) of function substr() "
1918 "is an unbound octetstring element.");
1919 check_substr_arguments(idx
, returncount
, "octetstring", "octet");
1920 if (returncount
== 0) return OCTETSTRING(0, NULL
);
1922 unsigned char octet
= value
.get_octet();
1923 return OCTETSTRING(1, &octet
);
1927 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, int idx
,
1928 const INTEGER
& returncount
)
1930 returncount
.must_bound("The third argument (returncount) of function "
1931 "substr() is an unbound integer value.");
1932 return substr(value
, idx
, (int)returncount
);
1935 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1938 idx
.must_bound("The second argument (index) of function substr() "
1939 "is an unbound integer value.");
1940 return substr(value
, (int)idx
, returncount
);
1943 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1944 const INTEGER
& returncount
)
1946 idx
.must_bound("The second argument (index) of function substr() is an "
1947 "unbound integer value.");
1948 returncount
.must_bound("The third argument (returncount) of function "
1949 "substr() is an unbound integer value.");
1950 return substr(value
, (int)idx
, (int)returncount
);
1953 CHARSTRING
substr(const CHARSTRING
& value
, int idx
, int returncount
)
1955 value
.must_bound("The first argument (value) of function substr() "
1956 "is an unbound charstring value.");
1957 check_substr_arguments(value
.lengthof(), idx
, returncount
, "charstring",
1959 return CHARSTRING(returncount
, (const char*)value
+ idx
);
1962 CHARSTRING
substr(const CHARSTRING
& value
, int idx
,
1963 const INTEGER
& returncount
)
1965 returncount
.must_bound("The third argument (returncount) of function "
1966 "substr() is an unbound integer value.");
1967 return substr(value
, idx
, (int)returncount
);
1970 CHARSTRING
substr(const CHARSTRING
& value
, const INTEGER
& idx
,
1973 idx
.must_bound("The second argument (index) of function substr() "
1974 "is an unbound integer value.");
1975 return substr(value
, (int)idx
, returncount
);
1978 CHARSTRING
substr(const CHARSTRING
& value
, const INTEGER
& idx
,
1979 const INTEGER
& returncount
)
1981 idx
.must_bound("The second argument (index) of function substr() is an "
1982 "unbound integer value.");
1983 returncount
.must_bound("The third argument (returncount) of function "
1984 "substr() is an unbound integer value.");
1985 return substr(value
, (int)idx
, (int)returncount
);
1988 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, int idx
, int returncount
)
1990 value
.must_bound("The first argument (value) of function substr() "
1991 "is an unbound charstring element.");
1992 check_substr_arguments(idx
, returncount
, "charstring", "character");
1993 if (returncount
== 0) return CHARSTRING(0, NULL
);
1994 else return CHARSTRING(value
.get_char());
1997 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, int idx
,
1998 const INTEGER
& returncount
)
2000 returncount
.must_bound("The third argument (returncount) of function "
2001 "substr() is an unbound integer value.");
2002 return substr(value
, idx
, (int)returncount
);
2005 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, const INTEGER
& idx
,
2008 idx
.must_bound("The second argument (index) of function substr() "
2009 "is an unbound integer value.");
2010 return substr(value
, (int)idx
, returncount
);
2013 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, const INTEGER
& idx
,
2014 const INTEGER
& returncount
)
2016 idx
.must_bound("The second argument (index) of function substr() is an "
2017 "unbound integer value.");
2018 returncount
.must_bound("The third argument (returncount) of function "
2019 "substr() is an unbound integer value.");
2020 return substr(value
, (int)idx
, (int)returncount
);
2023 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2026 value
.must_bound("The first argument (value) of function substr() "
2027 "is an unbound universal charstring value.");
2028 check_substr_arguments(value
.lengthof(), idx
, returncount
,
2029 "universal charstring", "character");
2030 return UNIVERSAL_CHARSTRING(returncount
,
2031 (const universal_char
*)value
+ idx
);
2034 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2035 const INTEGER
& returncount
)
2037 returncount
.must_bound("The third argument (returncount) of function "
2038 "substr() is an unbound integer value.");
2039 return substr(value
, idx
, (int)returncount
);
2042 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
,
2043 const INTEGER
& idx
, int returncount
)
2045 idx
.must_bound("The second argument (index) of function substr() "
2046 "is an unbound integer value.");
2047 return substr(value
, (int)idx
, returncount
);
2050 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
,
2051 const INTEGER
& idx
, const INTEGER
& returncount
)
2053 idx
.must_bound("The second argument (index) of function substr() is an "
2054 "unbound integer value.");
2055 returncount
.must_bound("The third argument (returncount) of function "
2056 "substr() is an unbound integer value.");
2057 return substr(value
, (int)idx
, (int)returncount
);
2060 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2061 int idx
, int returncount
)
2063 value
.must_bound("The first argument (value) of function substr() "
2064 "is an unbound universal charstring element.");
2065 check_substr_arguments(idx
, returncount
, "universal charstring",
2067 if (returncount
== 0)
2068 return UNIVERSAL_CHARSTRING(0, (const universal_char
*)NULL
);
2069 else return UNIVERSAL_CHARSTRING(value
.get_uchar());
2072 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2073 int idx
, const INTEGER
& returncount
)
2075 returncount
.must_bound("The third argument (returncount) of function "
2076 "substr() is an unbound integer value.");
2077 return substr(value
, idx
, (int)returncount
);
2080 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2081 const INTEGER
& idx
, int returncount
)
2083 idx
.must_bound("The second argument (index) of function substr() "
2084 "is an unbound integer value.");
2085 return substr(value
, (int)idx
, returncount
);
2088 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2089 const INTEGER
& idx
, const INTEGER
& returncount
)
2091 idx
.must_bound("The second argument (index) of function substr() is an "
2092 "unbound integer value.");
2093 returncount
.must_bound("The third argument (returncount) of function "
2094 "substr() is an unbound integer value.");
2095 return substr(value
, (int)idx
, (int)returncount
);
2098 // substr() on templates
2099 BITSTRING
substr(const BITSTRING_template
& value
, int idx
, int returncount
)
2101 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2102 return substr(value
.valueof(), idx
, returncount
);
2105 BITSTRING
substr(const BITSTRING_template
& value
, int idx
, 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 BITSTRING
substr(const BITSTRING_template
& value
, const INTEGER
& 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 BITSTRING
substr(const BITSTRING_template
& value
, const INTEGER
& idx
,
2118 const INTEGER
& returncount
)
2120 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2121 return substr(value
.valueof(), idx
, returncount
);
2124 HEXSTRING
substr(const HEXSTRING_template
& value
, int idx
, int returncount
)
2126 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2127 return substr(value
.valueof(), idx
, returncount
);
2130 HEXSTRING
substr(const HEXSTRING_template
& value
, int idx
, 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 HEXSTRING
substr(const HEXSTRING_template
& value
, const INTEGER
& 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 HEXSTRING
substr(const HEXSTRING_template
& value
, const INTEGER
& 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
, int idx
, int returncount
)
2151 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2152 return substr(value
.valueof(), idx
, returncount
);
2155 OCTETSTRING
substr(const OCTETSTRING_template
& value
, int idx
,
2156 const INTEGER
& returncount
)
2158 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2159 return substr(value
.valueof(), idx
, returncount
);
2162 OCTETSTRING
substr(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
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 OCTETSTRING
substr(const OCTETSTRING_template
& value
, const INTEGER
& 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
, int idx
, int returncount
)
2178 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2179 return substr(value
.valueof(), idx
, returncount
);
2182 CHARSTRING
substr(const CHARSTRING_template
& value
, int idx
,
2183 const INTEGER
& returncount
)
2185 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2186 return substr(value
.valueof(), idx
, returncount
);
2189 CHARSTRING
substr(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2192 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2193 return substr(value
.valueof(), idx
, returncount
);
2196 CHARSTRING
substr(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2197 const INTEGER
& returncount
)
2199 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2200 return substr(value
.valueof(), idx
, returncount
);
2203 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
, int idx
,
2206 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2207 return substr(value
.valueof(), idx
, returncount
);
2210 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
, int idx
,
2211 const INTEGER
& returncount
)
2213 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2214 return substr(value
.valueof(), idx
, returncount
);
2217 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
,
2218 const INTEGER
& idx
, int returncount
)
2220 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2221 return substr(value
.valueof(), idx
, returncount
);
2224 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
,
2225 const INTEGER
& idx
, const INTEGER
& returncount
)
2227 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2228 return substr(value
.valueof(), idx
, returncount
);
2233 void check_replace_arguments(int value_length
, int idx
, int len
,
2234 const char *string_type
, const char *element_name
)
2236 if (idx
< 0) TTCN_error("The second argument (index) of function "
2237 "replace() is a negative integer value: %d.", idx
);
2238 if (idx
> value_length
) TTCN_error("The second argument (index) of "
2239 "function replace(), which is %d, is greater than the length of the "
2240 "%s value: %d.", idx
, string_type
, value_length
);
2241 if (len
< 0) TTCN_error("The third argument (len) of function replace() "
2242 "is a negative integer value: %d.", len
);
2243 if (len
> value_length
) TTCN_error("The third argument (len) of function "
2244 "replace(), which is %d, is greater than the length of the "
2245 "%s value: %d.", len
, string_type
, value_length
);
2246 if (idx
+ len
> value_length
) TTCN_error("The first argument of "
2247 "function replace(), the length of which is %d, does not have enough "
2248 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
2249 value_length
, element_name
, idx
, len
, element_name
,
2250 len
> 1 ? "s are" : " is", value_length
- idx
> 1 ? "are" : "is",
2251 value_length
- idx
);
2254 BITSTRING
replace(const BITSTRING
& value
, int idx
, int len
,
2255 const BITSTRING
& repl
)
2257 value
.must_bound("The first argument (value) of function replace() "
2258 "is an unbound bitstring value.");
2259 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2260 "unbound bitstring value.");
2261 check_replace_arguments(value
.lengthof(), idx
, len
, "bitstring", "bit");
2262 int value_len
= value
.lengthof();
2263 int repl_len
= repl
.lengthof();
2264 BITSTRING
ret_val(value_len
+ repl_len
- len
);
2265 for (int i
= 0; i
< idx
; i
++) ret_val
.set_bit(i
, value
.get_bit(i
));
2266 for (int i
= 0; i
< repl_len
; i
++)
2267 ret_val
.set_bit(i
+ idx
, repl
.get_bit(i
));
2268 for (int i
= 0; i
< value_len
- idx
- len
; i
++)
2269 ret_val
.set_bit(i
+ idx
+ repl_len
, value
.get_bit(idx
+ len
+ i
));
2273 BITSTRING
replace(const BITSTRING
& value
, int idx
, const INTEGER
& len
,
2274 const BITSTRING
& repl
)
2276 len
.must_bound("The third argument (len) of function replace() is an "
2277 "unbound integer value.");
2278 return replace(value
, idx
, (int)len
, repl
);
2281 BITSTRING
replace(const BITSTRING
& value
, const INTEGER
& idx
, int len
,
2282 const BITSTRING
& repl
)
2284 idx
.must_bound("The second argument (index) of function replace() is an "
2285 "unbound integer value.");
2286 return replace(value
, (int)idx
, len
, repl
);
2289 BITSTRING
replace(const BITSTRING
& value
, const INTEGER
& idx
,
2290 const INTEGER
& len
, const BITSTRING
& repl
)
2292 idx
.must_bound("The second argument (index) of function replace() is an "
2293 "unbound integer value.");
2294 len
.must_bound("The third argument (len) of function replace() is an "
2295 "unbound integer value.");
2296 return replace(value
, (int)idx
, (int)len
, repl
);
2299 HEXSTRING
replace(const HEXSTRING
& value
, int idx
, int len
,
2300 const HEXSTRING
& repl
)
2302 value
.must_bound("The first argument (value) of function replace() "
2303 "is an unbound hexstring value.");
2304 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2305 "unbound hexstring value.");
2306 check_replace_arguments(value
.lengthof(), idx
, len
, "hexstring",
2307 "hexadecimal digit");
2308 int value_len
= value
.lengthof();
2309 int repl_len
= repl
.lengthof();
2310 HEXSTRING
ret_val(value_len
+ repl_len
- len
);
2311 for (int i
= 0; i
< idx
; i
++)
2312 ret_val
.set_nibble(i
, value
.get_nibble(i
));
2313 for (int i
= 0; i
< repl_len
; i
++)
2314 ret_val
.set_nibble(idx
+ i
, repl
.get_nibble(i
));
2315 for (int i
= 0; i
< value_len
- idx
- len
; i
++)
2316 ret_val
.set_nibble(idx
+ i
+ repl_len
,
2317 value
.get_nibble(idx
+ i
+ len
));
2321 HEXSTRING
replace(const HEXSTRING
& value
, int idx
, const INTEGER
& len
,
2322 const HEXSTRING
& repl
)
2324 len
.must_bound("The third argument (len) of function replace() is an "
2325 "unbound integer value.");
2326 return replace(value
, idx
, (int)len
, repl
);
2329 HEXSTRING
replace(const HEXSTRING
& value
, const INTEGER
& idx
, int len
,
2330 const HEXSTRING
& repl
)
2332 idx
.must_bound("The second argument (index) of function replace() is an "
2333 "unbound integer value.");
2334 return replace(value
, (int)idx
, len
, repl
);
2337 HEXSTRING
replace(const HEXSTRING
& value
, const INTEGER
& idx
,
2338 const INTEGER
& len
, const HEXSTRING
& repl
)
2340 idx
.must_bound("The second argument (index) of function replace() is an "
2341 "unbound integer value.");
2342 len
.must_bound("The third argument (len) of function replace() is an "
2343 "unbound integer value.");
2344 return replace(value
, (int)idx
, (int)len
, repl
);
2347 OCTETSTRING
replace(const OCTETSTRING
& value
, int idx
, int len
,
2348 const OCTETSTRING
& repl
)
2350 value
.must_bound("The first argument (value) of function replace() "
2351 "is an unbound octetstring value.");
2352 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2353 "unbound octetstring value.");
2354 check_replace_arguments(value
.lengthof(), idx
, len
, "octetstring",
2356 int value_len
= value
.lengthof();
2357 int repl_len
= repl
.lengthof();
2358 OCTETSTRING
ret_val(value_len
+ repl_len
- len
);
2359 memcpy(ret_val
.val_ptr
->octets_ptr
, value
.val_ptr
->octets_ptr
, idx
);
2360 memcpy(ret_val
.val_ptr
->octets_ptr
+ idx
, repl
.val_ptr
->octets_ptr
,
2362 memcpy(ret_val
.val_ptr
->octets_ptr
+ idx
+ repl_len
,
2363 value
.val_ptr
->octets_ptr
+ idx
+ len
, value_len
- idx
- len
);
2367 OCTETSTRING
replace(const OCTETSTRING
& value
, int idx
, const INTEGER
& len
,
2368 const OCTETSTRING
& repl
)
2370 len
.must_bound("The third argument (len) of function replace() is an "
2371 "unbound integer value.");
2372 return replace(value
, idx
, (int)len
, repl
);
2375 OCTETSTRING
replace(const OCTETSTRING
& value
, const INTEGER
& idx
, int len
,
2376 const OCTETSTRING
& repl
)
2378 idx
.must_bound("The second argument (index) of function replace() is an "
2379 "unbound integer value.");
2380 return replace(value
, (int)idx
, len
, repl
);
2383 OCTETSTRING
replace(const OCTETSTRING
& value
, const INTEGER
& idx
,
2384 const INTEGER
& len
, const OCTETSTRING
& repl
)
2386 idx
.must_bound("The second argument (index) of function replace() is an "
2387 "unbound integer value.");
2388 len
.must_bound("The third argument (len) of function replace() is an "
2389 "unbound integer value.");
2390 return replace(value
, (int)idx
, (int)len
, repl
);
2393 CHARSTRING
replace(const CHARSTRING
& value
, int idx
, int len
,
2394 const CHARSTRING
& repl
)
2396 value
.must_bound("The first argument (value) of function replace() "
2397 "is an unbound charstring value.");
2398 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2399 "unbound charstring value.");
2400 check_replace_arguments(value
.lengthof(), idx
, len
, "charstring",
2402 int value_len
= value
.lengthof();
2403 int repl_len
= repl
.lengthof();
2404 CHARSTRING
ret_val(value_len
+ repl_len
- len
);
2405 /* According to http://gcc.gnu.org/ml/fortran/2007-05/msg00341.html it's
2406 worth using memcpy() instead of strncat(). There's no need to scan the
2407 strings for '\0'. */
2408 memcpy(ret_val
.val_ptr
->chars_ptr
, value
.val_ptr
->chars_ptr
, idx
);
2409 memcpy(ret_val
.val_ptr
->chars_ptr
+ idx
, repl
.val_ptr
->chars_ptr
,
2411 memcpy(ret_val
.val_ptr
->chars_ptr
+ idx
+ repl_len
,
2412 value
.val_ptr
->chars_ptr
+ idx
+ len
, value_len
- idx
- len
);
2416 CHARSTRING
replace(const CHARSTRING
& value
, int idx
, const INTEGER
& len
,
2417 const CHARSTRING
& repl
)
2419 len
.must_bound("The third argument (len) of function replace() is an "
2420 "unbound integer value.");
2421 return replace(value
, idx
, (int)len
, repl
);
2424 CHARSTRING
replace(const CHARSTRING
& value
, const INTEGER
& idx
, int len
,
2425 const CHARSTRING
& repl
)
2427 idx
.must_bound("The second argument (index) of function replace() is an "
2428 "unbound integer value.");
2429 return replace(value
, (int)idx
, len
, repl
);
2432 CHARSTRING
replace(const CHARSTRING
& value
, const INTEGER
& idx
,
2433 const INTEGER
& len
, const CHARSTRING
& repl
)
2435 idx
.must_bound("The second argument (index) of function replace() is an "
2436 "unbound integer value.");
2437 len
.must_bound("The third argument (len) of function replace() is an "
2438 "unbound integer value.");
2439 return replace(value
, (int)idx
, (int)len
, repl
);
2442 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2443 int len
, const UNIVERSAL_CHARSTRING
& repl
)
2445 value
.must_bound("The first argument (value) of function replace() "
2446 "is an unbound universal charstring value.");
2447 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2448 "unbound universal charstring value.");
2449 check_replace_arguments(value
.lengthof(), idx
, len
,
2450 "universal charstring", "character");
2451 int value_len
= value
.lengthof();
2452 int repl_len
= repl
.lengthof();
2453 UNIVERSAL_CHARSTRING
ret_val(value_len
+ repl_len
- len
);
2454 memcpy(ret_val
.val_ptr
->uchars_ptr
, value
.val_ptr
->uchars_ptr
,
2455 idx
* sizeof(universal_char
));
2456 memcpy(ret_val
.val_ptr
->uchars_ptr
+ idx
, repl
.val_ptr
->uchars_ptr
,
2457 repl_len
* sizeof(universal_char
));
2458 memcpy(ret_val
.val_ptr
->uchars_ptr
+ idx
+ repl_len
,
2459 value
.val_ptr
->uchars_ptr
+ idx
+ len
,
2460 (value_len
- idx
- len
) * sizeof(universal_char
));
2464 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2465 const INTEGER
& len
, const UNIVERSAL_CHARSTRING
& repl
)
2467 len
.must_bound("The third argument (len) of function replace() is an "
2468 "unbound integer value.");
2469 return replace(value
, idx
, (int)len
, repl
);
2472 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
,
2473 const INTEGER
& idx
, int len
, const UNIVERSAL_CHARSTRING
& repl
)
2475 idx
.must_bound("The second argument (index) of function replace() is an "
2476 "unbound integer value.");
2477 return replace(value
, (int)idx
, len
, repl
);
2480 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
,
2481 const INTEGER
& idx
, const INTEGER
& len
,
2482 const UNIVERSAL_CHARSTRING
& repl
)
2484 idx
.must_bound("The second argument (index) of function replace() is an "
2485 "unbound integer value.");
2486 len
.must_bound("The third argument (len) of function replace() is an "
2487 "unbound integer value.");
2488 return replace(value
, (int)idx
, (int)len
, repl
);
2491 // replace on templates
2493 BITSTRING
replace(const BITSTRING_template
& value
, int idx
, int len
,
2494 const BITSTRING_template
& repl
)
2496 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2497 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2498 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2501 BITSTRING
replace(const BITSTRING_template
& value
, int idx
, const INTEGER
& len
,
2502 const BITSTRING_template
& repl
)
2504 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2505 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2506 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2509 BITSTRING
replace(const BITSTRING_template
& value
, const INTEGER
& idx
, int len
,
2510 const BITSTRING_template
& repl
)
2512 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2513 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2514 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2517 BITSTRING
replace(const BITSTRING_template
& value
, const INTEGER
& idx
,
2518 const INTEGER
& len
, const BITSTRING_template
& repl
)
2520 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2521 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2522 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2525 HEXSTRING
replace(const HEXSTRING_template
& value
, int idx
, int len
,
2526 const HEXSTRING_template
& repl
)
2528 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2529 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2530 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2533 HEXSTRING
replace(const HEXSTRING_template
& value
, int idx
, const INTEGER
& len
,
2534 const HEXSTRING_template
& repl
)
2536 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2537 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2538 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2541 HEXSTRING
replace(const HEXSTRING_template
& value
, const INTEGER
& idx
, int len
,
2542 const HEXSTRING_template
& repl
)
2544 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2545 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2546 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2549 HEXSTRING
replace(const HEXSTRING_template
& value
, const INTEGER
& idx
,
2550 const INTEGER
& len
, const HEXSTRING_template
& repl
)
2552 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2553 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2554 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2557 OCTETSTRING
replace(const OCTETSTRING_template
& value
, int idx
, int len
,
2558 const OCTETSTRING_template
& repl
)
2560 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2561 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2562 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2565 OCTETSTRING
replace(const OCTETSTRING_template
& value
, int idx
, const INTEGER
& len
,
2566 const OCTETSTRING_template
& repl
)
2568 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2569 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2570 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2573 OCTETSTRING
replace(const OCTETSTRING_template
& value
, const INTEGER
& idx
, int len
,
2574 const OCTETSTRING_template
& repl
)
2576 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2577 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2578 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2581 OCTETSTRING
replace(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2582 const INTEGER
& len
, const OCTETSTRING_template
& repl
)
2584 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2585 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2586 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2589 CHARSTRING
replace(const CHARSTRING_template
& value
, int idx
, int len
,
2590 const CHARSTRING_template
& repl
)
2592 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2593 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2594 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2597 CHARSTRING
replace(const CHARSTRING_template
& value
, int idx
, const INTEGER
& len
,
2598 const CHARSTRING_template
& repl
)
2600 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2601 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2602 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2605 CHARSTRING
replace(const CHARSTRING_template
& value
, const INTEGER
& idx
, int len
,
2606 const CHARSTRING_template
& repl
)
2608 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2609 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2610 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2613 CHARSTRING
replace(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2614 const INTEGER
& len
, const CHARSTRING_template
& repl
)
2616 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2617 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2618 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2621 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, int idx
, int len
,
2622 const UNIVERSAL_CHARSTRING_template
& repl
)
2624 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2625 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2626 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2629 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, int idx
, const INTEGER
& len
,
2630 const UNIVERSAL_CHARSTRING_template
& repl
)
2632 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2633 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2634 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2637 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, const INTEGER
& idx
, int len
,
2638 const UNIVERSAL_CHARSTRING_template
& repl
)
2640 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2641 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2642 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2645 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, const INTEGER
& idx
,
2646 const INTEGER
& len
, const UNIVERSAL_CHARSTRING_template
& repl
)
2648 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2649 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2650 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2655 static boolean rnd_seed_set
= FALSE
;
2657 static void set_rnd_seed(double float_seed
)
2659 FLOAT::check_numeric(float_seed
, "The seed value of function rnd()");
2660 long integer_seed
= 0;
2661 const unsigned char *src_ptr
= (const unsigned char*)&float_seed
;
2662 unsigned char *dst_ptr
= (unsigned char*)&integer_seed
;
2663 for (size_t i
= 0; i
< sizeof(float_seed
); i
++) {
2664 dst_ptr
[i
% sizeof(integer_seed
)] ^= bit_reverse_table
[src_ptr
[i
]];
2665 dst_ptr
[(sizeof(float_seed
) - 1 - i
) % sizeof(integer_seed
)] ^=
2669 srand48(integer_seed
);
2670 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::seed
, float_seed
, integer_seed
);
2671 rnd_seed_set
= TRUE
;
2674 static double rnd_generate()
2677 ret_val
= drand48();
2678 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::read__out
, ret_val
, 0);
2684 if (!rnd_seed_set
) set_rnd_seed(TTCN_Snapshot::time_now());
2685 return rnd_generate();
2688 double rnd(double seed
)
2691 return rnd_generate();
2694 double rnd(const FLOAT
& seed
)
2696 seed
.must_bound("Initializing the random number generator with "
2697 "an unbound float value as seed.");
2698 set_rnd_seed((double)seed
);
2699 return rnd_generate();
2703 // Additional predefined functions defined in Annex B of ES 101 873-7
2705 // B.1 decomp - not implemented yet
2708 // Non-standard functions
2712 BITSTRING
str2bit(const char *value
)
2714 if (value
== NULL
) return BITSTRING(0, NULL
);
2715 else return str2bit(CHARSTRING(value
));
2718 BITSTRING
str2bit(const CHARSTRING
& value
)
2720 value
.must_bound("The argument of function str2bit() is an unbound "
2721 "charstring value.");
2722 int value_length
= value
.lengthof();
2723 const char *chars_ptr
= value
;
2724 BITSTRING
ret_val(value_length
);
2725 for (int i
= 0; i
< value_length
; i
++) {
2726 char c
= chars_ptr
[i
];
2729 ret_val
.set_bit(i
, FALSE
);
2732 ret_val
.set_bit(i
, TRUE
);
2735 TTCN_error_begin("The argument of function str2bit() shall "
2736 "contain characters `0' and `1' only, but character `");
2737 TTCN_Logger::log_char_escaped(c
);
2738 TTCN_Logger::log_event("' was found at index %d.", i
);
2742 ret_val
.clear_unused_bits();
2746 BITSTRING
str2bit(const CHARSTRING_ELEMENT
& value
)
2748 value
.must_bound("The argument of function str2bit() is an unbound "
2749 "charstring element.");
2750 char c
= value
.get_char();
2751 if (c
!= '0' && c
!= '1') {
2752 TTCN_error_begin("The argument of function str2bit() shall contain "
2753 "characters `0' and `1' only, but the given charstring element "
2754 "contains the character `");
2755 TTCN_Logger::log_char_escaped(c
);
2756 TTCN_Logger::log_event_str("'.");
2759 unsigned char bit
= c
== '1' ? 0x01 : 0x00;
2760 return BITSTRING(1, &bit
);
2765 HEXSTRING
str2hex(const char *value
)
2767 if (value
== NULL
) return HEXSTRING(0, NULL
);
2768 else return str2hex(CHARSTRING(value
));
2771 HEXSTRING
str2hex(const CHARSTRING
& value
)
2773 value
.must_bound("The argument of function str2hex() is an unbound "
2774 "charstring value.");
2775 int value_length
= value
.lengthof();
2776 const char *chars_ptr
= value
;
2777 HEXSTRING
ret_val(value_length
);
2778 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
2779 for (int i
= 0; i
< value_length
; i
++) {
2780 char c
= chars_ptr
[i
];
2781 unsigned char hex_digit
= char_to_hexdigit(c
);
2782 if (hex_digit
> 0x0F) {
2783 TTCN_error_begin("The argument of function str2hex() shall "
2784 "contain hexadecimal digits only, but character `");
2785 TTCN_Logger::log_char_escaped(c
);
2786 TTCN_Logger::log_event("' was found at index %d.", i
);
2789 if (i
% 2) nibbles_ptr
[i
/ 2] |= hex_digit
<< 4;
2790 else nibbles_ptr
[i
/ 2] = hex_digit
;
2795 HEXSTRING
str2hex(const CHARSTRING_ELEMENT
& value
)
2797 value
.must_bound("The argument of function str2hex() is an unbound "
2798 "charstring element.");
2799 char c
= value
.get_char();
2800 unsigned char hex_digit
= char_to_hexdigit(c
);
2801 if (hex_digit
> 0x0F) {
2802 TTCN_error_begin("The argument of function str2hex() shall contain "
2803 "only hexadecimal digits, but the given charstring element "
2804 "contains the character `");
2805 TTCN_Logger::log_char_escaped(c
);
2806 TTCN_Logger::log_event_str("'.");
2809 return HEXSTRING(1, &hex_digit
);
2814 CHARSTRING
float2str(double value
)
2816 bool f
= value
== 0.0
2817 || (value
> -MAX_DECIMAL_FLOAT
&& value
<= -MIN_DECIMAL_FLOAT
)
2818 || (value
>= MIN_DECIMAL_FLOAT
&& value
< MAX_DECIMAL_FLOAT
);
2819 // true if decimal representation possible (use %f format)
2821 int str_len
= snprintf(str_buf
, sizeof(str_buf
), f
? "%f" : "%e", value
);
2822 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
2823 TTCN_error("Internal error: system call snprintf() returned "
2824 "unexpected status code %d when converting value %g in function "
2825 "float2str().", str_len
, value
);
2827 return CHARSTRING(str_len
, str_buf
);
2830 CHARSTRING
float2str(const FLOAT
& value
)
2832 value
.must_bound("The argument of function float2str() is an unbound "
2834 return float2str((double)value
);
2839 CHARSTRING
unichar2char(const UNIVERSAL_CHARSTRING
& value
)
2841 value
.must_bound("The argument of function unichar2char() is an unbound "
2842 "universal charstring value.");
2843 int value_length
= value
.lengthof();
2844 const universal_char
*uchars_ptr
= value
;
2845 CHARSTRING
ret_val(value_length
);
2846 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
2847 for (int i
= 0; i
< value_length
; i
++) {
2848 const universal_char
& uchar
= uchars_ptr
[i
];
2849 if (uchar
.uc_group
!= 0 || uchar
.uc_plane
!= 0 || uchar
.uc_row
!= 0 ||
2850 uchar
.uc_cell
> 127) {
2851 TTCN_error("The characters in the argument of function "
2852 "unichar2char() shall be within the range char(0, 0, 0, 0) .. "
2853 "char(0, 0, 0, 127), but quadruple char(%u, %u, %u, %u) was "
2854 "found at index %d.", uchar
.uc_group
, uchar
.uc_plane
,
2855 uchar
.uc_row
, uchar
.uc_cell
, i
);
2857 chars_ptr
[i
] = uchar
.uc_cell
;
2862 CHARSTRING
unichar2char(const UNIVERSAL_CHARSTRING_ELEMENT
& value
)
2864 value
.must_bound("The argument of function unichar2char() is an unbound "
2865 "universal charstring element.");
2866 const universal_char
& uchar
= value
.get_uchar();
2867 if (uchar
.uc_group
!= 0 || uchar
.uc_plane
!= 0 || uchar
.uc_row
!= 0 ||
2868 uchar
.uc_cell
> 127) {
2869 TTCN_error("The characters in the argument of function unichar2char() "
2870 "shall be within the range char(0, 0, 0, 0) .. char(0, 0, 0, 127), "
2871 "but the given universal charstring element contains the quadruple "
2872 "char(%u, %u, %u, %u).", uchar
.uc_group
, uchar
.uc_plane
,
2873 uchar
.uc_row
, uchar
.uc_cell
);
2875 return CHARSTRING((char)uchar
.uc_cell
);
2878 OCTETSTRING
unichar2oct(const UNIVERSAL_CHARSTRING
& invalue
, const CHARSTRING
& string_encoding
)
2880 invalue
.must_bound("The argument of function unichar2oct() is an unbound "
2881 "universal charstring value.");
2882 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
2883 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
2885 if ("UTF-8" == string_encoding
) {
2886 invalue
.encode_utf8(buf
, false);
2888 else if ("UTF-8 BOM" == string_encoding
) {
2889 invalue
.encode_utf8(buf
, true);
2891 else if ("UTF-16" == string_encoding
) {
2892 invalue
.encode_utf16(buf
, CharCoding::UTF16
);
2894 else if ("UTF-16BE" == string_encoding
) {
2895 invalue
.encode_utf16(buf
, CharCoding::UTF16BE
);
2897 else if ("UTF-16LE" == string_encoding
) {
2898 invalue
.encode_utf16(buf
, CharCoding::UTF16LE
);
2900 else if ("UTF-32" == string_encoding
) {
2901 invalue
.encode_utf32(buf
, CharCoding::UTF32
);
2903 else if ("UTF-32BE" == string_encoding
) {
2904 invalue
.encode_utf32(buf
, CharCoding::UTF32BE
);
2905 } else if ("UTF-32LE" == string_encoding
) {
2906 invalue
.encode_utf32(buf
, CharCoding::UTF32LE
);
2909 TTCN_error("unichar2oct: Invalid parameter: %s", (const char*)string_encoding
);
2911 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
2912 return OCTETSTRING (buf
.get_len(), buf
.get_data());
2915 OCTETSTRING
unichar2oct(const UNIVERSAL_CHARSTRING
& invalue
)
2917 // no encoding parameter is default UTF-8
2918 invalue
.must_bound("The argument of function unichar2oct() is an unbound "
2919 "universal charstring value.");
2920 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
2921 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
2923 invalue
.encode_utf8(buf
, false);
2924 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
2925 return OCTETSTRING (buf
.get_len(), buf
.get_data());
2928 CHARSTRING
get_stringencoding(const OCTETSTRING
& encoded_value
)
2930 if (!encoded_value
.lengthof()) return CHARSTRING("<unknown>");
2931 unsigned int i
, j
, length
= encoded_value
.lengthof();
2932 const unsigned char* strptr
= (const unsigned char*)encoded_value
;
2933 for (i
= 0, j
= 0; UTF8_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF8_BOM
););
2934 if (i
== sizeof (UTF8_BOM
) && sizeof(UTF8_BOM
) <= length
) return "UTF-8";
2935 //UTF-32 shall be tested before UTF-16 !!!
2936 for (i
= 0, j
= 0; UTF32BE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF32BE_BOM
););
2937 if (i
== sizeof (UTF32BE_BOM
) && sizeof (UTF32BE_BOM
) <= length
) return "UTF-32BE";
2938 for (i
= 0, j
= 0; UTF32LE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF32LE_BOM
););
2939 if (i
== sizeof (UTF32LE_BOM
) && sizeof (UTF32LE_BOM
) <= length
) return "UTF-32LE";
2940 //UTF-32 shall be tested before UTF-16 !!!
2941 for (i
= 0, j
= 0; UTF16BE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF16BE_BOM
););
2942 if (i
== sizeof (UTF16BE_BOM
) && sizeof (UTF16BE_BOM
) <= length
) return "UTF-16BE";
2943 for (i
= 0, j
= 0; UTF16LE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF16LE_BOM
););
2944 if (i
== sizeof (UTF16LE_BOM
) && sizeof (UTF16LE_BOM
) <= length
) return "UTF-16LE";
2945 if (is_ascii (encoded_value
) == CharCoding::ASCII
) {
2948 else if (CharCoding::UTF_8
== is_utf8 (encoded_value
)) {
2955 // for internal purposes:
2956 // to obtain the name of the port when port array references are used
2957 // in connect/map/disconnect/unmap operations
2959 CHARSTRING
get_port_name(const char *port_name
, int array_index
)
2961 char *result_str
= mprintf("%s[%d]", port_name
, array_index
);
2962 CHARSTRING
ret_val(mstrlen(result_str
), result_str
);
2967 CHARSTRING
get_port_name(const char *port_name
, const INTEGER
& array_index
)
2969 array_index
.must_bound("Using an unbound integer value for indexing an "
2971 return get_port_name(port_name
, (int)array_index
);
2974 CHARSTRING
get_port_name(const CHARSTRING
& port_name
, int array_index
)
2976 port_name
.must_bound("Internal error: Using an unbound charstring value "
2977 "to obtain the name of a port.");
2978 return get_port_name((const char*)port_name
, array_index
);
2981 CHARSTRING
get_port_name(const CHARSTRING
& port_name
,
2982 const INTEGER
& array_index
)
2984 port_name
.must_bound("Internal error: Using an unbound charstring value "
2985 "to obtain the name of a port.");
2986 array_index
.must_bound("Using an unbound integer value for indexing an "
2988 return get_port_name((const char*)port_name
, (int)array_index
);
2991 OCTETSTRING
remove_bom(const OCTETSTRING
& encoded_value
)
2993 const unsigned char* str
= (const unsigned char*)encoded_value
;
2994 int length_of_BOM
= 0;
2995 if (0x00 == str
[0] && 0x00 == str
[1] && 0xFE == str
[2] && 0xFF == str
[3]) { // UTF-32BE
2998 else if (0xFF == str
[0] && 0xFE == str
[1] && 0x00 == str
[2] && 0x00 == str
[3]) { // UTF-32LE
3001 else if (0xFE == str
[0] && 0xFF == str
[1]) { // UTF-16BE
3004 else if (0xFF == str
[0] && 0xFE == str
[1]) { // UTF-16LE
3007 else if (0xEF == str
[0] && 0xBB == str
[1] && 0xBF == str
[2]) { // UTF-8
3011 return OCTETSTRING (encoded_value
); // no BOM found
3013 return OCTETSTRING (encoded_value
.lengthof() - length_of_BOM
, (str
+ length_of_BOM
));
3016 CHARSTRING
encode_base64(const OCTETSTRING
& msg
)
3018 const char *code_table
= {
3024 const char pad
= '=';
3025 const unsigned char *p_msg
= (const unsigned char *)msg
;
3026 int octets_left
= msg
.lengthof();
3027 char *output
= (char*)Malloc(((octets_left
*22)>>4) + 7);
3028 char *p_output
= output
;
3029 while(octets_left
>= 3) {
3030 *p_output
++ = code_table
[p_msg
[0] >> 2];
3031 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3032 *p_output
++ = code_table
[((p_msg
[1] << 2) | (p_msg
[2] >> 6)) & 0x3f];
3033 *p_output
++ = code_table
[p_msg
[2] & 0x3f];
3037 switch(octets_left
) {
3039 *p_output
++ = code_table
[p_msg
[0] >> 2];
3040 *p_output
++ = code_table
[(p_msg
[0] << 4) & 0x3f];
3045 *p_output
++ = code_table
[p_msg
[0] >> 2];
3046 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3047 *p_output
++ = code_table
[(p_msg
[1] << 2) & 0x3f];
3054 CHARSTRING
ret_val(output
);
3059 CHARSTRING
encode_base64(const OCTETSTRING
& msg
, bool use_linebreaks
)
3061 const char *code_table
= {
3067 const char pad
= '=';
3068 const unsigned char *p_msg
= (const unsigned char *)msg
;
3069 int octets_left
= msg
.lengthof();
3070 char *output
= (char*)Malloc(((octets_left
*22)>>4) + 7);
3071 char *p_output
= output
;
3073 while(octets_left
>= 3) {
3074 *p_output
++ = code_table
[p_msg
[0] >> 2];
3075 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3076 *p_output
++ = code_table
[((p_msg
[1] << 2) | (p_msg
[2] >> 6)) & 0x3f];
3077 *p_output
++ = code_table
[p_msg
[2] & 0x3f];
3079 if (use_linebreaks
&& n_4chars
>=19 && octets_left
!= 3) {
3087 switch(octets_left
) {
3089 *p_output
++ = code_table
[p_msg
[0] >> 2];
3090 *p_output
++ = code_table
[(p_msg
[0] << 4) & 0x3f];
3095 *p_output
++ = code_table
[p_msg
[0] >> 2];
3096 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3097 *p_output
++ = code_table
[(p_msg
[1] << 2) & 0x3f];
3104 CHARSTRING
ret_val(output
);
3110 OCTETSTRING
decode_base64(const CHARSTRING
& b64
)
3112 const unsigned char decode_table
[] = {
3113 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3114 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3115 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 62, 80, 80, 80, 63,
3116 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 80, 80, 80, 70, 80, 80,
3117 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
3118 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 80, 80, 80, 80, 80,
3119 80, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
3120 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 80, 80, 80, 80, 80
3122 const unsigned char *p_b64
= (const unsigned char *) ((const char *)b64
);
3123 int chars_left
= b64
.lengthof();
3124 unsigned char *output
= (unsigned char*)Malloc(((chars_left
>> 2) + 1) * 3);
3125 unsigned char *p_output
= output
;
3126 unsigned int bits
= 0;
3128 while(chars_left
--) {
3130 if (*p_b64
> 0 && (dec
= decode_table
[*p_b64
]) < 64) {
3135 *p_output
++ = (bits
>> (n_bits
- 8)) & 0xff;
3139 else if (*p_b64
== '=') {
3143 if (*p_b64
== '\r' && *(p_b64
+ 1) == '\n') {
3144 ++p_b64
; // skip \n too
3147 TTCN_error("Error: Invalid character in Base64 encoded data: 0x%02X", *p_b64
);
3152 OCTETSTRING
ret_val(p_output
- output
, output
);