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 unsigned char* tmp
= (unsigned char*)Malloc(bytes
* sizeof(unsigned char));
465 BN_bn2bin(value_tmp
, tmp
);
466 for (int i
= length
- 1; i
>= 0; i
--) {
467 if (bytes
-length
+i
>= 0) {
468 octets_ptr
[i
] = tmp
[bytes
-length
+i
] & 0xff;
470 else { // we used up all of the bignum; zero the beginning and quit
471 memset(octets_ptr
, 0, i
+1);
482 OCTETSTRING
int2oct(const INTEGER
& value
, const INTEGER
& length
)
484 value
.must_bound("The first argument (value) of function int2oct() is an "
485 "unbound integer value.");
486 length
.must_bound("The second argument (length) of function int2oct() is "
487 "an unbound integer value.");
488 const int_val_t
& value_int
= value
.get_val();
489 if (value_int
.is_native()) return int2oct(value_int
.get_val(), (int)length
);
490 return int2oct(value
, (int)length
);
495 CHARSTRING
int2str(int value
)
498 int str_len
= snprintf(str_buf
, sizeof(str_buf
), "%d", value
);
499 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
500 TTCN_error("Internal error: system call snprintf() returned "
501 "unexpected status code %d when converting value %d in function "
502 "int2str().", str_len
, value
);
504 return CHARSTRING(str_len
, str_buf
);
507 CHARSTRING
int2str(const INTEGER
& value
)
509 value
.must_bound("The argument of function int2str() is an unbound "
511 char *value_tmp
= value
.get_val().as_string();
512 CHARSTRING
value_str(value_tmp
);
519 double int2float(int value
)
521 return (double)value
;
524 double int2float(const INTEGER
& value
)
526 value
.must_bound("The argument of function int2float() is an unbound "
528 return value
.get_val().to_real();
533 INTEGER
float2int(double value
)
535 if (value
>= (double)INT_MIN
&& value
<= (double)INT_MAX
) return (int)value
;
536 // DBL_MAX has 316 digits including the trailing 0-s on x86_64.
538 snprintf(buf
, 511, "%f", value
);
539 char *dot
= strchr(buf
, '.');
540 if (!dot
) TTCN_error("Conversion of float value `%f' to integer failed", value
);
541 else memset(dot
, 0, sizeof(buf
) - (dot
- buf
));
545 INTEGER
float2int(const FLOAT
& value
)
547 value
.must_bound("The argument of function float2int() is an unbound float "
549 return float2int((double)value
);
554 int char2int(char value
)
556 unsigned char uchar_value
= value
;
557 if (uchar_value
> 127) TTCN_error("The argument of function "
558 "char2int() contains a character with character code %u, which is "
559 "outside the allowed range 0 .. 127.", uchar_value
);
563 int char2int(const char *value
)
565 if (value
== NULL
) value
= "";
566 int value_length
= strlen(value
);
567 if (value_length
!= 1) TTCN_error("The length of the argument in function "
568 "char2int() must be exactly 1 instead of %d.", value_length
);
569 return char2int(value
[0]);
572 int char2int(const CHARSTRING
& value
)
574 value
.must_bound("The argument of function char2int() is an unbound "
575 "charstring value.");
576 int value_length
= value
.lengthof();
577 if (value_length
!= 1) TTCN_error("The length of the argument in function "
578 "char2int() must be exactly 1 instead of %d.", value_length
);
579 return char2int(((const char*)value
)[0]);
582 int char2int(const CHARSTRING_ELEMENT
& value
)
584 value
.must_bound("The argument of function char2int() is an unbound "
585 "charstring element.");
586 return char2int(value
.get_char());
591 OCTETSTRING
char2oct(const char *value
)
593 if (value
== NULL
) return OCTETSTRING(0, NULL
);
594 else return OCTETSTRING(strlen(value
), (const unsigned char*)value
);
597 OCTETSTRING
char2oct(const CHARSTRING
& value
)
599 value
.must_bound("The argument of function char2oct() is an unbound "
600 "charstring value.");
601 return OCTETSTRING(value
.lengthof(),
602 (const unsigned char*)(const char*)value
);
605 OCTETSTRING
char2oct(const CHARSTRING_ELEMENT
& value
)
607 value
.must_bound("The argument of function char2oct() is an unbound "
608 "charstring element.");
609 unsigned char octet
= value
.get_char();
610 return OCTETSTRING(1, &octet
);
613 // C.11 - unichar2int
615 int unichar2int(const universal_char
& value
)
617 if (value
.uc_group
> 127) TTCN_error("The argument of function "
618 "unichar2int() is the invalid quadruple char(%u, %u, %u, %u), the "
619 "first number of which is outside the allowed range 0 .. 127.",
620 value
.uc_group
, value
.uc_plane
, value
.uc_row
, value
.uc_cell
);
621 int result
= (value
.uc_group
<< 24) | (value
.uc_plane
<< 16) |
622 (value
.uc_row
<< 8) | value
.uc_cell
;
626 int unichar2int(const UNIVERSAL_CHARSTRING
& value
)
628 value
.must_bound("The argument of function unichar2int() is an unbound "
629 "universal charstring value.");
630 int value_length
= value
.lengthof();
631 if (value_length
!= 1) TTCN_error("The length of the argument in function "
632 "unichar2int() must be exactly 1 instead of %d.", value_length
);
633 return unichar2int(((const universal_char
*)value
)[0]);
636 int unichar2int(const UNIVERSAL_CHARSTRING_ELEMENT
& value
)
638 value
.must_bound("The argument of function unichar2int() is an unbound "
639 "universal charstring element.");
640 return unichar2int(value
.get_uchar());
645 INTEGER
bit2int(const BITSTRING
& value
)
647 value
.must_bound("The argument of function bit2int() is an unbound "
649 int n_bits
= value
.lengthof();
650 const unsigned char *bit_ptr
= (const unsigned char *)value
;
651 // skip the leading zero bits
653 for (start_index
= 0; start_index
< n_bits
; start_index
++)
654 if (bit_ptr
[start_index
/ 8] & (1 << (start_index
% 8))) break;
656 int_val_t
ret_val((RInt
)0);
657 for (int i
= start_index
; i
< n_bits
; i
++) {
659 if (bit_ptr
[i
/ 8] & (1 << (i
% 8))) ret_val
+= 1;
661 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
662 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
665 INTEGER
bit2int(const BITSTRING_ELEMENT
& value
)
667 value
.must_bound("The argument of function bit2int() is an unbound "
668 "bitstring element.");
669 return INTEGER(value
.get_bit() ? 1 : 0);
674 HEXSTRING
bit2hex(const BITSTRING
& value
)
676 value
.must_bound("The argument of function bit2hex() is an unbound "
678 int n_bits
= value
.lengthof();
679 int n_nibbles
= (n_bits
+ 3) / 4;
680 int padding_bits
= 4 * n_nibbles
- n_bits
;
681 const unsigned char *bits_ptr
= (const unsigned char *)value
;
682 HEXSTRING
ret_val(n_nibbles
);
683 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
684 memset(nibbles_ptr
, '\0', (n_nibbles
+ 1) / 2);
685 for (int i
= 0; i
< n_bits
; i
++) {
686 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) {
687 nibbles_ptr
[(i
+ padding_bits
) / 8] |= 0x80 >>
688 ((i
+ padding_bits
+ 4) % 8);
694 HEXSTRING
bit2hex(const BITSTRING_ELEMENT
& value
)
696 value
.must_bound("The argument of function bit2hex() is an unbound "
697 "bitstring element.");
698 unsigned char nibble
= value
.get_bit() ? 0x01 : 0x00;
699 return HEXSTRING(1, &nibble
);
704 OCTETSTRING
bit2oct(const BITSTRING
& value
)
706 value
.must_bound("The argument of function bit2oct() is an unbound "
708 int n_bits
= value
.lengthof();
709 int n_octets
= (n_bits
+ 7) / 8;
710 int padding_bits
= 8 * n_octets
- n_bits
;
711 const unsigned char *bits_ptr
= (const unsigned char *)value
;
712 OCTETSTRING
ret_val(n_octets
);
713 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
714 memset(octets_ptr
, '\0', n_octets
);
715 for (int i
= 0; i
< n_bits
; i
++) {
716 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) {
717 octets_ptr
[(i
+ padding_bits
) / 8] |= 0x80 >>
718 ((i
+ padding_bits
) % 8);
724 OCTETSTRING
bit2oct(const BITSTRING_ELEMENT
& value
)
726 value
.must_bound("The argument of function bit2oct() is an unbound "
727 "bitstring element.");
728 unsigned char octet
= value
.get_bit() ? 0x01 : 0x00;
729 return OCTETSTRING(1, &octet
);
734 CHARSTRING
bit2str(const BITSTRING
& value
)
736 value
.must_bound("The argument of function bit2str() is an unbound "
738 int n_bits
= value
.lengthof();
739 const unsigned char *bits_ptr
= (const unsigned char*)value
;
740 CHARSTRING
ret_val(n_bits
);
741 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
742 for (int i
= 0; i
< n_bits
; i
++) {
743 if (bits_ptr
[i
/ 8] & (1 << (i
% 8))) chars_ptr
[i
] = '1';
744 else chars_ptr
[i
] = '0';
749 CHARSTRING
bit2str(const BITSTRING_ELEMENT
& value
)
751 value
.must_bound("The argument of function bit2str() is an unbound "
752 "bitstring element.");
753 return CHARSTRING(value
.get_bit() ? '1' : '0');
758 INTEGER
hex2int(const HEXSTRING
& value
)
760 value
.must_bound("The argument of function hex2int() is an unbound "
762 int n_nibbles
= value
.lengthof();
763 const unsigned char *nibble_ptr
= (const unsigned char *)value
;
764 // skip the leading zero hex digits
766 for (start_index
= 0; start_index
< n_nibbles
; start_index
++) {
767 unsigned char mask
= start_index
% 2 ? 0xF0 : 0x0F;
768 if (nibble_ptr
[start_index
/ 2] & mask
) break;
771 int_val_t
ret_val((RInt
)0);
772 for (int i
= start_index
; i
< n_nibbles
; i
++) {
774 if (i
% 2) ret_val
+= nibble_ptr
[i
/ 2] >> 4;
775 else ret_val
+= nibble_ptr
[i
/ 2] & 0x0F;
777 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
778 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
781 INTEGER
hex2int(const HEXSTRING_ELEMENT
& value
)
783 value
.must_bound("The argument of function hex2int() is an unbound "
784 "hexstring element.");
785 return INTEGER(value
.get_nibble());
790 BITSTRING
hex2bit(const HEXSTRING
& value
)
792 value
.must_bound("The argument of function hex2bit() is an unbound "
794 int n_nibbles
= value
.lengthof();
795 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
796 BITSTRING
ret_val(4 * n_nibbles
);
797 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
798 int n_octets
= (n_nibbles
+ 1) / 2;
799 for (int i
= 0; i
< n_octets
; i
++) {
800 bits_ptr
[i
] = nibble_reverse_table
[nibbles_ptr
[i
]];
802 ret_val
.clear_unused_bits();
806 BITSTRING
hex2bit(const HEXSTRING_ELEMENT
& value
)
808 value
.must_bound("The argument of function hex2bit() is an unbound "
809 "hexstring element.");
810 unsigned char bits
= nibble_reverse_table
[value
.get_nibble()];
811 return BITSTRING(4, &bits
);
816 OCTETSTRING
hex2oct(const HEXSTRING
& value
)
818 value
.must_bound("The argument of function hex2oct() is an unbound "
820 int n_nibbles
= value
.lengthof();
821 int n_octets
= (n_nibbles
+ 1) / 2;
822 int padding_nibbles
= n_nibbles
% 2;
823 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
824 OCTETSTRING
ret_val(n_octets
);
825 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
826 if (padding_nibbles
> 0) octets_ptr
[0] = 0;
827 for (int i
= 0; i
< n_nibbles
; i
++) {
828 unsigned char hexdigit
;
829 if (i
% 2) hexdigit
= nibbles_ptr
[i
/ 2] >> 4;
830 else hexdigit
= nibbles_ptr
[i
/ 2] & 0x0F;
831 if ((i
+ padding_nibbles
) % 2)
832 octets_ptr
[(i
+ padding_nibbles
) / 2] |= hexdigit
;
833 else octets_ptr
[(i
+ padding_nibbles
) / 2] = hexdigit
<< 4;
838 OCTETSTRING
hex2oct(const HEXSTRING_ELEMENT
& value
)
840 value
.must_bound("The argument of function hex2oct() is an unbound "
841 "hexstring element.");
842 unsigned char octet
= value
.get_nibble();
843 return OCTETSTRING(1, &octet
);
848 CHARSTRING
hex2str(const HEXSTRING
& value
)
850 value
.must_bound("The argument of function hex2str() is an unbound "
852 int n_nibbles
= value
.lengthof();
853 const unsigned char *nibbles_ptr
= (const unsigned char *)value
;
854 CHARSTRING
ret_val(n_nibbles
);
855 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
856 for (int i
= 0; i
< n_nibbles
; i
++) {
857 unsigned char hexdigit
;
858 if (i
% 2) hexdigit
= nibbles_ptr
[i
/ 2] >> 4;
859 else hexdigit
= nibbles_ptr
[i
/ 2] & 0x0F;
860 chars_ptr
[i
] = hexdigit_to_char(hexdigit
);
865 CHARSTRING
hex2str(const HEXSTRING_ELEMENT
& value
)
867 value
.must_bound("The argument of function hex2str() is an unbound "
868 "hexstring element.");
869 return CHARSTRING(hexdigit_to_char(value
.get_nibble()));
874 INTEGER
oct2int(const OCTETSTRING
& value
)
876 value
.must_bound("The argument of function oct2int() is an unbound "
877 "octetstring value.");
878 int n_octets
= value
.lengthof();
879 const unsigned char *octet_ptr
= (const unsigned char *)value
;
881 for (start_index
= 0; start_index
< n_octets
; start_index
++)
882 if (octet_ptr
[start_index
]) break;
883 int_val_t
ret_val((RInt
)0);
884 for (int i
= start_index
; i
< n_octets
; i
++) {
886 ret_val
+= octet_ptr
[i
];
888 if (ret_val
.is_native()) return INTEGER(ret_val
.get_val());
889 else return INTEGER(BN_dup(ret_val
.get_val_openssl()));
892 INTEGER
oct2int(const OCTETSTRING_ELEMENT
& value
)
894 value
.must_bound("The argument of function oct2int() is an unbound "
895 "octetstring element.");
896 return INTEGER(value
.get_octet());
901 BITSTRING
oct2bit(const OCTETSTRING
& value
)
903 value
.must_bound("The argument of function oct2bit() is an unbound "
904 "octetstring value.");
905 int n_octets
= value
.lengthof();
906 const unsigned char *octets_ptr
= (const unsigned char *)value
;
907 BITSTRING
ret_val(8 * n_octets
);
908 unsigned char *bits_ptr
= ret_val
.val_ptr
->bits_ptr
;
909 for (int i
= 0; i
< n_octets
; i
++) {
910 bits_ptr
[i
] = bit_reverse_table
[octets_ptr
[i
]];
915 BITSTRING
oct2bit(const OCTETSTRING_ELEMENT
& value
)
917 value
.must_bound("The argument of function oct2bit() is an unbound "
918 "octetstring element.");
919 unsigned char bits
= bit_reverse_table
[value
.get_octet()];
920 return BITSTRING(8, &bits
);
925 HEXSTRING
oct2hex(const OCTETSTRING
& value
)
927 value
.must_bound("The argument of function oct2hex() is an unbound "
928 "octetstring value.");
929 int n_octets
= value
.lengthof();
930 const unsigned char *octets_ptr
= (const unsigned char *)value
;
931 HEXSTRING
ret_val(2 * n_octets
);
932 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
933 for (int i
= 0; i
< n_octets
; i
++) {
934 nibbles_ptr
[i
] = nibble_swap_table
[octets_ptr
[i
]];
939 HEXSTRING
oct2hex(const OCTETSTRING_ELEMENT
& value
)
941 value
.must_bound("The argument of function oct2hex() is an unbound "
942 "octetstring element.");
943 unsigned char nibbles
= nibble_swap_table
[value
.get_octet()];
944 return HEXSTRING(2, &nibbles
);
949 CHARSTRING
oct2str(const OCTETSTRING
& value
)
951 value
.must_bound("The argument of function oct2str() is an unbound "
952 "octetstring value.");
953 int n_octets
= value
.lengthof();
954 const unsigned char *octets_ptr
= (const unsigned char *)value
;
955 CHARSTRING
ret_val(2 * n_octets
);
956 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
957 for (int i
= 0; i
< n_octets
; i
++) {
958 chars_ptr
[2 * i
] = hexdigit_to_char(octets_ptr
[i
] >> 4);
959 chars_ptr
[2 * i
+ 1] = hexdigit_to_char(octets_ptr
[i
] & 0x0F);
964 CHARSTRING
oct2str(const OCTETSTRING_ELEMENT
& value
)
966 value
.must_bound("The argument of function oct2str() is an unbound "
967 "octetstring element.");
968 unsigned char octet
= value
.get_octet();
970 result
[0] = hexdigit_to_char(octet
>> 4);
971 result
[1] = hexdigit_to_char(octet
& 0x0F);
972 return CHARSTRING(2, result
);
977 CHARSTRING
oct2char(const OCTETSTRING
& value
)
979 value
.must_bound("The argument of function oct2char() is an unbound "
980 "octetstring value.");
981 int value_length
= value
.lengthof();
982 const unsigned char *octets_ptr
= (const unsigned char*)value
;
983 for (int i
= 0; i
< value_length
; i
++) {
984 unsigned char octet
= octets_ptr
[i
];
985 if (octet
> 127) TTCN_error("The argument of function oct2char() "
986 "contains octet %02X at index %d, which is outside the allowed "
987 "range 00 .. 7F.", octet
, i
);
989 return CHARSTRING(value_length
, (const char*)octets_ptr
);
992 CHARSTRING
oct2char(const OCTETSTRING_ELEMENT
& value
)
994 value
.must_bound("The argument of function oct2char() is an unbound "
995 "octetstring element.");
996 unsigned char octet
= value
.get_octet();
997 if (octet
> 127) TTCN_error("The argument of function oct2char() "
998 "contains the octet %02X, which is outside the allowed range 00 .. 7F.",
1000 return CHARSTRING((char)octet
);
1003 UNIVERSAL_CHARSTRING
oct2unichar(const OCTETSTRING
& invalue
)
1005 // default encoding is UTF-8
1006 UNIVERSAL_CHARSTRING ucstr
;
1007 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
1008 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
1009 ucstr
.decode_utf8(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF_8
, true);
1010 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
1014 UNIVERSAL_CHARSTRING
oct2unichar(const OCTETSTRING
& invalue
,
1015 const CHARSTRING
& string_encoding
)
1017 UNIVERSAL_CHARSTRING ucstr
;
1018 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
1019 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
1020 if ("UTF-8" == string_encoding
) {
1021 ucstr
.decode_utf8(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF_8
, true);
1023 else if ("UTF-16" == string_encoding
) {
1024 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16
);
1026 else if ("UTF-16BE" == string_encoding
) {
1027 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16BE
);
1029 else if ("UTF-16LE" == string_encoding
) {
1030 ucstr
.decode_utf16(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF16LE
);
1032 else if ("UTF-32" == string_encoding
) {
1033 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32
);
1035 else if ("UTF-32BE" == string_encoding
) {
1036 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32BE
);
1038 else if ("UTF-32LE" == string_encoding
) {
1039 ucstr
.decode_utf32(invalue
.lengthof(), (const unsigned char *)invalue
, CharCoding::UTF32LE
);
1041 else { TTCN_error("oct2unichar: Invalid parameter: %s", (const char*)string_encoding
);
1043 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
1049 INTEGER
str2int(const char *value
)
1051 return str2int(CHARSTRING(value
));
1054 INTEGER
str2int(const CHARSTRING
& value
)
1056 value
.must_bound("The argument of function str2int() is an unbound "
1057 "charstring value.");
1058 int value_len
= value
.lengthof();
1059 if (value_len
== 0) TTCN_error("The argument of function str2int() is an "
1060 "empty string, which does not represent a valid integer value.");
1061 const char *value_str
= value
;
1062 enum { S_INITIAL
, S_FIRST
, S_ZERO
, S_MORE
, S_END
, S_ERR
} state
= S_INITIAL
;
1063 // state: expected characters
1064 // S_INITIAL: +, -, first digit, leading whitespace
1065 // S_FIRST: first digit
1066 // S_ZERO, S_MORE: more digit(s), trailing whitespace
1067 // S_END: trailing whitespace
1068 // S_ERR: error was found, stop
1069 boolean leading_ws
= FALSE
, leading_zero
= FALSE
;
1070 for (int i
= 0; i
< value_len
; i
++) {
1071 char c
= value_str
[i
];
1074 if (c
== '+' || c
== '-') state
= S_FIRST
;
1075 else if (c
== '0') state
= S_ZERO
;
1076 else if (c
>= '1' && c
<= '9') state
= S_MORE
;
1077 else if (is_whitespace(c
)) leading_ws
= TRUE
;
1081 if (c
== '0') state
= S_ZERO
;
1082 else if (c
>= '1' && c
<= '9') state
= S_MORE
;
1086 if (c
>= '0' && c
<= '9') {
1087 leading_zero
= TRUE
;
1089 } else if (is_whitespace(c
)) state
= S_END
;
1093 if (c
>= '0' && c
<= '9') {}
1094 else if (is_whitespace(c
)) state
= S_END
;
1098 if (!is_whitespace(c
)) state
= S_ERR
;
1103 if (state
== S_ERR
) {
1104 TTCN_error_begin("The argument of function str2int(), which is ");
1106 TTCN_Logger::log_event_str(", does not represent a valid integer "
1107 "value. Invalid character `");
1108 TTCN_Logger::log_char_escaped(c
);
1109 TTCN_Logger::log_event("' was found at index %d.", i
);
1113 if (state
!= S_ZERO
&& state
!= S_MORE
&& state
!= S_END
) {
1114 TTCN_error_begin("The argument of function str2int(), which is ");
1116 TTCN_Logger::log_event_str(", does not represent a valid integer "
1117 "value. Premature end of the string.");
1121 TTCN_warning_begin("Leading whitespace was detected in the argument "
1122 "of function str2int(): ");
1124 TTCN_Logger::log_char('.');
1128 TTCN_warning_begin("Leading zero digit was detected in the argument "
1129 "of function str2int(): ");
1131 TTCN_Logger::log_char('.');
1134 if (state
== S_END
) {
1135 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1136 "of function str2int(): ");
1138 TTCN_Logger::log_char('.');
1141 return INTEGER(value_str
);
1144 INTEGER
str2int(const CHARSTRING_ELEMENT
& value
)
1146 value
.must_bound("The argument of function str2int() is an unbound "
1147 "charstring element.");
1148 char c
= value
.get_char();
1149 if (c
< '0' || c
> '9') {
1150 TTCN_error_begin("The argument of function str2int(), which is a "
1151 "charstring element containing character `");
1152 TTCN_Logger::log_char_escaped(c
);
1153 TTCN_Logger::log_event_str("', does not represent a valid integer "
1157 return INTEGER(c
- '0');
1162 OCTETSTRING
str2oct(const char *value
)
1164 if (value
== NULL
) return OCTETSTRING(0, NULL
);
1165 else return str2oct(CHARSTRING(value
));
1168 OCTETSTRING
str2oct(const CHARSTRING
& value
)
1170 value
.must_bound("The argument of function str2oct() is an unbound "
1171 "charstring value.");
1172 int value_len
= value
.lengthof();
1173 if (value_len
% 2) TTCN_error("The argument of function str2oct() must "
1174 "have even number of characters containing hexadecimal digits, but "
1175 "the length of the string is odd: %d.", value_len
);
1176 OCTETSTRING
ret_val(value_len
/ 2);
1177 unsigned char *octets_ptr
= ret_val
.val_ptr
->octets_ptr
;
1178 const char *chars_ptr
= value
;
1179 for (int i
= 0; i
< value_len
; i
++) {
1180 char c
= chars_ptr
[i
];
1181 unsigned char hex_digit
= char_to_hexdigit(c
);
1182 if (hex_digit
> 0x0F) {
1183 TTCN_error_begin("The argument of function str2oct() shall "
1184 "contain hexadecimal digits only, but character `");
1185 TTCN_Logger::log_char_escaped(c
);
1186 TTCN_Logger::log_event("' was found at index %d.", i
);
1189 if (i
% 2) octets_ptr
[i
/ 2] |= hex_digit
;
1190 else octets_ptr
[i
/ 2] = hex_digit
<< 4;
1197 double str2float(const char *value
)
1199 return str2float(CHARSTRING(value
));
1203 * leading zeros are allowed;
1204 * leading "+" sign before positive values is allowed;
1205 * "-0.0" is allowed;
1206 * no numbers after the dot in the decimal notation are allowed.
1208 double str2float(const CHARSTRING
& value
)
1210 value
.must_bound("The argument of function str2float() is an unbound "
1211 "charstring value.");
1212 int value_len
= value
.lengthof();
1213 if (value_len
== 0) TTCN_error("The argument of function str2float() is "
1214 "an empty string, which does not represent a valid float value.");
1215 const char *value_str
= value
;
1216 enum { S_INITIAL
, S_FIRST_M
, S_ZERO_M
, S_MORE_M
, S_FIRST_F
, S_MORE_F
,
1217 S_INITIAL_E
, S_FIRST_E
, S_ZERO_E
, S_MORE_E
, S_END
, S_ERR
}
1219 // state: expected characters
1220 // S_INITIAL: +, -, first digit of integer part in mantissa,
1221 // leading whitespace
1222 // S_FIRST_M: first digit of integer part in mantissa
1223 // S_ZERO_M, S_MORE_M: more digits of mantissa, decimal dot, E
1224 // S_FIRST_F: first digit of fraction
1225 // S_MORE_F: more digits of fraction, E, trailing whitespace
1226 // S_INITIAL_E: +, -, first digit of exponent
1227 // S_FIRST_E: first digit of exponent
1228 // S_ZERO_E, S_MORE_E: more digits of exponent, trailing whitespace
1229 // S_END: trailing whitespace
1230 // S_ERR: error was found, stop
1231 boolean leading_ws
= FALSE
, leading_zero
= FALSE
;
1232 for (int i
= 0; i
< value_len
; i
++) {
1233 char c
= value_str
[i
];
1236 if (c
== '+' || c
== '-') state
= S_FIRST_M
;
1237 else if (c
== '0') state
= S_ZERO_M
;
1238 else if (c
>= '1' && c
<= '9') state
= S_MORE_M
;
1239 else if (is_whitespace(c
)) leading_ws
= TRUE
;
1242 case S_FIRST_M
: // first mantissa digit
1243 if (c
== '0') state
= S_ZERO_M
;
1244 else if (c
>= '1' && c
<= '9') state
= S_MORE_M
;
1247 case S_ZERO_M
: // leading mantissa zero
1248 if (c
== '.') state
= S_FIRST_F
;
1249 else if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1250 else if (c
>= '0' && c
<= '9') {
1251 leading_zero
= TRUE
;
1253 } else state
= S_ERR
;
1256 if (c
== '.') state
= S_FIRST_F
;
1257 else if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1258 else if (c
>= '0' && c
<= '9') {}
1262 if (c
>= '0' && c
<= '9') state
= S_MORE_F
;
1266 if (c
== 'E' || c
== 'e') state
= S_INITIAL_E
;
1267 else if (c
>= '0' && c
<= '9') {}
1268 else if (is_whitespace(c
)) state
= S_END
;
1272 if (c
== '+' || c
== '-') state
= S_FIRST_E
;
1273 else if (c
== '0') state
= S_ZERO_E
;
1274 else if (c
>= '1' && c
<= '9') state
= S_MORE_E
;
1278 if (c
== '0') state
= S_ZERO_E
;
1279 else if (c
>= '1' && c
<= '9') state
= S_MORE_E
;
1283 if (c
>= '0' && c
<= '9') {
1284 leading_zero
= TRUE
;
1286 } else if (is_whitespace(c
)) state
= S_END
;
1290 if (c
>= '0' && c
<= '9') {}
1291 else if (is_whitespace(c
)) state
= S_END
;
1295 if (!is_whitespace(c
)) state
= S_ERR
;
1300 if (state
== S_ERR
) {
1301 TTCN_error_begin("The argument of function str2float(), which is ");
1303 TTCN_Logger::log_event_str(", does not represent a valid float "
1304 "value. Invalid character `");
1305 TTCN_Logger::log_char_escaped(c
);
1306 TTCN_Logger::log_event("' was found at index %d.", i
);
1318 // OK now (decimal dot missing after mantissa)
1321 // OK now (fraction part missing)
1324 TTCN_error_begin("The argument of function str2float(), which is ");
1326 TTCN_Logger::log_event_str(", does not represent a valid float value. "
1327 "Premature end of the string.");
1332 TTCN_warning_begin("Leading whitespace was detected in the argument "
1333 "of function str2float(): ");
1335 TTCN_Logger::log_char('.');
1339 TTCN_warning_begin("Leading zero digit was detected in the argument "
1340 "of function str2float(): ");
1342 TTCN_Logger::log_char('.');
1345 if (state
== S_END
) {
1346 TTCN_warning_begin("Trailing whitespace was detected in the argument "
1347 "of function str2float(): ");
1349 TTCN_Logger::log_char('.');
1352 return atof(value_str
);
1357 CHARSTRING
regexp(const CHARSTRING
& instr
, const CHARSTRING
& expression
,
1360 instr
.must_bound("The first argument (instr) of function regexp() is an "
1361 "unbound charstring value.");
1362 expression
.must_bound("The second argument (expression) of function "
1363 "regexp() is an unbound charstring value.");
1364 if (groupno
< 0) TTCN_error("The third argument (groupno) of function "
1365 "regexp() is a negative integer value: %d.", groupno
);
1366 int instr_len
= instr
.lengthof();
1367 const char *instr_str
= instr
;
1368 for (int i
= 0; i
< instr_len
; i
++) {
1369 if (instr_str
[i
] == '\0') {
1370 TTCN_warning_begin("The first argument (instr) of function regexp(), "
1373 TTCN_Logger::log_event(", contains a character with zero character code "
1374 "at index %d. The rest of the string will be ignored during matching.",
1380 int expression_len
= expression
.lengthof();
1381 const char *expression_str
= expression
;
1382 for (int i
= 0; i
< expression_len
; i
++) {
1383 if (expression_str
[i
] == '\0') {
1384 TTCN_warning_begin("The second argument (expression) of function "
1385 "regexp(), which is ");
1387 TTCN_Logger::log_event(", contains a character with zero character code "
1388 "at index %d. The rest of the string will be ignored during matching.",
1394 char *posix_str
= TTCN_pattern_to_regexp(expression_str
);
1395 if (posix_str
== NULL
) {
1396 TTCN_error_begin("The second argument (expression) of function "
1397 "regexp(), which is ");
1399 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1402 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED
)) {
1403 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED
);
1404 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1405 CHARSTRING_template(STRING_PATTERN
, expression
).log();
1406 TTCN_Logger::log_event_str(" is: ");
1407 CHARSTRING(posix_str
).log();
1408 TTCN_Logger::end_event();
1410 regex_t posix_regexp
;
1411 int ret_val
= regcomp(&posix_regexp
, posix_str
, REG_EXTENDED
);
1414 char msg
[ERRMSG_BUFSIZE
];
1415 regerror(ret_val
, &posix_regexp
, msg
, sizeof(msg
));
1416 regfree(&posix_regexp
);
1417 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1418 "failed in function regexp() when trying to match with character "
1421 TTCN_Logger::log_event(". Error message: %s.", msg
);
1424 int re_nsub
= posix_regexp
.re_nsub
;
1426 regfree(&posix_regexp
);
1427 TTCN_error_begin("The character pattern in the second argument "
1428 "(expression) of function regexp() does not contain any groups: ");
1430 TTCN_Logger::log_char('.');
1433 if (groupno
>= re_nsub
) {
1434 regfree(&posix_regexp
);
1435 TTCN_error("The third argument (groupno) of function regexp() is too "
1436 "large: The requested group index is %d, but the pattern contains only "
1437 "%d group%s.", groupno
, re_nsub
, re_nsub
> 1 ? "s" : "");
1439 size_t nmatch
= groupno
+ 1;
1440 regmatch_t
*pmatch
= (regmatch_t
*)Malloc((nmatch
+ 1) * sizeof(*pmatch
));
1441 ret_val
= regexec(&posix_regexp
, instr
, nmatch
+ 1, pmatch
, 0);
1443 int begin_index
= pmatch
[nmatch
].rm_so
, end_index
= pmatch
[nmatch
].rm_eo
;
1445 regfree(&posix_regexp
);
1446 if (end_index
> instr_len
) TTCN_error("Internal error: The end index "
1447 "of the substring (%d) to be returned in function regexp() is greater "
1448 "than the length of the input string (%d).", end_index
, instr_len
);
1449 if (begin_index
> end_index
) TTCN_error("Internal error: The start index "
1450 "of the substring (%d) to be returned in function regexp() is greater "
1451 "than the end index (%d).", begin_index
, end_index
);
1452 return CHARSTRING(end_index
- begin_index
, instr_str
+ begin_index
);
1455 if (ret_val
!= REG_NOMATCH
) {
1456 char msg
[ERRMSG_BUFSIZE
];
1457 regerror(ret_val
, &posix_regexp
, msg
, ERRMSG_BUFSIZE
);
1458 regfree(&posix_regexp
);
1459 TTCN_error("Internal error: POSIX regular expression matching returned "
1460 "unexpected status code in function regexp(): %s.", msg
);
1461 } else regfree(&posix_regexp
);
1462 return CHARSTRING(0, NULL
);
1466 CHARSTRING
regexp(const CHARSTRING
& instr
, const CHARSTRING
& expression
,
1467 const INTEGER
& groupno
)
1469 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1470 "unbound integer value.");
1471 return regexp(instr
, expression
, (int)groupno
);
1474 /* Needed by regexp() */
1475 UNIVERSAL_CHARSTRING
convert_from_pattern_form(char* str
, int num
) {
1477 TTCN_error("Internal error: Cannot convert string from pattern form.");
1479 unsigned char c1
, c2
;
1480 universal_char
* const res
= new universal_char
[num
/8];
1481 unsigned char* ptr
= (unsigned char*)res
;
1483 while (index
< num
) {
1484 for (int j
= 0; j
< 4; j
++) {
1487 if (c1
>= 'A' && c1
<= 'P' && c2
>= 'A' && c2
<= 'P') {
1488 *(ptr
++) = ((c1
- 'A') << 4) | (c2
- 'A');
1490 TTCN_error("Internal error: Cannot convert string containing illegal "
1494 UNIVERSAL_CHARSTRING
retval(num
/ 8, res
);
1499 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1500 const UNIVERSAL_CHARSTRING
* expression_val
,
1501 const UNIVERSAL_CHARSTRING_template
* expression_tmpl
,
1504 if ( (expression_val
&& expression_tmpl
) ||
1505 (!expression_val
&& !expression_tmpl
) )
1506 TTCN_error("Internal error: regexp(): invalid parameters");
1507 instr
.must_bound("The first argument (instr) of function regexp() is an "
1508 "unbound charstring value.");
1510 expression_val
->must_bound("The second argument (expression) of function "
1511 "regexp() is an unbound universal charstring value.");
1513 if (!expression_tmpl
->is_bound())
1514 TTCN_error("The second argument (expression) of function "
1515 "regexp() is an unbound universal charstring template.");
1517 if (groupno
< 0) TTCN_error("The third argument (groupno) of function "
1518 "regexp() is a negative integer value: %d.", groupno
);
1520 int* user_groups
= 0;
1521 CHARSTRING expression_str
;
1523 expression_str
= expression_val
->get_stringRepr_for_pattern();
1525 expression_str
= expression_tmpl
->get_single_value();
1526 char *posix_str
= TTCN_pattern_to_regexp_uni((const char*)expression_str
,
1528 if (user_groups
== 0) {
1531 TTCN_error("Cannot find any groups in the second argument of regexp().");
1533 if (posix_str
== NULL
) {
1534 TTCN_error_begin("The second argument (expression) of function "
1535 "regexp(), which is ");
1536 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1537 TTCN_Logger::log_event(", is not a valid TTCN-3 character pattern.");
1540 if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_UNQUALIFIED
)) {
1541 TTCN_Logger::begin_event(TTCN_Logger::DEBUG_UNQUALIFIED
);
1542 TTCN_Logger::log_event_str("regexp(): POSIX ERE equivalent of ");
1543 CHARSTRING_template(STRING_PATTERN
, expression_str
).log();
1544 TTCN_Logger::log_event_str(" is: ");
1545 CHARSTRING(posix_str
).log();
1546 TTCN_Logger::end_event();
1549 regex_t posix_regexp
;
1550 int ret_val
= regcomp(&posix_regexp
, posix_str
, REG_EXTENDED
);
1553 char msg
[ERRMSG_BUFSIZE
];
1554 regerror(ret_val
, &posix_regexp
, msg
, sizeof(msg
));
1555 regfree(&posix_regexp
);
1556 TTCN_error_begin("Internal error: Compilation of POSIX regular expression "
1557 "failed in function regexp() when trying to match with character "
1559 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1560 TTCN_Logger::log_event(". Error message: %s.", msg
);
1564 int re_nsub
= user_groups
[0];
1566 if (posix_regexp
.re_nsub
<= 0) {
1567 regfree(&posix_regexp
);
1568 TTCN_error_begin("The character pattern in the second argument "
1569 "(expression) of function regexp() does not contain any groups: ");
1570 if (expression_val
) expression_val
->log(); else expression_tmpl
->log();
1571 TTCN_Logger::log_char('.');
1574 if (groupno
>= re_nsub
) {
1575 regfree(&posix_regexp
);
1576 TTCN_error("The third argument (groupno) of function regexp() is too "
1577 "large: The requested group index is %d, but the pattern contains only "
1578 "%d group%s.", groupno
, re_nsub
, re_nsub
> 1 ? "s" : "");
1580 if (groupno
> user_groups
[0]) {
1581 printf(" user_groups: %d\n", user_groups
[0]);
1582 TTCN_error("Error during parsing the pattern.");
1584 size_t nmatch
= (size_t)user_groups
[groupno
+1] + 1;
1585 regmatch_t
*pmatch
= (regmatch_t
*)Malloc((nmatch
+ 1) * sizeof(*pmatch
));
1589 char* instr_conv
= instr
.convert_to_regexp_form();
1590 int instr_len
= instr
.lengthof() * 8;
1592 ret_val
= regexec(&posix_regexp
, instr_conv
, nmatch
+ 1, pmatch
, 0);
1594 int begin_index
= pmatch
[nmatch
].rm_so
, end_index
= pmatch
[nmatch
].rm_eo
;
1596 regfree(&posix_regexp
);
1597 if (end_index
> instr_len
) TTCN_error("Internal error: The end index "
1598 "of the substring (%d) to be returned in function regexp() is greater "
1599 "than the length of the input string (%d).", end_index
, instr_len
);
1600 if (begin_index
> end_index
) TTCN_error("Internal error: The start index "
1601 "of the substring (%d) to be returned in function regexp() is greater "
1602 "than the end index (%d).", begin_index
, end_index
);
1603 UNIVERSAL_CHARSTRING res
= convert_from_pattern_form(
1604 instr_conv
+ begin_index
, end_index
- begin_index
);
1610 if (ret_val
!= REG_NOMATCH
) {
1611 char msg
[ERRMSG_BUFSIZE
];
1612 regerror(ret_val
, &posix_regexp
, msg
, ERRMSG_BUFSIZE
);
1613 regfree(&posix_regexp
);
1614 TTCN_error("Internal error: POSIX regular expression matching returned "
1615 "unexpected status code in function regexp(): %s.", msg
);
1616 } else regfree(&posix_regexp
);
1617 return UNIVERSAL_CHARSTRING(0, (const char*)NULL
);
1621 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1622 const UNIVERSAL_CHARSTRING
& expression
, int groupno
)
1624 return regexp(instr
, &expression
, NULL
, groupno
);
1627 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING
& instr
,
1628 const UNIVERSAL_CHARSTRING
& expression
, const INTEGER
& groupno
)
1630 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1631 "unbound integer value.");
1632 return regexp(instr
, expression
, (int)groupno
);
1635 // regexp() on templates
1637 CHARSTRING
regexp(const CHARSTRING_template
& instr
,
1638 const CHARSTRING_template
& expression
, int groupno
)
1640 if (!instr
.is_value())
1641 TTCN_error("The first argument of function regexp() is a "
1642 "template with non-specific value.");
1643 if (expression
.is_value())
1644 return regexp(instr
.valueof(), expression
.valueof(), groupno
);
1645 // pattern matching to specific value
1646 if (expression
.get_selection()==STRING_PATTERN
)
1647 return regexp(instr
.valueof(), expression
.get_single_value(), groupno
);
1648 TTCN_error("The second argument of function regexp() should be "
1649 "specific value or pattern matching template.");
1652 CHARSTRING
regexp(const CHARSTRING_template
& instr
,
1653 const CHARSTRING_template
& expression
, const INTEGER
& groupno
)
1655 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1656 "unbound integer value.");
1657 return regexp(instr
, expression
, (int)groupno
);
1660 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING_template
& instr
,
1661 const UNIVERSAL_CHARSTRING_template
& expression
, int groupno
)
1663 if (!instr
.is_value())
1664 TTCN_error("The first argument of function regexp() is a "
1665 "template with non-specific value.");
1666 if (expression
.is_value())
1667 return regexp(instr
.valueof(), expression
.valueof(), groupno
);
1668 // pattern matching to specific value
1669 if (expression
.get_selection()==STRING_PATTERN
)
1670 return regexp(instr
.valueof(), NULL
, &expression
, groupno
);
1671 TTCN_error("The second argument of function regexp() should be "
1672 "specific value or pattern matching template.");
1675 UNIVERSAL_CHARSTRING
regexp(const UNIVERSAL_CHARSTRING_template
& instr
,
1676 const UNIVERSAL_CHARSTRING_template
& expression
, const INTEGER
& groupno
)
1678 groupno
.must_bound("The third argument (groupno) of function regexp() is an "
1679 "unbound integer value.");
1680 return regexp(instr
, expression
, (int)groupno
);
1685 void check_substr_arguments(int value_length
, int idx
,
1686 int returncount
, const char *string_type
, const char *element_name
)
1688 if (idx
< 0) TTCN_error("The second argument (index) of function "
1689 "substr() is a negative integer value: %d.", idx
);
1690 if (idx
> value_length
) TTCN_error("The second argument (index) of "
1691 "function substr(), which is %d, is greater than the length of the "
1692 "%s value: %d.", idx
, string_type
, value_length
);
1693 if (returncount
< 0) TTCN_error("The third argument (returncount) of "
1694 "function substr() is a negative integer value: %d.", returncount
);
1695 if (idx
+ returncount
> value_length
) TTCN_error("The first argument of "
1696 "function substr(), the length of which is %d, does not have enough "
1697 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
1698 value_length
, element_name
, idx
, returncount
, element_name
,
1699 returncount
> 1 ? "s are" : " is",
1700 value_length
- idx
> 1 ? "are" : "is", value_length
- idx
);
1703 static void check_substr_arguments(int idx
, int returncount
,
1704 const char *string_type
, const char *element_name
)
1706 if (idx
< 0) TTCN_error("The second argument (index) of function "
1707 "substr() is a negative integer value: %d.", idx
);
1708 if (idx
> 1) TTCN_error("The second argument (index) of function "
1709 "substr(), which is %d, is greater than 1 (i.e. the length of the "
1710 "%s element).", idx
, string_type
);
1711 if (returncount
< 0) TTCN_error("The third argument (returncount) of "
1712 "function substr() is a negative integer value: %d.", returncount
);
1713 if (idx
+ returncount
> 1) TTCN_error("The first argument of function "
1714 "substr(), which is a%s %s element, does not have enough %ss starting "
1715 "at index %d: %d %s%s needed, but there is only %d.",
1716 string_type
[0] == 'o' ? "n" : "", string_type
, element_name
, idx
,
1717 returncount
, element_name
, returncount
> 1 ? "s are" : " is",
1721 BITSTRING
substr(const BITSTRING
& value
, int idx
, int returncount
)
1723 value
.must_bound("The first argument (value) of function substr() "
1724 "is an unbound bitstring value.");
1725 check_substr_arguments(value
.lengthof(), idx
, returncount
, "bitstring",
1728 BITSTRING
ret_val(returncount
);
1729 for (int i
= 0; i
< returncount
; i
++) {
1730 ret_val
.set_bit(i
, value
.get_bit(idx
+ i
));
1732 ret_val
.clear_unused_bits();
1735 return BITSTRING(returncount
, (const unsigned char*)value
+ idx
/ 8);
1739 BITSTRING
substr(const BITSTRING
& value
, int idx
, const INTEGER
& returncount
)
1741 returncount
.must_bound("The third argument (returncount) of function "
1742 "substr() is an unbound integer value.");
1743 return substr(value
, idx
, (int)returncount
);
1746 BITSTRING
substr(const BITSTRING
& value
, const INTEGER
& idx
, int returncount
)
1748 idx
.must_bound("The second argument (index) of function substr() "
1749 "is an unbound integer value.");
1750 return substr(value
, (int)idx
, returncount
);
1753 BITSTRING
substr(const BITSTRING
& value
, const INTEGER
& idx
,
1754 const INTEGER
& returncount
)
1756 idx
.must_bound("The second argument (index) of function substr() is an "
1757 "unbound integer value.");
1758 returncount
.must_bound("The third argument (returncount) of function "
1759 "substr() is an unbound integer value.");
1760 return substr(value
, (int)idx
, (int)returncount
);
1763 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, int idx
, int returncount
)
1765 value
.must_bound("The first argument (value) of function substr() "
1766 "is an unbound bitstring element.");
1767 check_substr_arguments(idx
, returncount
, "bitstring", "bit");
1768 if (returncount
== 0) return BITSTRING(0, NULL
);
1770 unsigned char bit
= value
.get_bit() ? 0x01 : 0x00;
1771 return BITSTRING(1, &bit
);
1775 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, int idx
,
1776 const INTEGER
& returncount
)
1778 returncount
.must_bound("The third argument (returncount) of function "
1779 "substr() is an unbound integer value.");
1780 return substr(value
, idx
, (int)returncount
);
1783 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1786 idx
.must_bound("The second argument (index) of function substr() "
1787 "is an unbound integer value.");
1788 return substr(value
, (int)idx
, returncount
);
1791 BITSTRING
substr(const BITSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1792 const INTEGER
& returncount
)
1794 idx
.must_bound("The second argument (index) of function substr() is an "
1795 "unbound integer value.");
1796 returncount
.must_bound("The third argument (returncount) of function "
1797 "substr() is an unbound integer value.");
1798 return substr(value
, (int)idx
, (int)returncount
);
1801 HEXSTRING
substr(const HEXSTRING
& value
, int idx
, int returncount
)
1803 value
.must_bound("The first argument (value) of function substr() "
1804 "is an unbound hexstring value.");
1805 check_substr_arguments(value
.lengthof(), idx
, returncount
, "hexstring",
1806 "hexadecimal digit");
1807 const unsigned char *src_ptr
= (const unsigned char*)value
;
1809 HEXSTRING
ret_val(returncount
);
1810 unsigned char *dst_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
1811 for (int i
= 0; i
< returncount
; i
++) {
1812 if (i
% 2) dst_ptr
[i
/ 2] |= (src_ptr
[(i
+ idx
) / 2] & 0x0F) << 4;
1813 else dst_ptr
[i
/ 2] = src_ptr
[(i
+ idx
) / 2] >> 4;
1816 } else return HEXSTRING(returncount
, src_ptr
+ idx
/ 2);
1819 HEXSTRING
substr(const HEXSTRING
& value
, int idx
, const INTEGER
& returncount
)
1821 returncount
.must_bound("The third argument (returncount) of function "
1822 "substr() is an unbound integer value.");
1823 return substr(value
, idx
, (int)returncount
);
1826 HEXSTRING
substr(const HEXSTRING
& value
, const INTEGER
& idx
, int returncount
)
1828 idx
.must_bound("The second argument (index) of function substr() "
1829 "is an unbound integer value.");
1830 return substr(value
, (int)idx
, returncount
);
1833 HEXSTRING
substr(const HEXSTRING
& value
, const INTEGER
& idx
,
1834 const INTEGER
& returncount
)
1836 idx
.must_bound("The second argument (index) of function substr() is an "
1837 "unbound integer value.");
1838 returncount
.must_bound("The third argument (returncount) of function "
1839 "substr() is an unbound integer value.");
1840 return substr(value
, (int)idx
, (int)returncount
);
1843 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, int idx
, int returncount
)
1845 value
.must_bound("The first argument (value) of function substr() "
1846 "is an unbound hexstring element.");
1847 check_substr_arguments(idx
, returncount
, "hexstring",
1848 "hexadecimal digit");
1849 if (returncount
== 0) return HEXSTRING(0, NULL
);
1851 unsigned char nibble
= value
.get_nibble();
1852 return HEXSTRING(1, &nibble
);
1856 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, int idx
,
1857 const INTEGER
& returncount
)
1859 returncount
.must_bound("The third argument (returncount) of function "
1860 "substr() is an unbound integer value.");
1861 return substr(value
, idx
, (int)returncount
);
1864 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1867 idx
.must_bound("The second argument (index) of function substr() "
1868 "is an unbound integer value.");
1869 return substr(value
, (int)idx
, returncount
);
1872 HEXSTRING
substr(const HEXSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1873 const INTEGER
& returncount
)
1875 idx
.must_bound("The second argument (index) of function substr() is an "
1876 "unbound integer value.");
1877 returncount
.must_bound("The third argument (returncount) of function "
1878 "substr() is an unbound integer value.");
1879 return substr(value
, (int)idx
, (int)returncount
);
1882 OCTETSTRING
substr(const OCTETSTRING
& value
, int idx
, int returncount
)
1884 value
.must_bound("The first argument (value) of function substr() "
1885 "is an unbound octetstring value.");
1886 check_substr_arguments(value
.lengthof(), idx
, returncount
, "octetstring",
1888 return OCTETSTRING(returncount
, (const unsigned char*)value
+ idx
);
1891 OCTETSTRING
substr(const OCTETSTRING
& value
, int idx
,
1892 const INTEGER
& returncount
)
1894 returncount
.must_bound("The third argument (returncount) of function "
1895 "substr() is an unbound integer value.");
1896 return substr(value
, idx
, (int)returncount
);
1899 OCTETSTRING
substr(const OCTETSTRING
& value
, const INTEGER
& idx
,
1902 idx
.must_bound("The second argument (index) of function substr() "
1903 "is an unbound integer value.");
1904 return substr(value
, (int)idx
, returncount
);
1907 OCTETSTRING
substr(const OCTETSTRING
& value
, const INTEGER
& idx
,
1908 const INTEGER
& returncount
)
1910 idx
.must_bound("The second argument (index) of function substr() is an "
1911 "unbound integer value.");
1912 returncount
.must_bound("The third argument (returncount) of function "
1913 "substr() is an unbound integer value.");
1914 return substr(value
, (int)idx
, (int)returncount
);
1917 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, int idx
, int returncount
)
1919 value
.must_bound("The first argument (value) of function substr() "
1920 "is an unbound octetstring element.");
1921 check_substr_arguments(idx
, returncount
, "octetstring", "octet");
1922 if (returncount
== 0) return OCTETSTRING(0, NULL
);
1924 unsigned char octet
= value
.get_octet();
1925 return OCTETSTRING(1, &octet
);
1929 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, int idx
,
1930 const INTEGER
& returncount
)
1932 returncount
.must_bound("The third argument (returncount) of function "
1933 "substr() is an unbound integer value.");
1934 return substr(value
, idx
, (int)returncount
);
1937 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1940 idx
.must_bound("The second argument (index) of function substr() "
1941 "is an unbound integer value.");
1942 return substr(value
, (int)idx
, returncount
);
1945 OCTETSTRING
substr(const OCTETSTRING_ELEMENT
& value
, const INTEGER
& idx
,
1946 const INTEGER
& returncount
)
1948 idx
.must_bound("The second argument (index) of function substr() is an "
1949 "unbound integer value.");
1950 returncount
.must_bound("The third argument (returncount) of function "
1951 "substr() is an unbound integer value.");
1952 return substr(value
, (int)idx
, (int)returncount
);
1955 CHARSTRING
substr(const CHARSTRING
& value
, int idx
, int returncount
)
1957 value
.must_bound("The first argument (value) of function substr() "
1958 "is an unbound charstring value.");
1959 check_substr_arguments(value
.lengthof(), idx
, returncount
, "charstring",
1961 return CHARSTRING(returncount
, (const char*)value
+ idx
);
1964 CHARSTRING
substr(const CHARSTRING
& value
, int idx
,
1965 const INTEGER
& returncount
)
1967 returncount
.must_bound("The third argument (returncount) of function "
1968 "substr() is an unbound integer value.");
1969 return substr(value
, idx
, (int)returncount
);
1972 CHARSTRING
substr(const CHARSTRING
& value
, const INTEGER
& idx
,
1975 idx
.must_bound("The second argument (index) of function substr() "
1976 "is an unbound integer value.");
1977 return substr(value
, (int)idx
, returncount
);
1980 CHARSTRING
substr(const CHARSTRING
& value
, const INTEGER
& idx
,
1981 const INTEGER
& returncount
)
1983 idx
.must_bound("The second argument (index) of function substr() is an "
1984 "unbound integer value.");
1985 returncount
.must_bound("The third argument (returncount) of function "
1986 "substr() is an unbound integer value.");
1987 return substr(value
, (int)idx
, (int)returncount
);
1990 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, int idx
, int returncount
)
1992 value
.must_bound("The first argument (value) of function substr() "
1993 "is an unbound charstring element.");
1994 check_substr_arguments(idx
, returncount
, "charstring", "character");
1995 if (returncount
== 0) return CHARSTRING(0, NULL
);
1996 else return CHARSTRING(value
.get_char());
1999 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, int idx
,
2000 const INTEGER
& returncount
)
2002 returncount
.must_bound("The third argument (returncount) of function "
2003 "substr() is an unbound integer value.");
2004 return substr(value
, idx
, (int)returncount
);
2007 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, const INTEGER
& idx
,
2010 idx
.must_bound("The second argument (index) of function substr() "
2011 "is an unbound integer value.");
2012 return substr(value
, (int)idx
, returncount
);
2015 CHARSTRING
substr(const CHARSTRING_ELEMENT
& value
, const INTEGER
& idx
,
2016 const INTEGER
& returncount
)
2018 idx
.must_bound("The second argument (index) of function substr() is an "
2019 "unbound integer value.");
2020 returncount
.must_bound("The third argument (returncount) of function "
2021 "substr() is an unbound integer value.");
2022 return substr(value
, (int)idx
, (int)returncount
);
2025 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2028 value
.must_bound("The first argument (value) of function substr() "
2029 "is an unbound universal charstring value.");
2030 check_substr_arguments(value
.lengthof(), idx
, returncount
,
2031 "universal charstring", "character");
2032 return UNIVERSAL_CHARSTRING(returncount
,
2033 (const universal_char
*)value
+ idx
);
2036 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2037 const INTEGER
& returncount
)
2039 returncount
.must_bound("The third argument (returncount) of function "
2040 "substr() is an unbound integer value.");
2041 return substr(value
, idx
, (int)returncount
);
2044 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
,
2045 const INTEGER
& idx
, int returncount
)
2047 idx
.must_bound("The second argument (index) of function substr() "
2048 "is an unbound integer value.");
2049 return substr(value
, (int)idx
, returncount
);
2052 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING
& value
,
2053 const INTEGER
& idx
, const INTEGER
& returncount
)
2055 idx
.must_bound("The second argument (index) of function substr() is an "
2056 "unbound integer value.");
2057 returncount
.must_bound("The third argument (returncount) of function "
2058 "substr() is an unbound integer value.");
2059 return substr(value
, (int)idx
, (int)returncount
);
2062 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2063 int idx
, int returncount
)
2065 value
.must_bound("The first argument (value) of function substr() "
2066 "is an unbound universal charstring element.");
2067 check_substr_arguments(idx
, returncount
, "universal charstring",
2069 if (returncount
== 0)
2070 return UNIVERSAL_CHARSTRING(0, (const universal_char
*)NULL
);
2071 else return UNIVERSAL_CHARSTRING(value
.get_uchar());
2074 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2075 int idx
, const INTEGER
& returncount
)
2077 returncount
.must_bound("The third argument (returncount) of function "
2078 "substr() is an unbound integer value.");
2079 return substr(value
, idx
, (int)returncount
);
2082 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2083 const INTEGER
& idx
, int returncount
)
2085 idx
.must_bound("The second argument (index) of function substr() "
2086 "is an unbound integer value.");
2087 return substr(value
, (int)idx
, returncount
);
2090 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_ELEMENT
& value
,
2091 const INTEGER
& idx
, const INTEGER
& returncount
)
2093 idx
.must_bound("The second argument (index) of function substr() is an "
2094 "unbound integer value.");
2095 returncount
.must_bound("The third argument (returncount) of function "
2096 "substr() is an unbound integer value.");
2097 return substr(value
, (int)idx
, (int)returncount
);
2100 // substr() on templates
2101 BITSTRING
substr(const BITSTRING_template
& value
, int idx
, int returncount
)
2103 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2104 return substr(value
.valueof(), idx
, returncount
);
2107 BITSTRING
substr(const BITSTRING_template
& value
, int idx
, const INTEGER
& returncount
)
2109 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2110 return substr(value
.valueof(), idx
, returncount
);
2113 BITSTRING
substr(const BITSTRING_template
& value
, const INTEGER
& idx
, int returncount
)
2115 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2116 return substr(value
.valueof(), idx
, returncount
);
2119 BITSTRING
substr(const BITSTRING_template
& value
, const INTEGER
& idx
,
2120 const INTEGER
& returncount
)
2122 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2123 return substr(value
.valueof(), idx
, returncount
);
2126 HEXSTRING
substr(const HEXSTRING_template
& value
, int idx
, int returncount
)
2128 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2129 return substr(value
.valueof(), idx
, returncount
);
2132 HEXSTRING
substr(const HEXSTRING_template
& value
, int idx
, const INTEGER
& returncount
)
2134 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2135 return substr(value
.valueof(), idx
, returncount
);
2138 HEXSTRING
substr(const HEXSTRING_template
& value
, const INTEGER
& idx
, int returncount
)
2140 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2141 return substr(value
.valueof(), idx
, returncount
);
2144 HEXSTRING
substr(const HEXSTRING_template
& value
, const INTEGER
& idx
,
2145 const INTEGER
& returncount
)
2147 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2148 return substr(value
.valueof(), idx
, returncount
);
2151 OCTETSTRING
substr(const OCTETSTRING_template
& value
, int idx
, int returncount
)
2153 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2154 return substr(value
.valueof(), idx
, returncount
);
2157 OCTETSTRING
substr(const OCTETSTRING_template
& value
, int idx
,
2158 const INTEGER
& returncount
)
2160 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2161 return substr(value
.valueof(), idx
, returncount
);
2164 OCTETSTRING
substr(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2167 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2168 return substr(value
.valueof(), idx
, returncount
);
2171 OCTETSTRING
substr(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2172 const INTEGER
& returncount
)
2174 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2175 return substr(value
.valueof(), idx
, returncount
);
2178 CHARSTRING
substr(const CHARSTRING_template
& value
, int idx
, int returncount
)
2180 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2181 return substr(value
.valueof(), idx
, returncount
);
2184 CHARSTRING
substr(const CHARSTRING_template
& value
, int idx
,
2185 const INTEGER
& returncount
)
2187 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2188 return substr(value
.valueof(), idx
, returncount
);
2191 CHARSTRING
substr(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2194 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2195 return substr(value
.valueof(), idx
, returncount
);
2198 CHARSTRING
substr(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2199 const INTEGER
& returncount
)
2201 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2202 return substr(value
.valueof(), idx
, returncount
);
2205 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
, int idx
,
2208 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2209 return substr(value
.valueof(), idx
, returncount
);
2212 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
, int idx
,
2213 const INTEGER
& returncount
)
2215 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2216 return substr(value
.valueof(), idx
, returncount
);
2219 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
,
2220 const INTEGER
& idx
, int returncount
)
2222 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2223 return substr(value
.valueof(), idx
, returncount
);
2226 UNIVERSAL_CHARSTRING
substr(const UNIVERSAL_CHARSTRING_template
& value
,
2227 const INTEGER
& idx
, const INTEGER
& returncount
)
2229 if (!value
.is_value()) TTCN_error("The first argument of function substr() is a template with non-specific value.");
2230 return substr(value
.valueof(), idx
, returncount
);
2235 void check_replace_arguments(int value_length
, int idx
, int len
,
2236 const char *string_type
, const char *element_name
)
2238 if (idx
< 0) TTCN_error("The second argument (index) of function "
2239 "replace() is a negative integer value: %d.", idx
);
2240 if (idx
> value_length
) TTCN_error("The second argument (index) of "
2241 "function replace(), which is %d, is greater than the length of the "
2242 "%s value: %d.", idx
, string_type
, value_length
);
2243 if (len
< 0) TTCN_error("The third argument (len) of function replace() "
2244 "is a negative integer value: %d.", len
);
2245 if (len
> value_length
) TTCN_error("The third argument (len) of function "
2246 "replace(), which is %d, is greater than the length of the "
2247 "%s value: %d.", len
, string_type
, value_length
);
2248 if (idx
+ len
> value_length
) TTCN_error("The first argument of "
2249 "function replace(), the length of which is %d, does not have enough "
2250 "%ss starting at index %d: %d %s%s needed, but there %s only %d.",
2251 value_length
, element_name
, idx
, len
, element_name
,
2252 len
> 1 ? "s are" : " is", value_length
- idx
> 1 ? "are" : "is",
2253 value_length
- idx
);
2256 BITSTRING
replace(const BITSTRING
& value
, int idx
, int len
,
2257 const BITSTRING
& repl
)
2259 value
.must_bound("The first argument (value) of function replace() "
2260 "is an unbound bitstring value.");
2261 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2262 "unbound bitstring value.");
2263 check_replace_arguments(value
.lengthof(), idx
, len
, "bitstring", "bit");
2264 int value_len
= value
.lengthof();
2265 int repl_len
= repl
.lengthof();
2266 BITSTRING
ret_val(value_len
+ repl_len
- len
);
2267 for (int i
= 0; i
< idx
; i
++) ret_val
.set_bit(i
, value
.get_bit(i
));
2268 for (int i
= 0; i
< repl_len
; i
++)
2269 ret_val
.set_bit(i
+ idx
, repl
.get_bit(i
));
2270 for (int i
= 0; i
< value_len
- idx
- len
; i
++)
2271 ret_val
.set_bit(i
+ idx
+ repl_len
, value
.get_bit(idx
+ len
+ i
));
2275 BITSTRING
replace(const BITSTRING
& value
, int idx
, const INTEGER
& len
,
2276 const BITSTRING
& repl
)
2278 len
.must_bound("The third argument (len) of function replace() is an "
2279 "unbound integer value.");
2280 return replace(value
, idx
, (int)len
, repl
);
2283 BITSTRING
replace(const BITSTRING
& value
, const INTEGER
& idx
, int len
,
2284 const BITSTRING
& repl
)
2286 idx
.must_bound("The second argument (index) of function replace() is an "
2287 "unbound integer value.");
2288 return replace(value
, (int)idx
, len
, repl
);
2291 BITSTRING
replace(const BITSTRING
& value
, const INTEGER
& idx
,
2292 const INTEGER
& len
, const BITSTRING
& repl
)
2294 idx
.must_bound("The second argument (index) of function replace() is an "
2295 "unbound integer value.");
2296 len
.must_bound("The third argument (len) of function replace() is an "
2297 "unbound integer value.");
2298 return replace(value
, (int)idx
, (int)len
, repl
);
2301 HEXSTRING
replace(const HEXSTRING
& value
, int idx
, int len
,
2302 const HEXSTRING
& repl
)
2304 value
.must_bound("The first argument (value) of function replace() "
2305 "is an unbound hexstring value.");
2306 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2307 "unbound hexstring value.");
2308 check_replace_arguments(value
.lengthof(), idx
, len
, "hexstring",
2309 "hexadecimal digit");
2310 int value_len
= value
.lengthof();
2311 int repl_len
= repl
.lengthof();
2312 HEXSTRING
ret_val(value_len
+ repl_len
- len
);
2313 for (int i
= 0; i
< idx
; i
++)
2314 ret_val
.set_nibble(i
, value
.get_nibble(i
));
2315 for (int i
= 0; i
< repl_len
; i
++)
2316 ret_val
.set_nibble(idx
+ i
, repl
.get_nibble(i
));
2317 for (int i
= 0; i
< value_len
- idx
- len
; i
++)
2318 ret_val
.set_nibble(idx
+ i
+ repl_len
,
2319 value
.get_nibble(idx
+ i
+ len
));
2323 HEXSTRING
replace(const HEXSTRING
& value
, int idx
, const INTEGER
& len
,
2324 const HEXSTRING
& repl
)
2326 len
.must_bound("The third argument (len) of function replace() is an "
2327 "unbound integer value.");
2328 return replace(value
, idx
, (int)len
, repl
);
2331 HEXSTRING
replace(const HEXSTRING
& value
, const INTEGER
& idx
, int len
,
2332 const HEXSTRING
& repl
)
2334 idx
.must_bound("The second argument (index) of function replace() is an "
2335 "unbound integer value.");
2336 return replace(value
, (int)idx
, len
, repl
);
2339 HEXSTRING
replace(const HEXSTRING
& value
, const INTEGER
& idx
,
2340 const INTEGER
& len
, const HEXSTRING
& repl
)
2342 idx
.must_bound("The second argument (index) of function replace() is an "
2343 "unbound integer value.");
2344 len
.must_bound("The third argument (len) of function replace() is an "
2345 "unbound integer value.");
2346 return replace(value
, (int)idx
, (int)len
, repl
);
2349 OCTETSTRING
replace(const OCTETSTRING
& value
, int idx
, int len
,
2350 const OCTETSTRING
& repl
)
2352 value
.must_bound("The first argument (value) of function replace() "
2353 "is an unbound octetstring value.");
2354 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2355 "unbound octetstring value.");
2356 check_replace_arguments(value
.lengthof(), idx
, len
, "octetstring",
2358 int value_len
= value
.lengthof();
2359 int repl_len
= repl
.lengthof();
2360 OCTETSTRING
ret_val(value_len
+ repl_len
- len
);
2361 memcpy(ret_val
.val_ptr
->octets_ptr
, value
.val_ptr
->octets_ptr
, idx
);
2362 memcpy(ret_val
.val_ptr
->octets_ptr
+ idx
, repl
.val_ptr
->octets_ptr
,
2364 memcpy(ret_val
.val_ptr
->octets_ptr
+ idx
+ repl_len
,
2365 value
.val_ptr
->octets_ptr
+ idx
+ len
, value_len
- idx
- len
);
2369 OCTETSTRING
replace(const OCTETSTRING
& value
, int idx
, const INTEGER
& len
,
2370 const OCTETSTRING
& repl
)
2372 len
.must_bound("The third argument (len) of function replace() is an "
2373 "unbound integer value.");
2374 return replace(value
, idx
, (int)len
, repl
);
2377 OCTETSTRING
replace(const OCTETSTRING
& value
, const INTEGER
& idx
, int len
,
2378 const OCTETSTRING
& repl
)
2380 idx
.must_bound("The second argument (index) of function replace() is an "
2381 "unbound integer value.");
2382 return replace(value
, (int)idx
, len
, repl
);
2385 OCTETSTRING
replace(const OCTETSTRING
& value
, const INTEGER
& idx
,
2386 const INTEGER
& len
, const OCTETSTRING
& repl
)
2388 idx
.must_bound("The second argument (index) of function replace() is an "
2389 "unbound integer value.");
2390 len
.must_bound("The third argument (len) of function replace() is an "
2391 "unbound integer value.");
2392 return replace(value
, (int)idx
, (int)len
, repl
);
2395 CHARSTRING
replace(const CHARSTRING
& value
, int idx
, int len
,
2396 const CHARSTRING
& repl
)
2398 value
.must_bound("The first argument (value) of function replace() "
2399 "is an unbound charstring value.");
2400 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2401 "unbound charstring value.");
2402 check_replace_arguments(value
.lengthof(), idx
, len
, "charstring",
2404 int value_len
= value
.lengthof();
2405 int repl_len
= repl
.lengthof();
2406 CHARSTRING
ret_val(value_len
+ repl_len
- len
);
2407 /* According to http://gcc.gnu.org/ml/fortran/2007-05/msg00341.html it's
2408 worth using memcpy() instead of strncat(). There's no need to scan the
2409 strings for '\0'. */
2410 memcpy(ret_val
.val_ptr
->chars_ptr
, value
.val_ptr
->chars_ptr
, idx
);
2411 memcpy(ret_val
.val_ptr
->chars_ptr
+ idx
, repl
.val_ptr
->chars_ptr
,
2413 memcpy(ret_val
.val_ptr
->chars_ptr
+ idx
+ repl_len
,
2414 value
.val_ptr
->chars_ptr
+ idx
+ len
, value_len
- idx
- len
);
2418 CHARSTRING
replace(const CHARSTRING
& value
, int idx
, const INTEGER
& len
,
2419 const CHARSTRING
& repl
)
2421 len
.must_bound("The third argument (len) of function replace() is an "
2422 "unbound integer value.");
2423 return replace(value
, idx
, (int)len
, repl
);
2426 CHARSTRING
replace(const CHARSTRING
& value
, const INTEGER
& idx
, int len
,
2427 const CHARSTRING
& repl
)
2429 idx
.must_bound("The second argument (index) of function replace() is an "
2430 "unbound integer value.");
2431 return replace(value
, (int)idx
, len
, repl
);
2434 CHARSTRING
replace(const CHARSTRING
& value
, const INTEGER
& idx
,
2435 const INTEGER
& len
, const CHARSTRING
& repl
)
2437 idx
.must_bound("The second argument (index) of function replace() is an "
2438 "unbound integer value.");
2439 len
.must_bound("The third argument (len) of function replace() is an "
2440 "unbound integer value.");
2441 return replace(value
, (int)idx
, (int)len
, repl
);
2444 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2445 int len
, const UNIVERSAL_CHARSTRING
& repl
)
2447 value
.must_bound("The first argument (value) of function replace() "
2448 "is an unbound universal charstring value.");
2449 repl
.must_bound("The fourth argument (repl) of function replace() is an "
2450 "unbound universal charstring value.");
2451 check_replace_arguments(value
.lengthof(), idx
, len
,
2452 "universal charstring", "character");
2453 int value_len
= value
.lengthof();
2454 int repl_len
= repl
.lengthof();
2455 UNIVERSAL_CHARSTRING
ret_val(value_len
+ repl_len
- len
);
2456 memcpy(ret_val
.val_ptr
->uchars_ptr
, value
.val_ptr
->uchars_ptr
,
2457 idx
* sizeof(universal_char
));
2458 memcpy(ret_val
.val_ptr
->uchars_ptr
+ idx
, repl
.val_ptr
->uchars_ptr
,
2459 repl_len
* sizeof(universal_char
));
2460 memcpy(ret_val
.val_ptr
->uchars_ptr
+ idx
+ repl_len
,
2461 value
.val_ptr
->uchars_ptr
+ idx
+ len
,
2462 (value_len
- idx
- len
) * sizeof(universal_char
));
2466 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
, int idx
,
2467 const INTEGER
& len
, const UNIVERSAL_CHARSTRING
& repl
)
2469 len
.must_bound("The third argument (len) of function replace() is an "
2470 "unbound integer value.");
2471 return replace(value
, idx
, (int)len
, repl
);
2474 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
,
2475 const INTEGER
& idx
, int len
, const UNIVERSAL_CHARSTRING
& repl
)
2477 idx
.must_bound("The second argument (index) of function replace() is an "
2478 "unbound integer value.");
2479 return replace(value
, (int)idx
, len
, repl
);
2482 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING
& value
,
2483 const INTEGER
& idx
, const INTEGER
& len
,
2484 const UNIVERSAL_CHARSTRING
& repl
)
2486 idx
.must_bound("The second argument (index) of function replace() is an "
2487 "unbound integer value.");
2488 len
.must_bound("The third argument (len) of function replace() is an "
2489 "unbound integer value.");
2490 return replace(value
, (int)idx
, (int)len
, repl
);
2493 // replace on templates
2495 BITSTRING
replace(const BITSTRING_template
& value
, int idx
, int len
,
2496 const BITSTRING_template
& repl
)
2498 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2499 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2500 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2503 BITSTRING
replace(const BITSTRING_template
& value
, int idx
, const INTEGER
& len
,
2504 const BITSTRING_template
& repl
)
2506 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2507 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2508 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2511 BITSTRING
replace(const BITSTRING_template
& value
, const INTEGER
& idx
, int len
,
2512 const BITSTRING_template
& repl
)
2514 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2515 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2516 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2519 BITSTRING
replace(const BITSTRING_template
& value
, const INTEGER
& idx
,
2520 const INTEGER
& len
, const BITSTRING_template
& repl
)
2522 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2523 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2524 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2527 HEXSTRING
replace(const HEXSTRING_template
& value
, int idx
, int len
,
2528 const HEXSTRING_template
& repl
)
2530 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2531 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2532 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2535 HEXSTRING
replace(const HEXSTRING_template
& value
, int idx
, const INTEGER
& len
,
2536 const HEXSTRING_template
& repl
)
2538 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2539 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2540 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2543 HEXSTRING
replace(const HEXSTRING_template
& value
, const INTEGER
& idx
, int len
,
2544 const HEXSTRING_template
& repl
)
2546 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2547 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2548 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2551 HEXSTRING
replace(const HEXSTRING_template
& value
, const INTEGER
& idx
,
2552 const INTEGER
& len
, const HEXSTRING_template
& repl
)
2554 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2555 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2556 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2559 OCTETSTRING
replace(const OCTETSTRING_template
& value
, int idx
, int len
,
2560 const OCTETSTRING_template
& repl
)
2562 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2563 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2564 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2567 OCTETSTRING
replace(const OCTETSTRING_template
& value
, int idx
, const INTEGER
& len
,
2568 const OCTETSTRING_template
& repl
)
2570 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2571 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2572 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2575 OCTETSTRING
replace(const OCTETSTRING_template
& value
, const INTEGER
& idx
, int len
,
2576 const OCTETSTRING_template
& repl
)
2578 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2579 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2580 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2583 OCTETSTRING
replace(const OCTETSTRING_template
& value
, const INTEGER
& idx
,
2584 const INTEGER
& len
, const OCTETSTRING_template
& repl
)
2586 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2587 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2588 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2591 CHARSTRING
replace(const CHARSTRING_template
& value
, int idx
, int len
,
2592 const CHARSTRING_template
& repl
)
2594 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2595 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2596 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2599 CHARSTRING
replace(const CHARSTRING_template
& value
, int idx
, const INTEGER
& len
,
2600 const CHARSTRING_template
& repl
)
2602 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2603 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2604 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2607 CHARSTRING
replace(const CHARSTRING_template
& value
, const INTEGER
& idx
, int len
,
2608 const CHARSTRING_template
& repl
)
2610 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2611 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2612 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2615 CHARSTRING
replace(const CHARSTRING_template
& value
, const INTEGER
& idx
,
2616 const INTEGER
& len
, const CHARSTRING_template
& repl
)
2618 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2619 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2620 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2623 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, int idx
, int len
,
2624 const UNIVERSAL_CHARSTRING_template
& repl
)
2626 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2627 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2628 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2631 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, int idx
, const INTEGER
& len
,
2632 const UNIVERSAL_CHARSTRING_template
& repl
)
2634 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2635 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2636 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2639 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, const INTEGER
& idx
, int len
,
2640 const UNIVERSAL_CHARSTRING_template
& repl
)
2642 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2643 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2644 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2647 UNIVERSAL_CHARSTRING
replace(const UNIVERSAL_CHARSTRING_template
& value
, const INTEGER
& idx
,
2648 const INTEGER
& len
, const UNIVERSAL_CHARSTRING_template
& repl
)
2650 if (!value
.is_value()) TTCN_error("The first argument of function replace() is a template with non-specific value.");
2651 if (!repl
.is_value()) TTCN_error("The fourth argument of function replace() is a template with non-specific value.");
2652 return replace(value
.valueof(), idx
, len
, repl
.valueof());
2657 static boolean rnd_seed_set
= FALSE
;
2659 static void set_rnd_seed(double float_seed
)
2661 FLOAT::check_numeric(float_seed
, "The seed value of function rnd()");
2662 long integer_seed
= 0;
2663 const unsigned char *src_ptr
= (const unsigned char*)&float_seed
;
2664 unsigned char *dst_ptr
= (unsigned char*)&integer_seed
;
2665 for (size_t i
= 0; i
< sizeof(float_seed
); i
++) {
2666 dst_ptr
[i
% sizeof(integer_seed
)] ^= bit_reverse_table
[src_ptr
[i
]];
2667 dst_ptr
[(sizeof(float_seed
) - 1 - i
) % sizeof(integer_seed
)] ^=
2671 srand48(integer_seed
);
2672 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::seed
, float_seed
, integer_seed
);
2673 rnd_seed_set
= TRUE
;
2676 static double rnd_generate()
2679 ret_val
= drand48();
2680 TTCN_Logger::log_random(TitanLoggerApi::RandomAction::read__out
, ret_val
, 0);
2686 if (!rnd_seed_set
) set_rnd_seed(TTCN_Snapshot::time_now());
2687 return rnd_generate();
2690 double rnd(double seed
)
2693 return rnd_generate();
2696 double rnd(const FLOAT
& seed
)
2698 seed
.must_bound("Initializing the random number generator with "
2699 "an unbound float value as seed.");
2700 set_rnd_seed((double)seed
);
2701 return rnd_generate();
2705 // Additional predefined functions defined in Annex B of ES 101 873-7
2707 // B.1 decomp - not implemented yet
2710 // Non-standard functions
2714 BITSTRING
str2bit(const char *value
)
2716 if (value
== NULL
) return BITSTRING(0, NULL
);
2717 else return str2bit(CHARSTRING(value
));
2720 BITSTRING
str2bit(const CHARSTRING
& value
)
2722 value
.must_bound("The argument of function str2bit() is an unbound "
2723 "charstring value.");
2724 int value_length
= value
.lengthof();
2725 const char *chars_ptr
= value
;
2726 BITSTRING
ret_val(value_length
);
2727 for (int i
= 0; i
< value_length
; i
++) {
2728 char c
= chars_ptr
[i
];
2731 ret_val
.set_bit(i
, FALSE
);
2734 ret_val
.set_bit(i
, TRUE
);
2737 TTCN_error_begin("The argument of function str2bit() shall "
2738 "contain characters `0' and `1' only, but character `");
2739 TTCN_Logger::log_char_escaped(c
);
2740 TTCN_Logger::log_event("' was found at index %d.", i
);
2744 ret_val
.clear_unused_bits();
2748 BITSTRING
str2bit(const CHARSTRING_ELEMENT
& value
)
2750 value
.must_bound("The argument of function str2bit() is an unbound "
2751 "charstring element.");
2752 char c
= value
.get_char();
2753 if (c
!= '0' && c
!= '1') {
2754 TTCN_error_begin("The argument of function str2bit() shall contain "
2755 "characters `0' and `1' only, but the given charstring element "
2756 "contains the character `");
2757 TTCN_Logger::log_char_escaped(c
);
2758 TTCN_Logger::log_event_str("'.");
2761 unsigned char bit
= c
== '1' ? 0x01 : 0x00;
2762 return BITSTRING(1, &bit
);
2767 HEXSTRING
str2hex(const char *value
)
2769 if (value
== NULL
) return HEXSTRING(0, NULL
);
2770 else return str2hex(CHARSTRING(value
));
2773 HEXSTRING
str2hex(const CHARSTRING
& value
)
2775 value
.must_bound("The argument of function str2hex() is an unbound "
2776 "charstring value.");
2777 int value_length
= value
.lengthof();
2778 const char *chars_ptr
= value
;
2779 HEXSTRING
ret_val(value_length
);
2780 unsigned char *nibbles_ptr
= ret_val
.val_ptr
->nibbles_ptr
;
2781 for (int i
= 0; i
< value_length
; i
++) {
2782 char c
= chars_ptr
[i
];
2783 unsigned char hex_digit
= char_to_hexdigit(c
);
2784 if (hex_digit
> 0x0F) {
2785 TTCN_error_begin("The argument of function str2hex() shall "
2786 "contain hexadecimal digits only, but character `");
2787 TTCN_Logger::log_char_escaped(c
);
2788 TTCN_Logger::log_event("' was found at index %d.", i
);
2791 if (i
% 2) nibbles_ptr
[i
/ 2] |= hex_digit
<< 4;
2792 else nibbles_ptr
[i
/ 2] = hex_digit
;
2797 HEXSTRING
str2hex(const CHARSTRING_ELEMENT
& value
)
2799 value
.must_bound("The argument of function str2hex() is an unbound "
2800 "charstring element.");
2801 char c
= value
.get_char();
2802 unsigned char hex_digit
= char_to_hexdigit(c
);
2803 if (hex_digit
> 0x0F) {
2804 TTCN_error_begin("The argument of function str2hex() shall contain "
2805 "only hexadecimal digits, but the given charstring element "
2806 "contains the character `");
2807 TTCN_Logger::log_char_escaped(c
);
2808 TTCN_Logger::log_event_str("'.");
2811 return HEXSTRING(1, &hex_digit
);
2816 CHARSTRING
float2str(double value
)
2818 bool f
= value
== 0.0
2819 || (value
> -MAX_DECIMAL_FLOAT
&& value
<= -MIN_DECIMAL_FLOAT
)
2820 || (value
>= MIN_DECIMAL_FLOAT
&& value
< MAX_DECIMAL_FLOAT
);
2821 // true if decimal representation possible (use %f format)
2823 int str_len
= snprintf(str_buf
, sizeof(str_buf
), f
? "%f" : "%e", value
);
2824 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
2825 TTCN_error("Internal error: system call snprintf() returned "
2826 "unexpected status code %d when converting value %g in function "
2827 "float2str().", str_len
, value
);
2829 return CHARSTRING(str_len
, str_buf
);
2832 CHARSTRING
float2str(const FLOAT
& value
)
2834 value
.must_bound("The argument of function float2str() is an unbound "
2836 return float2str((double)value
);
2841 CHARSTRING
unichar2char(const UNIVERSAL_CHARSTRING
& value
)
2843 value
.must_bound("The argument of function unichar2char() is an unbound "
2844 "universal charstring value.");
2845 int value_length
= value
.lengthof();
2846 const universal_char
*uchars_ptr
= value
;
2847 CHARSTRING
ret_val(value_length
);
2848 char *chars_ptr
= ret_val
.val_ptr
->chars_ptr
;
2849 for (int i
= 0; i
< value_length
; i
++) {
2850 const universal_char
& uchar
= uchars_ptr
[i
];
2851 if (uchar
.uc_group
!= 0 || uchar
.uc_plane
!= 0 || uchar
.uc_row
!= 0 ||
2852 uchar
.uc_cell
> 127) {
2853 TTCN_error("The characters in the argument of function "
2854 "unichar2char() shall be within the range char(0, 0, 0, 0) .. "
2855 "char(0, 0, 0, 127), but quadruple char(%u, %u, %u, %u) was "
2856 "found at index %d.", uchar
.uc_group
, uchar
.uc_plane
,
2857 uchar
.uc_row
, uchar
.uc_cell
, i
);
2859 chars_ptr
[i
] = uchar
.uc_cell
;
2864 CHARSTRING
unichar2char(const UNIVERSAL_CHARSTRING_ELEMENT
& value
)
2866 value
.must_bound("The argument of function unichar2char() is an unbound "
2867 "universal charstring element.");
2868 const universal_char
& uchar
= value
.get_uchar();
2869 if (uchar
.uc_group
!= 0 || uchar
.uc_plane
!= 0 || uchar
.uc_row
!= 0 ||
2870 uchar
.uc_cell
> 127) {
2871 TTCN_error("The characters in the argument of function unichar2char() "
2872 "shall be within the range char(0, 0, 0, 0) .. char(0, 0, 0, 127), "
2873 "but the given universal charstring element contains the quadruple "
2874 "char(%u, %u, %u, %u).", uchar
.uc_group
, uchar
.uc_plane
,
2875 uchar
.uc_row
, uchar
.uc_cell
);
2877 return CHARSTRING((char)uchar
.uc_cell
);
2880 OCTETSTRING
unichar2oct(const UNIVERSAL_CHARSTRING
& invalue
, const CHARSTRING
& string_encoding
)
2882 invalue
.must_bound("The argument of function unichar2oct() is an unbound "
2883 "universal charstring value.");
2884 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
2885 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
2887 if ("UTF-8" == string_encoding
) {
2888 invalue
.encode_utf8(buf
, false);
2890 else if ("UTF-8 BOM" == string_encoding
) {
2891 invalue
.encode_utf8(buf
, true);
2893 else if ("UTF-16" == string_encoding
) {
2894 invalue
.encode_utf16(buf
, CharCoding::UTF16
);
2896 else if ("UTF-16BE" == string_encoding
) {
2897 invalue
.encode_utf16(buf
, CharCoding::UTF16BE
);
2899 else if ("UTF-16LE" == string_encoding
) {
2900 invalue
.encode_utf16(buf
, CharCoding::UTF16LE
);
2902 else if ("UTF-32" == string_encoding
) {
2903 invalue
.encode_utf32(buf
, CharCoding::UTF32
);
2905 else if ("UTF-32BE" == string_encoding
) {
2906 invalue
.encode_utf32(buf
, CharCoding::UTF32BE
);
2907 } else if ("UTF-32LE" == string_encoding
) {
2908 invalue
.encode_utf32(buf
, CharCoding::UTF32LE
);
2911 TTCN_error("unichar2oct: Invalid parameter: %s", (const char*)string_encoding
);
2913 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
2914 return OCTETSTRING (buf
.get_len(), buf
.get_data());
2917 OCTETSTRING
unichar2oct(const UNIVERSAL_CHARSTRING
& invalue
)
2919 // no encoding parameter is default UTF-8
2920 invalue
.must_bound("The argument of function unichar2oct() is an unbound "
2921 "universal charstring value.");
2922 TTCN_EncDec::error_behavior_t err_behavior
= TTCN_EncDec::get_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
);
2923 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, TTCN_EncDec::EB_ERROR
);
2925 invalue
.encode_utf8(buf
, false);
2926 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_DEC_UCSTR
, err_behavior
);
2927 return OCTETSTRING (buf
.get_len(), buf
.get_data());
2930 CHARSTRING
get_stringencoding(const OCTETSTRING
& encoded_value
)
2932 if (!encoded_value
.lengthof()) return CHARSTRING("<unknown>");
2933 unsigned int i
, j
, length
= encoded_value
.lengthof();
2934 const unsigned char* strptr
= (const unsigned char*)encoded_value
;
2935 for (i
= 0, j
= 0; UTF8_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF8_BOM
););
2936 if (i
== sizeof (UTF8_BOM
) && sizeof(UTF8_BOM
) <= length
) return "UTF-8";
2937 //UTF-32 shall be tested before UTF-16 !!!
2938 for (i
= 0, j
= 0; UTF32BE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF32BE_BOM
););
2939 if (i
== sizeof (UTF32BE_BOM
) && sizeof (UTF32BE_BOM
) <= length
) return "UTF-32BE";
2940 for (i
= 0, j
= 0; UTF32LE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF32LE_BOM
););
2941 if (i
== sizeof (UTF32LE_BOM
) && sizeof (UTF32LE_BOM
) <= length
) return "UTF-32LE";
2942 //UTF-32 shall be tested before UTF-16 !!!
2943 for (i
= 0, j
= 0; UTF16BE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF16BE_BOM
););
2944 if (i
== sizeof (UTF16BE_BOM
) && sizeof (UTF16BE_BOM
) <= length
) return "UTF-16BE";
2945 for (i
= 0, j
= 0; UTF16LE_BOM
[i
++] == strptr
[j
++] && i
< sizeof (UTF16LE_BOM
););
2946 if (i
== sizeof (UTF16LE_BOM
) && sizeof (UTF16LE_BOM
) <= length
) return "UTF-16LE";
2947 if (is_ascii (encoded_value
) == CharCoding::ASCII
) {
2950 else if (CharCoding::UTF_8
== is_utf8 (encoded_value
)) {
2957 // for internal purposes:
2958 // to obtain the name of the port when port array references are used
2959 // in connect/map/disconnect/unmap operations
2961 CHARSTRING
get_port_name(const char *port_name
, int array_index
)
2963 char *result_str
= mprintf("%s[%d]", port_name
, array_index
);
2964 CHARSTRING
ret_val(mstrlen(result_str
), result_str
);
2969 CHARSTRING
get_port_name(const char *port_name
, const INTEGER
& array_index
)
2971 array_index
.must_bound("Using an unbound integer value for indexing an "
2973 return get_port_name(port_name
, (int)array_index
);
2976 CHARSTRING
get_port_name(const CHARSTRING
& port_name
, int array_index
)
2978 port_name
.must_bound("Internal error: Using an unbound charstring value "
2979 "to obtain the name of a port.");
2980 return get_port_name((const char*)port_name
, array_index
);
2983 CHARSTRING
get_port_name(const CHARSTRING
& port_name
,
2984 const INTEGER
& array_index
)
2986 port_name
.must_bound("Internal error: Using an unbound charstring value "
2987 "to obtain the name of a port.");
2988 array_index
.must_bound("Using an unbound integer value for indexing an "
2990 return get_port_name((const char*)port_name
, (int)array_index
);
2993 OCTETSTRING
remove_bom(const OCTETSTRING
& encoded_value
)
2995 const unsigned char* str
= (const unsigned char*)encoded_value
;
2996 int length_of_BOM
= 0;
2997 if (0x00 == str
[0] && 0x00 == str
[1] && 0xFE == str
[2] && 0xFF == str
[3]) { // UTF-32BE
3000 else if (0xFF == str
[0] && 0xFE == str
[1] && 0x00 == str
[2] && 0x00 == str
[3]) { // UTF-32LE
3003 else if (0xFE == str
[0] && 0xFF == str
[1]) { // UTF-16BE
3006 else if (0xFF == str
[0] && 0xFE == str
[1]) { // UTF-16LE
3009 else if (0xEF == str
[0] && 0xBB == str
[1] && 0xBF == str
[2]) { // UTF-8
3013 return OCTETSTRING (encoded_value
); // no BOM found
3015 return OCTETSTRING (encoded_value
.lengthof() - length_of_BOM
, (str
+ length_of_BOM
));
3018 CHARSTRING
encode_base64(const OCTETSTRING
& msg
)
3020 const char *code_table
= {
3026 const char pad
= '=';
3027 const unsigned char *p_msg
= (const unsigned char *)msg
;
3028 int octets_left
= msg
.lengthof();
3029 char *output
= (char*)Malloc(((octets_left
*22)>>4) + 7);
3030 char *p_output
= output
;
3031 while(octets_left
>= 3) {
3032 *p_output
++ = code_table
[p_msg
[0] >> 2];
3033 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3034 *p_output
++ = code_table
[((p_msg
[1] << 2) | (p_msg
[2] >> 6)) & 0x3f];
3035 *p_output
++ = code_table
[p_msg
[2] & 0x3f];
3039 switch(octets_left
) {
3041 *p_output
++ = code_table
[p_msg
[0] >> 2];
3042 *p_output
++ = code_table
[(p_msg
[0] << 4) & 0x3f];
3047 *p_output
++ = code_table
[p_msg
[0] >> 2];
3048 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3049 *p_output
++ = code_table
[(p_msg
[1] << 2) & 0x3f];
3056 CHARSTRING
ret_val(output
);
3061 CHARSTRING
encode_base64(const OCTETSTRING
& msg
, bool use_linebreaks
)
3063 const char *code_table
= {
3069 const char pad
= '=';
3070 const unsigned char *p_msg
= (const unsigned char *)msg
;
3071 int octets_left
= msg
.lengthof();
3072 char *output
= (char*)Malloc(((octets_left
*22)>>4) + 7);
3073 char *p_output
= output
;
3075 while(octets_left
>= 3) {
3076 *p_output
++ = code_table
[p_msg
[0] >> 2];
3077 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3078 *p_output
++ = code_table
[((p_msg
[1] << 2) | (p_msg
[2] >> 6)) & 0x3f];
3079 *p_output
++ = code_table
[p_msg
[2] & 0x3f];
3081 if (use_linebreaks
&& n_4chars
>=19 && octets_left
!= 3) {
3089 switch(octets_left
) {
3091 *p_output
++ = code_table
[p_msg
[0] >> 2];
3092 *p_output
++ = code_table
[(p_msg
[0] << 4) & 0x3f];
3097 *p_output
++ = code_table
[p_msg
[0] >> 2];
3098 *p_output
++ = code_table
[((p_msg
[0] << 4) | (p_msg
[1] >> 4)) & 0x3f];
3099 *p_output
++ = code_table
[(p_msg
[1] << 2) & 0x3f];
3106 CHARSTRING
ret_val(output
);
3112 OCTETSTRING
decode_base64(const CHARSTRING
& b64
)
3114 const unsigned char decode_table
[] = {
3115 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3116 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
3117 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 62, 80, 80, 80, 63,
3118 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 80, 80, 80, 70, 80, 80,
3119 80, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
3120 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 80, 80, 80, 80, 80,
3121 80, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
3122 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 80, 80, 80, 80, 80
3124 const unsigned char *p_b64
= (const unsigned char *) ((const char *)b64
);
3125 int chars_left
= b64
.lengthof();
3126 unsigned char *output
= (unsigned char*)Malloc(((chars_left
>> 2) + 1) * 3);
3127 unsigned char *p_output
= output
;
3128 unsigned int bits
= 0;
3130 while(chars_left
--) {
3132 if (*p_b64
> 0 && (dec
= decode_table
[*p_b64
]) < 64) {
3137 *p_output
++ = (bits
>> (n_bits
- 8)) & 0xff;
3141 else if (*p_b64
== '=') {
3145 if (*p_b64
== '\r' && *(p_b64
+ 1) == '\n') {
3146 ++p_b64
; // skip \n too
3149 TTCN_error("Error: Invalid character in Base64 encoded data: 0x%02X", *p_b64
);
3154 OCTETSTRING
ret_val(p_output
- output
, output
);