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