1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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
27 #define ERRMSG_BUFSIZE 500
29 // global function for universal_char comparison
31 boolean
operator==(const universal_char
& left_value
,
32 const universal_char
& right_value
)
34 return left_value
.uc_group
== right_value
.uc_group
&&
35 left_value
.uc_plane
== right_value
.uc_plane
&&
36 left_value
.uc_row
== right_value
.uc_row
&&
37 left_value
.uc_cell
== right_value
.uc_cell
;
40 boolean
operator<(const universal_char
& left_value
,
41 const universal_char
& right_value
)
43 if (left_value
.uc_group
< right_value
.uc_group
) return TRUE
;
44 else if (left_value
.uc_group
== right_value
.uc_group
) {
45 if (left_value
.uc_plane
< right_value
.uc_plane
) return TRUE
;
46 else if (left_value
.uc_plane
== right_value
.uc_plane
) {
47 if (left_value
.uc_row
< right_value
.uc_row
) return TRUE
;
48 else if (left_value
.uc_row
== right_value
.uc_row
) {
49 if (left_value
.uc_cell
< right_value
.uc_cell
) return TRUE
;
56 /** The amount of memory needed for a string containing n characters. */
57 #define MEMORY_SIZE(n) (sizeof(universal_charstring_struct) + \
58 ((n) - 1) * sizeof(universal_char))
60 // member functions of class UNIVERSAL_CHARSTRING
62 /** Allocate space for n characters.
64 * @param n_uchars number of characters needed
68 * If n_uchars is 0, no memory is allocated and a reference to the
69 * "empty string" is used instead.
71 * Otherwise, space for n_uchars is allocated (no terminating null).
73 * @note If the string is not empty, this will leak memory.
74 * Probably clean_up() should have been called before.
76 void UNIVERSAL_CHARSTRING::init_struct(int n_uchars
)
80 TTCN_error("Initializing a universal charstring with a negative length.");
81 } else if (n_uchars
== 0) {
82 /* This will represent the empty strings so they won't need allocated
83 * memory, this delays the memory allocation until it is really needed.
85 static universal_charstring_struct empty_string
=
86 { 1, 0, { { '\0', '\0', '\0', '\0' } } };
87 val_ptr
= &empty_string
;
88 empty_string
.ref_count
++;
90 val_ptr
= (universal_charstring_struct
*)Malloc(MEMORY_SIZE(n_uchars
));
91 val_ptr
->ref_count
= 1;
92 val_ptr
->n_uchars
= n_uchars
;
96 void UNIVERSAL_CHARSTRING::copy_value()
98 if (val_ptr
== NULL
|| val_ptr
->n_uchars
<= 0)
99 TTCN_error("Internal error: Invalid internal data structure when copying "
100 "the memory area of a universal charstring value.");
101 if (val_ptr
->ref_count
> 1) {
102 universal_charstring_struct
*old_ptr
= val_ptr
;
103 old_ptr
->ref_count
--;
104 init_struct(old_ptr
->n_uchars
);
105 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
, old_ptr
->n_uchars
*
106 sizeof(universal_char
));
110 void UNIVERSAL_CHARSTRING::clean_up()
112 if (val_ptr
!= NULL
) {
113 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
114 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
115 else TTCN_error("Internal error: Invalid reference counter in a universal "
116 "charstring value.");
122 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars
, bool cstring
)
123 : val_ptr(NULL
), cstr(cstring
? n_uchars
: 0), charstring(cstring
)
126 init_struct(n_uchars
);
129 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING()
130 : val_ptr(NULL
), cstr(0), charstring(false)
133 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(unsigned char uc_group
,
134 unsigned char uc_plane
, unsigned char uc_row
, unsigned char uc_cell
)
138 val_ptr
->uchars_ptr
[0].uc_group
= uc_group
;
139 val_ptr
->uchars_ptr
[0].uc_plane
= uc_plane
;
140 val_ptr
->uchars_ptr
[0].uc_row
= uc_row
;
141 val_ptr
->uchars_ptr
[0].uc_cell
= uc_cell
;
144 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
145 (const universal_char
& other_value
)
146 : cstr(0), charstring(false)
149 val_ptr
->uchars_ptr
[0] = other_value
;
152 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars
,
153 const universal_char
*uchars_ptr
)
154 : cstr(0), charstring(false)
156 init_struct(n_uchars
);
157 memcpy(val_ptr
->uchars_ptr
, uchars_ptr
, n_uchars
* sizeof(universal_char
));
160 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const char *chars_ptr
)
161 : val_ptr(NULL
), cstr(chars_ptr
), charstring(true)
165 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_chars
,
166 const char *chars_ptr
)
167 : val_ptr(NULL
), cstr(n_chars
, chars_ptr
), charstring(true)
171 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const CHARSTRING
& other_value
)
172 : val_ptr(NULL
), cstr(other_value
), charstring(true)
176 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
177 (const CHARSTRING_ELEMENT
& other_value
)
178 : val_ptr(NULL
), cstr(other_value
), charstring(true)
182 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
183 (const UNIVERSAL_CHARSTRING
& other_value
)
184 : Base_Type(other_value
), charstring(other_value
.charstring
)
186 other_value
.must_bound("Copying an unbound universal charstring value.");
187 if (other_value
.charstring
) {
188 cstr
= other_value
.cstr
;
191 val_ptr
= other_value
.val_ptr
;
192 val_ptr
->ref_count
++;
197 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
198 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
199 : charstring(other_value
.get_uchar().is_char())
201 other_value
.must_bound("Initialization of a universal charstring with an "
202 "unbound universal charstring element.");
204 cstr
= CHARSTRING((const char)(other_value
.get_uchar().uc_cell
));
208 val_ptr
->uchars_ptr
[0] = other_value
.get_uchar();
212 UNIVERSAL_CHARSTRING::~UNIVERSAL_CHARSTRING()
218 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
219 (const universal_char
& other_value
)
222 if (other_value
.is_char()) {
223 cstr
= CHARSTRING(other_value
.uc_cell
);
228 val_ptr
->uchars_ptr
[0] = other_value
;
234 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
235 (const char* other_value
)
245 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
246 (const CHARSTRING
& other_value
)
256 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
257 (const CHARSTRING_ELEMENT
& other_value
)
267 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
268 (const UNIVERSAL_CHARSTRING
& other_value
)
270 other_value
.must_bound("Assignment of an unbound universal charstring "
272 if (&other_value
!= this) {
274 if (other_value
.charstring
) {
275 cstr
= other_value
.cstr
;
277 val_ptr
= other_value
.val_ptr
;
278 val_ptr
->ref_count
++;
282 charstring
= other_value
.charstring
;
287 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
288 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
290 other_value
.must_bound("Assignment of an unbound universal charstring "
291 "element to a universal charstring.");
292 if (other_value
.str_val
.charstring
) {
293 char c
= other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
295 cstr
= CHARSTRING(c
);
298 universal_char uchar_value
= other_value
.get_uchar();
301 val_ptr
->uchars_ptr
[0] = uchar_value
;
307 boolean
UNIVERSAL_CHARSTRING::operator==
308 (const universal_char
& other_value
) const
310 must_bound("The left operand of comparison is an unbound universal "
311 "charstring value.");
313 return cstr
.lengthof() == 1 && other_value
.uc_group
== 0
314 && other_value
.uc_plane
== 0 && other_value
.uc_row
== 0
315 && other_value
.uc_cell
== (cbyte
)cstr
.val_ptr
->chars_ptr
[0];
317 if (val_ptr
->n_uchars
!= 1) return FALSE
;
318 else return val_ptr
->uchars_ptr
[0] == other_value
;
321 boolean
UNIVERSAL_CHARSTRING::operator==(const char* other_value
) const
323 must_bound("The left operand of comparison is an unbound universal "
324 "charstring value.");
326 return cstr
== other_value
;
329 if (other_value
== NULL
) n_chars
= 0;
330 else n_chars
= strlen(other_value
);
331 if (val_ptr
->n_uchars
!= n_chars
) return FALSE
;
332 for (int i
= 0; i
< n_chars
; i
++) {
333 if (val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
334 val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
335 val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
336 val_ptr
->uchars_ptr
[i
].uc_cell
!= (cbyte
)other_value
[i
]) return FALSE
;
342 boolean
UNIVERSAL_CHARSTRING::operator==
343 (const CHARSTRING
& other_value
) const
345 must_bound("The left operand of comparison is an unbound universal "
346 "charstring value.");
347 other_value
.must_bound("The right operand of comparison is an unbound "
348 "charstring value.");
350 return cstr
== other_value
;
351 if (val_ptr
->n_uchars
!= other_value
.val_ptr
->n_chars
) return FALSE
;
352 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
353 if (val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
354 val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
355 val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
356 val_ptr
->uchars_ptr
[i
].uc_cell
!=(cbyte
)other_value
.val_ptr
->chars_ptr
[i
])
362 boolean
UNIVERSAL_CHARSTRING::operator==
363 (const CHARSTRING_ELEMENT
& other_value
) const
365 must_bound("The left operand of comparison is an unbound universal "
366 "charstring value.");
367 other_value
.must_bound("The right operand of comparison is an unbound "
368 "charstring element.");
370 return cstr
== other_value
;
371 if (val_ptr
->n_uchars
!= 1) return FALSE
;
372 else return val_ptr
->uchars_ptr
[0].uc_group
== 0 &&
373 val_ptr
->uchars_ptr
[0].uc_plane
== 0 &&
374 val_ptr
->uchars_ptr
[0].uc_row
== 0 &&
375 val_ptr
->uchars_ptr
[0].uc_cell
== (cbyte
)other_value
.get_char();
378 boolean
UNIVERSAL_CHARSTRING::operator==
379 (const UNIVERSAL_CHARSTRING
& other_value
) const
381 must_bound("The left operand of comparison is an unbound universal "
382 "charstring value.");
383 other_value
.must_bound("The right operand of comparison is an unbound "
384 "universal charstring value.");
386 return cstr
== other_value
;
387 else if (other_value
.charstring
)
388 return other_value
.cstr
== *this;
389 if (val_ptr
->n_uchars
!= other_value
.val_ptr
->n_uchars
) return FALSE
;
390 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
391 if (val_ptr
->uchars_ptr
[i
] != other_value
.val_ptr
->uchars_ptr
[i
])
397 boolean
UNIVERSAL_CHARSTRING::operator==
398 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
400 must_bound("The left operand of comparison is an unbound universal "
401 "charstring value.");
402 other_value
.must_bound("The right operand of comparison is an unbound "
403 "universal charstring element.");
405 return cstr
== other_value
;
406 if (val_ptr
->n_uchars
!= 1) return FALSE
;
407 else return val_ptr
->uchars_ptr
[0] == other_value
.get_uchar();
410 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
411 (const universal_char
& other_value
) const
413 must_bound("The left operand of concatenation is an unbound universal "
414 "charstring value.");
416 if (other_value
.is_char()) {
417 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1, true);
418 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
419 cstr
.val_ptr
->n_chars
);
420 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
424 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1);
425 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
426 universal_char
& uc
= ret_val
.val_ptr
->uchars_ptr
[i
];
427 uc
.uc_group
= uc
.uc_plane
= uc
.uc_row
= 0;
428 uc
.uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
430 ret_val
.val_ptr
->uchars_ptr
[cstr
.val_ptr
->n_chars
] = other_value
;
434 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
435 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
436 val_ptr
->n_uchars
* sizeof(universal_char
));
437 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
;
441 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
442 (const char* other_value
) const
444 must_bound("The left operand of concatenation is an unbound universal "
445 "charstring value.");
447 if (other_value
== NULL
) other_len
= 0;
448 else other_len
= strlen(other_value
);
449 if (other_len
== 0) return *this;
451 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + other_len
, true);
452 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
453 cstr
.val_ptr
->n_chars
);
454 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
455 other_value
, other_len
);
458 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ other_len
);
459 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
460 val_ptr
->n_uchars
* sizeof(universal_char
));
461 for (int i
= 0; i
< other_len
; i
++) {
462 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_group
= 0;
463 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_plane
= 0;
464 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_row
= 0;
465 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_cell
= other_value
[i
];
470 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
471 (const CHARSTRING
& other_value
) const
473 must_bound("The left operand of concatenation is an unbound universal "
474 "charstring value.");
475 other_value
.must_bound("The right operand of concatenation is an unbound "
476 "charstring value.");
477 if (other_value
.val_ptr
->n_chars
== 0) return *this;
479 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + other_value
.val_ptr
->n_chars
,
481 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
482 cstr
.val_ptr
->n_chars
);
483 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
484 other_value
.val_ptr
->chars_ptr
, other_value
.val_ptr
->n_chars
);
487 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+
488 other_value
.val_ptr
->n_chars
);
489 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
490 val_ptr
->n_uchars
* sizeof(universal_char
));
491 for (int i
= 0; i
< other_value
.val_ptr
->n_chars
; i
++) {
492 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_group
= 0;
493 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_plane
= 0;
494 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_row
= 0;
495 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_cell
=
496 other_value
.val_ptr
->chars_ptr
[i
];
501 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
502 (const CHARSTRING_ELEMENT
& other_value
) const
504 must_bound("The left operand of concatenation is an unbound universal "
505 "charstring value.");
506 other_value
.must_bound("The right operand of concatenation is an unbound "
507 "charstring element.");
509 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1, true);
510 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
511 cstr
.val_ptr
->n_chars
);
512 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
513 other_value
.get_char();
516 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
517 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
518 val_ptr
->n_uchars
* sizeof(universal_char
));
519 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_group
= 0;
520 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_plane
= 0;
521 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_row
= 0;
522 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_cell
=
523 other_value
.get_char();
527 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
528 (const UNIVERSAL_CHARSTRING
& other_value
) const
530 must_bound("The left operand of concatenation is an unbound universal "
531 "charstring value.");
532 other_value
.must_bound("The right operand of concatenation is an unbound "
533 "universal charstring value.");
535 if (cstr
.val_ptr
->n_chars
== 0)
537 if (other_value
.charstring
) {
538 if (other_value
.cstr
.val_ptr
->n_chars
== 0)
540 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+
541 other_value
.cstr
.val_ptr
->n_chars
, true);
542 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
543 cstr
.val_ptr
->n_chars
);
544 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
545 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
548 if (other_value
.val_ptr
->n_uchars
== 0)
550 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+
551 other_value
.val_ptr
->n_uchars
);
552 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
553 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
554 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
555 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
556 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
558 memcpy(ret_val
.val_ptr
->uchars_ptr
+ cstr
.val_ptr
->n_chars
,
559 other_value
.val_ptr
->uchars_ptr
, other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
563 if (other_value
.charstring
) {
564 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ other_value
.cstr
.val_ptr
->n_chars
);
565 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
* sizeof(universal_char
));
566 for (int i
= val_ptr
->n_uchars
; i
< val_ptr
->n_uchars
+ other_value
.cstr
.val_ptr
->n_chars
; i
++) {
567 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
568 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
569 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
570 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= other_value
.cstr
.val_ptr
->chars_ptr
[i
-val_ptr
->n_uchars
];
574 if (val_ptr
->n_uchars
== 0) return other_value
;
575 if (other_value
.val_ptr
->n_uchars
== 0) return *this;
576 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+
577 other_value
.val_ptr
->n_uchars
);
578 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
579 val_ptr
->n_uchars
* sizeof(universal_char
));
580 memcpy(ret_val
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
,
581 other_value
.val_ptr
->uchars_ptr
,
582 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
588 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
589 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
591 must_bound("The left operand of concatenation is an unbound universal "
592 "charstring value.");
593 other_value
.must_bound("The right operand of concatenation is an unbound "
594 "universal charstring element.");
595 bool other_ischar
= other_value
.str_val
.charstring
;
598 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+ 1, true);
599 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
600 cstr
.val_ptr
->n_chars
);
601 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
602 other_value
.get_uchar().uc_cell
;
605 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+ 1);
606 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
607 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
608 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
609 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
610 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
612 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
.get_uchar();
615 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
616 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
617 val_ptr
->n_uchars
* sizeof(universal_char
));
619 universal_char
& uc
= ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
];
620 uc
.uc_group
= uc
.uc_plane
= uc
.uc_row
= 0;
621 uc
.uc_cell
= other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
623 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
.get_uchar();
628 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator<<=
629 (int rotate_count
) const
631 must_bound("The left operand of rotate left operator is an unbound "
632 "universal charstring value.");
635 return cstr
<<= rotate_count
;
637 if (val_ptr
->n_uchars
== 0) return *this;
638 if (rotate_count
>= 0) {
639 rotate_count
%= val_ptr
->n_uchars
;
640 if (rotate_count
== 0) return *this;
641 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
);
642 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
+ rotate_count
,
643 (val_ptr
->n_uchars
- rotate_count
) * sizeof(universal_char
));
644 memcpy(ret_val
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
- rotate_count
,
645 val_ptr
->uchars_ptr
, rotate_count
* sizeof(universal_char
));
647 } else return *this >>= (-rotate_count
);
650 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator<<=
651 (const INTEGER
& rotate_count
) const
653 rotate_count
.must_bound("The right operand of rotate left operator is an "
654 "unbound integer value.");
655 return *this <<= (int)rotate_count
;
658 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator>>=
659 (int rotate_count
) const
661 must_bound("The left operand of rotate right operator is an unbound "
662 "universal charstring value.");
665 return cstr
>>= rotate_count
;
667 if (val_ptr
->n_uchars
== 0) return *this;
668 if (rotate_count
>= 0) {
669 rotate_count
%= val_ptr
->n_uchars
;
670 if (rotate_count
== 0) return *this;
671 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
);
672 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
+
673 val_ptr
->n_uchars
- rotate_count
, rotate_count
* sizeof(universal_char
));
674 memcpy(ret_val
.val_ptr
->uchars_ptr
+ rotate_count
, val_ptr
->uchars_ptr
,
675 (val_ptr
->n_uchars
- rotate_count
) * sizeof(universal_char
));
677 } else return *this <<= (-rotate_count
);
681 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator>>=
682 (const INTEGER
& rotate_count
) const
684 rotate_count
.must_bound("The right operand of rotate right operator is an "
685 "unbound integer value.");
686 return *this >>= (int)rotate_count
;
690 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
693 if (!charstring
&& val_ptr
== NULL
&& index_value
== 0) {
695 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE
, *this, 0);
697 must_bound("Accessing an element of an unbound universal charstring "
699 if (index_value
< 0) TTCN_error("Accessing a universal charstring element "
700 "using a negative index (%d).", index_value
);
702 charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
;
703 if (index_value
> n_uchars
) TTCN_error("Index overflow when accessing a "
704 "universal charstring element: The index is %d, but the string has only "
705 "%d characters.", index_value
, n_uchars
);
706 if (index_value
== n_uchars
) {
708 (void)cstr
[index_value
]; // invoked for side-effect only (incr. length)
710 if (val_ptr
->ref_count
== 1) {
711 val_ptr
= (universal_charstring_struct
*)
712 Realloc(val_ptr
, MEMORY_SIZE(n_uchars
+ 1));
715 universal_charstring_struct
*old_ptr
= val_ptr
;
716 old_ptr
->ref_count
--;
717 init_struct(n_uchars
+ 1);
718 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
,
719 n_uchars
* sizeof(universal_char
));
722 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE
, *this, index_value
);
723 } else return UNIVERSAL_CHARSTRING_ELEMENT(TRUE
, *this, index_value
);
727 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
728 (const INTEGER
& index_value
)
730 index_value
.must_bound("Indexing a universal charstring value with an "
731 "unbound integer value.");
732 return (*this)[(int)index_value
];
735 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
736 (int index_value
) const
738 must_bound("Accessing an element of an unbound universal charstring value.");
739 const int size
= charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
;
740 if (index_value
< 0) TTCN_error("Accessing a universal charstring element "
741 "using a negative index (%d).", index_value
);
742 else if (index_value
>= size
) TTCN_error("Index overflow when "
743 "accessing a universal charstring element: The index is %d, but the "
744 "string has only %d characters.", index_value
, size
);
745 return UNIVERSAL_CHARSTRING_ELEMENT(TRUE
,
746 const_cast<UNIVERSAL_CHARSTRING
&>(*this), index_value
);
749 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
750 (const INTEGER
& index_value
) const
752 index_value
.must_bound("Indexing a universal charstring value with an "
753 "unbound integer value.");
754 return (*this)[(int)index_value
];
758 UNIVERSAL_CHARSTRING::operator const universal_char
*() const
760 must_bound("Casting an unbound universal charstring value to const "
763 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
764 return val_ptr
->uchars_ptr
;
767 int UNIVERSAL_CHARSTRING::lengthof() const
769 must_bound("Performing lengthof operation on an unbound universal charstring "
772 return cstr
.val_ptr
->n_chars
;
773 return val_ptr
->n_uchars
;
776 char* UNIVERSAL_CHARSTRING::convert_to_regexp_form() const {
777 must_bound("Performing pattern conversion operation on an unbound"
778 "universal charstring value.");
779 int size
= (charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
) * 8 + 1;
780 char* res
= static_cast<char*>(Malloc(size
));
785 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++, ptr
+= 8) {
786 q
.set(0, 0, 0, cstr
.val_ptr
->chars_ptr
[i
]);
787 Quad::get_hexrepr(q
, ptr
);
790 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++, ptr
+= 8) {
791 q
.set(val_ptr
->uchars_ptr
[i
].uc_group
, val_ptr
->uchars_ptr
[i
].uc_plane
,
792 val_ptr
->uchars_ptr
[i
].uc_row
, val_ptr
->uchars_ptr
[i
].uc_cell
);
793 Quad::get_hexrepr(q
, ptr
);
798 static inline boolean
is_printable(const universal_char
& uchar
)
800 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
801 TTCN_Logger::is_printable(uchar
.uc_cell
);
804 CHARSTRING
UNIVERSAL_CHARSTRING::get_stringRepr_for_pattern() const {
805 must_bound("Performing pattern conversion operation on an unbound"
806 "universal charstring value.");
807 CHARSTRING
ret_val("");
809 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
810 const char& chr
= cstr
.val_ptr
->chars_ptr
[i
];
811 if (TTCN_Logger::is_printable(chr
))
814 ret_val
+= "\\q{0,0,0,";
815 ret_val
+= int2str(chr
);
820 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
821 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
822 if (is_printable(uchar
))
823 ret_val
+= uchar
.uc_cell
;
826 ret_val
+= int2str(uchar
.uc_group
);
828 ret_val
+= int2str(uchar
.uc_plane
);
830 ret_val
+= int2str(uchar
.uc_row
);
832 ret_val
+= int2str(uchar
.uc_cell
);
839 void UNIVERSAL_CHARSTRING::convert_cstr_to_uni() {
840 init_struct(cstr
.lengthof());
841 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
842 val_ptr
->uchars_ptr
[i
].uc_group
= 0;
843 val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
844 val_ptr
->uchars_ptr
[i
].uc_row
= 0;
845 val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
852 void UNIVERSAL_CHARSTRING::dump() const
854 if (val_ptr
!= NULL
) {
855 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
856 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
857 std::wcout
<< "uchar[" << i
<< "] = " << "("
858 << uchar
.uc_group
<< "," << uchar
.uc_plane
<< "," << uchar
.uc_row
<< "," << uchar
.uc_cell
<< ")"<< std::endl
;
863 void UNIVERSAL_CHARSTRING::log() const
869 if (val_ptr
!= NULL
) {
870 expstring_t buffer
= 0;
871 enum { INIT
, PCHAR
, UCHAR
} state
= INIT
;
872 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
873 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
874 if (is_printable(uchar
)) {
875 // the actual character is printable
877 case UCHAR
: // concatenation sign if previous part was not printable
878 buffer
= mputstr(buffer
, " & ");
880 case INIT
: // opening "
881 buffer
= mputc(buffer
, '"');
883 case PCHAR
: // the character itself
884 TTCN_Logger::log_char_escaped(uchar
.uc_cell
, buffer
);
889 // the actual character is not printable
891 case PCHAR
: // closing " if previous part was printable
892 buffer
= mputc(buffer
, '"');
894 case UCHAR
: // concatenation sign
895 buffer
= mputstr(buffer
, " & ");
897 case INIT
: // the character itself
898 buffer
= mputprintf(buffer
, "char(%u, %u, %u, %u)",
899 uchar
.uc_group
, uchar
.uc_plane
, uchar
.uc_row
, uchar
.uc_cell
);
907 case INIT
: // the string was empty
908 buffer
= mputstr(buffer
, "\"\"");
910 case PCHAR
: // last character was printable -> closing "
911 buffer
= mputc(buffer
, '"');
916 TTCN_Logger::log_event_str(buffer
);
919 TTCN_Logger::log_event_unbound();
923 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::from_UTF8_buffer(TTCN_Buffer
& p_buff
)
926 p_buff
.get_string(os
);
927 if ("UTF-8" == get_stringencoding(os
)) {
928 UNIVERSAL_CHARSTRING ret
;
929 ret
.decode_utf8(p_buff
.get_len(), p_buff
.get_data());
932 return UNIVERSAL_CHARSTRING(p_buff
.get_len(), (const char*)p_buff
.get_data());
936 boolean
UNIVERSAL_CHARSTRING::set_param_internal(Module_Param
& param
, boolean allow_pattern
) {
937 boolean is_pattern
= FALSE
;
938 param
.basic_check(Module_Param::BC_VALUE
|Module_Param::BC_LIST
, "universal charstring value");
939 Module_Param_Ptr mp
= ¶m
;
940 if (param
.get_type() == Module_Param::MP_Reference
) {
941 mp
= param
.get_referenced_param();
943 switch (mp
->get_type()) {
944 case Module_Param::MP_Charstring
: {
945 switch (param
.get_operation_type()) {
946 case Module_Param::OT_ASSIGN
:
949 case Module_Param::OT_CONCAT
: {
951 buff
.put_s(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
953 *this = *this + from_UTF8_buffer(buff
);
955 *this = from_UTF8_buffer(buff
);
959 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
962 case Module_Param::MP_Universal_Charstring
: {
963 switch (param
.get_operation_type()) {
964 case Module_Param::OT_ASSIGN
:
967 case Module_Param::OT_CONCAT
:
969 *this = *this + UNIVERSAL_CHARSTRING(mp
->get_string_size(), (universal_char
*)mp
->get_string_data());
971 *this = UNIVERSAL_CHARSTRING(mp
->get_string_size(), (universal_char
*)mp
->get_string_data());
975 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
978 case Module_Param::MP_Expression
:
979 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
980 UNIVERSAL_CHARSTRING operand1
, operand2
;
981 is_pattern
= operand1
.set_param_internal(*mp
->get_operand1(), allow_pattern
);
982 operand2
.set_param(*mp
->get_operand2());
983 if (param
.get_operation_type() == Module_Param::OT_CONCAT
) {
984 *this = *this + operand1
+ operand2
;
987 *this = operand1
+ operand2
;
991 param
.expr_type_error("a universal charstring");
994 case Module_Param::MP_Pattern
:
996 *this = CHARSTRING(mp
->get_pattern());
1000 // else fall through
1002 param
.type_error("universal charstring value");
1007 void UNIVERSAL_CHARSTRING::set_param(Module_Param
& param
) {
1008 set_param_internal(param
, FALSE
);
1011 Module_Param
* UNIVERSAL_CHARSTRING::get_param(Module_Param_Name
& param_name
) const
1014 return new Module_Param_Unbound();
1017 return cstr
.get_param(param_name
);
1019 universal_char
* val_cpy
= (universal_char
*)Malloc(val_ptr
->n_uchars
* sizeof(universal_char
));
1020 memcpy(val_cpy
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
* sizeof(universal_char
));
1021 return new Module_Param_Universal_Charstring(val_ptr
->n_uchars
, val_cpy
);
1024 void UNIVERSAL_CHARSTRING::encode_text(Text_Buf
& text_buf
) const
1026 must_bound("Text encoder: Encoding an unbound universal charstring value.");
1028 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1029 text_buf
.push_int(val_ptr
->n_uchars
);
1030 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
1031 unsigned char buf
[4];
1032 buf
[0] = val_ptr
->uchars_ptr
[i
].uc_group
;
1033 buf
[1] = val_ptr
->uchars_ptr
[i
].uc_plane
;
1034 buf
[2] = val_ptr
->uchars_ptr
[i
].uc_row
;
1035 buf
[3] = val_ptr
->uchars_ptr
[i
].uc_cell
;
1036 text_buf
.push_raw(4, buf
);
1040 void UNIVERSAL_CHARSTRING::decode_text(Text_Buf
& text_buf
)
1042 int n_uchars
= text_buf
.pull_int().get_val();
1043 if (n_uchars
< 0) TTCN_error("Text decoder: Negative length was received "
1044 "for a universal charstring.");
1047 init_struct(n_uchars
);
1048 for (int i
= 0; i
< n_uchars
; i
++) {
1049 unsigned char buf
[4];
1050 text_buf
.pull_raw(4, buf
);
1051 val_ptr
->uchars_ptr
[i
].uc_group
= buf
[0];
1052 val_ptr
->uchars_ptr
[i
].uc_plane
= buf
[1];
1053 val_ptr
->uchars_ptr
[i
].uc_row
= buf
[2];
1054 val_ptr
->uchars_ptr
[i
].uc_cell
= buf
[3];
1058 void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t
& p_td
,
1059 TTCN_Buffer
& p_buf
, TTCN_EncDec::coding_t p_coding
, ...) const
1062 va_start(pvar
, p_coding
);
1064 case TTCN_EncDec::CT_BER
: {
1065 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
1066 unsigned BER_coding
=va_arg(pvar
, unsigned);
1067 BER_encode_chk_coding(BER_coding
);
1068 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
1069 tlv
->put_in_buffer(p_buf
);
1070 ASN_BER_TLV_t::destruct(tlv
);
1072 case TTCN_EncDec::CT_RAW
: {
1073 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
1074 TTCN_EncDec_ErrorContext::error_internal
1075 ("No RAW descriptor available for type '%s'.", p_td
.name
);
1077 case TTCN_EncDec::CT_TEXT
: {
1078 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
1080 TTCN_EncDec_ErrorContext::error_internal
1081 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
1082 TEXT_encode(p_td
,p_buf
);
1084 case TTCN_EncDec::CT_XER
: {
1085 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
1086 unsigned XER_coding
=va_arg(pvar
, unsigned);
1087 switch (p_td
.asnbasetype
) {
1088 case TTCN_Typedescriptor_t::BMPSTRING
:
1089 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1090 XER_coding
|= XER_ESCAPE_ENTITIES
;
1092 default: // nothing to do
1095 XER_encode(*p_td
.xer
,p_buf
, XER_coding
, 0, 0);
1098 case TTCN_EncDec::CT_JSON
: {
1099 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
1101 TTCN_EncDec_ErrorContext::error_internal
1102 ("No JSON descriptor available for type '%s'.", p_td
.name
);
1103 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
1104 JSON_encode(p_td
, tok
);
1105 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
1108 TTCN_error("Unknown coding method requested to encode type '%s'",
1114 void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t
& p_td
,
1115 TTCN_Buffer
& p_buf
, TTCN_EncDec::coding_t p_coding
, ...)
1118 va_start(pvar
, p_coding
);
1120 case TTCN_EncDec::CT_BER
: {
1121 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
1122 unsigned L_form
=va_arg(pvar
, unsigned);
1124 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
1125 BER_decode_TLV(p_td
, tlv
, L_form
);
1126 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
1128 case TTCN_EncDec::CT_RAW
: {
1129 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
1130 TTCN_EncDec_ErrorContext::error_internal
1131 ("No RAW descriptor available for type '%s'.", p_td
.name
);
1133 case TTCN_EncDec::CT_TEXT
: {
1134 Limit_Token_List limit
;
1135 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
1137 TTCN_EncDec_ErrorContext::error_internal
1138 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
1139 const unsigned char *b
=p_buf
.get_data();
1140 if(b
[p_buf
.get_len()-1]!='\0'){
1141 p_buf
.set_pos(p_buf
.get_len());
1142 p_buf
.put_zero(8,ORDER_LSB
);
1145 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
1146 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
1147 "Can not decode type '%s', because invalid or incomplete"
1148 " message was received"
1151 case TTCN_EncDec::CT_XER
: {
1152 unsigned XER_coding
=va_arg(pvar
, unsigned);
1153 XmlReaderWrap
reader(p_buf
);
1154 int success
= reader
.Read();
1155 for (; success
==1; success
=reader
.Read()) {
1156 int type
= reader
.NodeType();
1157 if (type
==XML_READER_TYPE_ELEMENT
)
1160 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
1161 size_t bytes
= reader
.ByteConsumed();
1162 p_buf
.set_pos(bytes
);
1164 case TTCN_EncDec::CT_JSON
: {
1165 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
1167 TTCN_EncDec_ErrorContext::error_internal
1168 ("No JSON descriptor available for type '%s'.", p_td
.name
);
1169 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
1170 if(JSON_decode(p_td
, tok
, false)<0)
1171 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
1172 "Can not decode type '%s', because invalid or incomplete"
1173 " message was received"
1175 p_buf
.set_pos(tok
.get_buf_pos());
1178 TTCN_error("Unknown coding method requested to decode type '%s'",
1185 UNIVERSAL_CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
1186 unsigned p_coding
) const
1189 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1190 BER_chk_descr(p_td
);
1191 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
1194 switch(p_td
.asnbasetype
) {
1195 case TTCN_Typedescriptor_t::TELETEXSTRING
:
1196 buf
.put_os(TTCN_TeletexString_2_ISO2022(*this));
1198 case TTCN_Typedescriptor_t::VIDEOTEXSTRING
:
1199 buf
.put_os(TTCN_VideotexString_2_ISO2022(*this));
1201 case TTCN_Typedescriptor_t::GRAPHICSTRING
:
1202 buf
.put_os(TTCN_GraphicString_2_ISO2022(*this));
1204 case TTCN_Typedescriptor_t::GENERALSTRING
:
1205 buf
.put_os(TTCN_GeneralString_2_ISO2022(*this));
1207 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1208 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1209 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_group
);
1210 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_plane
);
1211 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_row
);
1212 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_cell
);
1215 case TTCN_Typedescriptor_t::BMPSTRING
:
1216 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1217 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_row
);
1218 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_cell
);
1221 case TTCN_Typedescriptor_t::UTF8STRING
:
1225 TTCN_EncDec_ErrorContext::error_internal
1226 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
1228 new_tlv
=BER_encode_TLV_OCTETSTRING
1229 (p_coding
, buf
.get_read_len(), buf
.get_read_data());
1231 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
1234 int UNIVERSAL_CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
1235 TTCN_Buffer
& buff
, Limit_Token_List
& limit
, boolean no_err
, boolean
/*first_call*/)
1237 int decoded_length
= 0;
1240 if (p_td
.text
->begin_decode
) {
1242 if ((tl
= p_td
.text
->begin_decode
->match_begin(buff
)) < 0) {
1243 if (no_err
) return -1;
1244 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1245 "The specified token '%s' not found for '%s': ",
1246 (const char*) *(p_td
.text
->begin_decode
), p_td
.name
);
1249 decoded_length
+= tl
;
1250 buff
.increase_pos(tl
);
1252 // never return "not enough bits"
1253 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
1255 if (p_td
.text
->select_token
) {
1257 if ((tl
= p_td
.text
->select_token
->match_begin(buff
)) < 0) {
1258 if (no_err
) return -1;
1263 // The length restriction needs some more work
1264 /* else if ( p_td.text->val.parameters
1265 && p_td.text->val.parameters->decoding_params.min_length != -1) {
1266 str_len = p_td.text->val.parameters->decoding_params.min_length;
1268 else if (p_td
.text
->end_decode
) {
1270 if ((tl
= p_td
.text
->end_decode
->match_first(buff
)) < 0) {
1271 if (no_err
) return -1;
1276 else if (limit
.has_token()) {
1278 if ((tl
= limit
.match(buff
)) < 0) tl
= buff
.get_read_len() - 1;
1282 str_len
= buff
.get_read_len() - 1;
1285 // only utf8 is supported now.
1286 decode_utf8(str_len
,buff
.get_read_data());
1288 decoded_length
+= str_len
;
1289 buff
.increase_pos(str_len
);
1291 // Case conversion is an another study
1292 // and it is locale dependent
1293 /* if ( p_td.text->val.parameters
1294 && p_td.text->val.parameters->decoding_params.convert != 0) {
1295 if (p_td.text->val.parameters->decoding_params.convert == 1) {
1296 for (int a = 0; a < str_len; a++) {
1297 val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
1301 for (int a = 0; a < str_len; a++) {
1302 val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
1306 if (p_td
.text
->end_decode
) {
1308 if ((tl
= p_td
.text
->end_decode
->match_begin(buff
)) < 0) {
1309 if (no_err
) return -1;
1310 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1311 "The specified token '%s' not found for '%s': ",
1312 (const char*) *(p_td
.text
->end_decode
), p_td
.name
);
1315 decoded_length
+= tl
;
1316 buff
.increase_pos(tl
);
1318 return decoded_length
;
1321 int UNIVERSAL_CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1322 TTCN_Buffer
& buff
) const{
1323 int encoded_length
=0;
1324 if(p_td
.text
->begin_encode
){
1325 buff
.put_cs(*p_td
.text
->begin_encode
);
1326 encoded_length
+=p_td
.text
->begin_encode
->lengthof();
1329 TTCN_EncDec_ErrorContext::error
1330 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound value.");
1331 if(p_td
.text
->end_encode
){
1332 buff
.put_cs(*p_td
.text
->end_encode
);
1333 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1335 return encoded_length
;
1338 // The length restriction and case conversion will be added later
1339 // if(p_td.text->val.parameters==NULL){
1341 int base_size
=buff
.get_len(); // strore the current length of the data
1346 encoded_length
+=buff
.get_len()-base_size
; // calculate the number of the
1352 if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
1353 switch(p_td.text->val.parameters->coding_params.just){
1355 chars_after=p_td.text->
1356 val.parameters->coding_params.min_length-val_ptr->n_chars;
1360 val.parameters->coding_params.min_length-val_ptr->n_chars;
1362 chars_before=pad-chars_after;
1367 chars_before=p_td.text->
1368 val.parameters->coding_params.min_length-val_ptr->n_chars;
1373 unsigned char* p=NULL;
1374 size_t len=chars_before;
1375 buff.get_end(p,len);
1376 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
1377 buff.increase_length(chars_before);
1378 encoded_length+=chars_before;
1381 switch(p_td.text->val.parameters->coding_params.convert){
1382 case -1:{ //lower_case
1383 unsigned char* p=NULL;
1384 size_t len=val_ptr->n_chars;
1385 buff.get_end(p,len);
1386 for(int a=0;a<val_ptr->n_chars;a++)
1387 p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
1388 buff.increase_length(val_ptr->n_chars);
1391 case 0:{ // no conversion
1395 case 1: // upper_case
1398 unsigned char* p=NULL;
1399 size_t len=val_ptr->n_chars;
1400 buff.get_end(p,len);
1401 for(int a=0;a<val_ptr->n_chars;a++)
1402 p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
1403 buff.increase_length(val_ptr->n_chars);
1407 encoded_length+=val_ptr->n_chars;
1410 unsigned char* p=NULL;
1411 size_t len=chars_after;
1412 buff.get_end(p,len);
1413 for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
1414 buff.increase_length(chars_after);
1415 encoded_length+=chars_after;
1420 if(p_td
.text
->end_encode
){
1421 buff
.put_cs(*p_td
.text
->end_encode
);
1422 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1424 return encoded_length
;
1427 void UNIVERSAL_CHARSTRING::encode_utf8(TTCN_Buffer
& buf
, bool addBOM
/*= false*/) const
1436 buf
.put_s(cstr
.val_ptr
->n_chars
, (unsigned char*)cstr
.val_ptr
->chars_ptr
);
1437 // put_s avoids the check for boundness in put_cs
1440 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1441 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1442 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1443 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1444 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1445 if(g
==0x00 && p
<=0x1F) {
1447 if(r
==0x00 && c
<=0x7F) {
1453 buf
.put_c(0xC0|r
<<2|c
>>6);
1454 buf
.put_c(0x80|(c
&0x3F));
1458 buf
.put_c(0xE0|r
>>4);
1459 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1460 buf
.put_c(0x80|(c
&0x3F));
1465 buf
.put_c(0xF0|p
>>2);
1466 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1467 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1468 buf
.put_c(0x80|(c
&0x3F));
1474 buf
.put_c(0x80|p
>>2);
1475 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1476 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1477 buf
.put_c(0x80|(c
&0x3F));
1481 buf
.put_c(0xFC|g
>>6);
1482 buf
.put_c(0x80|(g
&0x3F));
1483 buf
.put_c(0x80|p
>>2);
1484 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1485 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1486 buf
.put_c(0x80|(c
&0x3F));
1492 void UNIVERSAL_CHARSTRING::encode_utf16(TTCN_Buffer
& buf
,
1493 CharCoding::CharCodingType expected_coding
) const
1497 switch (expected_coding
) {
1498 case CharCoding::UTF16
:
1499 case CharCoding::UTF16BE
:
1502 case CharCoding::UTF16LE
:
1506 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1507 "Unexpected coding type for UTF-16 encoding");
1510 buf
.put_c(isbig
? 0xFE : 0xFF);
1511 buf
.put_c(isbig
? 0xFF : 0xFE);
1514 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
1515 buf
.put_c(isbig
? 0 : cstr
.val_ptr
->chars_ptr
[i
]);
1516 buf
.put_c(isbig
? cstr
.val_ptr
->chars_ptr
[i
] : 0);
1520 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1521 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1522 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1523 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1524 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1525 if (g
|| (0x10 < p
)) {
1526 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1527 "Any UCS code (0x%02X%02X%02X%02X) to be encoded into UTF-16 "
1528 "shall not be greater than 0x10FFFF", g
, p
, r
, c
);
1530 else if (0x00 == g
&& 0x00 ==p
&& 0xD8 <= r
&& 0xDF >= r
) {
1531 // Values between 0xD800 and 0xDFFF are specifically reserved for use with UTF-16,
1532 // and don't have any characters assigned to them.
1533 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1534 "Any UCS code (0x%02X%02X) between 0xD800 and 0xDFFF is ill-formed", r
,c
);
1536 else if (0x00 == g
&& 0x00 == p
) {
1537 buf
.put_c(isbig
? r
: c
);
1538 buf
.put_c(isbig
? c
: r
);
1540 else if (g
|| p
) { // greater than 0xFFFF it needs surrogates
1541 uint32_t univc
= 0, temp
= 0;
1551 univc
|= c
; // universal char filled in univc
1552 uint16_t W1
= 0xD800;
1553 uint16_t W2
= 0xDC00;
1554 uint32_t univcmod
= univc
- 0x10000;
1555 uint16_t WH
= univcmod
>> 10;
1556 uint16_t WL
= univcmod
& 0x3ff;
1560 uc
= isbig
? W1
>> 8 : W1
;
1562 uc
= isbig
? W1
: W1
>> 8;
1564 uc
= isbig
? W2
>> 8 : W2
;
1566 uc
= isbig
? W2
: W2
>> 8;
1573 void UNIVERSAL_CHARSTRING::encode_utf32(TTCN_Buffer
& buf
,
1574 CharCoding::CharCodingType expected_coding
) const
1577 switch (expected_coding
) {
1578 case CharCoding::UTF32
:
1579 case CharCoding::UTF32BE
:
1582 case CharCoding::UTF32LE
:
1586 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1587 "Unexpected coding type for UTF-32 encoding");
1591 buf
.put_c(isbig
? 0x00 : 0xFF);
1592 buf
.put_c(isbig
? 0x00 : 0xFE);
1593 buf
.put_c(isbig
? 0xFE : 0x00);
1594 buf
.put_c(isbig
? 0xFF : 0x00);
1597 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
1598 buf
.put_c(isbig
? 0 : cstr
.val_ptr
->chars_ptr
[i
]);
1601 buf
.put_c(isbig
? cstr
.val_ptr
->chars_ptr
[i
] : 0);
1605 for(int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1606 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1607 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1608 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1609 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1610 uint32_t DW
= g
<< 8 | p
;
1615 if (0x0000D800 <= DW
&& 0x0000DFFF >= DW
) {
1616 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1617 "Any UCS code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW
);
1619 else if (0x0010FFFF < DW
) {
1620 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1621 "Any UCS code (0x%08X) greater than 0x0010FFFF is ill-formed", DW
);
1624 buf
.put_c(isbig
? g
: c
);
1625 buf
.put_c(isbig
? p
: r
);
1626 buf
.put_c(isbig
? r
: p
);
1627 buf
.put_c(isbig
? c
: g
);
1633 #ifdef TITAN_RUNTIME_2
1635 int UNIVERSAL_CHARSTRING::encode_raw(TTCN_Buffer
& p_buf
) const
1637 size_t len_before
= p_buf
.get_len();
1639 return p_buf
.get_len() - len_before
;
1642 int UNIVERSAL_CHARSTRING::JSON_encode_negtest_raw(JSON_Tokenizer
& p_tok
) const
1644 TTCN_Buffer tmp_buf
;
1645 encode_utf8(tmp_buf
);
1646 p_tok
.put_raw_data((const char*)tmp_buf
.get_data(), tmp_buf
.get_len());
1647 return tmp_buf
.get_len();
1652 boolean
UNIVERSAL_CHARSTRING::BER_decode_TLV
1653 (const TTCN_Typedescriptor_t
& p_td
, const ASN_BER_TLV_t
& p_tlv
,
1658 TTCN_EncDec_ErrorContext
ec("While decoding universal charstring type: ");
1660 if(!ostr
.BER_decode_TLV(p_td
, p_tlv
, L_form
)) return FALSE
;
1661 int os_len
=ostr
.lengthof();
1663 const unsigned char* os
=ostr
;
1664 switch(p_td
.asnbasetype
) {
1665 case TTCN_Typedescriptor_t::TELETEXSTRING
:
1666 *this=TTCN_ISO2022_2_TeletexString(ostr
);
1668 case TTCN_Typedescriptor_t::VIDEOTEXSTRING
:
1669 *this=TTCN_ISO2022_2_VideotexString(ostr
);
1671 case TTCN_Typedescriptor_t::GRAPHICSTRING
:
1672 *this=TTCN_ISO2022_2_GraphicString(ostr
);
1674 case TTCN_Typedescriptor_t::GENERALSTRING
:
1675 *this=TTCN_ISO2022_2_GeneralString(ostr
);
1677 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1679 TTCN_EncDec_ErrorContext::error
1680 (TTCN_EncDec::ET_DEC_UCSTR
, "Length of UCS-4-coded character"
1681 " string is not multiple of 4.");
1683 init_struct(ucs_len
);
1684 for(int i
=0; i
<ucs_len
; i
++) {
1685 val_ptr
->uchars_ptr
[i
].uc_group
=os
[0];
1686 val_ptr
->uchars_ptr
[i
].uc_plane
=os
[1];
1687 val_ptr
->uchars_ptr
[i
].uc_row
=os
[2];
1688 val_ptr
->uchars_ptr
[i
].uc_cell
=os
[3];
1692 case TTCN_Typedescriptor_t::BMPSTRING
:
1694 TTCN_EncDec_ErrorContext::error
1695 (TTCN_EncDec::ET_DEC_UCSTR
, "Length of UCS-2-coded character"
1696 " string is not multiple of 2.");
1698 init_struct(ucs_len
);
1699 for(int i
=0; i
<ucs_len
; i
++) {
1700 val_ptr
->uchars_ptr
[i
].uc_group
=0;
1701 val_ptr
->uchars_ptr
[i
].uc_plane
=0;
1702 val_ptr
->uchars_ptr
[i
].uc_row
=os
[0];
1703 val_ptr
->uchars_ptr
[i
].uc_cell
=os
[1];
1707 case TTCN_Typedescriptor_t::UTF8STRING
:
1708 decode_utf8(os_len
, os
);
1711 TTCN_EncDec_ErrorContext::error_internal
1712 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
1717 extern void xml_escape(const unsigned int c
, TTCN_Buffer
& p_buf
);
1719 int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t
& p_td
,
1720 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
1723 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1724 "Encoding an unbound UNIVERSAL CHARSTRING value.");
1727 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1728 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
1729 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1730 int encoded_length
=(int)p_buf
.get_len();
1731 bool do_empty_element
= val_ptr
==NULL
|| val_ptr
->n_uchars
== 0;
1733 flavor
&= ~XER_RECOF
; // universal charstring doesn't care
1734 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) {
1735 if (!is_canonical(flavor
)) {
1736 // Although ANY_ELEMENT is not canonical, this flag is still used to disable
1737 // indenting in a record/set with EMBED_VALUES
1738 do_indent(p_buf
, indent
);
1742 if (do_empty_element
&& exer
&& p_td
.dfeValue
!= 0) {
1743 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR
,
1744 "An encoded value with DEFAULT-FOR-EMPTY instruction "
1745 "applied should not be empty");
1747 if (begin_xml(p_td
, p_buf
, flavor
, indent
, do_empty_element
) == -1) {
1750 } // not any_element
1752 #define UCH(c) {0,0,0,c}
1753 if (!do_empty_element
) {
1754 if (flavor
& XER_ESCAPE_ENTITIES
) {
1755 for (int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1756 unsigned int ucs4
= unichar2int(val_ptr
->uchars_ptr
[i
]);
1757 xml_escape( ucs4
, p_buf
);
1760 else { // UTF-8 needs only to escape the low 32 and these five: <&>
1761 TTCN_Buffer other_buf
;
1762 static const universal_char amp
[] = { UCH('&'), UCH('a'), UCH('m'),
1763 UCH('p'), UCH(';') };
1764 static const universal_char lt
[] = { UCH('&'), UCH('l'), UCH('t'),
1766 static const universal_char gt
[] = { UCH('&'), UCH('g'), UCH('t'),
1768 static const universal_char apos
[]= { UCH('&'), UCH('a'), UCH('p'),
1769 UCH('o'), UCH('s'), UCH(';') };
1770 static const universal_char quot
[]= { UCH('&'), UCH('q'), UCH('u'),
1771 UCH('o'), UCH('t'), UCH(';') };
1773 static const universal_char escapes
[32][6] = {
1774 {UCH('<'), UCH('n'), UCH('u'), UCH('l'), UCH('/'), UCH('>')},
1775 {UCH('<'), UCH('s'), UCH('o'), UCH('h'), UCH('/'), UCH('>')},
1776 {UCH('<'), UCH('s'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1777 {UCH('<'), UCH('e'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1778 {UCH('<'), UCH('e'), UCH('o'), UCH('t'), UCH('/'), UCH('>')},
1779 {UCH('<'), UCH('e'), UCH('n'), UCH('q'), UCH('/'), UCH('>')},
1780 {UCH('<'), UCH('a'), UCH('c'), UCH('k'), UCH('/'), UCH('>')},
1781 {UCH('<'), UCH('b'), UCH('e'), UCH('l'), UCH('/'), UCH('>')},
1783 {UCH('<'), UCH('b'), UCH('s'), UCH('/'), UCH('>')},
1784 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('9'), UCH(';')}, // TAB
1785 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('A'), UCH(';')}, // LF
1786 {UCH('<'), UCH('v'), UCH('t'), UCH('/'), UCH('>')},
1787 {UCH('<'), UCH('f'), UCH('f'), UCH('/'), UCH('>')},
1788 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('D'), UCH(';')}, // CR
1789 {UCH('<'), UCH('s'), UCH('o'), UCH('/'), UCH('>')},
1790 {UCH('<'), UCH('s'), UCH('i'), UCH('/'), UCH('>')},
1792 {UCH('<'), UCH('d'), UCH('l'), UCH('e'), UCH('/'), UCH('>')},
1793 {UCH('<'), UCH('d'), UCH('c'), UCH('1'), UCH('/'), UCH('>')},
1794 {UCH('<'), UCH('d'), UCH('c'), UCH('2'), UCH('/'), UCH('>')},
1795 {UCH('<'), UCH('d'), UCH('c'), UCH('3'), UCH('/'), UCH('>')},
1796 {UCH('<'), UCH('d'), UCH('c'), UCH('4'), UCH('/'), UCH('>')},
1797 {UCH('<'), UCH('n'), UCH('a'), UCH('k'), UCH('/'), UCH('>')},
1798 {UCH('<'), UCH('s'), UCH('y'), UCH('n'), UCH('/'), UCH('>')},
1799 {UCH('<'), UCH('e'), UCH('t'), UCH('b'), UCH('/'), UCH('>')},
1801 {UCH('<'), UCH('c'), UCH('a'), UCH('n'), UCH('/'), UCH('>')},
1802 {UCH('<'), UCH('e'), UCH('m'), UCH('/'), UCH('>')},
1803 {UCH('<'), UCH('s'), UCH('u'), UCH('b'), UCH('/'), UCH('>')},
1804 {UCH('<'), UCH('e'), UCH('s'), UCH('c'), UCH('/'), UCH('>')},
1805 {UCH('<'), UCH('i'), UCH('s'), UCH('4'), UCH('/'), UCH('>')},
1806 {UCH('<'), UCH('i'), UCH('s'), UCH('3'), UCH('/'), UCH('>')},
1807 {UCH('<'), UCH('i'), UCH('s'), UCH('2'), UCH('/'), UCH('>')},
1808 {UCH('<'), UCH('i'), UCH('s'), UCH('1'), UCH('/'), UCH('>')}
1811 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) { // no escaping
1812 TTCN_EncDec_ErrorContext
ec("While checking anyElement: ");
1813 encode_utf8(other_buf
);
1814 XmlReaderWrap
checker(other_buf
);
1815 // Walk through the XML. If it's not well-formed, XmlReaderWrap
1816 // will call TTCN_error => Dynamic testcase error.
1817 while (1 == checker
.Read()) {
1818 if (checker
.NodeType() == XML_READER_TYPE_ELEMENT
&&
1819 (p_td
.xer_bits
& (ANY_FROM
| ANY_EXCEPT
))) {
1820 const char* xmlns
= (const char*)checker
.NamespaceUri();
1821 check_namespace_restrictions(p_td
, xmlns
);
1825 // other_buf is already UTF-8, just append it
1826 p_buf
.put_buf(other_buf
);
1828 else if (flavor
& ANY_ATTRIBUTES
) { // no escaping
1829 encode_utf8(other_buf
);
1830 p_buf
.put_buf(other_buf
);
1833 for (int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1834 int char_val
= unichar2int(val_ptr
->uchars_ptr
[i
]);
1835 size_t len
= 6; // 3 letters + the surrounding '<', '/' and '>'
1838 other_buf
.put_s(20, &(amp
[0].uc_group
));
1842 other_buf
.put_s(16, &(lt
[0].uc_group
));
1846 other_buf
.put_s(16, &(gt
[0].uc_group
));
1849 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1850 // so if they appear in content they must be escaped.
1851 // Currently this happens even if the string is not an attribute.
1852 other_buf
.put_s(24, &(apos
[0].uc_group
));
1855 case '\"': // HR58225
1856 other_buf
.put_s(24, &(quot
[0].uc_group
));
1859 case 8: case 11: case 12: case 14: case 15: case 25:
1860 // the name of these control characters has only two letters
1863 case 0: case 1: case 2: case 3: case 4: case 5: case 6:
1864 case 7: case 16: case 17: case 18: case 19: case 20: case 21:
1865 case 22: case 23: case 24: case 26: case 27: case 28: case 29:
1867 other_buf
.put_s(len
* 4, &(escapes
[char_val
][0].uc_group
));
1870 case 9: case 10: case 13:
1871 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1872 // X.693 20.3.15: TAB,LF,CR also needs to be escaped in ATTRIBUTE
1873 other_buf
.put_s(24, &(escapes
[char_val
][0].uc_group
));
1875 } // else fall through
1878 other_buf
.put_s(4, &(val_ptr
->uchars_ptr
[i
].uc_group
));
1882 // other_buf contains UCS-4, need to encode it
1883 UNIVERSAL_CHARSTRING cs
;
1884 other_buf
.get_string(cs
);
1885 (cs
).encode_utf8(p_buf
);
1886 } // not any_element
1887 } // if ESCAPE_ENTITIES
1889 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
) && !is_canonical(flavor
)) {
1894 end_xml(p_td
, p_buf
, flavor
, indent
, do_empty_element
);
1896 return (int)p_buf
.get_len() - encoded_length
;
1899 /* Hashing for xmlcstring representation of control characters.
1900 * This function was generated by gperf 3.0.3
1901 * (GNU perfect hash function generator) from the list of control character
1902 * names, one per line, like this:
1909 * See the ASN.1 standard, X.680/2002, clause 11.15.5
1913 hash (register const char *str
, register unsigned int len
)
1915 static unsigned char asso_values
[] =
1917 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1918 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1919 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1920 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1921 104, 104, 104, 104, 104, 104, 104, 104, 104, 1,
1922 60, 55, 45, 104, 104, 104, 104, 104, 104, 104,
1923 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1924 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1925 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1926 104, 104, 104, 104, 104, 104, 104, 10, 10, 50,
1927 40, 15, 0, 104, 6, 15, 104, 1, 5, 10,
1928 0, 20, 104, 15, 0, 0, 30, 104, 0, 104,
1929 20, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1930 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1931 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1932 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1933 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1934 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1935 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1936 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1937 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1938 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1939 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1940 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1941 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1942 104, 104, 104, 104, 104, 104
1944 return len
+ asso_values
[(unsigned char)str
[len
- 1]] +
1945 asso_values
[(unsigned char)str
[0]];
1948 /* This function was also generated by gperf and hand-edited afterwards.
1949 * The original wordlist[] was an array of strings containing the names of
1950 * the control characters, with empty strings as fillers. These have been
1951 * replaced with the actual numerical values of the control characters,
1952 * with -1 as the filler.
1956 in_word_set (const char *str
, unsigned int len
)
1958 static char wordlist
[] =
2005 -1, -1, -1, -1, -1, -1, -1, -1, -1,
2007 -1, -1, -1, -1, -1, -1, -1, -1, -1,
2012 #define MIN_WORD_LENGTH 2
2013 #define MAX_WORD_LENGTH 3
2014 #define MIN_HASH_VALUE 2
2015 #define MAX_HASH_VALUE 103
2017 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2019 register int key
= hash (str
, len
);
2021 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2023 register const char s
= wordlist
[key
];
2030 universal_char
const uspace
= {0,0,0,32};
2032 int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t
& p_td
,
2033 XmlReaderWrap
& reader
, unsigned int flavor
, embed_values_dec_struct_t
*)
2035 int exer
= is_exer(flavor
);
2036 int success
= reader
.Ok(), depth
= -1;
2037 bool omit_tag
= exer
2038 && ((p_td
.xer_bits
& UNTAGGED
)
2039 || (flavor
& (EMBED_VALUES
|XER_LIST
|USE_TYPE_ATTR
|ANY_ATTRIBUTES
|USE_NIL
)));
2041 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) {
2042 TTCN_EncDec_ErrorContext
ec("While checking anyElement: ");
2043 for (; success
== 1; success
= reader
.Read()) {
2044 int type
= reader
.NodeType();
2045 if (-1 == depth
&& XML_READER_TYPE_ELEMENT
== type
) {
2046 xmlChar
* value
= reader
.ReadOuterXml();
2047 size_t num_chars
= strlen((const char*)value
);
2050 decode_utf8(num_chars
, value
); // does init_struct
2053 if (p_td
.xer_bits
& (ANY_FROM
| ANY_EXCEPT
)) {
2054 const char* xmlns
= (const char*)reader
.NamespaceUri();
2055 check_namespace_restrictions(p_td
, xmlns
);
2058 if (reader
.IsEmptyElement()) {
2059 reader
.Read(); // skip past the empty element and we're done
2062 depth
= reader
.Depth(); // signals that we have the element's text
2063 // Stay in the loop until we reach the corresponding end tag
2065 else if (reader
.Depth() == depth
&& XML_READER_TYPE_END_ELEMENT
== type
) {
2066 reader
.Read(); // one last time
2070 // ANY-ELEMENT and WHITESPACE are mutually exclusive,
2071 // so this branch skips WHITESPACE processing
2073 else { // not ANY-ELEMENT
2074 clean_up(); // start with a clean slate
2076 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
2077 // we have it easy (but does decode_utf8 handle &nnn; ?)
2078 const char * name
= verify_name(reader
, p_td
, exer
);
2080 const char * value
= (const char *)reader
.Value();
2081 int len
= strlen(value
);
2082 decode_utf8(len
, (cbyte
*)value
);
2084 // Let the caller do reader.AdvanceAttribute();
2086 else { // not an attribute either
2087 // Get to the start of data.
2088 if (!omit_tag
) for (; success
== 1; success
= reader
.Read()) {
2089 int type
= reader
.NodeType();
2090 if (XML_READER_TYPE_ELEMENT
== type
) {
2091 verify_name(reader
, p_td
, exer
);
2092 if (reader
.IsEmptyElement()) {
2093 if (exer
&& p_td
.dfeValue
!= 0) {
2094 *this = *static_cast<const UNIVERSAL_CHARSTRING
*>(p_td
.dfeValue
);
2096 else init_struct(0); // it's an empty string
2097 reader
.Read(); // move on
2100 depth
= reader
.Depth();
2101 success
= reader
.Read();
2104 else if (XML_READER_TYPE_TEXT
== type
&& omit_tag
)
2106 else // if XML_READER_TYPE_END_ELEMENT, panic?
2111 TTCN_Buffer accumulator
;
2112 if (flavor
& PARENT_CLOSED
) {} // do nothing
2113 else for (; success
==1; success
= reader
.Read()) {
2114 int type
= reader
.NodeType();
2116 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE
:
2117 case XML_READER_TYPE_TEXT
:
2118 case XML_READER_TYPE_CDATA
: {
2119 const char * text
= (const char*)reader
.Value();
2120 int len
= strlen(text
);
2121 accumulator
.put_s(len
, (cbyte
*)text
);
2124 case XML_READER_TYPE_ELEMENT
: { // escaped control character
2125 const char * name
= (const char*)reader
.LocalName();
2126 size_t len
= strlen(name
);
2127 char ctrl
= in_word_set(name
, len
);
2129 accumulator
.put_c(ctrl
);
2132 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2133 "Invalid escape sequence '<%s/>'", name
);
2137 case XML_READER_TYPE_END_ELEMENT
: {
2138 decode_utf8(accumulator
.get_len(), accumulator
.get_data());
2140 verify_end(reader
, p_td
, depth
, exer
);
2141 reader
.Read(); // Moved to a different XML node!
2142 if (val_ptr
->n_uchars
== 0 && exer
&& p_td
.dfeValue
!= 0) {
2143 // This should be the <foo></foo> case. Treat it like <foo/>
2144 *this = *static_cast<const UNIVERSAL_CHARSTRING
*>(p_td
.dfeValue
);
2147 goto fini
; } // double "break" of switch and for loop
2153 } // endif (attribute)
2155 if (exer
&& p_td
.whitespace
>= WHITESPACE_REPLACE
) { // includes _COLLAPSE
2156 for(int i
=0; i
<val_ptr
->n_uchars
; ++i
) { // first, _REPLACE
2157 switch ( unichar2int(val_ptr
->uchars_ptr
[i
]) ) {
2158 case 9: // HORIZONTAL TAB
2159 case 10: // LINE FEED
2160 case 13: // CARRIAGE RETURN
2161 val_ptr
->uchars_ptr
[i
] = uspace
;
2168 if (p_td
.whitespace
>= WHITESPACE_COLLAPSE
) {
2170 const universal_char
*from
, *end
=
2171 val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
;
2172 for (from
= to
= val_ptr
->uchars_ptr
; from
< end
;) {
2174 // If the copied character (*to) was a space,
2175 // and the next character to be copied (*from) is also a space
2176 // (continuous run of spaces)
2177 // or this was the first character (leading spaces to be trimmed),
2178 // then don't advance the destination (will be overwritten).
2180 || (from
< end
&& *from
!= uspace
&& to
> val_ptr
->uchars_ptr
))
2183 val_ptr
->n_uchars
= to
- val_ptr
->uchars_ptr
;
2186 } // not ANY_ELEMENT
2187 return 1; // decode successful
2190 char* UNIVERSAL_CHARSTRING::to_JSON_string(const TTCN_Buffer
& p_buf
) const
2192 const unsigned char* ustr
= p_buf
.get_data();
2193 const size_t ustr_len
= p_buf
.get_len();
2195 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
2196 char* json_str
= (char*)Malloc(ustr_len
+ 3);
2199 json_str
= mputc(json_str
, '\"');
2201 for (size_t i
= 0; i
< ustr_len
; ++i
) {
2202 // Increase the size of the buffer if it's not big enough to store the
2203 // characters remaining in the universal charstring
2206 json_str
= mputstrn(json_str
, "\\\\", 2);
2209 json_str
= mputstrn(json_str
, "\\n", 2);
2212 json_str
= mputstrn(json_str
, "\\t", 2);
2215 json_str
= mputstrn(json_str
, "\\r", 2);
2218 json_str
= mputstrn(json_str
, "\\f", 2);
2221 json_str
= mputstrn(json_str
, "\\b", 2);
2224 json_str
= mputstrn(json_str
, "\\\"", 2);
2227 json_str
= mputc(json_str
, (char)ustr
[i
]);
2232 json_str
= mputc(json_str
, '\"');
2236 boolean
UNIVERSAL_CHARSTRING::from_JSON_string(boolean check_quotes
)
2238 int json_len
= val_ptr
->n_uchars
;
2239 universal_char
* json_str
= val_ptr
->uchars_ptr
;
2246 if (!json_str
[0].is_char() || json_str
[0].uc_cell
!= '\"' ||
2247 !json_str
[json_len
- 1].is_char() || json_str
[json_len
- 1].uc_cell
!= '\"') {
2252 // The resulting string will be shorter than the JSON string, at least by the 2 quotes
2253 universal_char
* ustr
= (universal_char
*)Malloc((json_len
- 2) * sizeof(universal_char
));
2254 memset(ustr
, 0, sizeof(universal_char
) * (json_len
- 2));
2256 boolean error
= false;
2258 for (int i
= start
; i
< end
; ++i
) {
2259 if (json_str
[i
].is_char() && '\\' == json_str
[i
].uc_cell
) {
2260 if (i
== end
- 1 || !json_str
[i
+ 1].is_char()) {
2264 switch(json_str
[i
+ 1].uc_cell
) {
2266 ustr
[ustr_len
++].uc_cell
= '\n';
2269 ustr
[ustr_len
++].uc_cell
= '\t';
2272 ustr
[ustr_len
++].uc_cell
= '\r';
2275 ustr
[ustr_len
++].uc_cell
= '\f';
2278 ustr
[ustr_len
++].uc_cell
= '\b';
2281 ustr
[ustr_len
++].uc_cell
= '\\';
2284 ustr
[ustr_len
++].uc_cell
= '\"';
2287 ustr
[ustr_len
++].uc_cell
= '/';
2290 if (end
- i
>= 6 && json_str
[i
+ 2].is_char() && json_str
[i
+ 3].is_char() &&
2291 json_str
[i
+ 4].is_char() && json_str
[i
+ 5].is_char()) {
2292 unsigned char row_upper_nibble
= char_to_hexdigit(json_str
[i
+ 2].uc_cell
);
2293 unsigned char row_lower_nibble
= char_to_hexdigit(json_str
[i
+ 3].uc_cell
);
2294 unsigned char cell_upper_nibble
= char_to_hexdigit(json_str
[i
+ 4].uc_cell
);
2295 unsigned char cell_lower_nibble
= char_to_hexdigit(json_str
[i
+ 5].uc_cell
);
2296 if (row_upper_nibble
<= 0x0F && row_lower_nibble
<= 0x0F &&
2297 cell_upper_nibble
<= 0x0F && cell_lower_nibble
<= 0x0F) {
2298 ustr
[ustr_len
].uc_row
= (row_upper_nibble
<< 4) | row_lower_nibble
;
2299 ustr
[ustr_len
++].uc_cell
= (cell_upper_nibble
<< 4) | cell_lower_nibble
;
2300 // skip 4 extra characters (the 4 hex digits)
2303 // error (encountered something other than a hex digit) -> leave the for cycle
2308 // error (not enough characters or the 'hex digits' are not even ascii characters) -> leave the for cycle
2315 // error (invalid escaped character) -> leave the for cycle
2320 // skip an extra character (the \)
2323 ustr
[ustr_len
++] = json_str
[i
];
2326 if (check_quotes
&& i
== json_len
- 1) {
2327 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
2334 init_struct(ustr_len
);
2335 memcpy(val_ptr
->uchars_ptr
, ustr
, ustr_len
* sizeof(universal_char
));
2341 int UNIVERSAL_CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
) const
2344 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
2345 "Encoding an unbound universal charstring value.");
2351 tmp_str
= cstr
.to_JSON_string();
2353 TTCN_Buffer tmp_buf
;
2354 encode_utf8(tmp_buf
);
2355 tmp_str
= to_JSON_string(tmp_buf
);
2357 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
2362 int UNIVERSAL_CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
2364 json_token_t token
= JSON_TOKEN_NONE
;
2366 size_t value_len
= 0;
2368 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
2370 // No JSON data in the buffer -> use default value
2371 value
= (char*)p_td
.json
->default_value
;
2372 value_len
= strlen(value
);
2374 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
2376 if (JSON_TOKEN_ERROR
== token
) {
2377 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
2378 return JSON_ERROR_FATAL
;
2380 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
2381 if (cstr
.from_JSON_string(value
, value_len
, !use_default
)) {
2386 decode_utf8(value_len
, (unsigned char*)value
);
2387 if (!from_JSON_string(!use_default
)) {
2388 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "universal charstring");
2392 return JSON_ERROR_FATAL
;
2396 return JSON_ERROR_INVALID_TOKEN
;
2402 static void fill_continuing_octets(int n_continuing
,
2403 unsigned char *continuing_ptr
, int n_octets
,
2404 const unsigned char *octets_ptr
, int start_pos
, int uchar_pos
)
2406 for (int i
= 0; i
< n_continuing
; i
++) {
2407 if (start_pos
+ i
< n_octets
) {
2408 unsigned char octet
= octets_ptr
[start_pos
+ i
];
2409 if ((octet
& 0xC0) != 0x80) {
2410 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2411 "Malformed: At character position %d, octet position %d: %02X is "
2412 "not a valid continuing octet.", uchar_pos
, start_pos
+ i
, octet
);
2414 continuing_ptr
[i
] = octet
& 0x3F;
2416 if (start_pos
+ i
== n_octets
) {
2418 // only a part of octets is missing
2419 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2420 "Incomplete: At character position %d, octet position %d: %d out "
2421 "of %d continuing octets %s missing from the end of the stream.",
2422 uchar_pos
, start_pos
+ i
, n_continuing
- i
, n_continuing
,
2423 n_continuing
- i
> 1 ? "are" : "is");
2425 // all octets are missing
2426 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2427 "Incomplete: At character position %d, octet position %d: %d "
2428 "continuing octet%s missing from the end of the stream.", uchar_pos
,
2429 start_pos
, n_continuing
, n_continuing
> 1 ? "s are" : " is");
2432 continuing_ptr
[i
] = 0;
2437 void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets
,
2438 const unsigned char *octets_ptr
,
2439 CharCoding::CharCodingType expected_coding
/*= UTF8*/,
2440 bool checkBOM
/*= false)*/)
2442 // approximate the number of characters
2444 for (int i
= 0; i
< n_octets
; i
++) {
2445 // count all octets except the continuing octets (10xxxxxx)
2446 if ((octets_ptr
[i
] & 0xC0) != 0x80) n_uchars
++;
2448 // allocate enough memory, start from clean state
2451 init_struct(n_uchars
);
2454 int start
= checkBOM
? check_BOM(CharCoding::UTF_8
, sizeof(octets_ptr
), octets_ptr
) : 0;
2455 for (int i
= start
; i
< n_octets
; ) {
2456 // perform the decoding character by character
2457 if (octets_ptr
[i
] <= 0x7F) {
2458 // character encoded on a single octet: 0xxxxxxx (7 useful bits)
2459 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2460 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2461 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= 0;
2462 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[i
];
2465 } else if (octets_ptr
[i
] <= 0xBF) {
2466 // continuing octet (10xxxxxx) without leading octet ==> malformed
2467 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2468 "Malformed: At character position %d, octet position %d: continuing "
2469 "octet %02X without leading octet.", n_uchars
, i
, octets_ptr
[i
]);
2471 } else if (octets_ptr
[i
] <= 0xDF) {
2472 // character encoded on 2 octets: 110xxxxx 10xxxxxx (11 useful bits)
2473 unsigned char octets
[2];
2474 octets
[0] = octets_ptr
[i
] & 0x1F;
2475 fill_continuing_octets(1, octets
+ 1, n_octets
, octets_ptr
, i
+ 1, n_uchars
);
2476 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2477 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2478 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[0] >> 2;
2479 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[0] << 6 | octets
[1];
2480 if (val_ptr
->uchars_ptr
[n_uchars
].uc_row
== 0x00 &&
2481 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
< 0x80)
2482 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2483 "Overlong: At character position %d, octet position %d: 2-octet "
2484 "encoding for quadruple (0, 0, 0, %u).", n_uchars
, i
,
2485 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2488 } else if (octets_ptr
[i
] <= 0xEF) {
2489 // character encoded on 3 octets: 1110xxxx 10xxxxxx 10xxxxxx
2491 unsigned char octets
[3];
2492 octets
[0] = octets_ptr
[i
] & 0x0F;
2493 fill_continuing_octets(2, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2495 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2496 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2497 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[0] << 4 | octets
[1] >> 2;
2498 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[1] << 6 | octets
[2];
2499 if (val_ptr
->uchars_ptr
[n_uchars
].uc_row
< 0x08)
2500 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2501 "Overlong: At character position %d, octet position %d: 3-octet "
2502 "encoding for quadruple (0, 0, %u, %u).", n_uchars
, i
,
2503 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2504 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2507 } else if (octets_ptr
[i
] <= 0xF7) {
2508 // character encoded on 4 octets: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2510 unsigned char octets
[4];
2511 octets
[0] = octets_ptr
[i
] & 0x07;
2512 fill_continuing_octets(3, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2514 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2515 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[0] << 2 | octets
[1] >> 4;
2516 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[1] << 4 | octets
[2] >> 2;
2517 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[2] << 6 | octets
[3];
2518 if (val_ptr
->uchars_ptr
[n_uchars
].uc_plane
== 0x00)
2519 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2520 "Overlong: At character position %d, octet position %d: 4-octet "
2521 "encoding for quadruple (0, 0, %u, %u).", n_uchars
, i
,
2522 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2523 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2526 } else if (octets_ptr
[i
] <= 0xFB) {
2527 // character encoded on 5 octets: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
2528 // 10xxxxxx (26 useful bits)
2529 unsigned char octets
[5];
2530 octets
[0] = octets_ptr
[i
] & 0x03;
2531 fill_continuing_octets(4, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2533 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets
[0];
2534 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[1] << 2 | octets
[2] >> 4;
2535 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[2] << 4 | octets
[3] >> 2;
2536 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[3] << 6 | octets
[4];
2537 if (val_ptr
->uchars_ptr
[n_uchars
].uc_group
== 0x00 &&
2538 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
< 0x20)
2539 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2540 "Overlong: At character position %d, octet position %d: 5-octet "
2541 "encoding for quadruple (0, %u, %u, %u).", n_uchars
, i
,
2542 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
,
2543 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2544 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2547 } else if (octets_ptr
[i
] <= 0xFD) {
2548 // character encoded on 6 octets: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx
2549 // 10xxxxxx 10xxxxxx (31 useful bits)
2550 unsigned char octets
[6];
2551 octets
[0] = octets_ptr
[i
] & 0x01;
2552 fill_continuing_octets(5, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2554 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets
[0] << 6 | octets
[1];
2555 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[2] << 2 | octets
[3] >> 4;
2556 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[3] << 4 | octets
[4] >> 2;
2557 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[4] << 6 | octets
[5];
2558 if (val_ptr
->uchars_ptr
[n_uchars
].uc_group
< 0x04)
2559 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2560 "Overlong: At character position %d, octet position %d: 6-octet "
2561 "encoding for quadruple (%u, %u, %u, %u).", n_uchars
, i
,
2562 val_ptr
->uchars_ptr
[n_uchars
].uc_group
,
2563 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
,
2564 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2565 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2569 // not used code points: FE and FF => malformed
2570 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2571 "Malformed: At character position %d, octet position %d: "
2572 "unused/reserved octet %02X.", n_uchars
, i
, octets_ptr
[i
]);
2576 if (val_ptr
->n_uchars
!= n_uchars
) {
2577 // truncate the memory and set the correct size in case of decoding errors
2578 // (e.g. skipped octets)
2580 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
,
2581 MEMORY_SIZE(n_uchars
));
2582 val_ptr
->n_uchars
= n_uchars
;
2590 void UNIVERSAL_CHARSTRING::decode_utf16(int n_octets
,
2591 const unsigned char *octets_ptr
,
2592 CharCoding::CharCodingType expected_coding
)
2594 if (n_octets
% 2 || 0 > n_octets
) {
2595 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2596 "Wrong UTF-16 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 2",
2599 int start
= check_BOM(expected_coding
, sizeof(octets_ptr
), octets_ptr
);
2600 int n_uchars
= n_octets
/2;
2601 init_struct(n_uchars
);
2604 switch (expected_coding
) {
2605 case CharCoding::UTF16
:
2606 case CharCoding::UTF16BE
:
2609 case CharCoding::UTF16LE
:
2613 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2614 "Unexpected coding type for UTF-16 encoding");
2617 for (int i
= start
; i
< n_octets
; i
+= 2 ) {
2618 int first
= isbig
? i
: i
+ 1;
2619 int second
= isbig
? i
+ 1 : i
;
2620 int third
= isbig
? i
+ 2 : i
+ 3;
2621 int fourth
= isbig
? i
+ 3 : i
+ 2;
2623 uint16_t W1
= octets_ptr
[first
] << 8 | octets_ptr
[second
];
2624 uint16_t W2
= (i
+ 3 < n_octets
) ? octets_ptr
[third
] << 8 | octets_ptr
[fourth
] : 0;
2626 if (0xD800 > W1
|| 0xDFFF < W1
) {
2627 //if W1 < 0xD800 or W1 > 0xDFFF, the character value is the value of W1
2628 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2629 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2630 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets_ptr
[first
];
2631 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[second
];
2634 else if (0xD800 > W1
|| 0xDBFF < W1
) {
2635 //Determine if W1 is between 0xD800 and 0xDBFF. If not, the sequence
2636 //is in error and no valid character can be obtained using W1.
2637 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2638 "The word (0x%04X) shall be between 0xD800 and 0xDBFF", W1
);
2640 else if (0 == W2
|| (0xDC00 > W2
|| 0xDFFF < W2
)) {
2641 //If there is no W2 (that is, the sequence ends with W1), or if W2
2642 //is not between 0xDC00 and 0xDFFF, the sequence is in error.
2644 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2645 "Wrong UTF-16 string. The word (0x%04X) shall be between 0xDC00 and 0xDFFF", W2
);
2647 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2648 "Wrong UTF-16 string. The decoding algorythm does not expect 0x00 or EOL");
2651 //Construct a 20-bit unsigned integer, taking the 10 low-order bits of W1 as its 10 high-
2652 //order bits and the 10 low-order bits of W2 as its 10 low-order bits.
2653 const uint16_t mask10bitlow
= 0x3FF;
2654 uint32_t DW
= (W1
& mask10bitlow
) << 10;
2655 DW
|= (W2
& mask10bitlow
);
2657 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2658 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= DW
>> 16;
2659 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= DW
>> 8;
2660 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= DW
;
2662 i
+= 2; // jump over w2 in octetstring
2665 if (val_ptr
->n_uchars
!= n_uchars
) {
2666 // truncate the memory and set the correct size in case of decoding errors
2667 // (e.g. skipped octets)
2669 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(n_uchars
));
2670 val_ptr
->n_uchars
= n_uchars
;
2679 void UNIVERSAL_CHARSTRING::decode_utf32(int n_octets
, const unsigned char *octets_ptr
,
2680 CharCoding::CharCodingType expected_coding
)
2682 if (n_octets
% 4 || 0 > n_octets
) {
2683 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2684 "Wrong UTF-32 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 4",
2687 int start
= check_BOM(expected_coding
, sizeof(octets_ptr
), octets_ptr
);
2688 int n_uchars
= n_octets
/4;
2689 init_struct(n_uchars
);
2692 switch (expected_coding
) {
2693 case CharCoding::UTF32
:
2694 case CharCoding::UTF32BE
:
2697 case CharCoding::UTF32LE
:
2701 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2702 "Unexpected coding type for UTF-32 encoding");
2705 for (int i
= start
; i
< n_octets
; i
+= 4 ) {
2706 int first
= isbig
? i
: i
+ 3;
2707 int second
= isbig
? i
+ 1 : i
+ 2;
2708 int third
= isbig
? i
+ 2 : i
+ 1;
2709 int fourth
= isbig
? i
+ 3 : i
;
2710 uint32_t DW
= octets_ptr
[first
] << 8 | octets_ptr
[second
];
2712 DW
|= octets_ptr
[third
];
2714 DW
|= octets_ptr
[fourth
];
2715 if (0x0000D800 <= DW
&& 0x0000DFFF >= DW
) {
2716 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2717 "Any UTF-32 code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW
);
2719 else if (0x0010FFFF < DW
) {
2720 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2721 "Any UTF-32 code (0x%08X) greater than 0x0010FFFF is ill-formed", DW
);
2724 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets_ptr
[first
];
2725 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets_ptr
[second
];
2726 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets_ptr
[third
];
2727 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[fourth
];
2731 if (val_ptr
->n_uchars
!= n_uchars
) {
2732 // truncate the memory and set the correct size in case of decoding errors
2733 // (e.g. skipped octets)
2735 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(n_uchars
));
2736 val_ptr
->n_uchars
= n_uchars
;
2744 int UNIVERSAL_CHARSTRING::check_BOM(CharCoding::CharCodingType expected_coding
,
2745 unsigned int length
,
2746 const unsigned char* ostr
)
2748 switch (expected_coding
) {
2749 case CharCoding::UTF32
:
2750 case CharCoding::UTF32BE
:
2751 case CharCoding::UTF32LE
:
2753 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2754 "The string is shorter than the expected BOM");
2757 case CharCoding::UTF16
:
2758 case CharCoding::UTF16BE
:
2759 case CharCoding::UTF16LE
:
2761 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2762 "The string is shorter than the expected BOM");
2765 case CharCoding::UTF_8
:
2767 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2768 "The string is shorter than the expected BOM");
2773 std::string coding_str
;
2774 //BOM indicates that the byte order is determined by a byte order mark,
2775 //if present at the beginning the length of BOM is returned.
2776 switch (expected_coding
) {
2777 case CharCoding::UTF32BE
:
2778 case CharCoding::UTF32
:
2779 if (0x00 == ostr
[0] && 0x00 == ostr
[1] && 0xFE == ostr
[2] && 0xFF == ostr
[3]) {
2782 coding_str
= "UTF-32BE";
2784 case CharCoding::UTF32LE
:
2785 if (0xFF == ostr
[0] && 0xFE == ostr
[1] && 0x00 == ostr
[2] && 0x00 == ostr
[3]) {
2788 coding_str
= "UTF-32LE";
2790 case CharCoding::UTF16BE
:
2791 case CharCoding::UTF16
:
2792 if (0xFE == ostr
[0] && 0xFF == ostr
[1]) {
2795 coding_str
= "UTF-16BE";
2797 case CharCoding::UTF16LE
:
2798 if (0xFF == ostr
[0] && 0xFE == ostr
[1]) {
2801 coding_str
= "UTF-16LE";
2803 case CharCoding::UTF_8
:
2804 if (0xEF == ostr
[0] && 0xBB == ostr
[1] && 0xBF == ostr
[2]) {
2807 coding_str
= "UTF-8";
2811 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2812 "Wrong %s string. No BOM detected, however the given coding type (%s) expects it to define the endianness",
2813 coding_str
.c_str(), coding_str
.c_str());
2816 TTCN_EncDec_ErrorContext::warning("No %s Byte Order Mark(BOM) detected. It may result decoding errors",
2817 coding_str
.c_str());
2821 // member functions of class UNIVERSAL_CHARSTRING_ELEMENTS
2823 UNIVERSAL_CHARSTRING_ELEMENT::UNIVERSAL_CHARSTRING_ELEMENT
2824 (boolean par_bound_flag
, UNIVERSAL_CHARSTRING
& par_str_val
,
2825 int par_uchar_pos
) :
2826 bound_flag(par_bound_flag
), str_val(par_str_val
), uchar_pos(par_uchar_pos
)
2831 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2832 (const universal_char
& other_value
)
2835 if (str_val
.charstring
) {
2836 if (other_value
.is_char()) {
2837 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
.uc_cell
;
2840 str_val
.convert_cstr_to_uni();
2842 str_val
.copy_value();
2843 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] = other_value
;
2847 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2848 (const char* other_value
)
2850 if (other_value
== NULL
|| other_value
[0] == '\0' || other_value
[1] != '\0')
2851 TTCN_error("Assignment of a charstring value with length other than 1 to "
2852 "a universal charstring element.");
2854 if (str_val
.charstring
)
2855 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
[0];
2857 str_val
.copy_value();
2858 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2859 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2860 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2861 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
= other_value
[0];
2866 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2867 (const CHARSTRING
& other_value
)
2869 other_value
.must_bound("Assignment of an unbound charstring value to a "
2870 "universal charstring element.");
2871 if(other_value
.val_ptr
->n_chars
!= 1)
2872 TTCN_error("Assignment of a charstring value with length other than 1 to "
2873 "a universal charstring element.");
2875 if (str_val
.charstring
)
2876 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] =
2877 other_value
.val_ptr
->chars_ptr
[0];
2879 str_val
.copy_value();
2880 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2881 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2882 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2883 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
=
2884 other_value
.val_ptr
->chars_ptr
[0];
2889 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2890 (const CHARSTRING_ELEMENT
& other_value
)
2892 other_value
.must_bound("Assignment of an unbound charstring element to a "
2893 "universal charstring element.");
2895 if (str_val
.charstring
)
2896 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
.get_char();
2898 str_val
.copy_value();
2899 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2900 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2901 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2902 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
= other_value
.get_char();
2907 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2908 (const UNIVERSAL_CHARSTRING
& other_value
)
2910 other_value
.must_bound("Assignment of an unbound universal charstring value "
2911 "to a universal charstring element.");
2912 int other_value_size
= other_value
.charstring
? other_value
.cstr
.val_ptr
->n_chars
:
2913 other_value
.val_ptr
->n_uchars
;
2914 if (other_value_size
!= 1)
2915 TTCN_error("Assignment of a universal charstring value with length other "
2916 "than 1 to a universal charstring element.");
2918 *this = other_value
[0];
2922 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2923 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
2925 other_value
.must_bound("Assignment of an unbound universal charstring "
2927 if (&other_value
!= this) {
2929 if (str_val
.charstring
) {
2930 if (other_value
.str_val
.charstring
)
2931 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] =
2932 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
2934 str_val
.convert_cstr_to_uni();
2935 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] =
2936 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
2939 if (other_value
.str_val
.charstring
) {
2940 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2941 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2942 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2943 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
=
2944 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
2946 str_val
.copy_value();
2947 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] =
2948 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
2955 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2956 (const universal_char
& other_value
) const
2958 must_bound("The left operand of comparison is an unbound universal "
2959 "charstring element.");
2960 if (str_val
.charstring
&& other_value
.is_char())
2961 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
.uc_cell
;
2962 if (str_val
.charstring
&& !other_value
.is_char())
2964 if (!str_val
.charstring
&& other_value
.is_char()) {
2965 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2966 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2967 uchar
.uc_cell
== other_value
.uc_cell
;
2969 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] == other_value
;
2972 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2973 (const char* other_value
) const
2975 must_bound("The left operand of comparison is an unbound universal "
2976 "charstring element.");
2977 if (other_value
== NULL
|| other_value
[0] == '\0' ||
2978 other_value
[1] != '\0') return FALSE
;
2979 if (str_val
.charstring
)
2980 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
[0];
2981 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2982 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2983 uchar
.uc_cell
== (cbyte
)other_value
[0];
2986 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
2987 (const CHARSTRING
& other_value
) const
2989 must_bound("The left operand of comparison is an unbound universal "
2990 "charstring element.");
2991 other_value
.must_bound("The right operand of comparison is an unbound "
2992 "charstring value.");
2993 if (other_value
.val_ptr
->n_chars
!= 1) return FALSE
;
2994 if (str_val
.charstring
)
2995 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
2996 other_value
.val_ptr
->chars_ptr
[0];
2997 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
2998 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
2999 uchar
.uc_cell
== (cbyte
)other_value
.val_ptr
->chars_ptr
[0];
3002 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3003 (const CHARSTRING_ELEMENT
& other_value
) const
3005 must_bound("The left operand of comparison is an unbound universal "
3006 "charstring element.");
3007 other_value
.must_bound("The right operand of comparison is an unbound "
3008 "charstring element.");
3009 if (str_val
.charstring
)
3010 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
.get_char();
3011 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3012 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3013 uchar
.uc_cell
== (cbyte
)other_value
.get_char();
3016 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3017 (const UNIVERSAL_CHARSTRING
& other_value
) const
3019 must_bound("The left operand of comparison is an unbound universal "
3020 "charstring element.");
3021 other_value
.must_bound("The right operand of comparison is an unbound "
3022 "universal charstring value.");
3023 if (other_value
.charstring
) {
3024 if (other_value
.cstr
.val_ptr
->n_chars
!= 1)
3026 if (str_val
.charstring
)
3027 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
3028 other_value
.cstr
.val_ptr
->chars_ptr
[0];
3030 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3031 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0
3032 && uchar
.uc_cell
== (cbyte
)other_value
.cstr
.val_ptr
->chars_ptr
[0];
3035 if (other_value
.val_ptr
->n_uchars
!= 1)
3037 if (str_val
.charstring
) {
3038 const universal_char
& uchar
= other_value
.val_ptr
->uchars_ptr
[0];
3039 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3040 uchar
.uc_cell
== (cbyte
)str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3042 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] ==
3043 other_value
.val_ptr
->uchars_ptr
[0];
3047 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3048 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
3050 must_bound("The left operand of comparison is an unbound universal "
3051 "charstring element.");
3052 other_value
.must_bound("The right operand of comparison is an unbound "
3053 "universal charstring element.");
3054 if (str_val
.charstring
) {
3055 if (other_value
.str_val
.charstring
)
3056 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
3057 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3059 const universal_char
& uchar
= other_value
.get_uchar();
3060 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3061 uchar
.uc_cell
== str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3064 if (other_value
.str_val
.charstring
) {
3065 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3066 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3068 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3070 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] ==
3071 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3075 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3076 (const universal_char
& other_value
) const
3078 must_bound("The left operand of concatenation is an unbound universal "
3079 "charstring element.");
3080 if (str_val
.charstring
&& other_value
.is_char()) {
3081 UNIVERSAL_CHARSTRING
ret_val(2, true);
3082 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3083 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3084 ret_val
.cstr
.val_ptr
->chars_ptr
[1] = other_value
.uc_cell
;
3086 } else if (str_val
.charstring
^ other_value
.is_char()) {
3087 universal_char result
[2];
3088 if (str_val
.charstring
) {
3089 result
[0].uc_group
= result
[0].uc_plane
= result
[0].uc_row
= 0;
3090 result
[0].uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3092 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3093 result
[1] = other_value
;
3094 return UNIVERSAL_CHARSTRING(2, result
);
3096 universal_char result
[2];
3097 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3098 result
[1] = other_value
;
3099 return UNIVERSAL_CHARSTRING(2, result
);
3102 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3103 (const char* other_value
) const
3105 must_bound("The left operand of concatenation is an unbound universal "
3106 "charstring element.");
3108 if (other_value
== NULL
) other_len
= 0;
3109 else other_len
= strlen(other_value
);
3111 UNIVERSAL_CHARSTRING
ret_val(other_len
+ 1, str_val
.charstring
);
3112 if (str_val
.charstring
) {
3113 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3114 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3115 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1, other_value
, other_len
);
3117 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3118 for (int i
= 0; i
< other_len
; i
++) {
3119 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_group
= 0;
3120 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_plane
= 0;
3121 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_row
= 0;
3122 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_cell
= other_value
[i
];
3128 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3129 (const CHARSTRING
& other_value
) const
3131 must_bound("The left operand of concatenation is an unbound universal "
3132 "charstring element.");
3133 other_value
.must_bound("The right operand of concatenation is an unbound "
3134 "charstring value.");
3135 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_chars
+ 1,
3136 str_val
.charstring
);
3137 if (str_val
.charstring
) {
3138 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3139 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3140 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1, other_value
.val_ptr
->chars_ptr
,
3141 other_value
.val_ptr
->n_chars
);
3143 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3144 for (int i
= 0; i
< other_value
.val_ptr
->n_chars
; i
++) {
3145 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_group
= 0;
3146 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_plane
= 0;
3147 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_row
= 0;
3148 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_cell
=
3149 other_value
.val_ptr
->chars_ptr
[i
];
3155 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3156 (const CHARSTRING_ELEMENT
& other_value
) const
3158 must_bound("The left operand of concatenation is an unbound universal "
3159 "charstring element.");
3160 other_value
.must_bound("The right operand of concatenation is an unbound "
3161 "charstring element.");
3162 if (str_val
.charstring
) {
3163 UNIVERSAL_CHARSTRING
ret_val(2, true);
3164 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3165 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3166 ret_val
.cstr
.val_ptr
->chars_ptr
[1] = other_value
.get_char();
3169 universal_char result
[2];
3170 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3171 result
[1].uc_group
= 0;
3172 result
[1].uc_plane
= 0;
3173 result
[1].uc_row
= 0;
3174 result
[1].uc_cell
= other_value
.get_char();
3175 return UNIVERSAL_CHARSTRING(2, result
);
3179 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3180 (const UNIVERSAL_CHARSTRING
& other_value
) const
3182 must_bound("The left operand of concatenation is an unbound universal "
3183 "charstring element.");
3184 other_value
.must_bound("The right operand of concatenation is an unbound "
3185 "universal charstring value.");
3186 if (str_val
.charstring
) {
3187 if (other_value
.charstring
) {
3188 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1, true);
3189 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3190 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3191 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1,
3192 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3195 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3196 universal_char
& uchar
= ret_val
.val_ptr
->uchars_ptr
[0];
3197 uchar
.uc_group
= uchar
.uc_plane
= uchar
.uc_row
= 0;
3198 uchar
.uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3199 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3200 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3204 if (other_value
.charstring
) {
3205 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1);
3206 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3207 for (int i
= 1; i
<= other_value
.cstr
.val_ptr
->n_chars
; ++i
) {
3208 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3209 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3210 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3211 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
=
3212 other_value
.cstr
.val_ptr
->chars_ptr
[i
-1];
3216 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3217 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3218 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3219 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3225 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3226 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
3228 must_bound("The left operand of concatenation is an unbound universal "
3229 "charstring element.");
3230 other_value
.must_bound("The right operand of concatenation is an unbound "
3231 "universal charstring element.");
3232 if (str_val
.charstring
) {
3233 if (other_value
.str_val
.charstring
) {
3234 UNIVERSAL_CHARSTRING
ret_val(2, true);
3235 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3236 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3237 ret_val
.cstr
.val_ptr
->chars_ptr
[1] =
3238 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3241 UNIVERSAL_CHARSTRING
ret_val(2);
3242 universal_char
& uchar
= ret_val
.val_ptr
->uchars_ptr
[0];
3243 uchar
.uc_group
= uchar
.uc_plane
= uchar
.uc_row
= 0;
3244 uchar
.uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3245 ret_val
.val_ptr
->uchars_ptr
[1] =
3246 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3250 if (other_value
.str_val
.charstring
) {
3251 UNIVERSAL_CHARSTRING
ret_val(2);
3252 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3253 ret_val
.val_ptr
->uchars_ptr
[1].uc_group
= 0;
3254 ret_val
.val_ptr
->uchars_ptr
[1].uc_plane
= 0;
3255 ret_val
.val_ptr
->uchars_ptr
[1].uc_row
= 0;
3256 ret_val
.val_ptr
->uchars_ptr
[1].uc_cell
=
3257 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3260 universal_char result
[2];
3261 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3262 result
[1] = other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3263 return UNIVERSAL_CHARSTRING(2, result
);
3268 const universal_char
& UNIVERSAL_CHARSTRING_ELEMENT::get_uchar() const
3270 if (str_val
.charstring
)
3271 const_cast<UNIVERSAL_CHARSTRING_ELEMENT
&>
3272 (*this).str_val
.convert_cstr_to_uni();
3273 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3276 void UNIVERSAL_CHARSTRING_ELEMENT::log() const
3279 if (str_val
.charstring
) {
3280 str_val
.cstr
[uchar_pos
].log();
3283 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3284 if (is_printable(uchar
)) {
3285 // the character is printable
3286 TTCN_Logger::log_char('"');
3287 TTCN_Logger::log_char_escaped(uchar
.uc_cell
);
3288 TTCN_Logger::log_char('"');
3290 // the character is not printable
3291 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3292 uchar
.uc_group
, uchar
.uc_plane
, uchar
.uc_row
, uchar
.uc_cell
);
3294 } else TTCN_Logger::log_event_unbound();
3299 boolean
operator==(const universal_char
& uchar_value
,
3300 const UNIVERSAL_CHARSTRING
& other_value
)
3302 other_value
.must_bound("The right operand of comparison is an unbound "
3303 "universal charstring value.");
3304 if (other_value
.charstring
) {
3305 if (other_value
.cstr
.val_ptr
->n_chars
!= 1) return FALSE
;
3306 else return uchar_value
.is_char() &&
3307 uchar_value
.uc_cell
== other_value
.cstr
.val_ptr
->chars_ptr
[0];
3309 if (other_value
.val_ptr
->n_uchars
!= 1) return FALSE
;
3310 else return uchar_value
== other_value
.val_ptr
->uchars_ptr
[0];
3313 boolean
operator==(const universal_char
& uchar_value
,
3314 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3316 other_value
.must_bound("The right operand of comparison is an unbound "
3317 "universal charstring element.");
3318 return uchar_value
== other_value
.get_uchar();
3321 UNIVERSAL_CHARSTRING
operator+(const universal_char
& uchar_value
,
3322 const UNIVERSAL_CHARSTRING
& other_value
)
3324 other_value
.must_bound("The right operand of concatenation is an unbound "
3325 "universal charstring value.");
3326 if (other_value
.charstring
) {
3327 if (uchar_value
.is_char()) {
3328 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1, true);
3329 ret_val
.cstr
.val_ptr
->chars_ptr
[0] = uchar_value
.uc_cell
;
3330 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1,
3331 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3334 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3335 ret_val
.val_ptr
->uchars_ptr
[0] = uchar_value
;
3336 for (int i
= 0; i
< other_value
.cstr
.val_ptr
->n_chars
; i
++) {
3337 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_group
= 0;
3338 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_plane
= 0;
3339 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_row
= 0;
3340 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_cell
=
3341 other_value
.cstr
.val_ptr
->chars_ptr
[i
];
3346 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3347 ret_val
.val_ptr
->uchars_ptr
[0] = uchar_value
;
3348 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3349 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3354 UNIVERSAL_CHARSTRING
operator+(const universal_char
& uchar_value
,
3355 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3357 other_value
.must_bound("The right operand of concatenation is an unbound "
3358 "universal charstring element.");
3359 if (other_value
.str_val
.charstring
) {
3360 if (uchar_value
.is_char()) {
3362 result
[0] = uchar_value
.uc_cell
;
3364 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3365 return UNIVERSAL_CHARSTRING(2, result
);
3367 universal_char result
[2];
3368 result
[0] = uchar_value
;
3369 result
[1].uc_group
= 0;
3370 result
[1].uc_plane
= 0;
3371 result
[1].uc_row
= 0;
3373 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3374 return UNIVERSAL_CHARSTRING(2, result
);
3377 universal_char result
[2];
3378 result
[0] = uchar_value
;
3379 result
[1] = other_value
.get_uchar();
3380 return UNIVERSAL_CHARSTRING(2, result
);
3384 boolean
operator==(const char *string_value
,
3385 const UNIVERSAL_CHARSTRING
& other_value
)
3387 other_value
.must_bound("The right operand of comparison is an unbound "
3388 "universal charstring value.");
3390 if (string_value
== NULL
) string_len
= 0;
3391 else string_len
= strlen(string_value
);
3392 if (other_value
.charstring
) {
3393 return other_value
.cstr
== string_value
;
3395 if (string_len
!= other_value
.val_ptr
->n_uchars
) return FALSE
;
3396 for (int i
= 0; i
< string_len
; i
++) {
3397 if (other_value
.val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
3398 other_value
.val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
3399 other_value
.val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
3400 other_value
.val_ptr
->uchars_ptr
[i
].uc_cell
!= string_value
[i
])
3407 boolean
operator==(const char *string_value
,
3408 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3410 other_value
.must_bound("The right operand of comparison is an unbound "
3411 "universal charstring element.");
3412 if (string_value
== NULL
|| string_value
[0] == '\0' ||
3413 string_value
[1] != '\0') return FALSE
;
3414 if (other_value
.str_val
.charstring
)
3415 return other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
]
3417 const universal_char
& uchar
= other_value
.get_uchar();
3418 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3419 uchar
.uc_cell
== string_value
[0];
3422 UNIVERSAL_CHARSTRING
operator+(const char *string_value
,
3423 const UNIVERSAL_CHARSTRING
& other_value
)
3425 other_value
.must_bound("The right operand of concatenation is an unbound "
3426 "universal charstring value.");
3428 if (string_value
== NULL
) string_len
= 0;
3429 else string_len
= strlen(string_value
);
3430 if (other_value
.charstring
) {
3431 UNIVERSAL_CHARSTRING
ret_val(string_len
+ other_value
.cstr
.val_ptr
->n_chars
,
3433 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, string_value
, string_len
);
3434 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ string_len
,
3435 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3438 UNIVERSAL_CHARSTRING
ret_val(string_len
+ other_value
.val_ptr
->n_uchars
);
3439 for (int i
= 0; i
< string_len
; i
++) {
3440 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3441 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3442 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3443 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= string_value
[i
];
3445 memcpy(ret_val
.val_ptr
->uchars_ptr
+ string_len
,
3446 other_value
.val_ptr
->uchars_ptr
,
3447 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3451 UNIVERSAL_CHARSTRING
operator+(const char *string_value
,
3452 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3454 other_value
.must_bound("The right operand of concatenation is an unbound "
3455 "universal charstring element.");
3457 if (string_value
== NULL
) string_len
= 0;
3458 else string_len
= strlen(string_value
);
3459 if (other_value
.str_val
.charstring
) {
3460 UNIVERSAL_CHARSTRING
ret_val(string_len
+ 1, true);
3461 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, string_value
, string_len
);
3462 ret_val
.cstr
.val_ptr
->chars_ptr
[string_len
] =
3463 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3466 UNIVERSAL_CHARSTRING
ret_val(string_len
+ 1);
3467 for (int i
= 0; i
< string_len
; i
++) {
3468 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3469 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3470 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3471 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= string_value
[i
];
3473 ret_val
.val_ptr
->uchars_ptr
[string_len
] = other_value
.get_uchar();
3477 // member functions of class UNIVERSAL_CHARSTRING_template
3479 void UNIVERSAL_CHARSTRING_template::clean_up()
3481 if (template_selection
== VALUE_LIST
||
3482 template_selection
== COMPLEMENTED_LIST
) delete [] value_list
.list_value
;
3483 else if (template_selection
== STRING_PATTERN
) {
3484 if (pattern_value
.regexp_init
) regfree(&pattern_value
.posix_regexp
);
3485 delete pattern_string
;
3487 template_selection
= UNINITIALIZED_TEMPLATE
;
3490 void UNIVERSAL_CHARSTRING_template::copy_template
3491 (const CHARSTRING_template
& other_value
)
3493 switch (other_value
.template_selection
) {
3494 case SPECIFIC_VALUE
:
3495 single_value
= other_value
.single_value
;
3502 case COMPLEMENTED_LIST
:
3503 value_list
.n_values
= other_value
.value_list
.n_values
;
3504 value_list
.list_value
=
3505 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3506 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3507 value_list
.list_value
[i
].copy_template(
3508 other_value
.value_list
.list_value
[i
]);
3511 if (!other_value
.value_range
.min_is_set
) TTCN_error("The lower bound is "
3512 "not set when copying a charstring value range template to a universal "
3513 "charstring template.");
3514 if (!other_value
.value_range
.max_is_set
) TTCN_error("The upper bound is "
3515 "not set when copying a charstring value range template to a universal "
3516 "charstring template.");
3517 value_range
.min_is_set
= TRUE
;
3518 value_range
.max_is_set
= TRUE
;
3519 value_range
.min_value
.uc_group
= 0;
3520 value_range
.min_value
.uc_plane
= 0;
3521 value_range
.min_value
.uc_row
= 0;
3522 value_range
.min_value
.uc_cell
= other_value
.value_range
.min_value
;
3523 value_range
.max_value
.uc_group
= 0;
3524 value_range
.max_value
.uc_plane
= 0;
3525 value_range
.max_value
.uc_row
= 0;
3526 value_range
.max_value
.uc_cell
= other_value
.value_range
.max_value
;
3528 case STRING_PATTERN
:
3529 pattern_string
= new CHARSTRING(other_value
.single_value
);
3530 pattern_value
.regexp_init
=FALSE
;
3533 TTCN_error("Copying an uninitialized/unsupported charstring template to a "
3534 "universal charstring template.");
3536 set_selection(other_value
);
3539 void UNIVERSAL_CHARSTRING_template::copy_template
3540 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3542 switch (other_value
.template_selection
) {
3543 case SPECIFIC_VALUE
:
3544 single_value
= other_value
.single_value
;
3551 case COMPLEMENTED_LIST
:
3552 value_list
.n_values
= other_value
.value_list
.n_values
;
3553 value_list
.list_value
=
3554 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3555 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3556 value_list
.list_value
[i
].copy_template(
3557 other_value
.value_list
.list_value
[i
]);
3560 if (!other_value
.value_range
.min_is_set
) TTCN_error("The lower bound is "
3561 "not set when copying a universal charstring value range template.");
3562 if (!other_value
.value_range
.max_is_set
) TTCN_error("The upper bound is "
3563 "not set when copying a universal charstring value range template.");
3564 value_range
= other_value
.value_range
;
3566 case STRING_PATTERN
:
3567 pattern_string
= new CHARSTRING(*(other_value
.pattern_string
));
3568 pattern_value
.regexp_init
=FALSE
;
3571 TTCN_error("Copying an uninitialized/unsupported universal charstring "
3574 set_selection(other_value
);
3577 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template()
3581 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3582 (template_sel other_value
) : Restricted_Length_Template(other_value
)
3585 check_single_selection(other_value
);
3588 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3589 (const CHARSTRING
& other_value
) :
3590 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3594 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3595 (const UNIVERSAL_CHARSTRING
& other_value
) :
3596 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3600 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3601 (const CHARSTRING_ELEMENT
& other_value
) :
3602 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3606 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3607 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) :
3608 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3612 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3613 (const OPTIONAL
<CHARSTRING
>& other_value
)
3615 switch (other_value
.get_selection()) {
3616 case OPTIONAL_PRESENT
:
3617 set_selection(SPECIFIC_VALUE
);
3618 single_value
= (const CHARSTRING
&)other_value
;
3621 set_selection(OMIT_VALUE
);
3624 TTCN_error("Creating a universal charstring template from an unbound "
3629 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3630 (const OPTIONAL
<UNIVERSAL_CHARSTRING
>& other_value
)
3632 switch (other_value
.get_selection()) {
3633 case OPTIONAL_PRESENT
:
3634 set_selection(SPECIFIC_VALUE
);
3635 single_value
= (const UNIVERSAL_CHARSTRING
&)other_value
;
3638 set_selection(OMIT_VALUE
);
3641 TTCN_error("Creating a universal charstring template from an unbound "
3646 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3647 (const CHARSTRING_template
& other_value
)
3648 : Restricted_Length_Template()
3650 copy_template(other_value
);
3653 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3654 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3655 : Restricted_Length_Template()
3657 copy_template(other_value
);
3660 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3661 (template_sel p_sel
, const CHARSTRING
& p_str
)
3662 : Restricted_Length_Template(STRING_PATTERN
)
3664 if(p_sel
!=STRING_PATTERN
)
3665 TTCN_error("Internal error: Initializing a universal charstring"
3666 "pattern template with invalid selection.");
3667 pattern_string
= new CHARSTRING(p_str
);
3668 pattern_value
.regexp_init
=FALSE
;
3671 UNIVERSAL_CHARSTRING_template::~UNIVERSAL_CHARSTRING_template()
3676 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3677 (template_sel other_value
)
3679 check_single_selection(other_value
);
3681 set_selection(other_value
);
3685 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3686 (const CHARSTRING
& other_value
)
3688 other_value
.must_bound("Assignment of an unbound charstring value to a "
3689 "universal charstring template.");
3691 set_selection(SPECIFIC_VALUE
);
3692 single_value
= other_value
;
3696 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3697 (const UNIVERSAL_CHARSTRING
& other_value
)
3699 other_value
.must_bound("Assignment of an unbound universal charstring value "
3702 set_selection(SPECIFIC_VALUE
);
3703 single_value
= other_value
;
3707 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3708 (const CHARSTRING_ELEMENT
& other_value
)
3710 other_value
.must_bound("Assignment of an unbound charstring element to a "
3711 "universal charstring template.");
3713 set_selection(SPECIFIC_VALUE
);
3714 single_value
= other_value
;
3718 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3719 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3721 other_value
.must_bound("Assignment of an unbound universal charstring "
3722 "element to a template.");
3724 set_selection(SPECIFIC_VALUE
);
3725 single_value
= other_value
;
3729 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3730 (const OPTIONAL
<CHARSTRING
>& other_value
)
3733 switch (other_value
.get_selection()) {
3734 case OPTIONAL_PRESENT
:
3735 set_selection(SPECIFIC_VALUE
);
3736 single_value
= (const CHARSTRING
&)other_value
;
3739 set_selection(OMIT_VALUE
);
3742 TTCN_error("Assignment of an unbound optional field to a universal "
3743 "charstring template.");
3748 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3749 (const OPTIONAL
<UNIVERSAL_CHARSTRING
>& other_value
)
3752 switch (other_value
.get_selection()) {
3753 case OPTIONAL_PRESENT
:
3754 set_selection(SPECIFIC_VALUE
);
3755 single_value
= (const UNIVERSAL_CHARSTRING
&)other_value
;
3758 set_selection(OMIT_VALUE
);
3761 TTCN_error("Assignment of an unbound optional field to a universal "
3762 "charstring template.");
3767 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3768 (const CHARSTRING_template
& other_value
)
3771 copy_template(other_value
);
3775 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3776 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3778 if (&other_value
!= this) {
3780 copy_template(other_value
);
3785 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](int index_value
)
3787 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3788 TTCN_error("Accessing a universal charstring element of a non-specific "
3789 "universal charstring template.");
3790 return single_value
[index_value
];
3793 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](const INTEGER
& index_value
)
3795 index_value
.must_bound("Indexing a universal charstring template with an "
3796 "unbound integer value.");
3797 return (*this)[(int)index_value
];
3800 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](int index_value
) const
3802 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3803 TTCN_error("Accessing a universal charstring element of a non-specific "
3804 "universal charstring template.");
3805 return single_value
[index_value
];
3808 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](const INTEGER
& index_value
) const
3810 index_value
.must_bound("Indexing a universal charstring template with an "
3811 "unbound integer value.");
3812 return (*this)[(int)index_value
];
3815 boolean
UNIVERSAL_CHARSTRING_template::match
3816 (const UNIVERSAL_CHARSTRING
& other_value
, boolean
/* legacy */) const
3818 if (!other_value
.is_bound()) return FALSE
;
3819 int value_length
= other_value
.lengthof();
3820 if (!match_length(value_length
)) return FALSE
;
3821 switch (template_selection
) {
3822 case SPECIFIC_VALUE
:
3823 return single_value
== other_value
;
3830 case COMPLEMENTED_LIST
:
3831 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3832 if (value_list
.list_value
[i
].match(other_value
))
3833 return template_selection
== VALUE_LIST
;
3834 return template_selection
== COMPLEMENTED_LIST
;
3836 if (!value_range
.min_is_set
) TTCN_error("The lower bound is not set when "
3837 "matching with a universal charstring value range template.");
3838 if (!value_range
.max_is_set
) TTCN_error("The upper bound is not set when "
3839 "matching with a universal charstring value range template.");
3840 if (value_range
.max_value
< value_range
.min_value
)
3841 TTCN_error("The lower bound is greater than the upper bound "
3842 "when matching with a universal charstring value range template.");
3843 const universal_char
*uchars_ptr
= other_value
;
3844 for (int i
= 0; i
< value_length
; i
++) {
3845 if (uchars_ptr
[i
] < value_range
.min_value
||
3846 value_range
.max_value
< uchars_ptr
[i
]) return FALSE
;
3849 case STRING_PATTERN
: {
3850 if (!pattern_value
.regexp_init
) {
3852 TTCN_pattern_to_regexp_uni((const char*)(*pattern_string
));
3853 if(posix_str
==NULL
) {
3854 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
3855 (const char*)(*pattern_string
));
3857 int ret_val
=regcomp(&pattern_value
.posix_regexp
, posix_str
,
3858 REG_EXTENDED
|REG_NOSUB
);
3862 char msg
[ERRMSG_BUFSIZE
];
3863 regerror(ret_val
, &pattern_value
.posix_regexp
, msg
, ERRMSG_BUFSIZE
);
3864 regfree(&pattern_value
.posix_regexp
);
3865 TTCN_error("Pattern matching error: %s", msg
);
3867 pattern_value
.regexp_init
=TRUE
;
3869 char* other_value_converted
= other_value
.convert_to_regexp_form();
3870 int ret_val
=regexec(&pattern_value
.posix_regexp
, other_value_converted
, 0,
3872 Free(other_value_converted
);
3880 char msg
[ERRMSG_BUFSIZE
];
3881 regerror(ret_val
, &pattern_value
.posix_regexp
, msg
, ERRMSG_BUFSIZE
);
3882 TTCN_error("Pattern matching error: %s", msg
);
3886 TTCN_error("Matching with an uninitialized/unsupported universal "
3887 "charstring template.");
3892 const UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING_template::valueof() const
3894 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3895 TTCN_error("Performing valueof or send operation on a non-specific "
3896 "universal charstring template.");
3897 return single_value
;
3900 int UNIVERSAL_CHARSTRING_template::lengthof() const
3903 boolean has_any_or_none
;
3905 TTCN_error("Performing lengthof() operation on a universal charstring "
3906 "template which has an ifpresent attribute.");
3907 switch (template_selection
)
3909 case SPECIFIC_VALUE
:
3910 min_length
= single_value
.lengthof();
3911 has_any_or_none
= FALSE
;
3914 TTCN_error("Performing lengthof() operation on a universal charstring "
3915 "template containing omit value.");
3920 has_any_or_none
= TRUE
; // max. length is infinity
3924 // error if any element does not have length or the lengths differ
3925 if (value_list
.n_values
<1)
3926 TTCN_error("Internal error: "
3927 "Performing lengthof() operation on a universal charstring "
3928 "template containing an empty list.");
3929 int item_length
= value_list
.list_value
[0].lengthof();
3930 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
3931 if (value_list
.list_value
[i
].lengthof()!=item_length
)
3932 TTCN_error("Performing lengthof() operation on a universal charstring "
3933 "template containing a value list with different lengths.");
3935 min_length
= item_length
;
3936 has_any_or_none
= FALSE
;
3939 case COMPLEMENTED_LIST
:
3940 TTCN_error("Performing lengthof() operation on a universal charstring "
3941 "template containing complemented list.");
3942 case STRING_PATTERN
:
3943 TTCN_error("Performing lengthof() operation on a universal charstring "
3944 "template containing a pattern is not allowed.");
3946 TTCN_error("Performing lengthof() operation on an "
3947 "uninitialized/unsupported universal charstring template.");
3949 return check_section_is_single(min_length
, has_any_or_none
,
3950 "length", "a", "universal charstring template");
3953 void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type
,
3954 unsigned int list_length
)
3957 switch (template_type
) {
3959 case COMPLEMENTED_LIST
:
3960 set_selection(template_type
);
3961 value_list
.n_values
= list_length
;
3962 value_list
.list_value
= new UNIVERSAL_CHARSTRING_template
[list_length
];
3965 set_selection(VALUE_RANGE
);
3966 value_range
.min_is_set
= FALSE
;
3967 value_range
.max_is_set
= FALSE
;
3970 TTCN_error("Setting an invalid type for a universal charstring template.");
3974 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::list_item
3975 (unsigned int list_index
)
3977 if (template_selection
!= VALUE_LIST
&&
3978 template_selection
!= COMPLEMENTED_LIST
)
3979 TTCN_error("Accessing a list element of a non-list universal charstring "
3981 if (list_index
>= value_list
.n_values
)
3982 TTCN_error("Index overflow in a universal charstring value list template.");
3983 return value_list
.list_value
[list_index
];
3986 void UNIVERSAL_CHARSTRING_template::set_min
3987 (const UNIVERSAL_CHARSTRING
& min_value
)
3989 if (template_selection
!= VALUE_RANGE
) TTCN_error("Setting the lower bound "
3990 "for a non-range universal charstring template.");
3991 min_value
.must_bound("Setting an unbound value as lower bound in a "
3992 "universal charstring value range template.");
3993 int length
= min_value
.lengthof();
3994 if (length
!= 1) TTCN_error("The length of the lower bound in a universal "
3995 "charstring value range template must be 1 instead of %d.", length
);
3996 value_range
.min_is_set
= TRUE
;
3997 value_range
.min_value
= *(const universal_char
*)min_value
;
3998 if (value_range
.max_is_set
&& value_range
.max_value
< value_range
.min_value
)
3999 TTCN_error("The lower bound in a universal charstring value range template "
4000 "is greater than the upper bound.");
4003 void UNIVERSAL_CHARSTRING_template::set_max
4004 (const UNIVERSAL_CHARSTRING
& max_value
)
4006 if (template_selection
!= VALUE_RANGE
) TTCN_error("Setting the upper bound "
4007 "for a non-range universal charstring template.");
4008 max_value
.must_bound("Setting an unbound value as upper bound in a "
4009 "universal charstring value range template.");
4010 int length
= max_value
.lengthof();
4011 if (length
!= 1) TTCN_error("The length of the upper bound in a universal "
4012 "charstring value range template must be 1 instead of %d.", length
);
4013 value_range
.max_is_set
= TRUE
;
4014 value_range
.max_value
= *(const universal_char
*)max_value
;
4015 if (value_range
.min_is_set
&& value_range
.max_value
< value_range
.min_value
)
4016 TTCN_error("The upper bound in a universal charstring value range template "
4017 "is smaller than the lower bound.");
4020 void UNIVERSAL_CHARSTRING_template::log() const
4022 switch (template_selection
) {
4023 case STRING_PATTERN
:
4024 CHARSTRING_template::log_pattern(pattern_string
->lengthof(),
4025 (const char*)*pattern_string
);
4027 case SPECIFIC_VALUE
:
4030 case COMPLEMENTED_LIST
:
4031 TTCN_Logger::log_event_str("complement ");
4034 TTCN_Logger::log_char('(');
4035 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
4036 if (i
> 0) TTCN_Logger::log_event_str(", ");
4037 value_list
.list_value
[i
].log();
4039 TTCN_Logger::log_char(')');
4042 TTCN_Logger::log_char('(');
4043 if (value_range
.min_is_set
) {
4044 if (is_printable(value_range
.min_value
)) {
4045 TTCN_Logger::log_char('"');
4046 TTCN_Logger::log_char_escaped(value_range
.min_value
.uc_cell
);
4047 TTCN_Logger::log_char('"');
4049 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4050 value_range
.min_value
.uc_group
, value_range
.min_value
.uc_plane
,
4051 value_range
.min_value
.uc_row
, value_range
.min_value
.uc_cell
);
4053 } else TTCN_Logger::log_event_str("<unknown lower bound>");
4054 TTCN_Logger::log_event_str(" .. ");
4055 if (value_range
.max_is_set
) {
4056 if (is_printable(value_range
.max_value
)) {
4057 TTCN_Logger::log_char('"');
4058 TTCN_Logger::log_char_escaped(value_range
.max_value
.uc_cell
);
4059 TTCN_Logger::log_char('"');
4061 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4062 value_range
.max_value
.uc_group
, value_range
.max_value
.uc_plane
,
4063 value_range
.max_value
.uc_row
, value_range
.max_value
.uc_cell
);
4065 } else TTCN_Logger::log_event_str("<unknown upper bound>");
4066 TTCN_Logger::log_char(')');
4076 void UNIVERSAL_CHARSTRING_template::log_match
4077 (const UNIVERSAL_CHARSTRING
& match_value
, boolean
/* legacy */) const
4079 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
4080 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
4081 TTCN_Logger::print_logmatch_buffer();
4082 TTCN_Logger::log_event_str(" := ");
4085 TTCN_Logger::log_event_str(" with ");
4087 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
4088 else TTCN_Logger::log_event_str(" unmatched");
4091 void UNIVERSAL_CHARSTRING_template::set_param(Module_Param
& param
) {
4092 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "universal charstring template");
4093 Module_Param_Ptr mp
= ¶m
;
4094 if (param
.get_type() == Module_Param::MP_Reference
) {
4095 mp
= param
.get_referenced_param();
4097 switch (mp
->get_type()) {
4098 case Module_Param::MP_Omit
:
4101 case Module_Param::MP_Any
:
4104 case Module_Param::MP_AnyOrNone
:
4105 *this = ANY_OR_OMIT
;
4107 case Module_Param::MP_List_Template
:
4108 case Module_Param::MP_ComplementList_Template
: {
4109 UNIVERSAL_CHARSTRING_template temp
;
4110 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
4111 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
4112 for (size_t i
=0; i
<mp
->get_size(); i
++) {
4113 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
4117 case Module_Param::MP_Charstring
:
4118 *this = CHARSTRING(mp
->get_string_size(), (char*)mp
->get_string_data());
4120 case Module_Param::MP_Universal_Charstring
:
4121 *this = UNIVERSAL_CHARSTRING(mp
->get_string_size(), (universal_char
*)mp
->get_string_data());
4123 case Module_Param::MP_StringRange
: {
4124 universal_char lower_uchar
= mp
->get_lower_uchar();
4125 universal_char upper_uchar
= mp
->get_upper_uchar();
4127 set_selection(VALUE_RANGE
);
4128 value_range
.min_is_set
= TRUE
;
4129 value_range
.max_is_set
= TRUE
;
4130 value_range
.min_value
= lower_uchar
;
4131 value_range
.max_value
= upper_uchar
;
4133 case Module_Param::MP_Pattern
:
4135 pattern_string
= new CHARSTRING(mp
->get_pattern());
4136 pattern_value
.regexp_init
= FALSE
;
4137 set_selection(STRING_PATTERN
);
4139 case Module_Param::MP_Expression
:
4140 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
4141 UNIVERSAL_CHARSTRING operand1
, operand2
, result
;
4142 boolean is_pattern
= operand1
.set_param_internal(*mp
->get_operand1(), TRUE
);
4143 operand2
.set_param(*mp
->get_operand2());
4144 result
= operand1
+ operand2
;
4147 if (result
.charstring
) {
4148 pattern_string
= new CHARSTRING(result
.cstr
);
4151 pattern_string
= new CHARSTRING(result
.get_stringRepr_for_pattern());
4153 pattern_value
.regexp_init
= FALSE
;
4154 set_selection(STRING_PATTERN
);
4161 param
.expr_type_error("a charstring");
4165 param
.type_error("universal charstring template");
4167 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
4168 if (param
.get_length_restriction() != NULL
) {
4169 set_length_range(param
);
4172 set_length_range(*mp
);
4176 Module_Param
* UNIVERSAL_CHARSTRING_template::get_param(Module_Param_Name
& param_name
) const
4178 Module_Param
* mp
= NULL
;
4179 switch (template_selection
) {
4180 case UNINITIALIZED_TEMPLATE
:
4181 mp
= new Module_Param_Unbound();
4184 mp
= new Module_Param_Omit();
4187 mp
= new Module_Param_Any();
4190 mp
= new Module_Param_AnyOrNone();
4192 case SPECIFIC_VALUE
:
4193 mp
= single_value
.get_param(param_name
);
4196 case COMPLEMENTED_LIST
: {
4197 if (template_selection
== VALUE_LIST
) {
4198 mp
= new Module_Param_List_Template();
4201 mp
= new Module_Param_ComplementList_Template();
4203 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
4204 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
4208 mp
= new Module_Param_StringRange(value_range
.min_value
, value_range
.max_value
);
4210 case STRING_PATTERN
:
4211 mp
= new Module_Param_Pattern(mcopystr(*pattern_string
));
4217 mp
->set_ifpresent();
4219 mp
->set_length_restriction(get_length_range());
4223 void UNIVERSAL_CHARSTRING_template::encode_text(Text_Buf
& text_buf
) const
4225 encode_text_restricted(text_buf
);
4226 switch (template_selection
) {
4231 case SPECIFIC_VALUE
:
4232 single_value
.encode_text(text_buf
);
4235 case COMPLEMENTED_LIST
:
4236 text_buf
.push_int(value_list
.n_values
);
4237 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
4238 value_list
.list_value
[i
].encode_text(text_buf
);
4241 if (!value_range
.min_is_set
) TTCN_error("Text encoder: The lower bound is "
4242 "not set in a universal charstring value range template.");
4243 if (!value_range
.max_is_set
) TTCN_error("Text encoder: The upper bound is "
4244 "not set in a universal charstring value range template.");
4245 unsigned char buf
[8];
4246 buf
[0] = value_range
.min_value
.uc_group
;
4247 buf
[1] = value_range
.min_value
.uc_plane
;
4248 buf
[2] = value_range
.min_value
.uc_row
;
4249 buf
[3] = value_range
.min_value
.uc_cell
;
4250 buf
[4] = value_range
.max_value
.uc_group
;
4251 buf
[5] = value_range
.max_value
.uc_plane
;
4252 buf
[6] = value_range
.max_value
.uc_row
;
4253 buf
[7] = value_range
.max_value
.uc_cell
;
4254 text_buf
.push_raw(8, buf
);
4257 TTCN_error("Text encoder: Encoding an uninitialized/unsupported universal "
4258 "charstring template.");
4262 void UNIVERSAL_CHARSTRING_template::decode_text(Text_Buf
& text_buf
)
4265 decode_text_restricted(text_buf
);
4266 switch (template_selection
) {
4271 case SPECIFIC_VALUE
:
4272 single_value
.decode_text(text_buf
);
4275 case COMPLEMENTED_LIST
:
4276 value_list
.n_values
= text_buf
.pull_int().get_val();
4277 value_list
.list_value
=
4278 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
4279 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
4280 value_list
.list_value
[i
].decode_text(text_buf
);
4283 unsigned char buf
[8];
4284 text_buf
.pull_raw(8, buf
);
4285 value_range
.min_value
.uc_group
= buf
[0];
4286 value_range
.min_value
.uc_plane
= buf
[1];
4287 value_range
.min_value
.uc_row
= buf
[2];
4288 value_range
.min_value
.uc_cell
= buf
[3];
4289 value_range
.max_value
.uc_group
= buf
[4];
4290 value_range
.max_value
.uc_plane
= buf
[5];
4291 value_range
.max_value
.uc_row
= buf
[6];
4292 value_range
.max_value
.uc_cell
= buf
[7];
4293 if (value_range
.max_value
< value_range
.min_value
)
4294 TTCN_error("Text decoder: The received lower bound is greater than the "
4295 "upper bound in a universal charstring value range template.");
4296 value_range
.min_is_set
= TRUE
;
4297 value_range
.max_is_set
= TRUE
;
4300 TTCN_error("Text decoder: An unknown/unsupported selection was "
4301 "received for a universal charstring template.");
4305 boolean
UNIVERSAL_CHARSTRING_template::is_present(boolean legacy
/* = FALSE */) const
4307 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
4308 return !match_omit(legacy
);
4311 boolean
UNIVERSAL_CHARSTRING_template::match_omit(boolean legacy
/* = FALSE */) const
4313 if (is_ifpresent
) return TRUE
;
4314 switch (template_selection
) {
4319 case COMPLEMENTED_LIST
:
4321 // legacy behavior: 'omit' can appear in the value/complement list
4322 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
4323 if (value_list
.list_value
[i
].match_omit())
4324 return template_selection
==VALUE_LIST
;
4325 return template_selection
==COMPLEMENTED_LIST
;
4327 // else fall through
4334 #ifndef TITAN_RUNTIME_2
4335 void UNIVERSAL_CHARSTRING_template::check_restriction(template_res t_res
,
4336 const char* t_name
, boolean legacy
) const
4338 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
4339 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
4341 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
4344 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
4345 template_selection
==SPECIFIC_VALUE
)) return;
4348 if (!match_omit(legacy
)) return;
4353 TTCN_error("Restriction `%s' on template of type %s violated.",
4354 get_res_name(t_res
), t_name
? t_name
: "universal charstring");
4358 const CHARSTRING
& UNIVERSAL_CHARSTRING_template::get_single_value() const {
4359 if (!pattern_string
)
4360 TTCN_error("Pattern string does not exist in universal charstring template");
4361 return *pattern_string
;
4365 * ISO 2022 conversion functions -- these can be overwritten by users
4366 * by defining their own versions. Because these --of course :)-- are
4367 * not really conform to ISO 2022. :o)
4370 /** TTCN_UCSTR_2_ISO2022: A dummy common implementation. */
4371 OCTETSTRING
TTCN_UCSTR_2_ISO2022(const UNIVERSAL_CHARSTRING
& p_s
)
4373 const universal_char
* ucstr
=static_cast<const universal_char
*>(p_s
);
4374 int len
=p_s
.lengthof();
4375 unsigned char* osstr
=(unsigned char*)Malloc(len
);
4376 for(int i
=0; i
<len
; i
++) osstr
[i
]=ucstr
[i
].uc_cell
;
4377 OCTETSTRING
os(len
, osstr
);
4382 /** TTCN_ISO2022_2_UCSTR: A dummy common implementation. */
4383 UNIVERSAL_CHARSTRING
TTCN_ISO2022_2_UCSTR(const OCTETSTRING
& p_os
)
4385 const unsigned char* osstr
=static_cast<const unsigned char*>(p_os
);
4386 int len
=p_os
.lengthof();
4387 universal_char
* ucstr
=(universal_char
*)Malloc(len
*sizeof(*ucstr
));
4388 for(int i
=0; i
<len
; i
++) {
4389 ucstr
[i
].uc_group
=0;
4390 ucstr
[i
].uc_plane
=0;
4392 ucstr
[i
].uc_cell
=osstr
[i
];
4394 UNIVERSAL_CHARSTRING
us(len
, ucstr
);
4399 OCTETSTRING
TTCN_TeletexString_2_ISO2022(const TeletexString
& p_s
)
4401 return TTCN_UCSTR_2_ISO2022(p_s
);
4404 TeletexString
TTCN_ISO2022_2_TeletexString(const OCTETSTRING
& p_os
)
4406 return TTCN_ISO2022_2_UCSTR(p_os
);
4409 OCTETSTRING
TTCN_VideotexString_2_ISO2022(const VideotexString
& p_s
)
4411 return TTCN_UCSTR_2_ISO2022(p_s
);
4414 VideotexString
TTCN_ISO2022_2_VideotexString(const OCTETSTRING
& p_os
)
4416 return TTCN_ISO2022_2_UCSTR(p_os
);
4419 OCTETSTRING
TTCN_GraphicString_2_ISO2022(const GraphicString
& p_s
)
4421 return TTCN_UCSTR_2_ISO2022(p_s
);
4424 GraphicString
TTCN_ISO2022_2_GraphicString(const OCTETSTRING
& p_os
)
4426 return TTCN_ISO2022_2_UCSTR(p_os
);
4429 OCTETSTRING
TTCN_GeneralString_2_ISO2022(const GeneralString
& p_s
)
4431 return TTCN_UCSTR_2_ISO2022(p_s
);
4434 GeneralString
TTCN_ISO2022_2_GeneralString(const OCTETSTRING
& p_os
)
4436 return TTCN_ISO2022_2_UCSTR(p_os
);