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