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