Sync with 5.4.0
[deliverable/titan.core.git] / core / Universal_charstring.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
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
3abe9331 936boolean UNIVERSAL_CHARSTRING::set_param_internal(Module_Param& param, boolean allow_pattern) {
937 boolean is_pattern = FALSE;
970ed795 938 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "universal charstring value");
3abe9331 939 Module_Param_Ptr mp = &param;
940 if (param.get_type() == Module_Param::MP_Reference) {
941 mp = param.get_referenced_param();
942 }
943 switch (mp->get_type()) {
970ed795
EL
944 case Module_Param::MP_Charstring: {
945 switch (param.get_operation_type()) {
946 case Module_Param::OT_ASSIGN:
947 clean_up();
948 // no break
949 case Module_Param::OT_CONCAT: {
950 TTCN_Buffer buff;
3abe9331 951 buff.put_s(mp->get_string_size(), (unsigned char*)mp->get_string_data());
970ed795
EL
952 if (is_bound()) {
953 *this = *this + from_UTF8_buffer(buff);
954 } else {
955 *this = from_UTF8_buffer(buff);
956 }
957 break; }
958 default:
959 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
960 }
961 break; }
962 case Module_Param::MP_Universal_Charstring: {
963 switch (param.get_operation_type()) {
964 case Module_Param::OT_ASSIGN:
965 clean_up();
966 // no break
3abe9331 967 case Module_Param::OT_CONCAT:
968 if (is_bound()) {
969 *this = *this + UNIVERSAL_CHARSTRING(mp->get_string_size(), (universal_char*)mp->get_string_data());
970ed795 970 } else {
3abe9331 971 *this = UNIVERSAL_CHARSTRING(mp->get_string_size(), (universal_char*)mp->get_string_data());
970ed795 972 }
3abe9331 973 break;
970ed795
EL
974 default:
975 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
976 }
977 break; }
3abe9331 978 case Module_Param::MP_Expression:
979 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
980 UNIVERSAL_CHARSTRING operand1, operand2;
981 is_pattern = operand1.set_param_internal(*mp->get_operand1(), allow_pattern);
982 operand2.set_param(*mp->get_operand2());
983 if (param.get_operation_type() == Module_Param::OT_CONCAT) {
984 *this = *this + operand1 + operand2;
985 }
986 else {
987 *this = operand1 + operand2;
988 }
989 }
990 else {
991 param.expr_type_error("a universal charstring");
992 }
993 break;
994 case Module_Param::MP_Pattern:
995 if (allow_pattern) {
996 *this = CHARSTRING(mp->get_pattern());
997 is_pattern = TRUE;
998 break;
999 }
1000 // else fall through
970ed795
EL
1001 default:
1002 param.type_error("universal charstring value");
1003 }
3abe9331 1004 return is_pattern;
1005}
1006
1007void UNIVERSAL_CHARSTRING::set_param(Module_Param& param) {
1008 set_param_internal(param, FALSE);
1009}
1010
1011Module_Param* UNIVERSAL_CHARSTRING::get_param(Module_Param_Name& param_name) const
1012{
1013 if (!is_bound()) {
1014 return new Module_Param_Unbound();
1015 }
1016 if (charstring) {
1017 return cstr.get_param(param_name);
1018 }
1019 universal_char* val_cpy = (universal_char*)Malloc(val_ptr->n_uchars * sizeof(universal_char));
1020 memcpy(val_cpy, val_ptr->uchars_ptr, val_ptr->n_uchars * sizeof(universal_char));
1021 return new Module_Param_Universal_Charstring(val_ptr->n_uchars, val_cpy);
970ed795
EL
1022}
1023
1024void UNIVERSAL_CHARSTRING::encode_text(Text_Buf& text_buf) const
1025{
1026 must_bound("Text encoder: Encoding an unbound universal charstring value.");
1027 if (charstring)
1028 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
1029 text_buf.push_int(val_ptr->n_uchars);
1030 for (int i = 0; i < val_ptr->n_uchars; i++) {
1031 unsigned char buf[4];
1032 buf[0] = val_ptr->uchars_ptr[i].uc_group;
1033 buf[1] = val_ptr->uchars_ptr[i].uc_plane;
1034 buf[2] = val_ptr->uchars_ptr[i].uc_row;
1035 buf[3] = val_ptr->uchars_ptr[i].uc_cell;
1036 text_buf.push_raw(4, buf);
1037 }
1038}
1039
1040void UNIVERSAL_CHARSTRING::decode_text(Text_Buf& text_buf)
1041{
1042 int n_uchars = text_buf.pull_int().get_val();
1043 if (n_uchars < 0) TTCN_error("Text decoder: Negative length was received "
1044 "for a universal charstring.");
1045 clean_up();
1046 charstring = false;
1047 init_struct(n_uchars);
1048 for (int i = 0; i < n_uchars; i++) {
1049 unsigned char buf[4];
1050 text_buf.pull_raw(4, buf);
1051 val_ptr->uchars_ptr[i].uc_group = buf[0];
1052 val_ptr->uchars_ptr[i].uc_plane = buf[1];
1053 val_ptr->uchars_ptr[i].uc_row = buf[2];
1054 val_ptr->uchars_ptr[i].uc_cell = buf[3];
1055 }
1056}
1057
1058void UNIVERSAL_CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td,
1059 TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
1060{
1061 va_list pvar;
1062 va_start(pvar, p_coding);
1063 switch(p_coding) {
1064 case TTCN_EncDec::CT_BER: {
1065 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
1066 unsigned BER_coding=va_arg(pvar, unsigned);
1067 BER_encode_chk_coding(BER_coding);
1068 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
1069 tlv->put_in_buffer(p_buf);
1070 ASN_BER_TLV_t::destruct(tlv);
1071 break;}
1072 case TTCN_EncDec::CT_RAW: {
1073 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
1074 TTCN_EncDec_ErrorContext::error_internal
1075 ("No RAW descriptor available for type '%s'.", p_td.name);
1076 break;}
a38c6d4c 1077 case TTCN_EncDec::CT_TEXT: {
1078 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
1079 if(!p_td.text)
1080 TTCN_EncDec_ErrorContext::error_internal
1081 ("No TEXT descriptor available for type '%s'.", p_td.name);
1082 TEXT_encode(p_td,p_buf);
1083 break;}
970ed795
EL
1084 case TTCN_EncDec::CT_XER: {
1085 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
1086 unsigned XER_coding=va_arg(pvar, unsigned);
1087 switch (p_td.asnbasetype) {
1088 case TTCN_Typedescriptor_t::BMPSTRING:
1089 case TTCN_Typedescriptor_t::UNIVERSALSTRING:
1090 XER_coding |= XER_ESCAPE_ENTITIES;
1091 break;
1092 default: // nothing to do
1093 break;
1094 }
af710487 1095 XER_encode(*p_td.xer,p_buf, XER_coding, 0, 0);
970ed795
EL
1096 p_buf.put_c('\n');
1097 break; }
1098 case TTCN_EncDec::CT_JSON: {
1099 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
1100 if(!p_td.json)
1101 TTCN_EncDec_ErrorContext::error_internal
1102 ("No JSON descriptor available for type '%s'.", p_td.name);
1103 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
1104 JSON_encode(p_td, tok);
1105 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
1106 break; }
1107 default:
1108 TTCN_error("Unknown coding method requested to encode type '%s'",
1109 p_td.name);
1110 }
1111 va_end(pvar);
1112}
1113
1114void UNIVERSAL_CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td,
1115 TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
1116{
1117 va_list pvar;
1118 va_start(pvar, p_coding);
1119 switch(p_coding) {
1120 case TTCN_EncDec::CT_BER: {
1121 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
1122 unsigned L_form=va_arg(pvar, unsigned);
1123 ASN_BER_TLV_t tlv;
1124 BER_decode_str2TLV(p_buf, tlv, L_form);
1125 BER_decode_TLV(p_td, tlv, L_form);
1126 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
1127 break;}
1128 case TTCN_EncDec::CT_RAW: {
1129 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
1130 TTCN_EncDec_ErrorContext::error_internal
1131 ("No RAW descriptor available for type '%s'.", p_td.name);
1132 break;}
a38c6d4c 1133 case TTCN_EncDec::CT_TEXT: {
1134 Limit_Token_List limit;
1135 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
1136 if(!p_td.text)
1137 TTCN_EncDec_ErrorContext::error_internal
1138 ("No TEXT descriptor available for type '%s'.", p_td.name);
1139 const unsigned char *b=p_buf.get_data();
1140 if(b[p_buf.get_len()-1]!='\0'){
1141 p_buf.set_pos(p_buf.get_len());
1142 p_buf.put_zero(8,ORDER_LSB);
1143 p_buf.rewind();
1144 }
1145 if(TEXT_decode(p_td,p_buf,limit)<0)
1146 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
1147 "Can not decode type '%s', because invalid or incomplete"
1148 " message was received"
1149 , p_td.name);
1150 break;}
970ed795
EL
1151 case TTCN_EncDec::CT_XER : {
1152 unsigned XER_coding=va_arg(pvar, unsigned);
1153 XmlReaderWrap reader(p_buf);
1154 int success = reader.Read();
1155 for (; success==1; success=reader.Read()) {
1156 int type = reader.NodeType();
1157 if (type==XML_READER_TYPE_ELEMENT)
1158 break;
1159 }
af710487 1160 XER_decode(*p_td.xer, reader, XER_coding, 0);
970ed795
EL
1161 size_t bytes = reader.ByteConsumed();
1162 p_buf.set_pos(bytes);
1163 break; }
1164 case TTCN_EncDec::CT_JSON: {
1165 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
1166 if(!p_td.json)
1167 TTCN_EncDec_ErrorContext::error_internal
1168 ("No JSON descriptor available for type '%s'.", p_td.name);
1169 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
1170 if(JSON_decode(p_td, tok, false)<0)
1171 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
1172 "Can not decode type '%s', because invalid or incomplete"
1173 " message was received"
1174 , p_td.name);
1175 p_buf.set_pos(tok.get_buf_pos());
1176 break;}
1177 default:
1178 TTCN_error("Unknown coding method requested to decode type '%s'",
1179 p_td.name);
1180 }
1181 va_end(pvar);
1182}
1183
1184ASN_BER_TLV_t*
1185UNIVERSAL_CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
1186 unsigned p_coding) const
1187{
1188 if (charstring)
1189 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
1190 BER_chk_descr(p_td);
1191 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
1192 if(!new_tlv) {
1193 TTCN_Buffer buf;
1194 switch(p_td.asnbasetype) {
1195 case TTCN_Typedescriptor_t::TELETEXSTRING:
1196 buf.put_os(TTCN_TeletexString_2_ISO2022(*this));
1197 break;
1198 case TTCN_Typedescriptor_t::VIDEOTEXSTRING:
1199 buf.put_os(TTCN_VideotexString_2_ISO2022(*this));
1200 break;
1201 case TTCN_Typedescriptor_t::GRAPHICSTRING:
1202 buf.put_os(TTCN_GraphicString_2_ISO2022(*this));
1203 break;
1204 case TTCN_Typedescriptor_t::GENERALSTRING:
1205 buf.put_os(TTCN_GeneralString_2_ISO2022(*this));
1206 break;
1207 case TTCN_Typedescriptor_t::UNIVERSALSTRING:
1208 for(int i=0; i<val_ptr->n_uchars; i++) {
1209 buf.put_c(val_ptr->uchars_ptr[i].uc_group);
1210 buf.put_c(val_ptr->uchars_ptr[i].uc_plane);
1211 buf.put_c(val_ptr->uchars_ptr[i].uc_row);
1212 buf.put_c(val_ptr->uchars_ptr[i].uc_cell);
1213 }
1214 break;
1215 case TTCN_Typedescriptor_t::BMPSTRING:
1216 for(int i=0; i<val_ptr->n_uchars; i++) {
1217 buf.put_c(val_ptr->uchars_ptr[i].uc_row);
1218 buf.put_c(val_ptr->uchars_ptr[i].uc_cell);
1219 }
1220 break;
1221 case TTCN_Typedescriptor_t::UTF8STRING:
1222 encode_utf8(buf);
1223 break;
1224 default:
1225 TTCN_EncDec_ErrorContext::error_internal
1226 ("Missing/wrong basetype info for type '%s'.", p_td.name);
1227 } // switch
1228 new_tlv=BER_encode_TLV_OCTETSTRING
1229 (p_coding, buf.get_read_len(), buf.get_read_data());
1230 }
1231 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
1232 return new_tlv;
1233}
a38c6d4c 1234int UNIVERSAL_CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
1235 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
1236{
1237 int decoded_length = 0;
1238 int str_len = 0;
1239 clean_up();
1240 if (p_td.text->begin_decode) {
1241 int tl;
1242 if ((tl = p_td.text->begin_decode->match_begin(buff)) < 0) {
1243 if (no_err) return -1;
1244 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
1245 "The specified token '%s' not found for '%s': ",
1246 (const char*) *(p_td.text->begin_decode), p_td.name);
1247 return 0;
1248 }
1249 decoded_length += tl;
1250 buff.increase_pos(tl);
1251 }
1252 // never return "not enough bits"
1253 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
1254
1255 if (p_td.text->select_token) {
1256 int tl;
1257 if ((tl = p_td.text->select_token->match_begin(buff)) < 0) {
1258 if (no_err) return -1;
1259 else tl = 0;
1260 }
1261 str_len = tl;
1262 }
1263 // The length restriction needs some more work
1264/* else if ( p_td.text->val.parameters
1265 && p_td.text->val.parameters->decoding_params.min_length != -1) {
1266 str_len = p_td.text->val.parameters->decoding_params.min_length;
1267 }*/
1268 else if (p_td.text->end_decode) {
1269 int tl;
1270 if ((tl = p_td.text->end_decode->match_first(buff)) < 0) {
1271 if (no_err) return -1;
1272 else tl = 0;
1273 }
1274 str_len = tl;
1275 }
1276 else if (limit.has_token()) {
1277 int tl;
1278 if ((tl = limit.match(buff)) < 0) tl = buff.get_read_len() - 1;
1279 str_len = tl;
1280 }
1281 else {
1282 str_len = buff.get_read_len() - 1;
1283 }
1284
1285// only utf8 is supported now.
1286 decode_utf8(str_len,buff.get_read_data());
1287
1288 decoded_length += str_len;
1289 buff.increase_pos(str_len);
1290
1291// Case conversion is an another study
1292// and it is locale dependent
1293/* if ( p_td.text->val.parameters
1294 && p_td.text->val.parameters->decoding_params.convert != 0) {
1295 if (p_td.text->val.parameters->decoding_params.convert == 1) {
1296 for (int a = 0; a < str_len; a++) {
1297 val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
1298 }
1299 }
1300 else {
1301 for (int a = 0; a < str_len; a++) {
1302 val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
1303 }
1304 }
1305 }*/
1306 if (p_td.text->end_decode) {
1307 int tl;
1308 if ((tl = p_td.text->end_decode->match_begin(buff)) < 0) {
1309 if (no_err) return -1;
1310 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
1311 "The specified token '%s' not found for '%s': ",
1312 (const char*) *(p_td.text->end_decode), p_td.name);
1313 return 0;
1314 }
1315 decoded_length += tl;
1316 buff.increase_pos(tl);
1317 }
1318 return decoded_length;
1319}
1320
1321int UNIVERSAL_CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1322 TTCN_Buffer& buff) const{
1323 int encoded_length=0;
1324 if(p_td.text->begin_encode){
1325 buff.put_cs(*p_td.text->begin_encode);
1326 encoded_length+=p_td.text->begin_encode->lengthof();
1327 }
1328 if(!is_bound()) {
1329 TTCN_EncDec_ErrorContext::error
1330 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
1331 if(p_td.text->end_encode){
1332 buff.put_cs(*p_td.text->end_encode);
1333 encoded_length+=p_td.text->end_encode->lengthof();
1334 }
1335 return encoded_length;
1336 }
1337
1338// The length restriction and case conversion will be added later
1339// if(p_td.text->val.parameters==NULL){
1340
1341 int base_size=buff.get_len(); // strore the current length of the data
1342 // in the buffer
1343
1344 encode_utf8(buff);
1345
1346 encoded_length+=buff.get_len()-base_size; // calculate the number of the
1347 // stored octets
1348
1349/* } else {
1350 int chars_before=0;
1351 int chars_after=0;
1352 if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
1353 switch(p_td.text->val.parameters->coding_params.just){
1354 case -1: //left
1355 chars_after=p_td.text->
1356 val.parameters->coding_params.min_length-val_ptr->n_chars;
1357 break;
1358 case 0:{ // center
1359 int pad=p_td.text->
1360 val.parameters->coding_params.min_length-val_ptr->n_chars;
1361 chars_after=pad/2;
1362 chars_before=pad-chars_after;
1363 break;
1364 }
1365 case 1: // right
1366 default:
1367 chars_before=p_td.text->
1368 val.parameters->coding_params.min_length-val_ptr->n_chars;
1369 break;
1370 }
1371 }
1372 if(chars_before){
1373 unsigned char* p=NULL;
1374 size_t len=chars_before;
1375 buff.get_end(p,len);
1376 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
1377 buff.increase_length(chars_before);
1378 encoded_length+=chars_before;
1379 }
1380
1381 switch(p_td.text->val.parameters->coding_params.convert){
1382 case -1:{ //lower_case
1383 unsigned char* p=NULL;
1384 size_t len=val_ptr->n_chars;
1385 buff.get_end(p,len);
1386 for(int a=0;a<val_ptr->n_chars;a++)
1387 p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
1388 buff.increase_length(val_ptr->n_chars);
1389 break;
1390 }
1391 case 0:{ // no conversion
1392 buff.put_cs(*this);
1393 break;
1394 }
1395 case 1: // upper_case
1396 default:
1397 {
1398 unsigned char* p=NULL;
1399 size_t len=val_ptr->n_chars;
1400 buff.get_end(p,len);
1401 for(int a=0;a<val_ptr->n_chars;a++)
1402 p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
1403 buff.increase_length(val_ptr->n_chars);
1404 break;
1405 }
1406 }
1407 encoded_length+=val_ptr->n_chars;
1408
1409 if(chars_after){
1410 unsigned char* p=NULL;
1411 size_t len=chars_after;
1412 buff.get_end(p,len);
1413 for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
1414 buff.increase_length(chars_after);
1415 encoded_length+=chars_after;
1416 }
1417 }
1418*/
1419
1420 if(p_td.text->end_encode){
1421 buff.put_cs(*p_td.text->end_encode);
1422 encoded_length+=p_td.text->end_encode->lengthof();
1423 }
1424 return encoded_length;
1425}
970ed795
EL
1426
1427void UNIVERSAL_CHARSTRING::encode_utf8(TTCN_Buffer& buf, bool addBOM /*= false*/) const
1428{
1429 // Add BOM
1430 if (addBOM) {
1431 buf.put_c(0xEF);
1432 buf.put_c(0xBB);
1433 buf.put_c(0xBF);
1434 }
1435 if (charstring) {
1436 buf.put_s(cstr.val_ptr->n_chars, (unsigned char*)cstr.val_ptr->chars_ptr);
1437 // put_s avoids the check for boundness in put_cs
1438 }
1439 else {
1440 for(int i=0; i<val_ptr->n_uchars; i++) {
1441 unsigned char g=val_ptr->uchars_ptr[i].uc_group;
1442 unsigned char p=val_ptr->uchars_ptr[i].uc_plane;
1443 unsigned char r=val_ptr->uchars_ptr[i].uc_row;
1444 unsigned char c=val_ptr->uchars_ptr[i].uc_cell;
1445 if(g==0x00 && p<=0x1F) {
1446 if(p==0x00) {
1447 if(r==0x00 && c<=0x7F) {
1448 // 1 octet
1449 buf.put_c(c);
1450 } // r
1451 // 2 octets
1452 else if(r<=0x07) {
1453 buf.put_c(0xC0|r<<2|c>>6);
1454 buf.put_c(0x80|(c&0x3F));
1455 } // r
1456 // 3 octets
1457 else {
1458 buf.put_c(0xE0|r>>4);
1459 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1460 buf.put_c(0x80|(c&0x3F));
1461 } // r
1462 } // p
1463 // 4 octets
1464 else {
1465 buf.put_c(0xF0|p>>2);
1466 buf.put_c(0x80|(p<<4&0x30)|r>>4);
1467 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1468 buf.put_c(0x80|(c&0x3F));
1469 } // p
1470 } //g
1471 // 5 octets
1472 else if(g<=0x03) {
1473 buf.put_c(0xF8|g);
1474 buf.put_c(0x80|p>>2);
1475 buf.put_c(0x80|(p<<4&0x30)|r>>4);
1476 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1477 buf.put_c(0x80|(c&0x3F));
1478 } // g
1479 // 6 octets
1480 else {
1481 buf.put_c(0xFC|g>>6);
1482 buf.put_c(0x80|(g&0x3F));
1483 buf.put_c(0x80|p>>2);
1484 buf.put_c(0x80|(p<<4&0x30)|r>>4);
1485 buf.put_c(0x80|(r<<2&0x3C)|c>>6);
1486 buf.put_c(0x80|(c&0x3F));
1487 }
1488 } // for i
1489 }
1490}
1491
1492void UNIVERSAL_CHARSTRING::encode_utf16(TTCN_Buffer& buf,
1493 CharCoding::CharCodingType expected_coding) const
1494{
1495 // add BOM
1496 bool isbig = true;
1497 switch (expected_coding) {
1498 case CharCoding::UTF16:
1499 case CharCoding::UTF16BE:
1500 isbig = true;
1501 break;
1502 case CharCoding::UTF16LE:
1503 isbig = false;
1504 break;
1505 default:
1506 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1507 "Unexpected coding type for UTF-16 encoding");
1508 break;
1509 }
1510 buf.put_c(isbig ? 0xFE : 0xFF);
1511 buf.put_c(isbig ? 0xFF : 0xFE);
1512
1513 if (charstring) {
1514 for (int i = 0; i < cstr.val_ptr->n_chars; ++i) {
1515 buf.put_c(isbig ? 0 : cstr.val_ptr->chars_ptr[i]);
1516 buf.put_c(isbig ? cstr.val_ptr->chars_ptr[i] : 0);
1517 }
1518 }
1519 else {
1520 for(int i=0; i<val_ptr->n_uchars; i++) {
1521 unsigned char g=val_ptr->uchars_ptr[i].uc_group;
1522 unsigned char p=val_ptr->uchars_ptr[i].uc_plane;
1523 unsigned char r=val_ptr->uchars_ptr[i].uc_row;
1524 unsigned char c=val_ptr->uchars_ptr[i].uc_cell;
1525 if (g || (0x10 < p)) {
1526 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1527 "Any UCS code (0x%02X%02X%02X%02X) to be encoded into UTF-16 "
1528 "shall not be greater than 0x10FFFF", g, p, r, c);
1529 }
1530 else if (0x00 == g && 0x00 ==p && 0xD8 <= r && 0xDF >= r) {
1531 // Values between 0xD800 and 0xDFFF are specifically reserved for use with UTF-16,
1532 // and don't have any characters assigned to them.
1533 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1534 "Any UCS code (0x%02X%02X) between 0xD800 and 0xDFFF is ill-formed", r,c);
1535 }
1536 else if (0x00 == g && 0x00 == p) {
1537 buf.put_c(isbig ? r : c);
1538 buf.put_c(isbig ? c : r);
1539 }
1540 else if (g || p) { // greater than 0xFFFF it needs surrogates
1541 uint32_t univc = 0, temp = 0;
1542 univc = g;
1543 univc <<= 24;
1544 temp = p;
1545 temp <<= 16;
1546 univc |= temp;
1547 temp = 0;
1548 temp = r;
1549 temp <<= 8;
1550 univc |= temp;
1551 univc |= c; // universal char filled in univc
1552 uint16_t W1 = 0xD800;
1553 uint16_t W2 = 0xDC00;
1554 uint32_t univcmod = univc - 0x10000;
1555 uint16_t WH = univcmod >> 10;
1556 uint16_t WL = univcmod & 0x3ff;
1557 W1 |= WH;
1558 W2 |= WL;
1559 unsigned char uc;
1560 uc = isbig ? W1 >> 8 : W1;
1561 buf.put_c(uc);
1562 uc = isbig ? W1 : W1 >> 8;
1563 buf.put_c(uc);
1564 uc = isbig ? W2 >> 8 : W2;
1565 buf.put_c(uc);
1566 uc = isbig ? W2 : W2 >> 8;
1567 buf.put_c(uc);
1568 }
1569 }
1570 }
1571}
1572
1573void UNIVERSAL_CHARSTRING::encode_utf32(TTCN_Buffer& buf,
1574 CharCoding::CharCodingType expected_coding) const
1575{
1576 bool isbig = true;
1577 switch (expected_coding) {
1578 case CharCoding::UTF32:
1579 case CharCoding::UTF32BE:
1580 isbig = true;
1581 break;
1582 case CharCoding::UTF32LE:
1583 isbig = false;
1584 break;
1585 default:
1586 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1587 "Unexpected coding type for UTF-32 encoding");
1588 break;
1589 }
1590 // add BOM
1591 buf.put_c(isbig ? 0x00 : 0xFF);
1592 buf.put_c(isbig ? 0x00 : 0xFE);
1593 buf.put_c(isbig ? 0xFE : 0x00);
1594 buf.put_c(isbig ? 0xFF : 0x00);
1595
1596 if (charstring) {
1597 for (int i = 0; i < cstr.val_ptr->n_chars; ++i) {
1598 buf.put_c(isbig ? 0 : cstr.val_ptr->chars_ptr[i]);
1599 buf.put_c(0);
1600 buf.put_c(0);
1601 buf.put_c(isbig ? cstr.val_ptr->chars_ptr[i] : 0);
1602 }
1603 }
1604 else {
1605 for(int i = 0; i < val_ptr->n_uchars; ++i) {
1606 unsigned char g=val_ptr->uchars_ptr[i].uc_group;
1607 unsigned char p=val_ptr->uchars_ptr[i].uc_plane;
1608 unsigned char r=val_ptr->uchars_ptr[i].uc_row;
1609 unsigned char c=val_ptr->uchars_ptr[i].uc_cell;
1610 uint32_t DW = g << 8 | p;
1611 DW <<= 8;
1612 DW |= r;
1613 DW <<= 8;
1614 DW |= c;
1615 if (0x0000D800 <= DW && 0x0000DFFF >= DW) {
1616 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1617 "Any UCS code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW);
1618 }
1619 else if (0x0010FFFF < DW) {
1620 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
1621 "Any UCS code (0x%08X) greater than 0x0010FFFF is ill-formed", DW);
1622 }
1623 else {
1624 buf.put_c(isbig ? g : c);
1625 buf.put_c(isbig ? p : r);
1626 buf.put_c(isbig ? r : p);
1627 buf.put_c(isbig ? c : g);
1628 }
1629 }
1630 }
1631}
1632
1633#ifdef TITAN_RUNTIME_2
1634//virtual
1635int UNIVERSAL_CHARSTRING::encode_raw(TTCN_Buffer& p_buf) const
1636{
1637 size_t len_before = p_buf.get_len();
1638 encode_utf8(p_buf);
1639 return p_buf.get_len() - len_before;
1640}
1641#endif
1642
1643
1644boolean UNIVERSAL_CHARSTRING::BER_decode_TLV
1645(const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv,
1646 unsigned L_form)
1647{
1648 clean_up();
1649 charstring = false;
1650 TTCN_EncDec_ErrorContext ec("While decoding universal charstring type: ");
1651 OCTETSTRING ostr;
1652 if(!ostr.BER_decode_TLV(p_td, p_tlv, L_form)) return FALSE;
1653 int os_len=ostr.lengthof();
1654 int ucs_len;
1655 const unsigned char* os=ostr;
1656 switch(p_td.asnbasetype) {
1657 case TTCN_Typedescriptor_t::TELETEXSTRING:
1658 *this=TTCN_ISO2022_2_TeletexString(ostr);
1659 break;
1660 case TTCN_Typedescriptor_t::VIDEOTEXSTRING:
1661 *this=TTCN_ISO2022_2_VideotexString(ostr);
1662 break;
1663 case TTCN_Typedescriptor_t::GRAPHICSTRING:
1664 *this=TTCN_ISO2022_2_GraphicString(ostr);
1665 break;
1666 case TTCN_Typedescriptor_t::GENERALSTRING:
1667 *this=TTCN_ISO2022_2_GeneralString(ostr);
1668 break;
1669 case TTCN_Typedescriptor_t::UNIVERSALSTRING:
1670 if(os_len%4)
1671 TTCN_EncDec_ErrorContext::error
1672 (TTCN_EncDec::ET_DEC_UCSTR, "Length of UCS-4-coded character"
1673 " string is not multiple of 4.");
1674 ucs_len=os_len/4;
1675 init_struct(ucs_len);
1676 for(int i=0; i<ucs_len; i++) {
1677 val_ptr->uchars_ptr[i].uc_group=os[0];
1678 val_ptr->uchars_ptr[i].uc_plane=os[1];
1679 val_ptr->uchars_ptr[i].uc_row=os[2];
1680 val_ptr->uchars_ptr[i].uc_cell=os[3];
1681 os+=4;
1682 }
1683 break;
1684 case TTCN_Typedescriptor_t::BMPSTRING:
1685 if(os_len%2)
1686 TTCN_EncDec_ErrorContext::error
1687 (TTCN_EncDec::ET_DEC_UCSTR, "Length of UCS-2-coded character"
1688 " string is not multiple of 2.");
1689 ucs_len=os_len/2;
1690 init_struct(ucs_len);
1691 for(int i=0; i<ucs_len; i++) {
1692 val_ptr->uchars_ptr[i].uc_group=0;
1693 val_ptr->uchars_ptr[i].uc_plane=0;
1694 val_ptr->uchars_ptr[i].uc_row=os[0];
1695 val_ptr->uchars_ptr[i].uc_cell=os[1];
1696 os+=2;
1697 }
1698 break;
1699 case TTCN_Typedescriptor_t::UTF8STRING:
1700 decode_utf8(os_len, os);
1701 break;
1702 default:
1703 TTCN_EncDec_ErrorContext::error_internal
1704 ("Missing/wrong basetype info for type '%s'.", p_td.name);
1705 } // switch
1706 return TRUE;
1707}
1708
1709extern void xml_escape(const unsigned int c, TTCN_Buffer& p_buf);
1710
1711int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t& p_td,
af710487 1712 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
970ed795
EL
1713{
1714 if(!is_bound()) {
1715 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1716 "Encoding an unbound UNIVERSAL CHARSTRING value.");
1717 }
1718 if (charstring)
1719 const_cast<UNIVERSAL_CHARSTRING&>(*this).convert_cstr_to_uni();
1720 int exer = is_exer(flavor |= SIMPLE_TYPE);
1721 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1722 int encoded_length=(int)p_buf.get_len();
1723 bool do_empty_element = val_ptr==NULL || val_ptr->n_uchars == 0;
1724
1725 flavor &= ~XER_RECOF; // universal charstring doesn't care
1726 if (exer && (p_td.xer_bits & ANY_ELEMENT)) {
1727 if (!is_canonical(flavor)) {
1728 // Although ANY_ELEMENT is not canonical, this flag is still used to disable
1729 // indenting in a record/set with EMBED_VALUES
1730 do_indent(p_buf, indent);
1731 }
1732 }
1733 else {
1734 if (do_empty_element && exer && p_td.dfeValue != 0) {
1735 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR,
1736 "An encoded value with DEFAULT-FOR-EMPTY instruction "
1737 "applied should not be empty");
1738 }
1739 if (begin_xml(p_td, p_buf, flavor, indent, do_empty_element) == -1) {
1740 --encoded_length;
1741 }
1742 } // not any_element
1743
1744#define UCH(c) {0,0,0,c}
1745 if (!do_empty_element) {
1746 if (flavor & XER_ESCAPE_ENTITIES) {
1747 for (int i = 0; i < val_ptr->n_uchars; ++i) {
1748 unsigned int ucs4 = unichar2int(val_ptr->uchars_ptr[i]);
1749 xml_escape( ucs4, p_buf );
1750 }
1751 }
1752 else { // UTF-8 needs only to escape the low 32 and these five: <&>
1753 TTCN_Buffer other_buf;
1754 static const universal_char amp[] = { UCH('&'), UCH('a'), UCH('m'),
1755 UCH('p'), UCH(';') };
1756 static const universal_char lt [] = { UCH('&'), UCH('l'), UCH('t'),
1757 UCH(';') };
1758 static const universal_char gt [] = { UCH('&'), UCH('g'), UCH('t'),
1759 UCH(';') };
1760 static const universal_char apos[]= { UCH('&'), UCH('a'), UCH('p'),
1761 UCH('o'), UCH('s'), UCH(';') };
1762 static const universal_char quot[]= { UCH('&'), UCH('q'), UCH('u'),
1763 UCH('o'), UCH('t'), UCH(';') };
1764
1765 static const universal_char escapes[32][6] = {
1766 {UCH('<'), UCH('n'), UCH('u'), UCH('l'), UCH('/'), UCH('>')},
1767 {UCH('<'), UCH('s'), UCH('o'), UCH('h'), UCH('/'), UCH('>')},
1768 {UCH('<'), UCH('s'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1769 {UCH('<'), UCH('e'), UCH('t'), UCH('x'), UCH('/'), UCH('>')},
1770 {UCH('<'), UCH('e'), UCH('o'), UCH('t'), UCH('/'), UCH('>')},
1771 {UCH('<'), UCH('e'), UCH('n'), UCH('q'), UCH('/'), UCH('>')},
1772 {UCH('<'), UCH('a'), UCH('c'), UCH('k'), UCH('/'), UCH('>')},
1773 {UCH('<'), UCH('b'), UCH('e'), UCH('l'), UCH('/'), UCH('>')},
1774
1775 {UCH('<'), UCH('b'), UCH('s'), UCH('/'), UCH('>')},
1776 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('9'), UCH(';')}, // TAB
1777 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('A'), UCH(';')}, // LF
1778 {UCH('<'), UCH('v'), UCH('t'), UCH('/'), UCH('>')},
1779 {UCH('<'), UCH('f'), UCH('f'), UCH('/'), UCH('>')},
1780 {UCH('&'), UCH('#'), UCH('x'), UCH('0'), UCH('D'), UCH(';')}, // CR
1781 {UCH('<'), UCH('s'), UCH('o'), UCH('/'), UCH('>')},
1782 {UCH('<'), UCH('s'), UCH('i'), UCH('/'), UCH('>')},
1783
1784 {UCH('<'), UCH('d'), UCH('l'), UCH('e'), UCH('/'), UCH('>')},
1785 {UCH('<'), UCH('d'), UCH('c'), UCH('1'), UCH('/'), UCH('>')},
1786 {UCH('<'), UCH('d'), UCH('c'), UCH('2'), UCH('/'), UCH('>')},
1787 {UCH('<'), UCH('d'), UCH('c'), UCH('3'), UCH('/'), UCH('>')},
1788 {UCH('<'), UCH('d'), UCH('c'), UCH('4'), UCH('/'), UCH('>')},
1789 {UCH('<'), UCH('n'), UCH('a'), UCH('k'), UCH('/'), UCH('>')},
1790 {UCH('<'), UCH('s'), UCH('y'), UCH('n'), UCH('/'), UCH('>')},
1791 {UCH('<'), UCH('e'), UCH('t'), UCH('b'), UCH('/'), UCH('>')},
1792
1793 {UCH('<'), UCH('c'), UCH('a'), UCH('n'), UCH('/'), UCH('>')},
1794 {UCH('<'), UCH('e'), UCH('m'), UCH('/'), UCH('>')},
1795 {UCH('<'), UCH('s'), UCH('u'), UCH('b'), UCH('/'), UCH('>')},
1796 {UCH('<'), UCH('e'), UCH('s'), UCH('c'), UCH('/'), UCH('>')},
1797 {UCH('<'), UCH('i'), UCH('s'), UCH('4'), UCH('/'), UCH('>')},
1798 {UCH('<'), UCH('i'), UCH('s'), UCH('3'), UCH('/'), UCH('>')},
1799 {UCH('<'), UCH('i'), UCH('s'), UCH('2'), UCH('/'), UCH('>')},
1800 {UCH('<'), UCH('i'), UCH('s'), UCH('1'), UCH('/'), UCH('>')}
1801 };
1802
1803 if (exer && (p_td.xer_bits & ANY_ELEMENT)) { // no escaping
1804 TTCN_EncDec_ErrorContext ec("While checking anyElement: ");
1805 encode_utf8(other_buf);
1806 XmlReaderWrap checker(other_buf);
1807 // Walk through the XML. If it's not well-formed, XmlReaderWrap
1808 // will call TTCN_error => Dynamic testcase error.
1809 while (1 == checker.Read()) {
1810 if (checker.NodeType() == XML_READER_TYPE_ELEMENT &&
1811 (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT))) {
1812 const char* xmlns = (const char*)checker.NamespaceUri();
1813 check_namespace_restrictions(p_td, xmlns);
1814 }
1815 }
1816
1817 // other_buf is already UTF-8, just append it
1818 p_buf.put_buf(other_buf);
1819 }
1820 else if (flavor & ANY_ATTRIBUTES) { // no escaping
1821 encode_utf8(other_buf);
1822 p_buf.put_buf(other_buf);
1823 }
1824 else {
1825 for (int i = 0; i < val_ptr->n_uchars; ++i) {
1826 int char_val = unichar2int(val_ptr->uchars_ptr[i]);
1827 size_t len = 6; // 3 letters + the surrounding '<', '/' and '>'
1828 switch (char_val) {
1829 case '&':
1830 other_buf.put_s(20, &(amp[0].uc_group));
1831 break;
1832
1833 case '<':
1834 other_buf.put_s(16, &(lt[0].uc_group));
1835 break;
1836
1837 case '>':
1838 other_buf.put_s(16, &(gt[0].uc_group));
1839 break;
1840
1841 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1842 // so if they appear in content they must be escaped.
1843 // Currently this happens even if the string is not an attribute.
1844 other_buf.put_s(24, &(apos[0].uc_group));
1845 break;
1846
1847 case '\"': // HR58225
1848 other_buf.put_s(24, &(quot[0].uc_group));
1849 break;
1850
1851 case 8: case 11: case 12: case 14: case 15: case 25:
1852 // the name of these control characters has only two letters
1853 --len;
1854 // no break
1855 case 0: case 1: case 2: case 3: case 4: case 5: case 6:
1856 case 7: case 16: case 17: case 18: case 19: case 20: case 21:
1857 case 22: case 23: case 24: case 26: case 27: case 28: case 29:
1858 case 30: case 31:
1859 other_buf.put_s(len * 4, &(escapes[char_val][0].uc_group));
1860 break;
1861
1862 case 9: case 10: case 13:
1863 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1864 // X.693 20.3.15: TAB,LF,CR also needs to be escaped in ATTRIBUTE
1865 other_buf.put_s(24, &(escapes[char_val][0].uc_group));
1866 break;
1867 } // else fall through
1868 // no break
1869 default:
1870 other_buf.put_s(4, &(val_ptr->uchars_ptr[i].uc_group));
1871 break;
1872 }
1873 } // next
1874 // other_buf contains UCS-4, need to encode it
1875 UNIVERSAL_CHARSTRING cs;
1876 other_buf.get_string(cs);
1877 (cs).encode_utf8(p_buf);
1878 } // not any_element
1879 } // if ESCAPE_ENTITIES
1880
1881 if (exer && (p_td.xer_bits & ANY_ELEMENT) && !is_canonical(flavor)) {
1882 p_buf.put_c('\n');
1883 }
1884 }
1885
1886 end_xml(p_td, p_buf, flavor, indent, do_empty_element);
1887
1888 return (int)p_buf.get_len() - encoded_length;
1889}
1890
1891/* Hashing for xmlcstring representation of control characters.
1892 * This function was generated by gperf 3.0.3
1893 * (GNU perfect hash function generator) from the list of control character
1894 * names, one per line, like this:
1895 *
1896 * nul
1897 * soh
1898 * ...etc...
1899 * is1
1900 *
1901 * See the ASN.1 standard, X.680/2002, clause 11.15.5
1902 */
1903inline
1904static unsigned int
1905hash (register const char *str, register unsigned int len)
1906{
1907 static unsigned char asso_values[] =
1908 {
1909 104, 104, 104, 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, 104, 104, 1,
1914 60, 55, 45, 104, 104, 104, 104, 104, 104, 104,
1915 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1916 104, 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, 10, 10, 50,
1919 40, 15, 0, 104, 6, 15, 104, 1, 5, 10,
1920 0, 20, 104, 15, 0, 0, 30, 104, 0, 104,
1921 20, 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, 104, 104, 104, 104,
1930 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1931 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1932 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1933 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
1934 104, 104, 104, 104, 104, 104
1935 };
1936 return len + asso_values[(unsigned char)str[len - 1]] +
1937 asso_values[(unsigned char)str[0]];
1938}
1939
1940/* This function was also generated by gperf and hand-edited afterwards.
1941 * The original wordlist[] was an array of strings containing the names of
1942 * the control characters, with empty strings as fillers. These have been
1943 * replaced with the actual numerical values of the control characters,
1944 * with -1 as the filler.
1945 */
1946inline
1947static char
1948in_word_set (const char *str, unsigned int len)
1949{
1950 static char wordlist[] =
1951 {
1952 -1, -1,
1953 12, // FF
1954 22, // SYN
1955 21, // NAK
1956 -1, -1,
1957 10, // LF
1958 0, // NUL
1959 1, // SOH
1960 -1, -1,
1961 8, // BS
1962 26, // SUB
1963 6, // ACK
1964 -1, -1,
1965 15, // SI
1966 7, // BEL
1967 31, // IS1
1968 -1, -1,
1969 14, // SO
1970 2, // STX
1971 -1, -1, -1,
1972 25, // EM
1973 23, // ETB
1974 -1, -1, -1,
1975 11, // VT
1976 5, // ENQ
1977 -1, -1, -1, -1,
1978 3, // ETX
1979 -1, -1, -1, -1,
1980 9, // TAB
1981 17, // DC1
1982 -1, -1, -1,
1983 4, // EOT
1984 -1, -1, -1,
1985 13, // CR
1986 24, // CAN
1987 -1, -1, -1, -1,
1988 16, // DLE
1989 -1, -1, -1, -1,
1990 28, // IS4
1991 -1, -1, -1, -1,
1992 27, // ESC
1993 -1, -1, -1, -1,
1994 29, // IS3
1995 -1, -1, -1, -1,
1996 30, // IS2
1997 -1, -1, -1, -1, -1, -1, -1, -1, -1,
1998 20, // DC4
1999 -1, -1, -1, -1, -1, -1, -1, -1, -1,
2000 19, // DC3
2001 -1, -1, -1, -1,
2002 18 // DC2
2003 };
2004#define MIN_WORD_LENGTH 2
2005#define MAX_WORD_LENGTH 3
2006#define MIN_HASH_VALUE 2
2007#define MAX_HASH_VALUE 103
2008
2009 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
2010 {
2011 register int key = hash (str, len);
2012
2013 if (key <= MAX_HASH_VALUE && key >= 0)
2014 {
2015 register const char s = wordlist[key];
2016 return s;
2017 }
2018 }
2019 return -1;
2020}
2021
2022universal_char const uspace = {0,0,0,32};
2023
2024int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t& p_td,
af710487 2025 XmlReaderWrap& reader, unsigned int flavor, embed_values_dec_struct_t*)
970ed795
EL
2026{
2027 int exer = is_exer(flavor);
2028 int success = reader.Ok(), depth = -1;
2029 bool omit_tag = exer
2030 && ((p_td.xer_bits & UNTAGGED)
2031 || (flavor & (EMBED_VALUES|XER_LIST|USE_TYPE_ATTR|ANY_ATTRIBUTES|USE_NIL)));
2032
2033 if (exer && (p_td.xer_bits & ANY_ELEMENT)) {
2034 TTCN_EncDec_ErrorContext ec("While checking anyElement: ");
2035 for (; success == 1; success = reader.Read()) {
2036 int type = reader.NodeType();
2037 if (-1 == depth && XML_READER_TYPE_ELEMENT == type) {
2038 xmlChar * value = reader.ReadOuterXml();
2039 size_t num_chars = strlen((const char*)value);
2040 clean_up();
2041 charstring = false;
2042 decode_utf8(num_chars, value); // does init_struct
2043 xmlFree(value);
2044
2045 if (p_td.xer_bits & (ANY_FROM | ANY_EXCEPT)) {
2046 const char* xmlns = (const char*)reader.NamespaceUri();
2047 check_namespace_restrictions(p_td, xmlns);
2048 }
2049
2050 if (reader.IsEmptyElement()) {
2051 reader.Read(); // skip past the empty element and we're done
2052 break;
2053 }
2054 depth = reader.Depth(); // signals that we have the element's text
2055 // Stay in the loop until we reach the corresponding end tag
2056 }
2057 else if (reader.Depth() == depth && XML_READER_TYPE_END_ELEMENT == type) {
2058 reader.Read(); // one last time
2059 break;
2060 } // type
2061 } // next read
2062 // ANY-ELEMENT and WHITESPACE are mutually exclusive,
2063 // so this branch skips WHITESPACE processing
2064 }
2065 else { // not ANY-ELEMENT
2066 clean_up(); // start with a clean slate
2067 charstring = false;
2068 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
2069 // we have it easy (but does decode_utf8 handle &nnn; ?)
2070 const char * name = verify_name(reader, p_td, exer);
2071 (void)name;
2072 const char * value = (const char *)reader.Value();
2073 int len = strlen(value);
2074 decode_utf8(len, (cbyte*)value);
2075
2076 // Let the caller do reader.AdvanceAttribute();
2077 }
2078 else { // not an attribute either
2079 // Get to the start of data.
2080 if (!omit_tag) for (; success == 1; success = reader.Read()) {
2081 int type = reader.NodeType();
2082 if (XML_READER_TYPE_ELEMENT == type) {
2083 verify_name(reader, p_td, exer);
2084 if (reader.IsEmptyElement()) {
2085 if (exer && p_td.dfeValue != 0) {
2086 *this = *static_cast<const UNIVERSAL_CHARSTRING*>(p_td.dfeValue);
2087 }
2088 else init_struct(0); // it's an empty string
2089 reader.Read(); // move on
2090 return 0;
2091 }
2092 depth = reader.Depth();
2093 success = reader.Read();
2094 break; // the loop
2095 }
2096 else if (XML_READER_TYPE_TEXT == type && omit_tag)
2097 break;
2098 else // if XML_READER_TYPE_END_ELEMENT, panic?
2099 continue;
2100 } // next read
2101
2102 init_struct(0);
2103 TTCN_Buffer accumulator;
2104 if (flavor & PARENT_CLOSED) {} // do nothing
2105 else for (; success==1; success = reader.Read()) {
2106 int type = reader.NodeType();
2107 switch (type) {
2108 case XML_READER_TYPE_SIGNIFICANT_WHITESPACE:
2109 case XML_READER_TYPE_TEXT:
2110 case XML_READER_TYPE_CDATA: {
2111 const char * text = (const char*)reader.Value();
2112 int len = strlen(text);
2113 accumulator.put_s(len, (cbyte*)text);
2114 break; }
2115
2116 case XML_READER_TYPE_ELEMENT: { // escaped control character
2117 const char * name = (const char*)reader.LocalName();
2118 size_t len = strlen(name);
2119 char ctrl = in_word_set(name, len);
2120 if (ctrl >= 0) {
2121 accumulator.put_c(ctrl);
2122 }
2123 else {
2124 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2125 "Invalid escape sequence '<%s/>'", name);
2126 }
2127 break; }
2128
2129 case XML_READER_TYPE_END_ELEMENT: {
2130 decode_utf8(accumulator.get_len(), accumulator.get_data());
2131 if (!omit_tag) {
2132 verify_end(reader, p_td, depth, exer);
2133 reader.Read(); // Moved to a different XML node!
2134 if (val_ptr->n_uchars == 0 && exer && p_td.dfeValue != 0) {
2135 // This should be the <foo></foo> case. Treat it like <foo/>
2136 *this = *static_cast<const UNIVERSAL_CHARSTRING*>(p_td.dfeValue);
2137 }
2138 }
2139 goto fini; } // double "break" of switch and for loop
2140
2141 default:
2142 break;
2143 } // switch
2144 } // next read
2145 } // endif (attribute)
2146fini:
2147 if (exer && p_td.whitespace >= WHITESPACE_REPLACE) { // includes _COLLAPSE
2148 for(int i=0; i<val_ptr->n_uchars; ++i) { // first, _REPLACE
2149 switch ( unichar2int(val_ptr->uchars_ptr[i]) ) {
2150 case 9: // HORIZONTAL TAB
2151 case 10: // LINE FEED
2152 case 13: // CARRIAGE RETURN
2153 val_ptr->uchars_ptr[i] = uspace;
2154 break;
2155 default:
2156 break;
2157 } // switch
2158 } // next i
2159
2160 if (p_td.whitespace >= WHITESPACE_COLLAPSE) {
2161 universal_char *to;
2162 const universal_char *from, *end =
2163 val_ptr->uchars_ptr + val_ptr->n_uchars;
2164 for (from = to = val_ptr->uchars_ptr; from < end;) {
2165 *to = *from++;
2166 // If the copied character (*to) was a space,
2167 // and the next character to be copied (*from) is also a space
2168 // (continuous run of spaces)
2169 // or this was the first character (leading spaces to be trimmed),
2170 // then don't advance the destination (will be overwritten).
2171 if (*to != uspace
2172 || (from < end && *from != uspace && to > val_ptr->uchars_ptr))
2173 ++to;
2174 } // next
2175 val_ptr->n_uchars = to - val_ptr->uchars_ptr;
2176 }
2177 } // if WHITESPACE
2178 } // not ANY_ELEMENT
2179 return 1; // decode successful
2180}
2181
2182char* UNIVERSAL_CHARSTRING::to_JSON_string(const TTCN_Buffer& p_buf) const
2183{
2184 const unsigned char* ustr = p_buf.get_data();
2185 const size_t ustr_len = p_buf.get_len();
2186
2187 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
2188 char* json_str = (char*)Malloc(ustr_len + 3);
2189
2190 json_str[0] = 0;
2191 json_str = mputc(json_str, '\"');
2192
2193 for (size_t i = 0; i < ustr_len; ++i) {
2194 // Increase the size of the buffer if it's not big enough to store the
2195 // characters remaining in the universal charstring
2196 switch(ustr[i]) {
2197 case '\\':
2198 json_str = mputstrn(json_str, "\\\\", 2);
2199 break;
2200 case '\n':
2201 json_str = mputstrn(json_str, "\\n", 2);
2202 break;
2203 case '\t':
2204 json_str = mputstrn(json_str, "\\t", 2);
2205 break;
2206 case '\r':
2207 json_str = mputstrn(json_str, "\\r", 2);
2208 break;
2209 case '\f':
2210 json_str = mputstrn(json_str, "\\f", 2);
2211 break;
2212 case '\b':
2213 json_str = mputstrn(json_str, "\\b", 2);
2214 break;
2215 case '\"':
2216 json_str = mputstrn(json_str, "\\\"", 2);
2217 break;
2218 default:
2219 json_str = mputc(json_str, (char)ustr[i]);
2220 break;
2221 }
2222 }
2223
2224 json_str = mputc(json_str, '\"');
2225 return json_str;
2226}
2227
2228boolean UNIVERSAL_CHARSTRING::from_JSON_string(boolean check_quotes)
2229{
2230 int json_len = val_ptr->n_uchars;
2231 universal_char* json_str = val_ptr->uchars_ptr;
2232
2233 int start = 0;
2234 int end = json_len;
2235 if (check_quotes) {
2236 start = 1;
2237 end = json_len - 1;
2238 if (!json_str[0].is_char() || json_str[0].uc_cell != '\"' ||
2239 !json_str[json_len - 1].is_char() || json_str[json_len - 1].uc_cell != '\"') {
2240 return false;
2241 }
2242 }
2243
2244 // The resulting string will be shorter than the JSON string, at least by the 2 quotes
2245 universal_char* ustr = (universal_char*)Malloc((json_len - 2) * sizeof(universal_char));
2246 memset(ustr, 0, sizeof(universal_char) * (json_len - 2));
2247 int ustr_len = 0;
2248 boolean error = false;
2249
2250 for (int i = start; i < end; ++i) {
2251 if (json_str[i].is_char() && '\\' == json_str[i].uc_cell) {
2252 if (i == end - 1 || !json_str[i + 1].is_char()) {
2253 error = true;
2254 break;
2255 }
2256 switch(json_str[i + 1].uc_cell) {
2257 case 'n':
2258 ustr[ustr_len++].uc_cell = '\n';
2259 break;
2260 case 't':
2261 ustr[ustr_len++].uc_cell = '\t';
2262 break;
2263 case 'r':
2264 ustr[ustr_len++].uc_cell = '\r';
2265 break;
2266 case 'f':
2267 ustr[ustr_len++].uc_cell = '\f';
2268 break;
2269 case 'b':
2270 ustr[ustr_len++].uc_cell = '\b';
2271 break;
2272 case '\\':
2273 ustr[ustr_len++].uc_cell = '\\';
2274 break;
2275 case '\"':
2276 ustr[ustr_len++].uc_cell = '\"';
2277 break;
2278 case '/':
2279 ustr[ustr_len++].uc_cell = '/';
2280 break;
2281 case 'u': {
2282 if (end - i >= 6 && json_str[i + 2].is_char() && json_str[i + 3].is_char() &&
2283 json_str[i + 4].is_char() && json_str[i + 5].is_char()) {
2284 unsigned char row_upper_nibble = char_to_hexdigit(json_str[i + 2].uc_cell);
2285 unsigned char row_lower_nibble = char_to_hexdigit(json_str[i + 3].uc_cell);
2286 unsigned char cell_upper_nibble = char_to_hexdigit(json_str[i + 4].uc_cell);
2287 unsigned char cell_lower_nibble = char_to_hexdigit(json_str[i + 5].uc_cell);
2288 if (row_upper_nibble <= 0x0F && row_lower_nibble <= 0x0F &&
2289 cell_upper_nibble <= 0x0F && cell_lower_nibble <= 0x0F) {
2290 ustr[ustr_len].uc_row = (row_upper_nibble << 4) | row_lower_nibble;
2291 ustr[ustr_len++].uc_cell = (cell_upper_nibble << 4) | cell_lower_nibble;
2292 // skip 4 extra characters (the 4 hex digits)
2293 i += 4;
2294 } else {
2295 // error (encountered something other than a hex digit) -> leave the for cycle
2296 i = end;
2297 error = true;
2298 }
2299 } else {
2300 // error (not enough characters or the 'hex digits' are not even ascii characters) -> leave the for cycle
2301 i = end;
2302 error = true;
2303 }
2304 break;
2305 }
2306 default:
2307 // error (invalid escaped character) -> leave the for cycle
2308 i = end;
2309 error = true;
2310 break;
2311 }
2312 // skip an extra character (the \)
2313 ++i;
2314 } else {
2315 ustr[ustr_len++] = json_str[i];
2316 }
2317
2318 if (check_quotes && i == json_len - 1) {
2319 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
2320 error = true;
2321 }
2322 }
2323
2324 if (!error) {
2325 clean_up();
2326 init_struct(ustr_len);
2327 memcpy(val_ptr->uchars_ptr, ustr, ustr_len * sizeof(universal_char));
2328 }
2329 Free(ustr);
2330 return !error;
2331}
2332
2333int UNIVERSAL_CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
2334{
2335 if (!is_bound()) {
2336 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
2337 "Encoding an unbound universal charstring value.");
2338 return -1;
2339 }
2340
2341 char* tmp_str = 0;
2342 if (charstring) {
2343 tmp_str = cstr.to_JSON_string();
2344 } else {
2345 TTCN_Buffer tmp_buf;
2346 encode_utf8(tmp_buf);
2347 tmp_str = to_JSON_string(tmp_buf);
2348 }
2349 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
2350 Free(tmp_str);
2351 return enc_len;
2352}
2353
2354int UNIVERSAL_CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
2355{
2356 json_token_t token = JSON_TOKEN_NONE;
2357 char* value = 0;
2358 size_t value_len = 0;
2359 int dec_len = 0;
2360 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
2361 if (use_default) {
2362 // No JSON data in the buffer -> use default value
2363 value = (char*)p_td.json->default_value;
2364 value_len = strlen(value);
2365 } else {
2366 dec_len = p_tok.get_next_token(&token, &value, &value_len);
2367 }
2368 if (JSON_TOKEN_ERROR == token) {
2369 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
2370 return JSON_ERROR_FATAL;
2371 }
2372 else if (JSON_TOKEN_STRING == token || use_default) {
2373 if (cstr.from_JSON_string(value, value_len, !use_default)) {
2374 charstring = true;
2375 }
2376 else {
2377 charstring = false;
2378 decode_utf8(value_len, (unsigned char*)value);
2379 if (!from_JSON_string(!use_default)) {
2380 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "universal charstring");
2381 if (p_silent) {
2382 clean_up();
2383 }
2384 return JSON_ERROR_FATAL;
2385 }
2386 }
2387 } else {
2388 return JSON_ERROR_INVALID_TOKEN;
2389 }
2390 return dec_len;
2391}
2392
2393
2394static void fill_continuing_octets(int n_continuing,
2395 unsigned char *continuing_ptr, int n_octets,
2396 const unsigned char *octets_ptr, int start_pos, int uchar_pos)
2397{
2398 for (int i = 0; i < n_continuing; i++) {
2399 if (start_pos + i < n_octets) {
2400 unsigned char octet = octets_ptr[start_pos + i];
2401 if ((octet & 0xC0) != 0x80) {
2402 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2403 "Malformed: At character position %d, octet position %d: %02X is "
2404 "not a valid continuing octet.", uchar_pos, start_pos + i, octet);
2405 }
2406 continuing_ptr[i] = octet & 0x3F;
2407 } else {
2408 if (start_pos + i == n_octets) {
2409 if (i > 0) {
2410 // only a part of octets is missing
2411 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2412 "Incomplete: At character position %d, octet position %d: %d out "
2413 "of %d continuing octets %s missing from the end of the stream.",
2414 uchar_pos, start_pos + i, n_continuing - i, n_continuing,
2415 n_continuing - i > 1 ? "are" : "is");
2416 } else {
2417 // all octets are missing
2418 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2419 "Incomplete: At character position %d, octet position %d: %d "
2420 "continuing octet%s missing from the end of the stream.", uchar_pos,
2421 start_pos, n_continuing, n_continuing > 1 ? "s are" : " is");
2422 }
2423 }
2424 continuing_ptr[i] = 0;
2425 }
2426 }
2427}
2428
2429void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets,
2430 const unsigned char *octets_ptr,
2431 CharCoding::CharCodingType expected_coding /*= UTF8*/,
2432 bool checkBOM /*= false)*/)
2433{
2434 // approximate the number of characters
2435 int n_uchars = 0;
2436 for (int i = 0; i < n_octets; i++) {
2437 // count all octets except the continuing octets (10xxxxxx)
2438 if ((octets_ptr[i] & 0xC0) != 0x80) n_uchars++;
2439 }
a38c6d4c 2440 // allocate enough memory, start from clean state
2441 clean_up();
2442 charstring=false;
970ed795
EL
2443 init_struct(n_uchars);
2444 n_uchars = 0;
2445
2446 int start = checkBOM ? check_BOM(CharCoding::UTF_8, sizeof(octets_ptr), octets_ptr) : 0;
2447 for (int i = start; i < n_octets; ) {
2448 // perform the decoding character by character
2449 if (octets_ptr[i] <= 0x7F) {
2450 // character encoded on a single octet: 0xxxxxxx (7 useful bits)
2451 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2452 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2453 val_ptr->uchars_ptr[n_uchars].uc_row = 0;
2454 val_ptr->uchars_ptr[n_uchars].uc_cell = octets_ptr[i];
2455 i++;
2456 n_uchars++;
2457 } else if (octets_ptr[i] <= 0xBF) {
2458 // continuing octet (10xxxxxx) without leading octet ==> malformed
2459 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2460 "Malformed: At character position %d, octet position %d: continuing "
2461 "octet %02X without leading octet.", n_uchars, i, octets_ptr[i]);
2462 i++;
2463 } else if (octets_ptr[i] <= 0xDF) {
2464 // character encoded on 2 octets: 110xxxxx 10xxxxxx (11 useful bits)
2465 unsigned char octets[2];
2466 octets[0] = octets_ptr[i] & 0x1F;
2467 fill_continuing_octets(1, octets + 1, n_octets, octets_ptr, i + 1, n_uchars);
2468 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2469 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2470 val_ptr->uchars_ptr[n_uchars].uc_row = octets[0] >> 2;
2471 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[0] << 6 | octets[1];
2472 if (val_ptr->uchars_ptr[n_uchars].uc_row == 0x00 &&
2473 val_ptr->uchars_ptr[n_uchars].uc_cell < 0x80)
2474 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2475 "Overlong: At character position %d, octet position %d: 2-octet "
2476 "encoding for quadruple (0, 0, 0, %u).", n_uchars, i,
2477 val_ptr->uchars_ptr[n_uchars].uc_cell);
2478 i += 2;
2479 n_uchars++;
2480 } else if (octets_ptr[i] <= 0xEF) {
2481 // character encoded on 3 octets: 1110xxxx 10xxxxxx 10xxxxxx
2482 // (16 useful bits)
2483 unsigned char octets[3];
2484 octets[0] = octets_ptr[i] & 0x0F;
2485 fill_continuing_octets(2, octets + 1, n_octets, octets_ptr, i + 1,
2486 n_uchars);
2487 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2488 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2489 val_ptr->uchars_ptr[n_uchars].uc_row = octets[0] << 4 | octets[1] >> 2;
2490 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[1] << 6 | octets[2];
2491 if (val_ptr->uchars_ptr[n_uchars].uc_row < 0x08)
2492 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2493 "Overlong: At character position %d, octet position %d: 3-octet "
2494 "encoding for quadruple (0, 0, %u, %u).", n_uchars, i,
2495 val_ptr->uchars_ptr[n_uchars].uc_row,
2496 val_ptr->uchars_ptr[n_uchars].uc_cell);
2497 i += 3;
2498 n_uchars++;
2499 } else if (octets_ptr[i] <= 0xF7) {
2500 // character encoded on 4 octets: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
2501 // (21 useful bits)
2502 unsigned char octets[4];
2503 octets[0] = octets_ptr[i] & 0x07;
2504 fill_continuing_octets(3, octets + 1, n_octets, octets_ptr, i + 1,
2505 n_uchars);
2506 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2507 val_ptr->uchars_ptr[n_uchars].uc_plane = octets[0] << 2 | octets[1] >> 4;
2508 val_ptr->uchars_ptr[n_uchars].uc_row = octets[1] << 4 | octets[2] >> 2;
2509 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[2] << 6 | octets[3];
2510 if (val_ptr->uchars_ptr[n_uchars].uc_plane == 0x00)
2511 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2512 "Overlong: At character position %d, octet position %d: 4-octet "
2513 "encoding for quadruple (0, 0, %u, %u).", n_uchars, i,
2514 val_ptr->uchars_ptr[n_uchars].uc_row,
2515 val_ptr->uchars_ptr[n_uchars].uc_cell);
2516 i += 4;
2517 n_uchars++;
2518 } else if (octets_ptr[i] <= 0xFB) {
2519 // character encoded on 5 octets: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
2520 // 10xxxxxx (26 useful bits)
2521 unsigned char octets[5];
2522 octets[0] = octets_ptr[i] & 0x03;
2523 fill_continuing_octets(4, octets + 1, n_octets, octets_ptr, i + 1,
2524 n_uchars);
2525 val_ptr->uchars_ptr[n_uchars].uc_group = octets[0];
2526 val_ptr->uchars_ptr[n_uchars].uc_plane = octets[1] << 2 | octets[2] >> 4;
2527 val_ptr->uchars_ptr[n_uchars].uc_row = octets[2] << 4 | octets[3] >> 2;
2528 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[3] << 6 | octets[4];
2529 if (val_ptr->uchars_ptr[n_uchars].uc_group == 0x00 &&
2530 val_ptr->uchars_ptr[n_uchars].uc_plane < 0x20)
2531 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2532 "Overlong: At character position %d, octet position %d: 5-octet "
2533 "encoding for quadruple (0, %u, %u, %u).", n_uchars, i,
2534 val_ptr->uchars_ptr[n_uchars].uc_plane,
2535 val_ptr->uchars_ptr[n_uchars].uc_row,
2536 val_ptr->uchars_ptr[n_uchars].uc_cell);
2537 i += 5;
2538 n_uchars++;
2539 } else if (octets_ptr[i] <= 0xFD) {
2540 // character encoded on 6 octets: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx
2541 // 10xxxxxx 10xxxxxx (31 useful bits)
2542 unsigned char octets[6];
2543 octets[0] = octets_ptr[i] & 0x01;
2544 fill_continuing_octets(5, octets + 1, n_octets, octets_ptr, i + 1,
2545 n_uchars);
2546 val_ptr->uchars_ptr[n_uchars].uc_group = octets[0] << 6 | octets[1];
2547 val_ptr->uchars_ptr[n_uchars].uc_plane = octets[2] << 2 | octets[3] >> 4;
2548 val_ptr->uchars_ptr[n_uchars].uc_row = octets[3] << 4 | octets[4] >> 2;
2549 val_ptr->uchars_ptr[n_uchars].uc_cell = octets[4] << 6 | octets[5];
2550 if (val_ptr->uchars_ptr[n_uchars].uc_group < 0x04)
2551 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2552 "Overlong: At character position %d, octet position %d: 6-octet "
2553 "encoding for quadruple (%u, %u, %u, %u).", n_uchars, i,
2554 val_ptr->uchars_ptr[n_uchars].uc_group,
2555 val_ptr->uchars_ptr[n_uchars].uc_plane,
2556 val_ptr->uchars_ptr[n_uchars].uc_row,
2557 val_ptr->uchars_ptr[n_uchars].uc_cell);
2558 i += 6;
2559 n_uchars++;
2560 } else {
2561 // not used code points: FE and FF => malformed
2562 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2563 "Malformed: At character position %d, octet position %d: "
2564 "unused/reserved octet %02X.", n_uchars, i, octets_ptr[i]);
2565 i++;
2566 }
2567 } // for i
2568 if (val_ptr->n_uchars != n_uchars) {
2569 // truncate the memory and set the correct size in case of decoding errors
2570 // (e.g. skipped octets)
2571 if (n_uchars > 0) {
2572 val_ptr = (universal_charstring_struct*)Realloc(val_ptr,
2573 MEMORY_SIZE(n_uchars));
2574 val_ptr->n_uchars = n_uchars;
2575 } else {
2576 clean_up();
2577 init_struct(0);
2578 }
2579 }
2580}
2581
2582void UNIVERSAL_CHARSTRING::decode_utf16(int n_octets,
2583 const unsigned char *octets_ptr,
2584 CharCoding::CharCodingType expected_coding)
2585{
2586 if (n_octets % 2 || 0 > n_octets) {
2587 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2588 "Wrong UTF-16 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 2",
2589 n_octets);
2590 }
2591 int start = check_BOM(expected_coding, sizeof(octets_ptr), octets_ptr);
2592 int n_uchars = n_octets/2;
2593 init_struct(n_uchars);
2594 n_uchars = 0;
2595 bool isbig = true;
2596 switch (expected_coding) {
2597 case CharCoding::UTF16:
2598 case CharCoding::UTF16BE:
2599 isbig = true;
2600 break;
2601 case CharCoding::UTF16LE:
2602 isbig = false;
2603 break;
2604 default:
2605 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2606 "Unexpected coding type for UTF-16 encoding");
2607 break;
2608 }
2609 for (int i = start; i < n_octets; i += 2 ) {
2610 int first = isbig ? i : i + 1;
2611 int second = isbig ? i + 1 : i;
2612 int third = isbig ? i + 2 : i + 3;
2613 int fourth = isbig ? i + 3 : i + 2;
2614
2615 uint16_t W1 = octets_ptr[first] << 8 | octets_ptr[second];
2616 uint16_t W2 = (i + 3 < n_octets) ? octets_ptr[third] << 8 | octets_ptr[fourth] : 0;
2617
2618 if (0xD800 > W1 || 0xDFFF < W1) {
2619 //if W1 < 0xD800 or W1 > 0xDFFF, the character value is the value of W1
2620 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2621 val_ptr->uchars_ptr[n_uchars].uc_plane = 0;
2622 val_ptr->uchars_ptr[n_uchars].uc_row = octets_ptr[first];
2623 val_ptr->uchars_ptr[n_uchars].uc_cell = octets_ptr[second];
2624 ++n_uchars;
2625 }
2626 else if (0xD800 > W1 || 0xDBFF < W1) {
2627 //Determine if W1 is between 0xD800 and 0xDBFF. If not, the sequence
2628 //is in error and no valid character can be obtained using W1.
2629 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2630 "The word (0x%04X) shall be between 0xD800 and 0xDBFF", W1);
2631 }
2632 else if (0 == W2 || (0xDC00 > W2 || 0xDFFF < W2)) {
2633 //If there is no W2 (that is, the sequence ends with W1), or if W2
2634 //is not between 0xDC00 and 0xDFFF, the sequence is in error.
2635 if (W2)
2636 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2637 "Wrong UTF-16 string. The word (0x%04X) shall be between 0xDC00 and 0xDFFF", W2);
2638 else
2639 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2640 "Wrong UTF-16 string. The decoding algorythm does not expect 0x00 or EOL");
2641 }
2642 else {
2643 //Construct a 20-bit unsigned integer, taking the 10 low-order bits of W1 as its 10 high-
2644 //order bits and the 10 low-order bits of W2 as its 10 low-order bits.
2645 const uint16_t mask10bitlow = 0x3FF;
2646 uint32_t DW = (W1 & mask10bitlow) << 10;
2647 DW |= (W2 & mask10bitlow);
2648 DW += 0x10000;
2649 val_ptr->uchars_ptr[n_uchars].uc_group = 0;
2650 val_ptr->uchars_ptr[n_uchars].uc_plane = DW >> 16;
2651 val_ptr->uchars_ptr[n_uchars].uc_row = DW >> 8;
2652 val_ptr->uchars_ptr[n_uchars].uc_cell = DW;
2653 ++n_uchars;
2654 i += 2; // jump over w2 in octetstring
2655 }
2656 }
2657 if (val_ptr->n_uchars != n_uchars) {
2658 // truncate the memory and set the correct size in case of decoding errors
2659 // (e.g. skipped octets)
2660 if (n_uchars > 0) {
2661 val_ptr = (universal_charstring_struct*)Realloc(val_ptr, MEMORY_SIZE(n_uchars));
2662 val_ptr->n_uchars = n_uchars;
2663 }
2664 else {
2665 clean_up();
2666 init_struct(0);
2667 }
2668 }
2669}
2670
2671void UNIVERSAL_CHARSTRING::decode_utf32(int n_octets, const unsigned char *octets_ptr,
2672 CharCoding::CharCodingType expected_coding)
2673{
2674 if (n_octets % 4 || 0 > n_octets) {
2675 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2676 "Wrong UTF-32 string. The number of bytes (%d) in octetstring shall be non negative and divisible by 4",
2677 n_octets);
2678 }
2679 int start = check_BOM(expected_coding, sizeof(octets_ptr), octets_ptr);
2680 int n_uchars = n_octets/4;
2681 init_struct(n_uchars);
2682 n_uchars = 0;
2683 bool isbig = true;
2684 switch (expected_coding) {
2685 case CharCoding::UTF32:
2686 case CharCoding::UTF32BE:
2687 isbig = true;
2688 break;
2689 case CharCoding::UTF32LE:
2690 isbig = false;
2691 break;
2692 default:
2693 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2694 "Unexpected coding type for UTF-32 encoding");
2695 break;
2696 }
2697 for (int i = start; i < n_octets; i += 4 ) {
2698 int first = isbig ? i : i + 3;
2699 int second = isbig ? i + 1 : i + 2;
2700 int third = isbig ? i + 2 : i + 1;
2701 int fourth = isbig ? i + 3 : i;
2702 uint32_t DW = octets_ptr[first] << 8 | octets_ptr[second];
2703 DW <<= 8;
2704 DW |= octets_ptr[third];
2705 DW <<= 8;
2706 DW |= octets_ptr[fourth];
2707 if (0x0000D800 <= DW && 0x0000DFFF >= DW) {
2708 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2709 "Any UTF-32 code (0x%08X) between 0x0000D800 and 0x0000DFFF is ill-formed", DW);
2710 }
2711 else if (0x0010FFFF < DW) {
2712 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2713 "Any UTF-32 code (0x%08X) greater than 0x0010FFFF is ill-formed", DW);
2714 }
2715 else {
2716 val_ptr->uchars_ptr[n_uchars].uc_group = octets_ptr[first];
2717 val_ptr->uchars_ptr[n_uchars].uc_plane = octets_ptr[second];
2718 val_ptr->uchars_ptr[n_uchars].uc_row = octets_ptr[third];
2719 val_ptr->uchars_ptr[n_uchars].uc_cell = octets_ptr[fourth];
2720 ++n_uchars;
2721 }
2722 }
2723 if (val_ptr->n_uchars != n_uchars) {
2724 // truncate the memory and set the correct size in case of decoding errors
2725 // (e.g. skipped octets)
2726 if (n_uchars > 0) {
2727 val_ptr = (universal_charstring_struct*)Realloc(val_ptr, MEMORY_SIZE(n_uchars));
2728 val_ptr->n_uchars = n_uchars;
2729 }
2730 else {
2731 clean_up();
2732 init_struct(0);
2733 }
2734 }
2735}
2736int UNIVERSAL_CHARSTRING::check_BOM(CharCoding::CharCodingType expected_coding,
2737 unsigned int length,
2738 const unsigned char* ostr)
2739{
2740 switch (expected_coding) {
2741 case CharCoding::UTF32:
2742 case CharCoding::UTF32BE:
2743 case CharCoding::UTF32LE:
2744 if (4 > length) {
2745 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2746 "The string is shorter than the expected BOM");
2747 }
2748 break;
2749 case CharCoding::UTF16:
2750 case CharCoding::UTF16BE:
2751 case CharCoding::UTF16LE:
2752 if (2 > length) {
2753 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2754 "The string is shorter than the expected BOM");
2755 }
2756 break;
2757 case CharCoding::UTF_8:
2758 if (3 > length) {
2759 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
2760 "The string is shorter than the expected BOM");
2761 }
2762 break;
2763 default: break;
2764 }
2765 std::string coding_str;
2766 //BOM indicates that the byte order is determined by a byte order mark,
2767 //if present at the beginning the length of BOM is returned.
2768 switch (expected_coding) {
2769 case CharCoding::UTF32BE:
2770 case CharCoding::UTF32:
2771 if (0x00 == ostr[0] && 0x00 == ostr[1] && 0xFE == ostr[2] && 0xFF == ostr[3]) {
2772 return 4;
2773 }
2774 coding_str = "UTF-32BE";
2775 break;
2776 case CharCoding::UTF32LE:
2777 if (0xFF == ostr[0] && 0xFE == ostr[1] && 0x00 == ostr[2] && 0x00 == ostr[3]) {
2778 return 4;
2779 }
2780 coding_str = "UTF-32LE";
2781 break;
2782 case CharCoding::UTF16BE:
2783 case CharCoding::UTF16:
2784 if (0xFE == ostr[0] && 0xFF == ostr[1]) {
2785 return 2;
2786 }
2787 coding_str = "UTF-16BE";
2788 break;
2789 case CharCoding::UTF16LE:
2790 if (0xFF == ostr[0] && 0xFE == ostr[1]) {
2791 return 2;
2792 }
2793 coding_str = "UTF-16LE";
2794 break;
2795 case CharCoding::UTF_8:
2796 if (0xEF == ostr[0] && 0xBB == ostr[1] && 0xBF == ostr[2]) {
2797 return 3;
2798 }
2799 coding_str = "UTF-8";
2800 break;
2801 default:
2802 // No BOM found
2803 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_DEC_UCSTR,
2804 "Wrong %s string. No BOM detected, however the given coding type (%s) expects it to define the endianness",
2805 coding_str.c_str(), coding_str.c_str());
2806 break;
2807 }
2808 TTCN_EncDec_ErrorContext::warning("No %s Byte Order Mark(BOM) detected. It may result decoding errors",
2809 coding_str.c_str());
2810 return 0;
2811}
2812
2813// member functions of class UNIVERSAL_CHARSTRING_ELEMENTS
2814
2815UNIVERSAL_CHARSTRING_ELEMENT::UNIVERSAL_CHARSTRING_ELEMENT
2816 (boolean par_bound_flag, UNIVERSAL_CHARSTRING& par_str_val,
2817 int par_uchar_pos) :
2818 bound_flag(par_bound_flag), str_val(par_str_val), uchar_pos(par_uchar_pos)
2819{
2820
2821}
2822
2823UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2824 (const universal_char& other_value)
2825{
2826 bound_flag = TRUE;
2827 if (str_val.charstring) {
2828 if (other_value.is_char()) {
2829 str_val.cstr.val_ptr->chars_ptr[uchar_pos] = other_value.uc_cell;
2830 return *this;
2831 } else
2832 str_val.convert_cstr_to_uni();
2833 } else
2834 str_val.copy_value();
2835 str_val.val_ptr->uchars_ptr[uchar_pos] = other_value;
2836 return *this;
2837}
2838
2839UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2840 (const char* other_value)
2841{
2842 if (other_value == NULL || other_value[0] == '\0' || other_value[1] != '\0')
2843 TTCN_error("Assignment of a charstring value with length other than 1 to "
2844 "a universal charstring element.");
2845 bound_flag = TRUE;
2846 if (str_val.charstring)
2847 str_val.cstr.val_ptr->chars_ptr[uchar_pos] = other_value[0];
2848 else {
2849 str_val.copy_value();
2850 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2851 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2852 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2853 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell = other_value[0];
2854 }
2855 return *this;
2856}
2857
2858UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2859 (const CHARSTRING& other_value)
2860{
2861 other_value.must_bound("Assignment of an unbound charstring value to a "
2862 "universal charstring element.");
2863 if(other_value.val_ptr->n_chars != 1)
2864 TTCN_error("Assignment of a charstring value with length other than 1 to "
2865 "a universal charstring element.");
2866 bound_flag = TRUE;
2867 if (str_val.charstring)
2868 str_val.cstr.val_ptr->chars_ptr[uchar_pos] =
2869 other_value.val_ptr->chars_ptr[0];
2870 else {
2871 str_val.copy_value();
2872 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2873 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2874 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2875 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell =
2876 other_value.val_ptr->chars_ptr[0];
2877 }
2878 return *this;
2879}
2880
2881UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2882 (const CHARSTRING_ELEMENT& other_value)
2883{
2884 other_value.must_bound("Assignment of an unbound charstring element to a "
2885 "universal charstring element.");
2886 bound_flag = TRUE;
2887 if (str_val.charstring)
2888 str_val.cstr.val_ptr->chars_ptr[uchar_pos] = other_value.get_char();
2889 else {
2890 str_val.copy_value();
2891 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2892 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2893 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2894 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell = other_value.get_char();
2895 }
2896 return *this;
2897}
2898
2899UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2900 (const UNIVERSAL_CHARSTRING& other_value)
2901{
2902 other_value.must_bound("Assignment of an unbound universal charstring value "
2903 "to a universal charstring element.");
a38c6d4c 2904 int other_value_size = other_value.charstring ? other_value.cstr.val_ptr->n_chars :
2905 other_value.val_ptr->n_uchars;
2906 if (other_value_size != 1)
970ed795
EL
2907 TTCN_error("Assignment of a universal charstring value with length other "
2908 "than 1 to a universal charstring element.");
2909 bound_flag = TRUE;
a38c6d4c 2910 *this = other_value[0];
970ed795
EL
2911 return *this;
2912}
2913
2914UNIVERSAL_CHARSTRING_ELEMENT& UNIVERSAL_CHARSTRING_ELEMENT::operator=
2915 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
2916{
2917 other_value.must_bound("Assignment of an unbound universal charstring "
2918 "element.");
2919 if (&other_value != this) {
2920 bound_flag = TRUE;
2921 if (str_val.charstring) {
2922 if (other_value.str_val.charstring)
2923 str_val.cstr.val_ptr->chars_ptr[uchar_pos] =
2924 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
2925 else {
2926 str_val.convert_cstr_to_uni();
2927 str_val.val_ptr->uchars_ptr[uchar_pos] =
2928 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
2929 }
2930 } else {
2931 if (other_value.str_val.charstring) {
2932 str_val.val_ptr->uchars_ptr[uchar_pos].uc_group = 0;
2933 str_val.val_ptr->uchars_ptr[uchar_pos].uc_plane = 0;
2934 str_val.val_ptr->uchars_ptr[uchar_pos].uc_row = 0;
2935 str_val.val_ptr->uchars_ptr[uchar_pos].uc_cell =
2936 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
2937 } else {
2938 str_val.copy_value();
2939 str_val.val_ptr->uchars_ptr[uchar_pos] =
2940 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
2941 }
2942 }
2943 }
2944 return *this;
2945}
2946
2947boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2948 (const universal_char& other_value) const
2949{
2950 must_bound("The left operand of comparison is an unbound universal "
2951 "charstring element.");
2952 if (str_val.charstring && other_value.is_char())
2953 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] == other_value.uc_cell;
2954 if (str_val.charstring && !other_value.is_char())
2955 return FALSE;
2956 if (!str_val.charstring && other_value.is_char()) {
2957 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2958 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
2959 uchar.uc_cell == other_value.uc_cell;
2960 }
2961 return str_val.val_ptr->uchars_ptr[uchar_pos] == other_value;
2962}
2963
2964boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2965 (const char* other_value) const
2966{
2967 must_bound("The left operand of comparison is an unbound universal "
2968 "charstring element.");
2969 if (other_value == NULL || other_value[0] == '\0' ||
2970 other_value[1] != '\0') return FALSE;
2971 if (str_val.charstring)
2972 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] == other_value[0];
2973 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2974 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
2975 uchar.uc_cell == (cbyte)other_value[0];
2976}
2977
2978boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2979 (const CHARSTRING& other_value) const
2980{
2981 must_bound("The left operand of comparison is an unbound universal "
2982 "charstring element.");
2983 other_value.must_bound("The right operand of comparison is an unbound "
2984 "charstring value.");
2985 if (other_value.val_ptr->n_chars != 1) return FALSE;
2986 if (str_val.charstring)
2987 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] ==
2988 other_value.val_ptr->chars_ptr[0];
2989 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
2990 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
2991 uchar.uc_cell == (cbyte)other_value.val_ptr->chars_ptr[0];
2992}
2993
2994boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
2995 (const CHARSTRING_ELEMENT& other_value) const
2996{
2997 must_bound("The left operand of comparison is an unbound universal "
2998 "charstring element.");
2999 other_value.must_bound("The right operand of comparison is an unbound "
3000 "charstring element.");
3001 if (str_val.charstring)
3002 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] == other_value.get_char();
3003 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3004 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3005 uchar.uc_cell == (cbyte)other_value.get_char();
3006}
3007
3008boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
3009 (const UNIVERSAL_CHARSTRING& other_value) const
3010{
3011 must_bound("The left operand of comparison is an unbound universal "
3012 "charstring element.");
3013 other_value.must_bound("The right operand of comparison is an unbound "
3014 "universal charstring value.");
3015 if (other_value.charstring) {
3016 if (other_value.cstr.val_ptr->n_chars != 1)
3017 return FALSE;
3018 if (str_val.charstring)
3019 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] ==
3020 other_value.cstr.val_ptr->chars_ptr[0];
3021 else {
3022 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3023 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0
3024 && uchar.uc_cell == (cbyte)other_value.cstr.val_ptr->chars_ptr[0];
3025 }
3026 } else {
3027 if (other_value.val_ptr->n_uchars != 1)
3028 return FALSE;
3029 if (str_val.charstring) {
3030 const universal_char& uchar = other_value.val_ptr->uchars_ptr[0];
3031 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3032 uchar.uc_cell == (cbyte)str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3033 } else
3034 return str_val.val_ptr->uchars_ptr[uchar_pos] ==
3035 other_value.val_ptr->uchars_ptr[0];
3036 }
3037}
3038
3039boolean UNIVERSAL_CHARSTRING_ELEMENT::operator==
3040 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
3041{
3042 must_bound("The left operand of comparison is an unbound universal "
3043 "charstring element.");
3044 other_value.must_bound("The right operand of comparison is an unbound "
3045 "universal charstring element.");
3046 if (str_val.charstring) {
3047 if (other_value.str_val.charstring)
3048 return str_val.cstr.val_ptr->chars_ptr[uchar_pos] ==
3049 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3050 else {
3051 const universal_char& uchar = other_value.get_uchar();
3052 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3053 uchar.uc_cell == str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3054 }
3055 } else {
3056 if (other_value.str_val.charstring) {
3057 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3058 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3059 uchar.uc_cell ==
3060 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3061 } else
3062 return str_val.val_ptr->uchars_ptr[uchar_pos] ==
3063 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
3064 }
3065}
3066
3067UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3068 (const universal_char& other_value) const
3069{
3070 must_bound("The left operand of concatenation is an unbound universal "
3071 "charstring element.");
3072 if (str_val.charstring && other_value.is_char()) {
3073 UNIVERSAL_CHARSTRING ret_val(2, true);
3074 ret_val.cstr.val_ptr->chars_ptr[0] =
3075 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3076 ret_val.cstr.val_ptr->chars_ptr[1] = other_value.uc_cell;
3077 return ret_val;
3078 } else if (str_val.charstring ^ other_value.is_char()) {
3079 universal_char result[2];
3080 if (str_val.charstring) {
3081 result[0].uc_group = result[0].uc_plane = result[0].uc_row = 0;
3082 result[0].uc_cell = str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3083 } else
3084 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3085 result[1] = other_value;
3086 return UNIVERSAL_CHARSTRING(2, result);
3087 }
3088 universal_char result[2];
3089 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3090 result[1] = other_value;
3091 return UNIVERSAL_CHARSTRING(2, result);
3092}
3093
3094UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3095 (const char* other_value) const
3096{
3097 must_bound("The left operand of concatenation is an unbound universal "
3098 "charstring element.");
3099 int other_len;
3100 if (other_value == NULL) other_len = 0;
3101 else other_len = strlen(other_value);
3102
3103 UNIVERSAL_CHARSTRING ret_val(other_len + 1, str_val.charstring);
3104 if (str_val.charstring) {
3105 ret_val.cstr.val_ptr->chars_ptr[0] =
3106 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3107 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1, other_value, other_len);
3108 } else {
3109 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3110 for (int i = 0; i < other_len; i++) {
3111 ret_val.val_ptr->uchars_ptr[i + 1].uc_group = 0;
3112 ret_val.val_ptr->uchars_ptr[i + 1].uc_plane = 0;
3113 ret_val.val_ptr->uchars_ptr[i + 1].uc_row = 0;
3114 ret_val.val_ptr->uchars_ptr[i + 1].uc_cell = other_value[i];
3115 }
3116 }
3117 return ret_val;
3118}
3119
3120UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3121 (const CHARSTRING& other_value) const
3122{
3123 must_bound("The left operand of concatenation is an unbound universal "
3124 "charstring element.");
3125 other_value.must_bound("The right operand of concatenation is an unbound "
3126 "charstring value.");
3127 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_chars + 1,
3128 str_val.charstring);
3129 if (str_val.charstring) {
3130 ret_val.cstr.val_ptr->chars_ptr[0] =
3131 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3132 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1, other_value.val_ptr->chars_ptr,
3133 other_value.val_ptr->n_chars);
3134 } else {
3135 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3136 for (int i = 0; i < other_value.val_ptr->n_chars; i++) {
3137 ret_val.val_ptr->uchars_ptr[i + 1].uc_group = 0;
3138 ret_val.val_ptr->uchars_ptr[i + 1].uc_plane = 0;
3139 ret_val.val_ptr->uchars_ptr[i + 1].uc_row = 0;
3140 ret_val.val_ptr->uchars_ptr[i + 1].uc_cell =
3141 other_value.val_ptr->chars_ptr[i];
3142 }
3143 }
3144 return ret_val;
3145}
3146
3147UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3148 (const CHARSTRING_ELEMENT& other_value) const
3149{
3150 must_bound("The left operand of concatenation is an unbound universal "
3151 "charstring element.");
3152 other_value.must_bound("The right operand of concatenation is an unbound "
3153 "charstring element.");
3154 if (str_val.charstring) {
3155 UNIVERSAL_CHARSTRING ret_val(2, true);
3156 ret_val.cstr.val_ptr->chars_ptr[0] =
3157 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3158 ret_val.cstr.val_ptr->chars_ptr[1] = other_value.get_char();
3159 return ret_val;
3160 } else {
3161 universal_char result[2];
3162 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3163 result[1].uc_group = 0;
3164 result[1].uc_plane = 0;
3165 result[1].uc_row = 0;
3166 result[1].uc_cell = other_value.get_char();
3167 return UNIVERSAL_CHARSTRING(2, result);
3168 }
3169}
3170
3171UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3172 (const UNIVERSAL_CHARSTRING& other_value) const
3173{
3174 must_bound("The left operand of concatenation is an unbound universal "
3175 "charstring element.");
3176 other_value.must_bound("The right operand of concatenation is an unbound "
3177 "universal charstring value.");
3178 if (str_val.charstring) {
3179 if (other_value.charstring) {
3180 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1, true);
3181 ret_val.cstr.val_ptr->chars_ptr[0] =
3182 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3183 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1,
3184 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
3185 return ret_val;
3186 } else {
3187 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3188 universal_char& uchar = ret_val.val_ptr->uchars_ptr[0];
3189 uchar.uc_group = uchar.uc_plane = uchar.uc_row = 0;
3190 uchar.uc_cell = str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3191 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
3192 other_value.val_ptr->n_uchars * sizeof(universal_char));
3193 return ret_val;
3194 }
3195 } else {
3196 if (other_value.charstring) {
3197 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1);
3198 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3199 for (int i = 1; i <= other_value.cstr.val_ptr->n_chars; ++i) {
3200 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
3201 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
3202 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
3203 ret_val.val_ptr->uchars_ptr[i].uc_cell =
3204 other_value.cstr.val_ptr->chars_ptr[i-1];
3205 }
3206 return ret_val;
3207 } else {
3208 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3209 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3210 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
3211 other_value.val_ptr->n_uchars * sizeof(universal_char));
3212 return ret_val;
3213 }
3214 }
3215}
3216
3217UNIVERSAL_CHARSTRING UNIVERSAL_CHARSTRING_ELEMENT::operator+
3218 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
3219{
3220 must_bound("The left operand of concatenation is an unbound universal "
3221 "charstring element.");
3222 other_value.must_bound("The right operand of concatenation is an unbound "
3223 "universal charstring element.");
3224 if (str_val.charstring) {
3225 if (other_value.str_val.charstring) {
3226 UNIVERSAL_CHARSTRING ret_val(2, true);
3227 ret_val.cstr.val_ptr->chars_ptr[0] =
3228 str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3229 ret_val.cstr.val_ptr->chars_ptr[1] =
3230 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3231 return ret_val;
3232 } else {
3233 UNIVERSAL_CHARSTRING ret_val(2);
3234 universal_char& uchar = ret_val.val_ptr->uchars_ptr[0];
3235 uchar.uc_group = uchar.uc_plane = uchar.uc_row = 0;
3236 uchar.uc_cell = str_val.cstr.val_ptr->chars_ptr[uchar_pos];
3237 ret_val.val_ptr->uchars_ptr[1] =
3238 other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
3239 return ret_val;
3240 }
3241 } else {
3242 if (other_value.str_val.charstring) {
3243 UNIVERSAL_CHARSTRING ret_val(2);
3244 ret_val.val_ptr->uchars_ptr[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3245 ret_val.val_ptr->uchars_ptr[1].uc_group = 0;
3246 ret_val.val_ptr->uchars_ptr[1].uc_plane = 0;
3247 ret_val.val_ptr->uchars_ptr[1].uc_row = 0;
3248 ret_val.val_ptr->uchars_ptr[1].uc_cell =
3249 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3250 return ret_val;
3251 } else {
3252 universal_char result[2];
3253 result[0] = str_val.val_ptr->uchars_ptr[uchar_pos];
3254 result[1] = other_value.str_val.val_ptr->uchars_ptr[other_value.uchar_pos];
3255 return UNIVERSAL_CHARSTRING(2, result);
3256 }
3257 }
3258}
3259
3260const universal_char& UNIVERSAL_CHARSTRING_ELEMENT::get_uchar() const
3261{
3262 if (str_val.charstring)
3263 const_cast<UNIVERSAL_CHARSTRING_ELEMENT&>
3264 (*this).str_val.convert_cstr_to_uni();
3265 return str_val.val_ptr->uchars_ptr[uchar_pos];
3266}
3267
3268void UNIVERSAL_CHARSTRING_ELEMENT::log() const
3269{
3270 if (bound_flag) {
3271 if (str_val.charstring) {
3272 str_val.cstr[uchar_pos].log();
3273 return;
3274 }
3275 const universal_char& uchar = str_val.val_ptr->uchars_ptr[uchar_pos];
3276 if (is_printable(uchar)) {
3277 // the character is printable
3278 TTCN_Logger::log_char('"');
3279 TTCN_Logger::log_char_escaped(uchar.uc_cell);
3280 TTCN_Logger::log_char('"');
3281 } else {
3282 // the character is not printable
3283 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
3284 uchar.uc_group, uchar.uc_plane, uchar.uc_row, uchar.uc_cell);
3285 }
3286 } else TTCN_Logger::log_event_unbound();
3287}
3288
3289// global functions
3290
3291boolean operator==(const universal_char& uchar_value,
3292 const UNIVERSAL_CHARSTRING& other_value)
3293{
3294 other_value.must_bound("The right operand of comparison is an unbound "
3295 "universal charstring value.");
3296 if (other_value.charstring) {
3297 if (other_value.cstr.val_ptr->n_chars != 1) return FALSE;
3298 else return uchar_value.is_char() &&
3299 uchar_value.uc_cell == other_value.cstr.val_ptr->chars_ptr[0];
3300 }
3301 if (other_value.val_ptr->n_uchars != 1) return FALSE;
3302 else return uchar_value == other_value.val_ptr->uchars_ptr[0];
3303}
3304
3305boolean operator==(const universal_char& uchar_value,
3306 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3307{
3308 other_value.must_bound("The right operand of comparison is an unbound "
3309 "universal charstring element.");
3310 return uchar_value == other_value.get_uchar();
3311}
3312
3313UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value,
3314 const UNIVERSAL_CHARSTRING& other_value)
3315{
3316 other_value.must_bound("The right operand of concatenation is an unbound "
3317 "universal charstring value.");
3318 if (other_value.charstring) {
3319 if (uchar_value.is_char()) {
3320 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1, true);
3321 ret_val.cstr.val_ptr->chars_ptr[0] = uchar_value.uc_cell;
3322 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1,
3323 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
3324 return ret_val;
3325 } else {
3326 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3327 ret_val.val_ptr->uchars_ptr[0] = uchar_value;
3328 for (int i = 0; i < other_value.cstr.val_ptr->n_chars; i++) {
3329 ret_val.val_ptr->uchars_ptr[i+1].uc_group = 0;
3330 ret_val.val_ptr->uchars_ptr[i+1].uc_plane = 0;
3331 ret_val.val_ptr->uchars_ptr[i+1].uc_row = 0;
3332 ret_val.val_ptr->uchars_ptr[i+1].uc_cell =
3333 other_value.cstr.val_ptr->chars_ptr[i];
3334 }
3335 return ret_val;
3336 }
3337 } else {
3338 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
3339 ret_val.val_ptr->uchars_ptr[0] = uchar_value;
3340 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
3341 other_value.val_ptr->n_uchars * sizeof(universal_char));
3342 return ret_val;
3343 }
3344}
3345
3346UNIVERSAL_CHARSTRING operator+(const universal_char& uchar_value,
3347 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3348{
3349 other_value.must_bound("The right operand of concatenation is an unbound "
3350 "universal charstring element.");
3351 if (other_value.str_val.charstring) {
3352 if (uchar_value.is_char()) {
3353 char result[2];
3354 result[0] = uchar_value.uc_cell;
3355 result[1] =
3356 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3357 return UNIVERSAL_CHARSTRING(2, result);
3358 } else {
3359 universal_char result[2];
3360 result[0] = uchar_value;
3361 result[1].uc_group = 0;
3362 result[1].uc_plane = 0;
3363 result[1].uc_row = 0;
3364 result[1].uc_cell =
3365 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3366 return UNIVERSAL_CHARSTRING(2, result);
3367 }
3368 } else {
3369 universal_char result[2];
3370 result[0] = uchar_value;
3371 result[1] = other_value.get_uchar();
3372 return UNIVERSAL_CHARSTRING(2, result);
3373 }
3374}
3375
3376boolean operator==(const char *string_value,
3377 const UNIVERSAL_CHARSTRING& other_value)
3378{
3379 other_value.must_bound("The right operand of comparison is an unbound "
3380 "universal charstring value.");
3381 int string_len;
3382 if (string_value == NULL) string_len = 0;
3383 else string_len = strlen(string_value);
3384 if (other_value.charstring) {
3385 return other_value.cstr == string_value;
3386 } else {
3387 if (string_len != other_value.val_ptr->n_uchars) return FALSE;
3388 for (int i = 0; i < string_len; i++) {
3389 if (other_value.val_ptr->uchars_ptr[i].uc_group != 0 ||
3390 other_value.val_ptr->uchars_ptr[i].uc_plane != 0 ||
3391 other_value.val_ptr->uchars_ptr[i].uc_row != 0 ||
3392 other_value.val_ptr->uchars_ptr[i].uc_cell != string_value[i])
3393 return FALSE;
3394 }
3395 }
3396 return TRUE;
3397}
3398
3399boolean operator==(const char *string_value,
3400 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3401{
3402 other_value.must_bound("The right operand of comparison is an unbound "
3403 "universal charstring element.");
3404 if (string_value == NULL || string_value[0] == '\0' ||
3405 string_value[1] != '\0') return FALSE;
3406 if (other_value.str_val.charstring)
3407 return other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos]
3408 == string_value[0];
3409 const universal_char& uchar = other_value.get_uchar();
3410 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
3411 uchar.uc_cell == string_value[0];
3412}
3413
3414UNIVERSAL_CHARSTRING operator+(const char *string_value,
3415 const UNIVERSAL_CHARSTRING& other_value)
3416{
3417 other_value.must_bound("The right operand of concatenation is an unbound "
3418 "universal charstring value.");
3419 int string_len;
3420 if (string_value == NULL) string_len = 0;
3421 else string_len = strlen(string_value);
3422 if (other_value.charstring) {
3423 UNIVERSAL_CHARSTRING ret_val(string_len + other_value.cstr.val_ptr->n_chars,
3424 true);
3425 memcpy(ret_val.cstr.val_ptr->chars_ptr, string_value, string_len);
3426 memcpy(ret_val.cstr.val_ptr->chars_ptr + string_len,
3427 other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
3428 return ret_val;
3429 }
3430 UNIVERSAL_CHARSTRING ret_val(string_len + other_value.val_ptr->n_uchars);
3431 for (int i = 0; i < string_len; i++) {
3432 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
3433 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
3434 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
3435 ret_val.val_ptr->uchars_ptr[i].uc_cell = string_value[i];
3436 }
3437 memcpy(ret_val.val_ptr->uchars_ptr + string_len,
3438 other_value.val_ptr->uchars_ptr,
3439 other_value.val_ptr->n_uchars * sizeof(universal_char));
3440 return ret_val;
3441}
3442
3443UNIVERSAL_CHARSTRING operator+(const char *string_value,
3444 const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3445{
3446 other_value.must_bound("The right operand of concatenation is an unbound "
3447 "universal charstring element.");
3448 int string_len;
3449 if (string_value == NULL) string_len = 0;
3450 else string_len = strlen(string_value);
3451 if (other_value.str_val.charstring) {
3452 UNIVERSAL_CHARSTRING ret_val(string_len + 1, true);
3453 memcpy(ret_val.cstr.val_ptr->chars_ptr, string_value, string_len);
3454 ret_val.cstr.val_ptr->chars_ptr[string_len] =
3455 other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
3456 return ret_val;
3457 }
3458 UNIVERSAL_CHARSTRING ret_val(string_len + 1);
3459 for (int i = 0; i < string_len; i++) {
3460 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
3461 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
3462 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
3463 ret_val.val_ptr->uchars_ptr[i].uc_cell = string_value[i];
3464 }
3465 ret_val.val_ptr->uchars_ptr[string_len] = other_value.get_uchar();
3466 return ret_val;
3467}
3468
3469// member functions of class UNIVERSAL_CHARSTRING_template
3470
3471void UNIVERSAL_CHARSTRING_template::clean_up()
3472{
3473 if (template_selection == VALUE_LIST ||
3474 template_selection == COMPLEMENTED_LIST) delete [] value_list.list_value;
3475 else if (template_selection == STRING_PATTERN) {
3476 if (pattern_value.regexp_init) regfree(&pattern_value.posix_regexp);
3477 delete pattern_string;
3478 }
3479 template_selection = UNINITIALIZED_TEMPLATE;
3480}
3481
3482void UNIVERSAL_CHARSTRING_template::copy_template
3483 (const CHARSTRING_template& other_value)
3484{
3485 switch (other_value.template_selection) {
3486 case SPECIFIC_VALUE:
3487 single_value = other_value.single_value;
3488 break;
3489 case OMIT_VALUE:
3490 case ANY_VALUE:
3491 case ANY_OR_OMIT:
3492 break;
3493 case VALUE_LIST:
3494 case COMPLEMENTED_LIST:
3495 value_list.n_values = other_value.value_list.n_values;
3496 value_list.list_value =
3497 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
3498 for (unsigned int i = 0; i < value_list.n_values; i++)
3499 value_list.list_value[i].copy_template(
3500 other_value.value_list.list_value[i]);
3501 break;
3502 case VALUE_RANGE:
3503 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
3504 "not set when copying a charstring value range template to a universal "
3505 "charstring template.");
3506 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
3507 "not set when copying a charstring value range template to a universal "
3508 "charstring template.");
3509 value_range.min_is_set = TRUE;
3510 value_range.max_is_set = TRUE;
3511 value_range.min_value.uc_group = 0;
3512 value_range.min_value.uc_plane = 0;
3513 value_range.min_value.uc_row = 0;
3514 value_range.min_value.uc_cell = other_value.value_range.min_value;
3515 value_range.max_value.uc_group = 0;
3516 value_range.max_value.uc_plane = 0;
3517 value_range.max_value.uc_row = 0;
3518 value_range.max_value.uc_cell = other_value.value_range.max_value;
3519 break;
3520 case STRING_PATTERN:
3521 pattern_string = new CHARSTRING(other_value.single_value);
3522 pattern_value.regexp_init=FALSE;
3523 break;
3524 default:
3525 TTCN_error("Copying an uninitialized/unsupported charstring template to a "
3526 "universal charstring template.");
3527 }
3528 set_selection(other_value);
3529}
3530
3531void UNIVERSAL_CHARSTRING_template::copy_template
3532 (const UNIVERSAL_CHARSTRING_template& other_value)
3533{
3534 switch (other_value.template_selection) {
3535 case SPECIFIC_VALUE:
3536 single_value = other_value.single_value;
3537 break;
3538 case OMIT_VALUE:
3539 case ANY_VALUE:
3540 case ANY_OR_OMIT:
3541 break;
3542 case VALUE_LIST:
3543 case COMPLEMENTED_LIST:
3544 value_list.n_values = other_value.value_list.n_values;
3545 value_list.list_value =
3546 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
3547 for (unsigned int i = 0; i < value_list.n_values; i++)
3548 value_list.list_value[i].copy_template(
3549 other_value.value_list.list_value[i]);
3550 break;
3551 case VALUE_RANGE:
3552 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
3553 "not set when copying a universal charstring value range template.");
3554 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
3555 "not set when copying a universal charstring value range template.");
3556 value_range = other_value.value_range;
3557 break;
3558 case STRING_PATTERN:
3559 pattern_string = new CHARSTRING(*(other_value.pattern_string));
3560 pattern_value.regexp_init=FALSE;
3561 break;
3562 default:
3563 TTCN_error("Copying an uninitialized/unsupported universal charstring "
3564 "template.");
3565 }
3566 set_selection(other_value);
3567}
3568
3569UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template()
3570{
3571}
3572
3573UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3574 (template_sel other_value) : Restricted_Length_Template(other_value)
3575
3576{
3577 check_single_selection(other_value);
3578}
3579
3580UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3581 (const CHARSTRING& other_value) :
3582 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3583{
3584}
3585
3586UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3587 (const UNIVERSAL_CHARSTRING& other_value) :
3588 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3589{
3590}
3591
3592UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3593 (const CHARSTRING_ELEMENT& other_value) :
3594 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3595{
3596}
3597
3598UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3599 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) :
3600 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3601{
3602}
3603
3604UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3605 (const OPTIONAL<CHARSTRING>& other_value)
3606{
3607 switch (other_value.get_selection()) {
3608 case OPTIONAL_PRESENT:
3609 set_selection(SPECIFIC_VALUE);
3610 single_value = (const CHARSTRING&)other_value;
3611 break;
3612 case OPTIONAL_OMIT:
3613 set_selection(OMIT_VALUE);
3614 break;
3615 default:
3616 TTCN_error("Creating a universal charstring template from an unbound "
3617 "optional field.");
3618 }
3619}
3620
3621UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3622 (const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value)
3623{
3624 switch (other_value.get_selection()) {
3625 case OPTIONAL_PRESENT:
3626 set_selection(SPECIFIC_VALUE);
3627 single_value = (const UNIVERSAL_CHARSTRING&)other_value;
3628 break;
3629 case OPTIONAL_OMIT:
3630 set_selection(OMIT_VALUE);
3631 break;
3632 default:
3633 TTCN_error("Creating a universal charstring template from an unbound "
3634 "optional field.");
3635 }
3636}
3637
3638UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3639 (const CHARSTRING_template& other_value)
3640: Restricted_Length_Template()
3641{
3642 copy_template(other_value);
3643}
3644
3645UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3646 (const UNIVERSAL_CHARSTRING_template& other_value)
3647: Restricted_Length_Template()
3648{
3649 copy_template(other_value);
3650}
3651
3652UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3653 (template_sel p_sel, const CHARSTRING& p_str)
3654: Restricted_Length_Template(STRING_PATTERN)
3655{
3656 if(p_sel!=STRING_PATTERN)
3657 TTCN_error("Internal error: Initializing a universal charstring"
3658 "pattern template with invalid selection.");
3659 pattern_string = new CHARSTRING(p_str);
3660 pattern_value.regexp_init=FALSE;
3661}
3662
3663UNIVERSAL_CHARSTRING_template::~UNIVERSAL_CHARSTRING_template()
3664{
3665 clean_up();
3666}
3667
3668UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3669 (template_sel other_value)
3670{
3671 check_single_selection(other_value);
3672 clean_up();
3673 set_selection(other_value);
3674 return *this;
3675}
3676
3677UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3678 (const CHARSTRING& other_value)
3679{
3680 other_value.must_bound("Assignment of an unbound charstring value to a "
3681 "universal charstring template.");
3682 clean_up();
3683 set_selection(SPECIFIC_VALUE);
3684 single_value = other_value;
3685 return *this;
3686}
3687
3688UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3689 (const UNIVERSAL_CHARSTRING& other_value)
3690{
3691 other_value.must_bound("Assignment of an unbound universal charstring value "
3692 "to a template.");
3693 clean_up();
3694 set_selection(SPECIFIC_VALUE);
3695 single_value = other_value;
3696 return *this;
3697}
3698
3699UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3700 (const CHARSTRING_ELEMENT& other_value)
3701{
3702 other_value.must_bound("Assignment of an unbound charstring element to a "
3703 "universal charstring template.");
3704 clean_up();
3705 set_selection(SPECIFIC_VALUE);
3706 single_value = other_value;
3707 return *this;
3708}
3709
3710UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3711 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3712{
3713 other_value.must_bound("Assignment of an unbound universal charstring "
3714 "element to a template.");
3715 clean_up();
3716 set_selection(SPECIFIC_VALUE);
3717 single_value = other_value;
3718 return *this;
3719}
3720
3721UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3722 (const OPTIONAL<CHARSTRING>& other_value)
3723{
3724 clean_up();
3725 switch (other_value.get_selection()) {
3726 case OPTIONAL_PRESENT:
3727 set_selection(SPECIFIC_VALUE);
3728 single_value = (const CHARSTRING&)other_value;
3729 break;
3730 case OPTIONAL_OMIT:
3731 set_selection(OMIT_VALUE);
3732 break;
3733 default:
3734 TTCN_error("Assignment of an unbound optional field to a universal "
3735 "charstring template.");
3736 }
3737 return *this;
3738}
3739
3740UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3741 (const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value)
3742{
3743 clean_up();
3744 switch (other_value.get_selection()) {
3745 case OPTIONAL_PRESENT:
3746 set_selection(SPECIFIC_VALUE);
3747 single_value = (const UNIVERSAL_CHARSTRING&)other_value;
3748 break;
3749 case OPTIONAL_OMIT:
3750 set_selection(OMIT_VALUE);
3751 break;
3752 default:
3753 TTCN_error("Assignment of an unbound optional field to a universal "
3754 "charstring template.");
3755 }
3756 return *this;
3757}
3758
3759UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3760 (const CHARSTRING_template& other_value)
3761{
3762 clean_up();
3763 copy_template(other_value);
3764 return *this;
3765}
3766
3767UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3768 (const UNIVERSAL_CHARSTRING_template& other_value)
3769{
3770 if (&other_value != this) {
3771 clean_up();
3772 copy_template(other_value);
3773 }
3774 return *this;
3775}
3776
3777UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value)
3778{
3779 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3780 TTCN_error("Accessing a universal charstring element of a non-specific "
3781 "universal charstring template.");
3782 return single_value[index_value];
3783}
3784
3785UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](const INTEGER& index_value)
3786{
3787 index_value.must_bound("Indexing a universal charstring template with an "
3788 "unbound integer value.");
3789 return (*this)[(int)index_value];
3790}
3791
3792const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value) const
3793{
3794 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3795 TTCN_error("Accessing a universal charstring element of a non-specific "
3796 "universal charstring template.");
3797 return single_value[index_value];
3798}
3799
3800const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](const INTEGER& index_value) const
3801{
3802 index_value.must_bound("Indexing a universal charstring template with an "
3803 "unbound integer value.");
3804 return (*this)[(int)index_value];
3805}
3806
3807boolean UNIVERSAL_CHARSTRING_template::match
3abe9331 3808 (const UNIVERSAL_CHARSTRING& other_value, boolean /* legacy */) const
970ed795
EL
3809{
3810 if (!other_value.is_bound()) return FALSE;
3811 int value_length = other_value.lengthof();
3812 if (!match_length(value_length)) return FALSE;
3813 switch (template_selection) {
3814 case SPECIFIC_VALUE:
3815 return single_value == other_value;
3816 case OMIT_VALUE:
3817 return FALSE;
3818 case ANY_VALUE:
3819 case ANY_OR_OMIT:
3820 return TRUE;
3821 case VALUE_LIST:
3822 case COMPLEMENTED_LIST:
3823 for (unsigned int i = 0; i < value_list.n_values; i++)
3824 if (value_list.list_value[i].match(other_value))
3825 return template_selection == VALUE_LIST;
3826 return template_selection == COMPLEMENTED_LIST;
3827 case VALUE_RANGE: {
3828 if (!value_range.min_is_set) TTCN_error("The lower bound is not set when "
3829 "matching with a universal charstring value range template.");
3830 if (!value_range.max_is_set) TTCN_error("The upper bound is not set when "
3831 "matching with a universal charstring value range template.");
3832 if (value_range.max_value < value_range.min_value)
3833 TTCN_error("The lower bound is greater than the upper bound "
3834 "when matching with a universal charstring value range template.");
3835 const universal_char *uchars_ptr = other_value;
3836 for (int i = 0; i < value_length; i++) {
3837 if (uchars_ptr[i] < value_range.min_value ||
3838 value_range.max_value < uchars_ptr[i]) return FALSE;
3839 }
3840 return TRUE; }
3841 case STRING_PATTERN: {
3842 if (!pattern_value.regexp_init) {
3843 char *posix_str =
3844 TTCN_pattern_to_regexp_uni((const char*)(*pattern_string));
3845 if(posix_str==NULL) {
3846 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
3847 (const char*)(*pattern_string));
3848 }
3849 int ret_val=regcomp(&pattern_value.posix_regexp, posix_str,
3850 REG_EXTENDED|REG_NOSUB);
3851 Free(posix_str);
3852 if(ret_val!=0) {
3853 /* regexp error */
3854 char msg[ERRMSG_BUFSIZE];
3855 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
3856 regfree(&pattern_value.posix_regexp);
3857 TTCN_error("Pattern matching error: %s", msg);
3858 }
3859 pattern_value.regexp_init=TRUE;
3860 }
3861 char* other_value_converted = other_value.convert_to_regexp_form();
3862 int ret_val=regexec(&pattern_value.posix_regexp, other_value_converted, 0,
3863 NULL, 0);
3864 Free(other_value_converted);
3865 switch (ret_val) {
3866 case 0:
3867 return TRUE;
3868 case REG_NOMATCH:
3869 return FALSE;
3870 default:
3871 /* regexp error */
3872 char msg[ERRMSG_BUFSIZE];
3873 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
3874 TTCN_error("Pattern matching error: %s", msg);
3875 }
3876 break;}
3877 default:
3878 TTCN_error("Matching with an uninitialized/unsupported universal "
3879 "charstring template.");
3880 }
3881 return FALSE;
3882}
3883
3884const UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING_template::valueof() const
3885{
3886 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3887 TTCN_error("Performing valueof or send operation on a non-specific "
3888 "universal charstring template.");
3889 return single_value;
3890}
3891
3892int UNIVERSAL_CHARSTRING_template::lengthof() const
3893{
3894 int min_length;
3895 boolean has_any_or_none;
3896 if (is_ifpresent)
3897 TTCN_error("Performing lengthof() operation on a universal charstring "
3898 "template which has an ifpresent attribute.");
3899 switch (template_selection)
3900 {
3901 case SPECIFIC_VALUE:
3902 min_length = single_value.lengthof();
3903 has_any_or_none = FALSE;
3904 break;
3905 case OMIT_VALUE:
3906 TTCN_error("Performing lengthof() operation on a universal charstring "
3907 "template containing omit value.");
3908 case ANY_VALUE:
3909 case ANY_OR_OMIT:
3910 case VALUE_RANGE:
3911 min_length = 0;
3912 has_any_or_none = TRUE; // max. length is infinity
3913 break;
3914 case VALUE_LIST:
3915 {
3916 // error if any element does not have length or the lengths differ
3917 if (value_list.n_values<1)
3918 TTCN_error("Internal error: "
3919 "Performing lengthof() operation on a universal charstring "
3920 "template containing an empty list.");
3921 int item_length = value_list.list_value[0].lengthof();
3922 for (unsigned int i = 1; i < value_list.n_values; i++) {
3923 if (value_list.list_value[i].lengthof()!=item_length)
3924 TTCN_error("Performing lengthof() operation on a universal charstring "
3925 "template containing a value list with different lengths.");
3926 }
3927 min_length = item_length;
3928 has_any_or_none = FALSE;
3929 break;
3930 }
3931 case COMPLEMENTED_LIST:
3932 TTCN_error("Performing lengthof() operation on a universal charstring "
3933 "template containing complemented list.");
3934 case STRING_PATTERN:
3935 TTCN_error("Performing lengthof() operation on a universal charstring "
3936 "template containing a pattern is not allowed.");
3937 default:
3938 TTCN_error("Performing lengthof() operation on an "
3939 "uninitialized/unsupported universal charstring template.");
3940 }
3941 return check_section_is_single(min_length, has_any_or_none,
3942 "length", "a", "universal charstring template");
3943}
3944
3945void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type,
3946 unsigned int list_length)
3947{
3948 clean_up();
3949 switch (template_type) {
3950 case VALUE_LIST:
3951 case COMPLEMENTED_LIST:
3952 set_selection(template_type);
3953 value_list.n_values = list_length;
3954 value_list.list_value = new UNIVERSAL_CHARSTRING_template[list_length];
3955 break;
3956 case VALUE_RANGE:
3957 set_selection(VALUE_RANGE);
3958 value_range.min_is_set = FALSE;
3959 value_range.max_is_set = FALSE;
3960 break;
3961 default:
3962 TTCN_error("Setting an invalid type for a universal charstring template.");
3963 }
3964}
3965
3966UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::list_item
3967 (unsigned int list_index)
3968{
3969 if (template_selection != VALUE_LIST &&
3970 template_selection != COMPLEMENTED_LIST)
3971 TTCN_error("Accessing a list element of a non-list universal charstring "
3972 "template.");
3973 if (list_index >= value_list.n_values)
3974 TTCN_error("Index overflow in a universal charstring value list template.");
3975 return value_list.list_value[list_index];
3976}
3977
3978void UNIVERSAL_CHARSTRING_template::set_min
3979 (const UNIVERSAL_CHARSTRING& min_value)
3980{
3981 if (template_selection != VALUE_RANGE) TTCN_error("Setting the lower bound "
3982 "for a non-range universal charstring template.");
3983 min_value.must_bound("Setting an unbound value as lower bound in a "
3984 "universal charstring value range template.");
3985 int length = min_value.lengthof();
3986 if (length != 1) TTCN_error("The length of the lower bound in a universal "
3987 "charstring value range template must be 1 instead of %d.", length);
3988 value_range.min_is_set = TRUE;
3989 value_range.min_value = *(const universal_char*)min_value;
3990 if (value_range.max_is_set && value_range.max_value < value_range.min_value)
3991 TTCN_error("The lower bound in a universal charstring value range template "
3992 "is greater than the upper bound.");
3993}
3994
3995void UNIVERSAL_CHARSTRING_template::set_max
3996 (const UNIVERSAL_CHARSTRING& max_value)
3997{
3998 if (template_selection != VALUE_RANGE) TTCN_error("Setting the upper bound "
3999 "for a non-range universal charstring template.");
4000 max_value.must_bound("Setting an unbound value as upper bound in a "
4001 "universal charstring value range template.");
4002 int length = max_value.lengthof();
4003 if (length != 1) TTCN_error("The length of the upper bound in a universal "
4004 "charstring value range template must be 1 instead of %d.", length);
4005 value_range.max_is_set = TRUE;
4006 value_range.max_value = *(const universal_char*)max_value;
4007 if (value_range.min_is_set && value_range.max_value < value_range.min_value)
4008 TTCN_error("The upper bound in a universal charstring value range template "
4009 "is smaller than the lower bound.");
4010}
4011
4012void UNIVERSAL_CHARSTRING_template::log() const
4013{
4014 switch (template_selection) {
4015 case STRING_PATTERN:
4016 CHARSTRING_template::log_pattern(pattern_string->lengthof(),
4017 (const char*)*pattern_string);
4018 break;
4019 case SPECIFIC_VALUE:
4020 single_value.log();
4021 break;
4022 case COMPLEMENTED_LIST:
4023 TTCN_Logger::log_event_str("complement ");
4024 // no break
4025 case VALUE_LIST:
4026 TTCN_Logger::log_char('(');
4027 for(unsigned int i = 0; i < value_list.n_values; i++) {
4028 if (i > 0) TTCN_Logger::log_event_str(", ");
4029 value_list.list_value[i].log();
4030 }
4031 TTCN_Logger::log_char(')');
4032 break;
4033 case VALUE_RANGE:
4034 TTCN_Logger::log_char('(');
4035 if (value_range.min_is_set) {
4036 if (is_printable(value_range.min_value)) {
4037 TTCN_Logger::log_char('"');
4038 TTCN_Logger::log_char_escaped(value_range.min_value.uc_cell);
4039 TTCN_Logger::log_char('"');
4040 } else {
4041 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4042 value_range.min_value.uc_group, value_range.min_value.uc_plane,
4043 value_range.min_value.uc_row, value_range.min_value.uc_cell);
4044 }
4045 } else TTCN_Logger::log_event_str("<unknown lower bound>");
4046 TTCN_Logger::log_event_str(" .. ");
4047 if (value_range.max_is_set) {
4048 if (is_printable(value_range.max_value)) {
4049 TTCN_Logger::log_char('"');
4050 TTCN_Logger::log_char_escaped(value_range.max_value.uc_cell);
4051 TTCN_Logger::log_char('"');
4052 } else {
4053 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4054 value_range.max_value.uc_group, value_range.max_value.uc_plane,
4055 value_range.max_value.uc_row, value_range.max_value.uc_cell);
4056 }
4057 } else TTCN_Logger::log_event_str("<unknown upper bound>");
4058 TTCN_Logger::log_char(')');
4059 break;
4060 default:
4061 log_generic();
4062 break;
4063 }
4064 log_restricted();
4065 log_ifpresent();
4066}
4067
4068void UNIVERSAL_CHARSTRING_template::log_match
3abe9331 4069 (const UNIVERSAL_CHARSTRING& match_value, boolean /* legacy */) const
970ed795
EL
4070{
4071 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
4072 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
4073 TTCN_Logger::print_logmatch_buffer();
4074 TTCN_Logger::log_event_str(" := ");
4075 }
4076 match_value.log();
4077 TTCN_Logger::log_event_str(" with ");
4078 log();
4079 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
4080 else TTCN_Logger::log_event_str(" unmatched");
4081}
4082
4083void UNIVERSAL_CHARSTRING_template::set_param(Module_Param& param) {
4084 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "universal charstring template");
3abe9331 4085 Module_Param_Ptr mp = &param;
4086 if (param.get_type() == Module_Param::MP_Reference) {
4087 mp = param.get_referenced_param();
4088 }
4089 switch (mp->get_type()) {
970ed795
EL
4090 case Module_Param::MP_Omit:
4091 *this = OMIT_VALUE;
4092 break;
4093 case Module_Param::MP_Any:
4094 *this = ANY_VALUE;
4095 break;
4096 case Module_Param::MP_AnyOrNone:
4097 *this = ANY_OR_OMIT;
4098 break;
4099 case Module_Param::MP_List_Template:
3abe9331 4100 case Module_Param::MP_ComplementList_Template: {
4101 UNIVERSAL_CHARSTRING_template temp;
4102 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
4103 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
4104 for (size_t i=0; i<mp->get_size(); i++) {
4105 temp.list_item(i).set_param(*mp->get_elem(i));
970ed795 4106 }
3abe9331 4107 *this = temp;
4108 break; }
970ed795 4109 case Module_Param::MP_Charstring:
3abe9331 4110 *this = CHARSTRING(mp->get_string_size(), (char*)mp->get_string_data());
970ed795
EL
4111 break;
4112 case Module_Param::MP_Universal_Charstring:
3abe9331 4113 *this = UNIVERSAL_CHARSTRING(mp->get_string_size(), (universal_char*)mp->get_string_data());
970ed795
EL
4114 break;
4115 case Module_Param::MP_StringRange: {
3abe9331 4116 universal_char lower_uchar = mp->get_lower_uchar();
4117 universal_char upper_uchar = mp->get_upper_uchar();
970ed795
EL
4118 clean_up();
4119 set_selection(VALUE_RANGE);
4120 value_range.min_is_set = TRUE;
4121 value_range.max_is_set = TRUE;
4122 value_range.min_value = lower_uchar;
4123 value_range.max_value = upper_uchar;
4124 } break;
4125 case Module_Param::MP_Pattern:
4126 clean_up();
3abe9331 4127 pattern_string = new CHARSTRING(mp->get_pattern());
970ed795
EL
4128 pattern_value.regexp_init = FALSE;
4129 set_selection(STRING_PATTERN);
4130 break;
3abe9331 4131 case Module_Param::MP_Expression:
4132 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
4133 UNIVERSAL_CHARSTRING operand1, operand2, result;
4134 boolean is_pattern = operand1.set_param_internal(*mp->get_operand1(), TRUE);
4135 operand2.set_param(*mp->get_operand2());
4136 result = operand1 + operand2;
4137 if (is_pattern) {
4138 clean_up();
4139 if (result.charstring) {
4140 pattern_string = new CHARSTRING(result.cstr);
4141 }
4142 else {
4143 pattern_string = new CHARSTRING(result.get_stringRepr_for_pattern());
4144 }
4145 pattern_value.regexp_init = FALSE;
4146 set_selection(STRING_PATTERN);
4147 }
4148 else {
4149 *this = result;
4150 }
4151 }
4152 else {
4153 param.expr_type_error("a charstring");
4154 }
4155 break;
970ed795
EL
4156 default:
4157 param.type_error("universal charstring template");
4158 }
3abe9331 4159 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
4160 if (param.get_length_restriction() != NULL) {
4161 set_length_range(param);
4162 }
4163 else {
4164 set_length_range(*mp);
4165 }
4166}
4167
4168Module_Param* UNIVERSAL_CHARSTRING_template::get_param(Module_Param_Name& param_name) const
4169{
4170 Module_Param* mp = NULL;
4171 switch (template_selection) {
4172 case UNINITIALIZED_TEMPLATE:
4173 mp = new Module_Param_Unbound();
4174 break;
4175 case OMIT_VALUE:
4176 mp = new Module_Param_Omit();
4177 break;
4178 case ANY_VALUE:
4179 mp = new Module_Param_Any();
4180 break;
4181 case ANY_OR_OMIT:
4182 mp = new Module_Param_AnyOrNone();
4183 break;
4184 case SPECIFIC_VALUE:
4185 mp = single_value.get_param(param_name);
4186 break;
4187 case VALUE_LIST:
4188 case COMPLEMENTED_LIST: {
4189 if (template_selection == VALUE_LIST) {
4190 mp = new Module_Param_List_Template();
4191 }
4192 else {
4193 mp = new Module_Param_ComplementList_Template();
4194 }
4195 for (size_t i = 0; i < value_list.n_values; ++i) {
4196 mp->add_elem(value_list.list_value[i].get_param(param_name));
4197 }
4198 break; }
4199 case VALUE_RANGE:
4200 mp = new Module_Param_StringRange(value_range.min_value, value_range.max_value);
4201 break;
4202 case STRING_PATTERN:
4203 mp = new Module_Param_Pattern(mcopystr(*pattern_string));
4204 break;
4205 default:
4206 break;
4207 }
4208 if (is_ifpresent) {
4209 mp->set_ifpresent();
4210 }
4211 mp->set_length_restriction(get_length_range());
4212 return mp;
970ed795
EL
4213}
4214
4215void UNIVERSAL_CHARSTRING_template::encode_text(Text_Buf& text_buf) const
4216{
4217 encode_text_restricted(text_buf);
4218 switch (template_selection) {
4219 case OMIT_VALUE:
4220 case ANY_VALUE:
4221 case ANY_OR_OMIT:
4222 break;
4223 case SPECIFIC_VALUE:
4224 single_value.encode_text(text_buf);
4225 break;
4226 case VALUE_LIST:
4227 case COMPLEMENTED_LIST:
4228 text_buf.push_int(value_list.n_values);
4229 for (unsigned int i = 0; i < value_list.n_values; i++)
4230 value_list.list_value[i].encode_text(text_buf);
4231 break;
4232 case VALUE_RANGE: {
4233 if (!value_range.min_is_set) TTCN_error("Text encoder: The lower bound is "
4234 "not set in a universal charstring value range template.");
4235 if (!value_range.max_is_set) TTCN_error("Text encoder: The upper bound is "
4236 "not set in a universal charstring value range template.");
4237 unsigned char buf[8];
4238 buf[0] = value_range.min_value.uc_group;
4239 buf[1] = value_range.min_value.uc_plane;
4240 buf[2] = value_range.min_value.uc_row;
4241 buf[3] = value_range.min_value.uc_cell;
4242 buf[4] = value_range.max_value.uc_group;
4243 buf[5] = value_range.max_value.uc_plane;
4244 buf[6] = value_range.max_value.uc_row;
4245 buf[7] = value_range.max_value.uc_cell;
4246 text_buf.push_raw(8, buf);
4247 break; }
4248 default:
4249 TTCN_error("Text encoder: Encoding an uninitialized/unsupported universal "
4250 "charstring template.");
4251 }
4252}
4253
4254void UNIVERSAL_CHARSTRING_template::decode_text(Text_Buf& text_buf)
4255{
4256 clean_up();
4257 decode_text_restricted(text_buf);
4258 switch (template_selection) {
4259 case OMIT_VALUE:
4260 case ANY_VALUE:
4261 case ANY_OR_OMIT:
4262 break;
4263 case SPECIFIC_VALUE:
4264 single_value.decode_text(text_buf);
4265 break;
4266 case VALUE_LIST:
4267 case COMPLEMENTED_LIST:
4268 value_list.n_values = text_buf.pull_int().get_val();
4269 value_list.list_value =
4270 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
4271 for (unsigned int i = 0; i < value_list.n_values; i++)
4272 value_list.list_value[i].decode_text(text_buf);
4273 break;
4274 case VALUE_RANGE: {
4275 unsigned char buf[8];
4276 text_buf.pull_raw(8, buf);
4277 value_range.min_value.uc_group = buf[0];
4278 value_range.min_value.uc_plane = buf[1];
4279 value_range.min_value.uc_row = buf[2];
4280 value_range.min_value.uc_cell = buf[3];
4281 value_range.max_value.uc_group = buf[4];
4282 value_range.max_value.uc_plane = buf[5];
4283 value_range.max_value.uc_row = buf[6];
4284 value_range.max_value.uc_cell = buf[7];
4285 if (value_range.max_value < value_range.min_value)
4286 TTCN_error("Text decoder: The received lower bound is greater than the "
4287 "upper bound in a universal charstring value range template.");
4288 value_range.min_is_set = TRUE;
4289 value_range.max_is_set = TRUE;
4290 break; }
4291 default:
4292 TTCN_error("Text decoder: An unknown/unsupported selection was "
4293 "received for a universal charstring template.");
4294 }
4295}
4296
3abe9331 4297boolean UNIVERSAL_CHARSTRING_template::is_present(boolean legacy /* = FALSE */) const
970ed795
EL
4298{
4299 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 4300 return !match_omit(legacy);
970ed795
EL
4301}
4302
3abe9331 4303boolean UNIVERSAL_CHARSTRING_template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
4304{
4305 if (is_ifpresent) return TRUE;
4306 switch (template_selection) {
4307 case OMIT_VALUE:
4308 case ANY_OR_OMIT:
4309 return TRUE;
4310 case VALUE_LIST:
4311 case COMPLEMENTED_LIST:
3abe9331 4312 if (legacy) {
4313 // legacy behavior: 'omit' can appear in the value/complement list
4314 for (unsigned int i=0; i<value_list.n_values; i++)
4315 if (value_list.list_value[i].match_omit())
4316 return template_selection==VALUE_LIST;
4317 return template_selection==COMPLEMENTED_LIST;
4318 }
4319 // else fall through
970ed795
EL
4320 default:
4321 return FALSE;
4322 }
4323 return FALSE;
4324}
4325
4326#ifndef TITAN_RUNTIME_2
4327void UNIVERSAL_CHARSTRING_template::check_restriction(template_res t_res,
3abe9331 4328 const char* t_name, boolean legacy) const
970ed795
EL
4329{
4330 if (template_selection==UNINITIALIZED_TEMPLATE) return;
4331 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
4332 case TR_VALUE:
4333 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
4334 break;
4335 case TR_OMIT:
4336 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
4337 template_selection==SPECIFIC_VALUE)) return;
4338 break;
4339 case TR_PRESENT:
3abe9331 4340 if (!match_omit(legacy)) return;
970ed795
EL
4341 break;
4342 default:
4343 return;
4344 }
4345 TTCN_error("Restriction `%s' on template of type %s violated.",
4346 get_res_name(t_res), t_name ? t_name : "universal charstring");
4347}
4348#endif
4349
4350const CHARSTRING& UNIVERSAL_CHARSTRING_template::get_single_value() const {
4351 if (!pattern_string)
4352 TTCN_error("Pattern string does not exist in universal charstring template");
4353 return *pattern_string;
4354}
4355
4356/**
4357 * ISO 2022 conversion functions -- these can be overwritten by users
4358 * by defining their own versions. Because these --of course :)-- are
4359 * not really conform to ISO 2022. :o)
4360 */
4361
4362/** TTCN_UCSTR_2_ISO2022: A dummy common implementation. */
4363OCTETSTRING TTCN_UCSTR_2_ISO2022(const UNIVERSAL_CHARSTRING& p_s)
4364{
4365 const universal_char* ucstr=static_cast<const universal_char*>(p_s);
4366 int len=p_s.lengthof();
4367 unsigned char* osstr=(unsigned char*)Malloc(len);
4368 for(int i=0; i<len; i++) osstr[i]=ucstr[i].uc_cell;
4369 OCTETSTRING os(len, osstr);
4370 Free(osstr);
4371 return os;
4372}
4373
4374/** TTCN_ISO2022_2_UCSTR: A dummy common implementation. */
4375UNIVERSAL_CHARSTRING TTCN_ISO2022_2_UCSTR(const OCTETSTRING& p_os)
4376{
4377 const unsigned char* osstr=static_cast<const unsigned char*>(p_os);
4378 int len=p_os.lengthof();
4379 universal_char* ucstr=(universal_char*)Malloc(len*sizeof(*ucstr));
4380 for(int i=0; i<len; i++) {
4381 ucstr[i].uc_group=0;
4382 ucstr[i].uc_plane=0;
4383 ucstr[i].uc_row=0;
4384 ucstr[i].uc_cell=osstr[i];
4385 }
4386 UNIVERSAL_CHARSTRING us(len, ucstr);
4387 Free(ucstr);
4388 return us;
4389}
4390
4391OCTETSTRING TTCN_TeletexString_2_ISO2022(const TeletexString& p_s)
4392{
4393 return TTCN_UCSTR_2_ISO2022(p_s);
4394}
4395
4396TeletexString TTCN_ISO2022_2_TeletexString(const OCTETSTRING& p_os)
4397{
4398 return TTCN_ISO2022_2_UCSTR(p_os);
4399}
4400
4401OCTETSTRING TTCN_VideotexString_2_ISO2022(const VideotexString& p_s)
4402{
4403 return TTCN_UCSTR_2_ISO2022(p_s);
4404}
4405
4406VideotexString TTCN_ISO2022_2_VideotexString(const OCTETSTRING& p_os)
4407{
4408 return TTCN_ISO2022_2_UCSTR(p_os);
4409}
4410
4411OCTETSTRING TTCN_GraphicString_2_ISO2022(const GraphicString& p_s)
4412{
4413 return TTCN_UCSTR_2_ISO2022(p_s);
4414}
4415
4416GraphicString TTCN_ISO2022_2_GraphicString(const OCTETSTRING& p_os)
4417{
4418 return TTCN_ISO2022_2_UCSTR(p_os);
4419}
4420
4421OCTETSTRING TTCN_GeneralString_2_ISO2022(const GeneralString& p_s)
4422{
4423 return TTCN_UCSTR_2_ISO2022(p_s);
4424}
4425
4426GeneralString TTCN_ISO2022_2_GeneralString(const OCTETSTRING& p_os)
4427{
4428 return TTCN_ISO2022_2_UCSTR(p_os);
4429}
This page took 0.227425 seconds and 5 git commands to generate.