Update README.linux
[deliverable/titan.core.git] / core / Universal_charstring.cc
CommitLineData
970ed795
EL
1///////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2000-2014 Ericsson Telecom AB
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include "Universal_charstring.hh"
9
10#include "../common/dbgnew.hh"
11#include "../common/memory.h"
12#include "../common/pattern.hh"
13#include "../common/Quadruple.hh"
14#include "Integer.hh"
15#include "Octetstring.hh"
16#include "String_struct.hh"
17#include "Param_Types.hh"
18#include "Error.hh"
19#include "Logger.hh"
20#include "Encdec.hh"
21#include "Addfunc.hh" // for unichar2int
a38c6d4c 22#include "TEXT.hh"
970ed795
EL
23#include <string>
24#include <iostream>
25#include <stdint.h>
26
27#define ERRMSG_BUFSIZE 500
28
29// global function for universal_char comparison
30
31boolean operator==(const universal_char& left_value,
32 const universal_char& right_value)
33{
34 return left_value.uc_group == right_value.uc_group &&
35 left_value.uc_plane == right_value.uc_plane &&
36 left_value.uc_row == right_value.uc_row &&
37 left_value.uc_cell == right_value.uc_cell;
38}
39
40boolean operator<(const universal_char& left_value,
41 const universal_char& right_value)
42{
43 if (left_value.uc_group < right_value.uc_group) return TRUE;
44 else if (left_value.uc_group == right_value.uc_group) {
45 if (left_value.uc_plane < right_value.uc_plane) return TRUE;
46 else if (left_value.uc_plane == right_value.uc_plane) {
47 if (left_value.uc_row < right_value.uc_row) return TRUE;
48 else if (left_value.uc_row == right_value.uc_row) {
49 if (left_value.uc_cell < right_value.uc_cell) return TRUE;
50 else return FALSE;
51 } else return FALSE;
52 } else return FALSE;
53 } else return FALSE;
54}
55
56/** The amount of memory needed for a string containing n characters. */
57#define MEMORY_SIZE(n) (sizeof(universal_charstring_struct) + \
58 ((n) - 1) * sizeof(universal_char))
59
60// member functions of class UNIVERSAL_CHARSTRING
61
62/** Allocate space for n characters.
63 *
64 * @param n_uchars number of characters needed
65 *
66 * @pre n_uchars >= 0
67 *
68 * If n_uchars is 0, no memory is allocated and a reference to the
69 * "empty string" is used instead.
70 *
71 * Otherwise, space for n_uchars is allocated (no terminating null).
72 *
73 * @note If the string is not empty, this will leak memory.
74 * Probably clean_up() should have been called before.
75 */
76void UNIVERSAL_CHARSTRING::init_struct(int n_uchars)
77{
78 if (n_uchars < 0) {
79 val_ptr = NULL;
80 TTCN_error("Initializing a universal charstring with a negative length.");
81 } else if (n_uchars == 0) {
82 /* This will represent the empty strings so they won't need allocated
83 * memory, this delays the memory allocation until it is really needed.
84 */
85 static universal_charstring_struct empty_string =
86 { 1, 0, { { '\0', '\0', '\0', '\0' } } };
87 val_ptr = &empty_string;
88 empty_string.ref_count++;
89 } else {
90 val_ptr = (universal_charstring_struct*)Malloc(MEMORY_SIZE(n_uchars));
91 val_ptr->ref_count = 1;
92 val_ptr->n_uchars = n_uchars;
93 }
94}
95
96void UNIVERSAL_CHARSTRING::copy_value()
97{
98 if (val_ptr == NULL || val_ptr->n_uchars <= 0)
99 TTCN_error("Internal error: Invalid internal data structure when copying "
100 "the memory area of a universal charstring value.");
101 if (val_ptr->ref_count > 1) {
102 universal_charstring_struct *old_ptr = val_ptr;
103 old_ptr->ref_count--;
104 init_struct(old_ptr->n_uchars);
105 memcpy(val_ptr->uchars_ptr, old_ptr->uchars_ptr, old_ptr->n_uchars *
106 sizeof(universal_char));
107 }
108}
109
110void UNIVERSAL_CHARSTRING::clean_up()
111{
112 if (val_ptr != NULL) {
113 if (val_ptr->ref_count > 1) val_ptr->ref_count--;
114 else if (val_ptr->ref_count == 1) Free(val_ptr);
115 else TTCN_error("Internal error: Invalid reference counter in a universal "
116 "charstring value.");
117 val_ptr = NULL;
118 } else
119 cstr.clean_up();
120}
121
122UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars, bool cstring)
123: val_ptr(NULL), cstr(cstring ? n_uchars : 0), charstring(cstring)
124{
125 if (!charstring)
126 init_struct(n_uchars);
127}
128
129UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING()
130: val_ptr(NULL), cstr(0), charstring(false)
131{}
132
133UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(unsigned char uc_group,
134 unsigned char uc_plane, unsigned char uc_row, unsigned char uc_cell)
135: charstring(false)
136{
137 init_struct(1);
138 val_ptr->uchars_ptr[0].uc_group = uc_group;
139 val_ptr->uchars_ptr[0].uc_plane = uc_plane;
140 val_ptr->uchars_ptr[0].uc_row = uc_row;
141 val_ptr->uchars_ptr[0].uc_cell = uc_cell;
142}
143
144UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
145 (const universal_char& other_value)
146: cstr(0), charstring(false)
147{
148 init_struct(1);
149 val_ptr->uchars_ptr[0] = other_value;
150}
151
152UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_uchars,
153 const universal_char *uchars_ptr)
154: cstr(0), charstring(false)
155{
156 init_struct(n_uchars);
157 memcpy(val_ptr->uchars_ptr, uchars_ptr, n_uchars * sizeof(universal_char));
158}
159
160UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const char *chars_ptr)
161: val_ptr(NULL), cstr(chars_ptr), charstring(true)
162{
163}
164
165UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(int n_chars,
166 const char *chars_ptr)
167: val_ptr(NULL), cstr(n_chars, chars_ptr), charstring(true)
168{
169}
170
171UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const CHARSTRING& other_value)
172: val_ptr(NULL), cstr(other_value), charstring(true)
173{
174}
175
176UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
177 (const CHARSTRING_ELEMENT& other_value)
178: val_ptr(NULL), cstr(other_value), charstring(true)
179{
180}
181
182UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
183 (const UNIVERSAL_CHARSTRING& other_value)
184: Base_Type(other_value), charstring(other_value.charstring)
185{
186 other_value.must_bound("Copying an unbound universal charstring value.");
187 if (other_value.charstring) {
188 cstr = other_value.cstr;
189 val_ptr = NULL;
190 } else {
191 val_ptr = other_value.val_ptr;
192 val_ptr->ref_count++;
193 cstr.init_struct(0);
194 }
195}
196
197UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
198 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
199: charstring(other_value.get_uchar().is_char())
200{
201 other_value.must_bound("Initialization of a universal charstring with an "
202 "unbound universal charstring element.");
203 if (charstring) {
a38c6d4c 204 cstr = CHARSTRING((const char)(other_value.get_uchar().uc_cell));
970ed795
EL
205 val_ptr = NULL;
206 } else {
207 init_struct(1);
208 val_ptr->uchars_ptr[0] = other_value.get_uchar();
209 }
210}
211
212UNIVERSAL_CHARSTRING::~UNIVERSAL_CHARSTRING()
213{
214 clean_up();
215}
216
217
218UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING::operator=
219 (const universal_char& other_value)
220{
221 clean_up();
222 if (other_value.is_char()) {
223 cstr = CHARSTRING(other_value.uc_cell);
224 charstring = true;
225 } else {
226 charstring = false;
227 init_struct(1);
228 val_ptr->uchars_ptr[0] = other_value;
229 cstr.init_struct(0);
230 }
231 return *this;
232}
233
234UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING::operator=
235 (const char* other_value)
236{
237 if (!charstring) {
238 clean_up();
239 charstring = true;
240 }
241 cstr = other_value;
242 return *this;
243}
244
245UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING::operator=
246 (const CHARSTRING& other_value)
247{
248 if (!charstring) {
249 clean_up();
250 charstring = true;
251 }
252 cstr = other_value;
253 return *this;
254}
255
256UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING::operator=
257 (const CHARSTRING_ELEMENT& other_value)
258{
259 if (!charstring) {
260 clean_up();
261 charstring = true;
262 }
263 cstr = other_value;
264 return *this;
265}
266
267UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING::operator=
268 (const UNIVERSAL_CHARSTRING& other_value)
269{
270 other_value.must_bound("Assignment of an unbound universal charstring "
271 "value.");
272 if (&other_value != this) {
273 clean_up();
274 if (other_value.charstring) {
275 cstr = other_value.cstr;
276 } else {
277 val_ptr = other_value.val_ptr;
278 val_ptr->ref_count++;
279 cstr.clean_up();
280 cstr.init_struct(0);
281 }
282 charstring = other_value.charstring;
283 }
284 return *this;
285}
286
287UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING::operator=
288 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
289{
290 other_value.must_bound("Assignment of an unbound universal charstring "
291 "element to a universal charstring.");
292 if (other_value.str_val.charstring) {
293 char c = other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
294 clean_up();
295 cstr = CHARSTRING(c);
296 charstring = true;
297 } else {
298 universal_char uchar_value = other_value.get_uchar();
299 clean_up();
300 init_struct(1);
301 val_ptr->uchars_ptr[0] = uchar_value;
302 charstring = false;
303 }
304 return *this;
305}
306
307boolean UNIVERSAL_CHARSTRING::operator==
308 (const universal_char& other_value) const
309{
310 must_bound("The left operand of comparison is an unbound universal "
311 "charstring value.");
312 if (charstring) {
313 return cstr.lengthof() == 1 && other_value.uc_group == 0
314 && other_value.uc_plane == 0 && other_value.uc_row == 0
315 && other_value.uc_cell == (cbyte)cstr.val_ptr->chars_ptr[0];
316 }
317 if (val_ptr->n_uchars != 1) return FALSE;
318 else return val_ptr->uchars_ptr[0] == other_value;
319}
320
321boolean UNIVERSAL_CHARSTRING::operator==(const char* other_value) const
322{
323 must_bound("The left operand of comparison is an unbound universal "
324 "charstring value.");
325 if (charstring)
326 return cstr == other_value;
327 else {
328 int n_chars;
329 if (other_value == NULL) n_chars = 0;
330 else n_chars = strlen(other_value);
331 if (val_ptr->n_uchars != n_chars) return FALSE;
332 for (int i = 0; i < n_chars; i++) {
333 if (val_ptr->uchars_ptr[i].uc_group != 0 ||
334 val_ptr->uchars_ptr[i].uc_plane != 0 ||
335 val_ptr->uchars_ptr[i].uc_row != 0 ||
336 val_ptr->uchars_ptr[i].uc_cell != (cbyte)other_value[i]) return FALSE;
337 }
338 }
339 return TRUE;
340}
341
342boolean UNIVERSAL_CHARSTRING::operator==
343 (const CHARSTRING& other_value) const
344{
345 must_bound("The left operand of comparison is an unbound universal "
346 "charstring value.");
347 other_value.must_bound("The right operand of comparison is an unbound "
348 "charstring value.");
349 if (charstring)
350 return cstr == other_value;
351 if (val_ptr->n_uchars != other_value.val_ptr->n_chars) return FALSE;
352 for (int i = 0; i < val_ptr->n_uchars; i++) {
353 if (val_ptr->uchars_ptr[i].uc_group != 0 ||
354 val_ptr->uchars_ptr[i].uc_plane != 0 ||
355 val_ptr->uchars_ptr[i].uc_row != 0 ||
356 val_ptr->uchars_ptr[i].uc_cell !=(cbyte)other_value.val_ptr->chars_ptr[i])
357 return FALSE;
358 }
359 return TRUE;
360}
361
362boolean UNIVERSAL_CHARSTRING::operator==
363 (const CHARSTRING_ELEMENT& other_value) const
364{
365 must_bound("The left operand of comparison is an unbound universal "
366 "charstring value.");
367 other_value.must_bound("The right operand of comparison is an unbound "
368 "charstring element.");
369 if (charstring)
370 return cstr == other_value;
371 if (val_ptr->n_uchars != 1) return FALSE;
372 else return val_ptr->uchars_ptr[0].uc_group == 0 &&
373 val_ptr->uchars_ptr[0].uc_plane == 0 &&
374 val_ptr->uchars_ptr[0].uc_row == 0 &&
375 val_ptr->uchars_ptr[0].uc_cell == (cbyte)other_value.get_char();
376}
377
378boolean UNIVERSAL_CHARSTRING::operator==
379 (const UNIVERSAL_CHARSTRING& other_value) const
380{
381 must_bound("The left operand of comparison is an unbound universal "
382 "charstring value.");
383 other_value.must_bound("The right operand of comparison is an unbound "
384 "universal charstring value.");
385 if (charstring)
386 return cstr == other_value;
387 else if (other_value.charstring)
388 return other_value.cstr == *this;
389 if (val_ptr->n_uchars != other_value.val_ptr->n_uchars) return FALSE;
390 for (int i = 0; i < val_ptr->n_uchars; i++) {
391 if (val_ptr->uchars_ptr[i] != other_value.val_ptr->uchars_ptr[i])
392 return FALSE;
393 }
394 return TRUE;
395}
396
397boolean UNIVERSAL_CHARSTRING::operator==
398 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
399{
400 must_bound("The left operand of comparison is an unbound universal "
401 "charstring value.");
402 other_value.must_bound("The right operand of comparison is an unbound "
403 "universal charstring element.");
404 if (charstring)
405 return cstr == other_value;
406 if (val_ptr->n_uchars != 1) return FALSE;
407 else return val_ptr->uchars_ptr[0] == other_value.get_uchar();
408}
409
410UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+
411 (const universal_char& other_value) const
412{
413 must_bound("The left operand of concatenation is an unbound universal "
414 "charstring value.");
415 if (charstring) {
416 if (other_value.is_char()) {
417 UNIVERSAL_CHARSTRING ret_val(cstr.lengthof() + 1, true);
418 memcpy(ret_val.cstr.val_ptr->chars_ptr, cstr.val_ptr->chars_ptr,
419 cstr.val_ptr->n_chars);
420 ret_val.cstr.val_ptr->chars_ptr[cstr.val_ptr->n_chars] =
421 other_value.uc_cell;
422 return ret_val;
423 } else {
424 UNIVERSAL_CHARSTRING ret_val(cstr.lengthof() + 1);
425 for (int i = 0; i < cstr.val_ptr->n_chars; ++i) {
426 universal_char& uc = ret_val.val_ptr->uchars_ptr[i];
427 uc.uc_group = uc.uc_plane = uc.uc_row = 0;
428 uc.uc_cell = cstr.val_ptr->chars_ptr[i];
429 }
430 ret_val.val_ptr->uchars_ptr[cstr.val_ptr->n_chars] = other_value;
431 return ret_val;
432 }
433 }
434 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars + 1);
435 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr,
436 val_ptr->n_uchars * sizeof(universal_char));
437 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars] = other_value;
438 return ret_val;
439}
440
441UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+
442 (const char* other_value) const
443{
444 must_bound("The left operand of concatenation is an unbound universal "
445 "charstring value.");
446 int other_len;
447 if (other_value == NULL) other_len = 0;
448 else other_len = strlen(other_value);
449 if (other_len == 0) return *this;
450 if (charstring) {
451 UNIVERSAL_CHARSTRING ret_val(cstr.lengthof() + other_len, true);
452 memcpy(ret_val.cstr.val_ptr->chars_ptr, cstr.val_ptr->chars_ptr,
453 cstr.val_ptr->n_chars);
454 memcpy(ret_val.cstr.val_ptr->chars_ptr + cstr.val_ptr->n_chars,
455 other_value, other_len);
456 return ret_val;
457 }
458 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars + other_len);
459 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr,
460 val_ptr->n_uchars * sizeof(universal_char));
461 for (int i = 0; i < other_len; i++) {
462 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_group = 0;
463 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_plane = 0;
464 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_row = 0;
465 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_cell = other_value[i];
466 }
467 return ret_val;
468}
469
470UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+
471 (const CHARSTRING& other_value) const
472{
473 must_bound("The left operand of concatenation is an unbound universal "
474 "charstring value.");
475 other_value.must_bound("The right operand of concatenation is an unbound "
476 "charstring value.");
477 if (other_value.val_ptr->n_chars == 0) return *this;
478 if (charstring) {
479 UNIVERSAL_CHARSTRING ret_val(cstr.lengthof() + other_value.val_ptr->n_chars,
480 true);
481 memcpy(ret_val.cstr.val_ptr->chars_ptr, cstr.val_ptr->chars_ptr,
482 cstr.val_ptr->n_chars);
483 memcpy(ret_val.cstr.val_ptr->chars_ptr + cstr.val_ptr->n_chars,
484 other_value.val_ptr->chars_ptr, other_value.val_ptr->n_chars);
485 return ret_val;
486 }
487 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars +
488 other_value.val_ptr->n_chars);
489 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr,
490 val_ptr->n_uchars * sizeof(universal_char));
491 for (int i = 0; i < other_value.val_ptr->n_chars; i++) {
492 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_group = 0;
493 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_plane = 0;
494 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_row = 0;
495 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars + i].uc_cell =
496 other_value.val_ptr->chars_ptr[i];
497 }
498 return ret_val;
499}
500
501UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+
502 (const CHARSTRING_ELEMENT& other_value) const
503{
504 must_bound("The left operand of concatenation is an unbound universal "
505 "charstring value.");
506 other_value.must_bound("The right operand of concatenation is an unbound "
507 "charstring element.");
508 if (charstring) {
509 UNIVERSAL_CHARSTRING ret_val(cstr.lengthof() + 1, true);
510 memcpy(ret_val.cstr.val_ptr->chars_ptr, cstr.val_ptr->chars_ptr,
511 cstr.val_ptr->n_chars);
512 ret_val.cstr.val_ptr->chars_ptr[cstr.val_ptr->n_chars] =
513 other_value.get_char();
514 return ret_val;
515 }
516 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars + 1);
517 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr,
518 val_ptr->n_uchars * sizeof(universal_char));
519 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars].uc_group = 0;
520 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars].uc_plane = 0;
521 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars].uc_row = 0;
522 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars].uc_cell =
523 other_value.get_char();
524 return ret_val;
525}
526
527UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+
528 (const UNIVERSAL_CHARSTRING& other_value) const
529{
530 must_bound("The left operand of concatenation is an unbound universal "
531 "charstring value.");
532 other_value.must_bound("The right operand of concatenation is an unbound "
533 "universal charstring value.");
534 if (charstring) {
535 if (cstr.val_ptr->n_chars == 0)
536 return other_value;
537 if (other_value.charstring) {
538 if (other_value.cstr.val_ptr->n_chars == 0)
539 return *this;
540 UNIVERSAL_CHARSTRING ret_val(cstr.val_ptr->n_chars +
541 other_value.cstr.val_ptr->n_chars, true);
542 memcpy(ret_val.cstr.val_ptr->chars_ptr, cstr.val_ptr->chars_ptr,
543 cstr.val_ptr->n_chars);
544 memcpy(ret_val.cstr.val_ptr->chars_ptr + cstr.val_ptr->n_chars,
545 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
546 return ret_val;
547 } else {
548 if (other_value.val_ptr->n_uchars == 0)
549 return *this;
550 UNIVERSAL_CHARSTRING ret_val(cstr.val_ptr->n_chars +
551 other_value.val_ptr->n_uchars);
552 for (int i = 0; i < cstr.val_ptr->n_chars; i++) {
553 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
554 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
555 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
556 ret_val.val_ptr->uchars_ptr[i].uc_cell = cstr.val_ptr->chars_ptr[i];
557 }
558 memcpy(ret_val.val_ptr->uchars_ptr + cstr.val_ptr->n_chars,
559 other_value.val_ptr->uchars_ptr, other_value.val_ptr->n_uchars * sizeof(universal_char));
560 return ret_val;
561 }
562 } else {
563 if (other_value.charstring) {
564 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars + other_value.cstr.val_ptr->n_chars);
565 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr, val_ptr->n_uchars * sizeof(universal_char));
566 for (int i = val_ptr->n_uchars; i < val_ptr->n_uchars + other_value.cstr.val_ptr->n_chars; i++) {
567 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
568 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
569 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
570 ret_val.val_ptr->uchars_ptr[i].uc_cell = other_value.cstr.val_ptr->chars_ptr[i-val_ptr->n_uchars];
571 }
572 return ret_val;
573 } else {
574 if (val_ptr->n_uchars == 0) return other_value;
575 if (other_value.val_ptr->n_uchars == 0) return *this;
576 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars +
577 other_value.val_ptr->n_uchars);
578 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr,
579 val_ptr->n_uchars * sizeof(universal_char));
580 memcpy(ret_val.val_ptr->uchars_ptr + val_ptr->n_uchars,
581 other_value.val_ptr->uchars_ptr,
582 other_value.val_ptr->n_uchars * sizeof(universal_char));
583 return ret_val;
584 }
585 }
586}
587
588UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator+
589 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
590{
591 must_bound("The left operand of concatenation is an unbound universal "
592 "charstring value.");
593 other_value.must_bound("The right operand of concatenation is an unbound "
594 "universal charstring element.");
595 bool other_ischar = other_value.str_val.charstring;
596 if (charstring) {
597 if (other_ischar) {
598 UNIVERSAL_CHARSTRING ret_val(cstr.val_ptr->n_chars + 1, true);
599 memcpy(ret_val.cstr.val_ptr->chars_ptr, cstr.val_ptr->chars_ptr,
600 cstr.val_ptr->n_chars);
601 ret_val.cstr.val_ptr->chars_ptr[cstr.val_ptr->n_chars] =
602 other_value.get_uchar().uc_cell;
603 return ret_val;
604 }
605 UNIVERSAL_CHARSTRING ret_val(cstr.val_ptr->n_chars + 1);
606 for (int i = 0; i < cstr.val_ptr->n_chars; i++) {
607 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
608 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
609 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
610 ret_val.val_ptr->uchars_ptr[i].uc_cell = cstr.val_ptr->chars_ptr[i];
611 }
612 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars] = other_value.get_uchar();
613 return ret_val;
614 } else {
615 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars + 1);
616 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr,
617 val_ptr->n_uchars * sizeof(universal_char));
618 if (other_ischar) {
619 universal_char& uc = ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars];
620 uc.uc_group = uc.uc_plane = uc.uc_row = 0;
621 uc.uc_cell = other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
622 } else
623 ret_val.val_ptr->uchars_ptr[val_ptr->n_uchars] = other_value.get_uchar();
624 return ret_val;
625 }
626}
627
628UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator<<=
629 (int rotate_count) const
630{
631 must_bound("The left operand of rotate left operator is an unbound "
632 "universal charstring value.");
633
634 if (charstring)
635 return cstr <<= rotate_count;
636
637 if (val_ptr->n_uchars == 0) return *this;
638 if (rotate_count >= 0) {
639 rotate_count %= val_ptr->n_uchars;
640 if (rotate_count == 0) return *this;
641 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars);
642 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr + rotate_count,
643 (val_ptr->n_uchars - rotate_count) * sizeof(universal_char));
644 memcpy(ret_val.val_ptr->uchars_ptr + val_ptr->n_uchars - rotate_count,
645 val_ptr->uchars_ptr, rotate_count * sizeof(universal_char));
646 return ret_val;
647 } else return *this >>= (-rotate_count);
648}
649
650UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator<<=
651 (const INTEGER& rotate_count) const
652{
653 rotate_count.must_bound("The right operand of rotate left operator is an "
654 "unbound integer value.");
655 return *this <<= (int)rotate_count;
656}
657
658UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator>>=
659 (int rotate_count) const
660{
661 must_bound("The left operand of rotate right operator is an unbound "
662 "universal charstring value.");
663
664 if (charstring)
665 return cstr >>= rotate_count;
666
667 if (val_ptr->n_uchars == 0) return *this;
668 if (rotate_count >= 0) {
669 rotate_count %= val_ptr->n_uchars;
670 if (rotate_count == 0) return *this;
671 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_uchars);
672 memcpy(ret_val.val_ptr->uchars_ptr, val_ptr->uchars_ptr +
673 val_ptr->n_uchars - rotate_count, rotate_count * sizeof(universal_char));
674 memcpy(ret_val.val_ptr->uchars_ptr + rotate_count, val_ptr->uchars_ptr,
675 (val_ptr->n_uchars - rotate_count) * sizeof(universal_char));
676 return ret_val;
677 } else return *this <<= (-rotate_count);
678
679}
680
681UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::operator>>=
682 (const INTEGER& rotate_count) const
683{
684 rotate_count.must_bound("The right operand of rotate right operator is an "
685 "unbound integer value.");
686 return *this >>= (int)rotate_count;
687}
688
689
690UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING::operator[]
691 (int index_value)
692{
693 if (!charstring && val_ptr == NULL && index_value == 0) {
694 init_struct(1);
695 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE, *this, 0);
696 } else {
697 must_bound("Accessing an element of an unbound universal charstring "
698 "value.");
699 if (index_value < 0) TTCN_error("Accessing a universal charstring element "
700 "using a negative index (%d).", index_value);
701 const int n_uchars =
702 charstring ? cstr.val_ptr->n_chars : val_ptr->n_uchars;
703 if (index_value > n_uchars) TTCN_error("Index overflow when accessing a "
704 "universal charstring element: The index is %d, but the string has only "
705 "%d characters.", index_value, n_uchars);
706 if (index_value == n_uchars) {
707 if (charstring)
708 (void)cstr[index_value]; // invoked for side-effect only (incr. length)
709 else {
710 if (val_ptr->ref_count == 1) {
711 val_ptr = (universal_charstring_struct*)
712 Realloc(val_ptr, MEMORY_SIZE(n_uchars + 1));
713 val_ptr->n_uchars++;
714 } else {
715 universal_charstring_struct *old_ptr = val_ptr;
716 old_ptr->ref_count--;
717 init_struct(n_uchars + 1);
718 memcpy(val_ptr->uchars_ptr, old_ptr->uchars_ptr,
719 n_uchars * sizeof(universal_char));
720 }
721 }
722 return UNIVERSAL_CHARSTRING_ELEMENT(FALSE, *this, index_value);
723 } else return UNIVERSAL_CHARSTRING_ELEMENT(TRUE, *this, index_value);
724 }
725}
726
727UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING::operator[]
728 (const INTEGER& index_value)
729{
730 index_value.must_bound("Indexing a universal charstring value with an "
731 "unbound integer value.");
732 return (*this)[(int)index_value];
733}
734
735const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING::operator[]
736 (int index_value) const
737{
738 must_bound("Accessing an element of an unbound universal charstring value.");
739 const int size = charstring ? cstr.val_ptr->n_chars : val_ptr->n_uchars;
740 if (index_value < 0) TTCN_error("Accessing a universal charstring element "
741 "using a negative index (%d).", index_value);
742 else if (index_value >= size) TTCN_error("Index overflow when "
743 "accessing a universal charstring element: The index is %d, but the "
744 "string has only %d characters.", index_value, size);
745 return UNIVERSAL_CHARSTRING_ELEMENT(TRUE,
746 const_cast<UNIVERSAL_CHARSTRING&>(*this), index_value);
747}
748
749const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING::operator[]
750 (const INTEGER& index_value) const
751{
752 index_value.must_bound("Indexing a universal charstring value with an "
753 "unbound integer value.");
754 return (*this)[(int)index_value];
755}
756
757
758UNIVERSAL_CHARSTRING::operator const universal_char*() const
759{
760 must_bound("Casting an unbound universal charstring value to const "
761 "universal_char*.");
762 if (charstring)
763 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
764 return val_ptr->uchars_ptr;
765}
766
767int UNIVERSAL_CHARSTRING::lengthof() const
768{
769 must_bound("Performing lengthof operation on an unbound universal charstring "
770 "value.");
771 if (charstring)
772 return cstr.val_ptr->n_chars;
773 return val_ptr->n_uchars;
774}
775
776char* UNIVERSAL_CHARSTRING::convert_to_regexp_form() const {
777 must_bound("Performing pattern conversion operation on an unbound"
778 "universal charstring value.");
779 int size = (charstring ? cstr.val_ptr->n_chars : val_ptr->n_uchars) * 8 + 1;
780 char* res = static_cast<char*>(Malloc(size));
781 char* ptr = res;
782 res[size-1] = '\0';
783 Quad q;
784 if (charstring)
785 for (int i = 0; i < cstr.val_ptr->n_chars; i++, ptr += 8) {
786 q.set(0, 0, 0, cstr.val_ptr->chars_ptr[i]);
787 Quad::get_hexrepr(q, ptr);
788 }
789 else
790 for (int i = 0; i < val_ptr->n_uchars; i++, ptr += 8) {
791 q.set(val_ptr->uchars_ptr[i].uc_group, val_ptr->uchars_ptr[i].uc_plane,
792 val_ptr->uchars_ptr[i].uc_row, val_ptr->uchars_ptr[i].uc_cell);
793 Quad::get_hexrepr(q, ptr);
794 }
795 return res;
796}
797
798static inline boolean is_printable(const universal_char& uchar)
799{
800 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
801 TTCN_Logger::is_printable(uchar.uc_cell);
802}
803
804CHARSTRING UNIVERSAL_CHARSTRING::get_stringRepr_for_pattern() const {
805 must_bound("Performing pattern conversion operation on an unbound"
806 "universal charstring value.");
807 CHARSTRING ret_val("");
808 if (charstring)
809 for (int i = 0; i < cstr.val_ptr->n_chars; i++) {
810 const char& chr = cstr.val_ptr->chars_ptr[i];
811 if (TTCN_Logger::is_printable(chr))
812 ret_val += chr;
813 else {
814 ret_val += "\\q{0,0,0,";
815 ret_val += int2str(chr);
816 ret_val += "}";
817 }
818 }
819 else
820 for (int i = 0; i < val_ptr->n_uchars; i++) {
821 const universal_char& uchar = val_ptr->uchars_ptr[i];
822 if (is_printable(uchar))
823 ret_val += uchar.uc_cell;
824 else {
825 ret_val += "\\q{";
826 ret_val += int2str(uchar.uc_group);
827 ret_val += ",";
828 ret_val += int2str(uchar.uc_plane);
829 ret_val += ",";
830 ret_val += int2str(uchar.uc_row);
831 ret_val += ",";
832 ret_val += int2str(uchar.uc_cell);
833 ret_val += "}";
834 }
835 }
836 return ret_val;
837}
838
839void UNIVERSAL_CHARSTRING::convert_cstr_to_uni() {
840 init_struct(cstr.lengthof());
841 for (int i = 0; i < cstr.val_ptr->n_chars; i++) {
842 val_ptr->uchars_ptr[i].uc_group = 0;
843 val_ptr->uchars_ptr[i].uc_plane = 0;
844 val_ptr->uchars_ptr[i].uc_row = 0;
845 val_ptr->uchars_ptr[i].uc_cell = cstr.val_ptr->chars_ptr[i];
846 }
847 charstring = false;
848 cstr.clean_up();
849 cstr.init_struct(0);
850}
851
852void UNIVERSAL_CHARSTRING::dump() const
853{
854 if (val_ptr != NULL) {
855 for (int i = 0; i < val_ptr->n_uchars; i++) {
856 const universal_char& uchar = val_ptr->uchars_ptr[i];
857 std::wcout << "uchar[" << i << "] = " << "("
858 << uchar.uc_group << "," << uchar.uc_plane << "," << uchar.uc_row << "," << uchar.uc_cell << ")"<< std::endl;
859 }
860 }
861}
862
863void UNIVERSAL_CHARSTRING::log() const
864{
865 if (charstring) {
866 cstr.log();
867 return;
868 }
869 if (val_ptr != NULL) {
870 expstring_t buffer = 0;
871 enum { INIT, PCHAR, UCHAR } state = INIT;
872 for (int i = 0; i < val_ptr->n_uchars; i++) {
873 const universal_char& uchar = val_ptr->uchars_ptr[i];
874 if (is_printable(uchar)) {
875 // the actual character is printable
876 switch (state) {
877 case UCHAR: // concatenation sign if previous part was not printable
878 buffer = mputstr(buffer, " & ");
879 // no break
880 case INIT: // opening "
881 buffer = mputc(buffer, '"');
882 // no break
883 case PCHAR: // the character itself
884 TTCN_Logger::log_char_escaped(uchar.uc_cell, buffer);
885 break;
886 }
887 state = PCHAR;
888 } else {
889 // the actual character is not printable
890 switch (state) {
891 case PCHAR: // closing " if previous part was printable
892 buffer = mputc(buffer, '"');
893 // no break
894 case UCHAR: // concatenation sign
895 buffer = mputstr(buffer, " & ");
896 // no break
897 case INIT: // the character itself
898 buffer = mputprintf(buffer, "char(%u, %u, %u, %u)",
899 uchar.uc_group, uchar.uc_plane, uchar.uc_row, uchar.uc_cell);
900 break;
901 }
902 state = UCHAR;
903 }
904 }
905 // final steps
906 switch (state) {
907 case INIT: // the string was empty
908 buffer = mputstr(buffer, "\"\"");
909 break;
910 case PCHAR: // last character was printable -> closing "
911 buffer = mputc(buffer, '"');
912 break;
913 default:
914 break;
915 }
916 TTCN_Logger::log_event_str(buffer);
917 Free(buffer);
918 } else {
919 TTCN_Logger::log_event_unbound();
920 }
921}
922
923UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING::from_UTF8_buffer(TTCN_Buffer& p_buff)
924{
925 OCTETSTRING os;
926 p_buff.get_string(os);
927 if ("UTF-8" == get_stringencoding(os)) {
928 UNIVERSAL_CHARSTRING ret;
929 ret.decode_utf8(p_buff.get_len(), p_buff.get_data());
930 return ret;
931 } else {
932 return UNIVERSAL_CHARSTRING(p_buff.get_len(), (const char*)p_buff.get_data());
933 }
934}
935
936void UNIVERSAL_CHARSTRING::set_param(Module_Param& param) {
937 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "universal charstring value");
938
939 switch (param.get_type()) {
940 case Module_Param::MP_Charstring: {
941 switch (param.get_operation_type()) {
942 case Module_Param::OT_ASSIGN:
943 clean_up();
944 // no break
945 case Module_Param::OT_CONCAT: {
946 TTCN_Buffer buff;
947 buff.put_s(param.get_string_size(), (unsigned char*)param.get_string_data());
948 if (is_bound()) {
949 *this = *this + from_UTF8_buffer(buff);
950 } else {
951 *this = from_UTF8_buffer(buff);
952 }
953 break; }
954 default:
955 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
956 }
957 break; }
958 case Module_Param::MP_Universal_Charstring: {
959 switch (param.get_operation_type()) {
960 case Module_Param::OT_ASSIGN:
961 clean_up();
962 // no break
963 case Module_Param::OT_CONCAT: {
964 const Module_Param_Universal_Charstring* ucs_param = dynamic_cast<const Module_Param_Universal_Charstring*>(&param);
965 if (0 != ucs_param) {
966 // The Module_Param_Universal_Charstring class also contains the positions
967 // of all characters added in quadruple form (in char(g,p,r,c) form)
968 // The strings between these positions need to be decoded if they are
969 // in UTF-8 format (the quad characters shouldn't be decoded).
970 int nof_quads = ucs_param->get_nof_quads();
971 universal_char* uchars = (universal_char*)ucs_param->get_string_data();
972 for (int i = 0; i < nof_quads + 1; ++i) {
973 // Each iteration processes the string before a quad and the quad itself
974 // the last iteration processes the string after the last quad
975 // ex. "ccccccQccccccccQcccccccc" => 2 quads at positions 6 and 15
976 // iterations: <-1st-><--2nd--><--3rd->
977 int start_pos = (i == 0) ? 0 : ucs_param->get_quad_pos(i - 1) + 1;
978 int end_pos = (i == nof_quads) ? ucs_param->get_string_size() : ucs_param->get_quad_pos(i);
979 if (end_pos > start_pos) {
980 TTCN_Buffer buff;
981 for (int j = start_pos; j < end_pos; ++j) {
982 buff.put_c(uchars[j].uc_cell);
983 }
984 if (is_bound()) {
985 // Add the string before the quad character
986 *this = *this + from_UTF8_buffer(buff);
987 } else {
988 *this = from_UTF8_buffer(buff);
989 }
990 }
991 if (i != nof_quads) {
992 // Add the quad character itself
993 if (is_bound()) {
994 *this = *this + uchars[end_pos];
995 } else {
996 *this = UNIVERSAL_CHARSTRING(uchars[end_pos]);
997 }
998 }
999 }
1000 } else {
1001 // plan B (should never happen)
1002 if (is_bound()) {
1003 *this = *this + UNIVERSAL_CHARSTRING(param.get_string_size(), (universal_char*)param.get_string_data());
1004 } else {
1005 init_struct(param.get_string_size());
1006 memcpy(val_ptr->uchars_ptr, param.get_string_data(), val_ptr->n_uchars * sizeof(universal_char));
1007 }
1008 }
1009 break; }
1010 default:
1011 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
1012 }
1013 break; }
1014 default:
1015 param.type_error("universal charstring value");
1016 }
1017}
1018
1019void UNIVERSAL_CHARSTRING::encode_text(Text_Buf& text_buf) const
1020{
1021 must_bound("Text encoder: Encoding an unbound universal charstring value.");
1022 if (charstring)
1023 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
1024 text_buf.push_int(val_ptr->n_uchars);
1025 for (int i = 0; i < val_ptr->n_uchars; i++) {
1026 unsigned char buf[4];
1027 buf[0] = val_ptr->uchars_ptr[i].uc_group;
1028 buf[1] = val_ptr->uchars_ptr[i].uc_plane;
1029 buf[2] = val_ptr->uchars_ptr[i].uc_row;
1030 buf[3] = val_ptr->uchars_ptr[i].uc_cell;
1031 text_buf.push_raw(4, buf);
1032 }
1033}
1034
1035void UNIVERSAL_CHARSTRING::decode_text(Text_Buf& text_buf)
1036{
1037 int n_uchars = text_buf.pull_int().get_val();
1038 if (n_uchars < 0) TTCN_error("Text decoder: Negative length was received "
1039 "for a universal charstring.");
1040 clean_up();
1041 charstring = false;
1042 init_struct(n_uchars);
1043 for (int i = 0; i < n_uchars; i++) {
1044 unsigned char buf[4];
1045 text_buf.pull_raw(4, buf);
1046 val_ptr->uchars_ptr[i].uc_group = buf[0];
1047 val_ptr->uchars_ptr[i].uc_plane = buf[1];
1048 val_ptr->uchars_ptr[i].uc_row = buf[2];
1049 val_ptr->uchars_ptr[i].uc_cell = buf[3];
1050 }
1051}
1052
1053void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td,
1054 TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
1055{
1056 va_list pvar;
1057 va_start(pvar, p_coding);
1058 switch(p_coding) {
1059 case TTCN_EncDec::CT_BER: {
1060 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
1061 unsigned BER_coding=va_arg(pvar, unsigned);
1062 BER_encode_chk_coding(BER_coding);
1063 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
1064 tlv->put_in_buffer(p_buf);
1065 ASN_BER_TLV_t::destruct(tlv);
1066 break;}
1067 case TTCN_EncDec::CT_RAW: {
1068 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
1069 TTCN_EncDec_ErrorContext::error_internal
1070 ("No RAW descriptor available for type '%s'.", p_td.name);
1071 break;}
a38c6d4c 1072 case TTCN_EncDec::CT_TEXT: {
1073 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
1074 if(!p_td.text)
1075 TTCN_EncDec_ErrorContext::error_internal
1076 ("No TEXT descriptor available for type '%s'.", p_td.name);
1077 TEXT_encode(p_td,p_buf);
1078 break;}
970ed795
EL
1079 case TTCN_EncDec::CT_XER: {
1080 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
1081 unsigned XER_coding=va_arg(pvar, unsigned);
1082 switch (p_td.asnbasetype) {
1083 case TTCN_Typedescriptor_t::BMPSTRING:
1084 case TTCN_Typedescriptor_t::UNIVERSALSTRING:
1085 XER_coding |= XER_ESCAPE_ENTITIES;
1086 break;
1087 default: // nothing to do
1088 break;
1089 }
af710487 1090 XER_encode(*p_td.xer,p_buf, XER_coding, 0, 0);
970ed795
EL
1091 p_buf.put_c('\n');
1092 break; }
1093 case TTCN_EncDec::CT_JSON: {
1094 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
1095 if(!p_td.json)
1096 TTCN_EncDec_ErrorContext::error_internal
1097 ("No JSON descriptor available for type '%s'.", p_td.name);
1098 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
1099 JSON_encode(p_td, tok);
1100 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
1101 break; }
1102 default:
1103 TTCN_error("Unknown coding method requested to encode type '%s'",
1104 p_td.name);
1105 }
1106 va_end(pvar);
1107}
1108
1109void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td,
1110 TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
1111{
1112 va_list pvar;
1113 va_start(pvar, p_coding);
1114 switch(p_coding) {
1115 case TTCN_EncDec::CT_BER: {
1116 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
1117 unsigned L_form=va_arg(pvar, unsigned);
1118 ASN_BER_TLV_t tlv;
1119 BER_decode_str2TLV(p_buf, tlv, L_form);
1120 BER_decode_TLV(p_td, tlv, L_form);
1121 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
1122 break;}
1123 case TTCN_EncDec::CT_RAW: {
1124 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
1125 TTCN_EncDec_ErrorContext::error_internal
1126 ("No RAW descriptor available for type '%s'.", p_td.name);
1127 break;}
a38c6d4c 1128 case TTCN_EncDec::CT_TEXT: {
1129 Limit_Token_List limit;
1130 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
1131 if(!p_td.text)
1132 TTCN_EncDec_ErrorContext::error_internal
1133 ("No TEXT descriptor available for type '%s'.", p_td.name);
1134 const unsigned char *b=p_buf.get_data();
1135 if(b[p_buf.get_len()-1]!='\0'){
1136 p_buf.set_pos(p_buf.get_len());
1137 p_buf.put_zero(8,ORDER_LSB);
1138 p_buf.rewind();
1139 }
1140 if(TEXT_decode(p_td,p_buf,limit)<0)
1141 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
1142 "Can not decode type '%s', because invalid or incomplete"
1143 " message was received"
1144 , p_td.name);
1145 break;}
970ed795
EL
1146 case TTCN_EncDec::CT_XER : {
1147 unsigned XER_coding=va_arg(pvar, unsigned);
1148 XmlReaderWrap reader(p_buf);
1149 int success = reader.Read();
1150 for (; success==1; success=reader.Read()) {
1151 int type = reader.NodeType();
1152 if (type==XML_READER_TYPE_ELEMENT)
1153 break;
1154 }
af710487 1155 XER_decode(*p_td.xer, reader, XER_coding, 0);
970ed795
EL
1156 size_t bytes = reader.ByteConsumed();
1157 p_buf.set_pos(bytes);
1158 break; }
1159 case TTCN_EncDec::CT_JSON: {
1160 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
1161 if(!p_td.json)
1162 TTCN_EncDec_ErrorContext::error_internal
1163 ("No JSON descriptor available for type '%s'.", p_td.name);
1164 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
1165 if(JSON_decode(p_td, tok, false)<0)
1166 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
1167 "Can not decode type '%s', because invalid or incomplete"
1168 " message was received"
1169 , p_td.name);
1170 p_buf.set_pos(tok.get_buf_pos());
1171 break;}
1172 default:
1173 TTCN_error("Unknown coding method requested to decode type '%s'",
1174 p_td.name);
1175 }
1176 va_end(pvar);
1177}
1178
1179ASN_BER_TLV_t*
1180UNIVERSAL_CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
1181 unsigned p_coding) const
1182{
1183 if (charstring)
1184 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
1185 BER_chk_descr(p_td);
1186 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
1187 if(!new_tlv) {
1188 TTCN_Buffer buf;
1189 switch(p_td.asnbasetype) {
1190 case TTCN_Typedescriptor_t::TELETEXSTRING:
1191 buf.put_os(TTCN_TeletexString_2_ISO2022(*this));
1192 break;
1193 case TTCN_Typedescriptor_t::VIDEOTEXSTRING:
1194 buf.put_os(TTCN_VideotexString_2_ISO2022(*this));
1195 break;
1196 case TTCN_Typedescriptor_t::GRAPHICSTRING:
1197 buf.put_os(TTCN_GraphicString_2_ISO2022(*this));
1198 break;
1199 case TTCN_Typedescriptor_t::GENERALSTRING:
1200 buf.put_os(TTCN_GeneralString_2_ISO2022(*this));
1201 break;
1202 case TTCN_Typedescriptor_t::UNIVERSALSTRING:
1203 for(int i=0; i<val_ptr->n_uchars; i++) {
1204 buf.put_c(val_ptr->uchars_ptr[i].uc_group);
1205 buf.put_c(val_ptr->uchars_ptr[i].uc_plane);
1206 buf.put_c(val_ptr->uchars_ptr[i].uc_row);
1207 buf.put_c(val_ptr->uchars_ptr[i].uc_cell);
1208 }
1209 break;
1210 case TTCN_Typedescriptor_t::BMPSTRING:
1211 for(int i=0; i<val_ptr->n_uchars; i++) {
1212 buf.put_c(val_ptr->uchars_ptr[i].uc_row);
1213 buf.put_c(val_ptr->uchars_ptr[i].uc_cell);
1214 }
1215 break;
1216 case TTCN_Typedescriptor_t::UTF8STRING:
1217 encode_utf8(buf);
1218 break;
1219 default:
1220 TTCN_EncDec_ErrorContext::error_internal
1221 ("Missing/wrong basetype info for type '%s'.", p_td.name);
1222 } // switch
1223 new_tlv=BER_encode_TLV_OCTETSTRING
1224 (p_coding, buf.get_read_len(), buf.get_read_data());
1225 }
1226 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
1227 return new_tlv;
1228}
a38c6d4c 1229int UNIVERSAL_CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
1230 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
1231{
1232 int decoded_length = 0;
1233 int str_len = 0;
1234 clean_up();
1235 if (p_td.text->begin_decode) {
1236 int tl;
1237 if ((tl = p_td.text->begin_decode->match_begin(buff)) < 0) {
1238 if (no_err) return -1;
1239 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
1240 "The specified token '%s' not found for '%s': ",
1241 (const char*) *(p_td.text->begin_decode), p_td.name);
1242 return 0;
1243 }
1244 decoded_length += tl;
1245 buff.increase_pos(tl);
1246 }
1247 // never return "not enough bits"
1248 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
1249
1250 if (p_td.text->select_token) {
1251 int tl;
1252 if ((tl = p_td.text->select_token->match_begin(buff)) < 0) {
1253 if (no_err) return -1;
1254 else tl = 0;
1255 }
1256 str_len = tl;
1257 }
1258 // The length restriction needs some more work
1259/* else if ( p_td.text->val.parameters
1260 && p_td.text->val.parameters->decoding_params.min_length != -1) {
1261 str_len = p_td.text->val.parameters->decoding_params.min_length;
1262 }*/
1263 else if (p_td.text->end_decode) {
1264 int tl;
1265 if ((tl = p_td.text->end_decode->match_first(buff)) < 0) {
1266 if (no_err) return -1;
1267 else tl = 0;
1268 }
1269 str_len = tl;
1270 }
1271 else if (limit.has_token()) {
1272 int tl;
1273 if ((tl = limit.match(buff)) < 0) tl = buff.get_read_len() - 1;
1274 str_len = tl;
1275 }
1276 else {
1277 str_len = buff.get_read_len() - 1;
1278 }
1279
1280// only utf8 is supported now.
1281 decode_utf8(str_len,buff.get_read_data());
1282
1283 decoded_length += str_len;
1284 buff.increase_pos(str_len);
1285
1286// Case conversion is an another study
1287// and it is locale dependent
1288/* if ( p_td.text->val.parameters
1289 && p_td.text->val.parameters->decoding_params.convert != 0) {
1290 if (p_td.text->val.parameters->decoding_params.convert == 1) {
1291 for (int a = 0; a < str_len; a++) {
1292 val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
1293 }
1294 }
1295 else {
1296 for (int a = 0; a < str_len; a++) {
1297 val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
1298 }
1299 }
1300 }*/
1301 if (p_td.text->end_decode) {
1302 int tl;
1303 if ((tl = p_td.text->end_decode->match_begin(buff)) < 0) {
1304 if (no_err) return -1;
1305 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
1306 "The specified token '%s' not found for '%s': ",
1307 (const char*) *(p_td.text->end_decode), p_td.name);
1308 return 0;
1309 }
1310 decoded_length += tl;
1311 buff.increase_pos(tl);
1312 }
1313 return decoded_length;
1314}
1315
1316int UNIVERSAL_CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1317 TTCN_Buffer& buff) const{
1318 int encoded_length=0;
1319 if(p_td.text->begin_encode){
1320 buff.put_cs(*p_td.text->begin_encode);
1321 encoded_length+=p_td.text->begin_encode->lengthof();
1322 }
1323 if(!is_bound()) {
1324 TTCN_EncDec_ErrorContext::error
1325 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
1326 if(p_td.text->end_encode){
1327 buff.put_cs(*p_td.text->end_encode);
1328 encoded_length+=p_td.text->end_encode->lengthof();
1329 }
1330 return encoded_length;
1331 }
1332
1333// The length restriction and case conversion will be added later
1334// if(p_td.text->val.parameters==NULL){
1335
1336 int base_size=buff.get_len(); // strore the current length of the data
1337 // in the buffer
1338
1339 encode_utf8(buff);
1340
1341 encoded_length+=buff.get_len()-base_size; // calculate the number of the
1342 // stored octets
1343
1344/* } else {
1345 int chars_before=0;
1346 int chars_after=0;
1347 if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
1348 switch(p_td.text->val.parameters->coding_params.just){
1349 case -1: //left
1350 chars_after=p_td.text->
1351 val.parameters->coding_params.min_length-val_ptr->n_chars;
1352 break;
1353 case 0:{ // center
1354 int pad=p_td.text->
1355 val.parameters->coding_params.min_length-val_ptr->n_chars;
1356 chars_after=pad/2;
1357 chars_before=pad-chars_after;
1358 break;
1359 }
1360 case 1: // right
1361 default:
1362 chars_before=p_td.text->
1363 val.parameters->coding_params.min_length-val_ptr->n_chars;
1364 break;
1365 }
1366 }
1367 if(chars_before){
1368 unsigned char* p=NULL;
1369 size_t len=chars_before;
1370 buff.get_end(p,len);
1371 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
1372 buff.increase_length(chars_before);
1373 encoded_length+=chars_before;
1374 }
1375
1376 switch(p_td.text->val.parameters->coding_params.convert){
1377 case -1:{ //lower_case
1378 unsigned char* p=NULL;
1379 size_t len=val_ptr->n_chars;
1380 buff.get_end(p,len);
1381 for(int a=0;a<val_ptr->n_chars;a++)
1382 p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
1383 buff.increase_length(val_ptr->n_chars);
1384 break;
1385 }
1386 case 0:{ // no conversion
1387 buff.put_cs(*this);
1388 break;
1389 }
1390 case 1: // upper_case
1391 default:
1392 {
1393 unsigned char* p=NULL;
1394 size_t len=val_ptr->n_chars;
1395 buff.get_end(p,len);
1396 for(int a=0;a<val_ptr->n_chars;a++)
1397 p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
1398 buff.increase_length(val_ptr->n_chars);
1399 break;
1400 }
1401 }
1402 encoded_length+=val_ptr->n_chars;
1403
1404 if(chars_after){
1405 unsigned char* p=NULL;
1406 size_t len=chars_after;
1407 buff.get_end(p,len);
1408 for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
1409 buff.increase_length(chars_after);
1410 encoded_length+=chars_after;
1411 }
1412 }
1413*/
1414
1415 if(p_td.text->end_encode){
1416 buff.put_cs(*p_td.text->end_encode);
1417 encoded_length+=p_td.text->end_encode->lengthof();
1418 }
1419 return encoded_length;
1420}
970ed795
EL
1421
1422void UNIVERSAL_CHARSTRING::encode_utf8(TTCN_Buffer& buf, bool addBOM /*= false*/) const
1423{
1424 // Add BOM
1425 if (addBOM) {
1426 buf.put_c(0xEF);
1427 buf.put_c(0xBB);
1428 buf.put_c(0xBF);
1429 }
1430 if (charstring) {
1431 buf.put_s(cstr.val_ptr->n_chars, (unsigned char*)cstr.val_ptr->chars_ptr);
1432 // put_s avoids the check for boundness in put_cs
1433 }
1434 else {
1435 for(int i=0; i<val_ptr->n_uchars; i++) {
1436 unsigned char g=val_ptr->uchars_ptr[i].uc_group;
1437 unsigned char p=val_ptr->uchars_ptr[i].uc_plane;
1438 unsigned char r=val_ptr->uchars_ptr[i].uc_row;
1439 unsigned char c=val_ptr->uchars_ptr[i].uc_cell;
1440 if(g==0x00 && p<=0x1F) {
1441 if(p==0x00) {
1442 if(r==0x00 && c<=0x7F) {
1443 // 1 octet
1444 buf.put_c(c);
1445 } // r
1446 // 2 octets
1447 else if(r<=0x07) {
1448 buf.put_c(0xC0|r<<2|c>>6);
1449 buf.put_c(0x80|(c&0x3F));
1450 } // r
1451 // 3 octets
1452 else {
1453 buf.put_c(0xE0|r>>4);
1454 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1455 buf.put_c(0x80|(c&0x3F));
1456 } // r
1457 } // p
1458 // 4 octets
1459 else {
1460 buf.put_c(0xF0|p>>2);
1461 buf.put_c(0x80|(p<<4&0x30)|r>>4);
1462 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1463 buf.put_c(0x80|(c&0x3F));
1464 } // p
1465 } //g
1466 // 5 octets
1467 else if(g<=0x03) {
1468 buf.put_c(0xF8|g);
1469 buf.put_c(0x80|p>>2);
1470 buf.put_c(0x80|(p<<4&0x30)|r>>4);
1471 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1472 buf.put_c(0x80|(c&0x3F));
1473 } // g
1474 // 6 octets
1475 else {
1476 buf.put_c(0xFC|g>>6);
1477 buf.put_c(0x80|(g&0x3F));
1478 buf.put_c(0x80|p>>2);
1479 buf.put_c(0x80|(p<<4&0x30)|r>>4);
1480 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1481 buf.put_c(0x80|(c&0x3F));
1482 }
1483 } // for i
1484 }
1485}
1486
1487void UNIVERSAL_CHARSTRING::encode_utf16(TTCN_Buffer& buf,
1488 CharCoding::CharCodingType expected_coding) const
1489{
1490 // add BOM
1491 bool isbig = true;
1492 switch (expected_coding) {
1493 case CharCoding::UTF16:
1494 case CharCoding::UTF16BE:
1495 isbig = true;
1496 break;
1497 case CharCoding::UTF16LE:
1498 isbig = false;
1499 break;
1500 default:
1501 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1502 "Unexpected coding type for UTF-16 encoding");
1503 break;
1504 }
1505 buf.put_c(isbig ? 0xFE : 0xFF);
1506 buf.put_c(isbig ? 0xFF : 0xFE);
1507
1508 if (charstring) {
1509 for (int i = 0; i < cstr.val_ptr->n_chars; ++i) {
1510 buf.put_c(isbig ? 0 : cstr.val_ptr->chars_ptr[i]);
1511 buf.put_c(isbig ? cstr.val_ptr->chars_ptr[i] : 0);
1512 }
1513 }
1514 else {
1515 for(int i=0; i<val_ptr->n_uchars; i++) {
1516 unsigned char g=val_ptr->uchars_ptr[i].uc_group;
1517 unsigned char p=val_ptr->uchars_ptr[i].uc_plane;
1518 unsigned char r=val_ptr->uchars_ptr[i].uc_row;
1519 unsigned char c=val_ptr->uchars_ptr[i].uc_cell;
1520 if (g || (0x10 < p)) {
1521 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1522 "Any UCS code (0x%02X%02X%02X%02X) to be encoded into UTF-16 "
1523 "shall not be greater than 0x10FFFF", g, p, r, c);
1524 }
1525 else if (0x00 == g && 0x00 ==p && 0xD8 <= r && 0xDF >= r) {
1526 // Values between 0xD800 and 0xDFFF are specifically reserved for use with UTF-16,
1527 // and don't have any characters assigned to them.
1528 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1529 "Any UCS code (0x%02X%02X) between 0xD800 and 0xDFFF is ill-formed", r,c);
1530 }
1531 else if (0x00 == g && 0x00 == p) {
1532 buf.put_c(isbig ? r : c);
1533 buf.put_c(isbig ? c : r);
1534 }
1535 else if (g || p) { // greater than 0xFFFF it needs surrogates
1536 uint32_t univc = 0, temp = 0;
1537 univc = g;
1538 univc <<= 24;
1539 temp = p;
1540 temp <<= 16;
1541 univc |= temp;
1542 temp = 0;
1543 temp = r;
1544 temp <<= 8;
1545 univc |= temp;
1546 univc |= c; // universal char filled in univc
1547 uint16_t W1 = 0xD800;
1548 uint16_t W2 = 0xDC00;
1549 uint32_t univcmod = univc - 0x10000;
1550 uint16_t WH = univcmod >> 10;
1551 uint16_t WL = univcmod & 0x3ff;
1552 W1 |= WH;
1553 W2 |= WL;
1554 unsigned char uc;
1555 uc = isbig ? W1 >> 8 : W1;
1556 buf.put_c(uc);
1557 uc = isbig ? W1 : W1 >> 8;
1558 buf.put_c(uc);
1559 uc = isbig ? W2 >> 8 : W2;
1560 buf.put_c(uc);
1561 uc = isbig ? W2 : W2 >> 8;
1562 buf.put_c(uc);
1563 }
1564 }
1565 }
1566}
1567
1568void UNIVERSAL_CHARSTRING::encode_utf32(TTCN_Buffer& buf,
1569 CharCoding::CharCodingType expected_coding) const
1570{
1571 bool isbig = true;
1572 switch (expected_coding) {
1573 case CharCoding::UTF32:
1574 case CharCoding::UTF32BE:
1575 isbig = true;
1576 break;
1577 case CharCoding::UTF32LE:
1578 isbig = false;
1579 break;
1580 default:
1581 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1582 "Unexpected coding type for UTF-32 encoding");
1583 break;
1584 }
1585 // add BOM
1586 buf.put_c(isbig ? 0x00 : 0xFF);
1587 buf.put_c(isbig ? 0x00 : 0xFE);
1588 buf.put_c(isbig ? 0xFE : 0x00);
1589 buf.put_c(isbig ? 0xFF : 0x00);
1590
1591 if (charstring) {
1592 for (int i = 0; i < cstr.val_ptr->n_chars; ++i) {
1593 buf.put_c(isbig ? 0 : cstr.val_ptr->chars_ptr[i]);
1594 buf.put_c(0);
1595 buf.put_c(0);
1596 buf.put_c(isbig ? cstr.val_ptr->chars_ptr[i] : 0);
1597 }
1598 }
1599 else {
1600 for(int i = 0; i < val_ptr->n_uchars; ++i) {
1601 unsigned char g=val_ptr->uchars_ptr[i].uc_group;
1602 unsigned char p=val_ptr->uchars_ptr[i].uc_plane;
1603 unsigned char r=val_ptr->uchars_ptr[i].uc_row;
1604 unsigned char c=val_ptr->uchars_ptr[i].uc_cell;
1605 uint32_t DW = g << 8 | p;
1606 DW <<= 8;
1607 DW |= r;
1608 DW <<= 8;
1609 DW |= c;
1610 if (0x0000D800 <= DW && 0x0000DFFF >= DW) {
1611 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1612 "Any UCS code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW);
1613 }
1614 else if (0x0010FFFF < DW) {
1615 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1616 "Any UCS code (0x%08X) greater than 0x0010FFFF is ill-formed", DW);
1617 }
1618 else {
1619 buf.put_c(isbig ? g : c);
1620 buf.put_c(isbig ? p : r);
1621 buf.put_c(isbig ? r : p);
1622 buf.put_c(isbig ? c : g);
1623 }
1624 }
1625 }
1626}
1627
1628#ifdef TITAN_RUNTIME_2
1629//virtual
1630int UNIVERSAL_CHARSTRING::encode_raw(TTCN_Buffer& p_buf) const
1631{
1632 size_t len_before = p_buf.get_len();
1633 encode_utf8(p_buf);
1634 return p_buf.get_len() - len_before;
1635}
1636#endif
1637
1638
1639boolean UNIVERSAL_CHARSTRING::BER_decode_TLV
1640(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv,
1641 unsigned L_form)
1642{
1643 clean_up();
1644 charstring = false;
1645 TTCN_EncDec_ErrorContext ec("While decoding universal charstring type: ");
1646 OCTETSTRING ostr;
1647 if(!ostr.BER_decode_TLV(p_td, p_tlv, L_form)) return FALSE;
1648 int os_len=ostr.lengthof();
1649 int ucs_len;
1650 const unsigned char* os=ostr;
1651 switch(p_td.asnbasetype) {
1652 case TTCN_Typedescriptor_t::TELETEXSTRING:
1653 *this=TTCN_ISO2022_2_TeletexString(ostr);
1654 break;
1655 case TTCN_Typedescriptor_t::VIDEOTEXSTRING:
1656 *this=TTCN_ISO2022_2_VideotexString(ostr);
1657 break;
1658 case TTCN_Typedescriptor_t::GRAPHICSTRING:
1659 *this=TTCN_ISO2022_2_GraphicString(ostr);
1660 break;
1661 case TTCN_Typedescriptor_t::GENERALSTRING:
1662 *this=TTCN_ISO2022_2_GeneralString(ostr);
1663 break;
1664 case TTCN_Typedescriptor_t::UNIVERSALSTRING:
1665 if(os_len%4)
1666 TTCN_EncDec_ErrorContext::error
1667 (TTCN_EncDec::ET_DEC_UCSTR, "Length of UCS-4-coded character"
1668 " string is not multiple of 4.");
1669 ucs_len=os_len/4;
1670 init_struct(ucs_len);
1671 for(int i=0; i<ucs_len; i++) {
1672 val_ptr->uchars_ptr[i].uc_group=os[0];
1673 val_ptr->uchars_ptr[i].uc_plane=os[1];
1674 val_ptr->uchars_ptr[i].uc_row=os[2];
1675 val_ptr->uchars_ptr[i].uc_cell=os[3];
1676 os+=4;
1677 }
1678 break;
1679 case TTCN_Typedescriptor_t::BMPSTRING:
1680 if(os_len%2)
1681 TTCN_EncDec_ErrorContext::error
1682 (TTCN_EncDec::ET_DEC_UCSTR, "Length of UCS-2-coded character"
1683 " string is not multiple of 2.");
1684 ucs_len=os_len/2;
1685 init_struct(ucs_len);
1686 for(int i=0; i<ucs_len; i++) {
1687 val_ptr->uchars_ptr[i].uc_group=0;
1688 val_ptr->uchars_ptr[i].uc_plane=0;
1689 val_ptr->uchars_ptr[i].uc_row=os[0];
1690 val_ptr->uchars_ptr[i].uc_cell=os[1];
1691 os+=2;
1692 }
1693 break;
1694 case TTCN_Typedescriptor_t::UTF8STRING:
1695 decode_utf8(os_len, os);
1696 break;
1697 default:
1698 TTCN_EncDec_ErrorContext::error_internal
1699 ("Missing/wrong basetype info for type '%s'.", p_td.name);
1700 } // switch
1701 return TRUE;
1702}
1703
1704extern void xml_escape(const unsigned int c, TTCN_Buffer& p_buf);
1705
1706int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t& p_td,
af710487 1707 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
970ed795
EL
1708{
1709 if(!is_bound()) {
1710 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1711 "Encoding an unbound UNIVERSAL CHARSTRING value.");
1712 }
1713 if (charstring)
1714 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
1715 int exer = is_exer(flavor |= SIMPLE_TYPE);
1716 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1717 int encoded_length=(int)p_buf.get_len();
1718 bool do_empty_element = val_ptr==NULL || val_ptr->n_uchars == 0;
1719
1720 flavor &= ~XER_RECOF; // universal charstring doesn't care
1721 if (exer && (p_td.xer_bits & ANY_ELEMENT)) {
1722 if (!is_canonical(flavor)) {
1723 // Although ANY_ELEMENT is not canonical, this flag is still used to disable
1724 // indenting in a record/set with EMBED_VALUES
1725 do_indent(p_buf, indent);
1726 }
1727 }
1728 else {
1729 if (do_empty_element && exer && p_td.dfeValue != 0) {
1730 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR,
1731 "An encoded value with DEFAULT-FOR-EMPTY instruction "
1732 "applied should not be empty");
1733 }
1734 if (begin_xml(p_td, p_buf, flavor, indent, do_empty_element) == -1) {
1735 --encoded_length;
1736 }
1737 } // not any_element
1738
1739#define UCH(c) {0,0,0,c}
1740 if (!do_empty_element) {
1741 if (flavor & XER_ESCAPE_ENTITIES) {
1742 for (int i = 0; i < val_ptr->n_uchars; ++i) {
1743 unsigned int ucs4 = unichar2int(val_ptr->uchars_ptr[i]);
1744 xml_escape( ucs4, p_buf );
1745 }
1746 }
1747 else { // UTF-8 needs only to escape the low 32 and these five: <&>
1748 TTCN_Buffer other_buf;
1749 static const universal_char amp[] = { UCH('&'), UCH('a'), UCH('m'),
1750 UCH('p'), UCH(';') };
1751 static const universal_char lt [] = { UCH('&'), UCH('l'), UCH('t'),
1752 UCH(';') };
1753 static const universal_char gt [] = { UCH('&'), UCH('g'), UCH('t'),
1754 UCH(';') };
1755 static const universal_char apos[]= { UCH('&'), UCH('a'), UCH('p'),
1756 UCH('o'), UCH('s'), UCH(';') };
1757 static const universal_char quot[]= { UCH('&'), UCH('q'), UCH('u'),
1758 UCH('o'), UCH('t'), UCH(';') };
1759
1760 static const universal_char escapes[32][6] = {
1761 {UCH('<'), UCH('n'), UCH('u'), UCH('l'), UCH('/'), UCH('>')},
1762 {UCH('<'), UCH('s'), UCH('o'), UCH('h'), UCH('/'), UCH('>')},
1763 {UCH('<'), UCH('s'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1764 {UCH('<'), UCH('e'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1765 {UCH('<'), UCH('e'), UCH('o'), UCH('t'), UCH('/'), UCH('>')},
1766 {UCH('<'), UCH('e'), UCH('n'), UCH('q'), UCH('/'), UCH('>')},
1767 {UCH('<'), UCH('a'), UCH('c'), UCH('k'), UCH('/'), UCH('>')},
1768 {UCH('<'), UCH('b'), UCH('e'), UCH('l'), UCH('/'), UCH('>')},
1769
1770 {UCH('<'), UCH('b'), UCH('s'), UCH('/'), UCH('>')},
1771 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('9'), UCH(';')}, // TAB
1772 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('A'), UCH(';')}, // LF
1773 {UCH('<'), UCH('v'), UCH('t'), UCH('/'), UCH('>')},
1774 {UCH('<'), UCH('f'), UCH('f'), UCH('/'), UCH('>')},
1775 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('D'), UCH(';')}, // CR
1776 {UCH('<'), UCH('s'), UCH('o'), UCH('/'), UCH('>')},
1777 {UCH('<'), UCH('s'), UCH('i'), UCH('/'), UCH('>')},
1778
1779 {UCH('<'), UCH('d'), UCH('l'), UCH('e'), UCH('/'), UCH('>')},
1780 {UCH('<'), UCH('d'), UCH('c'), UCH('1'), UCH('/'), UCH('>')},
1781 {UCH('<'), UCH('d'), UCH('c'), UCH('2'), UCH('/'), UCH('>')},
1782 {UCH('<'), UCH('d'), UCH('c'), UCH('3'), UCH('/'), UCH('>')},
1783 {UCH('<'), UCH('d'), UCH('c'), UCH('4'), UCH('/'), UCH('>')},
1784 {UCH('<'), UCH('n'), UCH('a'), UCH('k'), UCH('/'), UCH('>')},
1785 {UCH('<'), UCH('s'), UCH('y'), UCH('n'), UCH('/'), UCH('>')},
1786 {UCH('<'), UCH('e'), UCH('t'), UCH('b'), UCH('/'), UCH('>')},
1787
1788 {UCH('<'), UCH('c'), UCH('a'), UCH('n'), UCH('/'), UCH('>')},
1789 {UCH('<'), UCH('e'), UCH('m'), UCH('/'), UCH('>')},
1790 {UCH('<'), UCH('s'), UCH('u'), UCH('b'), UCH('/'), UCH('>')},
1791 {UCH('<'), UCH('e'), UCH('s'), UCH('c'), UCH('/'), UCH('>')},
1792 {UCH('<'), UCH('i'), UCH('s'), UCH('4'), UCH('/'), UCH('>')},
1793 {UCH('<'), UCH('i'), UCH('s'), UCH('3'), UCH('/'), UCH('>')},
1794 {UCH('<'), UCH('i'), UCH('s'), UCH('2'), UCH('/'), UCH('>')},
1795 {UCH('<'), UCH('i'), UCH('s'), UCH('1'), UCH('/'), UCH('>')}
1796 };
1797
1798 if (exer && (p_td.xer_bits & ANY_ELEMENT)) { // no escaping
1799 TTCN_EncDec_ErrorContext ec("While checking anyElement: ");
1800 encode_utf8(other_buf);
1801 XmlReaderWrap checker(other_buf);
1802 // Walk through the XML. If it's not well-formed, XmlReaderWrap
1803 // will call TTCN_error => Dynamic testcase error.
1804 while (1 == checker.Read()) {
1805 if (checker.NodeType() == XML_READER_TYPE_ELEMENT &&
1806 (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT))) {
1807 const char* xmlns = (const char*)checker.NamespaceUri();
1808 check_namespace_restrictions(p_td, xmlns);
1809 }
1810 }
1811
1812 // other_buf is already UTF-8, just append it
1813 p_buf.put_buf(other_buf);
1814 }
1815 else if (flavor & ANY_ATTRIBUTES) { // no escaping
1816 encode_utf8(other_buf);
1817 p_buf.put_buf(other_buf);
1818 }
1819 else {
1820 for (int i = 0; i < val_ptr->n_uchars; ++i) {
1821 int char_val = unichar2int(val_ptr->uchars_ptr[i]);
1822 size_t len = 6; // 3 letters + the surrounding '<', '/' and '>'
1823 switch (char_val) {
1824 case '&':
1825 other_buf.put_s(20, &(amp[0].uc_group));
1826 break;
1827
1828 case '<':
1829 other_buf.put_s(16, &(lt[0].uc_group));
1830 break;
1831
1832 case '>':
1833 other_buf.put_s(16, &(gt[0].uc_group));
1834 break;
1835
1836 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1837 // so if they appear in content they must be escaped.
1838 // Currently this happens even if the string is not an attribute.
1839 other_buf.put_s(24, &(apos[0].uc_group));
1840 break;
1841
1842 case '\"': // HR58225
1843 other_buf.put_s(24, &(quot[0].uc_group));
1844 break;
1845
1846 case 8: case 11: case 12: case 14: case 15: case 25:
1847 // the name of these control characters has only two letters
1848 --len;
1849 // no break
1850 case 0: case 1: case 2: case 3: case 4: case 5: case 6:
1851 case 7: case 16: case 17: case 18: case 19: case 20: case 21:
1852 case 22: case 23: case 24: case 26: case 27: case 28: case 29:
1853 case 30: case 31:
1854 other_buf.put_s(len * 4, &(escapes[char_val][0].uc_group));
1855 break;
1856
1857 case 9: case 10: case 13:
1858 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1859 // X.693 20.3.15: TAB,LF,CR also needs to be escaped in ATTRIBUTE
1860 other_buf.put_s(24, &(escapes[char_val][0].uc_group));
1861 break;
1862 } // else fall through
1863 // no break
1864 default:
1865 other_buf.put_s(4, &(val_ptr->uchars_ptr[i].uc_group));
1866 break;
1867 }
1868 } // next
1869 // other_buf contains UCS-4, need to encode it
1870 UNIVERSAL_CHARSTRING cs;
1871 other_buf.get_string(cs);
1872 (cs).encode_utf8(p_buf);
1873 } // not any_element
1874 } // if ESCAPE_ENTITIES
1875
1876 if (exer && (p_td.xer_bits & ANY_ELEMENT) && !is_canonical(flavor)) {
1877 p_buf.put_c('\n');
1878 }
1879 }
1880
1881 end_xml(p_td, p_buf, flavor, indent, do_empty_element);
1882
1883 return (int)p_buf.get_len() - encoded_length;
1884}
1885
1886/* Hashing for xmlcstring representation of control characters.
1887 * This function was generated by gperf 3.0.3
1888 * (GNU perfect hash function generator) from the list of control character
1889 * names, one per line, like this:
1890 *
1891 * nul
1892 * soh
1893 * ...etc...
1894 * is1
1895 *
1896 * See the ASN.1 standard, X.680/2002, clause 11.15.5
1897 */
1898inline
1899static unsigned int
1900hash (register const char *str, register unsigned int len)
1901{
1902 static unsigned char asso_values[] =
1903 {
1904 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1905 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1906 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1907 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1908 104, 104, 104, 104, 104, 104, 104, 104, 104, 1,
1909 60, 55, 45, 104, 104, 104, 104, 104, 104, 104,
1910 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1911 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1912 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1913 104, 104, 104, 104, 104, 104, 104, 10, 10, 50,
1914 40, 15, 0, 104, 6, 15, 104, 1, 5, 10,
1915 0, 20, 104, 15, 0, 0, 30, 104, 0, 104,
1916 20, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1917 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1918 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1919 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1920 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1921 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1922 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1923 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1924 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1925 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1926 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1927 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1928 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1929 104, 104, 104, 104, 104, 104
1930 };
1931 return len + asso_values[(unsigned char)str[len - 1]] +
1932 asso_values[(unsigned char)str[0]];
1933}
1934
1935/* This function was also generated by gperf and hand-edited afterwards.
1936 * The original wordlist[] was an array of strings containing the names of
1937 * the control characters, with empty strings as fillers. These have been
1938 * replaced with the actual numerical values of the control characters,
1939 * with -1 as the filler.
1940 */
1941inline
1942static char
1943in_word_set (const char *str, unsigned int len)
1944{
1945 static char wordlist[] =
1946 {
1947 -1, -1,
1948 12, // FF
1949 22, // SYN
1950 21, // NAK
1951 -1, -1,
1952 10, // LF
1953 0, // NUL
1954 1, // SOH
1955 -1, -1,
1956 8, // BS
1957 26, // SUB
1958 6, // ACK
1959 -1, -1,
1960 15, // SI
1961 7, // BEL
1962 31, // IS1
1963 -1, -1,
1964 14, // SO
1965 2, // STX
1966 -1, -1, -1,
1967 25, // EM
1968 23, // ETB
1969 -1, -1, -1,
1970 11, // VT
1971 5, // ENQ
1972 -1, -1, -1, -1,
1973 3, // ETX
1974 -1, -1, -1, -1,
1975 9, // TAB
1976 17, // DC1
1977 -1, -1, -1,
1978 4, // EOT
1979 -1, -1, -1,
1980 13, // CR
1981 24, // CAN
1982 -1, -1, -1, -1,
1983 16, // DLE
1984 -1, -1, -1, -1,
1985 28, // IS4
1986 -1, -1, -1, -1,
1987 27, // ESC
1988 -1, -1, -1, -1,
1989 29, // IS3
1990 -1, -1, -1, -1,
1991 30, // IS2
1992 -1, -1, -1, -1, -1, -1, -1, -1, -1,
1993 20, // DC4
1994 -1, -1, -1, -1, -1, -1, -1, -1, -1,
1995 19, // DC3
1996 -1, -1, -1, -1,
1997 18 // DC2
1998 };
1999#define MIN_WORD_LENGTH 2
2000#define MAX_WORD_LENGTH 3
2001#define MIN_HASH_VALUE 2
2002#define MAX_HASH_VALUE 103
2003
2004 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2005 {
2006 register int key = hash (str, len);
2007
2008 if (key <= MAX_HASH_VALUE && key >= 0)
2009 {
2010 register const char s = wordlist[key];
2011 return s;
2012 }
2013 }
2014 return -1;
2015}
2016
2017universal_char const uspace = {0,0,0,32};
2018
2019int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t& p_td,
af710487 2020 XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*)
970ed795
EL
2021{
2022 int exer = is_exer(flavor);
2023 int success = reader.Ok(), depth = -1;
2024 bool omit_tag = exer
2025 && ((p_td.xer_bits & UNTAGGED)
2026 || (flavor & (EMBED_VALUES|XER_LIST|USE_TYPE_ATTR|ANY_ATTRIBUTES|USE_NIL)));
2027
2028 if (exer && (p_td.xer_bits & ANY_ELEMENT)) {
2029 TTCN_EncDec_ErrorContext ec("While checking anyElement: ");
2030 for (; success == 1; success = reader.Read()) {
2031 int type = reader.NodeType();
2032 if (-1 == depth && XML_READER_TYPE_ELEMENT == type) {
2033 xmlChar * value = reader.ReadOuterXml();
2034 size_t num_chars = strlen((const char*)value);
2035 clean_up();
2036 charstring = false;
2037 decode_utf8(num_chars, value); // does init_struct
2038 xmlFree(value);
2039
2040 if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {
2041 const char* xmlns = (const char*)reader.NamespaceUri();
2042 check_namespace_restrictions(p_td, xmlns);
2043 }
2044
2045 if (reader.IsEmptyElement()) {
2046 reader.Read(); // skip past the empty element and we're done
2047 break;
2048 }
2049 depth = reader.Depth(); // signals that we have the element's text
2050 // Stay in the loop until we reach the corresponding end tag
2051 }
2052 else if (reader.Depth() == depth && XML_READER_TYPE_END_ELEMENT == type) {
2053 reader.Read(); // one last time
2054 break;
2055 } // type
2056 } // next read
2057 // ANY-ELEMENT and WHITESPACE are mutually exclusive,
2058 // so this branch skips WHITESPACE processing
2059 }
2060 else { // not ANY-ELEMENT
2061 clean_up(); // start with a clean slate
2062 charstring = false;
2063 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
2064 // we have it easy (but does decode_utf8 handle &nnn; ?)
2065 const char * name = verify_name(reader, p_td, exer);
2066 (void)name;
2067 const char * value = (const char *)reader.Value();
2068 int len = strlen(value);
2069 decode_utf8(len, (cbyte*)value);
2070
2071 // Let the caller do reader.AdvanceAttribute();
2072 }
2073 else { // not an attribute either
2074 // Get to the start of data.
2075 if (!omit_tag) for (; success == 1; success = reader.Read()) {
2076 int type = reader.NodeType();
2077 if (XML_READER_TYPE_ELEMENT == type) {
2078 verify_name(reader, p_td, exer);
2079 if (reader.IsEmptyElement()) {
2080 if (exer && p_td.dfeValue != 0) {
2081 *this = *static_cast<const UNIVERSAL_CHARSTRING*>(p_td.dfeValue);
2082 }
2083 else init_struct(0); // it's an empty string
2084 reader.Read(); // move on
2085 return 0;
2086 }
2087 depth = reader.Depth();
2088 success = reader.Read();
2089 break; // the loop
2090 }
2091 else if (XML_READER_TYPE_TEXT == type && omit_tag)
2092 break;
2093 else // if XML_READER_TYPE_END_ELEMENT, panic?
2094 continue;
2095 } // next read
2096
2097 init_struct(0);
2098 TTCN_Buffer accumulator;
2099 if (flavor & PARENT_CLOSED) {} // do nothing
2100 else for (; success==1; success = reader.Read()) {
2101 int type = reader.NodeType();
2102 switch (type) {
2103 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
2104 case XML_READER_TYPE_TEXT:
2105 case XML_READER_TYPE_CDATA: {
2106 const char * text = (const char*)reader.Value();
2107 int len = strlen(text);
2108 accumulator.put_s(len, (cbyte*)text);
2109 break; }
2110
2111 case XML_READER_TYPE_ELEMENT: { // escaped control character
2112 const char * name = (const char*)reader.LocalName();
2113 size_t len = strlen(name);
2114 char ctrl = in_word_set(name, len);
2115 if (ctrl >= 0) {
2116 accumulator.put_c(ctrl);
2117 }
2118 else {
2119 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2120 "Invalid escape sequence '<%s/>'", name);
2121 }
2122 break; }
2123
2124 case XML_READER_TYPE_END_ELEMENT: {
2125 decode_utf8(accumulator.get_len(), accumulator.get_data());
2126 if (!omit_tag) {
2127 verify_end(reader, p_td, depth, exer);
2128 reader.Read(); // Moved to a different XML node!
2129 if (val_ptr->n_uchars == 0 && exer && p_td.dfeValue != 0) {
2130 // This should be the <foo></foo> case. Treat it like <foo/>
2131 *this = *static_cast<const UNIVERSAL_CHARSTRING*>(p_td.dfeValue);
2132 }
2133 }
2134 goto fini; } // double "break" of switch and for loop
2135
2136 default:
2137 break;
2138 } // switch
2139 } // next read
2140 } // endif (attribute)
2141fini:
2142 if (exer && p_td.whitespace >= WHITESPACE_REPLACE) { // includes _COLLAPSE
2143 for(int i=0; i<val_ptr->n_uchars; ++i) { // first, _REPLACE
2144 switch ( unichar2int(val_ptr->uchars_ptr[i]) ) {
2145 case 9: // HORIZONTAL TAB
2146 case 10: // LINE FEED
2147 case 13: // CARRIAGE RETURN
2148 val_ptr->uchars_ptr[i] = uspace;
2149 break;
2150 default:
2151 break;
2152 } // switch
2153 } // next i
2154
2155 if (p_td.whitespace >= WHITESPACE_COLLAPSE) {
2156 universal_char *to;
2157 const universal_char *from, *end =
2158 val_ptr->uchars_ptr + val_ptr->n_uchars;
2159 for (from = to = val_ptr->uchars_ptr; from < end;) {
2160 *to = *from++;
2161 // If the copied character (*to) was a space,
2162 // and the next character to be copied (*from) is also a space
2163 // (continuous run of spaces)
2164 // or this was the first character (leading spaces to be trimmed),
2165 // then don't advance the destination (will be overwritten).
2166 if (*to != uspace
2167 || (from < end && *from != uspace && to > val_ptr->uchars_ptr))
2168 ++to;
2169 } // next
2170 val_ptr->n_uchars = to - val_ptr->uchars_ptr;
2171 }
2172 } // if WHITESPACE
2173 } // not ANY_ELEMENT
2174 return 1; // decode successful
2175}
2176
2177char* UNIVERSAL_CHARSTRING::to_JSON_string(const TTCN_Buffer& p_buf) const
2178{
2179 const unsigned char* ustr = p_buf.get_data();
2180 const size_t ustr_len = p_buf.get_len();
2181
2182 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
2183 char* json_str = (char*)Malloc(ustr_len + 3);
2184
2185 json_str[0] = 0;
2186 json_str = mputc(json_str, '\"');
2187
2188 for (size_t i = 0; i < ustr_len; ++i) {
2189 // Increase the size of the buffer if it's not big enough to store the
2190 // characters remaining in the universal charstring
2191 switch(ustr[i]) {
2192 case '\\':
2193 json_str = mputstrn(json_str, "\\\\", 2);
2194 break;
2195 case '\n':
2196 json_str = mputstrn(json_str, "\\n", 2);
2197 break;
2198 case '\t':
2199 json_str = mputstrn(json_str, "\\t", 2);
2200 break;
2201 case '\r':
2202 json_str = mputstrn(json_str, "\\r", 2);
2203 break;
2204 case '\f':
2205 json_str = mputstrn(json_str, "\\f", 2);
2206 break;
2207 case '\b':
2208 json_str = mputstrn(json_str, "\\b", 2);
2209 break;
2210 case '\"':
2211 json_str = mputstrn(json_str, "\\\"", 2);
2212 break;
2213 default:
2214 json_str = mputc(json_str, (char)ustr[i]);
2215 break;
2216 }
2217 }
2218
2219 json_str = mputc(json_str, '\"');
2220 return json_str;
2221}
2222
2223boolean UNIVERSAL_CHARSTRING::from_JSON_string(boolean check_quotes)
2224{
2225 int json_len = val_ptr->n_uchars;
2226 universal_char* json_str = val_ptr->uchars_ptr;
2227
2228 int start = 0;
2229 int end = json_len;
2230 if (check_quotes) {
2231 start = 1;
2232 end = json_len - 1;
2233 if (!json_str[0].is_char() || json_str[0].uc_cell != '\"' ||
2234 !json_str[json_len - 1].is_char() || json_str[json_len - 1].uc_cell != '\"') {
2235 return false;
2236 }
2237 }
2238
2239 // The resulting string will be shorter than the JSON string, at least by the 2 quotes
2240 universal_char* ustr = (universal_char*)Malloc((json_len - 2) * sizeof(universal_char));
2241 memset(ustr, 0, sizeof(universal_char) * (json_len - 2));
2242 int ustr_len = 0;
2243 boolean error = false;
2244
2245 for (int i = start; i < end; ++i) {
2246 if (json_str[i].is_char() && '\\' == json_str[i].uc_cell) {
2247 if (i == end - 1 || !json_str[i + 1].is_char()) {
2248 error = true;
2249 break;
2250 }
2251 switch(json_str[i + 1].uc_cell) {
2252 case 'n':
2253 ustr[ustr_len++].uc_cell = '\n';
2254 break;
2255 case 't':
2256 ustr[ustr_len++].uc_cell = '\t';
2257 break;
2258 case 'r':
2259 ustr[ustr_len++].uc_cell = '\r';
2260 break;
2261 case 'f':
2262 ustr[ustr_len++].uc_cell = '\f';
2263 break;
2264 case 'b':
2265 ustr[ustr_len++].uc_cell = '\b';
2266 break;
2267 case '\\':
2268 ustr[ustr_len++].uc_cell = '\\';
2269 break;
2270 case '\"':
2271 ustr[ustr_len++].uc_cell = '\"';
2272 break;
2273 case '/':
2274 ustr[ustr_len++].uc_cell = '/';
2275 break;
2276 case 'u': {
2277 if (end - i >= 6 && json_str[i + 2].is_char() && json_str[i + 3].is_char() &&
2278 json_str[i + 4].is_char() && json_str[i + 5].is_char()) {
2279 unsigned char row_upper_nibble = char_to_hexdigit(json_str[i + 2].uc_cell);
2280 unsigned char row_lower_nibble = char_to_hexdigit(json_str[i + 3].uc_cell);
2281 unsigned char cell_upper_nibble = char_to_hexdigit(json_str[i + 4].uc_cell);
2282 unsigned char cell_lower_nibble = char_to_hexdigit(json_str[i + 5].uc_cell);
2283 if (row_upper_nibble <= 0x0F && row_lower_nibble <= 0x0F &&
2284 cell_upper_nibble <= 0x0F && cell_lower_nibble <= 0x0F) {
2285 ustr[ustr_len].uc_row = (row_upper_nibble << 4) | row_lower_nibble;
2286 ustr[ustr_len++].uc_cell = (cell_upper_nibble << 4) | cell_lower_nibble;
2287 // skip 4 extra characters (the 4 hex digits)
2288 i += 4;
2289 } else {
2290 // error (encountered something other than a hex digit) -> leave the for cycle
2291 i = end;
2292 error = true;
2293 }
2294 } else {
2295 // error (not enough characters or the 'hex digits' are not even ascii characters) -> leave the for cycle
2296 i = end;
2297 error = true;
2298 }
2299 break;
2300 }
2301 default:
2302 // error (invalid escaped character) -> leave the for cycle
2303 i = end;
2304 error = true;
2305 break;
2306 }
2307 // skip an extra character (the \)
2308 ++i;
2309 } else {
2310 ustr[ustr_len++] = json_str[i];
2311 }
2312
2313 if (check_quotes && i == json_len - 1) {
2314 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
2315 error = true;
2316 }
2317 }
2318
2319 if (!error) {
2320 clean_up();
2321 init_struct(ustr_len);
2322 memcpy(val_ptr->uchars_ptr, ustr, ustr_len * sizeof(universal_char));
2323 }
2324 Free(ustr);
2325 return !error;
2326}
2327
2328int UNIVERSAL_CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
2329{
2330 if (!is_bound()) {
2331 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
2332 "Encoding an unbound universal charstring value.");
2333 return -1;
2334 }
2335
2336 char* tmp_str = 0;
2337 if (charstring) {
2338 tmp_str = cstr.to_JSON_string();
2339 } else {
2340 TTCN_Buffer tmp_buf;
2341 encode_utf8(tmp_buf);
2342 tmp_str = to_JSON_string(tmp_buf);
2343 }
2344 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
2345 Free(tmp_str);
2346 return enc_len;
2347}
2348
2349int UNIVERSAL_CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
2350{
2351 json_token_t token = JSON_TOKEN_NONE;
2352 char* value = 0;
2353 size_t value_len = 0;
2354 int dec_len = 0;
2355 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
2356 if (use_default) {
2357 // No JSON data in the buffer -> use default value
2358 value = (char*)p_td.json->default_value;
2359 value_len = strlen(value);
2360 } else {
2361 dec_len = p_tok.get_next_token(&token, &value, &value_len);
2362 }
2363 if (JSON_TOKEN_ERROR == token) {
2364 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
2365 return JSON_ERROR_FATAL;
2366 }
2367 else if (JSON_TOKEN_STRING == token || use_default) {
2368 if (cstr.from_JSON_string(value, value_len, !use_default)) {
2369 charstring = true;
2370 }
2371 else {
2372 charstring = false;
2373 decode_utf8(value_len, (unsigned char*)value);
2374 if (!from_JSON_string(!use_default)) {
2375 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "universal charstring");
2376 if (p_silent) {
2377 clean_up();
2378 }
2379 return JSON_ERROR_FATAL;
2380 }
2381 }
2382 } else {
2383 return JSON_ERROR_INVALID_TOKEN;
2384 }
2385 return dec_len;
2386}
2387
2388
2389static void fill_continuing_octets(int n_continuing,
2390 unsigned char *continuing_ptr, int n_octets,
2391 const unsigned char *octets_ptr, int start_pos, int uchar_pos)
2392{
2393 for (int i = 0; i < n_continuing; i++) {
2394 if (start_pos + i < n_octets) {
2395 unsigned char octet = octets_ptr[start_pos + i];
2396 if ((octet & 0xC0) != 0x80) {
2397 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2398 "Malformed: At character position %d, octet position %d: %02X is "
2399 "not a valid continuing octet.", uchar_pos, start_pos + i, octet);
2400 }
2401 continuing_ptr[i] = octet & 0x3F;
2402 } else {
2403 if (start_pos + i == n_octets) {
2404 if (i > 0) {
2405 // only a part of octets is missing
2406 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2407 "Incomplete: At character position %d, octet position %d: %d out "
2408 "of %d continuing octets %s missing from the end of the stream.",
2409 uchar_pos, start_pos + i, n_continuing - i, n_continuing,
2410 n_continuing - i > 1 ? "are" : "is");
2411 } else {
2412 // all octets are missing
2413 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2414 "Incomplete: At character position %d, octet position %d: %d "
2415 "continuing octet%s missing from the end of the stream.", uchar_pos,
2416 start_pos, n_continuing, n_continuing > 1 ? "s are" : " is");
2417 }
2418 }
2419 continuing_ptr[i] = 0;
2420 }
2421 }
2422}
2423
2424void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets,
2425 const unsigned char *octets_ptr,
2426 CharCoding::CharCodingType expected_coding /*= UTF8*/,
2427 bool checkBOM /*= false)*/)
2428{
2429 // approximate the number of characters
2430 int n_uchars = 0;
2431 for (int i = 0; i < n_octets; i++) {
2432 // count all octets except the continuing octets (10xxxxxx)
2433 if ((octets_ptr[i] & 0xC0) != 0x80) n_uchars++;
2434 }
a38c6d4c 2435 // allocate enough memory, start from clean state
2436 clean_up();
2437 charstring=false;
970ed795
EL
2438 init_struct(n_uchars);
2439 n_uchars = 0;
2440
2441 int start = checkBOM ? check_BOM(CharCoding::UTF_8, sizeof(octets_ptr), octets_ptr) : 0;
2442 for (int i = start; i < n_octets; ) {
2443 // perform the decoding character by character
2444 if (octets_ptr[i] <= 0x7F) {
2445 // character encoded on a single octet: 0xxxxxxx (7 useful bits)
2446 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2447 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2448 val_ptr->uchars_ptr[n_uchars].uc_row = 0;
2449 val_ptr->uchars_ptr[n_uchars].uc_cell = octets_ptr[i];
2450 i++;
2451 n_uchars++;
2452 } else if (octets_ptr[i] <= 0xBF) {
2453 // continuing octet (10xxxxxx) without leading octet ==> malformed
2454 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2455 "Malformed: At character position %d, octet position %d: continuing "
2456 "octet %02X without leading octet.", n_uchars, i, octets_ptr[i]);
2457 i++;
2458 } else if (octets_ptr[i] <= 0xDF) {
2459 // character encoded on 2 octets: 110xxxxx 10xxxxxx (11 useful bits)
2460 unsigned char octets[2];
2461 octets[0] = octets_ptr[i] & 0x1F;
2462 fill_continuing_octets(1, octets + 1, n_octets, octets_ptr, i + 1, n_uchars);
2463 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2464 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2465 val_ptr->uchars_ptr[n_uchars].uc_row = octets[0] >> 2;
2466 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[0] << 6 | octets[1];
2467 if (val_ptr->uchars_ptr[n_uchars].uc_row == 0x00 &&
2468 val_ptr->uchars_ptr[n_uchars].uc_cell < 0x80)
2469 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2470 "Overlong: At character position %d, octet position %d: 2-octet "
2471 "encoding for quadruple (0, 0, 0, %u).", n_uchars, i,
2472 val_ptr->uchars_ptr[n_uchars].uc_cell);
2473 i += 2;
2474 n_uchars++;
2475 } else if (octets_ptr[i] <= 0xEF) {
2476 // character encoded on 3 octets: 1110xxxx 10xxxxxx 10xxxxxx
2477 // (16 useful bits)
2478 unsigned char octets[3];
2479 octets[0] = octets_ptr[i] & 0x0F;
2480 fill_continuing_octets(2, octets + 1, n_octets, octets_ptr, i + 1,
2481 n_uchars);
2482 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2483 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2484 val_ptr->uchars_ptr[n_uchars].uc_row = octets[0] << 4 | octets[1] >> 2;
2485 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[1] << 6 | octets[2];
2486 if (val_ptr->uchars_ptr[n_uchars].uc_row < 0x08)
2487 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2488 "Overlong: At character position %d, octet position %d: 3-octet "
2489 "encoding for quadruple (0, 0, %u, %u).", n_uchars, i,
2490 val_ptr->uchars_ptr[n_uchars].uc_row,
2491 val_ptr->uchars_ptr[n_uchars].uc_cell);
2492 i += 3;
2493 n_uchars++;
2494 } else if (octets_ptr[i] <= 0xF7) {
2495 // character encoded on 4 octets: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2496 // (21 useful bits)
2497 unsigned char octets[4];
2498 octets[0] = octets_ptr[i] & 0x07;
2499 fill_continuing_octets(3, octets + 1, n_octets, octets_ptr, i + 1,
2500 n_uchars);
2501 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2502 val_ptr->uchars_ptr[n_uchars].uc_plane = octets[0] << 2 | octets[1] >> 4;
2503 val_ptr->uchars_ptr[n_uchars].uc_row = octets[1] << 4 | octets[2] >> 2;
2504 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[2] << 6 | octets[3];
2505 if (val_ptr->uchars_ptr[n_uchars].uc_plane == 0x00)
2506 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2507 "Overlong: At character position %d, octet position %d: 4-octet "
2508 "encoding for quadruple (0, 0, %u, %u).", n_uchars, i,
2509 val_ptr->uchars_ptr[n_uchars].uc_row,
2510 val_ptr->uchars_ptr[n_uchars].uc_cell);
2511 i += 4;
2512 n_uchars++;
2513 } else if (octets_ptr[i] <= 0xFB) {
2514 // character encoded on 5 octets: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
2515 // 10xxxxxx (26 useful bits)
2516 unsigned char octets[5];
2517 octets[0] = octets_ptr[i] & 0x03;
2518 fill_continuing_octets(4, octets + 1, n_octets, octets_ptr, i + 1,
2519 n_uchars);
2520 val_ptr->uchars_ptr[n_uchars].uc_group = octets[0];
2521 val_ptr->uchars_ptr[n_uchars].uc_plane = octets[1] << 2 | octets[2] >> 4;
2522 val_ptr->uchars_ptr[n_uchars].uc_row = octets[2] << 4 | octets[3] >> 2;
2523 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[3] << 6 | octets[4];
2524 if (val_ptr->uchars_ptr[n_uchars].uc_group == 0x00 &&
2525 val_ptr->uchars_ptr[n_uchars].uc_plane < 0x20)
2526 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2527 "Overlong: At character position %d, octet position %d: 5-octet "
2528 "encoding for quadruple (0, %u, %u, %u).", n_uchars, i,
2529 val_ptr->uchars_ptr[n_uchars].uc_plane,
2530 val_ptr->uchars_ptr[n_uchars].uc_row,
2531 val_ptr->uchars_ptr[n_uchars].uc_cell);
2532 i += 5;
2533 n_uchars++;
2534 } else if (octets_ptr[i] <= 0xFD) {
2535 // character encoded on 6 octets: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx
2536 // 10xxxxxx 10xxxxxx (31 useful bits)
2537 unsigned char octets[6];
2538 octets[0] = octets_ptr[i] & 0x01;
2539 fill_continuing_octets(5, octets + 1, n_octets, octets_ptr, i + 1,
2540 n_uchars);
2541 val_ptr->uchars_ptr[n_uchars].uc_group = octets[0] << 6 | octets[1];
2542 val_ptr->uchars_ptr[n_uchars].uc_plane = octets[2] << 2 | octets[3] >> 4;
2543 val_ptr->uchars_ptr[n_uchars].uc_row = octets[3] << 4 | octets[4] >> 2;
2544 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[4] << 6 | octets[5];
2545 if (val_ptr->uchars_ptr[n_uchars].uc_group < 0x04)
2546 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2547 "Overlong: At character position %d, octet position %d: 6-octet "
2548 "encoding for quadruple (%u, %u, %u, %u).", n_uchars, i,
2549 val_ptr->uchars_ptr[n_uchars].uc_group,
2550 val_ptr->uchars_ptr[n_uchars].uc_plane,
2551 val_ptr->uchars_ptr[n_uchars].uc_row,
2552 val_ptr->uchars_ptr[n_uchars].uc_cell);
2553 i += 6;
2554 n_uchars++;
2555 } else {
2556 // not used code points: FE and FF => malformed
2557 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2558 "Malformed: At character position %d, octet position %d: "
2559 "unused/reserved octet %02X.", n_uchars, i, octets_ptr[i]);
2560 i++;
2561 }
2562 } // for i
2563 if (val_ptr->n_uchars != n_uchars) {
2564 // truncate the memory and set the correct size in case of decoding errors
2565 // (e.g. skipped octets)
2566 if (n_uchars > 0) {
2567 val_ptr = (universal_charstring_struct*)Realloc(val_ptr,
2568 MEMORY_SIZE(n_uchars));
2569 val_ptr->n_uchars = n_uchars;
2570 } else {
2571 clean_up();
2572 init_struct(0);
2573 }
2574 }
2575}
2576
2577void UNIVERSAL_CHARSTRING::decode_utf16(int n_octets,
2578 const unsigned char *octets_ptr,
2579 CharCoding::CharCodingType expected_coding)
2580{
2581 if (n_octets % 2 || 0 > n_octets) {
2582 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2583 "Wrong UTF-16 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 2",
2584 n_octets);
2585 }
2586 int start = check_BOM(expected_coding, sizeof(octets_ptr), octets_ptr);
2587 int n_uchars = n_octets/2;
2588 init_struct(n_uchars);
2589 n_uchars = 0;
2590 bool isbig = true;
2591 switch (expected_coding) {
2592 case CharCoding::UTF16:
2593 case CharCoding::UTF16BE:
2594 isbig = true;
2595 break;
2596 case CharCoding::UTF16LE:
2597 isbig = false;
2598 break;
2599 default:
2600 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2601 "Unexpected coding type for UTF-16 encoding");
2602 break;
2603 }
2604 for (int i = start; i < n_octets; i += 2 ) {
2605 int first = isbig ? i : i + 1;
2606 int second = isbig ? i + 1 : i;
2607 int third = isbig ? i + 2 : i + 3;
2608 int fourth = isbig ? i + 3 : i + 2;
2609
2610 uint16_t W1 = octets_ptr[first] << 8 | octets_ptr[second];
2611 uint16_t W2 = (i + 3 < n_octets) ? octets_ptr[third] << 8 | octets_ptr[fourth] : 0;
2612
2613 if (0xD800 > W1 || 0xDFFF < W1) {
2614 //if W1 < 0xD800 or W1 > 0xDFFF, the character value is the value of W1
2615 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2616 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2617 val_ptr->uchars_ptr[n_uchars].uc_row = octets_ptr[first];
2618 val_ptr->uchars_ptr[n_uchars].uc_cell = octets_ptr[second];
2619 ++n_uchars;
2620 }
2621 else if (0xD800 > W1 || 0xDBFF < W1) {
2622 //Determine if W1 is between 0xD800 and 0xDBFF. If not, the sequence
2623 //is in error and no valid character can be obtained using W1.
2624 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2625 "The word (0x%04X) shall be between 0xD800 and 0xDBFF", W1);
2626 }
2627 else if (0 == W2 || (0xDC00 > W2 || 0xDFFF < W2)) {
2628 //If there is no W2 (that is, the sequence ends with W1), or if W2
2629 //is not between 0xDC00 and 0xDFFF, the sequence is in error.
2630 if (W2)
2631 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2632 "Wrong UTF-16 string. The word (0x%04X) shall be between 0xDC00 and 0xDFFF", W2);
2633 else
2634 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2635 "Wrong UTF-16 string. The decoding algorythm does not expect 0x00 or EOL");
2636 }
2637 else {
2638 //Construct a 20-bit unsigned integer, taking the 10 low-order bits of W1 as its 10 high-
2639 //order bits and the 10 low-order bits of W2 as its 10 low-order bits.
2640 const uint16_t mask10bitlow = 0x3FF;
2641 uint32_t DW = (W1 & mask10bitlow) << 10;
2642 DW |= (W2 & mask10bitlow);
2643 DW += 0x10000;
2644 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2645 val_ptr->uchars_ptr[n_uchars].uc_plane = DW >> 16;
2646 val_ptr->uchars_ptr[n_uchars].uc_row = DW >> 8;
2647 val_ptr->uchars_ptr[n_uchars].uc_cell = DW;
2648 ++n_uchars;
2649 i += 2; // jump over w2 in octetstring
2650 }
2651 }
2652 if (val_ptr->n_uchars != n_uchars) {
2653 // truncate the memory and set the correct size in case of decoding errors
2654 // (e.g. skipped octets)
2655 if (n_uchars > 0) {
2656 val_ptr = (universal_charstring_struct*)Realloc(val_ptr, MEMORY_SIZE(n_uchars));
2657 val_ptr->n_uchars = n_uchars;
2658 }
2659 else {
2660 clean_up();
2661 init_struct(0);
2662 }
2663 }
2664}
2665
2666void UNIVERSAL_CHARSTRING::decode_utf32(int n_octets, const unsigned char *octets_ptr,
2667 CharCoding::CharCodingType expected_coding)
2668{
2669 if (n_octets % 4 || 0 > n_octets) {
2670 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2671 "Wrong UTF-32 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 4",
2672 n_octets);
2673 }
2674 int start = check_BOM(expected_coding, sizeof(octets_ptr), octets_ptr);
2675 int n_uchars = n_octets/4;
2676 init_struct(n_uchars);
2677 n_uchars = 0;
2678 bool isbig = true;
2679 switch (expected_coding) {
2680 case CharCoding::UTF32:
2681 case CharCoding::UTF32BE:
2682 isbig = true;
2683 break;
2684 case CharCoding::UTF32LE:
2685 isbig = false;
2686 break;
2687 default:
2688 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2689 "Unexpected coding type for UTF-32 encoding");
2690 break;
2691 }
2692 for (int i = start; i < n_octets; i += 4 ) {
2693 int first = isbig ? i : i + 3;
2694 int second = isbig ? i + 1 : i + 2;
2695 int third = isbig ? i + 2 : i + 1;
2696 int fourth = isbig ? i + 3 : i;
2697 uint32_t DW = octets_ptr[first] << 8 | octets_ptr[second];
2698 DW <<= 8;
2699 DW |= octets_ptr[third];
2700 DW <<= 8;
2701 DW |= octets_ptr[fourth];
2702 if (0x0000D800 <= DW && 0x0000DFFF >= DW) {
2703 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2704 "Any UTF-32 code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW);
2705 }
2706 else if (0x0010FFFF < DW) {
2707 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2708 "Any UTF-32 code (0x%08X) greater than 0x0010FFFF is ill-formed", DW);
2709 }
2710 else {
2711 val_ptr->uchars_ptr[n_uchars].uc_group = octets_ptr[first];
2712 val_ptr->uchars_ptr[n_uchars].uc_plane = octets_ptr[second];
2713 val_ptr->uchars_ptr[n_uchars].uc_row = octets_ptr[third];
2714 val_ptr->uchars_ptr[n_uchars].uc_cell = octets_ptr[fourth];
2715 ++n_uchars;
2716 }
2717 }
2718 if (val_ptr->n_uchars != n_uchars) {
2719 // truncate the memory and set the correct size in case of decoding errors
2720 // (e.g. skipped octets)
2721 if (n_uchars > 0) {
2722 val_ptr = (universal_charstring_struct*)Realloc(val_ptr, MEMORY_SIZE(n_uchars));
2723 val_ptr->n_uchars = n_uchars;
2724 }
2725 else {
2726 clean_up();
2727 init_struct(0);
2728 }
2729 }
2730}
2731int UNIVERSAL_CHARSTRING::check_BOM(CharCoding::CharCodingType expected_coding,
2732 unsigned int length,
2733 const unsigned char* ostr)
2734{
2735 switch (expected_coding) {
2736 case CharCoding::UTF32:
2737 case CharCoding::UTF32BE:
2738 case CharCoding::UTF32LE:
2739 if (4 > length) {
2740 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2741 "The string is shorter than the expected BOM");
2742 }
2743 break;
2744 case CharCoding::UTF16:
2745 case CharCoding::UTF16BE:
2746 case CharCoding::UTF16LE:
2747 if (2 > length) {
2748 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2749 "The string is shorter than the expected BOM");
2750 }
2751 break;
2752 case CharCoding::UTF_8:
2753 if (3 > length) {
2754 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2755 "The string is shorter than the expected BOM");
2756 }
2757 break;
2758 default: break;
2759 }
2760 std::string coding_str;
2761 //BOM indicates that the byte order is determined by a byte order mark,
2762 //if present at the beginning the length of BOM is returned.
2763 switch (expected_coding) {
2764 case CharCoding::UTF32BE:
2765 case CharCoding::UTF32:
2766 if (0x00 == ostr[0] && 0x00 == ostr[1] && 0xFE == ostr[2] && 0xFF == ostr[3]) {
2767 return 4;
2768 }
2769 coding_str = "UTF-32BE";
2770 break;
2771 case CharCoding::UTF32LE:
2772 if (0xFF == ostr[0] && 0xFE == ostr[1] && 0x00 == ostr[2] && 0x00 == ostr[3]) {
2773 return 4;
2774 }
2775 coding_str = "UTF-32LE";
2776 break;
2777 case CharCoding::UTF16BE:
2778 case CharCoding::UTF16:
2779 if (0xFE == ostr[0] && 0xFF == ostr[1]) {
2780 return 2;
2781 }
2782 coding_str = "UTF-16BE";
2783 break;
2784 case CharCoding::UTF16LE:
2785 if (0xFF == ostr[0] && 0xFE == ostr[1]) {
2786 return 2;
2787 }
2788 coding_str = "UTF-16LE";
2789 break;
2790 case CharCoding::UTF_8:
2791 if (0xEF == ostr[0] && 0xBB == ostr[1] && 0xBF == ostr[2]) {
2792 return 3;
2793 }
2794 coding_str = "UTF-8";
2795 break;
2796 default:
2797 // No BOM found
2798 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2799 "Wrong %s string. No BOM detected, however the given coding type (%s) expects it to define the endianness",
2800 coding_str.c_str(), coding_str.c_str());
2801 break;
2802 }
2803 TTCN_EncDec_ErrorContext::warning("No %s Byte Order Mark(BOM) detected. It may result decoding errors",
2804 coding_str.c_str());
2805 return 0;
2806}
2807
2808// member functions of class UNIVERSAL_CHARSTRING_ELEMENTS
2809
2810UNIVERSAL_CHARSTRING_ELEMENT::UNIVERSAL_CHARSTRING_ELEMENT
2811 (boolean par_bound_flag, UNIVERSAL_CHARSTRING& par_str_val,
2812 int par_uchar_pos) :
2813 bound_flag(par_bound_flag), str_val(par_str_val), uchar_pos(par_uchar_pos)
2814{
2815
2816}
2817
2818UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2819 (const universal_char& other_value)
2820{
2821 bound_flag = TRUE;
2822 if (str_val.charstring) {
2823 if (other_value.is_char()) {
2824 str_val.cstr.val_ptr->chars_ptr[uchar_pos] = other_value.uc_cell;
2825 return *this;
2826 } else
2827 str_val.convert_cstr_to_uni();
2828 } else
2829 str_val.copy_value();
2830 str_val.val_ptr->uchars_ptr[uchar_pos] = other_value;
2831 return *this;
2832}
2833
2834UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2835 (const char* other_value)
2836{
2837 if (other_value == NULL || other_value[0] == '\0' || other_value[1] != '\0')
2838 TTCN_error("Assignment of a charstring value with length other than 1 to "
2839 "a universal charstring element.");
2840 bound_flag = TRUE;
2841 if (str_val.charstring)
2842 str_val.cstr.val_ptr->chars_ptr[uchar_pos] = other_value[0];
2843 else {
2844 str_val.copy_value();
2845 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2846 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2847 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2848 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell = other_value[0];
2849 }
2850 return *this;
2851}
2852
2853UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2854 (const CHARSTRING& other_value)
2855{
2856 other_value.must_bound("Assignment of an unbound charstring value to a "
2857 "universal charstring element.");
2858 if(other_value.val_ptr->n_chars != 1)
2859 TTCN_error("Assignment of a charstring value with length other than 1 to "
2860 "a universal charstring element.");
2861 bound_flag = TRUE;
2862 if (str_val.charstring)
2863 str_val.cstr.val_ptr->chars_ptr[uchar_pos] =
2864 other_value.val_ptr->chars_ptr[0];
2865 else {
2866 str_val.copy_value();
2867 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2868 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2869 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2870 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell =
2871 other_value.val_ptr->chars_ptr[0];
2872 }
2873 return *this;
2874}
2875
2876UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2877 (const CHARSTRING_ELEMENT& other_value)
2878{
2879 other_value.must_bound("Assignment of an unbound charstring element to a "
2880 "universal charstring element.");
2881 bound_flag = TRUE;
2882 if (str_val.charstring)
2883 str_val.cstr.val_ptr->chars_ptr[uchar_pos] = other_value.get_char();
2884 else {
2885 str_val.copy_value();
2886 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2887 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2888 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2889 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell = other_value.get_char();
2890 }
2891 return *this;
2892}
2893
2894UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2895 (const UNIVERSAL_CHARSTRING& other_value)
2896{
2897 other_value.must_bound("Assignment of an unbound universal charstring value "
2898 "to a universal charstring element.");
a38c6d4c 2899 int other_value_size = other_value.charstring ? other_value.cstr.val_ptr->n_chars :
2900 other_value.val_ptr->n_uchars;
2901 if (other_value_size != 1)
970ed795
EL
2902 TTCN_error("Assignment of a universal charstring value with length other "
2903 "than 1 to a universal charstring element.");
2904 bound_flag = TRUE;
a38c6d4c 2905 *this = other_value[0];
970ed795
EL
2906 return *this;
2907}
2908
2909UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2910 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
2911{
2912 other_value.must_bound("Assignment of an unbound universal charstring "
2913 "element.");
2914 if (&other_value != this) {
2915 bound_flag = TRUE;
2916 if (str_val.charstring) {
2917 if (other_value.str_val.charstring)
2918 str_val.cstr.val_ptr->chars_ptr[uchar_pos] =
2919 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
2920 else {
2921 str_val.convert_cstr_to_uni();
2922 str_val.val_ptr->uchars_ptr[uchar_pos] =
2923 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
2924 }
2925 } else {
2926 if (other_value.str_val.charstring) {
2927 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2928 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2929 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2930 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell =
2931 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
2932 } else {
2933 str_val.copy_value();
2934 str_val.val_ptr->uchars_ptr[uchar_pos] =
2935 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
2936 }
2937 }
2938 }
2939 return *this;
2940}
2941
2942boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2943 (const universal_char& other_value) const
2944{
2945 must_bound("The left operand of comparison is an unbound universal "
2946 "charstring element.");
2947 if (str_val.charstring && other_value.is_char())
2948 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] == other_value.uc_cell;
2949 if (str_val.charstring && !other_value.is_char())
2950 return FALSE;
2951 if (!str_val.charstring && other_value.is_char()) {
2952 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2953 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
2954 uchar.uc_cell == other_value.uc_cell;
2955 }
2956 return str_val.val_ptr->uchars_ptr[uchar_pos] == other_value;
2957}
2958
2959boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2960 (const char* other_value) const
2961{
2962 must_bound("The left operand of comparison is an unbound universal "
2963 "charstring element.");
2964 if (other_value == NULL || other_value[0] == '\0' ||
2965 other_value[1] != '\0') return FALSE;
2966 if (str_val.charstring)
2967 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] == other_value[0];
2968 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2969 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
2970 uchar.uc_cell == (cbyte)other_value[0];
2971}
2972
2973boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2974 (const CHARSTRING& other_value) const
2975{
2976 must_bound("The left operand of comparison is an unbound universal "
2977 "charstring element.");
2978 other_value.must_bound("The right operand of comparison is an unbound "
2979 "charstring value.");
2980 if (other_value.val_ptr->n_chars != 1) return FALSE;
2981 if (str_val.charstring)
2982 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] ==
2983 other_value.val_ptr->chars_ptr[0];
2984 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2985 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
2986 uchar.uc_cell == (cbyte)other_value.val_ptr->chars_ptr[0];
2987}
2988
2989boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2990 (const CHARSTRING_ELEMENT& other_value) const
2991{
2992 must_bound("The left operand of comparison is an unbound universal "
2993 "charstring element.");
2994 other_value.must_bound("The right operand of comparison is an unbound "
2995 "charstring element.");
2996 if (str_val.charstring)
2997 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] == other_value.get_char();
2998 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2999 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3000 uchar.uc_cell == (cbyte)other_value.get_char();
3001}
3002
3003boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
3004 (const UNIVERSAL_CHARSTRING& other_value) const
3005{
3006 must_bound("The left operand of comparison is an unbound universal "
3007 "charstring element.");
3008 other_value.must_bound("The right operand of comparison is an unbound "
3009 "universal charstring value.");
3010 if (other_value.charstring) {
3011 if (other_value.cstr.val_ptr->n_chars != 1)
3012 return FALSE;
3013 if (str_val.charstring)
3014 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] ==
3015 other_value.cstr.val_ptr->chars_ptr[0];
3016 else {
3017 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3018 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0
3019 && uchar.uc_cell == (cbyte)other_value.cstr.val_ptr->chars_ptr[0];
3020 }
3021 } else {
3022 if (other_value.val_ptr->n_uchars != 1)
3023 return FALSE;
3024 if (str_val.charstring) {
3025 const universal_char& uchar = other_value.val_ptr->uchars_ptr[0];
3026 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3027 uchar.uc_cell == (cbyte)str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3028 } else
3029 return str_val.val_ptr->uchars_ptr[uchar_pos] ==
3030 other_value.val_ptr->uchars_ptr[0];
3031 }
3032}
3033
3034boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
3035 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
3036{
3037 must_bound("The left operand of comparison is an unbound universal "
3038 "charstring element.");
3039 other_value.must_bound("The right operand of comparison is an unbound "
3040 "universal charstring element.");
3041 if (str_val.charstring) {
3042 if (other_value.str_val.charstring)
3043 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] ==
3044 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3045 else {
3046 const universal_char& uchar = other_value.get_uchar();
3047 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3048 uchar.uc_cell == str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3049 }
3050 } else {
3051 if (other_value.str_val.charstring) {
3052 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3053 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3054 uchar.uc_cell ==
3055 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3056 } else
3057 return str_val.val_ptr->uchars_ptr[uchar_pos] ==
3058 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
3059 }
3060}
3061
3062UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3063 (const universal_char& other_value) const
3064{
3065 must_bound("The left operand of concatenation is an unbound universal "
3066 "charstring element.");
3067 if (str_val.charstring && other_value.is_char()) {
3068 UNIVERSAL_CHARSTRING ret_val(2, true);
3069 ret_val.cstr.val_ptr->chars_ptr[0] =
3070 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3071 ret_val.cstr.val_ptr->chars_ptr[1] = other_value.uc_cell;
3072 return ret_val;
3073 } else if (str_val.charstring ^ other_value.is_char()) {
3074 universal_char result[2];
3075 if (str_val.charstring) {
3076 result[0].uc_group = result[0].uc_plane = result[0].uc_row = 0;
3077 result[0].uc_cell = str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3078 } else
3079 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3080 result[1] = other_value;
3081 return UNIVERSAL_CHARSTRING(2, result);
3082 }
3083 universal_char result[2];
3084 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3085 result[1] = other_value;
3086 return UNIVERSAL_CHARSTRING(2, result);
3087}
3088
3089UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3090 (const char* other_value) const
3091{
3092 must_bound("The left operand of concatenation is an unbound universal "
3093 "charstring element.");
3094 int other_len;
3095 if (other_value == NULL) other_len = 0;
3096 else other_len = strlen(other_value);
3097
3098 UNIVERSAL_CHARSTRING ret_val(other_len + 1, str_val.charstring);
3099 if (str_val.charstring) {
3100 ret_val.cstr.val_ptr->chars_ptr[0] =
3101 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3102 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1, other_value, other_len);
3103 } else {
3104 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3105 for (int i = 0; i < other_len; i++) {
3106 ret_val.val_ptr->uchars_ptr[i + 1].uc_group = 0;
3107 ret_val.val_ptr->uchars_ptr[i + 1].uc_plane = 0;
3108 ret_val.val_ptr->uchars_ptr[i + 1].uc_row = 0;
3109 ret_val.val_ptr->uchars_ptr[i + 1].uc_cell = other_value[i];
3110 }
3111 }
3112 return ret_val;
3113}
3114
3115UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3116 (const CHARSTRING& other_value) const
3117{
3118 must_bound("The left operand of concatenation is an unbound universal "
3119 "charstring element.");
3120 other_value.must_bound("The right operand of concatenation is an unbound "
3121 "charstring value.");
3122 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_chars + 1,
3123 str_val.charstring);
3124 if (str_val.charstring) {
3125 ret_val.cstr.val_ptr->chars_ptr[0] =
3126 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3127 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1, other_value.val_ptr->chars_ptr,
3128 other_value.val_ptr->n_chars);
3129 } else {
3130 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3131 for (int i = 0; i < other_value.val_ptr->n_chars; i++) {
3132 ret_val.val_ptr->uchars_ptr[i + 1].uc_group = 0;
3133 ret_val.val_ptr->uchars_ptr[i + 1].uc_plane = 0;
3134 ret_val.val_ptr->uchars_ptr[i + 1].uc_row = 0;
3135 ret_val.val_ptr->uchars_ptr[i + 1].uc_cell =
3136 other_value.val_ptr->chars_ptr[i];
3137 }
3138 }
3139 return ret_val;
3140}
3141
3142UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3143 (const CHARSTRING_ELEMENT& other_value) const
3144{
3145 must_bound("The left operand of concatenation is an unbound universal "
3146 "charstring element.");
3147 other_value.must_bound("The right operand of concatenation is an unbound "
3148 "charstring element.");
3149 if (str_val.charstring) {
3150 UNIVERSAL_CHARSTRING ret_val(2, true);
3151 ret_val.cstr.val_ptr->chars_ptr[0] =
3152 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3153 ret_val.cstr.val_ptr->chars_ptr[1] = other_value.get_char();
3154 return ret_val;
3155 } else {
3156 universal_char result[2];
3157 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3158 result[1].uc_group = 0;
3159 result[1].uc_plane = 0;
3160 result[1].uc_row = 0;
3161 result[1].uc_cell = other_value.get_char();
3162 return UNIVERSAL_CHARSTRING(2, result);
3163 }
3164}
3165
3166UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3167 (const UNIVERSAL_CHARSTRING& other_value) const
3168{
3169 must_bound("The left operand of concatenation is an unbound universal "
3170 "charstring element.");
3171 other_value.must_bound("The right operand of concatenation is an unbound "
3172 "universal charstring value.");
3173 if (str_val.charstring) {
3174 if (other_value.charstring) {
3175 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1, true);
3176 ret_val.cstr.val_ptr->chars_ptr[0] =
3177 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3178 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1,
3179 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
3180 return ret_val;
3181 } else {
3182 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3183 universal_char& uchar = ret_val.val_ptr->uchars_ptr[0];
3184 uchar.uc_group = uchar.uc_plane = uchar.uc_row = 0;
3185 uchar.uc_cell = str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3186 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
3187 other_value.val_ptr->n_uchars * sizeof(universal_char));
3188 return ret_val;
3189 }
3190 } else {
3191 if (other_value.charstring) {
3192 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1);
3193 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3194 for (int i = 1; i <= other_value.cstr.val_ptr->n_chars; ++i) {
3195 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
3196 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
3197 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
3198 ret_val.val_ptr->uchars_ptr[i].uc_cell =
3199 other_value.cstr.val_ptr->chars_ptr[i-1];
3200 }
3201 return ret_val;
3202 } else {
3203 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3204 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3205 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
3206 other_value.val_ptr->n_uchars * sizeof(universal_char));
3207 return ret_val;
3208 }
3209 }
3210}
3211
3212UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3213 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
3214{
3215 must_bound("The left operand of concatenation is an unbound universal "
3216 "charstring element.");
3217 other_value.must_bound("The right operand of concatenation is an unbound "
3218 "universal charstring element.");
3219 if (str_val.charstring) {
3220 if (other_value.str_val.charstring) {
3221 UNIVERSAL_CHARSTRING ret_val(2, true);
3222 ret_val.cstr.val_ptr->chars_ptr[0] =
3223 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3224 ret_val.cstr.val_ptr->chars_ptr[1] =
3225 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3226 return ret_val;
3227 } else {
3228 UNIVERSAL_CHARSTRING ret_val(2);
3229 universal_char& uchar = ret_val.val_ptr->uchars_ptr[0];
3230 uchar.uc_group = uchar.uc_plane = uchar.uc_row = 0;
3231 uchar.uc_cell = str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3232 ret_val.val_ptr->uchars_ptr[1] =
3233 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
3234 return ret_val;
3235 }
3236 } else {
3237 if (other_value.str_val.charstring) {
3238 UNIVERSAL_CHARSTRING ret_val(2);
3239 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3240 ret_val.val_ptr->uchars_ptr[1].uc_group = 0;
3241 ret_val.val_ptr->uchars_ptr[1].uc_plane = 0;
3242 ret_val.val_ptr->uchars_ptr[1].uc_row = 0;
3243 ret_val.val_ptr->uchars_ptr[1].uc_cell =
3244 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3245 return ret_val;
3246 } else {
3247 universal_char result[2];
3248 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3249 result[1] = other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
3250 return UNIVERSAL_CHARSTRING(2, result);
3251 }
3252 }
3253}
3254
3255const universal_char& UNIVERSAL_CHARSTRING_ELEMENT::get_uchar() const
3256{
3257 if (str_val.charstring)
3258 const_cast<UNIVERSAL_CHARSTRING_ELEMENT&>
3259 (*this).str_val.convert_cstr_to_uni();
3260 return str_val.val_ptr->uchars_ptr[uchar_pos];
3261}
3262
3263void UNIVERSAL_CHARSTRING_ELEMENT::log() const
3264{
3265 if (bound_flag) {
3266 if (str_val.charstring) {
3267 str_val.cstr[uchar_pos].log();
3268 return;
3269 }
3270 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3271 if (is_printable(uchar)) {
3272 // the character is printable
3273 TTCN_Logger::log_char('"');
3274 TTCN_Logger::log_char_escaped(uchar.uc_cell);
3275 TTCN_Logger::log_char('"');
3276 } else {
3277 // the character is not printable
3278 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3279 uchar.uc_group, uchar.uc_plane, uchar.uc_row, uchar.uc_cell);
3280 }
3281 } else TTCN_Logger::log_event_unbound();
3282}
3283
3284// global functions
3285
3286boolean operator==(const universal_char& uchar_value,
3287 const UNIVERSAL_CHARSTRING& other_value)
3288{
3289 other_value.must_bound("The right operand of comparison is an unbound "
3290 "universal charstring value.");
3291 if (other_value.charstring) {
3292 if (other_value.cstr.val_ptr->n_chars != 1) return FALSE;
3293 else return uchar_value.is_char() &&
3294 uchar_value.uc_cell == other_value.cstr.val_ptr->chars_ptr[0];
3295 }
3296 if (other_value.val_ptr->n_uchars != 1) return FALSE;
3297 else return uchar_value == other_value.val_ptr->uchars_ptr[0];
3298}
3299
3300boolean operator==(const universal_char& uchar_value,
3301 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3302{
3303 other_value.must_bound("The right operand of comparison is an unbound "
3304 "universal charstring element.");
3305 return uchar_value == other_value.get_uchar();
3306}
3307
3308UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value,
3309 const UNIVERSAL_CHARSTRING& other_value)
3310{
3311 other_value.must_bound("The right operand of concatenation is an unbound "
3312 "universal charstring value.");
3313 if (other_value.charstring) {
3314 if (uchar_value.is_char()) {
3315 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1, true);
3316 ret_val.cstr.val_ptr->chars_ptr[0] = uchar_value.uc_cell;
3317 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1,
3318 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
3319 return ret_val;
3320 } else {
3321 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3322 ret_val.val_ptr->uchars_ptr[0] = uchar_value;
3323 for (int i = 0; i < other_value.cstr.val_ptr->n_chars; i++) {
3324 ret_val.val_ptr->uchars_ptr[i+1].uc_group = 0;
3325 ret_val.val_ptr->uchars_ptr[i+1].uc_plane = 0;
3326 ret_val.val_ptr->uchars_ptr[i+1].uc_row = 0;
3327 ret_val.val_ptr->uchars_ptr[i+1].uc_cell =
3328 other_value.cstr.val_ptr->chars_ptr[i];
3329 }
3330 return ret_val;
3331 }
3332 } else {
3333 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3334 ret_val.val_ptr->uchars_ptr[0] = uchar_value;
3335 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
3336 other_value.val_ptr->n_uchars * sizeof(universal_char));
3337 return ret_val;
3338 }
3339}
3340
3341UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value,
3342 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3343{
3344 other_value.must_bound("The right operand of concatenation is an unbound "
3345 "universal charstring element.");
3346 if (other_value.str_val.charstring) {
3347 if (uchar_value.is_char()) {
3348 char result[2];
3349 result[0] = uchar_value.uc_cell;
3350 result[1] =
3351 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3352 return UNIVERSAL_CHARSTRING(2, result);
3353 } else {
3354 universal_char result[2];
3355 result[0] = uchar_value;
3356 result[1].uc_group = 0;
3357 result[1].uc_plane = 0;
3358 result[1].uc_row = 0;
3359 result[1].uc_cell =
3360 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3361 return UNIVERSAL_CHARSTRING(2, result);
3362 }
3363 } else {
3364 universal_char result[2];
3365 result[0] = uchar_value;
3366 result[1] = other_value.get_uchar();
3367 return UNIVERSAL_CHARSTRING(2, result);
3368 }
3369}
3370
3371boolean operator==(const char *string_value,
3372 const UNIVERSAL_CHARSTRING& other_value)
3373{
3374 other_value.must_bound("The right operand of comparison is an unbound "
3375 "universal charstring value.");
3376 int string_len;
3377 if (string_value == NULL) string_len = 0;
3378 else string_len = strlen(string_value);
3379 if (other_value.charstring) {
3380 return other_value.cstr == string_value;
3381 } else {
3382 if (string_len != other_value.val_ptr->n_uchars) return FALSE;
3383 for (int i = 0; i < string_len; i++) {
3384 if (other_value.val_ptr->uchars_ptr[i].uc_group != 0 ||
3385 other_value.val_ptr->uchars_ptr[i].uc_plane != 0 ||
3386 other_value.val_ptr->uchars_ptr[i].uc_row != 0 ||
3387 other_value.val_ptr->uchars_ptr[i].uc_cell != string_value[i])
3388 return FALSE;
3389 }
3390 }
3391 return TRUE;
3392}
3393
3394boolean operator==(const char *string_value,
3395 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3396{
3397 other_value.must_bound("The right operand of comparison is an unbound "
3398 "universal charstring element.");
3399 if (string_value == NULL || string_value[0] == '\0' ||
3400 string_value[1] != '\0') return FALSE;
3401 if (other_value.str_val.charstring)
3402 return other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos]
3403 == string_value[0];
3404 const universal_char& uchar = other_value.get_uchar();
3405 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3406 uchar.uc_cell == string_value[0];
3407}
3408
3409UNIVERSAL_CHARSTRING operator+(const char *string_value,
3410 const UNIVERSAL_CHARSTRING& other_value)
3411{
3412 other_value.must_bound("The right operand of concatenation is an unbound "
3413 "universal charstring value.");
3414 int string_len;
3415 if (string_value == NULL) string_len = 0;
3416 else string_len = strlen(string_value);
3417 if (other_value.charstring) {
3418 UNIVERSAL_CHARSTRING ret_val(string_len + other_value.cstr.val_ptr->n_chars,
3419 true);
3420 memcpy(ret_val.cstr.val_ptr->chars_ptr, string_value, string_len);
3421 memcpy(ret_val.cstr.val_ptr->chars_ptr + string_len,
3422 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
3423 return ret_val;
3424 }
3425 UNIVERSAL_CHARSTRING ret_val(string_len + other_value.val_ptr->n_uchars);
3426 for (int i = 0; i < string_len; i++) {
3427 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
3428 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
3429 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
3430 ret_val.val_ptr->uchars_ptr[i].uc_cell = string_value[i];
3431 }
3432 memcpy(ret_val.val_ptr->uchars_ptr + string_len,
3433 other_value.val_ptr->uchars_ptr,
3434 other_value.val_ptr->n_uchars * sizeof(universal_char));
3435 return ret_val;
3436}
3437
3438UNIVERSAL_CHARSTRING operator+(const char *string_value,
3439 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3440{
3441 other_value.must_bound("The right operand of concatenation is an unbound "
3442 "universal charstring element.");
3443 int string_len;
3444 if (string_value == NULL) string_len = 0;
3445 else string_len = strlen(string_value);
3446 if (other_value.str_val.charstring) {
3447 UNIVERSAL_CHARSTRING ret_val(string_len + 1, true);
3448 memcpy(ret_val.cstr.val_ptr->chars_ptr, string_value, string_len);
3449 ret_val.cstr.val_ptr->chars_ptr[string_len] =
3450 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3451 return ret_val;
3452 }
3453 UNIVERSAL_CHARSTRING ret_val(string_len + 1);
3454 for (int i = 0; i < string_len; i++) {
3455 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
3456 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
3457 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
3458 ret_val.val_ptr->uchars_ptr[i].uc_cell = string_value[i];
3459 }
3460 ret_val.val_ptr->uchars_ptr[string_len] = other_value.get_uchar();
3461 return ret_val;
3462}
3463
3464// member functions of class UNIVERSAL_CHARSTRING_template
3465
3466void UNIVERSAL_CHARSTRING_template::clean_up()
3467{
3468 if (template_selection == VALUE_LIST ||
3469 template_selection == COMPLEMENTED_LIST) delete [] value_list.list_value;
3470 else if (template_selection == STRING_PATTERN) {
3471 if (pattern_value.regexp_init) regfree(&pattern_value.posix_regexp);
3472 delete pattern_string;
3473 }
3474 template_selection = UNINITIALIZED_TEMPLATE;
3475}
3476
3477void UNIVERSAL_CHARSTRING_template::copy_template
3478 (const CHARSTRING_template& other_value)
3479{
3480 switch (other_value.template_selection) {
3481 case SPECIFIC_VALUE:
3482 single_value = other_value.single_value;
3483 break;
3484 case OMIT_VALUE:
3485 case ANY_VALUE:
3486 case ANY_OR_OMIT:
3487 break;
3488 case VALUE_LIST:
3489 case COMPLEMENTED_LIST:
3490 value_list.n_values = other_value.value_list.n_values;
3491 value_list.list_value =
3492 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
3493 for (unsigned int i = 0; i < value_list.n_values; i++)
3494 value_list.list_value[i].copy_template(
3495 other_value.value_list.list_value[i]);
3496 break;
3497 case VALUE_RANGE:
3498 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
3499 "not set when copying a charstring value range template to a universal "
3500 "charstring template.");
3501 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
3502 "not set when copying a charstring value range template to a universal "
3503 "charstring template.");
3504 value_range.min_is_set = TRUE;
3505 value_range.max_is_set = TRUE;
3506 value_range.min_value.uc_group = 0;
3507 value_range.min_value.uc_plane = 0;
3508 value_range.min_value.uc_row = 0;
3509 value_range.min_value.uc_cell = other_value.value_range.min_value;
3510 value_range.max_value.uc_group = 0;
3511 value_range.max_value.uc_plane = 0;
3512 value_range.max_value.uc_row = 0;
3513 value_range.max_value.uc_cell = other_value.value_range.max_value;
3514 break;
3515 case STRING_PATTERN:
3516 pattern_string = new CHARSTRING(other_value.single_value);
3517 pattern_value.regexp_init=FALSE;
3518 break;
3519 default:
3520 TTCN_error("Copying an uninitialized/unsupported charstring template to a "
3521 "universal charstring template.");
3522 }
3523 set_selection(other_value);
3524}
3525
3526void UNIVERSAL_CHARSTRING_template::copy_template
3527 (const UNIVERSAL_CHARSTRING_template& other_value)
3528{
3529 switch (other_value.template_selection) {
3530 case SPECIFIC_VALUE:
3531 single_value = other_value.single_value;
3532 break;
3533 case OMIT_VALUE:
3534 case ANY_VALUE:
3535 case ANY_OR_OMIT:
3536 break;
3537 case VALUE_LIST:
3538 case COMPLEMENTED_LIST:
3539 value_list.n_values = other_value.value_list.n_values;
3540 value_list.list_value =
3541 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
3542 for (unsigned int i = 0; i < value_list.n_values; i++)
3543 value_list.list_value[i].copy_template(
3544 other_value.value_list.list_value[i]);
3545 break;
3546 case VALUE_RANGE:
3547 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
3548 "not set when copying a universal charstring value range template.");
3549 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
3550 "not set when copying a universal charstring value range template.");
3551 value_range = other_value.value_range;
3552 break;
3553 case STRING_PATTERN:
3554 pattern_string = new CHARSTRING(*(other_value.pattern_string));
3555 pattern_value.regexp_init=FALSE;
3556 break;
3557 default:
3558 TTCN_error("Copying an uninitialized/unsupported universal charstring "
3559 "template.");
3560 }
3561 set_selection(other_value);
3562}
3563
3564UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template()
3565{
3566}
3567
3568UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3569 (template_sel other_value) : Restricted_Length_Template(other_value)
3570
3571{
3572 check_single_selection(other_value);
3573}
3574
3575UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3576 (const CHARSTRING& other_value) :
3577 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3578{
3579}
3580
3581UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3582 (const UNIVERSAL_CHARSTRING& other_value) :
3583 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3584{
3585}
3586
3587UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3588 (const CHARSTRING_ELEMENT& other_value) :
3589 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3590{
3591}
3592
3593UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3594 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) :
3595 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3596{
3597}
3598
3599UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3600 (const OPTIONAL<CHARSTRING>& other_value)
3601{
3602 switch (other_value.get_selection()) {
3603 case OPTIONAL_PRESENT:
3604 set_selection(SPECIFIC_VALUE);
3605 single_value = (const CHARSTRING&)other_value;
3606 break;
3607 case OPTIONAL_OMIT:
3608 set_selection(OMIT_VALUE);
3609 break;
3610 default:
3611 TTCN_error("Creating a universal charstring template from an unbound "
3612 "optional field.");
3613 }
3614}
3615
3616UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3617 (const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value)
3618{
3619 switch (other_value.get_selection()) {
3620 case OPTIONAL_PRESENT:
3621 set_selection(SPECIFIC_VALUE);
3622 single_value = (const UNIVERSAL_CHARSTRING&)other_value;
3623 break;
3624 case OPTIONAL_OMIT:
3625 set_selection(OMIT_VALUE);
3626 break;
3627 default:
3628 TTCN_error("Creating a universal charstring template from an unbound "
3629 "optional field.");
3630 }
3631}
3632
3633UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3634 (const CHARSTRING_template& other_value)
3635: Restricted_Length_Template()
3636{
3637 copy_template(other_value);
3638}
3639
3640UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3641 (const UNIVERSAL_CHARSTRING_template& other_value)
3642: Restricted_Length_Template()
3643{
3644 copy_template(other_value);
3645}
3646
3647UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3648 (template_sel p_sel, const CHARSTRING& p_str)
3649: Restricted_Length_Template(STRING_PATTERN)
3650{
3651 if(p_sel!=STRING_PATTERN)
3652 TTCN_error("Internal error: Initializing a universal charstring"
3653 "pattern template with invalid selection.");
3654 pattern_string = new CHARSTRING(p_str);
3655 pattern_value.regexp_init=FALSE;
3656}
3657
3658UNIVERSAL_CHARSTRING_template::~UNIVERSAL_CHARSTRING_template()
3659{
3660 clean_up();
3661}
3662
3663UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3664 (template_sel other_value)
3665{
3666 check_single_selection(other_value);
3667 clean_up();
3668 set_selection(other_value);
3669 return *this;
3670}
3671
3672UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3673 (const CHARSTRING& other_value)
3674{
3675 other_value.must_bound("Assignment of an unbound charstring value to a "
3676 "universal charstring template.");
3677 clean_up();
3678 set_selection(SPECIFIC_VALUE);
3679 single_value = other_value;
3680 return *this;
3681}
3682
3683UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3684 (const UNIVERSAL_CHARSTRING& other_value)
3685{
3686 other_value.must_bound("Assignment of an unbound universal charstring value "
3687 "to a template.");
3688 clean_up();
3689 set_selection(SPECIFIC_VALUE);
3690 single_value = other_value;
3691 return *this;
3692}
3693
3694UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3695 (const CHARSTRING_ELEMENT& other_value)
3696{
3697 other_value.must_bound("Assignment of an unbound charstring element to a "
3698 "universal charstring template.");
3699 clean_up();
3700 set_selection(SPECIFIC_VALUE);
3701 single_value = other_value;
3702 return *this;
3703}
3704
3705UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3706 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3707{
3708 other_value.must_bound("Assignment of an unbound universal charstring "
3709 "element to a template.");
3710 clean_up();
3711 set_selection(SPECIFIC_VALUE);
3712 single_value = other_value;
3713 return *this;
3714}
3715
3716UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3717 (const OPTIONAL<CHARSTRING>& other_value)
3718{
3719 clean_up();
3720 switch (other_value.get_selection()) {
3721 case OPTIONAL_PRESENT:
3722 set_selection(SPECIFIC_VALUE);
3723 single_value = (const CHARSTRING&)other_value;
3724 break;
3725 case OPTIONAL_OMIT:
3726 set_selection(OMIT_VALUE);
3727 break;
3728 default:
3729 TTCN_error("Assignment of an unbound optional field to a universal "
3730 "charstring template.");
3731 }
3732 return *this;
3733}
3734
3735UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3736 (const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value)
3737{
3738 clean_up();
3739 switch (other_value.get_selection()) {
3740 case OPTIONAL_PRESENT:
3741 set_selection(SPECIFIC_VALUE);
3742 single_value = (const UNIVERSAL_CHARSTRING&)other_value;
3743 break;
3744 case OPTIONAL_OMIT:
3745 set_selection(OMIT_VALUE);
3746 break;
3747 default:
3748 TTCN_error("Assignment of an unbound optional field to a universal "
3749 "charstring template.");
3750 }
3751 return *this;
3752}
3753
3754UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3755 (const CHARSTRING_template& other_value)
3756{
3757 clean_up();
3758 copy_template(other_value);
3759 return *this;
3760}
3761
3762UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3763 (const UNIVERSAL_CHARSTRING_template& other_value)
3764{
3765 if (&other_value != this) {
3766 clean_up();
3767 copy_template(other_value);
3768 }
3769 return *this;
3770}
3771
3772UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value)
3773{
3774 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3775 TTCN_error("Accessing a universal charstring element of a non-specific "
3776 "universal charstring template.");
3777 return single_value[index_value];
3778}
3779
3780UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](const INTEGER& index_value)
3781{
3782 index_value.must_bound("Indexing a universal charstring template with an "
3783 "unbound integer value.");
3784 return (*this)[(int)index_value];
3785}
3786
3787const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value) const
3788{
3789 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3790 TTCN_error("Accessing a universal charstring element of a non-specific "
3791 "universal charstring template.");
3792 return single_value[index_value];
3793}
3794
3795const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](const INTEGER& index_value) const
3796{
3797 index_value.must_bound("Indexing a universal charstring template with an "
3798 "unbound integer value.");
3799 return (*this)[(int)index_value];
3800}
3801
3802boolean UNIVERSAL_CHARSTRING_template::match
3803 (const UNIVERSAL_CHARSTRING& other_value) const
3804{
3805 if (!other_value.is_bound()) return FALSE;
3806 int value_length = other_value.lengthof();
3807 if (!match_length(value_length)) return FALSE;
3808 switch (template_selection) {
3809 case SPECIFIC_VALUE:
3810 return single_value == other_value;
3811 case OMIT_VALUE:
3812 return FALSE;
3813 case ANY_VALUE:
3814 case ANY_OR_OMIT:
3815 return TRUE;
3816 case VALUE_LIST:
3817 case COMPLEMENTED_LIST:
3818 for (unsigned int i = 0; i < value_list.n_values; i++)
3819 if (value_list.list_value[i].match(other_value))
3820 return template_selection == VALUE_LIST;
3821 return template_selection == COMPLEMENTED_LIST;
3822 case VALUE_RANGE: {
3823 if (!value_range.min_is_set) TTCN_error("The lower bound is not set when "
3824 "matching with a universal charstring value range template.");
3825 if (!value_range.max_is_set) TTCN_error("The upper bound is not set when "
3826 "matching with a universal charstring value range template.");
3827 if (value_range.max_value < value_range.min_value)
3828 TTCN_error("The lower bound is greater than the upper bound "
3829 "when matching with a universal charstring value range template.");
3830 const universal_char *uchars_ptr = other_value;
3831 for (int i = 0; i < value_length; i++) {
3832 if (uchars_ptr[i] < value_range.min_value ||
3833 value_range.max_value < uchars_ptr[i]) return FALSE;
3834 }
3835 return TRUE; }
3836 case STRING_PATTERN: {
3837 if (!pattern_value.regexp_init) {
3838 char *posix_str =
3839 TTCN_pattern_to_regexp_uni((const char*)(*pattern_string));
3840 if(posix_str==NULL) {
3841 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
3842 (const char*)(*pattern_string));
3843 }
3844 int ret_val=regcomp(&pattern_value.posix_regexp, posix_str,
3845 REG_EXTENDED|REG_NOSUB);
3846 Free(posix_str);
3847 if(ret_val!=0) {
3848 /* regexp error */
3849 char msg[ERRMSG_BUFSIZE];
3850 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
3851 regfree(&pattern_value.posix_regexp);
3852 TTCN_error("Pattern matching error: %s", msg);
3853 }
3854 pattern_value.regexp_init=TRUE;
3855 }
3856 char* other_value_converted = other_value.convert_to_regexp_form();
3857 int ret_val=regexec(&pattern_value.posix_regexp, other_value_converted, 0,
3858 NULL, 0);
3859 Free(other_value_converted);
3860 switch (ret_val) {
3861 case 0:
3862 return TRUE;
3863 case REG_NOMATCH:
3864 return FALSE;
3865 default:
3866 /* regexp error */
3867 char msg[ERRMSG_BUFSIZE];
3868 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
3869 TTCN_error("Pattern matching error: %s", msg);
3870 }
3871 break;}
3872 default:
3873 TTCN_error("Matching with an uninitialized/unsupported universal "
3874 "charstring template.");
3875 }
3876 return FALSE;
3877}
3878
3879const UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING_template::valueof() const
3880{
3881 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3882 TTCN_error("Performing valueof or send operation on a non-specific "
3883 "universal charstring template.");
3884 return single_value;
3885}
3886
3887int UNIVERSAL_CHARSTRING_template::lengthof() const
3888{
3889 int min_length;
3890 boolean has_any_or_none;
3891 if (is_ifpresent)
3892 TTCN_error("Performing lengthof() operation on a universal charstring "
3893 "template which has an ifpresent attribute.");
3894 switch (template_selection)
3895 {
3896 case SPECIFIC_VALUE:
3897 min_length = single_value.lengthof();
3898 has_any_or_none = FALSE;
3899 break;
3900 case OMIT_VALUE:
3901 TTCN_error("Performing lengthof() operation on a universal charstring "
3902 "template containing omit value.");
3903 case ANY_VALUE:
3904 case ANY_OR_OMIT:
3905 case VALUE_RANGE:
3906 min_length = 0;
3907 has_any_or_none = TRUE; // max. length is infinity
3908 break;
3909 case VALUE_LIST:
3910 {
3911 // error if any element does not have length or the lengths differ
3912 if (value_list.n_values<1)
3913 TTCN_error("Internal error: "
3914 "Performing lengthof() operation on a universal charstring "
3915 "template containing an empty list.");
3916 int item_length = value_list.list_value[0].lengthof();
3917 for (unsigned int i = 1; i < value_list.n_values; i++) {
3918 if (value_list.list_value[i].lengthof()!=item_length)
3919 TTCN_error("Performing lengthof() operation on a universal charstring "
3920 "template containing a value list with different lengths.");
3921 }
3922 min_length = item_length;
3923 has_any_or_none = FALSE;
3924 break;
3925 }
3926 case COMPLEMENTED_LIST:
3927 TTCN_error("Performing lengthof() operation on a universal charstring "
3928 "template containing complemented list.");
3929 case STRING_PATTERN:
3930 TTCN_error("Performing lengthof() operation on a universal charstring "
3931 "template containing a pattern is not allowed.");
3932 default:
3933 TTCN_error("Performing lengthof() operation on an "
3934 "uninitialized/unsupported universal charstring template.");
3935 }
3936 return check_section_is_single(min_length, has_any_or_none,
3937 "length", "a", "universal charstring template");
3938}
3939
3940void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type,
3941 unsigned int list_length)
3942{
3943 clean_up();
3944 switch (template_type) {
3945 case VALUE_LIST:
3946 case COMPLEMENTED_LIST:
3947 set_selection(template_type);
3948 value_list.n_values = list_length;
3949 value_list.list_value = new UNIVERSAL_CHARSTRING_template[list_length];
3950 break;
3951 case VALUE_RANGE:
3952 set_selection(VALUE_RANGE);
3953 value_range.min_is_set = FALSE;
3954 value_range.max_is_set = FALSE;
3955 break;
3956 default:
3957 TTCN_error("Setting an invalid type for a universal charstring template.");
3958 }
3959}
3960
3961UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::list_item
3962 (unsigned int list_index)
3963{
3964 if (template_selection != VALUE_LIST &&
3965 template_selection != COMPLEMENTED_LIST)
3966 TTCN_error("Accessing a list element of a non-list universal charstring "
3967 "template.");
3968 if (list_index >= value_list.n_values)
3969 TTCN_error("Index overflow in a universal charstring value list template.");
3970 return value_list.list_value[list_index];
3971}
3972
3973void UNIVERSAL_CHARSTRING_template::set_min
3974 (const UNIVERSAL_CHARSTRING& min_value)
3975{
3976 if (template_selection != VALUE_RANGE) TTCN_error("Setting the lower bound "
3977 "for a non-range universal charstring template.");
3978 min_value.must_bound("Setting an unbound value as lower bound in a "
3979 "universal charstring value range template.");
3980 int length = min_value.lengthof();
3981 if (length != 1) TTCN_error("The length of the lower bound in a universal "
3982 "charstring value range template must be 1 instead of %d.", length);
3983 value_range.min_is_set = TRUE;
3984 value_range.min_value = *(const universal_char*)min_value;
3985 if (value_range.max_is_set && value_range.max_value < value_range.min_value)
3986 TTCN_error("The lower bound in a universal charstring value range template "
3987 "is greater than the upper bound.");
3988}
3989
3990void UNIVERSAL_CHARSTRING_template::set_max
3991 (const UNIVERSAL_CHARSTRING& max_value)
3992{
3993 if (template_selection != VALUE_RANGE) TTCN_error("Setting the upper bound "
3994 "for a non-range universal charstring template.");
3995 max_value.must_bound("Setting an unbound value as upper bound in a "
3996 "universal charstring value range template.");
3997 int length = max_value.lengthof();
3998 if (length != 1) TTCN_error("The length of the upper bound in a universal "
3999 "charstring value range template must be 1 instead of %d.", length);
4000 value_range.max_is_set = TRUE;
4001 value_range.max_value = *(const universal_char*)max_value;
4002 if (value_range.min_is_set && value_range.max_value < value_range.min_value)
4003 TTCN_error("The upper bound in a universal charstring value range template "
4004 "is smaller than the lower bound.");
4005}
4006
4007void UNIVERSAL_CHARSTRING_template::log() const
4008{
4009 switch (template_selection) {
4010 case STRING_PATTERN:
4011 CHARSTRING_template::log_pattern(pattern_string->lengthof(),
4012 (const char*)*pattern_string);
4013 break;
4014 case SPECIFIC_VALUE:
4015 single_value.log();
4016 break;
4017 case COMPLEMENTED_LIST:
4018 TTCN_Logger::log_event_str("complement ");
4019 // no break
4020 case VALUE_LIST:
4021 TTCN_Logger::log_char('(');
4022 for(unsigned int i = 0; i < value_list.n_values; i++) {
4023 if (i > 0) TTCN_Logger::log_event_str(", ");
4024 value_list.list_value[i].log();
4025 }
4026 TTCN_Logger::log_char(')');
4027 break;
4028 case VALUE_RANGE:
4029 TTCN_Logger::log_char('(');
4030 if (value_range.min_is_set) {
4031 if (is_printable(value_range.min_value)) {
4032 TTCN_Logger::log_char('"');
4033 TTCN_Logger::log_char_escaped(value_range.min_value.uc_cell);
4034 TTCN_Logger::log_char('"');
4035 } else {
4036 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4037 value_range.min_value.uc_group, value_range.min_value.uc_plane,
4038 value_range.min_value.uc_row, value_range.min_value.uc_cell);
4039 }
4040 } else TTCN_Logger::log_event_str("<unknown lower bound>");
4041 TTCN_Logger::log_event_str(" .. ");
4042 if (value_range.max_is_set) {
4043 if (is_printable(value_range.max_value)) {
4044 TTCN_Logger::log_char('"');
4045 TTCN_Logger::log_char_escaped(value_range.max_value.uc_cell);
4046 TTCN_Logger::log_char('"');
4047 } else {
4048 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4049 value_range.max_value.uc_group, value_range.max_value.uc_plane,
4050 value_range.max_value.uc_row, value_range.max_value.uc_cell);
4051 }
4052 } else TTCN_Logger::log_event_str("<unknown upper bound>");
4053 TTCN_Logger::log_char(')');
4054 break;
4055 default:
4056 log_generic();
4057 break;
4058 }
4059 log_restricted();
4060 log_ifpresent();
4061}
4062
4063void UNIVERSAL_CHARSTRING_template::log_match
4064 (const UNIVERSAL_CHARSTRING& match_value) const
4065{
4066 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
4067 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
4068 TTCN_Logger::print_logmatch_buffer();
4069 TTCN_Logger::log_event_str(" := ");
4070 }
4071 match_value.log();
4072 TTCN_Logger::log_event_str(" with ");
4073 log();
4074 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
4075 else TTCN_Logger::log_event_str(" unmatched");
4076}
4077
4078void UNIVERSAL_CHARSTRING_template::set_param(Module_Param& param) {
4079 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "universal charstring template");
4080 switch (param.get_type()) {
4081 case Module_Param::MP_Omit:
4082 *this = OMIT_VALUE;
4083 break;
4084 case Module_Param::MP_Any:
4085 *this = ANY_VALUE;
4086 break;
4087 case Module_Param::MP_AnyOrNone:
4088 *this = ANY_OR_OMIT;
4089 break;
4090 case Module_Param::MP_List_Template:
4091 case Module_Param::MP_ComplementList_Template:
4092 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
4093 for (size_t i=0; i<param.get_size(); i++) {
4094 list_item(i).set_param(*param.get_elem(i));
4095 }
4096 break;
4097 case Module_Param::MP_Charstring:
4098 *this = CHARSTRING(param.get_string_size(), (char*)param.get_string_data());
4099 break;
4100 case Module_Param::MP_Universal_Charstring:
4101 *this = UNIVERSAL_CHARSTRING(param.get_string_size(), (universal_char*)param.get_string_data());
4102 break;
4103 case Module_Param::MP_StringRange: {
4104 universal_char lower_uchar = param.get_lower_uchar();
4105 universal_char upper_uchar = param.get_upper_uchar();
4106 clean_up();
4107 set_selection(VALUE_RANGE);
4108 value_range.min_is_set = TRUE;
4109 value_range.max_is_set = TRUE;
4110 value_range.min_value = lower_uchar;
4111 value_range.max_value = upper_uchar;
4112 } break;
4113 case Module_Param::MP_Pattern:
4114 clean_up();
4115 pattern_string = new CHARSTRING(param.get_pattern());
4116 pattern_value.regexp_init = FALSE;
4117 set_selection(STRING_PATTERN);
4118 break;
4119 default:
4120 param.type_error("universal charstring template");
4121 }
4122 is_ifpresent = param.get_ifpresent();
4123 set_length_range(param);
4124}
4125
4126void UNIVERSAL_CHARSTRING_template::encode_text(Text_Buf& text_buf) const
4127{
4128 encode_text_restricted(text_buf);
4129 switch (template_selection) {
4130 case OMIT_VALUE:
4131 case ANY_VALUE:
4132 case ANY_OR_OMIT:
4133 break;
4134 case SPECIFIC_VALUE:
4135 single_value.encode_text(text_buf);
4136 break;
4137 case VALUE_LIST:
4138 case COMPLEMENTED_LIST:
4139 text_buf.push_int(value_list.n_values);
4140 for (unsigned int i = 0; i < value_list.n_values; i++)
4141 value_list.list_value[i].encode_text(text_buf);
4142 break;
4143 case VALUE_RANGE: {
4144 if (!value_range.min_is_set) TTCN_error("Text encoder: The lower bound is "
4145 "not set in a universal charstring value range template.");
4146 if (!value_range.max_is_set) TTCN_error("Text encoder: The upper bound is "
4147 "not set in a universal charstring value range template.");
4148 unsigned char buf[8];
4149 buf[0] = value_range.min_value.uc_group;
4150 buf[1] = value_range.min_value.uc_plane;
4151 buf[2] = value_range.min_value.uc_row;
4152 buf[3] = value_range.min_value.uc_cell;
4153 buf[4] = value_range.max_value.uc_group;
4154 buf[5] = value_range.max_value.uc_plane;
4155 buf[6] = value_range.max_value.uc_row;
4156 buf[7] = value_range.max_value.uc_cell;
4157 text_buf.push_raw(8, buf);
4158 break; }
4159 default:
4160 TTCN_error("Text encoder: Encoding an uninitialized/unsupported universal "
4161 "charstring template.");
4162 }
4163}
4164
4165void UNIVERSAL_CHARSTRING_template::decode_text(Text_Buf& text_buf)
4166{
4167 clean_up();
4168 decode_text_restricted(text_buf);
4169 switch (template_selection) {
4170 case OMIT_VALUE:
4171 case ANY_VALUE:
4172 case ANY_OR_OMIT:
4173 break;
4174 case SPECIFIC_VALUE:
4175 single_value.decode_text(text_buf);
4176 break;
4177 case VALUE_LIST:
4178 case COMPLEMENTED_LIST:
4179 value_list.n_values = text_buf.pull_int().get_val();
4180 value_list.list_value =
4181 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
4182 for (unsigned int i = 0; i < value_list.n_values; i++)
4183 value_list.list_value[i].decode_text(text_buf);
4184 break;
4185 case VALUE_RANGE: {
4186 unsigned char buf[8];
4187 text_buf.pull_raw(8, buf);
4188 value_range.min_value.uc_group = buf[0];
4189 value_range.min_value.uc_plane = buf[1];
4190 value_range.min_value.uc_row = buf[2];
4191 value_range.min_value.uc_cell = buf[3];
4192 value_range.max_value.uc_group = buf[4];
4193 value_range.max_value.uc_plane = buf[5];
4194 value_range.max_value.uc_row = buf[6];
4195 value_range.max_value.uc_cell = buf[7];
4196 if (value_range.max_value < value_range.min_value)
4197 TTCN_error("Text decoder: The received lower bound is greater than the "
4198 "upper bound in a universal charstring value range template.");
4199 value_range.min_is_set = TRUE;
4200 value_range.max_is_set = TRUE;
4201 break; }
4202 default:
4203 TTCN_error("Text decoder: An unknown/unsupported selection was "
4204 "received for a universal charstring template.");
4205 }
4206}
4207
4208boolean UNIVERSAL_CHARSTRING_template::is_present() const
4209{
4210 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
4211 return !match_omit();
4212}
4213
4214boolean UNIVERSAL_CHARSTRING_template::match_omit() const
4215{
4216 if (is_ifpresent) return TRUE;
4217 switch (template_selection) {
4218 case OMIT_VALUE:
4219 case ANY_OR_OMIT:
4220 return TRUE;
4221 case VALUE_LIST:
4222 case COMPLEMENTED_LIST:
4223 for (unsigned int i=0; i<value_list.n_values; i++)
4224 if (value_list.list_value[i].match_omit())
4225 return template_selection==VALUE_LIST;
4226 return template_selection==COMPLEMENTED_LIST;
4227 default:
4228 return FALSE;
4229 }
4230 return FALSE;
4231}
4232
4233#ifndef TITAN_RUNTIME_2
4234void UNIVERSAL_CHARSTRING_template::check_restriction(template_res t_res,
4235 const char* t_name) const
4236{
4237 if (template_selection==UNINITIALIZED_TEMPLATE) return;
4238 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
4239 case TR_VALUE:
4240 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
4241 break;
4242 case TR_OMIT:
4243 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
4244 template_selection==SPECIFIC_VALUE)) return;
4245 break;
4246 case TR_PRESENT:
4247 if (!match_omit()) return;
4248 break;
4249 default:
4250 return;
4251 }
4252 TTCN_error("Restriction `%s' on template of type %s violated.",
4253 get_res_name(t_res), t_name ? t_name : "universal charstring");
4254}
4255#endif
4256
4257const CHARSTRING& UNIVERSAL_CHARSTRING_template::get_single_value() const {
4258 if (!pattern_string)
4259 TTCN_error("Pattern string does not exist in universal charstring template");
4260 return *pattern_string;
4261}
4262
4263/**
4264 * ISO 2022 conversion functions -- these can be overwritten by users
4265 * by defining their own versions. Because these --of course :)-- are
4266 * not really conform to ISO 2022. :o)
4267 */
4268
4269/** TTCN_UCSTR_2_ISO2022: A dummy common implementation. */
4270OCTETSTRING TTCN_UCSTR_2_ISO2022(const UNIVERSAL_CHARSTRING& p_s)
4271{
4272 const universal_char* ucstr=static_cast<const universal_char*>(p_s);
4273 int len=p_s.lengthof();
4274 unsigned char* osstr=(unsigned char*)Malloc(len);
4275 for(int i=0; i<len; i++) osstr[i]=ucstr[i].uc_cell;
4276 OCTETSTRING os(len, osstr);
4277 Free(osstr);
4278 return os;
4279}
4280
4281/** TTCN_ISO2022_2_UCSTR: A dummy common implementation. */
4282UNIVERSAL_CHARSTRING TTCN_ISO2022_2_UCSTR(const OCTETSTRING& p_os)
4283{
4284 const unsigned char* osstr=static_cast<const unsigned char*>(p_os);
4285 int len=p_os.lengthof();
4286 universal_char* ucstr=(universal_char*)Malloc(len*sizeof(*ucstr));
4287 for(int i=0; i<len; i++) {
4288 ucstr[i].uc_group=0;
4289 ucstr[i].uc_plane=0;
4290 ucstr[i].uc_row=0;
4291 ucstr[i].uc_cell=osstr[i];
4292 }
4293 UNIVERSAL_CHARSTRING us(len, ucstr);
4294 Free(ucstr);
4295 return us;
4296}
4297
4298OCTETSTRING TTCN_TeletexString_2_ISO2022(const TeletexString& p_s)
4299{
4300 return TTCN_UCSTR_2_ISO2022(p_s);
4301}
4302
4303TeletexString TTCN_ISO2022_2_TeletexString(const OCTETSTRING& p_os)
4304{
4305 return TTCN_ISO2022_2_UCSTR(p_os);
4306}
4307
4308OCTETSTRING TTCN_VideotexString_2_ISO2022(const VideotexString& p_s)
4309{
4310 return TTCN_UCSTR_2_ISO2022(p_s);
4311}
4312
4313VideotexString TTCN_ISO2022_2_VideotexString(const OCTETSTRING& p_os)
4314{
4315 return TTCN_ISO2022_2_UCSTR(p_os);
4316}
4317
4318OCTETSTRING TTCN_GraphicString_2_ISO2022(const GraphicString& p_s)
4319{
4320 return TTCN_UCSTR_2_ISO2022(p_s);
4321}
4322
4323GraphicString TTCN_ISO2022_2_GraphicString(const OCTETSTRING& p_os)
4324{
4325 return TTCN_ISO2022_2_UCSTR(p_os);
4326}
4327
4328OCTETSTRING TTCN_GeneralString_2_ISO2022(const GeneralString& p_s)
4329{
4330 return TTCN_UCSTR_2_ISO2022(p_s);
4331}
4332
4333GeneralString TTCN_ISO2022_2_GeneralString(const OCTETSTRING& p_os)
4334{
4335 return TTCN_ISO2022_2_UCSTR(p_os);
4336}
This page took 0.184064 seconds and 5 git commands to generate.