1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
19 * Szabo, Janos Zoltan – initial implementation
21 * Zalanyi, Balazs Andor
23 ******************************************************************************/
24 #include "Universal_charstring.hh"
26 #include "../common/dbgnew.hh"
27 #include "../common/memory.h"
28 #include "../common/pattern.hh"
29 #include "../common/Quadruple.hh"
31 #include "Octetstring.hh"
32 #include "String_struct.hh"
33 #include "Param_Types.hh"
37 #include "Addfunc.hh" // for unichar2int
43 #define ERRMSG_BUFSIZE 500
45 // global function for universal_char comparison
47 boolean
operator==(const universal_char
& left_value
,
48 const universal_char
& right_value
)
50 return left_value
.uc_group
== right_value
.uc_group
&&
51 left_value
.uc_plane
== right_value
.uc_plane
&&
52 left_value
.uc_row
== right_value
.uc_row
&&
53 left_value
.uc_cell
== right_value
.uc_cell
;
56 boolean
operator<(const universal_char
& left_value
,
57 const universal_char
& right_value
)
59 if (left_value
.uc_group
< right_value
.uc_group
) return TRUE
;
60 else if (left_value
.uc_group
== right_value
.uc_group
) {
61 if (left_value
.uc_plane
< right_value
.uc_plane
) return TRUE
;
62 else if (left_value
.uc_plane
== right_value
.uc_plane
) {
63 if (left_value
.uc_row
< right_value
.uc_row
) return TRUE
;
64 else if (left_value
.uc_row
== right_value
.uc_row
) {
65 if (left_value
.uc_cell
< right_value
.uc_cell
) return TRUE
;
72 /** The amount of memory needed for a string containing n characters. */
73 #define MEMORY_SIZE(n) (sizeof(universal_charstring_struct) + \
74 ((n) - 1) * sizeof(universal_char))
76 // member functions of class UNIVERSAL_CHARSTRING
78 /** Allocate space for n characters.
80 * @param n_uchars number of characters needed
84 * If n_uchars is 0, no memory is allocated and a reference to the
85 * "empty string" is used instead.
87 * Otherwise, space for n_uchars is allocated (no terminating null).
89 * @note If the string is not empty, this will leak memory.
90 * Probably clean_up() should have been called before.
92 void UNIVERSAL_CHARSTRING::init_struct(int n_uchars
)
96 TTCN_error("Initializing a universal charstring with a negative length.");
97 } else if (n_uchars
== 0) {
98 /* This will represent the empty strings so they won't need allocated
99 * memory, this delays the memory allocation until it is really needed.
101 static universal_charstring_struct empty_string
=
102 { 1, 0, { { '\0', '\0', '\0', '\0' } } };
103 val_ptr
= &empty_string
;
104 empty_string
.ref_count
++;
106 val_ptr
= (universal_charstring_struct
*)Malloc(MEMORY_SIZE(n_uchars
));
107 val_ptr
->ref_count
= 1;
108 val_ptr
->n_uchars
= n_uchars
;
112 void UNIVERSAL_CHARSTRING::copy_value()
114 if (val_ptr
== NULL
|| val_ptr
->n_uchars
<= 0)
115 TTCN_error("Internal error: Invalid internal data structure when copying "
116 "the memory area of a universal charstring value.");
117 if (val_ptr
->ref_count
> 1) {
118 universal_charstring_struct
*old_ptr
= val_ptr
;
119 old_ptr
->ref_count
--;
120 init_struct(old_ptr
->n_uchars
);
121 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
, old_ptr
->n_uchars
*
122 sizeof(universal_char
));
126 void UNIVERSAL_CHARSTRING::clean_up()
128 if (val_ptr
!= NULL
) {
129 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
130 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
131 else TTCN_error("Internal error: Invalid reference counter in a universal "
132 "charstring value.");
138 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars
, bool cstring
)
139 : val_ptr(NULL
), cstr(cstring
? n_uchars
: 0), charstring(cstring
)
142 init_struct(n_uchars
);
145 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING()
146 : val_ptr(NULL
), cstr(0), charstring(false)
149 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(unsigned char uc_group
,
150 unsigned char uc_plane
, unsigned char uc_row
, unsigned char uc_cell
)
154 val_ptr
->uchars_ptr
[0].uc_group
= uc_group
;
155 val_ptr
->uchars_ptr
[0].uc_plane
= uc_plane
;
156 val_ptr
->uchars_ptr
[0].uc_row
= uc_row
;
157 val_ptr
->uchars_ptr
[0].uc_cell
= uc_cell
;
160 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
161 (const universal_char
& other_value
)
162 : cstr(0), charstring(false)
165 val_ptr
->uchars_ptr
[0] = other_value
;
168 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars
,
169 const universal_char
*uchars_ptr
)
170 : cstr(0), charstring(false)
172 init_struct(n_uchars
);
173 memcpy(val_ptr
->uchars_ptr
, uchars_ptr
, n_uchars
* sizeof(universal_char
));
176 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const char *chars_ptr
)
177 : val_ptr(NULL
), cstr(chars_ptr
), charstring(true)
181 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_chars
,
182 const char *chars_ptr
)
183 : val_ptr(NULL
), cstr(n_chars
, chars_ptr
), charstring(true)
187 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const CHARSTRING
& other_value
)
188 : val_ptr(NULL
), cstr(other_value
), charstring(true)
192 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
193 (const CHARSTRING_ELEMENT
& other_value
)
194 : val_ptr(NULL
), cstr(other_value
), charstring(true)
198 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
199 (const UNIVERSAL_CHARSTRING
& other_value
)
200 : Base_Type(other_value
), charstring(other_value
.charstring
)
202 other_value
.must_bound("Copying an unbound universal charstring value.");
203 if (other_value
.charstring
) {
204 cstr
= other_value
.cstr
;
207 val_ptr
= other_value
.val_ptr
;
208 val_ptr
->ref_count
++;
213 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
214 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
215 : charstring(other_value
.get_uchar().is_char())
217 other_value
.must_bound("Initialization of a universal charstring with an "
218 "unbound universal charstring element.");
220 cstr
= CHARSTRING((const char)(other_value
.get_uchar().uc_cell
));
224 val_ptr
->uchars_ptr
[0] = other_value
.get_uchar();
228 UNIVERSAL_CHARSTRING::~UNIVERSAL_CHARSTRING()
234 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
235 (const universal_char
& other_value
)
238 if (other_value
.is_char()) {
239 cstr
= CHARSTRING(other_value
.uc_cell
);
244 val_ptr
->uchars_ptr
[0] = other_value
;
250 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
251 (const char* other_value
)
261 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
262 (const CHARSTRING
& other_value
)
272 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
273 (const CHARSTRING_ELEMENT
& other_value
)
283 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
284 (const UNIVERSAL_CHARSTRING
& other_value
)
286 other_value
.must_bound("Assignment of an unbound universal charstring "
288 if (&other_value
!= this) {
290 if (other_value
.charstring
) {
291 cstr
= other_value
.cstr
;
293 val_ptr
= other_value
.val_ptr
;
294 val_ptr
->ref_count
++;
298 charstring
= other_value
.charstring
;
303 UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING::operator=
304 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
306 other_value
.must_bound("Assignment of an unbound universal charstring "
307 "element to a universal charstring.");
308 if (other_value
.str_val
.charstring
) {
309 char c
= other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
311 cstr
= CHARSTRING(c
);
314 universal_char uchar_value
= other_value
.get_uchar();
317 val_ptr
->uchars_ptr
[0] = uchar_value
;
323 boolean
UNIVERSAL_CHARSTRING::operator==
324 (const universal_char
& other_value
) const
326 must_bound("The left operand of comparison is an unbound universal "
327 "charstring value.");
329 return cstr
.lengthof() == 1 && other_value
.uc_group
== 0
330 && other_value
.uc_plane
== 0 && other_value
.uc_row
== 0
331 && other_value
.uc_cell
== (cbyte
)cstr
.val_ptr
->chars_ptr
[0];
333 if (val_ptr
->n_uchars
!= 1) return FALSE
;
334 else return val_ptr
->uchars_ptr
[0] == other_value
;
337 boolean
UNIVERSAL_CHARSTRING::operator==(const char* other_value
) const
339 must_bound("The left operand of comparison is an unbound universal "
340 "charstring value.");
342 return cstr
== other_value
;
345 if (other_value
== NULL
) n_chars
= 0;
346 else n_chars
= strlen(other_value
);
347 if (val_ptr
->n_uchars
!= n_chars
) return FALSE
;
348 for (int i
= 0; i
< n_chars
; i
++) {
349 if (val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
350 val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
351 val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
352 val_ptr
->uchars_ptr
[i
].uc_cell
!= (cbyte
)other_value
[i
]) return FALSE
;
358 boolean
UNIVERSAL_CHARSTRING::operator==
359 (const CHARSTRING
& other_value
) const
361 must_bound("The left operand of comparison is an unbound universal "
362 "charstring value.");
363 other_value
.must_bound("The right operand of comparison is an unbound "
364 "charstring value.");
366 return cstr
== other_value
;
367 if (val_ptr
->n_uchars
!= other_value
.val_ptr
->n_chars
) return FALSE
;
368 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
369 if (val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
370 val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
371 val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
372 val_ptr
->uchars_ptr
[i
].uc_cell
!=(cbyte
)other_value
.val_ptr
->chars_ptr
[i
])
378 boolean
UNIVERSAL_CHARSTRING::operator==
379 (const CHARSTRING_ELEMENT
& 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 "charstring element.");
386 return cstr
== other_value
;
387 if (val_ptr
->n_uchars
!= 1) return FALSE
;
388 else return val_ptr
->uchars_ptr
[0].uc_group
== 0 &&
389 val_ptr
->uchars_ptr
[0].uc_plane
== 0 &&
390 val_ptr
->uchars_ptr
[0].uc_row
== 0 &&
391 val_ptr
->uchars_ptr
[0].uc_cell
== (cbyte
)other_value
.get_char();
394 boolean
UNIVERSAL_CHARSTRING::operator==
395 (const UNIVERSAL_CHARSTRING
& other_value
) const
397 must_bound("The left operand of comparison is an unbound universal "
398 "charstring value.");
399 other_value
.must_bound("The right operand of comparison is an unbound "
400 "universal charstring value.");
402 return cstr
== other_value
;
403 else if (other_value
.charstring
)
404 return other_value
.cstr
== *this;
405 if (val_ptr
->n_uchars
!= other_value
.val_ptr
->n_uchars
) return FALSE
;
406 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
407 if (val_ptr
->uchars_ptr
[i
] != other_value
.val_ptr
->uchars_ptr
[i
])
413 boolean
UNIVERSAL_CHARSTRING::operator==
414 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
416 must_bound("The left operand of comparison is an unbound universal "
417 "charstring value.");
418 other_value
.must_bound("The right operand of comparison is an unbound "
419 "universal charstring element.");
421 return cstr
== other_value
;
422 if (val_ptr
->n_uchars
!= 1) return FALSE
;
423 else return val_ptr
->uchars_ptr
[0] == other_value
.get_uchar();
426 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
427 (const universal_char
& other_value
) const
429 must_bound("The left operand of concatenation is an unbound universal "
430 "charstring value.");
432 if (other_value
.is_char()) {
433 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1, true);
434 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
435 cstr
.val_ptr
->n_chars
);
436 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
440 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1);
441 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
442 universal_char
& uc
= ret_val
.val_ptr
->uchars_ptr
[i
];
443 uc
.uc_group
= uc
.uc_plane
= uc
.uc_row
= 0;
444 uc
.uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
446 ret_val
.val_ptr
->uchars_ptr
[cstr
.val_ptr
->n_chars
] = other_value
;
450 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
451 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
452 val_ptr
->n_uchars
* sizeof(universal_char
));
453 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
;
457 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
458 (const char* other_value
) const
460 must_bound("The left operand of concatenation is an unbound universal "
461 "charstring value.");
463 if (other_value
== NULL
) other_len
= 0;
464 else other_len
= strlen(other_value
);
465 if (other_len
== 0) return *this;
467 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + other_len
, true);
468 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
469 cstr
.val_ptr
->n_chars
);
470 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
471 other_value
, other_len
);
474 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ other_len
);
475 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
476 val_ptr
->n_uchars
* sizeof(universal_char
));
477 for (int i
= 0; i
< other_len
; i
++) {
478 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_group
= 0;
479 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_plane
= 0;
480 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_row
= 0;
481 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_cell
= other_value
[i
];
486 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
487 (const CHARSTRING
& other_value
) const
489 must_bound("The left operand of concatenation is an unbound universal "
490 "charstring value.");
491 other_value
.must_bound("The right operand of concatenation is an unbound "
492 "charstring value.");
493 if (other_value
.val_ptr
->n_chars
== 0) return *this;
495 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + other_value
.val_ptr
->n_chars
,
497 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
498 cstr
.val_ptr
->n_chars
);
499 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
500 other_value
.val_ptr
->chars_ptr
, other_value
.val_ptr
->n_chars
);
503 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+
504 other_value
.val_ptr
->n_chars
);
505 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
506 val_ptr
->n_uchars
* sizeof(universal_char
));
507 for (int i
= 0; i
< other_value
.val_ptr
->n_chars
; i
++) {
508 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_group
= 0;
509 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_plane
= 0;
510 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_row
= 0;
511 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
+ i
].uc_cell
=
512 other_value
.val_ptr
->chars_ptr
[i
];
517 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
518 (const CHARSTRING_ELEMENT
& other_value
) const
520 must_bound("The left operand of concatenation is an unbound universal "
521 "charstring value.");
522 other_value
.must_bound("The right operand of concatenation is an unbound "
523 "charstring element.");
525 UNIVERSAL_CHARSTRING
ret_val(cstr
.lengthof() + 1, true);
526 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
527 cstr
.val_ptr
->n_chars
);
528 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
529 other_value
.get_char();
532 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
533 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
534 val_ptr
->n_uchars
* sizeof(universal_char
));
535 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_group
= 0;
536 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_plane
= 0;
537 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_row
= 0;
538 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
].uc_cell
=
539 other_value
.get_char();
543 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
544 (const UNIVERSAL_CHARSTRING
& other_value
) const
546 must_bound("The left operand of concatenation is an unbound universal "
547 "charstring value.");
548 other_value
.must_bound("The right operand of concatenation is an unbound "
549 "universal charstring value.");
551 if (cstr
.val_ptr
->n_chars
== 0)
553 if (other_value
.charstring
) {
554 if (other_value
.cstr
.val_ptr
->n_chars
== 0)
556 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+
557 other_value
.cstr
.val_ptr
->n_chars
, true);
558 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
559 cstr
.val_ptr
->n_chars
);
560 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ cstr
.val_ptr
->n_chars
,
561 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
564 if (other_value
.val_ptr
->n_uchars
== 0)
566 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+
567 other_value
.val_ptr
->n_uchars
);
568 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
569 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
570 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
571 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
572 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
574 memcpy(ret_val
.val_ptr
->uchars_ptr
+ cstr
.val_ptr
->n_chars
,
575 other_value
.val_ptr
->uchars_ptr
, other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
579 if (other_value
.charstring
) {
580 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ other_value
.cstr
.val_ptr
->n_chars
);
581 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
* sizeof(universal_char
));
582 for (int i
= val_ptr
->n_uchars
; i
< val_ptr
->n_uchars
+ other_value
.cstr
.val_ptr
->n_chars
; i
++) {
583 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
584 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
585 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
586 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= other_value
.cstr
.val_ptr
->chars_ptr
[i
-val_ptr
->n_uchars
];
590 if (val_ptr
->n_uchars
== 0) return other_value
;
591 if (other_value
.val_ptr
->n_uchars
== 0) return *this;
592 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+
593 other_value
.val_ptr
->n_uchars
);
594 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
595 val_ptr
->n_uchars
* sizeof(universal_char
));
596 memcpy(ret_val
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
,
597 other_value
.val_ptr
->uchars_ptr
,
598 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
604 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator+
605 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
607 must_bound("The left operand of concatenation is an unbound universal "
608 "charstring value.");
609 other_value
.must_bound("The right operand of concatenation is an unbound "
610 "universal charstring element.");
611 bool other_ischar
= other_value
.str_val
.charstring
;
614 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+ 1, true);
615 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, cstr
.val_ptr
->chars_ptr
,
616 cstr
.val_ptr
->n_chars
);
617 ret_val
.cstr
.val_ptr
->chars_ptr
[cstr
.val_ptr
->n_chars
] =
618 other_value
.get_uchar().uc_cell
;
621 UNIVERSAL_CHARSTRING
ret_val(cstr
.val_ptr
->n_chars
+ 1);
622 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
623 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
624 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
625 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
626 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
628 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
.get_uchar();
631 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
+ 1);
632 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
,
633 val_ptr
->n_uchars
* sizeof(universal_char
));
635 universal_char
& uc
= ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
];
636 uc
.uc_group
= uc
.uc_plane
= uc
.uc_row
= 0;
637 uc
.uc_cell
= other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
639 ret_val
.val_ptr
->uchars_ptr
[val_ptr
->n_uchars
] = other_value
.get_uchar();
644 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator<<=
645 (int rotate_count
) const
647 must_bound("The left operand of rotate left operator is an unbound "
648 "universal charstring value.");
651 return cstr
<<= rotate_count
;
653 if (val_ptr
->n_uchars
== 0) return *this;
654 if (rotate_count
>= 0) {
655 rotate_count
%= val_ptr
->n_uchars
;
656 if (rotate_count
== 0) return *this;
657 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
);
658 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
+ rotate_count
,
659 (val_ptr
->n_uchars
- rotate_count
) * sizeof(universal_char
));
660 memcpy(ret_val
.val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
- rotate_count
,
661 val_ptr
->uchars_ptr
, rotate_count
* sizeof(universal_char
));
663 } else return *this >>= (-rotate_count
);
666 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator<<=
667 (const INTEGER
& rotate_count
) const
669 rotate_count
.must_bound("The right operand of rotate left operator is an "
670 "unbound integer value.");
671 return *this <<= (int)rotate_count
;
674 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator>>=
675 (int rotate_count
) const
677 must_bound("The left operand of rotate right operator is an unbound "
678 "universal charstring value.");
681 return cstr
>>= rotate_count
;
683 if (val_ptr
->n_uchars
== 0) return *this;
684 if (rotate_count
>= 0) {
685 rotate_count
%= val_ptr
->n_uchars
;
686 if (rotate_count
== 0) return *this;
687 UNIVERSAL_CHARSTRING
ret_val(val_ptr
->n_uchars
);
688 memcpy(ret_val
.val_ptr
->uchars_ptr
, val_ptr
->uchars_ptr
+
689 val_ptr
->n_uchars
- rotate_count
, rotate_count
* sizeof(universal_char
));
690 memcpy(ret_val
.val_ptr
->uchars_ptr
+ rotate_count
, val_ptr
->uchars_ptr
,
691 (val_ptr
->n_uchars
- rotate_count
) * sizeof(universal_char
));
693 } else return *this <<= (-rotate_count
);
697 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::operator>>=
698 (const INTEGER
& rotate_count
) const
700 rotate_count
.must_bound("The right operand of rotate right operator is an "
701 "unbound integer value.");
702 return *this >>= (int)rotate_count
;
706 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
709 if (!charstring
&& val_ptr
== NULL
&& index_value
== 0) {
711 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE
, *this, 0);
713 must_bound("Accessing an element of an unbound universal charstring "
715 if (index_value
< 0) TTCN_error("Accessing a universal charstring element "
716 "using a negative index (%d).", index_value
);
718 charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
;
719 if (index_value
> n_uchars
) TTCN_error("Index overflow when accessing a "
720 "universal charstring element: The index is %d, but the string has only "
721 "%d characters.", index_value
, n_uchars
);
722 if (index_value
== n_uchars
) {
724 (void)cstr
[index_value
]; // invoked for side-effect only (incr. length)
726 if (val_ptr
->ref_count
== 1) {
727 val_ptr
= (universal_charstring_struct
*)
728 Realloc(val_ptr
, MEMORY_SIZE(n_uchars
+ 1));
731 universal_charstring_struct
*old_ptr
= val_ptr
;
732 old_ptr
->ref_count
--;
733 init_struct(n_uchars
+ 1);
734 memcpy(val_ptr
->uchars_ptr
, old_ptr
->uchars_ptr
,
735 n_uchars
* sizeof(universal_char
));
738 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE
, *this, index_value
);
739 } else return UNIVERSAL_CHARSTRING_ELEMENT(TRUE
, *this, index_value
);
743 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
744 (const INTEGER
& index_value
)
746 index_value
.must_bound("Indexing a universal charstring value with an "
747 "unbound integer value.");
748 return (*this)[(int)index_value
];
751 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
752 (int index_value
) const
754 must_bound("Accessing an element of an unbound universal charstring value.");
755 const int size
= charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
;
756 if (index_value
< 0) TTCN_error("Accessing a universal charstring element "
757 "using a negative index (%d).", index_value
);
758 else if (index_value
>= size
) TTCN_error("Index overflow when "
759 "accessing a universal charstring element: The index is %d, but the "
760 "string has only %d characters.", index_value
, size
);
761 return UNIVERSAL_CHARSTRING_ELEMENT(TRUE
,
762 const_cast<UNIVERSAL_CHARSTRING
&>(*this), index_value
);
765 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING::operator[]
766 (const INTEGER
& index_value
) const
768 index_value
.must_bound("Indexing a universal charstring value with an "
769 "unbound integer value.");
770 return (*this)[(int)index_value
];
774 UNIVERSAL_CHARSTRING::operator const universal_char
*() const
776 must_bound("Casting an unbound universal charstring value to const "
779 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
780 return val_ptr
->uchars_ptr
;
783 int UNIVERSAL_CHARSTRING::lengthof() const
785 must_bound("Performing lengthof operation on an unbound universal charstring "
788 return cstr
.val_ptr
->n_chars
;
789 return val_ptr
->n_uchars
;
792 char* UNIVERSAL_CHARSTRING::convert_to_regexp_form() const {
793 must_bound("Performing pattern conversion operation on an unbound"
794 "universal charstring value.");
795 int size
= (charstring
? cstr
.val_ptr
->n_chars
: val_ptr
->n_uchars
) * 8 + 1;
796 char* res
= static_cast<char*>(Malloc(size
));
801 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++, ptr
+= 8) {
802 q
.set(0, 0, 0, cstr
.val_ptr
->chars_ptr
[i
]);
803 Quad::get_hexrepr(q
, ptr
);
806 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++, ptr
+= 8) {
807 q
.set(val_ptr
->uchars_ptr
[i
].uc_group
, val_ptr
->uchars_ptr
[i
].uc_plane
,
808 val_ptr
->uchars_ptr
[i
].uc_row
, val_ptr
->uchars_ptr
[i
].uc_cell
);
809 Quad::get_hexrepr(q
, ptr
);
814 static inline boolean
is_printable(const universal_char
& uchar
)
816 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
817 TTCN_Logger::is_printable(uchar
.uc_cell
);
820 CHARSTRING
UNIVERSAL_CHARSTRING::get_stringRepr_for_pattern() const {
821 must_bound("Performing pattern conversion operation on an unbound"
822 "universal charstring value.");
823 CHARSTRING
ret_val("");
825 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
826 const char& chr
= cstr
.val_ptr
->chars_ptr
[i
];
827 if (TTCN_Logger::is_printable(chr
))
830 ret_val
+= "\\q{0,0,0,";
831 ret_val
+= int2str(chr
);
836 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
837 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
838 if (is_printable(uchar
))
839 ret_val
+= uchar
.uc_cell
;
842 ret_val
+= int2str(uchar
.uc_group
);
844 ret_val
+= int2str(uchar
.uc_plane
);
846 ret_val
+= int2str(uchar
.uc_row
);
848 ret_val
+= int2str(uchar
.uc_cell
);
855 void UNIVERSAL_CHARSTRING::convert_cstr_to_uni() {
856 init_struct(cstr
.lengthof());
857 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; i
++) {
858 val_ptr
->uchars_ptr
[i
].uc_group
= 0;
859 val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
860 val_ptr
->uchars_ptr
[i
].uc_row
= 0;
861 val_ptr
->uchars_ptr
[i
].uc_cell
= cstr
.val_ptr
->chars_ptr
[i
];
868 void UNIVERSAL_CHARSTRING::dump() const
870 if (val_ptr
!= NULL
) {
871 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
872 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
873 std::wcout
<< "uchar[" << i
<< "] = " << "("
874 << uchar
.uc_group
<< "," << uchar
.uc_plane
<< "," << uchar
.uc_row
<< "," << uchar
.uc_cell
<< ")"<< std::endl
;
879 void UNIVERSAL_CHARSTRING::log() const
885 if (val_ptr
!= NULL
) {
886 expstring_t buffer
= 0;
887 enum { INIT
, PCHAR
, UCHAR
} state
= INIT
;
888 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
889 const universal_char
& uchar
= val_ptr
->uchars_ptr
[i
];
890 if (is_printable(uchar
)) {
891 // the actual character is printable
893 case UCHAR
: // concatenation sign if previous part was not printable
894 buffer
= mputstr(buffer
, " & ");
896 case INIT
: // opening "
897 buffer
= mputc(buffer
, '"');
899 case PCHAR
: // the character itself
900 TTCN_Logger::log_char_escaped(uchar
.uc_cell
, buffer
);
905 // the actual character is not printable
907 case PCHAR
: // closing " if previous part was printable
908 buffer
= mputc(buffer
, '"');
910 case UCHAR
: // concatenation sign
911 buffer
= mputstr(buffer
, " & ");
913 case INIT
: // the character itself
914 buffer
= mputprintf(buffer
, "char(%u, %u, %u, %u)",
915 uchar
.uc_group
, uchar
.uc_plane
, uchar
.uc_row
, uchar
.uc_cell
);
923 case INIT
: // the string was empty
924 buffer
= mputstr(buffer
, "\"\"");
926 case PCHAR
: // last character was printable -> closing "
927 buffer
= mputc(buffer
, '"');
932 TTCN_Logger::log_event_str(buffer
);
935 TTCN_Logger::log_event_unbound();
939 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING::from_UTF8_buffer(TTCN_Buffer
& p_buff
)
942 p_buff
.get_string(os
);
943 if ("UTF-8" == get_stringencoding(os
)) {
944 UNIVERSAL_CHARSTRING ret
;
945 ret
.decode_utf8(p_buff
.get_len(), p_buff
.get_data());
948 return UNIVERSAL_CHARSTRING(p_buff
.get_len(), (const char*)p_buff
.get_data());
952 boolean
UNIVERSAL_CHARSTRING::set_param_internal(Module_Param
& param
, boolean allow_pattern
) {
953 boolean is_pattern
= FALSE
;
954 param
.basic_check(Module_Param::BC_VALUE
|Module_Param::BC_LIST
, "universal charstring value");
955 Module_Param_Ptr mp
= ¶m
;
956 if (param
.get_type() == Module_Param::MP_Reference
) {
957 mp
= param
.get_referenced_param();
959 switch (mp
->get_type()) {
960 case Module_Param::MP_Charstring
: {
961 switch (param
.get_operation_type()) {
962 case Module_Param::OT_ASSIGN
:
965 case Module_Param::OT_CONCAT
: {
967 buff
.put_s(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
969 *this = *this + from_UTF8_buffer(buff
);
971 *this = from_UTF8_buffer(buff
);
975 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
978 case Module_Param::MP_Universal_Charstring
: {
979 switch (param
.get_operation_type()) {
980 case Module_Param::OT_ASSIGN
:
983 case Module_Param::OT_CONCAT
:
985 *this = *this + UNIVERSAL_CHARSTRING(mp
->get_string_size(), (universal_char
*)mp
->get_string_data());
987 *this = UNIVERSAL_CHARSTRING(mp
->get_string_size(), (universal_char
*)mp
->get_string_data());
991 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
994 case Module_Param::MP_Expression
:
995 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
996 UNIVERSAL_CHARSTRING operand1
, operand2
;
997 is_pattern
= operand1
.set_param_internal(*mp
->get_operand1(), allow_pattern
);
998 operand2
.set_param(*mp
->get_operand2());
999 if (param
.get_operation_type() == Module_Param::OT_CONCAT
) {
1000 *this = *this + operand1
+ operand2
;
1003 *this = operand1
+ operand2
;
1007 param
.expr_type_error("a universal charstring");
1010 case Module_Param::MP_Pattern
:
1011 if (allow_pattern
) {
1012 *this = CHARSTRING(mp
->get_pattern());
1016 // else fall through
1018 param
.type_error("universal charstring value");
1023 void UNIVERSAL_CHARSTRING::set_param(Module_Param
& param
) {
1024 set_param_internal(param
, FALSE
);
1027 Module_Param
* UNIVERSAL_CHARSTRING::get_param(Module_Param_Name
& param_name
) const
1030 return new Module_Param_Unbound();
1033 return cstr
.get_param(param_name
);
1035 universal_char
* val_cpy
= (universal_char
*)Malloc(val_ptr
->n_uchars
* sizeof(universal_char
));
1036 memcpy(val_cpy
, val_ptr
->uchars_ptr
, val_ptr
->n_uchars
* sizeof(universal_char
));
1037 return new Module_Param_Universal_Charstring(val_ptr
->n_uchars
, val_cpy
);
1040 void UNIVERSAL_CHARSTRING::encode_text(Text_Buf
& text_buf
) const
1042 must_bound("Text encoder: Encoding an unbound universal charstring value.");
1044 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1045 text_buf
.push_int(val_ptr
->n_uchars
);
1046 for (int i
= 0; i
< val_ptr
->n_uchars
; i
++) {
1047 unsigned char buf
[4];
1048 buf
[0] = val_ptr
->uchars_ptr
[i
].uc_group
;
1049 buf
[1] = val_ptr
->uchars_ptr
[i
].uc_plane
;
1050 buf
[2] = val_ptr
->uchars_ptr
[i
].uc_row
;
1051 buf
[3] = val_ptr
->uchars_ptr
[i
].uc_cell
;
1052 text_buf
.push_raw(4, buf
);
1056 void UNIVERSAL_CHARSTRING::decode_text(Text_Buf
& text_buf
)
1058 int n_uchars
= text_buf
.pull_int().get_val();
1059 if (n_uchars
< 0) TTCN_error("Text decoder: Negative length was received "
1060 "for a universal charstring.");
1063 init_struct(n_uchars
);
1064 for (int i
= 0; i
< n_uchars
; i
++) {
1065 unsigned char buf
[4];
1066 text_buf
.pull_raw(4, buf
);
1067 val_ptr
->uchars_ptr
[i
].uc_group
= buf
[0];
1068 val_ptr
->uchars_ptr
[i
].uc_plane
= buf
[1];
1069 val_ptr
->uchars_ptr
[i
].uc_row
= buf
[2];
1070 val_ptr
->uchars_ptr
[i
].uc_cell
= buf
[3];
1074 void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t
& p_td
,
1075 TTCN_Buffer
& p_buf
, TTCN_EncDec::coding_t p_coding
, ...) const
1078 va_start(pvar
, p_coding
);
1080 case TTCN_EncDec::CT_BER
: {
1081 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
1082 unsigned BER_coding
=va_arg(pvar
, unsigned);
1083 BER_encode_chk_coding(BER_coding
);
1084 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
1085 tlv
->put_in_buffer(p_buf
);
1086 ASN_BER_TLV_t::destruct(tlv
);
1088 case TTCN_EncDec::CT_RAW
: {
1089 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
1091 TTCN_EncDec_ErrorContext::error_internal
1092 ("No RAW descriptor available for type '%s'.", p_td
.name
);
1096 RAW_enc_tree
root(TRUE
, NULL
, &rp
, 1, p_td
.raw
);
1097 RAW_encode(p_td
, root
);
1098 root
.put_to_buf(p_buf
);
1100 case TTCN_EncDec::CT_TEXT
: {
1101 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
1103 TTCN_EncDec_ErrorContext::error_internal
1104 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
1105 TEXT_encode(p_td
,p_buf
);
1107 case TTCN_EncDec::CT_XER
: {
1108 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
1109 unsigned XER_coding
=va_arg(pvar
, unsigned);
1110 switch (p_td
.asnbasetype
) {
1111 case TTCN_Typedescriptor_t::BMPSTRING
:
1112 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1113 XER_coding
|= XER_ESCAPE_ENTITIES
;
1115 default: // nothing to do
1118 XER_encode(*p_td
.xer
,p_buf
, XER_coding
, 0, 0);
1121 case TTCN_EncDec::CT_JSON
: {
1122 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
1124 TTCN_EncDec_ErrorContext::error_internal
1125 ("No JSON descriptor available for type '%s'.", p_td
.name
);
1126 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
1127 JSON_encode(p_td
, tok
);
1128 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
1131 TTCN_error("Unknown coding method requested to encode type '%s'",
1137 void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t
& p_td
,
1138 TTCN_Buffer
& p_buf
, TTCN_EncDec::coding_t p_coding
, ...)
1141 va_start(pvar
, p_coding
);
1143 case TTCN_EncDec::CT_BER
: {
1144 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
1145 unsigned L_form
=va_arg(pvar
, unsigned);
1147 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
1148 BER_decode_TLV(p_td
, tlv
, L_form
);
1149 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
1151 case TTCN_EncDec::CT_RAW
: {
1152 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
1154 TTCN_EncDec_ErrorContext::error_internal
1155 ("No RAW descriptor available for type '%s'.", p_td
.name
);
1157 switch(p_td
.raw
->top_bit_order
){
1165 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
1166 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
1167 "Can not decode type '%s', because invalid or incomplete"
1168 " message was received"
1171 case TTCN_EncDec::CT_TEXT
: {
1172 Limit_Token_List limit
;
1173 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
1175 TTCN_EncDec_ErrorContext::error_internal
1176 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
1177 const unsigned char *b
=p_buf
.get_data();
1178 if(b
[p_buf
.get_len()-1]!='\0'){
1179 p_buf
.set_pos(p_buf
.get_len());
1180 p_buf
.put_zero(8,ORDER_LSB
);
1183 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
1184 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
1185 "Can not decode type '%s', because invalid or incomplete"
1186 " message was received"
1189 case TTCN_EncDec::CT_XER
: {
1190 unsigned XER_coding
=va_arg(pvar
, unsigned);
1191 XmlReaderWrap
reader(p_buf
);
1192 int success
= reader
.Read();
1193 for (; success
==1; success
=reader
.Read()) {
1194 int type
= reader
.NodeType();
1195 if (type
==XML_READER_TYPE_ELEMENT
)
1198 XER_decode(*p_td
.xer
, reader
, XER_coding
, XER_NONE
, 0);
1199 size_t bytes
= reader
.ByteConsumed();
1200 p_buf
.set_pos(bytes
);
1202 case TTCN_EncDec::CT_JSON
: {
1203 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
1205 TTCN_EncDec_ErrorContext::error_internal
1206 ("No JSON descriptor available for type '%s'.", p_td
.name
);
1207 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
1208 if(JSON_decode(p_td
, tok
, false)<0)
1209 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
1210 "Can not decode type '%s', because invalid or incomplete"
1211 " message was received"
1213 p_buf
.set_pos(tok
.get_buf_pos());
1216 TTCN_error("Unknown coding method requested to decode type '%s'",
1223 UNIVERSAL_CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
1224 unsigned p_coding
) const
1227 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1228 BER_chk_descr(p_td
);
1229 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
1232 switch(p_td
.asnbasetype
) {
1233 case TTCN_Typedescriptor_t::TELETEXSTRING
:
1234 buf
.put_os(TTCN_TeletexString_2_ISO2022(*this));
1236 case TTCN_Typedescriptor_t::VIDEOTEXSTRING
:
1237 buf
.put_os(TTCN_VideotexString_2_ISO2022(*this));
1239 case TTCN_Typedescriptor_t::GRAPHICSTRING
:
1240 buf
.put_os(TTCN_GraphicString_2_ISO2022(*this));
1242 case TTCN_Typedescriptor_t::GENERALSTRING
:
1243 buf
.put_os(TTCN_GeneralString_2_ISO2022(*this));
1245 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1246 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1247 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_group
);
1248 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_plane
);
1249 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_row
);
1250 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_cell
);
1253 case TTCN_Typedescriptor_t::BMPSTRING
:
1254 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1255 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_row
);
1256 buf
.put_c(val_ptr
->uchars_ptr
[i
].uc_cell
);
1259 case TTCN_Typedescriptor_t::UTF8STRING
:
1263 TTCN_EncDec_ErrorContext::error_internal
1264 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
1266 new_tlv
=BER_encode_TLV_OCTETSTRING
1267 (p_coding
, buf
.get_read_len(), buf
.get_read_data());
1269 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
1272 int UNIVERSAL_CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
1273 TTCN_Buffer
& buff
, Limit_Token_List
& limit
, boolean no_err
, boolean
/*first_call*/)
1275 int decoded_length
= 0;
1278 if (p_td
.text
->begin_decode
) {
1280 if ((tl
= p_td
.text
->begin_decode
->match_begin(buff
)) < 0) {
1281 if (no_err
) return -1;
1282 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1283 "The specified token '%s' not found for '%s': ",
1284 (const char*) *(p_td
.text
->begin_decode
), p_td
.name
);
1287 decoded_length
+= tl
;
1288 buff
.increase_pos(tl
);
1290 // never return "not enough bits"
1291 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
1293 if (p_td
.text
->select_token
) {
1295 if ((tl
= p_td
.text
->select_token
->match_begin(buff
)) < 0) {
1296 if (no_err
) return -1;
1301 // The length restriction needs some more work
1302 /* else if ( p_td.text->val.parameters
1303 && p_td.text->val.parameters->decoding_params.min_length != -1) {
1304 str_len = p_td.text->val.parameters->decoding_params.min_length;
1306 else if (p_td
.text
->end_decode
) {
1308 if ((tl
= p_td
.text
->end_decode
->match_first(buff
)) < 0) {
1309 if (no_err
) return -1;
1314 else if (limit
.has_token()) {
1316 if ((tl
= limit
.match(buff
)) < 0) tl
= buff
.get_read_len() - 1;
1320 str_len
= buff
.get_read_len() - 1;
1323 // only utf8 is supported now.
1324 decode_utf8(str_len
,buff
.get_read_data());
1326 decoded_length
+= str_len
;
1327 buff
.increase_pos(str_len
);
1329 // Case conversion is an another study
1330 // and it is locale dependent
1331 /* if ( p_td.text->val.parameters
1332 && p_td.text->val.parameters->decoding_params.convert != 0) {
1333 if (p_td.text->val.parameters->decoding_params.convert == 1) {
1334 for (int a = 0; a < str_len; a++) {
1335 val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
1339 for (int a = 0; a < str_len; a++) {
1340 val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
1344 if (p_td
.text
->end_decode
) {
1346 if ((tl
= p_td
.text
->end_decode
->match_begin(buff
)) < 0) {
1347 if (no_err
) return -1;
1348 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
1349 "The specified token '%s' not found for '%s': ",
1350 (const char*) *(p_td
.text
->end_decode
), p_td
.name
);
1353 decoded_length
+= tl
;
1354 buff
.increase_pos(tl
);
1356 return decoded_length
;
1359 int UNIVERSAL_CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1360 TTCN_Buffer
& buff
) const{
1361 int encoded_length
=0;
1362 if(p_td
.text
->begin_encode
){
1363 buff
.put_cs(*p_td
.text
->begin_encode
);
1364 encoded_length
+=p_td
.text
->begin_encode
->lengthof();
1367 TTCN_EncDec_ErrorContext::error
1368 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound value.");
1369 if(p_td
.text
->end_encode
){
1370 buff
.put_cs(*p_td
.text
->end_encode
);
1371 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1373 return encoded_length
;
1376 // The length restriction and case conversion will be added later
1377 // if(p_td.text->val.parameters==NULL){
1379 int base_size
=buff
.get_len(); // strore the current length of the data
1384 encoded_length
+=buff
.get_len()-base_size
; // calculate the number of the
1390 if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
1391 switch(p_td.text->val.parameters->coding_params.just){
1393 chars_after=p_td.text->
1394 val.parameters->coding_params.min_length-val_ptr->n_chars;
1398 val.parameters->coding_params.min_length-val_ptr->n_chars;
1400 chars_before=pad-chars_after;
1405 chars_before=p_td.text->
1406 val.parameters->coding_params.min_length-val_ptr->n_chars;
1411 unsigned char* p=NULL;
1412 size_t len=chars_before;
1413 buff.get_end(p,len);
1414 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
1415 buff.increase_length(chars_before);
1416 encoded_length+=chars_before;
1419 switch(p_td.text->val.parameters->coding_params.convert){
1420 case -1:{ //lower_case
1421 unsigned char* p=NULL;
1422 size_t len=val_ptr->n_chars;
1423 buff.get_end(p,len);
1424 for(int a=0;a<val_ptr->n_chars;a++)
1425 p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
1426 buff.increase_length(val_ptr->n_chars);
1429 case 0:{ // no conversion
1433 case 1: // upper_case
1436 unsigned char* p=NULL;
1437 size_t len=val_ptr->n_chars;
1438 buff.get_end(p,len);
1439 for(int a=0;a<val_ptr->n_chars;a++)
1440 p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
1441 buff.increase_length(val_ptr->n_chars);
1445 encoded_length+=val_ptr->n_chars;
1448 unsigned char* p=NULL;
1449 size_t len=chars_after;
1450 buff.get_end(p,len);
1451 for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
1452 buff.increase_length(chars_after);
1453 encoded_length+=chars_after;
1458 if(p_td
.text
->end_encode
){
1459 buff
.put_cs(*p_td
.text
->end_encode
);
1460 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1462 return encoded_length
;
1465 void UNIVERSAL_CHARSTRING::encode_utf8(TTCN_Buffer
& buf
, bool addBOM
/*= false*/) const
1474 buf
.put_s(cstr
.val_ptr
->n_chars
, (unsigned char*)cstr
.val_ptr
->chars_ptr
);
1475 // put_s avoids the check for boundness in put_cs
1478 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1479 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1480 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1481 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1482 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1483 if(g
==0x00 && p
<=0x1F) {
1485 if(r
==0x00 && c
<=0x7F) {
1491 buf
.put_c(0xC0|r
<<2|c
>>6);
1492 buf
.put_c(0x80|(c
&0x3F));
1496 buf
.put_c(0xE0|r
>>4);
1497 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1498 buf
.put_c(0x80|(c
&0x3F));
1503 buf
.put_c(0xF0|p
>>2);
1504 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1505 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1506 buf
.put_c(0x80|(c
&0x3F));
1512 buf
.put_c(0x80|p
>>2);
1513 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1514 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1515 buf
.put_c(0x80|(c
&0x3F));
1519 buf
.put_c(0xFC|g
>>6);
1520 buf
.put_c(0x80|(g
&0x3F));
1521 buf
.put_c(0x80|p
>>2);
1522 buf
.put_c(0x80|(p
<<4&0x30)|r
>>4);
1523 buf
.put_c(0x80|(r
<<2&0x3C)|c
>>6);
1524 buf
.put_c(0x80|(c
&0x3F));
1530 void UNIVERSAL_CHARSTRING::encode_utf16(TTCN_Buffer
& buf
,
1531 CharCoding::CharCodingType expected_coding
) const
1535 switch (expected_coding
) {
1536 case CharCoding::UTF16
:
1537 case CharCoding::UTF16BE
:
1540 case CharCoding::UTF16LE
:
1544 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1545 "Unexpected coding type for UTF-16 encoding");
1548 buf
.put_c(isbig
? 0xFE : 0xFF);
1549 buf
.put_c(isbig
? 0xFF : 0xFE);
1552 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
1553 buf
.put_c(isbig
? 0 : cstr
.val_ptr
->chars_ptr
[i
]);
1554 buf
.put_c(isbig
? cstr
.val_ptr
->chars_ptr
[i
] : 0);
1558 for(int i
=0; i
<val_ptr
->n_uchars
; i
++) {
1559 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1560 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1561 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1562 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1563 if (g
|| (0x10 < p
)) {
1564 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1565 "Any UCS code (0x%02X%02X%02X%02X) to be encoded into UTF-16 "
1566 "shall not be greater than 0x10FFFF", g
, p
, r
, c
);
1568 else if (0x00 == g
&& 0x00 ==p
&& 0xD8 <= r
&& 0xDF >= r
) {
1569 // Values between 0xD800 and 0xDFFF are specifically reserved for use with UTF-16,
1570 // and don't have any characters assigned to them.
1571 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1572 "Any UCS code (0x%02X%02X) between 0xD800 and 0xDFFF is ill-formed", r
,c
);
1574 else if (0x00 == g
&& 0x00 == p
) {
1575 buf
.put_c(isbig
? r
: c
);
1576 buf
.put_c(isbig
? c
: r
);
1578 else if (g
|| p
) { // greater than 0xFFFF it needs surrogates
1579 uint32_t univc
= 0, temp
= 0;
1589 univc
|= c
; // universal char filled in univc
1590 uint16_t W1
= 0xD800;
1591 uint16_t W2
= 0xDC00;
1592 uint32_t univcmod
= univc
- 0x10000;
1593 uint16_t WH
= univcmod
>> 10;
1594 uint16_t WL
= univcmod
& 0x3ff;
1598 uc
= isbig
? W1
>> 8 : W1
;
1600 uc
= isbig
? W1
: W1
>> 8;
1602 uc
= isbig
? W2
>> 8 : W2
;
1604 uc
= isbig
? W2
: W2
>> 8;
1611 void UNIVERSAL_CHARSTRING::encode_utf32(TTCN_Buffer
& buf
,
1612 CharCoding::CharCodingType expected_coding
) const
1615 switch (expected_coding
) {
1616 case CharCoding::UTF32
:
1617 case CharCoding::UTF32BE
:
1620 case CharCoding::UTF32LE
:
1624 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1625 "Unexpected coding type for UTF-32 encoding");
1629 buf
.put_c(isbig
? 0x00 : 0xFF);
1630 buf
.put_c(isbig
? 0x00 : 0xFE);
1631 buf
.put_c(isbig
? 0xFE : 0x00);
1632 buf
.put_c(isbig
? 0xFF : 0x00);
1635 for (int i
= 0; i
< cstr
.val_ptr
->n_chars
; ++i
) {
1636 buf
.put_c(isbig
? 0 : cstr
.val_ptr
->chars_ptr
[i
]);
1639 buf
.put_c(isbig
? cstr
.val_ptr
->chars_ptr
[i
] : 0);
1643 for(int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1644 unsigned char g
=val_ptr
->uchars_ptr
[i
].uc_group
;
1645 unsigned char p
=val_ptr
->uchars_ptr
[i
].uc_plane
;
1646 unsigned char r
=val_ptr
->uchars_ptr
[i
].uc_row
;
1647 unsigned char c
=val_ptr
->uchars_ptr
[i
].uc_cell
;
1648 uint32_t DW
= g
<< 8 | p
;
1653 if (0x0000D800 <= DW
&& 0x0000DFFF >= DW
) {
1654 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1655 "Any UCS code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW
);
1657 else if (0x0010FFFF < DW
) {
1658 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
1659 "Any UCS code (0x%08X) greater than 0x0010FFFF is ill-formed", DW
);
1662 buf
.put_c(isbig
? g
: c
);
1663 buf
.put_c(isbig
? p
: r
);
1664 buf
.put_c(isbig
? r
: p
);
1665 buf
.put_c(isbig
? c
: g
);
1671 #ifdef TITAN_RUNTIME_2
1673 int UNIVERSAL_CHARSTRING::encode_raw(TTCN_Buffer
& p_buf
) const
1675 size_t len_before
= p_buf
.get_len();
1677 return p_buf
.get_len() - len_before
;
1680 int UNIVERSAL_CHARSTRING::JSON_encode_negtest_raw(JSON_Tokenizer
& p_tok
) const
1682 TTCN_Buffer tmp_buf
;
1683 encode_utf8(tmp_buf
);
1684 p_tok
.put_raw_data((const char*)tmp_buf
.get_data(), tmp_buf
.get_len());
1685 return tmp_buf
.get_len();
1690 boolean
UNIVERSAL_CHARSTRING::BER_decode_TLV
1691 (const TTCN_Typedescriptor_t
& p_td
, const ASN_BER_TLV_t
& p_tlv
,
1696 TTCN_EncDec_ErrorContext
ec("While decoding universal charstring type: ");
1698 if(!ostr
.BER_decode_TLV(p_td
, p_tlv
, L_form
)) return FALSE
;
1699 int os_len
=ostr
.lengthof();
1701 const unsigned char* os
=ostr
;
1702 switch(p_td
.asnbasetype
) {
1703 case TTCN_Typedescriptor_t::TELETEXSTRING
:
1704 *this=TTCN_ISO2022_2_TeletexString(ostr
);
1706 case TTCN_Typedescriptor_t::VIDEOTEXSTRING
:
1707 *this=TTCN_ISO2022_2_VideotexString(ostr
);
1709 case TTCN_Typedescriptor_t::GRAPHICSTRING
:
1710 *this=TTCN_ISO2022_2_GraphicString(ostr
);
1712 case TTCN_Typedescriptor_t::GENERALSTRING
:
1713 *this=TTCN_ISO2022_2_GeneralString(ostr
);
1715 case TTCN_Typedescriptor_t::UNIVERSALSTRING
:
1717 TTCN_EncDec_ErrorContext::error
1718 (TTCN_EncDec::ET_DEC_UCSTR
, "Length of UCS-4-coded character"
1719 " string is not multiple of 4.");
1721 init_struct(ucs_len
);
1722 for(int i
=0; i
<ucs_len
; i
++) {
1723 val_ptr
->uchars_ptr
[i
].uc_group
=os
[0];
1724 val_ptr
->uchars_ptr
[i
].uc_plane
=os
[1];
1725 val_ptr
->uchars_ptr
[i
].uc_row
=os
[2];
1726 val_ptr
->uchars_ptr
[i
].uc_cell
=os
[3];
1730 case TTCN_Typedescriptor_t::BMPSTRING
:
1732 TTCN_EncDec_ErrorContext::error
1733 (TTCN_EncDec::ET_DEC_UCSTR
, "Length of UCS-2-coded character"
1734 " string is not multiple of 2.");
1736 init_struct(ucs_len
);
1737 for(int i
=0; i
<ucs_len
; i
++) {
1738 val_ptr
->uchars_ptr
[i
].uc_group
=0;
1739 val_ptr
->uchars_ptr
[i
].uc_plane
=0;
1740 val_ptr
->uchars_ptr
[i
].uc_row
=os
[0];
1741 val_ptr
->uchars_ptr
[i
].uc_cell
=os
[1];
1745 case TTCN_Typedescriptor_t::UTF8STRING
:
1746 decode_utf8(os_len
, os
);
1749 TTCN_EncDec_ErrorContext::error_internal
1750 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
1755 extern void xml_escape(const unsigned int c
, TTCN_Buffer
& p_buf
);
1757 int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t
& p_td
,
1758 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
1761 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1762 "Encoding an unbound UNIVERSAL CHARSTRING value.");
1765 const_cast<UNIVERSAL_CHARSTRING
&>(*this).convert_cstr_to_uni();
1766 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
1767 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1768 int encoded_length
=(int)p_buf
.get_len();
1769 bool do_empty_element
= val_ptr
==NULL
|| val_ptr
->n_uchars
== 0;
1771 flavor
&= ~XER_RECOF
; // universal charstring doesn't care
1772 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) {
1773 if (!is_canonical(flavor
)) {
1774 // Although ANY_ELEMENT is not canonical, this flag is still used to disable
1775 // indenting in a record/set with EMBED_VALUES
1776 do_indent(p_buf
, indent
);
1780 if (do_empty_element
&& exer
&& p_td
.dfeValue
!= 0) {
1781 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR
,
1782 "An encoded value with DEFAULT-FOR-EMPTY instruction "
1783 "applied should not be empty");
1785 if (begin_xml(p_td
, p_buf
, flavor
, indent
, do_empty_element
) == -1) {
1788 } // not any_element
1790 #define UCH(c) {0,0,0,c}
1791 if (!do_empty_element
) {
1792 if (flavor
& XER_ESCAPE_ENTITIES
) {
1793 for (int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1794 unsigned int ucs4
= unichar2int(val_ptr
->uchars_ptr
[i
]);
1795 xml_escape( ucs4
, p_buf
);
1798 else { // UTF-8 needs only to escape the low 32 and these five: <&>
1799 TTCN_Buffer other_buf
;
1800 static const universal_char amp
[] = { UCH('&'), UCH('a'), UCH('m'),
1801 UCH('p'), UCH(';') };
1802 static const universal_char lt
[] = { UCH('&'), UCH('l'), UCH('t'),
1804 static const universal_char gt
[] = { UCH('&'), UCH('g'), UCH('t'),
1806 static const universal_char apos
[]= { UCH('&'), UCH('a'), UCH('p'),
1807 UCH('o'), UCH('s'), UCH(';') };
1808 static const universal_char quot
[]= { UCH('&'), UCH('q'), UCH('u'),
1809 UCH('o'), UCH('t'), UCH(';') };
1811 static const universal_char escapes
[32][6] = {
1812 {UCH('<'), UCH('n'), UCH('u'), UCH('l'), UCH('/'), UCH('>')},
1813 {UCH('<'), UCH('s'), UCH('o'), UCH('h'), UCH('/'), UCH('>')},
1814 {UCH('<'), UCH('s'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1815 {UCH('<'), UCH('e'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1816 {UCH('<'), UCH('e'), UCH('o'), UCH('t'), UCH('/'), UCH('>')},
1817 {UCH('<'), UCH('e'), UCH('n'), UCH('q'), UCH('/'), UCH('>')},
1818 {UCH('<'), UCH('a'), UCH('c'), UCH('k'), UCH('/'), UCH('>')},
1819 {UCH('<'), UCH('b'), UCH('e'), UCH('l'), UCH('/'), UCH('>')},
1821 {UCH('<'), UCH('b'), UCH('s'), UCH('/'), UCH('>')},
1822 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('9'), UCH(';')}, // TAB
1823 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('A'), UCH(';')}, // LF
1824 {UCH('<'), UCH('v'), UCH('t'), UCH('/'), UCH('>')},
1825 {UCH('<'), UCH('f'), UCH('f'), UCH('/'), UCH('>')},
1826 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('D'), UCH(';')}, // CR
1827 {UCH('<'), UCH('s'), UCH('o'), UCH('/'), UCH('>')},
1828 {UCH('<'), UCH('s'), UCH('i'), UCH('/'), UCH('>')},
1830 {UCH('<'), UCH('d'), UCH('l'), UCH('e'), UCH('/'), UCH('>')},
1831 {UCH('<'), UCH('d'), UCH('c'), UCH('1'), UCH('/'), UCH('>')},
1832 {UCH('<'), UCH('d'), UCH('c'), UCH('2'), UCH('/'), UCH('>')},
1833 {UCH('<'), UCH('d'), UCH('c'), UCH('3'), UCH('/'), UCH('>')},
1834 {UCH('<'), UCH('d'), UCH('c'), UCH('4'), UCH('/'), UCH('>')},
1835 {UCH('<'), UCH('n'), UCH('a'), UCH('k'), UCH('/'), UCH('>')},
1836 {UCH('<'), UCH('s'), UCH('y'), UCH('n'), UCH('/'), UCH('>')},
1837 {UCH('<'), UCH('e'), UCH('t'), UCH('b'), UCH('/'), UCH('>')},
1839 {UCH('<'), UCH('c'), UCH('a'), UCH('n'), UCH('/'), UCH('>')},
1840 {UCH('<'), UCH('e'), UCH('m'), UCH('/'), UCH('>')},
1841 {UCH('<'), UCH('s'), UCH('u'), UCH('b'), UCH('/'), UCH('>')},
1842 {UCH('<'), UCH('e'), UCH('s'), UCH('c'), UCH('/'), UCH('>')},
1843 {UCH('<'), UCH('i'), UCH('s'), UCH('4'), UCH('/'), UCH('>')},
1844 {UCH('<'), UCH('i'), UCH('s'), UCH('3'), UCH('/'), UCH('>')},
1845 {UCH('<'), UCH('i'), UCH('s'), UCH('2'), UCH('/'), UCH('>')},
1846 {UCH('<'), UCH('i'), UCH('s'), UCH('1'), UCH('/'), UCH('>')}
1849 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) { // no escaping
1850 TTCN_EncDec_ErrorContext
ec("While checking anyElement: ");
1851 encode_utf8(other_buf
);
1852 XmlReaderWrap
checker(other_buf
);
1853 // Walk through the XML. If it's not well-formed, XmlReaderWrap
1854 // will call TTCN_error => Dynamic testcase error.
1855 while (1 == checker
.Read()) {
1856 if (checker
.NodeType() == XML_READER_TYPE_ELEMENT
&&
1857 (p_td
.xer_bits
& (ANY_FROM
| ANY_EXCEPT
))) {
1858 const char* xmlns
= (const char*)checker
.NamespaceUri();
1859 check_namespace_restrictions(p_td
, xmlns
);
1863 // other_buf is already UTF-8, just append it
1864 p_buf
.put_buf(other_buf
);
1866 else if (flavor
& ANY_ATTRIBUTES
) { // no escaping
1867 encode_utf8(other_buf
);
1868 p_buf
.put_buf(other_buf
);
1871 for (int i
= 0; i
< val_ptr
->n_uchars
; ++i
) {
1872 int char_val
= unichar2int(val_ptr
->uchars_ptr
[i
]);
1873 size_t len
= 6; // 3 letters + the surrounding '<', '/' and '>'
1876 other_buf
.put_s(20, &(amp
[0].uc_group
));
1880 other_buf
.put_s(16, &(lt
[0].uc_group
));
1884 other_buf
.put_s(16, &(gt
[0].uc_group
));
1887 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1888 // so if they appear in content they must be escaped.
1889 // Currently this happens even if the string is not an attribute.
1890 other_buf
.put_s(24, &(apos
[0].uc_group
));
1893 case '\"': // HR58225
1894 other_buf
.put_s(24, &(quot
[0].uc_group
));
1897 case 8: case 11: case 12: case 14: case 15: case 25:
1898 // the name of these control characters has only two letters
1901 case 0: case 1: case 2: case 3: case 4: case 5: case 6:
1902 case 7: case 16: case 17: case 18: case 19: case 20: case 21:
1903 case 22: case 23: case 24: case 26: case 27: case 28: case 29:
1905 other_buf
.put_s(len
* 4, &(escapes
[char_val
][0].uc_group
));
1908 case 9: case 10: case 13:
1909 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1910 // X.693 20.3.15: TAB,LF,CR also needs to be escaped in ATTRIBUTE
1911 other_buf
.put_s(24, &(escapes
[char_val
][0].uc_group
));
1913 } // else fall through
1916 other_buf
.put_s(4, &(val_ptr
->uchars_ptr
[i
].uc_group
));
1920 // other_buf contains UCS-4, need to encode it
1921 UNIVERSAL_CHARSTRING cs
;
1922 other_buf
.get_string(cs
);
1923 (cs
).encode_utf8(p_buf
);
1924 } // not any_element
1925 } // if ESCAPE_ENTITIES
1927 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
) && !is_canonical(flavor
)) {
1932 end_xml(p_td
, p_buf
, flavor
, indent
, do_empty_element
);
1934 return (int)p_buf
.get_len() - encoded_length
;
1937 /* Hashing for xmlcstring representation of control characters.
1938 * This function was generated by gperf 3.0.3
1939 * (GNU perfect hash function generator) from the list of control character
1940 * names, one per line, like this:
1947 * See the ASN.1 standard, X.680/2002, clause 11.15.5
1951 hash (register const char *str
, register unsigned int len
)
1953 static unsigned char asso_values
[] =
1955 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1956 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1957 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1958 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1959 104, 104, 104, 104, 104, 104, 104, 104, 104, 1,
1960 60, 55, 45, 104, 104, 104, 104, 104, 104, 104,
1961 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1962 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1963 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1964 104, 104, 104, 104, 104, 104, 104, 10, 10, 50,
1965 40, 15, 0, 104, 6, 15, 104, 1, 5, 10,
1966 0, 20, 104, 15, 0, 0, 30, 104, 0, 104,
1967 20, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1968 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1969 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1970 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1971 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1972 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1973 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1974 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1975 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1976 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1977 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1978 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1979 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1980 104, 104, 104, 104, 104, 104
1982 return len
+ asso_values
[(unsigned char)str
[len
- 1]] +
1983 asso_values
[(unsigned char)str
[0]];
1986 /* This function was also generated by gperf and hand-edited afterwards.
1987 * The original wordlist[] was an array of strings containing the names of
1988 * the control characters, with empty strings as fillers. These have been
1989 * replaced with the actual numerical values of the control characters,
1990 * with -1 as the filler.
1994 in_word_set (const char *str
, unsigned int len
)
1996 static char wordlist
[] =
2043 -1, -1, -1, -1, -1, -1, -1, -1, -1,
2045 -1, -1, -1, -1, -1, -1, -1, -1, -1,
2050 #define MIN_WORD_LENGTH 2
2051 #define MAX_WORD_LENGTH 3
2052 #define MIN_HASH_VALUE 2
2053 #define MAX_HASH_VALUE 103
2055 if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
2057 register int key
= hash (str
, len
);
2059 if (key
<= MAX_HASH_VALUE
&& key
>= 0)
2061 register const char s
= wordlist
[key
];
2068 universal_char
const uspace
= {0,0,0,32};
2070 int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t
& p_td
,
2071 XmlReaderWrap
& reader
, unsigned int flavor
, unsigned int /*flavor2*/, embed_values_dec_struct_t
*)
2073 int exer
= is_exer(flavor
);
2074 int success
= reader
.Ok(), depth
= -1;
2075 bool omit_tag
= exer
2076 && ((p_td
.xer_bits
& UNTAGGED
)
2077 || (flavor
& (EMBED_VALUES
|XER_LIST
|USE_TYPE_ATTR
|ANY_ATTRIBUTES
|USE_NIL
)));
2079 if (exer
&& (p_td
.xer_bits
& ANY_ELEMENT
)) {
2080 TTCN_EncDec_ErrorContext
ec("While checking anyElement: ");
2081 for (; success
== 1; success
= reader
.Read()) {
2082 int type
= reader
.NodeType();
2083 if (-1 == depth
&& XML_READER_TYPE_ELEMENT
== type
) {
2084 xmlChar
* value
= reader
.ReadOuterXml();
2085 size_t num_chars
= strlen((const char*)value
);
2088 decode_utf8(num_chars
, value
); // does init_struct
2091 if (p_td
.xer_bits
& (ANY_FROM
| ANY_EXCEPT
)) {
2092 const char* xmlns
= (const char*)reader
.NamespaceUri();
2093 check_namespace_restrictions(p_td
, xmlns
);
2096 if (reader
.IsEmptyElement()) {
2097 reader
.Read(); // skip past the empty element and we're done
2100 depth
= reader
.Depth(); // signals that we have the element's text
2101 // Stay in the loop until we reach the corresponding end tag
2103 else if (reader
.Depth() == depth
&& XML_READER_TYPE_END_ELEMENT
== type
) {
2104 reader
.Read(); // one last time
2108 // ANY-ELEMENT and WHITESPACE are mutually exclusive,
2109 // so this branch skips WHITESPACE processing
2111 else { // not ANY-ELEMENT
2112 clean_up(); // start with a clean slate
2114 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
2115 // we have it easy (but does decode_utf8 handle &nnn; ?)
2116 const char * name
= verify_name(reader
, p_td
, exer
);
2118 const char * value
= (const char *)reader
.Value();
2119 int len
= strlen(value
);
2120 decode_utf8(len
, (cbyte
*)value
);
2122 // Let the caller do reader.AdvanceAttribute();
2124 else { // not an attribute either
2125 // Get to the start of data.
2126 if (!omit_tag
) for (; success
== 1; success
= reader
.Read()) {
2127 int type
= reader
.NodeType();
2128 if (XML_READER_TYPE_ELEMENT
== type
) {
2129 verify_name(reader
, p_td
, exer
);
2130 if (reader
.IsEmptyElement()) {
2131 if (exer
&& p_td
.dfeValue
!= 0) {
2132 *this = *static_cast<const UNIVERSAL_CHARSTRING
*>(p_td
.dfeValue
);
2134 else init_struct(0); // it's an empty string
2135 reader
.Read(); // move on
2138 depth
= reader
.Depth();
2139 success
= reader
.Read();
2142 else if (XML_READER_TYPE_TEXT
== type
&& omit_tag
)
2144 else // if XML_READER_TYPE_END_ELEMENT, panic?
2149 TTCN_Buffer accumulator
;
2150 if (flavor
& PARENT_CLOSED
) {} // do nothing
2151 else for (; success
==1; success
= reader
.Read()) {
2152 int type
= reader
.NodeType();
2154 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE
:
2155 case XML_READER_TYPE_TEXT
:
2156 case XML_READER_TYPE_CDATA
: {
2157 const char * text
= (const char*)reader
.Value();
2158 int len
= strlen(text
);
2159 accumulator
.put_s(len
, (cbyte
*)text
);
2162 case XML_READER_TYPE_ELEMENT
: { // escaped control character
2163 const char * name
= (const char*)reader
.LocalName();
2164 size_t len
= strlen(name
);
2165 char ctrl
= in_word_set(name
, len
);
2167 accumulator
.put_c(ctrl
);
2170 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2171 "Invalid escape sequence '<%s/>'", name
);
2175 case XML_READER_TYPE_END_ELEMENT
: {
2176 decode_utf8(accumulator
.get_len(), accumulator
.get_data());
2178 verify_end(reader
, p_td
, depth
, exer
);
2179 reader
.Read(); // Moved to a different XML node!
2180 if (val_ptr
->n_uchars
== 0 && exer
&& p_td
.dfeValue
!= 0) {
2181 // This should be the <foo></foo> case. Treat it like <foo/>
2182 *this = *static_cast<const UNIVERSAL_CHARSTRING
*>(p_td
.dfeValue
);
2185 goto fini
; } // double "break" of switch and for loop
2191 } // endif (attribute)
2193 if (exer
&& p_td
.whitespace
>= WHITESPACE_REPLACE
) { // includes _COLLAPSE
2194 for(int i
=0; i
<val_ptr
->n_uchars
; ++i
) { // first, _REPLACE
2195 switch ( unichar2int(val_ptr
->uchars_ptr
[i
]) ) {
2196 case 9: // HORIZONTAL TAB
2197 case 10: // LINE FEED
2198 case 13: // CARRIAGE RETURN
2199 val_ptr
->uchars_ptr
[i
] = uspace
;
2206 if (p_td
.whitespace
>= WHITESPACE_COLLAPSE
) {
2208 const universal_char
*from
, *end
=
2209 val_ptr
->uchars_ptr
+ val_ptr
->n_uchars
;
2210 for (from
= to
= val_ptr
->uchars_ptr
; from
< end
;) {
2212 // If the copied character (*to) was a space,
2213 // and the next character to be copied (*from) is also a space
2214 // (continuous run of spaces)
2215 // or this was the first character (leading spaces to be trimmed),
2216 // then don't advance the destination (will be overwritten).
2218 || (from
< end
&& *from
!= uspace
&& to
> val_ptr
->uchars_ptr
))
2221 val_ptr
->n_uchars
= to
- val_ptr
->uchars_ptr
;
2224 } // not ANY_ELEMENT
2225 return 1; // decode successful
2228 char* UNIVERSAL_CHARSTRING::to_JSON_string(const TTCN_Buffer
& p_buf
) const
2230 const unsigned char* ustr
= p_buf
.get_data();
2231 const size_t ustr_len
= p_buf
.get_len();
2233 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
2234 char* json_str
= (char*)Malloc(ustr_len
+ 3);
2237 json_str
= mputc(json_str
, '\"');
2239 for (size_t i
= 0; i
< ustr_len
; ++i
) {
2240 // Increase the size of the buffer if it's not big enough to store the
2241 // characters remaining in the universal charstring
2244 json_str
= mputstrn(json_str
, "\\\\", 2);
2247 json_str
= mputstrn(json_str
, "\\n", 2);
2250 json_str
= mputstrn(json_str
, "\\t", 2);
2253 json_str
= mputstrn(json_str
, "\\r", 2);
2256 json_str
= mputstrn(json_str
, "\\f", 2);
2259 json_str
= mputstrn(json_str
, "\\b", 2);
2262 json_str
= mputstrn(json_str
, "\\\"", 2);
2265 json_str
= mputc(json_str
, (char)ustr
[i
]);
2270 json_str
= mputc(json_str
, '\"');
2274 int UNIVERSAL_CHARSTRING::RAW_encode(const TTCN_Typedescriptor_t
& p_td
,
2275 RAW_enc_tree
& myleaf
) const
2278 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
2279 "Encoding an unbound value.");
2282 return cstr
.RAW_encode(p_td
, myleaf
);
2286 int buff_len
= buff
.get_len();
2287 int bl
= buff_len
* 8; // bit length
2288 int align_length
= p_td
.raw
->fieldlength
? p_td
.raw
->fieldlength
- bl
: 0;
2289 if (align_length
< 0) {
2290 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
2291 "There are insufficient bits to encode '%s': ", p_td
.name
);
2292 bl
= p_td
.raw
->fieldlength
;
2295 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
2296 myleaf
.body
.leaf
.data_ptr
= (unsigned char*)Malloc(buff_len
);
2297 memcpy(myleaf
.body
.leaf
.data_ptr
, buff
.get_data(), buff_len
);
2298 myleaf
.must_free
= TRUE
;
2299 myleaf
.data_ptr_used
= TRUE
;
2300 if (p_td
.raw
->endianness
== ORDER_MSB
) myleaf
.align
= -align_length
;
2301 else myleaf
.align
= align_length
;
2302 return myleaf
.length
= bl
+ align_length
;
2305 int UNIVERSAL_CHARSTRING::RAW_decode(const TTCN_Typedescriptor_t
& p_td
,
2306 TTCN_Buffer
& buff
, int limit
, raw_order_t top_bit_ord
, boolean no_err
,
2307 int /*sel_field*/, boolean
/*first_call*/)
2309 CHARSTRING buff_str
;
2310 int dec_len
= buff_str
.RAW_decode(p_td
, buff
, limit
, top_bit_ord
, no_err
);
2311 if (buff_str
.is_bound()) {
2313 for (int i
= 0; i
< buff_str
.val_ptr
->n_chars
; ++i
) {
2314 if (buff_str
.val_ptr
->chars_ptr
[i
] < 0) {
2323 decode_utf8(buff_str
.val_ptr
->n_chars
, (const unsigned char*)buff_str
.val_ptr
->chars_ptr
);
2329 boolean
UNIVERSAL_CHARSTRING::from_JSON_string(boolean check_quotes
)
2331 int json_len
= val_ptr
->n_uchars
;
2332 universal_char
* json_str
= val_ptr
->uchars_ptr
;
2339 if (!json_str
[0].is_char() || json_str
[0].uc_cell
!= '\"' ||
2340 !json_str
[json_len
- 1].is_char() || json_str
[json_len
- 1].uc_cell
!= '\"') {
2345 // The resulting string will be shorter than the JSON string, at least by the 2 quotes
2346 universal_char
* ustr
= (universal_char
*)Malloc((json_len
- 2) * sizeof(universal_char
));
2347 memset(ustr
, 0, sizeof(universal_char
) * (json_len
- 2));
2349 boolean error
= false;
2351 for (int i
= start
; i
< end
; ++i
) {
2352 if (json_str
[i
].is_char() && '\\' == json_str
[i
].uc_cell
) {
2353 if (i
== end
- 1 || !json_str
[i
+ 1].is_char()) {
2357 switch(json_str
[i
+ 1].uc_cell
) {
2359 ustr
[ustr_len
++].uc_cell
= '\n';
2362 ustr
[ustr_len
++].uc_cell
= '\t';
2365 ustr
[ustr_len
++].uc_cell
= '\r';
2368 ustr
[ustr_len
++].uc_cell
= '\f';
2371 ustr
[ustr_len
++].uc_cell
= '\b';
2374 ustr
[ustr_len
++].uc_cell
= '\\';
2377 ustr
[ustr_len
++].uc_cell
= '\"';
2380 ustr
[ustr_len
++].uc_cell
= '/';
2383 if (end
- i
>= 6 && json_str
[i
+ 2].is_char() && json_str
[i
+ 3].is_char() &&
2384 json_str
[i
+ 4].is_char() && json_str
[i
+ 5].is_char()) {
2385 unsigned char row_upper_nibble
= char_to_hexdigit(json_str
[i
+ 2].uc_cell
);
2386 unsigned char row_lower_nibble
= char_to_hexdigit(json_str
[i
+ 3].uc_cell
);
2387 unsigned char cell_upper_nibble
= char_to_hexdigit(json_str
[i
+ 4].uc_cell
);
2388 unsigned char cell_lower_nibble
= char_to_hexdigit(json_str
[i
+ 5].uc_cell
);
2389 if (row_upper_nibble
<= 0x0F && row_lower_nibble
<= 0x0F &&
2390 cell_upper_nibble
<= 0x0F && cell_lower_nibble
<= 0x0F) {
2391 ustr
[ustr_len
].uc_row
= (row_upper_nibble
<< 4) | row_lower_nibble
;
2392 ustr
[ustr_len
++].uc_cell
= (cell_upper_nibble
<< 4) | cell_lower_nibble
;
2393 // skip 4 extra characters (the 4 hex digits)
2396 // error (encountered something other than a hex digit) -> leave the for cycle
2401 // error (not enough characters or the 'hex digits' are not even ascii characters) -> leave the for cycle
2408 // error (invalid escaped character) -> leave the for cycle
2413 // skip an extra character (the \)
2416 ustr
[ustr_len
++] = json_str
[i
];
2419 if (check_quotes
&& i
== json_len
- 1) {
2420 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
2427 init_struct(ustr_len
);
2428 memcpy(val_ptr
->uchars_ptr
, ustr
, ustr_len
* sizeof(universal_char
));
2434 int UNIVERSAL_CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
) const
2437 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
2438 "Encoding an unbound universal charstring value.");
2444 tmp_str
= cstr
.to_JSON_string();
2446 TTCN_Buffer tmp_buf
;
2447 encode_utf8(tmp_buf
);
2448 tmp_str
= to_JSON_string(tmp_buf
);
2450 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
2455 int UNIVERSAL_CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
2457 json_token_t token
= JSON_TOKEN_NONE
;
2459 size_t value_len
= 0;
2461 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
2463 // No JSON data in the buffer -> use default value
2464 value
= (char*)p_td
.json
->default_value
;
2465 value_len
= strlen(value
);
2467 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
2469 if (JSON_TOKEN_ERROR
== token
) {
2470 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
2471 return JSON_ERROR_FATAL
;
2473 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
2474 if (cstr
.from_JSON_string(value
, value_len
, !use_default
)) {
2479 decode_utf8(value_len
, (unsigned char*)value
);
2480 if (!from_JSON_string(!use_default
)) {
2481 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "universal charstring");
2485 return JSON_ERROR_FATAL
;
2489 return JSON_ERROR_INVALID_TOKEN
;
2495 static void fill_continuing_octets(int n_continuing
,
2496 unsigned char *continuing_ptr
, int n_octets
,
2497 const unsigned char *octets_ptr
, int start_pos
, int uchar_pos
)
2499 for (int i
= 0; i
< n_continuing
; i
++) {
2500 if (start_pos
+ i
< n_octets
) {
2501 unsigned char octet
= octets_ptr
[start_pos
+ i
];
2502 if ((octet
& 0xC0) != 0x80) {
2503 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2504 "Malformed: At character position %d, octet position %d: %02X is "
2505 "not a valid continuing octet.", uchar_pos
, start_pos
+ i
, octet
);
2507 continuing_ptr
[i
] = octet
& 0x3F;
2509 if (start_pos
+ i
== n_octets
) {
2511 // only a part of octets is missing
2512 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2513 "Incomplete: At character position %d, octet position %d: %d out "
2514 "of %d continuing octets %s missing from the end of the stream.",
2515 uchar_pos
, start_pos
+ i
, n_continuing
- i
, n_continuing
,
2516 n_continuing
- i
> 1 ? "are" : "is");
2518 // all octets are missing
2519 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2520 "Incomplete: At character position %d, octet position %d: %d "
2521 "continuing octet%s missing from the end of the stream.", uchar_pos
,
2522 start_pos
, n_continuing
, n_continuing
> 1 ? "s are" : " is");
2525 continuing_ptr
[i
] = 0;
2530 void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets
,
2531 const unsigned char *octets_ptr
,
2532 CharCoding::CharCodingType expected_coding
/*= UTF8*/,
2533 bool checkBOM
/*= false)*/)
2535 // approximate the number of characters
2537 for (int i
= 0; i
< n_octets
; i
++) {
2538 // count all octets except the continuing octets (10xxxxxx)
2539 if ((octets_ptr
[i
] & 0xC0) != 0x80) n_uchars
++;
2541 // allocate enough memory, start from clean state
2544 init_struct(n_uchars
);
2547 int start
= checkBOM
? check_BOM(CharCoding::UTF_8
, sizeof(octets_ptr
), octets_ptr
) : 0;
2548 for (int i
= start
; i
< n_octets
; ) {
2549 // perform the decoding character by character
2550 if (octets_ptr
[i
] <= 0x7F) {
2551 // character encoded on a single octet: 0xxxxxxx (7 useful bits)
2552 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2553 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2554 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= 0;
2555 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[i
];
2558 } else if (octets_ptr
[i
] <= 0xBF) {
2559 // continuing octet (10xxxxxx) without leading octet ==> malformed
2560 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2561 "Malformed: At character position %d, octet position %d: continuing "
2562 "octet %02X without leading octet.", n_uchars
, i
, octets_ptr
[i
]);
2564 } else if (octets_ptr
[i
] <= 0xDF) {
2565 // character encoded on 2 octets: 110xxxxx 10xxxxxx (11 useful bits)
2566 unsigned char octets
[2];
2567 octets
[0] = octets_ptr
[i
] & 0x1F;
2568 fill_continuing_octets(1, octets
+ 1, n_octets
, octets_ptr
, i
+ 1, n_uchars
);
2569 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2570 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2571 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[0] >> 2;
2572 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[0] << 6 | octets
[1];
2573 if (val_ptr
->uchars_ptr
[n_uchars
].uc_row
== 0x00 &&
2574 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
< 0x80)
2575 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2576 "Overlong: At character position %d, octet position %d: 2-octet "
2577 "encoding for quadruple (0, 0, 0, %u).", n_uchars
, i
,
2578 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2581 } else if (octets_ptr
[i
] <= 0xEF) {
2582 // character encoded on 3 octets: 1110xxxx 10xxxxxx 10xxxxxx
2584 unsigned char octets
[3];
2585 octets
[0] = octets_ptr
[i
] & 0x0F;
2586 fill_continuing_octets(2, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2588 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2589 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2590 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[0] << 4 | octets
[1] >> 2;
2591 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[1] << 6 | octets
[2];
2592 if (val_ptr
->uchars_ptr
[n_uchars
].uc_row
< 0x08)
2593 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2594 "Overlong: At character position %d, octet position %d: 3-octet "
2595 "encoding for quadruple (0, 0, %u, %u).", n_uchars
, i
,
2596 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2597 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2600 } else if (octets_ptr
[i
] <= 0xF7) {
2601 // character encoded on 4 octets: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2603 unsigned char octets
[4];
2604 octets
[0] = octets_ptr
[i
] & 0x07;
2605 fill_continuing_octets(3, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2607 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2608 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[0] << 2 | octets
[1] >> 4;
2609 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[1] << 4 | octets
[2] >> 2;
2610 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[2] << 6 | octets
[3];
2611 if (val_ptr
->uchars_ptr
[n_uchars
].uc_plane
== 0x00)
2612 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2613 "Overlong: At character position %d, octet position %d: 4-octet "
2614 "encoding for quadruple (0, 0, %u, %u).", n_uchars
, i
,
2615 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2616 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2619 } else if (octets_ptr
[i
] <= 0xFB) {
2620 // character encoded on 5 octets: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
2621 // 10xxxxxx (26 useful bits)
2622 unsigned char octets
[5];
2623 octets
[0] = octets_ptr
[i
] & 0x03;
2624 fill_continuing_octets(4, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2626 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets
[0];
2627 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[1] << 2 | octets
[2] >> 4;
2628 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[2] << 4 | octets
[3] >> 2;
2629 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[3] << 6 | octets
[4];
2630 if (val_ptr
->uchars_ptr
[n_uchars
].uc_group
== 0x00 &&
2631 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
< 0x20)
2632 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2633 "Overlong: At character position %d, octet position %d: 5-octet "
2634 "encoding for quadruple (0, %u, %u, %u).", n_uchars
, i
,
2635 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
,
2636 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2637 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2640 } else if (octets_ptr
[i
] <= 0xFD) {
2641 // character encoded on 6 octets: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx
2642 // 10xxxxxx 10xxxxxx (31 useful bits)
2643 unsigned char octets
[6];
2644 octets
[0] = octets_ptr
[i
] & 0x01;
2645 fill_continuing_octets(5, octets
+ 1, n_octets
, octets_ptr
, i
+ 1,
2647 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets
[0] << 6 | octets
[1];
2648 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets
[2] << 2 | octets
[3] >> 4;
2649 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets
[3] << 4 | octets
[4] >> 2;
2650 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets
[4] << 6 | octets
[5];
2651 if (val_ptr
->uchars_ptr
[n_uchars
].uc_group
< 0x04)
2652 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2653 "Overlong: At character position %d, octet position %d: 6-octet "
2654 "encoding for quadruple (%u, %u, %u, %u).", n_uchars
, i
,
2655 val_ptr
->uchars_ptr
[n_uchars
].uc_group
,
2656 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
,
2657 val_ptr
->uchars_ptr
[n_uchars
].uc_row
,
2658 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
);
2662 // not used code points: FE and FF => malformed
2663 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2664 "Malformed: At character position %d, octet position %d: "
2665 "unused/reserved octet %02X.", n_uchars
, i
, octets_ptr
[i
]);
2669 if (val_ptr
->n_uchars
!= n_uchars
) {
2670 // truncate the memory and set the correct size in case of decoding errors
2671 // (e.g. skipped octets)
2673 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
,
2674 MEMORY_SIZE(n_uchars
));
2675 val_ptr
->n_uchars
= n_uchars
;
2683 void UNIVERSAL_CHARSTRING::decode_utf16(int n_octets
,
2684 const unsigned char *octets_ptr
,
2685 CharCoding::CharCodingType expected_coding
)
2687 if (n_octets
% 2 || 0 > n_octets
) {
2688 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2689 "Wrong UTF-16 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 2",
2692 int start
= check_BOM(expected_coding
, sizeof(octets_ptr
), octets_ptr
);
2693 int n_uchars
= n_octets
/2;
2694 init_struct(n_uchars
);
2697 switch (expected_coding
) {
2698 case CharCoding::UTF16
:
2699 case CharCoding::UTF16BE
:
2702 case CharCoding::UTF16LE
:
2706 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2707 "Unexpected coding type for UTF-16 encoding");
2710 for (int i
= start
; i
< n_octets
; i
+= 2 ) {
2711 int first
= isbig
? i
: i
+ 1;
2712 int second
= isbig
? i
+ 1 : i
;
2713 int third
= isbig
? i
+ 2 : i
+ 3;
2714 int fourth
= isbig
? i
+ 3 : i
+ 2;
2716 uint16_t W1
= octets_ptr
[first
] << 8 | octets_ptr
[second
];
2717 uint16_t W2
= (i
+ 3 < n_octets
) ? octets_ptr
[third
] << 8 | octets_ptr
[fourth
] : 0;
2719 if (0xD800 > W1
|| 0xDFFF < W1
) {
2720 //if W1 < 0xD800 or W1 > 0xDFFF, the character value is the value of W1
2721 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2722 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= 0;
2723 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets_ptr
[first
];
2724 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[second
];
2727 else if (0xD800 > W1
|| 0xDBFF < W1
) {
2728 //Determine if W1 is between 0xD800 and 0xDBFF. If not, the sequence
2729 //is in error and no valid character can be obtained using W1.
2730 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2731 "The word (0x%04X) shall be between 0xD800 and 0xDBFF", W1
);
2733 else if (0 == W2
|| (0xDC00 > W2
|| 0xDFFF < W2
)) {
2734 //If there is no W2 (that is, the sequence ends with W1), or if W2
2735 //is not between 0xDC00 and 0xDFFF, the sequence is in error.
2737 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2738 "Wrong UTF-16 string. The word (0x%04X) shall be between 0xDC00 and 0xDFFF", W2
);
2740 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2741 "Wrong UTF-16 string. The decoding algorythm does not expect 0x00 or EOL");
2744 //Construct a 20-bit unsigned integer, taking the 10 low-order bits of W1 as its 10 high-
2745 //order bits and the 10 low-order bits of W2 as its 10 low-order bits.
2746 const uint16_t mask10bitlow
= 0x3FF;
2747 uint32_t DW
= (W1
& mask10bitlow
) << 10;
2748 DW
|= (W2
& mask10bitlow
);
2750 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= 0;
2751 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= DW
>> 16;
2752 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= DW
>> 8;
2753 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= DW
;
2755 i
+= 2; // jump over w2 in octetstring
2758 if (val_ptr
->n_uchars
!= n_uchars
) {
2759 // truncate the memory and set the correct size in case of decoding errors
2760 // (e.g. skipped octets)
2762 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(n_uchars
));
2763 val_ptr
->n_uchars
= n_uchars
;
2772 void UNIVERSAL_CHARSTRING::decode_utf32(int n_octets
, const unsigned char *octets_ptr
,
2773 CharCoding::CharCodingType expected_coding
)
2775 if (n_octets
% 4 || 0 > n_octets
) {
2776 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2777 "Wrong UTF-32 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 4",
2780 int start
= check_BOM(expected_coding
, sizeof(octets_ptr
), octets_ptr
);
2781 int n_uchars
= n_octets
/4;
2782 init_struct(n_uchars
);
2785 switch (expected_coding
) {
2786 case CharCoding::UTF32
:
2787 case CharCoding::UTF32BE
:
2790 case CharCoding::UTF32LE
:
2794 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2795 "Unexpected coding type for UTF-32 encoding");
2798 for (int i
= start
; i
< n_octets
; i
+= 4 ) {
2799 int first
= isbig
? i
: i
+ 3;
2800 int second
= isbig
? i
+ 1 : i
+ 2;
2801 int third
= isbig
? i
+ 2 : i
+ 1;
2802 int fourth
= isbig
? i
+ 3 : i
;
2803 uint32_t DW
= octets_ptr
[first
] << 8 | octets_ptr
[second
];
2805 DW
|= octets_ptr
[third
];
2807 DW
|= octets_ptr
[fourth
];
2808 if (0x0000D800 <= DW
&& 0x0000DFFF >= DW
) {
2809 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2810 "Any UTF-32 code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW
);
2812 else if (0x0010FFFF < DW
) {
2813 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2814 "Any UTF-32 code (0x%08X) greater than 0x0010FFFF is ill-formed", DW
);
2817 val_ptr
->uchars_ptr
[n_uchars
].uc_group
= octets_ptr
[first
];
2818 val_ptr
->uchars_ptr
[n_uchars
].uc_plane
= octets_ptr
[second
];
2819 val_ptr
->uchars_ptr
[n_uchars
].uc_row
= octets_ptr
[third
];
2820 val_ptr
->uchars_ptr
[n_uchars
].uc_cell
= octets_ptr
[fourth
];
2824 if (val_ptr
->n_uchars
!= n_uchars
) {
2825 // truncate the memory and set the correct size in case of decoding errors
2826 // (e.g. skipped octets)
2828 val_ptr
= (universal_charstring_struct
*)Realloc(val_ptr
, MEMORY_SIZE(n_uchars
));
2829 val_ptr
->n_uchars
= n_uchars
;
2837 int UNIVERSAL_CHARSTRING::check_BOM(CharCoding::CharCodingType expected_coding
,
2838 unsigned int length
,
2839 const unsigned char* ostr
)
2841 switch (expected_coding
) {
2842 case CharCoding::UTF32
:
2843 case CharCoding::UTF32BE
:
2844 case CharCoding::UTF32LE
:
2846 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2847 "The string is shorter than the expected BOM");
2850 case CharCoding::UTF16
:
2851 case CharCoding::UTF16BE
:
2852 case CharCoding::UTF16LE
:
2854 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2855 "The string is shorter than the expected BOM");
2858 case CharCoding::UTF_8
:
2860 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
2861 "The string is shorter than the expected BOM");
2866 std::string coding_str
;
2867 //BOM indicates that the byte order is determined by a byte order mark,
2868 //if present at the beginning the length of BOM is returned.
2869 switch (expected_coding
) {
2870 case CharCoding::UTF32BE
:
2871 case CharCoding::UTF32
:
2872 if (0x00 == ostr
[0] && 0x00 == ostr
[1] && 0xFE == ostr
[2] && 0xFF == ostr
[3]) {
2875 coding_str
= "UTF-32BE";
2877 case CharCoding::UTF32LE
:
2878 if (0xFF == ostr
[0] && 0xFE == ostr
[1] && 0x00 == ostr
[2] && 0x00 == ostr
[3]) {
2881 coding_str
= "UTF-32LE";
2883 case CharCoding::UTF16BE
:
2884 case CharCoding::UTF16
:
2885 if (0xFE == ostr
[0] && 0xFF == ostr
[1]) {
2888 coding_str
= "UTF-16BE";
2890 case CharCoding::UTF16LE
:
2891 if (0xFF == ostr
[0] && 0xFE == ostr
[1]) {
2894 coding_str
= "UTF-16LE";
2896 case CharCoding::UTF_8
:
2897 if (0xEF == ostr
[0] && 0xBB == ostr
[1] && 0xBF == ostr
[2]) {
2900 coding_str
= "UTF-8";
2904 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR
,
2905 "Wrong %s string. No BOM detected, however the given coding type (%s) expects it to define the endianness",
2906 coding_str
.c_str(), coding_str
.c_str());
2909 TTCN_EncDec_ErrorContext::warning("No %s Byte Order Mark(BOM) detected. It may result decoding errors",
2910 coding_str
.c_str());
2914 // member functions of class UNIVERSAL_CHARSTRING_ELEMENTS
2916 UNIVERSAL_CHARSTRING_ELEMENT::UNIVERSAL_CHARSTRING_ELEMENT
2917 (boolean par_bound_flag
, UNIVERSAL_CHARSTRING
& par_str_val
,
2918 int par_uchar_pos
) :
2919 bound_flag(par_bound_flag
), str_val(par_str_val
), uchar_pos(par_uchar_pos
)
2924 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2925 (const universal_char
& other_value
)
2928 if (str_val
.charstring
) {
2929 if (other_value
.is_char()) {
2930 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
.uc_cell
;
2933 str_val
.convert_cstr_to_uni();
2935 str_val
.copy_value();
2936 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] = other_value
;
2940 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2941 (const char* other_value
)
2943 if (other_value
== NULL
|| other_value
[0] == '\0' || other_value
[1] != '\0')
2944 TTCN_error("Assignment of a charstring value with length other than 1 to "
2945 "a universal charstring element.");
2947 if (str_val
.charstring
)
2948 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
[0];
2950 str_val
.copy_value();
2951 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2952 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2953 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2954 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
= other_value
[0];
2959 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2960 (const CHARSTRING
& other_value
)
2962 other_value
.must_bound("Assignment of an unbound charstring value to a "
2963 "universal charstring element.");
2964 if(other_value
.val_ptr
->n_chars
!= 1)
2965 TTCN_error("Assignment of a charstring value with length other than 1 to "
2966 "a universal charstring element.");
2968 if (str_val
.charstring
)
2969 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] =
2970 other_value
.val_ptr
->chars_ptr
[0];
2972 str_val
.copy_value();
2973 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2974 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2975 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2976 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
=
2977 other_value
.val_ptr
->chars_ptr
[0];
2982 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2983 (const CHARSTRING_ELEMENT
& other_value
)
2985 other_value
.must_bound("Assignment of an unbound charstring element to a "
2986 "universal charstring element.");
2988 if (str_val
.charstring
)
2989 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] = other_value
.get_char();
2991 str_val
.copy_value();
2992 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
2993 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
2994 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
2995 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
= other_value
.get_char();
3000 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
3001 (const UNIVERSAL_CHARSTRING
& other_value
)
3003 other_value
.must_bound("Assignment of an unbound universal charstring value "
3004 "to a universal charstring element.");
3005 int other_value_size
= other_value
.charstring
? other_value
.cstr
.val_ptr
->n_chars
:
3006 other_value
.val_ptr
->n_uchars
;
3007 if (other_value_size
!= 1)
3008 TTCN_error("Assignment of a universal charstring value with length other "
3009 "than 1 to a universal charstring element.");
3011 *this = other_value
[0];
3015 UNIVERSAL_CHARSTRING_ELEMENT
& UNIVERSAL_CHARSTRING_ELEMENT::operator=
3016 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3018 other_value
.must_bound("Assignment of an unbound universal charstring "
3020 if (&other_value
!= this) {
3022 if (str_val
.charstring
) {
3023 if (other_value
.str_val
.charstring
)
3024 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] =
3025 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3027 str_val
.convert_cstr_to_uni();
3028 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] =
3029 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3032 if (other_value
.str_val
.charstring
) {
3033 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_group
= 0;
3034 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_plane
= 0;
3035 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_row
= 0;
3036 str_val
.val_ptr
->uchars_ptr
[uchar_pos
].uc_cell
=
3037 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3039 str_val
.copy_value();
3040 str_val
.val_ptr
->uchars_ptr
[uchar_pos
] =
3041 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3048 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3049 (const universal_char
& other_value
) const
3051 must_bound("The left operand of comparison is an unbound universal "
3052 "charstring element.");
3053 if (str_val
.charstring
&& other_value
.is_char())
3054 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
.uc_cell
;
3055 if (str_val
.charstring
&& !other_value
.is_char())
3057 if (!str_val
.charstring
&& other_value
.is_char()) {
3058 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3059 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3060 uchar
.uc_cell
== other_value
.uc_cell
;
3062 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] == other_value
;
3065 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3066 (const char* other_value
) const
3068 must_bound("The left operand of comparison is an unbound universal "
3069 "charstring element.");
3070 if (other_value
== NULL
|| other_value
[0] == '\0' ||
3071 other_value
[1] != '\0') return FALSE
;
3072 if (str_val
.charstring
)
3073 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
[0];
3074 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3075 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3076 uchar
.uc_cell
== (cbyte
)other_value
[0];
3079 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3080 (const CHARSTRING
& other_value
) const
3082 must_bound("The left operand of comparison is an unbound universal "
3083 "charstring element.");
3084 other_value
.must_bound("The right operand of comparison is an unbound "
3085 "charstring value.");
3086 if (other_value
.val_ptr
->n_chars
!= 1) return FALSE
;
3087 if (str_val
.charstring
)
3088 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
3089 other_value
.val_ptr
->chars_ptr
[0];
3090 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3091 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3092 uchar
.uc_cell
== (cbyte
)other_value
.val_ptr
->chars_ptr
[0];
3095 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3096 (const CHARSTRING_ELEMENT
& other_value
) const
3098 must_bound("The left operand of comparison is an unbound universal "
3099 "charstring element.");
3100 other_value
.must_bound("The right operand of comparison is an unbound "
3101 "charstring element.");
3102 if (str_val
.charstring
)
3103 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] == other_value
.get_char();
3104 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3105 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3106 uchar
.uc_cell
== (cbyte
)other_value
.get_char();
3109 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3110 (const UNIVERSAL_CHARSTRING
& other_value
) const
3112 must_bound("The left operand of comparison is an unbound universal "
3113 "charstring element.");
3114 other_value
.must_bound("The right operand of comparison is an unbound "
3115 "universal charstring value.");
3116 if (other_value
.charstring
) {
3117 if (other_value
.cstr
.val_ptr
->n_chars
!= 1)
3119 if (str_val
.charstring
)
3120 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
3121 other_value
.cstr
.val_ptr
->chars_ptr
[0];
3123 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3124 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0
3125 && uchar
.uc_cell
== (cbyte
)other_value
.cstr
.val_ptr
->chars_ptr
[0];
3128 if (other_value
.val_ptr
->n_uchars
!= 1)
3130 if (str_val
.charstring
) {
3131 const universal_char
& uchar
= other_value
.val_ptr
->uchars_ptr
[0];
3132 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3133 uchar
.uc_cell
== (cbyte
)str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3135 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] ==
3136 other_value
.val_ptr
->uchars_ptr
[0];
3140 boolean
UNIVERSAL_CHARSTRING_ELEMENT::operator==
3141 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
3143 must_bound("The left operand of comparison is an unbound universal "
3144 "charstring element.");
3145 other_value
.must_bound("The right operand of comparison is an unbound "
3146 "universal charstring element.");
3147 if (str_val
.charstring
) {
3148 if (other_value
.str_val
.charstring
)
3149 return str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
] ==
3150 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3152 const universal_char
& uchar
= other_value
.get_uchar();
3153 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3154 uchar
.uc_cell
== str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3157 if (other_value
.str_val
.charstring
) {
3158 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3159 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3161 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3163 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
] ==
3164 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3168 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3169 (const universal_char
& other_value
) const
3171 must_bound("The left operand of concatenation is an unbound universal "
3172 "charstring element.");
3173 if (str_val
.charstring
&& other_value
.is_char()) {
3174 UNIVERSAL_CHARSTRING
ret_val(2, true);
3175 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3176 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3177 ret_val
.cstr
.val_ptr
->chars_ptr
[1] = other_value
.uc_cell
;
3179 } else if (str_val
.charstring
^ other_value
.is_char()) {
3180 universal_char result
[2];
3181 if (str_val
.charstring
) {
3182 result
[0].uc_group
= result
[0].uc_plane
= result
[0].uc_row
= 0;
3183 result
[0].uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3185 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3186 result
[1] = other_value
;
3187 return UNIVERSAL_CHARSTRING(2, result
);
3189 universal_char result
[2];
3190 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3191 result
[1] = other_value
;
3192 return UNIVERSAL_CHARSTRING(2, result
);
3195 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3196 (const char* other_value
) const
3198 must_bound("The left operand of concatenation is an unbound universal "
3199 "charstring element.");
3201 if (other_value
== NULL
) other_len
= 0;
3202 else other_len
= strlen(other_value
);
3204 UNIVERSAL_CHARSTRING
ret_val(other_len
+ 1, str_val
.charstring
);
3205 if (str_val
.charstring
) {
3206 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3207 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3208 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1, other_value
, other_len
);
3210 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3211 for (int i
= 0; i
< other_len
; i
++) {
3212 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_group
= 0;
3213 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_plane
= 0;
3214 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_row
= 0;
3215 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_cell
= other_value
[i
];
3221 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3222 (const CHARSTRING
& other_value
) const
3224 must_bound("The left operand of concatenation is an unbound universal "
3225 "charstring element.");
3226 other_value
.must_bound("The right operand of concatenation is an unbound "
3227 "charstring value.");
3228 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_chars
+ 1,
3229 str_val
.charstring
);
3230 if (str_val
.charstring
) {
3231 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3232 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3233 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1, other_value
.val_ptr
->chars_ptr
,
3234 other_value
.val_ptr
->n_chars
);
3236 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3237 for (int i
= 0; i
< other_value
.val_ptr
->n_chars
; i
++) {
3238 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_group
= 0;
3239 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_plane
= 0;
3240 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_row
= 0;
3241 ret_val
.val_ptr
->uchars_ptr
[i
+ 1].uc_cell
=
3242 other_value
.val_ptr
->chars_ptr
[i
];
3248 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3249 (const CHARSTRING_ELEMENT
& other_value
) const
3251 must_bound("The left operand of concatenation is an unbound universal "
3252 "charstring element.");
3253 other_value
.must_bound("The right operand of concatenation is an unbound "
3254 "charstring element.");
3255 if (str_val
.charstring
) {
3256 UNIVERSAL_CHARSTRING
ret_val(2, true);
3257 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3258 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3259 ret_val
.cstr
.val_ptr
->chars_ptr
[1] = other_value
.get_char();
3262 universal_char result
[2];
3263 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3264 result
[1].uc_group
= 0;
3265 result
[1].uc_plane
= 0;
3266 result
[1].uc_row
= 0;
3267 result
[1].uc_cell
= other_value
.get_char();
3268 return UNIVERSAL_CHARSTRING(2, result
);
3272 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3273 (const UNIVERSAL_CHARSTRING
& other_value
) const
3275 must_bound("The left operand of concatenation is an unbound universal "
3276 "charstring element.");
3277 other_value
.must_bound("The right operand of concatenation is an unbound "
3278 "universal charstring value.");
3279 if (str_val
.charstring
) {
3280 if (other_value
.charstring
) {
3281 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1, true);
3282 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3283 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3284 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1,
3285 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3288 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3289 universal_char
& uchar
= ret_val
.val_ptr
->uchars_ptr
[0];
3290 uchar
.uc_group
= uchar
.uc_plane
= uchar
.uc_row
= 0;
3291 uchar
.uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3292 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3293 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3297 if (other_value
.charstring
) {
3298 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1);
3299 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3300 for (int i
= 1; i
<= other_value
.cstr
.val_ptr
->n_chars
; ++i
) {
3301 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3302 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3303 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3304 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
=
3305 other_value
.cstr
.val_ptr
->chars_ptr
[i
-1];
3309 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3310 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3311 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3312 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3318 UNIVERSAL_CHARSTRING
UNIVERSAL_CHARSTRING_ELEMENT::operator+
3319 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) const
3321 must_bound("The left operand of concatenation is an unbound universal "
3322 "charstring element.");
3323 other_value
.must_bound("The right operand of concatenation is an unbound "
3324 "universal charstring element.");
3325 if (str_val
.charstring
) {
3326 if (other_value
.str_val
.charstring
) {
3327 UNIVERSAL_CHARSTRING
ret_val(2, true);
3328 ret_val
.cstr
.val_ptr
->chars_ptr
[0] =
3329 str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3330 ret_val
.cstr
.val_ptr
->chars_ptr
[1] =
3331 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3334 UNIVERSAL_CHARSTRING
ret_val(2);
3335 universal_char
& uchar
= ret_val
.val_ptr
->uchars_ptr
[0];
3336 uchar
.uc_group
= uchar
.uc_plane
= uchar
.uc_row
= 0;
3337 uchar
.uc_cell
= str_val
.cstr
.val_ptr
->chars_ptr
[uchar_pos
];
3338 ret_val
.val_ptr
->uchars_ptr
[1] =
3339 other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3343 if (other_value
.str_val
.charstring
) {
3344 UNIVERSAL_CHARSTRING
ret_val(2);
3345 ret_val
.val_ptr
->uchars_ptr
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3346 ret_val
.val_ptr
->uchars_ptr
[1].uc_group
= 0;
3347 ret_val
.val_ptr
->uchars_ptr
[1].uc_plane
= 0;
3348 ret_val
.val_ptr
->uchars_ptr
[1].uc_row
= 0;
3349 ret_val
.val_ptr
->uchars_ptr
[1].uc_cell
=
3350 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3353 universal_char result
[2];
3354 result
[0] = str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3355 result
[1] = other_value
.str_val
.val_ptr
->uchars_ptr
[other_value
.uchar_pos
];
3356 return UNIVERSAL_CHARSTRING(2, result
);
3361 const universal_char
& UNIVERSAL_CHARSTRING_ELEMENT::get_uchar() const
3363 if (str_val
.charstring
)
3364 const_cast<UNIVERSAL_CHARSTRING_ELEMENT
&>
3365 (*this).str_val
.convert_cstr_to_uni();
3366 return str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3369 void UNIVERSAL_CHARSTRING_ELEMENT::log() const
3372 if (str_val
.charstring
) {
3373 str_val
.cstr
[uchar_pos
].log();
3376 const universal_char
& uchar
= str_val
.val_ptr
->uchars_ptr
[uchar_pos
];
3377 if (is_printable(uchar
)) {
3378 // the character is printable
3379 TTCN_Logger::log_char('"');
3380 TTCN_Logger::log_char_escaped(uchar
.uc_cell
);
3381 TTCN_Logger::log_char('"');
3383 // the character is not printable
3384 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3385 uchar
.uc_group
, uchar
.uc_plane
, uchar
.uc_row
, uchar
.uc_cell
);
3387 } else TTCN_Logger::log_event_unbound();
3392 boolean
operator==(const universal_char
& uchar_value
,
3393 const UNIVERSAL_CHARSTRING
& other_value
)
3395 other_value
.must_bound("The right operand of comparison is an unbound "
3396 "universal charstring value.");
3397 if (other_value
.charstring
) {
3398 if (other_value
.cstr
.val_ptr
->n_chars
!= 1) return FALSE
;
3399 else return uchar_value
.is_char() &&
3400 uchar_value
.uc_cell
== other_value
.cstr
.val_ptr
->chars_ptr
[0];
3402 if (other_value
.val_ptr
->n_uchars
!= 1) return FALSE
;
3403 else return uchar_value
== other_value
.val_ptr
->uchars_ptr
[0];
3406 boolean
operator==(const universal_char
& uchar_value
,
3407 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3409 other_value
.must_bound("The right operand of comparison is an unbound "
3410 "universal charstring element.");
3411 return uchar_value
== other_value
.get_uchar();
3414 UNIVERSAL_CHARSTRING
operator+(const universal_char
& uchar_value
,
3415 const UNIVERSAL_CHARSTRING
& other_value
)
3417 other_value
.must_bound("The right operand of concatenation is an unbound "
3418 "universal charstring value.");
3419 if (other_value
.charstring
) {
3420 if (uchar_value
.is_char()) {
3421 UNIVERSAL_CHARSTRING
ret_val(other_value
.cstr
.val_ptr
->n_chars
+ 1, true);
3422 ret_val
.cstr
.val_ptr
->chars_ptr
[0] = uchar_value
.uc_cell
;
3423 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ 1,
3424 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3427 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3428 ret_val
.val_ptr
->uchars_ptr
[0] = uchar_value
;
3429 for (int i
= 0; i
< other_value
.cstr
.val_ptr
->n_chars
; i
++) {
3430 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_group
= 0;
3431 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_plane
= 0;
3432 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_row
= 0;
3433 ret_val
.val_ptr
->uchars_ptr
[i
+1].uc_cell
=
3434 other_value
.cstr
.val_ptr
->chars_ptr
[i
];
3439 UNIVERSAL_CHARSTRING
ret_val(other_value
.val_ptr
->n_uchars
+ 1);
3440 ret_val
.val_ptr
->uchars_ptr
[0] = uchar_value
;
3441 memcpy(ret_val
.val_ptr
->uchars_ptr
+ 1, other_value
.val_ptr
->uchars_ptr
,
3442 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3447 UNIVERSAL_CHARSTRING
operator+(const universal_char
& uchar_value
,
3448 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3450 other_value
.must_bound("The right operand of concatenation is an unbound "
3451 "universal charstring element.");
3452 if (other_value
.str_val
.charstring
) {
3453 if (uchar_value
.is_char()) {
3455 result
[0] = uchar_value
.uc_cell
;
3457 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3458 return UNIVERSAL_CHARSTRING(2, result
);
3460 universal_char result
[2];
3461 result
[0] = uchar_value
;
3462 result
[1].uc_group
= 0;
3463 result
[1].uc_plane
= 0;
3464 result
[1].uc_row
= 0;
3466 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3467 return UNIVERSAL_CHARSTRING(2, result
);
3470 universal_char result
[2];
3471 result
[0] = uchar_value
;
3472 result
[1] = other_value
.get_uchar();
3473 return UNIVERSAL_CHARSTRING(2, result
);
3477 boolean
operator==(const char *string_value
,
3478 const UNIVERSAL_CHARSTRING
& other_value
)
3480 other_value
.must_bound("The right operand of comparison is an unbound "
3481 "universal charstring value.");
3483 if (string_value
== NULL
) string_len
= 0;
3484 else string_len
= strlen(string_value
);
3485 if (other_value
.charstring
) {
3486 return other_value
.cstr
== string_value
;
3488 if (string_len
!= other_value
.val_ptr
->n_uchars
) return FALSE
;
3489 for (int i
= 0; i
< string_len
; i
++) {
3490 if (other_value
.val_ptr
->uchars_ptr
[i
].uc_group
!= 0 ||
3491 other_value
.val_ptr
->uchars_ptr
[i
].uc_plane
!= 0 ||
3492 other_value
.val_ptr
->uchars_ptr
[i
].uc_row
!= 0 ||
3493 other_value
.val_ptr
->uchars_ptr
[i
].uc_cell
!= string_value
[i
])
3500 boolean
operator==(const char *string_value
,
3501 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3503 other_value
.must_bound("The right operand of comparison is an unbound "
3504 "universal charstring element.");
3505 if (string_value
== NULL
|| string_value
[0] == '\0' ||
3506 string_value
[1] != '\0') return FALSE
;
3507 if (other_value
.str_val
.charstring
)
3508 return other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
]
3510 const universal_char
& uchar
= other_value
.get_uchar();
3511 return uchar
.uc_group
== 0 && uchar
.uc_plane
== 0 && uchar
.uc_row
== 0 &&
3512 uchar
.uc_cell
== string_value
[0];
3515 UNIVERSAL_CHARSTRING
operator+(const char *string_value
,
3516 const UNIVERSAL_CHARSTRING
& other_value
)
3518 other_value
.must_bound("The right operand of concatenation is an unbound "
3519 "universal charstring value.");
3521 if (string_value
== NULL
) string_len
= 0;
3522 else string_len
= strlen(string_value
);
3523 if (other_value
.charstring
) {
3524 UNIVERSAL_CHARSTRING
ret_val(string_len
+ other_value
.cstr
.val_ptr
->n_chars
,
3526 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, string_value
, string_len
);
3527 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
+ string_len
,
3528 other_value
.cstr
.val_ptr
->chars_ptr
, other_value
.cstr
.val_ptr
->n_chars
);
3531 UNIVERSAL_CHARSTRING
ret_val(string_len
+ other_value
.val_ptr
->n_uchars
);
3532 for (int i
= 0; i
< string_len
; i
++) {
3533 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3534 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3535 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3536 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= string_value
[i
];
3538 memcpy(ret_val
.val_ptr
->uchars_ptr
+ string_len
,
3539 other_value
.val_ptr
->uchars_ptr
,
3540 other_value
.val_ptr
->n_uchars
* sizeof(universal_char
));
3544 UNIVERSAL_CHARSTRING
operator+(const char *string_value
,
3545 const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3547 other_value
.must_bound("The right operand of concatenation is an unbound "
3548 "universal charstring element.");
3550 if (string_value
== NULL
) string_len
= 0;
3551 else string_len
= strlen(string_value
);
3552 if (other_value
.str_val
.charstring
) {
3553 UNIVERSAL_CHARSTRING
ret_val(string_len
+ 1, true);
3554 memcpy(ret_val
.cstr
.val_ptr
->chars_ptr
, string_value
, string_len
);
3555 ret_val
.cstr
.val_ptr
->chars_ptr
[string_len
] =
3556 other_value
.str_val
.cstr
.val_ptr
->chars_ptr
[other_value
.uchar_pos
];
3559 UNIVERSAL_CHARSTRING
ret_val(string_len
+ 1);
3560 for (int i
= 0; i
< string_len
; i
++) {
3561 ret_val
.val_ptr
->uchars_ptr
[i
].uc_group
= 0;
3562 ret_val
.val_ptr
->uchars_ptr
[i
].uc_plane
= 0;
3563 ret_val
.val_ptr
->uchars_ptr
[i
].uc_row
= 0;
3564 ret_val
.val_ptr
->uchars_ptr
[i
].uc_cell
= string_value
[i
];
3566 ret_val
.val_ptr
->uchars_ptr
[string_len
] = other_value
.get_uchar();
3570 // member functions of class UNIVERSAL_CHARSTRING_template
3572 void UNIVERSAL_CHARSTRING_template::clean_up()
3574 if (template_selection
== VALUE_LIST
||
3575 template_selection
== COMPLEMENTED_LIST
) delete [] value_list
.list_value
;
3576 else if (template_selection
== STRING_PATTERN
) {
3577 if (pattern_value
.regexp_init
) regfree(&pattern_value
.posix_regexp
);
3578 delete pattern_string
;
3580 else if (template_selection
== DECODE_MATCH
) {
3581 if (dec_match
->ref_count
> 1) {
3582 dec_match
->ref_count
--;
3584 else if (dec_match
->ref_count
== 1) {
3585 delete dec_match
->instance
;
3589 TTCN_error("Internal error: Invalid reference counter in a "
3590 "decoded content match.");
3593 template_selection
= UNINITIALIZED_TEMPLATE
;
3596 void UNIVERSAL_CHARSTRING_template::copy_template
3597 (const CHARSTRING_template
& other_value
)
3599 switch (other_value
.template_selection
) {
3600 case SPECIFIC_VALUE
:
3601 single_value
= other_value
.single_value
;
3608 case COMPLEMENTED_LIST
:
3609 value_list
.n_values
= other_value
.value_list
.n_values
;
3610 value_list
.list_value
=
3611 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3612 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3613 value_list
.list_value
[i
].copy_template(
3614 other_value
.value_list
.list_value
[i
]);
3617 if (!other_value
.value_range
.min_is_set
) TTCN_error("The lower bound is "
3618 "not set when copying a charstring value range template to a universal "
3619 "charstring template.");
3620 if (!other_value
.value_range
.max_is_set
) TTCN_error("The upper bound is "
3621 "not set when copying a charstring value range template to a universal "
3622 "charstring template.");
3623 value_range
.min_is_set
= TRUE
;
3624 value_range
.max_is_set
= TRUE
;
3625 value_range
.min_value
.uc_group
= 0;
3626 value_range
.min_value
.uc_plane
= 0;
3627 value_range
.min_value
.uc_row
= 0;
3628 value_range
.min_value
.uc_cell
= other_value
.value_range
.min_value
;
3629 value_range
.max_value
.uc_group
= 0;
3630 value_range
.max_value
.uc_plane
= 0;
3631 value_range
.max_value
.uc_row
= 0;
3632 value_range
.max_value
.uc_cell
= other_value
.value_range
.max_value
;
3634 case STRING_PATTERN
:
3635 pattern_string
= new CHARSTRING(other_value
.single_value
);
3636 pattern_value
.regexp_init
=FALSE
;
3639 dec_match
= other_value
.dec_match
;
3640 dec_match
->ref_count
++;
3643 TTCN_error("Copying an uninitialized/unsupported charstring template to a "
3644 "universal charstring template.");
3646 set_selection(other_value
);
3649 void UNIVERSAL_CHARSTRING_template::copy_template
3650 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3652 switch (other_value
.template_selection
) {
3653 case SPECIFIC_VALUE
:
3654 single_value
= other_value
.single_value
;
3661 case COMPLEMENTED_LIST
:
3662 value_list
.n_values
= other_value
.value_list
.n_values
;
3663 value_list
.list_value
=
3664 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
3665 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3666 value_list
.list_value
[i
].copy_template(
3667 other_value
.value_list
.list_value
[i
]);
3670 if (!other_value
.value_range
.min_is_set
) TTCN_error("The lower bound is "
3671 "not set when copying a universal charstring value range template.");
3672 if (!other_value
.value_range
.max_is_set
) TTCN_error("The upper bound is "
3673 "not set when copying a universal charstring value range template.");
3674 value_range
= other_value
.value_range
;
3676 case STRING_PATTERN
:
3677 pattern_string
= new CHARSTRING(*(other_value
.pattern_string
));
3678 pattern_value
.regexp_init
=FALSE
;
3681 dec_match
= other_value
.dec_match
;
3682 dec_match
->ref_count
++;
3685 TTCN_error("Copying an uninitialized/unsupported universal charstring "
3688 set_selection(other_value
);
3691 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template()
3695 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3696 (template_sel other_value
) : Restricted_Length_Template(other_value
)
3699 check_single_selection(other_value
);
3702 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3703 (const CHARSTRING
& other_value
) :
3704 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3708 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3709 (const UNIVERSAL_CHARSTRING
& other_value
) :
3710 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3714 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3715 (const CHARSTRING_ELEMENT
& other_value
) :
3716 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3720 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3721 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
) :
3722 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
3726 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3727 (const OPTIONAL
<CHARSTRING
>& other_value
)
3729 switch (other_value
.get_selection()) {
3730 case OPTIONAL_PRESENT
:
3731 set_selection(SPECIFIC_VALUE
);
3732 single_value
= (const CHARSTRING
&)other_value
;
3735 set_selection(OMIT_VALUE
);
3738 TTCN_error("Creating a universal charstring template from an unbound "
3743 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3744 (const OPTIONAL
<UNIVERSAL_CHARSTRING
>& other_value
)
3746 switch (other_value
.get_selection()) {
3747 case OPTIONAL_PRESENT
:
3748 set_selection(SPECIFIC_VALUE
);
3749 single_value
= (const UNIVERSAL_CHARSTRING
&)other_value
;
3752 set_selection(OMIT_VALUE
);
3755 TTCN_error("Creating a universal charstring template from an unbound "
3760 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3761 (const CHARSTRING_template
& other_value
)
3762 : Restricted_Length_Template()
3764 copy_template(other_value
);
3767 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3768 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3769 : Restricted_Length_Template()
3771 copy_template(other_value
);
3774 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3775 (template_sel p_sel
, const CHARSTRING
& p_str
)
3776 : Restricted_Length_Template(STRING_PATTERN
)
3778 if(p_sel
!=STRING_PATTERN
)
3779 TTCN_error("Internal error: Initializing a universal charstring"
3780 "pattern template with invalid selection.");
3781 pattern_string
= new CHARSTRING(p_str
);
3782 pattern_value
.regexp_init
=FALSE
;
3785 UNIVERSAL_CHARSTRING_template::~UNIVERSAL_CHARSTRING_template()
3790 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3791 (template_sel other_value
)
3793 check_single_selection(other_value
);
3795 set_selection(other_value
);
3799 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3800 (const CHARSTRING
& other_value
)
3802 other_value
.must_bound("Assignment of an unbound charstring value to a "
3803 "universal charstring template.");
3805 set_selection(SPECIFIC_VALUE
);
3806 single_value
= other_value
;
3810 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3811 (const UNIVERSAL_CHARSTRING
& other_value
)
3813 other_value
.must_bound("Assignment of an unbound universal charstring value "
3816 set_selection(SPECIFIC_VALUE
);
3817 single_value
= other_value
;
3821 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3822 (const CHARSTRING_ELEMENT
& other_value
)
3824 other_value
.must_bound("Assignment of an unbound charstring element to a "
3825 "universal charstring template.");
3827 set_selection(SPECIFIC_VALUE
);
3828 single_value
= other_value
;
3832 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3833 (const UNIVERSAL_CHARSTRING_ELEMENT
& other_value
)
3835 other_value
.must_bound("Assignment of an unbound universal charstring "
3836 "element to a template.");
3838 set_selection(SPECIFIC_VALUE
);
3839 single_value
= other_value
;
3843 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3844 (const OPTIONAL
<CHARSTRING
>& other_value
)
3847 switch (other_value
.get_selection()) {
3848 case OPTIONAL_PRESENT
:
3849 set_selection(SPECIFIC_VALUE
);
3850 single_value
= (const CHARSTRING
&)other_value
;
3853 set_selection(OMIT_VALUE
);
3856 TTCN_error("Assignment of an unbound optional field to a universal "
3857 "charstring template.");
3862 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3863 (const OPTIONAL
<UNIVERSAL_CHARSTRING
>& other_value
)
3866 switch (other_value
.get_selection()) {
3867 case OPTIONAL_PRESENT
:
3868 set_selection(SPECIFIC_VALUE
);
3869 single_value
= (const UNIVERSAL_CHARSTRING
&)other_value
;
3872 set_selection(OMIT_VALUE
);
3875 TTCN_error("Assignment of an unbound optional field to a universal "
3876 "charstring template.");
3881 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3882 (const CHARSTRING_template
& other_value
)
3885 copy_template(other_value
);
3889 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::operator=
3890 (const UNIVERSAL_CHARSTRING_template
& other_value
)
3892 if (&other_value
!= this) {
3894 copy_template(other_value
);
3899 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](int index_value
)
3901 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3902 TTCN_error("Accessing a universal charstring element of a non-specific "
3903 "universal charstring template.");
3904 return single_value
[index_value
];
3907 UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](const INTEGER
& index_value
)
3909 index_value
.must_bound("Indexing a universal charstring template with an "
3910 "unbound integer value.");
3911 return (*this)[(int)index_value
];
3914 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](int index_value
) const
3916 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
3917 TTCN_error("Accessing a universal charstring element of a non-specific "
3918 "universal charstring template.");
3919 return single_value
[index_value
];
3922 const UNIVERSAL_CHARSTRING_ELEMENT
UNIVERSAL_CHARSTRING_template::operator[](const INTEGER
& index_value
) const
3924 index_value
.must_bound("Indexing a universal charstring template with an "
3925 "unbound integer value.");
3926 return (*this)[(int)index_value
];
3929 boolean
UNIVERSAL_CHARSTRING_template::match
3930 (const UNIVERSAL_CHARSTRING
& other_value
, boolean
/* legacy */) const
3932 if (!other_value
.is_bound()) return FALSE
;
3933 int value_length
= other_value
.lengthof();
3934 if (!match_length(value_length
)) return FALSE
;
3935 switch (template_selection
) {
3936 case SPECIFIC_VALUE
:
3937 return single_value
== other_value
;
3944 case COMPLEMENTED_LIST
:
3945 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
3946 if (value_list
.list_value
[i
].match(other_value
))
3947 return template_selection
== VALUE_LIST
;
3948 return template_selection
== COMPLEMENTED_LIST
;
3950 if (!value_range
.min_is_set
) TTCN_error("The lower bound is not set when "
3951 "matching with a universal charstring value range template.");
3952 if (!value_range
.max_is_set
) TTCN_error("The upper bound is not set when "
3953 "matching with a universal charstring value range template.");
3954 if (value_range
.max_value
< value_range
.min_value
)
3955 TTCN_error("The lower bound is greater than the upper bound "
3956 "when matching with a universal charstring value range template.");
3957 const universal_char
*uchars_ptr
= other_value
;
3958 for (int i
= 0; i
< value_length
; i
++) {
3959 if (uchars_ptr
[i
] < value_range
.min_value
||
3960 value_range
.max_value
< uchars_ptr
[i
]) return FALSE
;
3963 case STRING_PATTERN
: {
3964 if (!pattern_value
.regexp_init
) {
3966 TTCN_pattern_to_regexp_uni((const char*)(*pattern_string
));
3967 if(posix_str
==NULL
) {
3968 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
3969 (const char*)(*pattern_string
));
3971 int ret_val
=regcomp(&pattern_value
.posix_regexp
, posix_str
,
3972 REG_EXTENDED
|REG_NOSUB
);
3976 char msg
[ERRMSG_BUFSIZE
];
3977 regerror(ret_val
, &pattern_value
.posix_regexp
, msg
, ERRMSG_BUFSIZE
);
3978 regfree(&pattern_value
.posix_regexp
);
3979 TTCN_error("Pattern matching error: %s", msg
);
3981 pattern_value
.regexp_init
=TRUE
;
3983 char* other_value_converted
= other_value
.convert_to_regexp_form();
3984 int ret_val
=regexec(&pattern_value
.posix_regexp
, other_value_converted
, 0,
3986 Free(other_value_converted
);
3994 char msg
[ERRMSG_BUFSIZE
];
3995 regerror(ret_val
, &pattern_value
.posix_regexp
, msg
, ERRMSG_BUFSIZE
);
3996 TTCN_error("Pattern matching error: %s", msg
);
3999 case DECODE_MATCH
: {
4000 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL
, TTCN_EncDec::EB_WARNING
);
4001 TTCN_EncDec::clear_error();
4003 switch (dec_match
->coding
) {
4004 case CharCoding::UTF_8
:
4005 other_value
.encode_utf8(buff
, false);
4007 case CharCoding::UTF16
:
4008 case CharCoding::UTF16LE
:
4009 case CharCoding::UTF16BE
:
4010 other_value
.encode_utf16(buff
, dec_match
->coding
);
4012 case CharCoding::UTF32
:
4013 case CharCoding::UTF32LE
:
4014 case CharCoding::UTF32BE
:
4015 other_value
.encode_utf32(buff
, dec_match
->coding
);
4018 TTCN_error("Internal error: Invalid string serialization for "
4019 "universal charstring template with decoded content matching.");
4021 boolean ret_val
= dec_match
->instance
->match(buff
);
4022 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL
,TTCN_EncDec::EB_DEFAULT
);
4023 TTCN_EncDec::clear_error();
4026 TTCN_error("Matching with an uninitialized/unsupported universal "
4027 "charstring template.");
4032 const UNIVERSAL_CHARSTRING
& UNIVERSAL_CHARSTRING_template::valueof() const
4034 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
4035 TTCN_error("Performing valueof or send operation on a non-specific "
4036 "universal charstring template.");
4037 return single_value
;
4040 int UNIVERSAL_CHARSTRING_template::lengthof() const
4043 boolean has_any_or_none
;
4045 TTCN_error("Performing lengthof() operation on a universal charstring "
4046 "template which has an ifpresent attribute.");
4047 switch (template_selection
)
4049 case SPECIFIC_VALUE
:
4050 min_length
= single_value
.lengthof();
4051 has_any_or_none
= FALSE
;
4054 TTCN_error("Performing lengthof() operation on a universal charstring "
4055 "template containing omit value.");
4060 has_any_or_none
= TRUE
; // max. length is infinity
4064 // error if any element does not have length or the lengths differ
4065 if (value_list
.n_values
<1)
4066 TTCN_error("Internal error: "
4067 "Performing lengthof() operation on a universal charstring "
4068 "template containing an empty list.");
4069 int item_length
= value_list
.list_value
[0].lengthof();
4070 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
4071 if (value_list
.list_value
[i
].lengthof()!=item_length
)
4072 TTCN_error("Performing lengthof() operation on a universal charstring "
4073 "template containing a value list with different lengths.");
4075 min_length
= item_length
;
4076 has_any_or_none
= FALSE
;
4079 case COMPLEMENTED_LIST
:
4080 TTCN_error("Performing lengthof() operation on a universal charstring "
4081 "template containing complemented list.");
4082 case STRING_PATTERN
:
4083 TTCN_error("Performing lengthof() operation on a universal charstring "
4084 "template containing a pattern is not allowed.");
4086 TTCN_error("Performing lengthof() operation on an "
4087 "uninitialized/unsupported universal charstring template.");
4089 return check_section_is_single(min_length
, has_any_or_none
,
4090 "length", "a", "universal charstring template");
4093 void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type
,
4094 unsigned int list_length
)
4097 switch (template_type
) {
4099 case COMPLEMENTED_LIST
:
4100 set_selection(template_type
);
4101 value_list
.n_values
= list_length
;
4102 value_list
.list_value
= new UNIVERSAL_CHARSTRING_template
[list_length
];
4105 set_selection(VALUE_RANGE
);
4106 value_range
.min_is_set
= FALSE
;
4107 value_range
.max_is_set
= FALSE
;
4110 set_selection(DECODE_MATCH
);
4113 TTCN_error("Setting an invalid type for a universal charstring template.");
4117 UNIVERSAL_CHARSTRING_template
& UNIVERSAL_CHARSTRING_template::list_item
4118 (unsigned int list_index
)
4120 if (template_selection
!= VALUE_LIST
&&
4121 template_selection
!= COMPLEMENTED_LIST
)
4122 TTCN_error("Accessing a list element of a non-list universal charstring "
4124 if (list_index
>= value_list
.n_values
)
4125 TTCN_error("Index overflow in a universal charstring value list template.");
4126 return value_list
.list_value
[list_index
];
4129 void UNIVERSAL_CHARSTRING_template::set_min
4130 (const UNIVERSAL_CHARSTRING
& min_value
)
4132 if (template_selection
!= VALUE_RANGE
) TTCN_error("Setting the lower bound "
4133 "for a non-range universal charstring template.");
4134 min_value
.must_bound("Setting an unbound value as lower bound in a "
4135 "universal charstring value range template.");
4136 int length
= min_value
.lengthof();
4137 if (length
!= 1) TTCN_error("The length of the lower bound in a universal "
4138 "charstring value range template must be 1 instead of %d.", length
);
4139 value_range
.min_is_set
= TRUE
;
4140 value_range
.min_value
= *(const universal_char
*)min_value
;
4141 if (value_range
.max_is_set
&& value_range
.max_value
< value_range
.min_value
)
4142 TTCN_error("The lower bound in a universal charstring value range template "
4143 "is greater than the upper bound.");
4146 void UNIVERSAL_CHARSTRING_template::set_max
4147 (const UNIVERSAL_CHARSTRING
& max_value
)
4149 if (template_selection
!= VALUE_RANGE
) TTCN_error("Setting the upper bound "
4150 "for a non-range universal charstring template.");
4151 max_value
.must_bound("Setting an unbound value as upper bound in a "
4152 "universal charstring value range template.");
4153 int length
= max_value
.lengthof();
4154 if (length
!= 1) TTCN_error("The length of the upper bound in a universal "
4155 "charstring value range template must be 1 instead of %d.", length
);
4156 value_range
.max_is_set
= TRUE
;
4157 value_range
.max_value
= *(const universal_char
*)max_value
;
4158 if (value_range
.min_is_set
&& value_range
.max_value
< value_range
.min_value
)
4159 TTCN_error("The upper bound in a universal charstring value range template "
4160 "is smaller than the lower bound.");
4163 void UNIVERSAL_CHARSTRING_template::set_decmatch(Dec_Match_Interface
* new_instance
,
4164 const char* coding_str
/* = NULL */)
4166 if (template_selection
!= DECODE_MATCH
) {
4167 TTCN_error("Setting the decoded content matching mechanism of a non-decmatch "
4168 "universal charstring template.");
4170 CharCoding::CharCodingType new_coding
= CharCoding::UTF_8
;
4171 if (coding_str
!= NULL
&& strcmp(coding_str
, "UTF-8") != 0) {
4172 if (strcmp(coding_str
, "UTF-16") == 0) {
4173 new_coding
= CharCoding::UTF16
;
4175 else if (strcmp(coding_str
, "UTF-16LE") == 0) {
4176 new_coding
= CharCoding::UTF16LE
;
4178 else if (strcmp(coding_str
, "UTF-16BE") == 0) {
4179 new_coding
= CharCoding::UTF16BE
;
4181 else if (strcmp(coding_str
, "UTF-32") == 0) {
4182 new_coding
= CharCoding::UTF32
;
4184 else if (strcmp(coding_str
, "UTF-32LE") == 0) {
4185 new_coding
= CharCoding::UTF32LE
;
4187 else if (strcmp(coding_str
, "UTF-32BE") == 0) {
4188 new_coding
= CharCoding::UTF32BE
;
4191 TTCN_error("Invalid string serialization for decoded content matching.");
4194 dec_match
= new unichar_decmatch_struct
;
4195 dec_match
->ref_count
= 1;
4196 dec_match
->instance
= new_instance
;
4197 dec_match
->coding
= new_coding
;
4200 void UNIVERSAL_CHARSTRING_template::log() const
4202 switch (template_selection
) {
4203 case STRING_PATTERN
:
4204 CHARSTRING_template::log_pattern(pattern_string
->lengthof(),
4205 (const char*)*pattern_string
);
4207 case SPECIFIC_VALUE
:
4210 case COMPLEMENTED_LIST
:
4211 TTCN_Logger::log_event_str("complement ");
4214 TTCN_Logger::log_char('(');
4215 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
4216 if (i
> 0) TTCN_Logger::log_event_str(", ");
4217 value_list
.list_value
[i
].log();
4219 TTCN_Logger::log_char(')');
4222 TTCN_Logger::log_char('(');
4223 if (value_range
.min_is_set
) {
4224 if (is_printable(value_range
.min_value
)) {
4225 TTCN_Logger::log_char('"');
4226 TTCN_Logger::log_char_escaped(value_range
.min_value
.uc_cell
);
4227 TTCN_Logger::log_char('"');
4229 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4230 value_range
.min_value
.uc_group
, value_range
.min_value
.uc_plane
,
4231 value_range
.min_value
.uc_row
, value_range
.min_value
.uc_cell
);
4233 } else TTCN_Logger::log_event_str("<unknown lower bound>");
4234 TTCN_Logger::log_event_str(" .. ");
4235 if (value_range
.max_is_set
) {
4236 if (is_printable(value_range
.max_value
)) {
4237 TTCN_Logger::log_char('"');
4238 TTCN_Logger::log_char_escaped(value_range
.max_value
.uc_cell
);
4239 TTCN_Logger::log_char('"');
4241 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4242 value_range
.max_value
.uc_group
, value_range
.max_value
.uc_plane
,
4243 value_range
.max_value
.uc_row
, value_range
.max_value
.uc_cell
);
4245 } else TTCN_Logger::log_event_str("<unknown upper bound>");
4246 TTCN_Logger::log_char(')');
4249 TTCN_Logger::log_event_str("decmatch(");
4250 switch (dec_match
->coding
) {
4251 case CharCoding::UTF_8
:
4252 TTCN_Logger::log_event_str("UTF-8");
4254 case CharCoding::UTF16
:
4255 TTCN_Logger::log_event_str("UTF-16");
4257 case CharCoding::UTF16LE
:
4258 TTCN_Logger::log_event_str("UTF-16LE");
4260 case CharCoding::UTF16BE
:
4261 TTCN_Logger::log_event_str("UTF-16BE");
4263 case CharCoding::UTF32
:
4264 TTCN_Logger::log_event_str("UTF-32");
4266 case CharCoding::UTF32LE
:
4267 TTCN_Logger::log_event_str("UTF-32LE");
4269 case CharCoding::UTF32BE
:
4270 TTCN_Logger::log_event_str("UTF-32BE");
4273 TTCN_Logger::log_event_str("<unknown coding>");
4276 TTCN_Logger::log_event_str(") ");
4277 dec_match
->instance
->log();
4287 void UNIVERSAL_CHARSTRING_template::log_match
4288 (const UNIVERSAL_CHARSTRING
& match_value
, boolean
/* legacy */) const
4290 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
4291 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
4292 TTCN_Logger::print_logmatch_buffer();
4293 TTCN_Logger::log_event_str(" := ");
4296 TTCN_Logger::log_event_str(" with ");
4298 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
4299 else TTCN_Logger::log_event_str(" unmatched");
4302 void UNIVERSAL_CHARSTRING_template::set_param(Module_Param
& param
) {
4303 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "universal charstring template");
4304 Module_Param_Ptr mp
= ¶m
;
4305 if (param
.get_type() == Module_Param::MP_Reference
) {
4306 mp
= param
.get_referenced_param();
4308 switch (mp
->get_type()) {
4309 case Module_Param::MP_Omit
:
4312 case Module_Param::MP_Any
:
4315 case Module_Param::MP_AnyOrNone
:
4316 *this = ANY_OR_OMIT
;
4318 case Module_Param::MP_List_Template
:
4319 case Module_Param::MP_ComplementList_Template
: {
4320 UNIVERSAL_CHARSTRING_template temp
;
4321 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
4322 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
4323 for (size_t i
=0; i
<mp
->get_size(); i
++) {
4324 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
4328 case Module_Param::MP_Charstring
: {
4330 buff
.put_s(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
4331 *this = UNIVERSAL_CHARSTRING::from_UTF8_buffer(buff
);
4333 case Module_Param::MP_Universal_Charstring
:
4334 *this = UNIVERSAL_CHARSTRING(mp
->get_string_size(), (universal_char
*)mp
->get_string_data());
4336 case Module_Param::MP_StringRange
: {
4337 universal_char lower_uchar
= mp
->get_lower_uchar();
4338 universal_char upper_uchar
= mp
->get_upper_uchar();
4340 set_selection(VALUE_RANGE
);
4341 value_range
.min_is_set
= TRUE
;
4342 value_range
.max_is_set
= TRUE
;
4343 value_range
.min_value
= lower_uchar
;
4344 value_range
.max_value
= upper_uchar
;
4346 case Module_Param::MP_Pattern
:
4348 pattern_string
= new CHARSTRING(mp
->get_pattern());
4349 pattern_value
.regexp_init
= FALSE
;
4350 set_selection(STRING_PATTERN
);
4352 case Module_Param::MP_Expression
:
4353 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
4354 UNIVERSAL_CHARSTRING operand1
, operand2
, result
;
4355 boolean is_pattern
= operand1
.set_param_internal(*mp
->get_operand1(), TRUE
);
4356 operand2
.set_param(*mp
->get_operand2());
4357 result
= operand1
+ operand2
;
4360 if (result
.charstring
) {
4361 pattern_string
= new CHARSTRING(result
.cstr
);
4364 pattern_string
= new CHARSTRING(result
.get_stringRepr_for_pattern());
4366 pattern_value
.regexp_init
= FALSE
;
4367 set_selection(STRING_PATTERN
);
4374 param
.expr_type_error("a charstring");
4378 param
.type_error("universal charstring template");
4380 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
4381 if (param
.get_length_restriction() != NULL
) {
4382 set_length_range(param
);
4385 set_length_range(*mp
);
4389 Module_Param
* UNIVERSAL_CHARSTRING_template::get_param(Module_Param_Name
& param_name
) const
4391 Module_Param
* mp
= NULL
;
4392 switch (template_selection
) {
4393 case UNINITIALIZED_TEMPLATE
:
4394 mp
= new Module_Param_Unbound();
4397 mp
= new Module_Param_Omit();
4400 mp
= new Module_Param_Any();
4403 mp
= new Module_Param_AnyOrNone();
4405 case SPECIFIC_VALUE
:
4406 mp
= single_value
.get_param(param_name
);
4409 case COMPLEMENTED_LIST
: {
4410 if (template_selection
== VALUE_LIST
) {
4411 mp
= new Module_Param_List_Template();
4414 mp
= new Module_Param_ComplementList_Template();
4416 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
4417 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
4421 mp
= new Module_Param_StringRange(value_range
.min_value
, value_range
.max_value
);
4423 case STRING_PATTERN
:
4424 mp
= new Module_Param_Pattern(mcopystr(*pattern_string
));
4427 mp
->error("Referencing a decoded content matching template is not supported.");
4433 mp
->set_ifpresent();
4435 mp
->set_length_restriction(get_length_range());
4439 void UNIVERSAL_CHARSTRING_template::encode_text(Text_Buf
& text_buf
) const
4441 encode_text_restricted(text_buf
);
4442 switch (template_selection
) {
4447 case SPECIFIC_VALUE
:
4448 single_value
.encode_text(text_buf
);
4451 case COMPLEMENTED_LIST
:
4452 text_buf
.push_int(value_list
.n_values
);
4453 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
4454 value_list
.list_value
[i
].encode_text(text_buf
);
4457 if (!value_range
.min_is_set
) TTCN_error("Text encoder: The lower bound is "
4458 "not set in a universal charstring value range template.");
4459 if (!value_range
.max_is_set
) TTCN_error("Text encoder: The upper bound is "
4460 "not set in a universal charstring value range template.");
4461 unsigned char buf
[8];
4462 buf
[0] = value_range
.min_value
.uc_group
;
4463 buf
[1] = value_range
.min_value
.uc_plane
;
4464 buf
[2] = value_range
.min_value
.uc_row
;
4465 buf
[3] = value_range
.min_value
.uc_cell
;
4466 buf
[4] = value_range
.max_value
.uc_group
;
4467 buf
[5] = value_range
.max_value
.uc_plane
;
4468 buf
[6] = value_range
.max_value
.uc_row
;
4469 buf
[7] = value_range
.max_value
.uc_cell
;
4470 text_buf
.push_raw(8, buf
);
4473 TTCN_error("Text encoder: Encoding an uninitialized/unsupported universal "
4474 "charstring template.");
4478 void UNIVERSAL_CHARSTRING_template::decode_text(Text_Buf
& text_buf
)
4481 decode_text_restricted(text_buf
);
4482 switch (template_selection
) {
4487 case SPECIFIC_VALUE
:
4488 single_value
.decode_text(text_buf
);
4491 case COMPLEMENTED_LIST
:
4492 value_list
.n_values
= text_buf
.pull_int().get_val();
4493 value_list
.list_value
=
4494 new UNIVERSAL_CHARSTRING_template
[value_list
.n_values
];
4495 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
4496 value_list
.list_value
[i
].decode_text(text_buf
);
4499 unsigned char buf
[8];
4500 text_buf
.pull_raw(8, buf
);
4501 value_range
.min_value
.uc_group
= buf
[0];
4502 value_range
.min_value
.uc_plane
= buf
[1];
4503 value_range
.min_value
.uc_row
= buf
[2];
4504 value_range
.min_value
.uc_cell
= buf
[3];
4505 value_range
.max_value
.uc_group
= buf
[4];
4506 value_range
.max_value
.uc_plane
= buf
[5];
4507 value_range
.max_value
.uc_row
= buf
[6];
4508 value_range
.max_value
.uc_cell
= buf
[7];
4509 if (value_range
.max_value
< value_range
.min_value
)
4510 TTCN_error("Text decoder: The received lower bound is greater than the "
4511 "upper bound in a universal charstring value range template.");
4512 value_range
.min_is_set
= TRUE
;
4513 value_range
.max_is_set
= TRUE
;
4516 TTCN_error("Text decoder: An unknown/unsupported selection was "
4517 "received for a universal charstring template.");
4521 boolean
UNIVERSAL_CHARSTRING_template::is_present(boolean legacy
/* = FALSE */) const
4523 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
4524 return !match_omit(legacy
);
4527 boolean
UNIVERSAL_CHARSTRING_template::match_omit(boolean legacy
/* = FALSE */) const
4529 if (is_ifpresent
) return TRUE
;
4530 switch (template_selection
) {
4535 case COMPLEMENTED_LIST
:
4537 // legacy behavior: 'omit' can appear in the value/complement list
4538 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
4539 if (value_list
.list_value
[i
].match_omit())
4540 return template_selection
==VALUE_LIST
;
4541 return template_selection
==COMPLEMENTED_LIST
;
4543 // else fall through
4550 #ifndef TITAN_RUNTIME_2
4551 void UNIVERSAL_CHARSTRING_template::check_restriction(template_res t_res
,
4552 const char* t_name
, boolean legacy
) const
4554 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
4555 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
4557 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
4560 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
4561 template_selection
==SPECIFIC_VALUE
)) return;
4564 if (!match_omit(legacy
)) return;
4569 TTCN_error("Restriction `%s' on template of type %s violated.",
4570 get_res_name(t_res
), t_name
? t_name
: "universal charstring");
4574 const CHARSTRING
& UNIVERSAL_CHARSTRING_template::get_single_value() const {
4575 if (!pattern_string
)
4576 TTCN_error("Pattern string does not exist in universal charstring template");
4577 return *pattern_string
;
4581 * ISO 2022 conversion functions -- these can be overwritten by users
4582 * by defining their own versions. Because these --of course :)-- are
4583 * not really conform to ISO 2022. :o)
4586 /** TTCN_UCSTR_2_ISO2022: A dummy common implementation. */
4587 OCTETSTRING
TTCN_UCSTR_2_ISO2022(const UNIVERSAL_CHARSTRING
& p_s
)
4589 const universal_char
* ucstr
=static_cast<const universal_char
*>(p_s
);
4590 int len
=p_s
.lengthof();
4591 unsigned char* osstr
=(unsigned char*)Malloc(len
);
4592 for(int i
=0; i
<len
; i
++) osstr
[i
]=ucstr
[i
].uc_cell
;
4593 OCTETSTRING
os(len
, osstr
);
4598 /** TTCN_ISO2022_2_UCSTR: A dummy common implementation. */
4599 UNIVERSAL_CHARSTRING
TTCN_ISO2022_2_UCSTR(const OCTETSTRING
& p_os
)
4601 const unsigned char* osstr
=static_cast<const unsigned char*>(p_os
);
4602 int len
=p_os
.lengthof();
4603 universal_char
* ucstr
=(universal_char
*)Malloc(len
*sizeof(*ucstr
));
4604 for(int i
=0; i
<len
; i
++) {
4605 ucstr
[i
].uc_group
=0;
4606 ucstr
[i
].uc_plane
=0;
4608 ucstr
[i
].uc_cell
=osstr
[i
];
4610 UNIVERSAL_CHARSTRING
us(len
, ucstr
);
4615 OCTETSTRING
TTCN_TeletexString_2_ISO2022(const TeletexString
& p_s
)
4617 return TTCN_UCSTR_2_ISO2022(p_s
);
4620 TeletexString
TTCN_ISO2022_2_TeletexString(const OCTETSTRING
& p_os
)
4622 return TTCN_ISO2022_2_UCSTR(p_os
);
4625 OCTETSTRING
TTCN_VideotexString_2_ISO2022(const VideotexString
& p_s
)
4627 return TTCN_UCSTR_2_ISO2022(p_s
);
4630 VideotexString
TTCN_ISO2022_2_VideotexString(const OCTETSTRING
& p_os
)
4632 return TTCN_ISO2022_2_UCSTR(p_os
);
4635 OCTETSTRING
TTCN_GraphicString_2_ISO2022(const GraphicString
& p_s
)
4637 return TTCN_UCSTR_2_ISO2022(p_s
);
4640 GraphicString
TTCN_ISO2022_2_GraphicString(const OCTETSTRING
& p_os
)
4642 return TTCN_ISO2022_2_UCSTR(p_os
);
4645 OCTETSTRING
TTCN_GeneralString_2_ISO2022(const GeneralString
& p_s
)
4647 return TTCN_UCSTR_2_ISO2022(p_s
);
4650 GeneralString
TTCN_ISO2022_2_GeneralString(const OCTETSTRING
& p_os
)
4652 return TTCN_ISO2022_2_UCSTR(p_os
);