1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "Universal_charstring.hh"
10 #include "../common/dbgnew.hh"
11 #include "../common/memory.h"
12 #include "../common/pattern.hh"
13 #include "../common/Quadruple.hh"
15 #include "Octetstring.hh"
16 #include "String_struct.hh"
17 #include "Param_Types.hh"
21 #include "Addfunc.hh" // for unichar2int
26 #define ERRMSG_BUFSIZE 500
28 // global function for universal_char comparison
30 boolean
operator==(const universal_char
& left_value
,
31 const universal_char
& right_value
)
33 return left_value
.uc_group
== right_value
.uc_group
&&
34 left_value
.uc_plane
== right_value
.uc_plane
&&
35 left_value
.uc_row
== right_value
.uc_row
&&
36 left_value
.uc_cell
== right_value
.uc_cell
;
39 boolean
operator<(const universal_char
& left_value
,
40 const universal_char
& right_value
)
42 if (left_value
.uc_group
< right_value
.uc_group
) return TRUE
;
43 else if (left_value
.uc_group
== right_value
.uc_group
) {
44 if (left_value
.uc_plane
< right_value
.uc_plane
) return TRUE
;
45 else if (left_value
.uc_plane
== right_value
.uc_plane
) {
46 if (left_value
.uc_row
< right_value
.uc_row
) return TRUE
;
47 else if (left_value
.uc_row
== right_value
.uc_row
) {
48 if (left_value
.uc_cell
< right_value
.uc_cell
) return TRUE
;
55 /** The amount of memory needed for a string containing n characters. */
56 #define MEMORY_SIZE(n) (sizeof(universal_charstring_struct) + \
57 ((n) - 1) * sizeof(universal_char))
59 // member functions of class UNIVERSAL_CHARSTRING
61 /** Allocate space for n characters.
63 * @param n_uchars number of characters needed
67 * If n_uchars is 0, no memory is allocated and a reference to the
68 * "empty string" is used instead.
70 * Otherwise, space for n_uchars is allocated (no terminating null).
72 * @note If the string is not empty, this will leak memory.
73 * Probably clean_up() should have been called before.
75 void UNIVERSAL_CHARSTRING::init_struct(int n_uchars
)
79 TTCN_error("Initializing a universal charstring with a negative length.");
80 } else if (n_uchars
== 0) {
81 /* This will represent the empty strings so they won't need allocated
82 * memory, this delays the memory allocation until it is really needed.
84 static universal_charstring_struct empty_string
=
85 { 1, 0, { { '\0', '\0', '\0', '\0' } } };
86 val_ptr
= &empty_string
;
87 empty_string
.ref_count
++;
89 val_ptr
= (universal_charstring_struct
*)Malloc(MEMORY_SIZE(n_uchars
));
90 val_ptr
->ref_count
= 1;
91 val_ptr
->n_uchars
= n_uchars
;
95 void UNIVERSAL_CHARSTRING::copy_value()
97 if (val_ptr
== NULL
|| val_ptr
->n_uchars
<= 0)
98 TTCN_error("Internal error: Invalid internal data structure when copying "
99 "the memory area of a universal charstring value.");
100 if (val_ptr
->ref_count
> 1) {
101 universal_charstring_struct
*old_ptr
= val_ptr
;
102 old_ptr
->ref_count
--;
103 init_struct(old_ptr
->n_uchars
);
104 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
, old_ptr
->n_uchars
*
105 sizeof(universal_char
));
109 void UNIVERSAL_CHARSTRING::clean_up()
111 if (val_ptr
!= NULL
) {
112 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
113 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
114 else TTCN_error("Internal error: Invalid reference counter in a universal "
115 "charstring value.");
121 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars
, bool cstring
)
122 : val_ptr(NULL
), cstr(cstring
? n_uchars
: 0), charstring(cstring
)
125 init_struct(n_uchars
);
128 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING()
129 : val_ptr(NULL
), cstr(0), charstring(false)
132 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(unsigned char uc_group
,
133 unsigned char uc_plane
, unsigned char uc_row
, unsigned char uc_cell
)
137 val_ptr
->uchars_ptr
[0].uc_group
= uc_group
;
138 val_ptr
->uchars_ptr
[0].uc_plane
= uc_plane
;
139 val_ptr
->uchars_ptr
[0].uc_row
= uc_row
;
140 val_ptr
->uchars_ptr
[0].uc_cell
= uc_cell
;
143 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
144 (const universal_char
& other_value
)
145 : cstr(0), charstring(false)
148 val_ptr
->uchars_ptr
[0] = other_value
;
151 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars
,
152 const universal_char
*uchars_ptr
)
153 : cstr(0), charstring(false)
155 init_struct(n_uchars
);
156 memcpy(val_ptr
->uchars_ptr
, uchars_ptr
, n_uchars
* sizeof(universal_char
));
159 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const char *chars_ptr
)
160 : val_ptr(NULL
), cstr(chars_ptr
), charstring(true)
164 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_chars
,
165 const char *chars_ptr
)
166 : val_ptr(NULL
), cstr(n_chars
, chars_ptr
), charstring(true)
170 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const CHARSTRING
& other_value
)
171 : val_ptr(NULL
), cstr(other_value
), charstring(true)
175 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
176 (const CHARSTRING_ELEMENT
& other_value
)
177 : val_ptr(NULL
), cstr(other_value
), charstring(true)
181 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
182 (const UNIVERSAL_CHARSTRING
& other_value
)
183 : Base_Type(other_value
), charstring(other_value
.charstring
)
185 other_value
.must_bound("Copying an unbound universal charstring value.");
186 if (other_value
.charstring
) {
187 cstr
= other_value
.cstr
;
190 val_ptr
= other_value
.val_ptr
;
191 val_ptr
->ref_count
++;
196 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
197 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
198 : charstring(other_value
.get_uchar().is_char())
200 other_value
.must_bound("Initialization of a universal charstring with an "
201 "unbound universal charstring element.");
203 cstr
= CHARSTRING(other_value
.get_uchar().uc_cell
);
207 val_ptr
->uchars_ptr
[0] = other_value
.get_uchar();
211 UNIVERSAL_CHARSTRING::~UNIVERSAL_CHARSTRING()
217 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
218 (const universal_char
& other_value
)
221 if (other_value
.is_char()) {
222 cstr
= CHARSTRING(other_value
.uc_cell
);
227 val_ptr
->uchars_ptr
[0] = other_value
;
233 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
234 (const char* other_value
)
244 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
245 (const CHARSTRING
& other_value
)
255 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
256 (const CHARSTRING_ELEMENT
& other_value
)
266 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
267 (const UNIVERSAL_CHARSTRING
& other_value
)
269 other_value
.must_bound("Assignment of an unbound universal charstring "
271 if (&other_value
!= this) {
273 if (other_value
.charstring
) {
274 cstr
= other_value
.cstr
;
276 val_ptr
= other_value
.val_ptr
;
277 val_ptr
->ref_count
++;
281 charstring
= other_value
.charstring
;
286 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
287 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
289 other_value
.must_bound("Assignment of an unbound universal charstring "
290 "element to a universal charstring.");
291 if (other_value
.str_val
.charstring
) {
292 char c
= other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
294 cstr
= CHARSTRING(c
);
297 universal_char uchar_value
= other_value
.get_uchar();
300 val_ptr
->uchars_ptr
[0] = uchar_value
;
306 boolean
UNIVERSAL_CHARSTRING::operator==
307 (const universal_char
& other_value
) const
309 must_bound("The left operand of comparison is an unbound universal "
310 "charstring value.");
312 return cstr
.lengthof() == 1 && other_value
.uc_group
== 0
313 && other_value
.uc_plane
== 0 && other_value
.uc_row
== 0
314 && other_value
.uc_cell
== (cbyte
)cstr
.val_ptr
->chars_ptr
[0];
316 if (val_ptr
->n_uchars
!= 1) return FALSE
;
317 else return val_ptr
->uchars_ptr
[0] == other_value
;
320 boolean
UNIVERSAL_CHARSTRING::operator==(const char* other_value
) const
322 must_bound("The left operand of comparison is an unbound universal "
323 "charstring value.");
325 return cstr
== other_value
;
328 if (other_value
== NULL
) n_chars
= 0;
329 else n_chars
= strlen(other_value
);
330 if (val_ptr
->n_uchars
!= n_chars
) return FALSE
;
331 for (int i
= 0; i
< n_chars
; i
++) {
332 if (val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
333 val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
334 val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
335 val_ptr
->uchars_ptr
[i
].uc_cell
!= (cbyte
)other_value
[i
]) return FALSE
;
341 boolean
UNIVERSAL_CHARSTRING::operator==
342 (const CHARSTRING
& other_value
) const
344 must_bound("The left operand of comparison is an unbound universal "
345 "charstring value.");
346 other_value
.must_bound("The right operand of comparison is an unbound "
347 "charstring value.");
349 return cstr
== other_value
;
350 if (val_ptr
->n_uchars
!= other_value
.val_ptr
->n_chars
) return FALSE
;
351 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
352 if (val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
353 val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
354 val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
355 val_ptr
->uchars_ptr
[i
].uc_cell
!=(cbyte
)other_value
.val_ptr
->chars_ptr
[i
])
361 boolean
UNIVERSAL_CHARSTRING::operator==
362 (const CHARSTRING_ELEMENT
& other_value
) const
364 must_bound("The left operand of comparison is an unbound universal "
365 "charstring value.");
366 other_value
.must_bound("The right operand of comparison is an unbound "
367 "charstring element.");
369 return cstr
== other_value
;
370 if (val_ptr
->n_uchars
!= 1) return FALSE
;
371 else return val_ptr
->uchars_ptr
[0].uc_group
== 0 &&
372 val_ptr
->uchars_ptr
[0].uc_plane
== 0 &&
373 val_ptr
->uchars_ptr
[0].uc_row
== 0 &&
374 val_ptr
->uchars_ptr
[0].uc_cell
== (cbyte
)other_value
.get_char();
377 boolean
UNIVERSAL_CHARSTRING::operator==
378 (const UNIVERSAL_CHARSTRING
& other_value
) const
380 must_bound("The left operand of comparison is an unbound universal "
381 "charstring value.");
382 other_value
.must_bound("The right operand of comparison is an unbound "
383 "universal charstring value.");
385 return cstr
== other_value
;
386 else if (other_value
.charstring
)
387 return other_value
.cstr
== *this;
388 if (val_ptr
->n_uchars
!= other_value
.val_ptr
->n_uchars
) return FALSE
;
389 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
390 if (val_ptr
->uchars_ptr
[i
] != other_value
.val_ptr
->uchars_ptr
[i
])
396 boolean
UNIVERSAL_CHARSTRING::operator==
397 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
399 must_bound("The left operand of comparison is an unbound universal "
400 "charstring value.");
401 other_value
.must_bound("The right operand of comparison is an unbound "
402 "universal charstring element.");
404 return cstr
== other_value
;
405 if (val_ptr
->n_uchars
!= 1) return FALSE
;
406 else return val_ptr
->uchars_ptr
[0] == other_value
.get_uchar();
409 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
410 (const universal_char
& other_value
) const
412 must_bound("The left operand of concatenation is an unbound universal "
413 "charstring value.");
415 if (other_value
.is_char()) {
416 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1, true);
417 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
418 cstr
.val_ptr
->n_chars
);
419 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
423 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1);
424 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
425 universal_char
& uc
= ret_val
.val_ptr
->uchars_ptr
[i
];
426 uc
.uc_group
= uc
.uc_plane
= uc
.uc_row
= 0;
427 uc
.uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
429 ret_val
.val_ptr
->uchars_ptr
[cstr
.val_ptr
->n_chars
] = other_value
;
433 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
434 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
435 val_ptr
->n_uchars
* sizeof(universal_char
));
436 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
;
440 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
441 (const char* other_value
) const
443 must_bound("The left operand of concatenation is an unbound universal "
444 "charstring value.");
446 if (other_value
== NULL
) other_len
= 0;
447 else other_len
= strlen(other_value
);
448 if (other_len
== 0) return *this;
450 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + other_len
, true);
451 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
452 cstr
.val_ptr
->n_chars
);
453 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
454 other_value
, other_len
);
457 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ other_len
);
458 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
459 val_ptr
->n_uchars
* sizeof(universal_char
));
460 for (int i
= 0; i
< other_len
; i
++) {
461 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_group
= 0;
462 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_plane
= 0;
463 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_row
= 0;
464 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_cell
= other_value
[i
];
469 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
470 (const CHARSTRING
& other_value
) const
472 must_bound("The left operand of concatenation is an unbound universal "
473 "charstring value.");
474 other_value
.must_bound("The right operand of concatenation is an unbound "
475 "charstring value.");
476 if (other_value
.val_ptr
->n_chars
== 0) return *this;
478 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + other_value
.val_ptr
->n_chars
,
480 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
481 cstr
.val_ptr
->n_chars
);
482 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
483 other_value
.val_ptr
->chars_ptr
, other_value
.val_ptr
->n_chars
);
486 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+
487 other_value
.val_ptr
->n_chars
);
488 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
489 val_ptr
->n_uchars
* sizeof(universal_char
));
490 for (int i
= 0; i
< other_value
.val_ptr
->n_chars
; i
++) {
491 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_group
= 0;
492 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_plane
= 0;
493 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_row
= 0;
494 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_cell
=
495 other_value
.val_ptr
->chars_ptr
[i
];
500 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
501 (const CHARSTRING_ELEMENT
& other_value
) const
503 must_bound("The left operand of concatenation is an unbound universal "
504 "charstring value.");
505 other_value
.must_bound("The right operand of concatenation is an unbound "
506 "charstring element.");
508 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1, true);
509 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
510 cstr
.val_ptr
->n_chars
);
511 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
512 other_value
.get_char();
515 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
516 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
517 val_ptr
->n_uchars
* sizeof(universal_char
));
518 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_group
= 0;
519 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_plane
= 0;
520 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_row
= 0;
521 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_cell
=
522 other_value
.get_char();
526 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
527 (const UNIVERSAL_CHARSTRING
& other_value
) const
529 must_bound("The left operand of concatenation is an unbound universal "
530 "charstring value.");
531 other_value
.must_bound("The right operand of concatenation is an unbound "
532 "universal charstring value.");
534 if (cstr
.val_ptr
->n_chars
== 0)
536 if (other_value
.charstring
) {
537 if (other_value
.cstr
.val_ptr
->n_chars
== 0)
539 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+
540 other_value
.cstr
.val_ptr
->n_chars
, true);
541 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
542 cstr
.val_ptr
->n_chars
);
543 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
544 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
547 if (other_value
.val_ptr
->n_uchars
== 0)
549 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+
550 other_value
.val_ptr
->n_uchars
);
551 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
552 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
553 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
554 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
555 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
557 memcpy(ret_val
.val_ptr
->uchars_ptr
+ cstr
.val_ptr
->n_chars
,
558 other_value
.val_ptr
->uchars_ptr
, other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
562 if (other_value
.charstring
) {
563 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ other_value
.cstr
.val_ptr
->n_chars
);
564 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
* sizeof(universal_char
));
565 for (int i
= val_ptr
->n_uchars
; i
< val_ptr
->n_uchars
+ other_value
.cstr
.val_ptr
->n_chars
; i
++) {
566 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
567 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
568 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
569 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= other_value
.cstr
.val_ptr
->chars_ptr
[i
-val_ptr
->n_uchars
];
573 if (val_ptr
->n_uchars
== 0) return other_value
;
574 if (other_value
.val_ptr
->n_uchars
== 0) return *this;
575 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+
576 other_value
.val_ptr
->n_uchars
);
577 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
578 val_ptr
->n_uchars
* sizeof(universal_char
));
579 memcpy(ret_val
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
,
580 other_value
.val_ptr
->uchars_ptr
,
581 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
587 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
588 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
590 must_bound("The left operand of concatenation is an unbound universal "
591 "charstring value.");
592 other_value
.must_bound("The right operand of concatenation is an unbound "
593 "universal charstring element.");
594 bool other_ischar
= other_value
.str_val
.charstring
;
597 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+ 1, true);
598 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
599 cstr
.val_ptr
->n_chars
);
600 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
601 other_value
.get_uchar().uc_cell
;
604 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+ 1);
605 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
606 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
607 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
608 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
609 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
611 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
.get_uchar();
614 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
615 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
616 val_ptr
->n_uchars
* sizeof(universal_char
));
618 universal_char
& uc
= ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
];
619 uc
.uc_group
= uc
.uc_plane
= uc
.uc_row
= 0;
620 uc
.uc_cell
= other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
622 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
.get_uchar();
627 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator<<=
628 (int rotate_count
) const
630 must_bound("The left operand of rotate left operator is an unbound "
631 "universal charstring value.");
634 return cstr
<<= rotate_count
;
636 if (val_ptr
->n_uchars
== 0) return *this;
637 if (rotate_count
>= 0) {
638 rotate_count
%= val_ptr
->n_uchars
;
639 if (rotate_count
== 0) return *this;
640 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
);
641 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
+ rotate_count
,
642 (val_ptr
->n_uchars
- rotate_count
) * sizeof(universal_char
));
643 memcpy(ret_val
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
- rotate_count
,
644 val_ptr
->uchars_ptr
, rotate_count
* sizeof(universal_char
));
646 } else return *this >>= (-rotate_count
);
649 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator<<=
650 (const INTEGER
& rotate_count
) const
652 rotate_count
.must_bound("The right operand of rotate left operator is an "
653 "unbound integer value.");
654 return *this <<= (int)rotate_count
;
657 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator>>=
658 (int rotate_count
) const
660 must_bound("The left operand of rotate right operator is an unbound "
661 "universal charstring value.");
664 return cstr
>>= rotate_count
;
666 if (val_ptr
->n_uchars
== 0) return *this;
667 if (rotate_count
>= 0) {
668 rotate_count
%= val_ptr
->n_uchars
;
669 if (rotate_count
== 0) return *this;
670 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
);
671 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
+
672 val_ptr
->n_uchars
- rotate_count
, rotate_count
* sizeof(universal_char
));
673 memcpy(ret_val
.val_ptr
->uchars_ptr
+ rotate_count
, val_ptr
->uchars_ptr
,
674 (val_ptr
->n_uchars
- rotate_count
) * sizeof(universal_char
));
676 } else return *this <<= (-rotate_count
);
680 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator>>=
681 (const INTEGER
& rotate_count
) const
683 rotate_count
.must_bound("The right operand of rotate right operator is an "
684 "unbound integer value.");
685 return *this >>= (int)rotate_count
;
689 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
692 if (!charstring
&& val_ptr
== NULL
&& index_value
== 0) {
694 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE
, *this, 0);
696 must_bound("Accessing an element of an unbound universal charstring "
698 if (index_value
< 0) TTCN_error("Accessing a universal charstring element "
699 "using a negative index (%d).", index_value
);
701 charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
;
702 if (index_value
> n_uchars
) TTCN_error("Index overflow when accessing a "
703 "universal charstring element: The index is %d, but the string has only "
704 "%d characters.", index_value
, n_uchars
);
705 if (index_value
== n_uchars
) {
707 (void)cstr
[index_value
]; // invoked for side-effect only (incr. length)
709 if (val_ptr
->ref_count
== 1) {
710 val_ptr
= (universal_charstring_struct
*)
711 Realloc(val_ptr
, MEMORY_SIZE(n_uchars
+ 1));
714 universal_charstring_struct
*old_ptr
= val_ptr
;
715 old_ptr
->ref_count
--;
716 init_struct(n_uchars
+ 1);
717 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
,
718 n_uchars
* sizeof(universal_char
));
721 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE
, *this, index_value
);
722 } else return UNIVERSAL_CHARSTRING_ELEMENT(TRUE
, *this, index_value
);
726 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
727 (const INTEGER
& index_value
)
729 index_value
.must_bound("Indexing a universal charstring value with an "
730 "unbound integer value.");
731 return (*this)[(int)index_value
];
734 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
735 (int index_value
) const
737 must_bound("Accessing an element of an unbound universal charstring value.");
738 const int size
= charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
;
739 if (index_value
< 0) TTCN_error("Accessing a universal charstring element "
740 "using a negative index (%d).", index_value
);
741 else if (index_value
>= size
) TTCN_error("Index overflow when "
742 "accessing a universal charstring element: The index is %d, but the "
743 "string has only %d characters.", index_value
, size
);
744 return UNIVERSAL_CHARSTRING_ELEMENT(TRUE
,
745 const_cast<UNIVERSAL_CHARSTRING
&>(*this), index_value
);
748 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
749 (const INTEGER
& index_value
) const
751 index_value
.must_bound("Indexing a universal charstring value with an "
752 "unbound integer value.");
753 return (*this)[(int)index_value
];
757 UNIVERSAL_CHARSTRING::operator const universal_char
*() const
759 must_bound("Casting an unbound universal charstring value to const "
762 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
763 return val_ptr
->uchars_ptr
;
766 int UNIVERSAL_CHARSTRING::lengthof() const
768 must_bound("Performing lengthof operation on an unbound universal charstring "
771 return cstr
.val_ptr
->n_chars
;
772 return val_ptr
->n_uchars
;
775 char* UNIVERSAL_CHARSTRING::convert_to_regexp_form() const {
776 must_bound("Performing pattern conversion operation on an unbound"
777 "universal charstring value.");
778 int size
= (charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
) * 8 + 1;
779 char* res
= static_cast<char*>(Malloc(size
));
784 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++, ptr
+= 8) {
785 q
.set(0, 0, 0, cstr
.val_ptr
->chars_ptr
[i
]);
786 Quad::get_hexrepr(q
, ptr
);
789 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++, ptr
+= 8) {
790 q
.set(val_ptr
->uchars_ptr
[i
].uc_group
, val_ptr
->uchars_ptr
[i
].uc_plane
,
791 val_ptr
->uchars_ptr
[i
].uc_row
, val_ptr
->uchars_ptr
[i
].uc_cell
);
792 Quad::get_hexrepr(q
, ptr
);
797 static inline boolean
is_printable(const universal_char
& uchar
)
799 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
800 TTCN_Logger::is_printable(uchar
.uc_cell
);
803 CHARSTRING
UNIVERSAL_CHARSTRING::get_stringRepr_for_pattern() const {
804 must_bound("Performing pattern conversion operation on an unbound"
805 "universal charstring value.");
806 CHARSTRING
ret_val("");
808 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
809 const char& chr
= cstr
.val_ptr
->chars_ptr
[i
];
810 if (TTCN_Logger::is_printable(chr
))
813 ret_val
+= "\\q{0,0,0,";
814 ret_val
+= int2str(chr
);
819 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
820 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
821 if (is_printable(uchar
))
822 ret_val
+= uchar
.uc_cell
;
825 ret_val
+= int2str(uchar
.uc_group
);
827 ret_val
+= int2str(uchar
.uc_plane
);
829 ret_val
+= int2str(uchar
.uc_row
);
831 ret_val
+= int2str(uchar
.uc_cell
);
838 void UNIVERSAL_CHARSTRING::convert_cstr_to_uni() {
839 init_struct(cstr
.lengthof());
840 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
841 val_ptr
->uchars_ptr
[i
].uc_group
= 0;
842 val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
843 val_ptr
->uchars_ptr
[i
].uc_row
= 0;
844 val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
851 void UNIVERSAL_CHARSTRING::dump() const
853 if (val_ptr
!= NULL
) {
854 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
855 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
856 std::wcout
<< "uchar[" << i
<< "] = " << "("
857 << uchar
.uc_group
<< "," << uchar
.uc_plane
<< "," << uchar
.uc_row
<< "," << uchar
.uc_cell
<< ")"<< std::endl
;
862 void UNIVERSAL_CHARSTRING::log() const
868 if (val_ptr
!= NULL
) {
869 expstring_t buffer
= 0;
870 enum { INIT
, PCHAR
, UCHAR
} state
= INIT
;
871 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
872 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
873 if (is_printable(uchar
)) {
874 // the actual character is printable
876 case UCHAR
: // concatenation sign if previous part was not printable
877 buffer
= mputstr(buffer
, " & ");
879 case INIT
: // opening "
880 buffer
= mputc(buffer
, '"');
882 case PCHAR
: // the character itself
883 TTCN_Logger::log_char_escaped(uchar
.uc_cell
, buffer
);
888 // the actual character is not printable
890 case PCHAR
: // closing " if previous part was printable
891 buffer
= mputc(buffer
, '"');
893 case UCHAR
: // concatenation sign
894 buffer
= mputstr(buffer
, " & ");
896 case INIT
: // the character itself
897 buffer
= mputprintf(buffer
, "char(%u, %u, %u, %u)",
898 uchar
.uc_group
, uchar
.uc_plane
, uchar
.uc_row
, uchar
.uc_cell
);
906 case INIT
: // the string was empty
907 buffer
= mputstr(buffer
, "\"\"");
909 case PCHAR
: // last character was printable -> closing "
910 buffer
= mputc(buffer
, '"');
915 TTCN_Logger::log_event_str(buffer
);
918 TTCN_Logger::log_event_unbound();
922 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::from_UTF8_buffer(TTCN_Buffer
& p_buff
)
925 p_buff
.get_string(os
);
926 if ("UTF-8" == get_stringencoding(os
)) {
927 UNIVERSAL_CHARSTRING ret
;
928 ret
.decode_utf8(p_buff
.get_len(), p_buff
.get_data());
931 return UNIVERSAL_CHARSTRING(p_buff
.get_len(), (const char*)p_buff
.get_data());
935 void UNIVERSAL_CHARSTRING::set_param(Module_Param
& param
) {
936 param
.basic_check(Module_Param::BC_VALUE
|Module_Param::BC_LIST
, "universal charstring value");
938 switch (param
.get_type()) {
939 case Module_Param::MP_Charstring
: {
940 switch (param
.get_operation_type()) {
941 case Module_Param::OT_ASSIGN
:
944 case Module_Param::OT_CONCAT
: {
946 buff
.put_s(param
.get_string_size(), (unsigned char*)param
.get_string_data());
948 *this = *this + from_UTF8_buffer(buff
);
950 *this = from_UTF8_buffer(buff
);
954 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
957 case Module_Param::MP_Universal_Charstring
: {
958 switch (param
.get_operation_type()) {
959 case Module_Param::OT_ASSIGN
:
962 case Module_Param::OT_CONCAT
: {
963 const Module_Param_Universal_Charstring
* ucs_param
= dynamic_cast<const Module_Param_Universal_Charstring
*>(¶m
);
964 if (0 != ucs_param
) {
965 // The Module_Param_Universal_Charstring class also contains the positions
966 // of all characters added in quadruple form (in char(g,p,r,c) form)
967 // The strings between these positions need to be decoded if they are
968 // in UTF-8 format (the quad characters shouldn't be decoded).
969 int nof_quads
= ucs_param
->get_nof_quads();
970 universal_char
* uchars
= (universal_char
*)ucs_param
->get_string_data();
971 for (int i
= 0; i
< nof_quads
+ 1; ++i
) {
972 // Each iteration processes the string before a quad and the quad itself
973 // the last iteration processes the string after the last quad
974 // ex. "ccccccQccccccccQcccccccc" => 2 quads at positions 6 and 15
975 // iterations: <-1st-><--2nd--><--3rd->
976 int start_pos
= (i
== 0) ? 0 : ucs_param
->get_quad_pos(i
- 1) + 1;
977 int end_pos
= (i
== nof_quads
) ? ucs_param
->get_string_size() : ucs_param
->get_quad_pos(i
);
978 if (end_pos
> start_pos
) {
980 for (int j
= start_pos
; j
< end_pos
; ++j
) {
981 buff
.put_c(uchars
[j
].uc_cell
);
984 // Add the string before the quad character
985 *this = *this + from_UTF8_buffer(buff
);
987 *this = from_UTF8_buffer(buff
);
990 if (i
!= nof_quads
) {
991 // Add the quad character itself
993 *this = *this + uchars
[end_pos
];
995 *this = UNIVERSAL_CHARSTRING(uchars
[end_pos
]);
1000 // plan B (should never happen)
1002 *this = *this + UNIVERSAL_CHARSTRING(param
.get_string_size(), (universal_char
*)param
.get_string_data());
1004 init_struct(param
.get_string_size());
1005 memcpy(val_ptr
->uchars_ptr
, param
.get_string_data(), val_ptr
->n_uchars
* sizeof(universal_char
));
1010 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
1014 param
.type_error("universal charstring value");
1018 void UNIVERSAL_CHARSTRING::encode_text(Text_Buf
& text_buf
) const
1020 must_bound("Text encoder: Encoding an unbound universal charstring value.");
1022 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1023 text_buf
.push_int(val_ptr
->n_uchars
);
1024 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
1025 unsigned char buf
[4];
1026 buf
[0] = val_ptr
->uchars_ptr
[i
].uc_group
;
1027 buf
[1] = val_ptr
->uchars_ptr
[i
].uc_plane
;
1028 buf
[2] = val_ptr
->uchars_ptr
[i
].uc_row
;
1029 buf
[3] = val_ptr
->uchars_ptr
[i
].uc_cell
;
1030 text_buf
.push_raw(4, buf
);
1034 void UNIVERSAL_CHARSTRING::decode_text(Text_Buf
& text_buf
)
1036 int n_uchars
= text_buf
.pull_int().get_val();
1037 if (n_uchars
< 0) TTCN_error("Text decoder: Negative length was received "
1038 "for a universal charstring.");
1041 init_struct(n_uchars
);
1042 for (int i
= 0; i
< n_uchars
; i
++) {
1043 unsigned char buf
[4];
1044 text_buf
.pull_raw(4, buf
);
1045 val_ptr
->uchars_ptr
[i
].uc_group
= buf
[0];
1046 val_ptr
->uchars_ptr
[i
].uc_plane
= buf
[1];
1047 val_ptr
->uchars_ptr
[i
].uc_row
= buf
[2];
1048 val_ptr
->uchars_ptr
[i
].uc_cell
= buf
[3];
1052 void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t
& p_td
,
1053 TTCN_Buffer
& p_buf
, TTCN_EncDec::coding_t p_coding
, ...) const
1056 va_start(pvar
, p_coding
);
1058 case TTCN_EncDec::CT_BER
: {
1059 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
1060 unsigned BER_coding
=va_arg(pvar
, unsigned);
1061 BER_encode_chk_coding(BER_coding
);
1062 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
1063 tlv
->put_in_buffer(p_buf
);
1064 ASN_BER_TLV_t::destruct(tlv
);
1066 case TTCN_EncDec::CT_RAW
: {
1067 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
1068 TTCN_EncDec_ErrorContext::error_internal
1069 ("No RAW descriptor available for type '%s'.", p_td
.name
);
1071 case TTCN_EncDec::CT_XER
: {
1072 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
1073 unsigned XER_coding
=va_arg(pvar
, unsigned);
1074 switch (p_td
.asnbasetype
) {
1075 case TTCN_Typedescriptor_t::BMPSTRING
:
1076 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1077 XER_coding
|= XER_ESCAPE_ENTITIES
;
1079 default: // nothing to do
1082 XER_encode(*p_td
.xer
,p_buf
, XER_coding
, 0, 0);
1085 case TTCN_EncDec::CT_JSON
: {
1086 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
1088 TTCN_EncDec_ErrorContext::error_internal
1089 ("No JSON descriptor available for type '%s'.", p_td
.name
);
1090 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
1091 JSON_encode(p_td
, tok
);
1092 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
1095 TTCN_error("Unknown coding method requested to encode type '%s'",
1101 void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t
& p_td
,
1102 TTCN_Buffer
& p_buf
, TTCN_EncDec::coding_t p_coding
, ...)
1105 va_start(pvar
, p_coding
);
1107 case TTCN_EncDec::CT_BER
: {
1108 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
1109 unsigned L_form
=va_arg(pvar
, unsigned);
1111 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
1112 BER_decode_TLV(p_td
, tlv
, L_form
);
1113 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
1115 case TTCN_EncDec::CT_RAW
: {
1116 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
1117 TTCN_EncDec_ErrorContext::error_internal
1118 ("No RAW descriptor available for type '%s'.", p_td
.name
);
1120 case TTCN_EncDec::CT_XER
: {
1121 unsigned XER_coding
=va_arg(pvar
, unsigned);
1122 XmlReaderWrap
reader(p_buf
);
1123 int success
= reader
.Read();
1124 for (; success
==1; success
=reader
.Read()) {
1125 int type
= reader
.NodeType();
1126 if (type
==XML_READER_TYPE_ELEMENT
)
1129 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
1130 size_t bytes
= reader
.ByteConsumed();
1131 p_buf
.set_pos(bytes
);
1133 case TTCN_EncDec::CT_JSON
: {
1134 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
1136 TTCN_EncDec_ErrorContext::error_internal
1137 ("No JSON descriptor available for type '%s'.", p_td
.name
);
1138 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
1139 if(JSON_decode(p_td
, tok
, false)<0)
1140 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
1141 "Can not decode type '%s', because invalid or incomplete"
1142 " message was received"
1144 p_buf
.set_pos(tok
.get_buf_pos());
1147 TTCN_error("Unknown coding method requested to decode type '%s'",
1154 UNIVERSAL_CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
1155 unsigned p_coding
) const
1158 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1159 BER_chk_descr(p_td
);
1160 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
1163 switch(p_td
.asnbasetype
) {
1164 case TTCN_Typedescriptor_t::TELETEXSTRING
:
1165 buf
.put_os(TTCN_TeletexString_2_ISO2022(*this));
1167 case TTCN_Typedescriptor_t::VIDEOTEXSTRING
:
1168 buf
.put_os(TTCN_VideotexString_2_ISO2022(*this));
1170 case TTCN_Typedescriptor_t::GRAPHICSTRING
:
1171 buf
.put_os(TTCN_GraphicString_2_ISO2022(*this));
1173 case TTCN_Typedescriptor_t::GENERALSTRING
:
1174 buf
.put_os(TTCN_GeneralString_2_ISO2022(*this));
1176 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1177 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1178 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_group
);
1179 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_plane
);
1180 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_row
);
1181 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_cell
);
1184 case TTCN_Typedescriptor_t::BMPSTRING
:
1185 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1186 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_row
);
1187 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_cell
);
1190 case TTCN_Typedescriptor_t::UTF8STRING
:
1194 TTCN_EncDec_ErrorContext::error_internal
1195 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
1197 new_tlv
=BER_encode_TLV_OCTETSTRING
1198 (p_coding
, buf
.get_read_len(), buf
.get_read_data());
1200 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
1204 void UNIVERSAL_CHARSTRING::encode_utf8(TTCN_Buffer
& buf
, bool addBOM
/*= false*/) const
1213 buf
.put_s(cstr
.val_ptr
->n_chars
, (unsigned char*)cstr
.val_ptr
->chars_ptr
);
1214 // put_s avoids the check for boundness in put_cs
1217 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1218 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1219 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1220 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1221 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1222 if(g
==0x00 && p
<=0x1F) {
1224 if(r
==0x00 && c
<=0x7F) {
1230 buf
.put_c(0xC0|r
<<2|c
>>6);
1231 buf
.put_c(0x80|(c
&0x3F));
1235 buf
.put_c(0xE0|r
>>4);
1236 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1237 buf
.put_c(0x80|(c
&0x3F));
1242 buf
.put_c(0xF0|p
>>2);
1243 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1244 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1245 buf
.put_c(0x80|(c
&0x3F));
1251 buf
.put_c(0x80|p
>>2);
1252 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1253 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1254 buf
.put_c(0x80|(c
&0x3F));
1258 buf
.put_c(0xFC|g
>>6);
1259 buf
.put_c(0x80|(g
&0x3F));
1260 buf
.put_c(0x80|p
>>2);
1261 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1262 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1263 buf
.put_c(0x80|(c
&0x3F));
1269 void UNIVERSAL_CHARSTRING::encode_utf16(TTCN_Buffer
& buf
,
1270 CharCoding::CharCodingType expected_coding
) const
1274 switch (expected_coding
) {
1275 case CharCoding::UTF16
:
1276 case CharCoding::UTF16BE
:
1279 case CharCoding::UTF16LE
:
1283 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1284 "Unexpected coding type for UTF-16 encoding");
1287 buf
.put_c(isbig
? 0xFE : 0xFF);
1288 buf
.put_c(isbig
? 0xFF : 0xFE);
1291 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
1292 buf
.put_c(isbig
? 0 : cstr
.val_ptr
->chars_ptr
[i
]);
1293 buf
.put_c(isbig
? cstr
.val_ptr
->chars_ptr
[i
] : 0);
1297 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1298 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1299 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1300 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1301 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1302 if (g
|| (0x10 < p
)) {
1303 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1304 "Any UCS code (0x%02X%02X%02X%02X) to be encoded into UTF-16 "
1305 "shall not be greater than 0x10FFFF", g
, p
, r
, c
);
1307 else if (0x00 == g
&& 0x00 ==p
&& 0xD8 <= r
&& 0xDF >= r
) {
1308 // Values between 0xD800 and 0xDFFF are specifically reserved for use with UTF-16,
1309 // and don't have any characters assigned to them.
1310 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1311 "Any UCS code (0x%02X%02X) between 0xD800 and 0xDFFF is ill-formed", r
,c
);
1313 else if (0x00 == g
&& 0x00 == p
) {
1314 buf
.put_c(isbig
? r
: c
);
1315 buf
.put_c(isbig
? c
: r
);
1317 else if (g
|| p
) { // greater than 0xFFFF it needs surrogates
1318 uint32_t univc
= 0, temp
= 0;
1328 univc
|= c
; // universal char filled in univc
1329 uint16_t W1
= 0xD800;
1330 uint16_t W2
= 0xDC00;
1331 uint32_t univcmod
= univc
- 0x10000;
1332 uint16_t WH
= univcmod
>> 10;
1333 uint16_t WL
= univcmod
& 0x3ff;
1337 uc
= isbig
? W1
>> 8 : W1
;
1339 uc
= isbig
? W1
: W1
>> 8;
1341 uc
= isbig
? W2
>> 8 : W2
;
1343 uc
= isbig
? W2
: W2
>> 8;
1350 void UNIVERSAL_CHARSTRING::encode_utf32(TTCN_Buffer
& buf
,
1351 CharCoding::CharCodingType expected_coding
) const
1354 switch (expected_coding
) {
1355 case CharCoding::UTF32
:
1356 case CharCoding::UTF32BE
:
1359 case CharCoding::UTF32LE
:
1363 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1364 "Unexpected coding type for UTF-32 encoding");
1368 buf
.put_c(isbig
? 0x00 : 0xFF);
1369 buf
.put_c(isbig
? 0x00 : 0xFE);
1370 buf
.put_c(isbig
? 0xFE : 0x00);
1371 buf
.put_c(isbig
? 0xFF : 0x00);
1374 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
1375 buf
.put_c(isbig
? 0 : cstr
.val_ptr
->chars_ptr
[i
]);
1378 buf
.put_c(isbig
? cstr
.val_ptr
->chars_ptr
[i
] : 0);
1382 for(int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1383 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1384 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1385 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1386 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1387 uint32_t DW
= g
<< 8 | p
;
1392 if (0x0000D800 <= DW
&& 0x0000DFFF >= DW
) {
1393 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1394 "Any UCS code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW
);
1396 else if (0x0010FFFF < DW
) {
1397 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1398 "Any UCS code (0x%08X) greater than 0x0010FFFF is ill-formed", DW
);
1401 buf
.put_c(isbig
? g
: c
);
1402 buf
.put_c(isbig
? p
: r
);
1403 buf
.put_c(isbig
? r
: p
);
1404 buf
.put_c(isbig
? c
: g
);
1410 #ifdef TITAN_RUNTIME_2
1412 int UNIVERSAL_CHARSTRING::encode_raw(TTCN_Buffer
& p_buf
) const
1414 size_t len_before
= p_buf
.get_len();
1416 return p_buf
.get_len() - len_before
;
1421 boolean
UNIVERSAL_CHARSTRING::BER_decode_TLV
1422 (const TTCN_Typedescriptor_t
& p_td
, const ASN_BER_TLV_t
& p_tlv
,
1427 TTCN_EncDec_ErrorContext
ec("While decoding universal charstring type: ");
1429 if(!ostr
.BER_decode_TLV(p_td
, p_tlv
, L_form
)) return FALSE
;
1430 int os_len
=ostr
.lengthof();
1432 const unsigned char* os
=ostr
;
1433 switch(p_td
.asnbasetype
) {
1434 case TTCN_Typedescriptor_t::TELETEXSTRING
:
1435 *this=TTCN_ISO2022_2_TeletexString(ostr
);
1437 case TTCN_Typedescriptor_t::VIDEOTEXSTRING
:
1438 *this=TTCN_ISO2022_2_VideotexString(ostr
);
1440 case TTCN_Typedescriptor_t::GRAPHICSTRING
:
1441 *this=TTCN_ISO2022_2_GraphicString(ostr
);
1443 case TTCN_Typedescriptor_t::GENERALSTRING
:
1444 *this=TTCN_ISO2022_2_GeneralString(ostr
);
1446 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1448 TTCN_EncDec_ErrorContext::error
1449 (TTCN_EncDec::ET_DEC_UCSTR
, "Length of UCS-4-coded character"
1450 " string is not multiple of 4.");
1452 init_struct(ucs_len
);
1453 for(int i
=0; i
<ucs_len
; i
++) {
1454 val_ptr
->uchars_ptr
[i
].uc_group
=os
[0];
1455 val_ptr
->uchars_ptr
[i
].uc_plane
=os
[1];
1456 val_ptr
->uchars_ptr
[i
].uc_row
=os
[2];
1457 val_ptr
->uchars_ptr
[i
].uc_cell
=os
[3];
1461 case TTCN_Typedescriptor_t::BMPSTRING
:
1463 TTCN_EncDec_ErrorContext::error
1464 (TTCN_EncDec::ET_DEC_UCSTR
, "Length of UCS-2-coded character"
1465 " string is not multiple of 2.");
1467 init_struct(ucs_len
);
1468 for(int i
=0; i
<ucs_len
; i
++) {
1469 val_ptr
->uchars_ptr
[i
].uc_group
=0;
1470 val_ptr
->uchars_ptr
[i
].uc_plane
=0;
1471 val_ptr
->uchars_ptr
[i
].uc_row
=os
[0];
1472 val_ptr
->uchars_ptr
[i
].uc_cell
=os
[1];
1476 case TTCN_Typedescriptor_t::UTF8STRING
:
1477 decode_utf8(os_len
, os
);
1480 TTCN_EncDec_ErrorContext::error_internal
1481 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
1486 extern void xml_escape(const unsigned int c
, TTCN_Buffer
& p_buf
);
1488 int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t
& p_td
,
1489 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
1492 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1493 "Encoding an unbound UNIVERSAL CHARSTRING value.");
1496 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1497 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
1498 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1499 int encoded_length
=(int)p_buf
.get_len();
1500 bool do_empty_element
= val_ptr
==NULL
|| val_ptr
->n_uchars
== 0;
1502 flavor
&= ~XER_RECOF
; // universal charstring doesn't care
1503 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) {
1504 if (!is_canonical(flavor
)) {
1505 // Although ANY_ELEMENT is not canonical, this flag is still used to disable
1506 // indenting in a record/set with EMBED_VALUES
1507 do_indent(p_buf
, indent
);
1511 if (do_empty_element
&& exer
&& p_td
.dfeValue
!= 0) {
1512 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR
,
1513 "An encoded value with DEFAULT-FOR-EMPTY instruction "
1514 "applied should not be empty");
1516 if (begin_xml(p_td
, p_buf
, flavor
, indent
, do_empty_element
) == -1) {
1519 } // not any_element
1521 #define UCH(c) {0,0,0,c}
1522 if (!do_empty_element
) {
1523 if (flavor
& XER_ESCAPE_ENTITIES
) {
1524 for (int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1525 unsigned int ucs4
= unichar2int(val_ptr
->uchars_ptr
[i
]);
1526 xml_escape( ucs4
, p_buf
);
1529 else { // UTF-8 needs only to escape the low 32 and these five: <&>
1530 TTCN_Buffer other_buf
;
1531 static const universal_char amp
[] = { UCH('&'), UCH('a'), UCH('m'),
1532 UCH('p'), UCH(';') };
1533 static const universal_char lt
[] = { UCH('&'), UCH('l'), UCH('t'),
1535 static const universal_char gt
[] = { UCH('&'), UCH('g'), UCH('t'),
1537 static const universal_char apos
[]= { UCH('&'), UCH('a'), UCH('p'),
1538 UCH('o'), UCH('s'), UCH(';') };
1539 static const universal_char quot
[]= { UCH('&'), UCH('q'), UCH('u'),
1540 UCH('o'), UCH('t'), UCH(';') };
1542 static const universal_char escapes
[32][6] = {
1543 {UCH('<'), UCH('n'), UCH('u'), UCH('l'), UCH('/'), UCH('>')},
1544 {UCH('<'), UCH('s'), UCH('o'), UCH('h'), UCH('/'), UCH('>')},
1545 {UCH('<'), UCH('s'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1546 {UCH('<'), UCH('e'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1547 {UCH('<'), UCH('e'), UCH('o'), UCH('t'), UCH('/'), UCH('>')},
1548 {UCH('<'), UCH('e'), UCH('n'), UCH('q'), UCH('/'), UCH('>')},
1549 {UCH('<'), UCH('a'), UCH('c'), UCH('k'), UCH('/'), UCH('>')},
1550 {UCH('<'), UCH('b'), UCH('e'), UCH('l'), UCH('/'), UCH('>')},
1552 {UCH('<'), UCH('b'), UCH('s'), UCH('/'), UCH('>')},
1553 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('9'), UCH(';')}, // TAB
1554 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('A'), UCH(';')}, // LF
1555 {UCH('<'), UCH('v'), UCH('t'), UCH('/'), UCH('>')},
1556 {UCH('<'), UCH('f'), UCH('f'), UCH('/'), UCH('>')},
1557 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('D'), UCH(';')}, // CR
1558 {UCH('<'), UCH('s'), UCH('o'), UCH('/'), UCH('>')},
1559 {UCH('<'), UCH('s'), UCH('i'), UCH('/'), UCH('>')},
1561 {UCH('<'), UCH('d'), UCH('l'), UCH('e'), UCH('/'), UCH('>')},
1562 {UCH('<'), UCH('d'), UCH('c'), UCH('1'), UCH('/'), UCH('>')},
1563 {UCH('<'), UCH('d'), UCH('c'), UCH('2'), UCH('/'), UCH('>')},
1564 {UCH('<'), UCH('d'), UCH('c'), UCH('3'), UCH('/'), UCH('>')},
1565 {UCH('<'), UCH('d'), UCH('c'), UCH('4'), UCH('/'), UCH('>')},
1566 {UCH('<'), UCH('n'), UCH('a'), UCH('k'), UCH('/'), UCH('>')},
1567 {UCH('<'), UCH('s'), UCH('y'), UCH('n'), UCH('/'), UCH('>')},
1568 {UCH('<'), UCH('e'), UCH('t'), UCH('b'), UCH('/'), UCH('>')},
1570 {UCH('<'), UCH('c'), UCH('a'), UCH('n'), UCH('/'), UCH('>')},
1571 {UCH('<'), UCH('e'), UCH('m'), UCH('/'), UCH('>')},
1572 {UCH('<'), UCH('s'), UCH('u'), UCH('b'), UCH('/'), UCH('>')},
1573 {UCH('<'), UCH('e'), UCH('s'), UCH('c'), UCH('/'), UCH('>')},
1574 {UCH('<'), UCH('i'), UCH('s'), UCH('4'), UCH('/'), UCH('>')},
1575 {UCH('<'), UCH('i'), UCH('s'), UCH('3'), UCH('/'), UCH('>')},
1576 {UCH('<'), UCH('i'), UCH('s'), UCH('2'), UCH('/'), UCH('>')},
1577 {UCH('<'), UCH('i'), UCH('s'), UCH('1'), UCH('/'), UCH('>')}
1580 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) { // no escaping
1581 TTCN_EncDec_ErrorContext
ec("While checking anyElement: ");
1582 encode_utf8(other_buf
);
1583 XmlReaderWrap
checker(other_buf
);
1584 // Walk through the XML. If it's not well-formed, XmlReaderWrap
1585 // will call TTCN_error => Dynamic testcase error.
1586 while (1 == checker
.Read()) {
1587 if (checker
.NodeType() == XML_READER_TYPE_ELEMENT
&&
1588 (p_td
.xer_bits
& (ANY_FROM
| ANY_EXCEPT
))) {
1589 const char* xmlns
= (const char*)checker
.NamespaceUri();
1590 check_namespace_restrictions(p_td
, xmlns
);
1594 // other_buf is already UTF-8, just append it
1595 p_buf
.put_buf(other_buf
);
1597 else if (flavor
& ANY_ATTRIBUTES
) { // no escaping
1598 encode_utf8(other_buf
);
1599 p_buf
.put_buf(other_buf
);
1602 for (int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1603 int char_val
= unichar2int(val_ptr
->uchars_ptr
[i
]);
1604 size_t len
= 6; // 3 letters + the surrounding '<', '/' and '>'
1607 other_buf
.put_s(20, &(amp
[0].uc_group
));
1611 other_buf
.put_s(16, &(lt
[0].uc_group
));
1615 other_buf
.put_s(16, &(gt
[0].uc_group
));
1618 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1619 // so if they appear in content they must be escaped.
1620 // Currently this happens even if the string is not an attribute.
1621 other_buf
.put_s(24, &(apos
[0].uc_group
));
1624 case '\"': // HR58225
1625 other_buf
.put_s(24, &(quot
[0].uc_group
));
1628 case 8: case 11: case 12: case 14: case 15: case 25:
1629 // the name of these control characters has only two letters
1632 case 0: case 1: case 2: case 3: case 4: case 5: case 6:
1633 case 7: case 16: case 17: case 18: case 19: case 20: case 21:
1634 case 22: case 23: case 24: case 26: case 27: case 28: case 29:
1636 other_buf
.put_s(len
* 4, &(escapes
[char_val
][0].uc_group
));
1639 case 9: case 10: case 13:
1640 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1641 // X.693 20.3.15: TAB,LF,CR also needs to be escaped in ATTRIBUTE
1642 other_buf
.put_s(24, &(escapes
[char_val
][0].uc_group
));
1644 } // else fall through
1647 other_buf
.put_s(4, &(val_ptr
->uchars_ptr
[i
].uc_group
));
1651 // other_buf contains UCS-4, need to encode it
1652 UNIVERSAL_CHARSTRING cs
;
1653 other_buf
.get_string(cs
);
1654 (cs
).encode_utf8(p_buf
);
1655 } // not any_element
1656 } // if ESCAPE_ENTITIES
1658 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
) && !is_canonical(flavor
)) {
1663 end_xml(p_td
, p_buf
, flavor
, indent
, do_empty_element
);
1665 return (int)p_buf
.get_len() - encoded_length
;
1668 /* Hashing for xmlcstring representation of control characters.
1669 * This function was generated by gperf 3.0.3
1670 * (GNU perfect hash function generator) from the list of control character
1671 * names, one per line, like this:
1678 * See the ASN.1 standard, X.680/2002, clause 11.15.5
1682 hash (register const char *str
, register unsigned int len
)
1684 static unsigned char asso_values
[] =
1686 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1687 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1688 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1689 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1690 104, 104, 104, 104, 104, 104, 104, 104, 104, 1,
1691 60, 55, 45, 104, 104, 104, 104, 104, 104, 104,
1692 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1693 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1694 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1695 104, 104, 104, 104, 104, 104, 104, 10, 10, 50,
1696 40, 15, 0, 104, 6, 15, 104, 1, 5, 10,
1697 0, 20, 104, 15, 0, 0, 30, 104, 0, 104,
1698 20, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1699 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1700 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1701 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1702 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1703 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1704 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1705 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1706 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1707 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1708 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1709 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1710 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1711 104, 104, 104, 104, 104, 104
1713 return len
+ asso_values
[(unsigned char)str
[len
- 1]] +
1714 asso_values
[(unsigned char)str
[0]];
1717 /* This function was also generated by gperf and hand-edited afterwards.
1718 * The original wordlist[] was an array of strings containing the names of
1719 * the control characters, with empty strings as fillers. These have been
1720 * replaced with the actual numerical values of the control characters,
1721 * with -1 as the filler.
1725 in_word_set (const char *str
, unsigned int len
)
1727 static char wordlist
[] =
1774 -1, -1, -1, -1, -1, -1, -1, -1, -1,
1776 -1, -1, -1, -1, -1, -1, -1, -1, -1,
1781 #define MIN_WORD_LENGTH 2
1782 #define MAX_WORD_LENGTH 3
1783 #define MIN_HASH_VALUE 2
1784 #define MAX_HASH_VALUE 103
1786 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
1788 register int key
= hash (str
, len
);
1790 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
1792 register const char s
= wordlist
[key
];
1799 universal_char
const uspace
= {0,0,0,32};
1801 int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t
& p_td
,
1802 XmlReaderWrap
& reader
, unsigned int flavor
, embed_values_dec_struct_t
*)
1804 int exer
= is_exer(flavor
);
1805 int success
= reader
.Ok(), depth
= -1;
1806 bool omit_tag
= exer
1807 && ((p_td
.xer_bits
& UNTAGGED
)
1808 || (flavor
& (EMBED_VALUES
|XER_LIST
|USE_TYPE_ATTR
|ANY_ATTRIBUTES
|USE_NIL
)));
1810 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) {
1811 TTCN_EncDec_ErrorContext
ec("While checking anyElement: ");
1812 for (; success
== 1; success
= reader
.Read()) {
1813 int type
= reader
.NodeType();
1814 if (-1 == depth
&& XML_READER_TYPE_ELEMENT
== type
) {
1815 xmlChar
* value
= reader
.ReadOuterXml();
1816 size_t num_chars
= strlen((const char*)value
);
1819 decode_utf8(num_chars
, value
); // does init_struct
1822 if (p_td
.xer_bits
& (ANY_FROM
| ANY_EXCEPT
)) {
1823 const char* xmlns
= (const char*)reader
.NamespaceUri();
1824 check_namespace_restrictions(p_td
, xmlns
);
1827 if (reader
.IsEmptyElement()) {
1828 reader
.Read(); // skip past the empty element and we're done
1831 depth
= reader
.Depth(); // signals that we have the element's text
1832 // Stay in the loop until we reach the corresponding end tag
1834 else if (reader
.Depth() == depth
&& XML_READER_TYPE_END_ELEMENT
== type
) {
1835 reader
.Read(); // one last time
1839 // ANY-ELEMENT and WHITESPACE are mutually exclusive,
1840 // so this branch skips WHITESPACE processing
1842 else { // not ANY-ELEMENT
1843 clean_up(); // start with a clean slate
1845 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1846 // we have it easy (but does decode_utf8 handle &nnn; ?)
1847 const char * name
= verify_name(reader
, p_td
, exer
);
1849 const char * value
= (const char *)reader
.Value();
1850 int len
= strlen(value
);
1851 decode_utf8(len
, (cbyte
*)value
);
1853 // Let the caller do reader.AdvanceAttribute();
1855 else { // not an attribute either
1856 // Get to the start of data.
1857 if (!omit_tag
) for (; success
== 1; success
= reader
.Read()) {
1858 int type
= reader
.NodeType();
1859 if (XML_READER_TYPE_ELEMENT
== type
) {
1860 verify_name(reader
, p_td
, exer
);
1861 if (reader
.IsEmptyElement()) {
1862 if (exer
&& p_td
.dfeValue
!= 0) {
1863 *this = *static_cast<const UNIVERSAL_CHARSTRING
*>(p_td
.dfeValue
);
1865 else init_struct(0); // it's an empty string
1866 reader
.Read(); // move on
1869 depth
= reader
.Depth();
1870 success
= reader
.Read();
1873 else if (XML_READER_TYPE_TEXT
== type
&& omit_tag
)
1875 else // if XML_READER_TYPE_END_ELEMENT, panic?
1880 TTCN_Buffer accumulator
;
1881 if (flavor
& PARENT_CLOSED
) {} // do nothing
1882 else for (; success
==1; success
= reader
.Read()) {
1883 int type
= reader
.NodeType();
1885 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE
:
1886 case XML_READER_TYPE_TEXT
:
1887 case XML_READER_TYPE_CDATA
: {
1888 const char * text
= (const char*)reader
.Value();
1889 int len
= strlen(text
);
1890 accumulator
.put_s(len
, (cbyte
*)text
);
1893 case XML_READER_TYPE_ELEMENT
: { // escaped control character
1894 const char * name
= (const char*)reader
.LocalName();
1895 size_t len
= strlen(name
);
1896 char ctrl
= in_word_set(name
, len
);
1898 accumulator
.put_c(ctrl
);
1901 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1902 "Invalid escape sequence '<%s/>'", name
);
1906 case XML_READER_TYPE_END_ELEMENT
: {
1907 decode_utf8(accumulator
.get_len(), accumulator
.get_data());
1909 verify_end(reader
, p_td
, depth
, exer
);
1910 reader
.Read(); // Moved to a different XML node!
1911 if (val_ptr
->n_uchars
== 0 && exer
&& p_td
.dfeValue
!= 0) {
1912 // This should be the <foo></foo> case. Treat it like <foo/>
1913 *this = *static_cast<const UNIVERSAL_CHARSTRING
*>(p_td
.dfeValue
);
1916 goto fini
; } // double "break" of switch and for loop
1922 } // endif (attribute)
1924 if (exer
&& p_td
.whitespace
>= WHITESPACE_REPLACE
) { // includes _COLLAPSE
1925 for(int i
=0; i
<val_ptr
->n_uchars
; ++i
) { // first, _REPLACE
1926 switch ( unichar2int(val_ptr
->uchars_ptr
[i
]) ) {
1927 case 9: // HORIZONTAL TAB
1928 case 10: // LINE FEED
1929 case 13: // CARRIAGE RETURN
1930 val_ptr
->uchars_ptr
[i
] = uspace
;
1937 if (p_td
.whitespace
>= WHITESPACE_COLLAPSE
) {
1939 const universal_char
*from
, *end
=
1940 val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
;
1941 for (from
= to
= val_ptr
->uchars_ptr
; from
< end
;) {
1943 // If the copied character (*to) was a space,
1944 // and the next character to be copied (*from) is also a space
1945 // (continuous run of spaces)
1946 // or this was the first character (leading spaces to be trimmed),
1947 // then don't advance the destination (will be overwritten).
1949 || (from
< end
&& *from
!= uspace
&& to
> val_ptr
->uchars_ptr
))
1952 val_ptr
->n_uchars
= to
- val_ptr
->uchars_ptr
;
1955 } // not ANY_ELEMENT
1956 return 1; // decode successful
1959 char* UNIVERSAL_CHARSTRING::to_JSON_string(const TTCN_Buffer
& p_buf
) const
1961 const unsigned char* ustr
= p_buf
.get_data();
1962 const size_t ustr_len
= p_buf
.get_len();
1964 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
1965 char* json_str
= (char*)Malloc(ustr_len
+ 3);
1968 json_str
= mputc(json_str
, '\"');
1970 for (size_t i
= 0; i
< ustr_len
; ++i
) {
1971 // Increase the size of the buffer if it's not big enough to store the
1972 // characters remaining in the universal charstring
1975 json_str
= mputstrn(json_str
, "\\\\", 2);
1978 json_str
= mputstrn(json_str
, "\\n", 2);
1981 json_str
= mputstrn(json_str
, "\\t", 2);
1984 json_str
= mputstrn(json_str
, "\\r", 2);
1987 json_str
= mputstrn(json_str
, "\\f", 2);
1990 json_str
= mputstrn(json_str
, "\\b", 2);
1993 json_str
= mputstrn(json_str
, "\\\"", 2);
1996 json_str
= mputc(json_str
, (char)ustr
[i
]);
2001 json_str
= mputc(json_str
, '\"');
2005 boolean
UNIVERSAL_CHARSTRING::from_JSON_string(boolean check_quotes
)
2007 int json_len
= val_ptr
->n_uchars
;
2008 universal_char
* json_str
= val_ptr
->uchars_ptr
;
2015 if (!json_str
[0].is_char() || json_str
[0].uc_cell
!= '\"' ||
2016 !json_str
[json_len
- 1].is_char() || json_str
[json_len
- 1].uc_cell
!= '\"') {
2021 // The resulting string will be shorter than the JSON string, at least by the 2 quotes
2022 universal_char
* ustr
= (universal_char
*)Malloc((json_len
- 2) * sizeof(universal_char
));
2023 memset(ustr
, 0, sizeof(universal_char
) * (json_len
- 2));
2025 boolean error
= false;
2027 for (int i
= start
; i
< end
; ++i
) {
2028 if (json_str
[i
].is_char() && '\\' == json_str
[i
].uc_cell
) {
2029 if (i
== end
- 1 || !json_str
[i
+ 1].is_char()) {
2033 switch(json_str
[i
+ 1].uc_cell
) {
2035 ustr
[ustr_len
++].uc_cell
= '\n';
2038 ustr
[ustr_len
++].uc_cell
= '\t';
2041 ustr
[ustr_len
++].uc_cell
= '\r';
2044 ustr
[ustr_len
++].uc_cell
= '\f';
2047 ustr
[ustr_len
++].uc_cell
= '\b';
2050 ustr
[ustr_len
++].uc_cell
= '\\';
2053 ustr
[ustr_len
++].uc_cell
= '\"';
2056 ustr
[ustr_len
++].uc_cell
= '/';
2059 if (end
- i
>= 6 && json_str
[i
+ 2].is_char() && json_str
[i
+ 3].is_char() &&
2060 json_str
[i
+ 4].is_char() && json_str
[i
+ 5].is_char()) {
2061 unsigned char row_upper_nibble
= char_to_hexdigit(json_str
[i
+ 2].uc_cell
);
2062 unsigned char row_lower_nibble
= char_to_hexdigit(json_str
[i
+ 3].uc_cell
);
2063 unsigned char cell_upper_nibble
= char_to_hexdigit(json_str
[i
+ 4].uc_cell
);
2064 unsigned char cell_lower_nibble
= char_to_hexdigit(json_str
[i
+ 5].uc_cell
);
2065 if (row_upper_nibble
<= 0x0F && row_lower_nibble
<= 0x0F &&
2066 cell_upper_nibble
<= 0x0F && cell_lower_nibble
<= 0x0F) {
2067 ustr
[ustr_len
].uc_row
= (row_upper_nibble
<< 4) | row_lower_nibble
;
2068 ustr
[ustr_len
++].uc_cell
= (cell_upper_nibble
<< 4) | cell_lower_nibble
;
2069 // skip 4 extra characters (the 4 hex digits)
2072 // error (encountered something other than a hex digit) -> leave the for cycle
2077 // error (not enough characters or the 'hex digits' are not even ascii characters) -> leave the for cycle
2084 // error (invalid escaped character) -> leave the for cycle
2089 // skip an extra character (the \)
2092 ustr
[ustr_len
++] = json_str
[i
];
2095 if (check_quotes
&& i
== json_len
- 1) {
2096 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
2103 init_struct(ustr_len
);
2104 memcpy(val_ptr
->uchars_ptr
, ustr
, ustr_len
* sizeof(universal_char
));
2110 int UNIVERSAL_CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
) const
2113 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
2114 "Encoding an unbound universal charstring value.");
2120 tmp_str
= cstr
.to_JSON_string();
2122 TTCN_Buffer tmp_buf
;
2123 encode_utf8(tmp_buf
);
2124 tmp_str
= to_JSON_string(tmp_buf
);
2126 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
2131 int UNIVERSAL_CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
2133 json_token_t token
= JSON_TOKEN_NONE
;
2135 size_t value_len
= 0;
2137 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
2139 // No JSON data in the buffer -> use default value
2140 value
= (char*)p_td
.json
->default_value
;
2141 value_len
= strlen(value
);
2143 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
2145 if (JSON_TOKEN_ERROR
== token
) {
2146 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
2147 return JSON_ERROR_FATAL
;
2149 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
2150 if (cstr
.from_JSON_string(value
, value_len
, !use_default
)) {
2155 decode_utf8(value_len
, (unsigned char*)value
);
2156 if (!from_JSON_string(!use_default
)) {
2157 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "universal charstring");
2161 return JSON_ERROR_FATAL
;
2165 return JSON_ERROR_INVALID_TOKEN
;
2171 static void fill_continuing_octets(int n_continuing
,
2172 unsigned char *continuing_ptr
, int n_octets
,
2173 const unsigned char *octets_ptr
, int start_pos
, int uchar_pos
)
2175 for (int i
= 0; i
< n_continuing
; i
++) {
2176 if (start_pos
+ i
< n_octets
) {
2177 unsigned char octet
= octets_ptr
[start_pos
+ i
];
2178 if ((octet
& 0xC0) != 0x80) {
2179 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2180 "Malformed: At character position %d, octet position %d: %02X is "
2181 "not a valid continuing octet.", uchar_pos
, start_pos
+ i
, octet
);
2183 continuing_ptr
[i
] = octet
& 0x3F;
2185 if (start_pos
+ i
== n_octets
) {
2187 // only a part of octets is missing
2188 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2189 "Incomplete: At character position %d, octet position %d: %d out "
2190 "of %d continuing octets %s missing from the end of the stream.",
2191 uchar_pos
, start_pos
+ i
, n_continuing
- i
, n_continuing
,
2192 n_continuing
- i
> 1 ? "are" : "is");
2194 // all octets are missing
2195 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2196 "Incomplete: At character position %d, octet position %d: %d "
2197 "continuing octet%s missing from the end of the stream.", uchar_pos
,
2198 start_pos
, n_continuing
, n_continuing
> 1 ? "s are" : " is");
2201 continuing_ptr
[i
] = 0;
2206 void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets
,
2207 const unsigned char *octets_ptr
,
2208 CharCoding::CharCodingType expected_coding
/*= UTF8*/,
2209 bool checkBOM
/*= false)*/)
2211 // approximate the number of characters
2213 for (int i
= 0; i
< n_octets
; i
++) {
2214 // count all octets except the continuing octets (10xxxxxx)
2215 if ((octets_ptr
[i
] & 0xC0) != 0x80) n_uchars
++;
2217 // allocate enough memory
2218 init_struct(n_uchars
);
2221 int start
= checkBOM
? check_BOM(CharCoding::UTF_8
, sizeof(octets_ptr
), octets_ptr
) : 0;
2222 for (int i
= start
; i
< n_octets
; ) {
2223 // perform the decoding character by character
2224 if (octets_ptr
[i
] <= 0x7F) {
2225 // character encoded on a single octet: 0xxxxxxx (7 useful bits)
2226 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2227 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2228 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= 0;
2229 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[i
];
2232 } else if (octets_ptr
[i
] <= 0xBF) {
2233 // continuing octet (10xxxxxx) without leading octet ==> malformed
2234 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2235 "Malformed: At character position %d, octet position %d: continuing "
2236 "octet %02X without leading octet.", n_uchars
, i
, octets_ptr
[i
]);
2238 } else if (octets_ptr
[i
] <= 0xDF) {
2239 // character encoded on 2 octets: 110xxxxx 10xxxxxx (11 useful bits)
2240 unsigned char octets
[2];
2241 octets
[0] = octets_ptr
[i
] & 0x1F;
2242 fill_continuing_octets(1, octets
+ 1, n_octets
, octets_ptr
, i
+ 1, n_uchars
);
2243 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2244 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2245 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[0] >> 2;
2246 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[0] << 6 | octets
[1];
2247 if (val_ptr
->uchars_ptr
[n_uchars
].uc_row
== 0x00 &&
2248 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
< 0x80)
2249 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2250 "Overlong: At character position %d, octet position %d: 2-octet "
2251 "encoding for quadruple (0, 0, 0, %u).", n_uchars
, i
,
2252 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2255 } else if (octets_ptr
[i
] <= 0xEF) {
2256 // character encoded on 3 octets: 1110xxxx 10xxxxxx 10xxxxxx
2258 unsigned char octets
[3];
2259 octets
[0] = octets_ptr
[i
] & 0x0F;
2260 fill_continuing_octets(2, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2262 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2263 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2264 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[0] << 4 | octets
[1] >> 2;
2265 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[1] << 6 | octets
[2];
2266 if (val_ptr
->uchars_ptr
[n_uchars
].uc_row
< 0x08)
2267 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2268 "Overlong: At character position %d, octet position %d: 3-octet "
2269 "encoding for quadruple (0, 0, %u, %u).", n_uchars
, i
,
2270 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2271 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2274 } else if (octets_ptr
[i
] <= 0xF7) {
2275 // character encoded on 4 octets: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2277 unsigned char octets
[4];
2278 octets
[0] = octets_ptr
[i
] & 0x07;
2279 fill_continuing_octets(3, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2281 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2282 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[0] << 2 | octets
[1] >> 4;
2283 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[1] << 4 | octets
[2] >> 2;
2284 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[2] << 6 | octets
[3];
2285 if (val_ptr
->uchars_ptr
[n_uchars
].uc_plane
== 0x00)
2286 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2287 "Overlong: At character position %d, octet position %d: 4-octet "
2288 "encoding for quadruple (0, 0, %u, %u).", n_uchars
, i
,
2289 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2290 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2293 } else if (octets_ptr
[i
] <= 0xFB) {
2294 // character encoded on 5 octets: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
2295 // 10xxxxxx (26 useful bits)
2296 unsigned char octets
[5];
2297 octets
[0] = octets_ptr
[i
] & 0x03;
2298 fill_continuing_octets(4, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2300 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets
[0];
2301 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[1] << 2 | octets
[2] >> 4;
2302 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[2] << 4 | octets
[3] >> 2;
2303 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[3] << 6 | octets
[4];
2304 if (val_ptr
->uchars_ptr
[n_uchars
].uc_group
== 0x00 &&
2305 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
< 0x20)
2306 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2307 "Overlong: At character position %d, octet position %d: 5-octet "
2308 "encoding for quadruple (0, %u, %u, %u).", n_uchars
, i
,
2309 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
,
2310 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2311 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2314 } else if (octets_ptr
[i
] <= 0xFD) {
2315 // character encoded on 6 octets: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx
2316 // 10xxxxxx 10xxxxxx (31 useful bits)
2317 unsigned char octets
[6];
2318 octets
[0] = octets_ptr
[i
] & 0x01;
2319 fill_continuing_octets(5, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2321 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets
[0] << 6 | octets
[1];
2322 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[2] << 2 | octets
[3] >> 4;
2323 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[3] << 4 | octets
[4] >> 2;
2324 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[4] << 6 | octets
[5];
2325 if (val_ptr
->uchars_ptr
[n_uchars
].uc_group
< 0x04)
2326 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2327 "Overlong: At character position %d, octet position %d: 6-octet "
2328 "encoding for quadruple (%u, %u, %u, %u).", n_uchars
, i
,
2329 val_ptr
->uchars_ptr
[n_uchars
].uc_group
,
2330 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
,
2331 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2332 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2336 // not used code points: FE and FF => malformed
2337 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2338 "Malformed: At character position %d, octet position %d: "
2339 "unused/reserved octet %02X.", n_uchars
, i
, octets_ptr
[i
]);
2343 if (val_ptr
->n_uchars
!= n_uchars
) {
2344 // truncate the memory and set the correct size in case of decoding errors
2345 // (e.g. skipped octets)
2347 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
,
2348 MEMORY_SIZE(n_uchars
));
2349 val_ptr
->n_uchars
= n_uchars
;
2357 void UNIVERSAL_CHARSTRING::decode_utf16(int n_octets
,
2358 const unsigned char *octets_ptr
,
2359 CharCoding::CharCodingType expected_coding
)
2361 if (n_octets
% 2 || 0 > n_octets
) {
2362 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2363 "Wrong UTF-16 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 2",
2366 int start
= check_BOM(expected_coding
, sizeof(octets_ptr
), octets_ptr
);
2367 int n_uchars
= n_octets
/2;
2368 init_struct(n_uchars
);
2371 switch (expected_coding
) {
2372 case CharCoding::UTF16
:
2373 case CharCoding::UTF16BE
:
2376 case CharCoding::UTF16LE
:
2380 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2381 "Unexpected coding type for UTF-16 encoding");
2384 for (int i
= start
; i
< n_octets
; i
+= 2 ) {
2385 int first
= isbig
? i
: i
+ 1;
2386 int second
= isbig
? i
+ 1 : i
;
2387 int third
= isbig
? i
+ 2 : i
+ 3;
2388 int fourth
= isbig
? i
+ 3 : i
+ 2;
2390 uint16_t W1
= octets_ptr
[first
] << 8 | octets_ptr
[second
];
2391 uint16_t W2
= (i
+ 3 < n_octets
) ? octets_ptr
[third
] << 8 | octets_ptr
[fourth
] : 0;
2393 if (0xD800 > W1
|| 0xDFFF < W1
) {
2394 //if W1 < 0xD800 or W1 > 0xDFFF, the character value is the value of W1
2395 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2396 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2397 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets_ptr
[first
];
2398 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[second
];
2401 else if (0xD800 > W1
|| 0xDBFF < W1
) {
2402 //Determine if W1 is between 0xD800 and 0xDBFF. If not, the sequence
2403 //is in error and no valid character can be obtained using W1.
2404 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2405 "The word (0x%04X) shall be between 0xD800 and 0xDBFF", W1
);
2407 else if (0 == W2
|| (0xDC00 > W2
|| 0xDFFF < W2
)) {
2408 //If there is no W2 (that is, the sequence ends with W1), or if W2
2409 //is not between 0xDC00 and 0xDFFF, the sequence is in error.
2411 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2412 "Wrong UTF-16 string. The word (0x%04X) shall be between 0xDC00 and 0xDFFF", W2
);
2414 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2415 "Wrong UTF-16 string. The decoding algorythm does not expect 0x00 or EOL");
2418 //Construct a 20-bit unsigned integer, taking the 10 low-order bits of W1 as its 10 high-
2419 //order bits and the 10 low-order bits of W2 as its 10 low-order bits.
2420 const uint16_t mask10bitlow
= 0x3FF;
2421 uint32_t DW
= (W1
& mask10bitlow
) << 10;
2422 DW
|= (W2
& mask10bitlow
);
2424 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2425 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= DW
>> 16;
2426 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= DW
>> 8;
2427 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= DW
;
2429 i
+= 2; // jump over w2 in octetstring
2432 if (val_ptr
->n_uchars
!= n_uchars
) {
2433 // truncate the memory and set the correct size in case of decoding errors
2434 // (e.g. skipped octets)
2436 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(n_uchars
));
2437 val_ptr
->n_uchars
= n_uchars
;
2446 void UNIVERSAL_CHARSTRING::decode_utf32(int n_octets
, const unsigned char *octets_ptr
,
2447 CharCoding::CharCodingType expected_coding
)
2449 if (n_octets
% 4 || 0 > n_octets
) {
2450 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2451 "Wrong UTF-32 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 4",
2454 int start
= check_BOM(expected_coding
, sizeof(octets_ptr
), octets_ptr
);
2455 int n_uchars
= n_octets
/4;
2456 init_struct(n_uchars
);
2459 switch (expected_coding
) {
2460 case CharCoding::UTF32
:
2461 case CharCoding::UTF32BE
:
2464 case CharCoding::UTF32LE
:
2468 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2469 "Unexpected coding type for UTF-32 encoding");
2472 for (int i
= start
; i
< n_octets
; i
+= 4 ) {
2473 int first
= isbig
? i
: i
+ 3;
2474 int second
= isbig
? i
+ 1 : i
+ 2;
2475 int third
= isbig
? i
+ 2 : i
+ 1;
2476 int fourth
= isbig
? i
+ 3 : i
;
2477 uint32_t DW
= octets_ptr
[first
] << 8 | octets_ptr
[second
];
2479 DW
|= octets_ptr
[third
];
2481 DW
|= octets_ptr
[fourth
];
2482 if (0x0000D800 <= DW
&& 0x0000DFFF >= DW
) {
2483 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2484 "Any UTF-32 code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW
);
2486 else if (0x0010FFFF < DW
) {
2487 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2488 "Any UTF-32 code (0x%08X) greater than 0x0010FFFF is ill-formed", DW
);
2491 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets_ptr
[first
];
2492 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets_ptr
[second
];
2493 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets_ptr
[third
];
2494 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[fourth
];
2498 if (val_ptr
->n_uchars
!= n_uchars
) {
2499 // truncate the memory and set the correct size in case of decoding errors
2500 // (e.g. skipped octets)
2502 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(n_uchars
));
2503 val_ptr
->n_uchars
= n_uchars
;
2511 int UNIVERSAL_CHARSTRING::check_BOM(CharCoding::CharCodingType expected_coding
,
2512 unsigned int length
,
2513 const unsigned char* ostr
)
2515 switch (expected_coding
) {
2516 case CharCoding::UTF32
:
2517 case CharCoding::UTF32BE
:
2518 case CharCoding::UTF32LE
:
2520 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2521 "The string is shorter than the expected BOM");
2524 case CharCoding::UTF16
:
2525 case CharCoding::UTF16BE
:
2526 case CharCoding::UTF16LE
:
2528 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2529 "The string is shorter than the expected BOM");
2532 case CharCoding::UTF_8
:
2534 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2535 "The string is shorter than the expected BOM");
2540 std::string coding_str
;
2541 //BOM indicates that the byte order is determined by a byte order mark,
2542 //if present at the beginning the length of BOM is returned.
2543 switch (expected_coding
) {
2544 case CharCoding::UTF32BE
:
2545 case CharCoding::UTF32
:
2546 if (0x00 == ostr
[0] && 0x00 == ostr
[1] && 0xFE == ostr
[2] && 0xFF == ostr
[3]) {
2549 coding_str
= "UTF-32BE";
2551 case CharCoding::UTF32LE
:
2552 if (0xFF == ostr
[0] && 0xFE == ostr
[1] && 0x00 == ostr
[2] && 0x00 == ostr
[3]) {
2555 coding_str
= "UTF-32LE";
2557 case CharCoding::UTF16BE
:
2558 case CharCoding::UTF16
:
2559 if (0xFE == ostr
[0] && 0xFF == ostr
[1]) {
2562 coding_str
= "UTF-16BE";
2564 case CharCoding::UTF16LE
:
2565 if (0xFF == ostr
[0] && 0xFE == ostr
[1]) {
2568 coding_str
= "UTF-16LE";
2570 case CharCoding::UTF_8
:
2571 if (0xEF == ostr
[0] && 0xBB == ostr
[1] && 0xBF == ostr
[2]) {
2574 coding_str
= "UTF-8";
2578 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2579 "Wrong %s string. No BOM detected, however the given coding type (%s) expects it to define the endianness",
2580 coding_str
.c_str(), coding_str
.c_str());
2583 TTCN_EncDec_ErrorContext::warning("No %s Byte Order Mark(BOM) detected. It may result decoding errors",
2584 coding_str
.c_str());
2588 // member functions of class UNIVERSAL_CHARSTRING_ELEMENTS
2590 UNIVERSAL_CHARSTRING_ELEMENT::UNIVERSAL_CHARSTRING_ELEMENT
2591 (boolean par_bound_flag
, UNIVERSAL_CHARSTRING
& par_str_val
,
2592 int par_uchar_pos
) :
2593 bound_flag(par_bound_flag
), str_val(par_str_val
), uchar_pos(par_uchar_pos
)
2598 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2599 (const universal_char
& other_value
)
2602 if (str_val
.charstring
) {
2603 if (other_value
.is_char()) {
2604 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
.uc_cell
;
2607 str_val
.convert_cstr_to_uni();
2609 str_val
.copy_value();
2610 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] = other_value
;
2614 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2615 (const char* other_value
)
2617 if (other_value
== NULL
|| other_value
[0] == '\0' || other_value
[1] != '\0')
2618 TTCN_error("Assignment of a charstring value with length other than 1 to "
2619 "a universal charstring element.");
2621 if (str_val
.charstring
)
2622 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
[0];
2624 str_val
.copy_value();
2625 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2626 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2627 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2628 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
= other_value
[0];
2633 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2634 (const CHARSTRING
& other_value
)
2636 other_value
.must_bound("Assignment of an unbound charstring value to a "
2637 "universal charstring element.");
2638 if(other_value
.val_ptr
->n_chars
!= 1)
2639 TTCN_error("Assignment of a charstring value with length other than 1 to "
2640 "a universal charstring element.");
2642 if (str_val
.charstring
)
2643 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] =
2644 other_value
.val_ptr
->chars_ptr
[0];
2646 str_val
.copy_value();
2647 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2648 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2649 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2650 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
=
2651 other_value
.val_ptr
->chars_ptr
[0];
2656 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2657 (const CHARSTRING_ELEMENT
& other_value
)
2659 other_value
.must_bound("Assignment of an unbound charstring element to a "
2660 "universal charstring element.");
2662 if (str_val
.charstring
)
2663 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
.get_char();
2665 str_val
.copy_value();
2666 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2667 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2668 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2669 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
= other_value
.get_char();
2674 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2675 (const UNIVERSAL_CHARSTRING
& other_value
)
2677 other_value
.must_bound("Assignment of an unbound universal charstring value "
2678 "to a universal charstring element.");
2679 if (other_value
.val_ptr
->n_uchars
!= 1)
2680 TTCN_error("Assignment of a universal charstring value with length other "
2681 "than 1 to a universal charstring element.");
2683 const universal_char
& uchar
= other_value
.val_ptr
->uchars_ptr
[0];
2684 if (str_val
.charstring
) {
2685 if (uchar
.is_char())
2686 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = uchar
.uc_cell
;
2688 str_val
.convert_cstr_to_uni();
2689 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] = uchar
;
2692 str_val
.copy_value();
2693 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] = uchar
;
2698 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2699 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
2701 other_value
.must_bound("Assignment of an unbound universal charstring "
2703 if (&other_value
!= this) {
2705 if (str_val
.charstring
) {
2706 if (other_value
.str_val
.charstring
)
2707 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] =
2708 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
2710 str_val
.convert_cstr_to_uni();
2711 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] =
2712 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
2715 if (other_value
.str_val
.charstring
) {
2716 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2717 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2718 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2719 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
=
2720 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
2722 str_val
.copy_value();
2723 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] =
2724 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
2731 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2732 (const universal_char
& other_value
) const
2734 must_bound("The left operand of comparison is an unbound universal "
2735 "charstring element.");
2736 if (str_val
.charstring
&& other_value
.is_char())
2737 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
.uc_cell
;
2738 if (str_val
.charstring
&& !other_value
.is_char())
2740 if (!str_val
.charstring
&& other_value
.is_char()) {
2741 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2742 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2743 uchar
.uc_cell
== other_value
.uc_cell
;
2745 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] == other_value
;
2748 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2749 (const char* other_value
) const
2751 must_bound("The left operand of comparison is an unbound universal "
2752 "charstring element.");
2753 if (other_value
== NULL
|| other_value
[0] == '\0' ||
2754 other_value
[1] != '\0') return FALSE
;
2755 if (str_val
.charstring
)
2756 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
[0];
2757 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2758 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2759 uchar
.uc_cell
== (cbyte
)other_value
[0];
2762 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2763 (const CHARSTRING
& other_value
) const
2765 must_bound("The left operand of comparison is an unbound universal "
2766 "charstring element.");
2767 other_value
.must_bound("The right operand of comparison is an unbound "
2768 "charstring value.");
2769 if (other_value
.val_ptr
->n_chars
!= 1) return FALSE
;
2770 if (str_val
.charstring
)
2771 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
2772 other_value
.val_ptr
->chars_ptr
[0];
2773 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2774 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2775 uchar
.uc_cell
== (cbyte
)other_value
.val_ptr
->chars_ptr
[0];
2778 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2779 (const CHARSTRING_ELEMENT
& other_value
) const
2781 must_bound("The left operand of comparison is an unbound universal "
2782 "charstring element.");
2783 other_value
.must_bound("The right operand of comparison is an unbound "
2784 "charstring element.");
2785 if (str_val
.charstring
)
2786 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
.get_char();
2787 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2788 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2789 uchar
.uc_cell
== (cbyte
)other_value
.get_char();
2792 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2793 (const UNIVERSAL_CHARSTRING
& other_value
) const
2795 must_bound("The left operand of comparison is an unbound universal "
2796 "charstring element.");
2797 other_value
.must_bound("The right operand of comparison is an unbound "
2798 "universal charstring value.");
2799 if (other_value
.charstring
) {
2800 if (other_value
.cstr
.val_ptr
->n_chars
!= 1)
2802 if (str_val
.charstring
)
2803 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
2804 other_value
.cstr
.val_ptr
->chars_ptr
[0];
2806 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2807 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0
2808 && uchar
.uc_cell
== (cbyte
)other_value
.cstr
.val_ptr
->chars_ptr
[0];
2811 if (other_value
.val_ptr
->n_uchars
!= 1)
2813 if (str_val
.charstring
) {
2814 const universal_char
& uchar
= other_value
.val_ptr
->uchars_ptr
[0];
2815 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2816 uchar
.uc_cell
== (cbyte
)str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2818 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] ==
2819 other_value
.val_ptr
->uchars_ptr
[0];
2823 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2824 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
2826 must_bound("The left operand of comparison is an unbound universal "
2827 "charstring element.");
2828 other_value
.must_bound("The right operand of comparison is an unbound "
2829 "universal charstring element.");
2830 if (str_val
.charstring
) {
2831 if (other_value
.str_val
.charstring
)
2832 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
2833 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
2835 const universal_char
& uchar
= other_value
.get_uchar();
2836 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2837 uchar
.uc_cell
== str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2840 if (other_value
.str_val
.charstring
) {
2841 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2842 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2844 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
2846 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] ==
2847 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
2851 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
2852 (const universal_char
& other_value
) const
2854 must_bound("The left operand of concatenation is an unbound universal "
2855 "charstring element.");
2856 if (str_val
.charstring
&& other_value
.is_char()) {
2857 UNIVERSAL_CHARSTRING
ret_val(2, true);
2858 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
2859 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2860 ret_val
.cstr
.val_ptr
->chars_ptr
[1] = other_value
.uc_cell
;
2862 } else if (str_val
.charstring
^ other_value
.is_char()) {
2863 universal_char result
[2];
2864 if (str_val
.charstring
) {
2865 result
[0].uc_group
= result
[0].uc_plane
= result
[0].uc_row
= 0;
2866 result
[0].uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2868 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2869 result
[1] = other_value
;
2870 return UNIVERSAL_CHARSTRING(2, result
);
2872 universal_char result
[2];
2873 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2874 result
[1] = other_value
;
2875 return UNIVERSAL_CHARSTRING(2, result
);
2878 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
2879 (const char* other_value
) const
2881 must_bound("The left operand of concatenation is an unbound universal "
2882 "charstring element.");
2884 if (other_value
== NULL
) other_len
= 0;
2885 else other_len
= strlen(other_value
);
2887 UNIVERSAL_CHARSTRING
ret_val(other_len
+ 1, str_val
.charstring
);
2888 if (str_val
.charstring
) {
2889 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
2890 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2891 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1, other_value
, other_len
);
2893 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2894 for (int i
= 0; i
< other_len
; i
++) {
2895 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_group
= 0;
2896 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_plane
= 0;
2897 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_row
= 0;
2898 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_cell
= other_value
[i
];
2904 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
2905 (const CHARSTRING
& other_value
) const
2907 must_bound("The left operand of concatenation is an unbound universal "
2908 "charstring element.");
2909 other_value
.must_bound("The right operand of concatenation is an unbound "
2910 "charstring value.");
2911 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_chars
+ 1,
2912 str_val
.charstring
);
2913 if (str_val
.charstring
) {
2914 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
2915 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2916 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1, other_value
.val_ptr
->chars_ptr
,
2917 other_value
.val_ptr
->n_chars
);
2919 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2920 for (int i
= 0; i
< other_value
.val_ptr
->n_chars
; i
++) {
2921 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_group
= 0;
2922 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_plane
= 0;
2923 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_row
= 0;
2924 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_cell
=
2925 other_value
.val_ptr
->chars_ptr
[i
];
2931 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
2932 (const CHARSTRING_ELEMENT
& other_value
) const
2934 must_bound("The left operand of concatenation is an unbound universal "
2935 "charstring element.");
2936 other_value
.must_bound("The right operand of concatenation is an unbound "
2937 "charstring element.");
2938 if (str_val
.charstring
) {
2939 UNIVERSAL_CHARSTRING
ret_val(2, true);
2940 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
2941 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2942 ret_val
.cstr
.val_ptr
->chars_ptr
[1] = other_value
.get_char();
2945 universal_char result
[2];
2946 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2947 result
[1].uc_group
= 0;
2948 result
[1].uc_plane
= 0;
2949 result
[1].uc_row
= 0;
2950 result
[1].uc_cell
= other_value
.get_char();
2951 return UNIVERSAL_CHARSTRING(2, result
);
2955 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
2956 (const UNIVERSAL_CHARSTRING
& other_value
) const
2958 must_bound("The left operand of concatenation is an unbound universal "
2959 "charstring element.");
2960 other_value
.must_bound("The right operand of concatenation is an unbound "
2961 "universal charstring value.");
2962 if (str_val
.charstring
) {
2963 if (other_value
.charstring
) {
2964 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1, true);
2965 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
2966 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2967 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1,
2968 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
2971 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
2972 universal_char
& uchar
= ret_val
.val_ptr
->uchars_ptr
[0];
2973 uchar
.uc_group
= uchar
.uc_plane
= uchar
.uc_row
= 0;
2974 uchar
.uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
2975 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
2976 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
2980 if (other_value
.charstring
) {
2981 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1);
2982 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2983 for (int i
= 1; i
<= other_value
.cstr
.val_ptr
->n_chars
; ++i
) {
2984 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
2985 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
2986 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
2987 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
=
2988 other_value
.cstr
.val_ptr
->chars_ptr
[i
-1];
2992 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
2993 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2994 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
2995 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3001 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3002 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
3004 must_bound("The left operand of concatenation is an unbound universal "
3005 "charstring element.");
3006 other_value
.must_bound("The right operand of concatenation is an unbound "
3007 "universal charstring element.");
3008 if (str_val
.charstring
) {
3009 if (other_value
.str_val
.charstring
) {
3010 UNIVERSAL_CHARSTRING
ret_val(2, true);
3011 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3012 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3013 ret_val
.cstr
.val_ptr
->chars_ptr
[1] =
3014 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3017 UNIVERSAL_CHARSTRING
ret_val(2);
3018 universal_char
& uchar
= ret_val
.val_ptr
->uchars_ptr
[0];
3019 uchar
.uc_group
= uchar
.uc_plane
= uchar
.uc_row
= 0;
3020 uchar
.uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3021 ret_val
.val_ptr
->uchars_ptr
[1] =
3022 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3026 if (other_value
.str_val
.charstring
) {
3027 UNIVERSAL_CHARSTRING
ret_val(2);
3028 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3029 ret_val
.val_ptr
->uchars_ptr
[1].uc_group
= 0;
3030 ret_val
.val_ptr
->uchars_ptr
[1].uc_plane
= 0;
3031 ret_val
.val_ptr
->uchars_ptr
[1].uc_row
= 0;
3032 ret_val
.val_ptr
->uchars_ptr
[1].uc_cell
=
3033 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3036 universal_char result
[2];
3037 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3038 result
[1] = other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3039 return UNIVERSAL_CHARSTRING(2, result
);
3044 const universal_char
& UNIVERSAL_CHARSTRING_ELEMENT::get_uchar() const
3046 if (str_val
.charstring
)
3047 const_cast<UNIVERSAL_CHARSTRING_ELEMENT
&>
3048 (*this).str_val
.convert_cstr_to_uni();
3049 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3052 void UNIVERSAL_CHARSTRING_ELEMENT::log() const
3055 if (str_val
.charstring
) {
3056 str_val
.cstr
[uchar_pos
].log();
3059 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3060 if (is_printable(uchar
)) {
3061 // the character is printable
3062 TTCN_Logger::log_char('"');
3063 TTCN_Logger::log_char_escaped(uchar
.uc_cell
);
3064 TTCN_Logger::log_char('"');
3066 // the character is not printable
3067 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3068 uchar
.uc_group
, uchar
.uc_plane
, uchar
.uc_row
, uchar
.uc_cell
);
3070 } else TTCN_Logger::log_event_unbound();
3075 boolean
operator==(const universal_char
& uchar_value
,
3076 const UNIVERSAL_CHARSTRING
& other_value
)
3078 other_value
.must_bound("The right operand of comparison is an unbound "
3079 "universal charstring value.");
3080 if (other_value
.charstring
) {
3081 if (other_value
.cstr
.val_ptr
->n_chars
!= 1) return FALSE
;
3082 else return uchar_value
.is_char() &&
3083 uchar_value
.uc_cell
== other_value
.cstr
.val_ptr
->chars_ptr
[0];
3085 if (other_value
.val_ptr
->n_uchars
!= 1) return FALSE
;
3086 else return uchar_value
== other_value
.val_ptr
->uchars_ptr
[0];
3089 boolean
operator==(const universal_char
& uchar_value
,
3090 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3092 other_value
.must_bound("The right operand of comparison is an unbound "
3093 "universal charstring element.");
3094 return uchar_value
== other_value
.get_uchar();
3097 UNIVERSAL_CHARSTRING
operator+(const universal_char
& uchar_value
,
3098 const UNIVERSAL_CHARSTRING
& other_value
)
3100 other_value
.must_bound("The right operand of concatenation is an unbound "
3101 "universal charstring value.");
3102 if (other_value
.charstring
) {
3103 if (uchar_value
.is_char()) {
3104 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1, true);
3105 ret_val
.cstr
.val_ptr
->chars_ptr
[0] = uchar_value
.uc_cell
;
3106 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1,
3107 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3110 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3111 ret_val
.val_ptr
->uchars_ptr
[0] = uchar_value
;
3112 for (int i
= 0; i
< other_value
.cstr
.val_ptr
->n_chars
; i
++) {
3113 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_group
= 0;
3114 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_plane
= 0;
3115 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_row
= 0;
3116 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_cell
=
3117 other_value
.cstr
.val_ptr
->chars_ptr
[i
];
3122 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3123 ret_val
.val_ptr
->uchars_ptr
[0] = uchar_value
;
3124 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3125 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3130 UNIVERSAL_CHARSTRING
operator+(const universal_char
& uchar_value
,
3131 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3133 other_value
.must_bound("The right operand of concatenation is an unbound "
3134 "universal charstring element.");
3135 if (other_value
.str_val
.charstring
) {
3136 if (uchar_value
.is_char()) {
3138 result
[0] = uchar_value
.uc_cell
;
3140 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3141 return UNIVERSAL_CHARSTRING(2, result
);
3143 universal_char result
[2];
3144 result
[0] = uchar_value
;
3145 result
[1].uc_group
= 0;
3146 result
[1].uc_plane
= 0;
3147 result
[1].uc_row
= 0;
3149 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3150 return UNIVERSAL_CHARSTRING(2, result
);
3153 universal_char result
[2];
3154 result
[0] = uchar_value
;
3155 result
[1] = other_value
.get_uchar();
3156 return UNIVERSAL_CHARSTRING(2, result
);
3160 boolean
operator==(const char *string_value
,
3161 const UNIVERSAL_CHARSTRING
& other_value
)
3163 other_value
.must_bound("The right operand of comparison is an unbound "
3164 "universal charstring value.");
3166 if (string_value
== NULL
) string_len
= 0;
3167 else string_len
= strlen(string_value
);
3168 if (other_value
.charstring
) {
3169 return other_value
.cstr
== string_value
;
3171 if (string_len
!= other_value
.val_ptr
->n_uchars
) return FALSE
;
3172 for (int i
= 0; i
< string_len
; i
++) {
3173 if (other_value
.val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
3174 other_value
.val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
3175 other_value
.val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
3176 other_value
.val_ptr
->uchars_ptr
[i
].uc_cell
!= string_value
[i
])
3183 boolean
operator==(const char *string_value
,
3184 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3186 other_value
.must_bound("The right operand of comparison is an unbound "
3187 "universal charstring element.");
3188 if (string_value
== NULL
|| string_value
[0] == '\0' ||
3189 string_value
[1] != '\0') return FALSE
;
3190 if (other_value
.str_val
.charstring
)
3191 return other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
]
3193 const universal_char
& uchar
= other_value
.get_uchar();
3194 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3195 uchar
.uc_cell
== string_value
[0];
3198 UNIVERSAL_CHARSTRING
operator+(const char *string_value
,
3199 const UNIVERSAL_CHARSTRING
& other_value
)
3201 other_value
.must_bound("The right operand of concatenation is an unbound "
3202 "universal charstring value.");
3204 if (string_value
== NULL
) string_len
= 0;
3205 else string_len
= strlen(string_value
);
3206 if (other_value
.charstring
) {
3207 UNIVERSAL_CHARSTRING
ret_val(string_len
+ other_value
.cstr
.val_ptr
->n_chars
,
3209 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, string_value
, string_len
);
3210 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ string_len
,
3211 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3214 UNIVERSAL_CHARSTRING
ret_val(string_len
+ other_value
.val_ptr
->n_uchars
);
3215 for (int i
= 0; i
< string_len
; i
++) {
3216 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3217 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3218 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3219 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= string_value
[i
];
3221 memcpy(ret_val
.val_ptr
->uchars_ptr
+ string_len
,
3222 other_value
.val_ptr
->uchars_ptr
,
3223 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3227 UNIVERSAL_CHARSTRING
operator+(const char *string_value
,
3228 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3230 other_value
.must_bound("The right operand of concatenation is an unbound "
3231 "universal charstring element.");
3233 if (string_value
== NULL
) string_len
= 0;
3234 else string_len
= strlen(string_value
);
3235 if (other_value
.str_val
.charstring
) {
3236 UNIVERSAL_CHARSTRING
ret_val(string_len
+ 1, true);
3237 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, string_value
, string_len
);
3238 ret_val
.cstr
.val_ptr
->chars_ptr
[string_len
] =
3239 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3242 UNIVERSAL_CHARSTRING
ret_val(string_len
+ 1);
3243 for (int i
= 0; i
< string_len
; i
++) {
3244 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3245 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3246 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3247 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= string_value
[i
];
3249 ret_val
.val_ptr
->uchars_ptr
[string_len
] = other_value
.get_uchar();
3253 // member functions of class UNIVERSAL_CHARSTRING_template
3255 void UNIVERSAL_CHARSTRING_template::clean_up()
3257 if (template_selection
== VALUE_LIST
||
3258 template_selection
== COMPLEMENTED_LIST
) delete [] value_list
.list_value
;
3259 else if (template_selection
== STRING_PATTERN
) {
3260 if (pattern_value
.regexp_init
) regfree(&pattern_value
.posix_regexp
);
3261 delete pattern_string
;
3263 template_selection
= UNINITIALIZED_TEMPLATE
;
3266 void UNIVERSAL_CHARSTRING_template::copy_template
3267 (const CHARSTRING_template
& other_value
)
3269 switch (other_value
.template_selection
) {
3270 case SPECIFIC_VALUE
:
3271 single_value
= other_value
.single_value
;
3278 case COMPLEMENTED_LIST
:
3279 value_list
.n_values
= other_value
.value_list
.n_values
;
3280 value_list
.list_value
=
3281 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3282 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3283 value_list
.list_value
[i
].copy_template(
3284 other_value
.value_list
.list_value
[i
]);
3287 if (!other_value
.value_range
.min_is_set
) TTCN_error("The lower bound is "
3288 "not set when copying a charstring value range template to a universal "
3289 "charstring template.");
3290 if (!other_value
.value_range
.max_is_set
) TTCN_error("The upper bound is "
3291 "not set when copying a charstring value range template to a universal "
3292 "charstring template.");
3293 value_range
.min_is_set
= TRUE
;
3294 value_range
.max_is_set
= TRUE
;
3295 value_range
.min_value
.uc_group
= 0;
3296 value_range
.min_value
.uc_plane
= 0;
3297 value_range
.min_value
.uc_row
= 0;
3298 value_range
.min_value
.uc_cell
= other_value
.value_range
.min_value
;
3299 value_range
.max_value
.uc_group
= 0;
3300 value_range
.max_value
.uc_plane
= 0;
3301 value_range
.max_value
.uc_row
= 0;
3302 value_range
.max_value
.uc_cell
= other_value
.value_range
.max_value
;
3304 case STRING_PATTERN
:
3305 pattern_string
= new CHARSTRING(other_value
.single_value
);
3306 pattern_value
.regexp_init
=FALSE
;
3309 TTCN_error("Copying an uninitialized/unsupported charstring template to a "
3310 "universal charstring template.");
3312 set_selection(other_value
);
3315 void UNIVERSAL_CHARSTRING_template::copy_template
3316 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3318 switch (other_value
.template_selection
) {
3319 case SPECIFIC_VALUE
:
3320 single_value
= other_value
.single_value
;
3327 case COMPLEMENTED_LIST
:
3328 value_list
.n_values
= other_value
.value_list
.n_values
;
3329 value_list
.list_value
=
3330 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3331 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3332 value_list
.list_value
[i
].copy_template(
3333 other_value
.value_list
.list_value
[i
]);
3336 if (!other_value
.value_range
.min_is_set
) TTCN_error("The lower bound is "
3337 "not set when copying a universal charstring value range template.");
3338 if (!other_value
.value_range
.max_is_set
) TTCN_error("The upper bound is "
3339 "not set when copying a universal charstring value range template.");
3340 value_range
= other_value
.value_range
;
3342 case STRING_PATTERN
:
3343 pattern_string
= new CHARSTRING(*(other_value
.pattern_string
));
3344 pattern_value
.regexp_init
=FALSE
;
3347 TTCN_error("Copying an uninitialized/unsupported universal charstring "
3350 set_selection(other_value
);
3353 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template()
3357 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3358 (template_sel other_value
) : Restricted_Length_Template(other_value
)
3361 check_single_selection(other_value
);
3364 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3365 (const CHARSTRING
& other_value
) :
3366 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3370 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3371 (const UNIVERSAL_CHARSTRING
& other_value
) :
3372 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3376 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3377 (const CHARSTRING_ELEMENT
& other_value
) :
3378 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3382 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3383 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) :
3384 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3388 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3389 (const OPTIONAL
<CHARSTRING
>& other_value
)
3391 switch (other_value
.get_selection()) {
3392 case OPTIONAL_PRESENT
:
3393 set_selection(SPECIFIC_VALUE
);
3394 single_value
= (const CHARSTRING
&)other_value
;
3397 set_selection(OMIT_VALUE
);
3400 TTCN_error("Creating a universal charstring template from an unbound "
3405 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3406 (const OPTIONAL
<UNIVERSAL_CHARSTRING
>& other_value
)
3408 switch (other_value
.get_selection()) {
3409 case OPTIONAL_PRESENT
:
3410 set_selection(SPECIFIC_VALUE
);
3411 single_value
= (const UNIVERSAL_CHARSTRING
&)other_value
;
3414 set_selection(OMIT_VALUE
);
3417 TTCN_error("Creating a universal charstring template from an unbound "
3422 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3423 (const CHARSTRING_template
& other_value
)
3424 : Restricted_Length_Template()
3426 copy_template(other_value
);
3429 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3430 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3431 : Restricted_Length_Template()
3433 copy_template(other_value
);
3436 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3437 (template_sel p_sel
, const CHARSTRING
& p_str
)
3438 : Restricted_Length_Template(STRING_PATTERN
)
3440 if(p_sel
!=STRING_PATTERN
)
3441 TTCN_error("Internal error: Initializing a universal charstring"
3442 "pattern template with invalid selection.");
3443 pattern_string
= new CHARSTRING(p_str
);
3444 pattern_value
.regexp_init
=FALSE
;
3447 UNIVERSAL_CHARSTRING_template::~UNIVERSAL_CHARSTRING_template()
3452 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3453 (template_sel other_value
)
3455 check_single_selection(other_value
);
3457 set_selection(other_value
);
3461 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3462 (const CHARSTRING
& other_value
)
3464 other_value
.must_bound("Assignment of an unbound charstring value to a "
3465 "universal charstring template.");
3467 set_selection(SPECIFIC_VALUE
);
3468 single_value
= other_value
;
3472 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3473 (const UNIVERSAL_CHARSTRING
& other_value
)
3475 other_value
.must_bound("Assignment of an unbound universal charstring value "
3478 set_selection(SPECIFIC_VALUE
);
3479 single_value
= other_value
;
3483 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3484 (const CHARSTRING_ELEMENT
& other_value
)
3486 other_value
.must_bound("Assignment of an unbound charstring element to a "
3487 "universal charstring template.");
3489 set_selection(SPECIFIC_VALUE
);
3490 single_value
= other_value
;
3494 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3495 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3497 other_value
.must_bound("Assignment of an unbound universal charstring "
3498 "element to a template.");
3500 set_selection(SPECIFIC_VALUE
);
3501 single_value
= other_value
;
3505 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3506 (const OPTIONAL
<CHARSTRING
>& other_value
)
3509 switch (other_value
.get_selection()) {
3510 case OPTIONAL_PRESENT
:
3511 set_selection(SPECIFIC_VALUE
);
3512 single_value
= (const CHARSTRING
&)other_value
;
3515 set_selection(OMIT_VALUE
);
3518 TTCN_error("Assignment of an unbound optional field to a universal "
3519 "charstring template.");
3524 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3525 (const OPTIONAL
<UNIVERSAL_CHARSTRING
>& other_value
)
3528 switch (other_value
.get_selection()) {
3529 case OPTIONAL_PRESENT
:
3530 set_selection(SPECIFIC_VALUE
);
3531 single_value
= (const UNIVERSAL_CHARSTRING
&)other_value
;
3534 set_selection(OMIT_VALUE
);
3537 TTCN_error("Assignment of an unbound optional field to a universal "
3538 "charstring template.");
3543 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3544 (const CHARSTRING_template
& other_value
)
3547 copy_template(other_value
);
3551 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3552 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3554 if (&other_value
!= this) {
3556 copy_template(other_value
);
3561 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](int index_value
)
3563 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3564 TTCN_error("Accessing a universal charstring element of a non-specific "
3565 "universal charstring template.");
3566 return single_value
[index_value
];
3569 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](const INTEGER
& index_value
)
3571 index_value
.must_bound("Indexing a universal charstring template with an "
3572 "unbound integer value.");
3573 return (*this)[(int)index_value
];
3576 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](int index_value
) const
3578 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3579 TTCN_error("Accessing a universal charstring element of a non-specific "
3580 "universal charstring template.");
3581 return single_value
[index_value
];
3584 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](const INTEGER
& index_value
) const
3586 index_value
.must_bound("Indexing a universal charstring template with an "
3587 "unbound integer value.");
3588 return (*this)[(int)index_value
];
3591 boolean
UNIVERSAL_CHARSTRING_template::match
3592 (const UNIVERSAL_CHARSTRING
& other_value
) const
3594 if (!other_value
.is_bound()) return FALSE
;
3595 int value_length
= other_value
.lengthof();
3596 if (!match_length(value_length
)) return FALSE
;
3597 switch (template_selection
) {
3598 case SPECIFIC_VALUE
:
3599 return single_value
== other_value
;
3606 case COMPLEMENTED_LIST
:
3607 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3608 if (value_list
.list_value
[i
].match(other_value
))
3609 return template_selection
== VALUE_LIST
;
3610 return template_selection
== COMPLEMENTED_LIST
;
3612 if (!value_range
.min_is_set
) TTCN_error("The lower bound is not set when "
3613 "matching with a universal charstring value range template.");
3614 if (!value_range
.max_is_set
) TTCN_error("The upper bound is not set when "
3615 "matching with a universal charstring value range template.");
3616 if (value_range
.max_value
< value_range
.min_value
)
3617 TTCN_error("The lower bound is greater than the upper bound "
3618 "when matching with a universal charstring value range template.");
3619 const universal_char
*uchars_ptr
= other_value
;
3620 for (int i
= 0; i
< value_length
; i
++) {
3621 if (uchars_ptr
[i
] < value_range
.min_value
||
3622 value_range
.max_value
< uchars_ptr
[i
]) return FALSE
;
3625 case STRING_PATTERN
: {
3626 if (!pattern_value
.regexp_init
) {
3628 TTCN_pattern_to_regexp_uni((const char*)(*pattern_string
));
3629 if(posix_str
==NULL
) {
3630 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
3631 (const char*)(*pattern_string
));
3633 int ret_val
=regcomp(&pattern_value
.posix_regexp
, posix_str
,
3634 REG_EXTENDED
|REG_NOSUB
);
3638 char msg
[ERRMSG_BUFSIZE
];
3639 regerror(ret_val
, &pattern_value
.posix_regexp
, msg
, ERRMSG_BUFSIZE
);
3640 regfree(&pattern_value
.posix_regexp
);
3641 TTCN_error("Pattern matching error: %s", msg
);
3643 pattern_value
.regexp_init
=TRUE
;
3645 char* other_value_converted
= other_value
.convert_to_regexp_form();
3646 int ret_val
=regexec(&pattern_value
.posix_regexp
, other_value_converted
, 0,
3648 Free(other_value_converted
);
3656 char msg
[ERRMSG_BUFSIZE
];
3657 regerror(ret_val
, &pattern_value
.posix_regexp
, msg
, ERRMSG_BUFSIZE
);
3658 TTCN_error("Pattern matching error: %s", msg
);
3662 TTCN_error("Matching with an uninitialized/unsupported universal "
3663 "charstring template.");
3668 const UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING_template::valueof() const
3670 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3671 TTCN_error("Performing valueof or send operation on a non-specific "
3672 "universal charstring template.");
3673 return single_value
;
3676 int UNIVERSAL_CHARSTRING_template::lengthof() const
3679 boolean has_any_or_none
;
3681 TTCN_error("Performing lengthof() operation on a universal charstring "
3682 "template which has an ifpresent attribute.");
3683 switch (template_selection
)
3685 case SPECIFIC_VALUE
:
3686 min_length
= single_value
.lengthof();
3687 has_any_or_none
= FALSE
;
3690 TTCN_error("Performing lengthof() operation on a universal charstring "
3691 "template containing omit value.");
3696 has_any_or_none
= TRUE
; // max. length is infinity
3700 // error if any element does not have length or the lengths differ
3701 if (value_list
.n_values
<1)
3702 TTCN_error("Internal error: "
3703 "Performing lengthof() operation on a universal charstring "
3704 "template containing an empty list.");
3705 int item_length
= value_list
.list_value
[0].lengthof();
3706 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
3707 if (value_list
.list_value
[i
].lengthof()!=item_length
)
3708 TTCN_error("Performing lengthof() operation on a universal charstring "
3709 "template containing a value list with different lengths.");
3711 min_length
= item_length
;
3712 has_any_or_none
= FALSE
;
3715 case COMPLEMENTED_LIST
:
3716 TTCN_error("Performing lengthof() operation on a universal charstring "
3717 "template containing complemented list.");
3718 case STRING_PATTERN
:
3719 TTCN_error("Performing lengthof() operation on a universal charstring "
3720 "template containing a pattern is not allowed.");
3722 TTCN_error("Performing lengthof() operation on an "
3723 "uninitialized/unsupported universal charstring template.");
3725 return check_section_is_single(min_length
, has_any_or_none
,
3726 "length", "a", "universal charstring template");
3729 void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type
,
3730 unsigned int list_length
)
3733 switch (template_type
) {
3735 case COMPLEMENTED_LIST
:
3736 set_selection(template_type
);
3737 value_list
.n_values
= list_length
;
3738 value_list
.list_value
= new UNIVERSAL_CHARSTRING_template
[list_length
];
3741 set_selection(VALUE_RANGE
);
3742 value_range
.min_is_set
= FALSE
;
3743 value_range
.max_is_set
= FALSE
;
3746 TTCN_error("Setting an invalid type for a universal charstring template.");
3750 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::list_item
3751 (unsigned int list_index
)
3753 if (template_selection
!= VALUE_LIST
&&
3754 template_selection
!= COMPLEMENTED_LIST
)
3755 TTCN_error("Accessing a list element of a non-list universal charstring "
3757 if (list_index
>= value_list
.n_values
)
3758 TTCN_error("Index overflow in a universal charstring value list template.");
3759 return value_list
.list_value
[list_index
];
3762 void UNIVERSAL_CHARSTRING_template::set_min
3763 (const UNIVERSAL_CHARSTRING
& min_value
)
3765 if (template_selection
!= VALUE_RANGE
) TTCN_error("Setting the lower bound "
3766 "for a non-range universal charstring template.");
3767 min_value
.must_bound("Setting an unbound value as lower bound in a "
3768 "universal charstring value range template.");
3769 int length
= min_value
.lengthof();
3770 if (length
!= 1) TTCN_error("The length of the lower bound in a universal "
3771 "charstring value range template must be 1 instead of %d.", length
);
3772 value_range
.min_is_set
= TRUE
;
3773 value_range
.min_value
= *(const universal_char
*)min_value
;
3774 if (value_range
.max_is_set
&& value_range
.max_value
< value_range
.min_value
)
3775 TTCN_error("The lower bound in a universal charstring value range template "
3776 "is greater than the upper bound.");
3779 void UNIVERSAL_CHARSTRING_template::set_max
3780 (const UNIVERSAL_CHARSTRING
& max_value
)
3782 if (template_selection
!= VALUE_RANGE
) TTCN_error("Setting the upper bound "
3783 "for a non-range universal charstring template.");
3784 max_value
.must_bound("Setting an unbound value as upper bound in a "
3785 "universal charstring value range template.");
3786 int length
= max_value
.lengthof();
3787 if (length
!= 1) TTCN_error("The length of the upper bound in a universal "
3788 "charstring value range template must be 1 instead of %d.", length
);
3789 value_range
.max_is_set
= TRUE
;
3790 value_range
.max_value
= *(const universal_char
*)max_value
;
3791 if (value_range
.min_is_set
&& value_range
.max_value
< value_range
.min_value
)
3792 TTCN_error("The upper bound in a universal charstring value range template "
3793 "is smaller than the lower bound.");
3796 void UNIVERSAL_CHARSTRING_template::log() const
3798 switch (template_selection
) {
3799 case STRING_PATTERN
:
3800 CHARSTRING_template::log_pattern(pattern_string
->lengthof(),
3801 (const char*)*pattern_string
);
3803 case SPECIFIC_VALUE
:
3806 case COMPLEMENTED_LIST
:
3807 TTCN_Logger::log_event_str("complement ");
3810 TTCN_Logger::log_char('(');
3811 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
3812 if (i
> 0) TTCN_Logger::log_event_str(", ");
3813 value_list
.list_value
[i
].log();
3815 TTCN_Logger::log_char(')');
3818 TTCN_Logger::log_char('(');
3819 if (value_range
.min_is_set
) {
3820 if (is_printable(value_range
.min_value
)) {
3821 TTCN_Logger::log_char('"');
3822 TTCN_Logger::log_char_escaped(value_range
.min_value
.uc_cell
);
3823 TTCN_Logger::log_char('"');
3825 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3826 value_range
.min_value
.uc_group
, value_range
.min_value
.uc_plane
,
3827 value_range
.min_value
.uc_row
, value_range
.min_value
.uc_cell
);
3829 } else TTCN_Logger::log_event_str("<unknown lower bound>");
3830 TTCN_Logger::log_event_str(" .. ");
3831 if (value_range
.max_is_set
) {
3832 if (is_printable(value_range
.max_value
)) {
3833 TTCN_Logger::log_char('"');
3834 TTCN_Logger::log_char_escaped(value_range
.max_value
.uc_cell
);
3835 TTCN_Logger::log_char('"');
3837 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3838 value_range
.max_value
.uc_group
, value_range
.max_value
.uc_plane
,
3839 value_range
.max_value
.uc_row
, value_range
.max_value
.uc_cell
);
3841 } else TTCN_Logger::log_event_str("<unknown upper bound>");
3842 TTCN_Logger::log_char(')');
3852 void UNIVERSAL_CHARSTRING_template::log_match
3853 (const UNIVERSAL_CHARSTRING
& match_value
) const
3855 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
3856 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
3857 TTCN_Logger::print_logmatch_buffer();
3858 TTCN_Logger::log_event_str(" := ");
3861 TTCN_Logger::log_event_str(" with ");
3863 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
3864 else TTCN_Logger::log_event_str(" unmatched");
3867 void UNIVERSAL_CHARSTRING_template::set_param(Module_Param
& param
) {
3868 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "universal charstring template");
3869 switch (param
.get_type()) {
3870 case Module_Param::MP_Omit
:
3873 case Module_Param::MP_Any
:
3876 case Module_Param::MP_AnyOrNone
:
3877 *this = ANY_OR_OMIT
;
3879 case Module_Param::MP_List_Template
:
3880 case Module_Param::MP_ComplementList_Template
:
3881 set_type(param
.get_type()==Module_Param::MP_List_Template
? VALUE_LIST
: COMPLEMENTED_LIST
, param
.get_size());
3882 for (size_t i
=0; i
<param
.get_size(); i
++) {
3883 list_item(i
).set_param(*param
.get_elem(i
));
3886 case Module_Param::MP_Charstring
:
3887 *this = CHARSTRING(param
.get_string_size(), (char*)param
.get_string_data());
3889 case Module_Param::MP_Universal_Charstring
:
3890 *this = UNIVERSAL_CHARSTRING(param
.get_string_size(), (universal_char
*)param
.get_string_data());
3892 case Module_Param::MP_StringRange
: {
3893 universal_char lower_uchar
= param
.get_lower_uchar();
3894 universal_char upper_uchar
= param
.get_upper_uchar();
3896 set_selection(VALUE_RANGE
);
3897 value_range
.min_is_set
= TRUE
;
3898 value_range
.max_is_set
= TRUE
;
3899 value_range
.min_value
= lower_uchar
;
3900 value_range
.max_value
= upper_uchar
;
3902 case Module_Param::MP_Pattern
:
3904 pattern_string
= new CHARSTRING(param
.get_pattern());
3905 pattern_value
.regexp_init
= FALSE
;
3906 set_selection(STRING_PATTERN
);
3909 param
.type_error("universal charstring template");
3911 is_ifpresent
= param
.get_ifpresent();
3912 set_length_range(param
);
3915 void UNIVERSAL_CHARSTRING_template::encode_text(Text_Buf
& text_buf
) const
3917 encode_text_restricted(text_buf
);
3918 switch (template_selection
) {
3923 case SPECIFIC_VALUE
:
3924 single_value
.encode_text(text_buf
);
3927 case COMPLEMENTED_LIST
:
3928 text_buf
.push_int(value_list
.n_values
);
3929 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3930 value_list
.list_value
[i
].encode_text(text_buf
);
3933 if (!value_range
.min_is_set
) TTCN_error("Text encoder: The lower bound is "
3934 "not set in a universal charstring value range template.");
3935 if (!value_range
.max_is_set
) TTCN_error("Text encoder: The upper bound is "
3936 "not set in a universal charstring value range template.");
3937 unsigned char buf
[8];
3938 buf
[0] = value_range
.min_value
.uc_group
;
3939 buf
[1] = value_range
.min_value
.uc_plane
;
3940 buf
[2] = value_range
.min_value
.uc_row
;
3941 buf
[3] = value_range
.min_value
.uc_cell
;
3942 buf
[4] = value_range
.max_value
.uc_group
;
3943 buf
[5] = value_range
.max_value
.uc_plane
;
3944 buf
[6] = value_range
.max_value
.uc_row
;
3945 buf
[7] = value_range
.max_value
.uc_cell
;
3946 text_buf
.push_raw(8, buf
);
3949 TTCN_error("Text encoder: Encoding an uninitialized/unsupported universal "
3950 "charstring template.");
3954 void UNIVERSAL_CHARSTRING_template::decode_text(Text_Buf
& text_buf
)
3957 decode_text_restricted(text_buf
);
3958 switch (template_selection
) {
3963 case SPECIFIC_VALUE
:
3964 single_value
.decode_text(text_buf
);
3967 case COMPLEMENTED_LIST
:
3968 value_list
.n_values
= text_buf
.pull_int().get_val();
3969 value_list
.list_value
=
3970 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3971 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3972 value_list
.list_value
[i
].decode_text(text_buf
);
3975 unsigned char buf
[8];
3976 text_buf
.pull_raw(8, buf
);
3977 value_range
.min_value
.uc_group
= buf
[0];
3978 value_range
.min_value
.uc_plane
= buf
[1];
3979 value_range
.min_value
.uc_row
= buf
[2];
3980 value_range
.min_value
.uc_cell
= buf
[3];
3981 value_range
.max_value
.uc_group
= buf
[4];
3982 value_range
.max_value
.uc_plane
= buf
[5];
3983 value_range
.max_value
.uc_row
= buf
[6];
3984 value_range
.max_value
.uc_cell
= buf
[7];
3985 if (value_range
.max_value
< value_range
.min_value
)
3986 TTCN_error("Text decoder: The received lower bound is greater than the "
3987 "upper bound in a universal charstring value range template.");
3988 value_range
.min_is_set
= TRUE
;
3989 value_range
.max_is_set
= TRUE
;
3992 TTCN_error("Text decoder: An unknown/unsupported selection was "
3993 "received for a universal charstring template.");
3997 boolean
UNIVERSAL_CHARSTRING_template::is_present() const
3999 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
4000 return !match_omit();
4003 boolean
UNIVERSAL_CHARSTRING_template::match_omit() const
4005 if (is_ifpresent
) return TRUE
;
4006 switch (template_selection
) {
4011 case COMPLEMENTED_LIST
:
4012 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
4013 if (value_list
.list_value
[i
].match_omit())
4014 return template_selection
==VALUE_LIST
;
4015 return template_selection
==COMPLEMENTED_LIST
;
4022 #ifndef TITAN_RUNTIME_2
4023 void UNIVERSAL_CHARSTRING_template::check_restriction(template_res t_res
,
4024 const char* t_name
) const
4026 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
4027 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
4029 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
4032 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
4033 template_selection
==SPECIFIC_VALUE
)) return;
4036 if (!match_omit()) return;
4041 TTCN_error("Restriction `%s' on template of type %s violated.",
4042 get_res_name(t_res
), t_name
? t_name
: "universal charstring");
4046 const CHARSTRING
& UNIVERSAL_CHARSTRING_template::get_single_value() const {
4047 if (!pattern_string
)
4048 TTCN_error("Pattern string does not exist in universal charstring template");
4049 return *pattern_string
;
4053 * ISO 2022 conversion functions -- these can be overwritten by users
4054 * by defining their own versions. Because these --of course :)-- are
4055 * not really conform to ISO 2022. :o)
4058 /** TTCN_UCSTR_2_ISO2022: A dummy common implementation. */
4059 OCTETSTRING
TTCN_UCSTR_2_ISO2022(const UNIVERSAL_CHARSTRING
& p_s
)
4061 const universal_char
* ucstr
=static_cast<const universal_char
*>(p_s
);
4062 int len
=p_s
.lengthof();
4063 unsigned char* osstr
=(unsigned char*)Malloc(len
);
4064 for(int i
=0; i
<len
; i
++) osstr
[i
]=ucstr
[i
].uc_cell
;
4065 OCTETSTRING
os(len
, osstr
);
4070 /** TTCN_ISO2022_2_UCSTR: A dummy common implementation. */
4071 UNIVERSAL_CHARSTRING
TTCN_ISO2022_2_UCSTR(const OCTETSTRING
& p_os
)
4073 const unsigned char* osstr
=static_cast<const unsigned char*>(p_os
);
4074 int len
=p_os
.lengthof();
4075 universal_char
* ucstr
=(universal_char
*)Malloc(len
*sizeof(*ucstr
));
4076 for(int i
=0; i
<len
; i
++) {
4077 ucstr
[i
].uc_group
=0;
4078 ucstr
[i
].uc_plane
=0;
4080 ucstr
[i
].uc_cell
=osstr
[i
];
4082 UNIVERSAL_CHARSTRING
us(len
, ucstr
);
4087 OCTETSTRING
TTCN_TeletexString_2_ISO2022(const TeletexString
& p_s
)
4089 return TTCN_UCSTR_2_ISO2022(p_s
);
4092 TeletexString
TTCN_ISO2022_2_TeletexString(const OCTETSTRING
& p_os
)
4094 return TTCN_ISO2022_2_UCSTR(p_os
);
4097 OCTETSTRING
TTCN_VideotexString_2_ISO2022(const VideotexString
& p_s
)
4099 return TTCN_UCSTR_2_ISO2022(p_s
);
4102 VideotexString
TTCN_ISO2022_2_VideotexString(const OCTETSTRING
& p_os
)
4104 return TTCN_ISO2022_2_UCSTR(p_os
);
4107 OCTETSTRING
TTCN_GraphicString_2_ISO2022(const GraphicString
& p_s
)
4109 return TTCN_UCSTR_2_ISO2022(p_s
);
4112 GraphicString
TTCN_ISO2022_2_GraphicString(const OCTETSTRING
& p_os
)
4114 return TTCN_ISO2022_2_UCSTR(p_os
);
4117 OCTETSTRING
TTCN_GeneralString_2_ISO2022(const GeneralString
& p_s
)
4119 return TTCN_UCSTR_2_ISO2022(p_s
);
4122 GeneralString
TTCN_ISO2022_2_GeneralString(const OCTETSTRING
& p_os
)
4124 return TTCN_ISO2022_2_UCSTR(p_os
);