Merge pull request #62 from BenceJanosSzabo/master
[deliverable/titan.core.git] / core / Universal_charstring.cc
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 ******************************************************************************/
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
38 #include "TEXT.hh"
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
47 boolean 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
56 boolean 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 */
92 void 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
112 void 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
126 void 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
138 UNIVERSAL_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
145 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING()
146 : val_ptr(NULL), cstr(0), charstring(false)
147 {}
148
149 UNIVERSAL_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
160 UNIVERSAL_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
168 UNIVERSAL_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
176 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const char *chars_ptr)
177 : val_ptr(NULL), cstr(chars_ptr), charstring(true)
178 {
179 }
180
181 UNIVERSAL_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
187 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING(const CHARSTRING& other_value)
188 : val_ptr(NULL), cstr(other_value), charstring(true)
189 {
190 }
191
192 UNIVERSAL_CHARSTRING::UNIVERSAL_CHARSTRING
193 (const CHARSTRING_ELEMENT& other_value)
194 : val_ptr(NULL), cstr(other_value), charstring(true)
195 {
196 }
197
198 UNIVERSAL_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
213 UNIVERSAL_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) {
220 cstr = CHARSTRING((const char)(other_value.get_uchar().uc_cell));
221 val_ptr = NULL;
222 } else {
223 init_struct(1);
224 val_ptr->uchars_ptr[0] = other_value.get_uchar();
225 }
226 }
227
228 UNIVERSAL_CHARSTRING::~UNIVERSAL_CHARSTRING()
229 {
230 clean_up();
231 }
232
233
234 UNIVERSAL_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
250 UNIVERSAL_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
261 UNIVERSAL_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
272 UNIVERSAL_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
283 UNIVERSAL_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
303 UNIVERSAL_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
323 boolean 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
337 boolean 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
358 boolean 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
378 boolean 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
394 boolean 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
413 boolean 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
426 UNIVERSAL_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
457 UNIVERSAL_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
486 UNIVERSAL_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
517 UNIVERSAL_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
543 UNIVERSAL_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
604 UNIVERSAL_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
644 UNIVERSAL_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
666 UNIVERSAL_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
674 UNIVERSAL_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
697 UNIVERSAL_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
706 UNIVERSAL_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
743 UNIVERSAL_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
751 const 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
765 const 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
774 UNIVERSAL_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
783 int 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
792 char* UNIVERSAL_CHARSTRING::convert_to_regexp_form() const {
793 must_bound("Performing pattern conversion operation on an unbound"
794 "universal charstring value.");
795 int size = (charstring ? cstr.val_ptr->n_chars : val_ptr->n_uchars) * 8 + 1;
796 char* res = static_cast<char*>(Malloc(size));
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
814 static 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
820 CHARSTRING UNIVERSAL_CHARSTRING::get_stringRepr_for_pattern() const {
821 must_bound("Performing pattern conversion operation on an unbound"
822 "universal charstring value.");
823 CHARSTRING ret_val("");
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
855 void UNIVERSAL_CHARSTRING::convert_cstr_to_uni() {
856 init_struct(cstr.lengthof());
857 for (int i = 0; i < cstr.val_ptr->n_chars; i++) {
858 val_ptr->uchars_ptr[i].uc_group = 0;
859 val_ptr->uchars_ptr[i].uc_plane = 0;
860 val_ptr->uchars_ptr[i].uc_row = 0;
861 val_ptr->uchars_ptr[i].uc_cell = cstr.val_ptr->chars_ptr[i];
862 }
863 charstring = false;
864 cstr.clean_up();
865 cstr.init_struct(0);
866 }
867
868 void 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
879 void 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
939 UNIVERSAL_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
952 boolean UNIVERSAL_CHARSTRING::set_param_internal(Module_Param& param, boolean allow_pattern) {
953 boolean is_pattern = FALSE;
954 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "universal charstring value");
955 Module_Param_Ptr mp = &param;
956 if (param.get_type() == Module_Param::MP_Reference) {
957 mp = param.get_referenced_param();
958 }
959 switch (mp->get_type()) {
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;
967 buff.put_s(mp->get_string_size(), (unsigned char*)mp->get_string_data());
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
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());
986 } else {
987 *this = UNIVERSAL_CHARSTRING(mp->get_string_size(), (universal_char*)mp->get_string_data());
988 }
989 break;
990 default:
991 TTCN_error("Internal error: UNIVERSAL_CHARSTRING::set_param()");
992 }
993 break; }
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
1017 default:
1018 param.type_error("universal charstring value");
1019 }
1020 return is_pattern;
1021 }
1022
1023 void UNIVERSAL_CHARSTRING::set_param(Module_Param& param) {
1024 set_param_internal(param, FALSE);
1025 }
1026
1027 Module_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);
1038 }
1039
1040 void 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
1056 void 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
1074 void 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);
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);
1099 break;}
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;}
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 }
1118 XER_encode(*p_td.xer,p_buf, XER_coding, 0, 0);
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
1137 void 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);
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);
1170 break;}
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;}
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 }
1198 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
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
1222 ASN_BER_TLV_t*
1223 UNIVERSAL_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 }
1272 int UNIVERSAL_CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
1273 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
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
1359 int UNIVERSAL_CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1360 TTCN_Buffer& buff) const{
1361 int encoded_length=0;
1362 if(p_td.text->begin_encode){
1363 buff.put_cs(*p_td.text->begin_encode);
1364 encoded_length+=p_td.text->begin_encode->lengthof();
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 }
1464
1465 void 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
1530 void 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
1611 void 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
1673 int 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 }
1679
1680 int 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 }
1687 #endif
1688
1689
1690 boolean 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
1755 extern void xml_escape(const unsigned int c, TTCN_Buffer& p_buf);
1756
1757 int UNIVERSAL_CHARSTRING::XER_encode(const XERdescriptor_t& p_td,
1758 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
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 */
1949 inline
1950 static unsigned int
1951 hash (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 */
1992 inline
1993 static char
1994 in_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
2068 universal_char const uspace = {0,0,0,32};
2069
2070 int UNIVERSAL_CHARSTRING::XER_decode(const XERdescriptor_t& p_td,
2071 XmlReaderWrap& reader, unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
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)
2192 fini:
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
2228 char* 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
2274 int 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
2305 int UNIVERSAL_CHARSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td,
2306 TTCN_Buffer& buff, int limit, raw_order_t top_bit_ord, boolean no_err,
2307 int /*sel_field*/, boolean /*first_call*/)
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
2329 boolean 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
2434 int 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
2455 int 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
2495 static void fill_continuing_octets(int n_continuing,
2496 unsigned char *continuing_ptr, int n_octets,
2497 const unsigned char *octets_ptr, int start_pos, int uchar_pos)
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
2530 void UNIVERSAL_CHARSTRING::decode_utf8(int n_octets,
2531 const unsigned char *octets_ptr,
2532 CharCoding::CharCodingType expected_coding /*= UTF8*/,
2533 bool checkBOM /*= false)*/)
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 }
2541 // allocate enough memory, start from clean state
2542 clean_up();
2543 charstring=false;
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
2683 void 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
2772 void 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 }
2837 int 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
2916 UNIVERSAL_CHARSTRING_ELEMENT::UNIVERSAL_CHARSTRING_ELEMENT
2917 (boolean par_bound_flag, UNIVERSAL_CHARSTRING& par_str_val,
2918 int par_uchar_pos) :
2919 bound_flag(par_bound_flag), str_val(par_str_val), uchar_pos(par_uchar_pos)
2920 {
2921
2922 }
2923
2924 UNIVERSAL_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
2940 UNIVERSAL_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
2959 UNIVERSAL_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
2982 UNIVERSAL_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
3000 UNIVERSAL_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.");
3005 int other_value_size = other_value.charstring ? other_value.cstr.val_ptr->n_chars :
3006 other_value.val_ptr->n_uchars;
3007 if (other_value_size != 1)
3008 TTCN_error("Assignment of a universal charstring value with length other "
3009 "than 1 to a universal charstring element.");
3010 bound_flag = TRUE;
3011 *this = other_value[0];
3012 return *this;
3013 }
3014
3015 UNIVERSAL_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
3048 boolean 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
3065 boolean 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
3079 boolean 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
3095 boolean 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
3109 boolean 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
3140 boolean 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
3168 UNIVERSAL_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
3195 UNIVERSAL_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
3221 UNIVERSAL_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
3248 UNIVERSAL_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
3272 UNIVERSAL_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
3318 UNIVERSAL_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
3361 const 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
3369 void 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
3392 boolean 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
3406 boolean 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
3414 UNIVERSAL_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
3447 UNIVERSAL_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
3477 boolean 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
3500 boolean 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
3515 UNIVERSAL_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
3544 UNIVERSAL_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
3572 void 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 }
3580 template_selection = UNINITIALIZED_TEMPLATE;
3581 }
3582
3583 void UNIVERSAL_CHARSTRING_template::copy_template
3584 (const CHARSTRING_template& other_value)
3585 {
3586 switch (other_value.template_selection) {
3587 case SPECIFIC_VALUE:
3588 single_value = other_value.single_value;
3589 break;
3590 case OMIT_VALUE:
3591 case ANY_VALUE:
3592 case ANY_OR_OMIT:
3593 break;
3594 case VALUE_LIST:
3595 case COMPLEMENTED_LIST:
3596 value_list.n_values = other_value.value_list.n_values;
3597 value_list.list_value =
3598 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
3599 for (unsigned int i = 0; i < value_list.n_values; i++)
3600 value_list.list_value[i].copy_template(
3601 other_value.value_list.list_value[i]);
3602 break;
3603 case VALUE_RANGE:
3604 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
3605 "not set when copying a charstring value range template to a universal "
3606 "charstring template.");
3607 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
3608 "not set when copying a charstring value range template to a universal "
3609 "charstring template.");
3610 value_range.min_is_set = TRUE;
3611 value_range.max_is_set = TRUE;
3612 value_range.min_value.uc_group = 0;
3613 value_range.min_value.uc_plane = 0;
3614 value_range.min_value.uc_row = 0;
3615 value_range.min_value.uc_cell = other_value.value_range.min_value;
3616 value_range.max_value.uc_group = 0;
3617 value_range.max_value.uc_plane = 0;
3618 value_range.max_value.uc_row = 0;
3619 value_range.max_value.uc_cell = other_value.value_range.max_value;
3620 break;
3621 case STRING_PATTERN:
3622 pattern_string = new CHARSTRING(other_value.single_value);
3623 pattern_value.regexp_init=FALSE;
3624 break;
3625 default:
3626 TTCN_error("Copying an uninitialized/unsupported charstring template to a "
3627 "universal charstring template.");
3628 }
3629 set_selection(other_value);
3630 }
3631
3632 void UNIVERSAL_CHARSTRING_template::copy_template
3633 (const UNIVERSAL_CHARSTRING_template& other_value)
3634 {
3635 switch (other_value.template_selection) {
3636 case SPECIFIC_VALUE:
3637 single_value = other_value.single_value;
3638 break;
3639 case OMIT_VALUE:
3640 case ANY_VALUE:
3641 case ANY_OR_OMIT:
3642 break;
3643 case VALUE_LIST:
3644 case COMPLEMENTED_LIST:
3645 value_list.n_values = other_value.value_list.n_values;
3646 value_list.list_value =
3647 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
3648 for (unsigned int i = 0; i < value_list.n_values; i++)
3649 value_list.list_value[i].copy_template(
3650 other_value.value_list.list_value[i]);
3651 break;
3652 case VALUE_RANGE:
3653 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
3654 "not set when copying a universal charstring value range template.");
3655 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
3656 "not set when copying a universal charstring value range template.");
3657 value_range = other_value.value_range;
3658 break;
3659 case STRING_PATTERN:
3660 pattern_string = new CHARSTRING(*(other_value.pattern_string));
3661 pattern_value.regexp_init=FALSE;
3662 break;
3663 default:
3664 TTCN_error("Copying an uninitialized/unsupported universal charstring "
3665 "template.");
3666 }
3667 set_selection(other_value);
3668 }
3669
3670 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template()
3671 {
3672 }
3673
3674 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3675 (template_sel other_value) : Restricted_Length_Template(other_value)
3676
3677 {
3678 check_single_selection(other_value);
3679 }
3680
3681 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3682 (const CHARSTRING& other_value) :
3683 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3684 {
3685 }
3686
3687 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3688 (const UNIVERSAL_CHARSTRING& other_value) :
3689 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3690 {
3691 }
3692
3693 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3694 (const CHARSTRING_ELEMENT& other_value) :
3695 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3696 {
3697 }
3698
3699 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3700 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) :
3701 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
3702 {
3703 }
3704
3705 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3706 (const OPTIONAL<CHARSTRING>& other_value)
3707 {
3708 switch (other_value.get_selection()) {
3709 case OPTIONAL_PRESENT:
3710 set_selection(SPECIFIC_VALUE);
3711 single_value = (const CHARSTRING&)other_value;
3712 break;
3713 case OPTIONAL_OMIT:
3714 set_selection(OMIT_VALUE);
3715 break;
3716 default:
3717 TTCN_error("Creating a universal charstring template from an unbound "
3718 "optional field.");
3719 }
3720 }
3721
3722 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3723 (const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value)
3724 {
3725 switch (other_value.get_selection()) {
3726 case OPTIONAL_PRESENT:
3727 set_selection(SPECIFIC_VALUE);
3728 single_value = (const UNIVERSAL_CHARSTRING&)other_value;
3729 break;
3730 case OPTIONAL_OMIT:
3731 set_selection(OMIT_VALUE);
3732 break;
3733 default:
3734 TTCN_error("Creating a universal charstring template from an unbound "
3735 "optional field.");
3736 }
3737 }
3738
3739 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3740 (const CHARSTRING_template& other_value)
3741 : Restricted_Length_Template()
3742 {
3743 copy_template(other_value);
3744 }
3745
3746 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3747 (const UNIVERSAL_CHARSTRING_template& other_value)
3748 : Restricted_Length_Template()
3749 {
3750 copy_template(other_value);
3751 }
3752
3753 UNIVERSAL_CHARSTRING_template::UNIVERSAL_CHARSTRING_template
3754 (template_sel p_sel, const CHARSTRING& p_str)
3755 : Restricted_Length_Template(STRING_PATTERN)
3756 {
3757 if(p_sel!=STRING_PATTERN)
3758 TTCN_error("Internal error: Initializing a universal charstring"
3759 "pattern template with invalid selection.");
3760 pattern_string = new CHARSTRING(p_str);
3761 pattern_value.regexp_init=FALSE;
3762 }
3763
3764 UNIVERSAL_CHARSTRING_template::~UNIVERSAL_CHARSTRING_template()
3765 {
3766 clean_up();
3767 }
3768
3769 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3770 (template_sel other_value)
3771 {
3772 check_single_selection(other_value);
3773 clean_up();
3774 set_selection(other_value);
3775 return *this;
3776 }
3777
3778 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3779 (const CHARSTRING& other_value)
3780 {
3781 other_value.must_bound("Assignment of an unbound charstring value to a "
3782 "universal charstring template.");
3783 clean_up();
3784 set_selection(SPECIFIC_VALUE);
3785 single_value = other_value;
3786 return *this;
3787 }
3788
3789 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3790 (const UNIVERSAL_CHARSTRING& other_value)
3791 {
3792 other_value.must_bound("Assignment of an unbound universal charstring value "
3793 "to a template.");
3794 clean_up();
3795 set_selection(SPECIFIC_VALUE);
3796 single_value = other_value;
3797 return *this;
3798 }
3799
3800 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3801 (const CHARSTRING_ELEMENT& other_value)
3802 {
3803 other_value.must_bound("Assignment of an unbound charstring element to a "
3804 "universal charstring template.");
3805 clean_up();
3806 set_selection(SPECIFIC_VALUE);
3807 single_value = other_value;
3808 return *this;
3809 }
3810
3811 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3812 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
3813 {
3814 other_value.must_bound("Assignment of an unbound universal charstring "
3815 "element to a template.");
3816 clean_up();
3817 set_selection(SPECIFIC_VALUE);
3818 single_value = other_value;
3819 return *this;
3820 }
3821
3822 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3823 (const OPTIONAL<CHARSTRING>& other_value)
3824 {
3825 clean_up();
3826 switch (other_value.get_selection()) {
3827 case OPTIONAL_PRESENT:
3828 set_selection(SPECIFIC_VALUE);
3829 single_value = (const CHARSTRING&)other_value;
3830 break;
3831 case OPTIONAL_OMIT:
3832 set_selection(OMIT_VALUE);
3833 break;
3834 default:
3835 TTCN_error("Assignment of an unbound optional field to a universal "
3836 "charstring template.");
3837 }
3838 return *this;
3839 }
3840
3841 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3842 (const OPTIONAL<UNIVERSAL_CHARSTRING>& other_value)
3843 {
3844 clean_up();
3845 switch (other_value.get_selection()) {
3846 case OPTIONAL_PRESENT:
3847 set_selection(SPECIFIC_VALUE);
3848 single_value = (const UNIVERSAL_CHARSTRING&)other_value;
3849 break;
3850 case OPTIONAL_OMIT:
3851 set_selection(OMIT_VALUE);
3852 break;
3853 default:
3854 TTCN_error("Assignment of an unbound optional field to a universal "
3855 "charstring template.");
3856 }
3857 return *this;
3858 }
3859
3860 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3861 (const CHARSTRING_template& other_value)
3862 {
3863 clean_up();
3864 copy_template(other_value);
3865 return *this;
3866 }
3867
3868 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::operator=
3869 (const UNIVERSAL_CHARSTRING_template& other_value)
3870 {
3871 if (&other_value != this) {
3872 clean_up();
3873 copy_template(other_value);
3874 }
3875 return *this;
3876 }
3877
3878 UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value)
3879 {
3880 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3881 TTCN_error("Accessing a universal charstring element of a non-specific "
3882 "universal charstring template.");
3883 return single_value[index_value];
3884 }
3885
3886 UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](const INTEGER& index_value)
3887 {
3888 index_value.must_bound("Indexing a universal charstring template with an "
3889 "unbound integer value.");
3890 return (*this)[(int)index_value];
3891 }
3892
3893 const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](int index_value) const
3894 {
3895 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3896 TTCN_error("Accessing a universal charstring element of a non-specific "
3897 "universal charstring template.");
3898 return single_value[index_value];
3899 }
3900
3901 const UNIVERSAL_CHARSTRING_ELEMENT UNIVERSAL_CHARSTRING_template::operator[](const INTEGER& index_value) const
3902 {
3903 index_value.must_bound("Indexing a universal charstring template with an "
3904 "unbound integer value.");
3905 return (*this)[(int)index_value];
3906 }
3907
3908 boolean UNIVERSAL_CHARSTRING_template::match
3909 (const UNIVERSAL_CHARSTRING& other_value, boolean /* legacy */) const
3910 {
3911 if (!other_value.is_bound()) return FALSE;
3912 int value_length = other_value.lengthof();
3913 if (!match_length(value_length)) return FALSE;
3914 switch (template_selection) {
3915 case SPECIFIC_VALUE:
3916 return single_value == other_value;
3917 case OMIT_VALUE:
3918 return FALSE;
3919 case ANY_VALUE:
3920 case ANY_OR_OMIT:
3921 return TRUE;
3922 case VALUE_LIST:
3923 case COMPLEMENTED_LIST:
3924 for (unsigned int i = 0; i < value_list.n_values; i++)
3925 if (value_list.list_value[i].match(other_value))
3926 return template_selection == VALUE_LIST;
3927 return template_selection == COMPLEMENTED_LIST;
3928 case VALUE_RANGE: {
3929 if (!value_range.min_is_set) TTCN_error("The lower bound is not set when "
3930 "matching with a universal charstring value range template.");
3931 if (!value_range.max_is_set) TTCN_error("The upper bound is not set when "
3932 "matching with a universal charstring value range template.");
3933 if (value_range.max_value < value_range.min_value)
3934 TTCN_error("The lower bound is greater than the upper bound "
3935 "when matching with a universal charstring value range template.");
3936 const universal_char *uchars_ptr = other_value;
3937 for (int i = 0; i < value_length; i++) {
3938 if (uchars_ptr[i] < value_range.min_value ||
3939 value_range.max_value < uchars_ptr[i]) return FALSE;
3940 }
3941 return TRUE; }
3942 case STRING_PATTERN: {
3943 if (!pattern_value.regexp_init) {
3944 char *posix_str =
3945 TTCN_pattern_to_regexp_uni((const char*)(*pattern_string));
3946 if(posix_str==NULL) {
3947 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
3948 (const char*)(*pattern_string));
3949 }
3950 int ret_val=regcomp(&pattern_value.posix_regexp, posix_str,
3951 REG_EXTENDED|REG_NOSUB);
3952 Free(posix_str);
3953 if(ret_val!=0) {
3954 /* regexp error */
3955 char msg[ERRMSG_BUFSIZE];
3956 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
3957 regfree(&pattern_value.posix_regexp);
3958 TTCN_error("Pattern matching error: %s", msg);
3959 }
3960 pattern_value.regexp_init=TRUE;
3961 }
3962 char* other_value_converted = other_value.convert_to_regexp_form();
3963 int ret_val=regexec(&pattern_value.posix_regexp, other_value_converted, 0,
3964 NULL, 0);
3965 Free(other_value_converted);
3966 switch (ret_val) {
3967 case 0:
3968 return TRUE;
3969 case REG_NOMATCH:
3970 return FALSE;
3971 default:
3972 /* regexp error */
3973 char msg[ERRMSG_BUFSIZE];
3974 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
3975 TTCN_error("Pattern matching error: %s", msg);
3976 }
3977 break;}
3978 default:
3979 TTCN_error("Matching with an uninitialized/unsupported universal "
3980 "charstring template.");
3981 }
3982 return FALSE;
3983 }
3984
3985 const UNIVERSAL_CHARSTRING& UNIVERSAL_CHARSTRING_template::valueof() const
3986 {
3987 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
3988 TTCN_error("Performing valueof or send operation on a non-specific "
3989 "universal charstring template.");
3990 return single_value;
3991 }
3992
3993 int UNIVERSAL_CHARSTRING_template::lengthof() const
3994 {
3995 int min_length;
3996 boolean has_any_or_none;
3997 if (is_ifpresent)
3998 TTCN_error("Performing lengthof() operation on a universal charstring "
3999 "template which has an ifpresent attribute.");
4000 switch (template_selection)
4001 {
4002 case SPECIFIC_VALUE:
4003 min_length = single_value.lengthof();
4004 has_any_or_none = FALSE;
4005 break;
4006 case OMIT_VALUE:
4007 TTCN_error("Performing lengthof() operation on a universal charstring "
4008 "template containing omit value.");
4009 case ANY_VALUE:
4010 case ANY_OR_OMIT:
4011 case VALUE_RANGE:
4012 min_length = 0;
4013 has_any_or_none = TRUE; // max. length is infinity
4014 break;
4015 case VALUE_LIST:
4016 {
4017 // error if any element does not have length or the lengths differ
4018 if (value_list.n_values<1)
4019 TTCN_error("Internal error: "
4020 "Performing lengthof() operation on a universal charstring "
4021 "template containing an empty list.");
4022 int item_length = value_list.list_value[0].lengthof();
4023 for (unsigned int i = 1; i < value_list.n_values; i++) {
4024 if (value_list.list_value[i].lengthof()!=item_length)
4025 TTCN_error("Performing lengthof() operation on a universal charstring "
4026 "template containing a value list with different lengths.");
4027 }
4028 min_length = item_length;
4029 has_any_or_none = FALSE;
4030 break;
4031 }
4032 case COMPLEMENTED_LIST:
4033 TTCN_error("Performing lengthof() operation on a universal charstring "
4034 "template containing complemented list.");
4035 case STRING_PATTERN:
4036 TTCN_error("Performing lengthof() operation on a universal charstring "
4037 "template containing a pattern is not allowed.");
4038 default:
4039 TTCN_error("Performing lengthof() operation on an "
4040 "uninitialized/unsupported universal charstring template.");
4041 }
4042 return check_section_is_single(min_length, has_any_or_none,
4043 "length", "a", "universal charstring template");
4044 }
4045
4046 void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type,
4047 unsigned int list_length)
4048 {
4049 clean_up();
4050 switch (template_type) {
4051 case VALUE_LIST:
4052 case COMPLEMENTED_LIST:
4053 set_selection(template_type);
4054 value_list.n_values = list_length;
4055 value_list.list_value = new UNIVERSAL_CHARSTRING_template[list_length];
4056 break;
4057 case VALUE_RANGE:
4058 set_selection(VALUE_RANGE);
4059 value_range.min_is_set = FALSE;
4060 value_range.max_is_set = FALSE;
4061 break;
4062 default:
4063 TTCN_error("Setting an invalid type for a universal charstring template.");
4064 }
4065 }
4066
4067 UNIVERSAL_CHARSTRING_template& UNIVERSAL_CHARSTRING_template::list_item
4068 (unsigned int list_index)
4069 {
4070 if (template_selection != VALUE_LIST &&
4071 template_selection != COMPLEMENTED_LIST)
4072 TTCN_error("Accessing a list element of a non-list universal charstring "
4073 "template.");
4074 if (list_index >= value_list.n_values)
4075 TTCN_error("Index overflow in a universal charstring value list template.");
4076 return value_list.list_value[list_index];
4077 }
4078
4079 void UNIVERSAL_CHARSTRING_template::set_min
4080 (const UNIVERSAL_CHARSTRING& min_value)
4081 {
4082 if (template_selection != VALUE_RANGE) TTCN_error("Setting the lower bound "
4083 "for a non-range universal charstring template.");
4084 min_value.must_bound("Setting an unbound value as lower bound in a "
4085 "universal charstring value range template.");
4086 int length = min_value.lengthof();
4087 if (length != 1) TTCN_error("The length of the lower bound in a universal "
4088 "charstring value range template must be 1 instead of %d.", length);
4089 value_range.min_is_set = TRUE;
4090 value_range.min_value = *(const universal_char*)min_value;
4091 if (value_range.max_is_set && value_range.max_value < value_range.min_value)
4092 TTCN_error("The lower bound in a universal charstring value range template "
4093 "is greater than the upper bound.");
4094 }
4095
4096 void UNIVERSAL_CHARSTRING_template::set_max
4097 (const UNIVERSAL_CHARSTRING& max_value)
4098 {
4099 if (template_selection != VALUE_RANGE) TTCN_error("Setting the upper bound "
4100 "for a non-range universal charstring template.");
4101 max_value.must_bound("Setting an unbound value as upper bound in a "
4102 "universal charstring value range template.");
4103 int length = max_value.lengthof();
4104 if (length != 1) TTCN_error("The length of the upper bound in a universal "
4105 "charstring value range template must be 1 instead of %d.", length);
4106 value_range.max_is_set = TRUE;
4107 value_range.max_value = *(const universal_char*)max_value;
4108 if (value_range.min_is_set && value_range.max_value < value_range.min_value)
4109 TTCN_error("The upper bound in a universal charstring value range template "
4110 "is smaller than the lower bound.");
4111 }
4112
4113 void UNIVERSAL_CHARSTRING_template::log() const
4114 {
4115 switch (template_selection) {
4116 case STRING_PATTERN:
4117 CHARSTRING_template::log_pattern(pattern_string->lengthof(),
4118 (const char*)*pattern_string);
4119 break;
4120 case SPECIFIC_VALUE:
4121 single_value.log();
4122 break;
4123 case COMPLEMENTED_LIST:
4124 TTCN_Logger::log_event_str("complement ");
4125 // no break
4126 case VALUE_LIST:
4127 TTCN_Logger::log_char('(');
4128 for(unsigned int i = 0; i < value_list.n_values; i++) {
4129 if (i > 0) TTCN_Logger::log_event_str(", ");
4130 value_list.list_value[i].log();
4131 }
4132 TTCN_Logger::log_char(')');
4133 break;
4134 case VALUE_RANGE:
4135 TTCN_Logger::log_char('(');
4136 if (value_range.min_is_set) {
4137 if (is_printable(value_range.min_value)) {
4138 TTCN_Logger::log_char('"');
4139 TTCN_Logger::log_char_escaped(value_range.min_value.uc_cell);
4140 TTCN_Logger::log_char('"');
4141 } else {
4142 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4143 value_range.min_value.uc_group, value_range.min_value.uc_plane,
4144 value_range.min_value.uc_row, value_range.min_value.uc_cell);
4145 }
4146 } else TTCN_Logger::log_event_str("<unknown lower bound>");
4147 TTCN_Logger::log_event_str(" .. ");
4148 if (value_range.max_is_set) {
4149 if (is_printable(value_range.max_value)) {
4150 TTCN_Logger::log_char('"');
4151 TTCN_Logger::log_char_escaped(value_range.max_value.uc_cell);
4152 TTCN_Logger::log_char('"');
4153 } else {
4154 TTCN_Logger::log_event("char(%u, %u, %u, %u)",
4155 value_range.max_value.uc_group, value_range.max_value.uc_plane,
4156 value_range.max_value.uc_row, value_range.max_value.uc_cell);
4157 }
4158 } else TTCN_Logger::log_event_str("<unknown upper bound>");
4159 TTCN_Logger::log_char(')');
4160 break;
4161 default:
4162 log_generic();
4163 break;
4164 }
4165 log_restricted();
4166 log_ifpresent();
4167 }
4168
4169 void UNIVERSAL_CHARSTRING_template::log_match
4170 (const UNIVERSAL_CHARSTRING& match_value, boolean /* legacy */) const
4171 {
4172 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
4173 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
4174 TTCN_Logger::print_logmatch_buffer();
4175 TTCN_Logger::log_event_str(" := ");
4176 }
4177 match_value.log();
4178 TTCN_Logger::log_event_str(" with ");
4179 log();
4180 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
4181 else TTCN_Logger::log_event_str(" unmatched");
4182 }
4183
4184 void UNIVERSAL_CHARSTRING_template::set_param(Module_Param& param) {
4185 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "universal charstring template");
4186 Module_Param_Ptr mp = &param;
4187 if (param.get_type() == Module_Param::MP_Reference) {
4188 mp = param.get_referenced_param();
4189 }
4190 switch (mp->get_type()) {
4191 case Module_Param::MP_Omit:
4192 *this = OMIT_VALUE;
4193 break;
4194 case Module_Param::MP_Any:
4195 *this = ANY_VALUE;
4196 break;
4197 case Module_Param::MP_AnyOrNone:
4198 *this = ANY_OR_OMIT;
4199 break;
4200 case Module_Param::MP_List_Template:
4201 case Module_Param::MP_ComplementList_Template: {
4202 UNIVERSAL_CHARSTRING_template temp;
4203 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
4204 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
4205 for (size_t i=0; i<mp->get_size(); i++) {
4206 temp.list_item(i).set_param(*mp->get_elem(i));
4207 }
4208 *this = temp;
4209 break; }
4210 case Module_Param::MP_Charstring: {
4211 TTCN_Buffer buff;
4212 buff.put_s(mp->get_string_size(), (unsigned char*)mp->get_string_data());
4213 *this = UNIVERSAL_CHARSTRING::from_UTF8_buffer(buff);
4214 break; }
4215 case Module_Param::MP_Universal_Charstring:
4216 *this = UNIVERSAL_CHARSTRING(mp->get_string_size(), (universal_char*)mp->get_string_data());
4217 break;
4218 case Module_Param::MP_StringRange: {
4219 universal_char lower_uchar = mp->get_lower_uchar();
4220 universal_char upper_uchar = mp->get_upper_uchar();
4221 clean_up();
4222 set_selection(VALUE_RANGE);
4223 value_range.min_is_set = TRUE;
4224 value_range.max_is_set = TRUE;
4225 value_range.min_value = lower_uchar;
4226 value_range.max_value = upper_uchar;
4227 } break;
4228 case Module_Param::MP_Pattern:
4229 clean_up();
4230 pattern_string = new CHARSTRING(mp->get_pattern());
4231 pattern_value.regexp_init = FALSE;
4232 set_selection(STRING_PATTERN);
4233 break;
4234 case Module_Param::MP_Expression:
4235 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
4236 UNIVERSAL_CHARSTRING operand1, operand2, result;
4237 boolean is_pattern = operand1.set_param_internal(*mp->get_operand1(), TRUE);
4238 operand2.set_param(*mp->get_operand2());
4239 result = operand1 + operand2;
4240 if (is_pattern) {
4241 clean_up();
4242 if (result.charstring) {
4243 pattern_string = new CHARSTRING(result.cstr);
4244 }
4245 else {
4246 pattern_string = new CHARSTRING(result.get_stringRepr_for_pattern());
4247 }
4248 pattern_value.regexp_init = FALSE;
4249 set_selection(STRING_PATTERN);
4250 }
4251 else {
4252 *this = result;
4253 }
4254 }
4255 else {
4256 param.expr_type_error("a charstring");
4257 }
4258 break;
4259 default:
4260 param.type_error("universal charstring template");
4261 }
4262 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
4263 if (param.get_length_restriction() != NULL) {
4264 set_length_range(param);
4265 }
4266 else {
4267 set_length_range(*mp);
4268 }
4269 }
4270
4271 Module_Param* UNIVERSAL_CHARSTRING_template::get_param(Module_Param_Name& param_name) const
4272 {
4273 Module_Param* mp = NULL;
4274 switch (template_selection) {
4275 case UNINITIALIZED_TEMPLATE:
4276 mp = new Module_Param_Unbound();
4277 break;
4278 case OMIT_VALUE:
4279 mp = new Module_Param_Omit();
4280 break;
4281 case ANY_VALUE:
4282 mp = new Module_Param_Any();
4283 break;
4284 case ANY_OR_OMIT:
4285 mp = new Module_Param_AnyOrNone();
4286 break;
4287 case SPECIFIC_VALUE:
4288 mp = single_value.get_param(param_name);
4289 break;
4290 case VALUE_LIST:
4291 case COMPLEMENTED_LIST: {
4292 if (template_selection == VALUE_LIST) {
4293 mp = new Module_Param_List_Template();
4294 }
4295 else {
4296 mp = new Module_Param_ComplementList_Template();
4297 }
4298 for (size_t i = 0; i < value_list.n_values; ++i) {
4299 mp->add_elem(value_list.list_value[i].get_param(param_name));
4300 }
4301 break; }
4302 case VALUE_RANGE:
4303 mp = new Module_Param_StringRange(value_range.min_value, value_range.max_value);
4304 break;
4305 case STRING_PATTERN:
4306 mp = new Module_Param_Pattern(mcopystr(*pattern_string));
4307 break;
4308 default:
4309 break;
4310 }
4311 if (is_ifpresent) {
4312 mp->set_ifpresent();
4313 }
4314 mp->set_length_restriction(get_length_range());
4315 return mp;
4316 }
4317
4318 void UNIVERSAL_CHARSTRING_template::encode_text(Text_Buf& text_buf) const
4319 {
4320 encode_text_restricted(text_buf);
4321 switch (template_selection) {
4322 case OMIT_VALUE:
4323 case ANY_VALUE:
4324 case ANY_OR_OMIT:
4325 break;
4326 case SPECIFIC_VALUE:
4327 single_value.encode_text(text_buf);
4328 break;
4329 case VALUE_LIST:
4330 case COMPLEMENTED_LIST:
4331 text_buf.push_int(value_list.n_values);
4332 for (unsigned int i = 0; i < value_list.n_values; i++)
4333 value_list.list_value[i].encode_text(text_buf);
4334 break;
4335 case VALUE_RANGE: {
4336 if (!value_range.min_is_set) TTCN_error("Text encoder: The lower bound is "
4337 "not set in a universal charstring value range template.");
4338 if (!value_range.max_is_set) TTCN_error("Text encoder: The upper bound is "
4339 "not set in a universal charstring value range template.");
4340 unsigned char buf[8];
4341 buf[0] = value_range.min_value.uc_group;
4342 buf[1] = value_range.min_value.uc_plane;
4343 buf[2] = value_range.min_value.uc_row;
4344 buf[3] = value_range.min_value.uc_cell;
4345 buf[4] = value_range.max_value.uc_group;
4346 buf[5] = value_range.max_value.uc_plane;
4347 buf[6] = value_range.max_value.uc_row;
4348 buf[7] = value_range.max_value.uc_cell;
4349 text_buf.push_raw(8, buf);
4350 break; }
4351 default:
4352 TTCN_error("Text encoder: Encoding an uninitialized/unsupported universal "
4353 "charstring template.");
4354 }
4355 }
4356
4357 void UNIVERSAL_CHARSTRING_template::decode_text(Text_Buf& text_buf)
4358 {
4359 clean_up();
4360 decode_text_restricted(text_buf);
4361 switch (template_selection) {
4362 case OMIT_VALUE:
4363 case ANY_VALUE:
4364 case ANY_OR_OMIT:
4365 break;
4366 case SPECIFIC_VALUE:
4367 single_value.decode_text(text_buf);
4368 break;
4369 case VALUE_LIST:
4370 case COMPLEMENTED_LIST:
4371 value_list.n_values = text_buf.pull_int().get_val();
4372 value_list.list_value =
4373 new UNIVERSAL_CHARSTRING_template[value_list.n_values];
4374 for (unsigned int i = 0; i < value_list.n_values; i++)
4375 value_list.list_value[i].decode_text(text_buf);
4376 break;
4377 case VALUE_RANGE: {
4378 unsigned char buf[8];
4379 text_buf.pull_raw(8, buf);
4380 value_range.min_value.uc_group = buf[0];
4381 value_range.min_value.uc_plane = buf[1];
4382 value_range.min_value.uc_row = buf[2];
4383 value_range.min_value.uc_cell = buf[3];
4384 value_range.max_value.uc_group = buf[4];
4385 value_range.max_value.uc_plane = buf[5];
4386 value_range.max_value.uc_row = buf[6];
4387 value_range.max_value.uc_cell = buf[7];
4388 if (value_range.max_value < value_range.min_value)
4389 TTCN_error("Text decoder: The received lower bound is greater than the "
4390 "upper bound in a universal charstring value range template.");
4391 value_range.min_is_set = TRUE;
4392 value_range.max_is_set = TRUE;
4393 break; }
4394 default:
4395 TTCN_error("Text decoder: An unknown/unsupported selection was "
4396 "received for a universal charstring template.");
4397 }
4398 }
4399
4400 boolean UNIVERSAL_CHARSTRING_template::is_present(boolean legacy /* = FALSE */) const
4401 {
4402 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
4403 return !match_omit(legacy);
4404 }
4405
4406 boolean UNIVERSAL_CHARSTRING_template::match_omit(boolean legacy /* = FALSE */) const
4407 {
4408 if (is_ifpresent) return TRUE;
4409 switch (template_selection) {
4410 case OMIT_VALUE:
4411 case ANY_OR_OMIT:
4412 return TRUE;
4413 case VALUE_LIST:
4414 case COMPLEMENTED_LIST:
4415 if (legacy) {
4416 // legacy behavior: 'omit' can appear in the value/complement list
4417 for (unsigned int i=0; i<value_list.n_values; i++)
4418 if (value_list.list_value[i].match_omit())
4419 return template_selection==VALUE_LIST;
4420 return template_selection==COMPLEMENTED_LIST;
4421 }
4422 // else fall through
4423 default:
4424 return FALSE;
4425 }
4426 return FALSE;
4427 }
4428
4429 #ifndef TITAN_RUNTIME_2
4430 void UNIVERSAL_CHARSTRING_template::check_restriction(template_res t_res,
4431 const char* t_name, boolean legacy) const
4432 {
4433 if (template_selection==UNINITIALIZED_TEMPLATE) return;
4434 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
4435 case TR_VALUE:
4436 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
4437 break;
4438 case TR_OMIT:
4439 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
4440 template_selection==SPECIFIC_VALUE)) return;
4441 break;
4442 case TR_PRESENT:
4443 if (!match_omit(legacy)) return;
4444 break;
4445 default:
4446 return;
4447 }
4448 TTCN_error("Restriction `%s' on template of type %s violated.",
4449 get_res_name(t_res), t_name ? t_name : "universal charstring");
4450 }
4451 #endif
4452
4453 const CHARSTRING& UNIVERSAL_CHARSTRING_template::get_single_value() const {
4454 if (!pattern_string)
4455 TTCN_error("Pattern string does not exist in universal charstring template");
4456 return *pattern_string;
4457 }
4458
4459 /**
4460 * ISO 2022 conversion functions -- these can be overwritten by users
4461 * by defining their own versions. Because these --of course :)-- are
4462 * not really conform to ISO 2022. :o)
4463 */
4464
4465 /** TTCN_UCSTR_2_ISO2022: A dummy common implementation. */
4466 OCTETSTRING TTCN_UCSTR_2_ISO2022(const UNIVERSAL_CHARSTRING& p_s)
4467 {
4468 const universal_char* ucstr=static_cast<const universal_char*>(p_s);
4469 int len=p_s.lengthof();
4470 unsigned char* osstr=(unsigned char*)Malloc(len);
4471 for(int i=0; i<len; i++) osstr[i]=ucstr[i].uc_cell;
4472 OCTETSTRING os(len, osstr);
4473 Free(osstr);
4474 return os;
4475 }
4476
4477 /** TTCN_ISO2022_2_UCSTR: A dummy common implementation. */
4478 UNIVERSAL_CHARSTRING TTCN_ISO2022_2_UCSTR(const OCTETSTRING& p_os)
4479 {
4480 const unsigned char* osstr=static_cast<const unsigned char*>(p_os);
4481 int len=p_os.lengthof();
4482 universal_char* ucstr=(universal_char*)Malloc(len*sizeof(*ucstr));
4483 for(int i=0; i<len; i++) {
4484 ucstr[i].uc_group=0;
4485 ucstr[i].uc_plane=0;
4486 ucstr[i].uc_row=0;
4487 ucstr[i].uc_cell=osstr[i];
4488 }
4489 UNIVERSAL_CHARSTRING us(len, ucstr);
4490 Free(ucstr);
4491 return us;
4492 }
4493
4494 OCTETSTRING TTCN_TeletexString_2_ISO2022(const TeletexString& p_s)
4495 {
4496 return TTCN_UCSTR_2_ISO2022(p_s);
4497 }
4498
4499 TeletexString TTCN_ISO2022_2_TeletexString(const OCTETSTRING& p_os)
4500 {
4501 return TTCN_ISO2022_2_UCSTR(p_os);
4502 }
4503
4504 OCTETSTRING TTCN_VideotexString_2_ISO2022(const VideotexString& p_s)
4505 {
4506 return TTCN_UCSTR_2_ISO2022(p_s);
4507 }
4508
4509 VideotexString TTCN_ISO2022_2_VideotexString(const OCTETSTRING& p_os)
4510 {
4511 return TTCN_ISO2022_2_UCSTR(p_os);
4512 }
4513
4514 OCTETSTRING TTCN_GraphicString_2_ISO2022(const GraphicString& p_s)
4515 {
4516 return TTCN_UCSTR_2_ISO2022(p_s);
4517 }
4518
4519 GraphicString TTCN_ISO2022_2_GraphicString(const OCTETSTRING& p_os)
4520 {
4521 return TTCN_ISO2022_2_UCSTR(p_os);
4522 }
4523
4524 OCTETSTRING TTCN_GeneralString_2_ISO2022(const GeneralString& p_s)
4525 {
4526 return TTCN_UCSTR_2_ISO2022(p_s);
4527 }
4528
4529 GeneralString TTCN_ISO2022_2_GeneralString(const OCTETSTRING& p_os)
4530 {
4531 return TTCN_ISO2022_2_UCSTR(p_os);
4532 }
This page took 0.137463 seconds and 5 git commands to generate.