Sync with 5.4.3
[deliverable/titan.core.git] / core / Charstring.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 "Charstring.hh"
9 #include "../common/memory.h"
10 #include "../common/pattern.hh"
11 #include "Integer.hh"
12 #include "Octetstring.hh"
13 #include "String_struct.hh"
14 #include "Parameters.h"
15 #include "Param_Types.hh"
16 #include "Error.hh"
17 #include "Logger.hh"
18 #include "Encdec.hh"
19 #include "RAW.hh"
20 #include "BER.hh"
21 #include "TEXT.hh"
22 #include "XER.hh"
23 #include "JSON.hh"
24 #include "Addfunc.hh"
25
26 #include "../common/dbgnew.hh"
27
28 #include <string.h>
29 #include <ctype.h>
30 #include <limits.h>
31
32 #define ERRMSG_BUFSIZE 500
33
34 /** The amount of memory needed for a string containing n characters.
35 * -sizeof(int) because that much is already in charstring_struct.
36 * +1 for the terminating null character. */
37 #define MEMORY_SIZE(n) (sizeof(charstring_struct) - sizeof(int) + 1 + (n))
38
39 /** Allocate the memory needed to hold n_chars characters.
40 *
41 * @param \p n_chars the number of characters to hold
42 * @pre \p n_chars must be >= 0
43 */
44 void CHARSTRING::init_struct(int n_chars)
45 {
46 if (n_chars < 0) {
47 val_ptr = NULL;
48 TTCN_error("Initializing a charstring with a negative length.");
49 } else if (n_chars == 0) {
50 /** This will represent the empty strings so they won't need allocated
51 * memory, this delays the memory allocation until it is really needed.
52 */
53 static charstring_struct empty_string = { 1, 0, "" };
54 val_ptr = &empty_string;
55 empty_string.ref_count++;
56 } else {
57 val_ptr = (charstring_struct*)Malloc(MEMORY_SIZE(n_chars));
58 val_ptr->ref_count = 1;
59 val_ptr->n_chars = n_chars;
60 val_ptr->chars_ptr[n_chars] = '\0';
61 }
62 }
63
64 /** Implement the copy-on-write.
65 *
66 * Called from the various CHARSTRING_ELEMENT::operator=(), just before
67 * the string is about to be modified. Stops the sharing of the CHARSTRING
68 * and creates a new copy for modification.
69 */
70 void CHARSTRING::copy_value()
71 {
72 if (val_ptr == NULL || val_ptr->n_chars <= 0)
73 TTCN_error("Internal error: Invalid internal data structure when copying "
74 "the memory area of a charstring value.");
75 if (val_ptr->ref_count > 1) {
76 charstring_struct *old_ptr = val_ptr;
77 old_ptr->ref_count--;
78 init_struct(old_ptr->n_chars);
79 memcpy(val_ptr->chars_ptr, old_ptr->chars_ptr, old_ptr->n_chars + 1);
80 }
81 }
82
83 /** Create an uninitialized CHARSTRING object.
84 *
85 * Called from CHARSTRING::operator+() to create the return value with
86 * enough storage to hold the concatenation of the arguments.
87 *
88 * @param n_chars the number of characters to hold
89 *
90 */
91 CHARSTRING::CHARSTRING(int n_chars)
92 {
93 init_struct(n_chars);
94 }
95
96 CHARSTRING::CHARSTRING()
97 {
98 val_ptr = NULL;
99 }
100
101 CHARSTRING::CHARSTRING(char other_value)
102 {
103 init_struct(1);
104 val_ptr->chars_ptr[0] = other_value;
105 }
106
107 CHARSTRING::CHARSTRING(const char *chars_ptr)
108 {
109 int n_chars;
110 if (chars_ptr != NULL) n_chars = strlen(chars_ptr);
111 else n_chars = 0;
112 init_struct(n_chars);
113 memcpy(val_ptr->chars_ptr, chars_ptr, n_chars);
114 }
115
116 CHARSTRING::CHARSTRING(int n_chars, const char *chars_ptr)
117 {
118 init_struct(n_chars);
119 memcpy(val_ptr->chars_ptr, chars_ptr, n_chars);
120 }
121
122 CHARSTRING::CHARSTRING(const CHARSTRING& other_value)
123 : Base_Type(other_value), val_ptr(other_value.val_ptr)
124 {
125 other_value.must_bound("Copying an unbound charstring value.");
126 // ref_count can only be incremented after we check val_ptr
127 val_ptr->ref_count++;
128 }
129
130 CHARSTRING::CHARSTRING(const CHARSTRING_ELEMENT& other_value)
131 {
132 other_value.must_bound("Initialization of a charstring with an unbound "
133 "charstring element.");
134 init_struct(1);
135 val_ptr->chars_ptr[0] = other_value.get_char();
136 }
137
138 CHARSTRING::~CHARSTRING()
139 {
140 clean_up();
141 }
142
143 void CHARSTRING::clean_up()
144 {
145 if (val_ptr != NULL) {
146 if (val_ptr->ref_count > 1) val_ptr->ref_count--;
147 else if (val_ptr->ref_count == 1) Free(val_ptr);
148 else TTCN_error("Internal error: Invalid reference counter in a charstring "
149 "value.");
150 val_ptr = NULL;
151 }
152 }
153
154 CHARSTRING& CHARSTRING::operator=(const char* other_value)
155 {
156 if (val_ptr == NULL || val_ptr->chars_ptr != other_value) {
157 clean_up();
158 int n_chars;
159 if (other_value != NULL) n_chars = strlen(other_value);
160 else n_chars = 0;
161 init_struct(n_chars);
162 memcpy(val_ptr->chars_ptr, other_value, n_chars);
163 }
164 return *this;
165 }
166
167 CHARSTRING& CHARSTRING::operator=(const CHARSTRING& other_value)
168 {
169 other_value.must_bound("Assignment of an unbound charstring value.");
170 if (&other_value != this) {
171 clean_up();
172 val_ptr = other_value.val_ptr;
173 val_ptr->ref_count++;
174 }
175 return *this;
176 }
177
178 CHARSTRING& CHARSTRING::operator=(const CHARSTRING_ELEMENT& other_value)
179 {
180 other_value.must_bound("Assignment of an unbound charstring element to "
181 "a charstring.");
182 char char_value = other_value.get_char();
183 clean_up();
184 init_struct(1);
185 val_ptr->chars_ptr[0] = char_value;
186 return *this;
187 }
188
189 CHARSTRING& CHARSTRING::operator=(const UNIVERSAL_CHARSTRING& other_value)
190 {
191 other_value.must_bound("Assignment of an unbound universal charstring to "
192 "a charstring.");
193 clean_up();
194 int n_chars = other_value.val_ptr->n_uchars;
195 init_struct(n_chars);
196 for (int i = 0; i < n_chars; ++i) {
197 const universal_char& uc = other_value.val_ptr->uchars_ptr[i];
198 if (uc.uc_group != 0 || uc.uc_plane != 0 || uc.uc_row != 0) {
199 TTCN_error("Multiple-byte characters cannot be assigned to a charstring, "
200 "invalid character char(%u, %u, %u, %u) at index %d.",
201 uc.uc_group, uc.uc_plane, uc.uc_row, uc.uc_cell, i);
202 }
203 val_ptr->chars_ptr[i] = other_value.val_ptr->uchars_ptr[i].uc_cell;
204 }
205 return *this;
206 }
207
208 boolean CHARSTRING::operator==(const char* other_value) const
209 {
210 must_bound("Unbound operand of charstring comparison.");
211 if (other_value == NULL) other_value = "";
212 return !strcmp(val_ptr->chars_ptr, other_value);
213 }
214
215 boolean CHARSTRING::operator==(const CHARSTRING& other_value) const
216 {
217 must_bound("Unbound operand of charstring comparison.");
218 other_value.must_bound("Unbound operand of charstring comparison.");
219 if (val_ptr->n_chars != other_value.val_ptr->n_chars) return FALSE;
220 else return !memcmp(val_ptr->chars_ptr, other_value.val_ptr->chars_ptr,
221 val_ptr->n_chars);
222 }
223
224 boolean CHARSTRING::operator==(const CHARSTRING_ELEMENT& other_value) const
225 {
226 other_value.must_bound("Unbound operand of charstring element "
227 "comparison.");
228 must_bound("Unbound operand of charstring comparison.");
229 if (val_ptr->n_chars != 1) return FALSE;
230 else return val_ptr->chars_ptr[0] == other_value.get_char();
231 }
232
233 boolean CHARSTRING::operator==(const UNIVERSAL_CHARSTRING& other_value) const
234 {
235 must_bound("The left operand of comparison is an unbound charstring value.");
236 other_value.must_bound("The right operand of comparison is an unbound "
237 "universal charstring value.");
238 if (other_value.charstring)
239 return *this == other_value.cstr;
240 if (val_ptr->n_chars != other_value.val_ptr->n_uchars) return FALSE;
241 for (int i = 0; i < val_ptr->n_chars; i++) {
242 if (other_value.val_ptr->uchars_ptr[i].uc_group != 0 ||
243 other_value.val_ptr->uchars_ptr[i].uc_plane != 0 ||
244 other_value.val_ptr->uchars_ptr[i].uc_row != 0 ||
245 other_value.val_ptr->uchars_ptr[i].uc_cell != (cbyte)val_ptr->chars_ptr[i])
246 return FALSE;
247 }
248 return TRUE;
249 }
250
251 boolean CHARSTRING::operator==(const UNIVERSAL_CHARSTRING_ELEMENT& other_value)
252 const
253 {
254 must_bound("The left operand of comparison is an unbound charstring value.");
255 other_value.must_bound("The right operand of comparison is an unbound "
256 "universal charstring element.");
257 if (val_ptr->n_chars != 1) return FALSE;
258 const universal_char& uchar = other_value.get_uchar();
259 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
260 uchar.uc_cell == (cbyte)val_ptr->chars_ptr[0];
261 }
262
263 CHARSTRING CHARSTRING::operator+(const char* other_value) const
264 {
265 must_bound("Unbound operand of charstring concatenation.");
266 int other_len;
267 if (other_value == NULL) other_len = 0;
268 else other_len = strlen(other_value);
269 if (other_len == 0) return *this;
270 CHARSTRING ret_val(val_ptr->n_chars + other_len);
271 memcpy(ret_val.val_ptr->chars_ptr, val_ptr->chars_ptr, val_ptr->n_chars);
272 memcpy(ret_val.val_ptr->chars_ptr + val_ptr->n_chars, other_value, other_len);
273 return ret_val;
274 }
275
276 CHARSTRING CHARSTRING::operator+(const CHARSTRING& other_value) const
277 {
278 must_bound("Unbound operand of charstring concatenation.");
279 other_value.must_bound("Unbound operand of charstring concatenation.");
280 int first_n_chars = val_ptr->n_chars;
281 if (first_n_chars == 0) return other_value;
282 int second_n_chars = other_value.val_ptr->n_chars;
283 if (second_n_chars == 0) return *this;
284 CHARSTRING ret_val(first_n_chars + second_n_chars);
285 memcpy(ret_val.val_ptr->chars_ptr, val_ptr->chars_ptr, first_n_chars);
286 memcpy(ret_val.val_ptr->chars_ptr + first_n_chars,
287 other_value.val_ptr->chars_ptr, second_n_chars);
288 return ret_val;
289 }
290
291 CHARSTRING CHARSTRING::operator+(const CHARSTRING_ELEMENT& other_value) const
292 {
293 must_bound("Unbound operand of charstring concatenation.");
294 other_value.must_bound("Unbound operand of charstring element "
295 "concatenation.");
296 CHARSTRING ret_val(val_ptr->n_chars + 1);
297 memcpy(ret_val.val_ptr->chars_ptr, val_ptr->chars_ptr, val_ptr->n_chars);
298 ret_val.val_ptr->chars_ptr[val_ptr->n_chars] = other_value.get_char();
299 return ret_val;
300 }
301
302 UNIVERSAL_CHARSTRING CHARSTRING::operator+
303 (const UNIVERSAL_CHARSTRING& other_value) const
304 {
305 must_bound("The left operand of concatenation is an unbound charstring "
306 "value.");
307 other_value.must_bound("The right operand of concatenation is an unbound "
308 "universal charstring value.");
309 if (val_ptr->n_chars == 0) return other_value;
310 if (other_value.charstring) {
311 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_chars + other_value.cstr.val_ptr->n_chars, true);
312 memcpy(ret_val.cstr.val_ptr->chars_ptr, val_ptr->chars_ptr, val_ptr->n_chars);
313 memcpy(ret_val.cstr.val_ptr->chars_ptr + val_ptr->n_chars, other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
314 return ret_val;
315 } else {
316 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_chars +
317 other_value.val_ptr->n_uchars);
318 for (int i = 0; i < val_ptr->n_chars; i++) {
319 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
320 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
321 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
322 ret_val.val_ptr->uchars_ptr[i].uc_cell = val_ptr->chars_ptr[i];
323 }
324 memcpy(ret_val.val_ptr->uchars_ptr + val_ptr->n_chars,
325 other_value.val_ptr->uchars_ptr,
326 other_value.val_ptr->n_uchars * sizeof(universal_char));
327 return ret_val;
328 }
329 }
330
331 UNIVERSAL_CHARSTRING CHARSTRING::operator+
332 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
333 {
334 must_bound("The left operand of concatenation is an unbound charstring "
335 "value.");
336 other_value.must_bound("The right operand of concatenation is an unbound "
337 "universal charstring element.");
338 if (other_value.str_val.charstring) {
339 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_chars + 1, true);
340 memcpy(ret_val.cstr.val_ptr->chars_ptr, val_ptr->chars_ptr, val_ptr->n_chars);
341 ret_val.cstr.val_ptr->chars_ptr[val_ptr->n_chars] = other_value.str_val.cstr.val_ptr->chars_ptr[other_value.uchar_pos];
342 return ret_val;
343 } else {
344 UNIVERSAL_CHARSTRING ret_val(val_ptr->n_chars + 1);
345 for (int i = 0; i < val_ptr->n_chars; i++) {
346 ret_val.val_ptr->uchars_ptr[i].uc_group = 0;
347 ret_val.val_ptr->uchars_ptr[i].uc_plane = 0;
348 ret_val.val_ptr->uchars_ptr[i].uc_row = 0;
349 ret_val.val_ptr->uchars_ptr[i].uc_cell = val_ptr->chars_ptr[i];
350 }
351 ret_val.val_ptr->uchars_ptr[val_ptr->n_chars] = other_value.get_uchar();
352 return ret_val;
353 }
354 }
355
356 CHARSTRING& CHARSTRING::operator+=(char other_value)
357 {
358 must_bound("Appending a character to an unbound charstring value.");
359 if (val_ptr->ref_count > 1) {
360 charstring_struct *old_ptr = val_ptr;
361 old_ptr->ref_count--;
362 init_struct(old_ptr->n_chars + 1);
363 memcpy(val_ptr->chars_ptr, old_ptr->chars_ptr, old_ptr->n_chars);
364 val_ptr->chars_ptr[old_ptr->n_chars] = other_value;
365 } else {
366 val_ptr = (charstring_struct*)
367 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars + 1));
368 val_ptr->chars_ptr[val_ptr->n_chars] = other_value;
369 val_ptr->n_chars++;
370 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
371 }
372 return *this;
373 }
374
375 CHARSTRING& CHARSTRING::operator+=(const char *other_value)
376 {
377 must_bound("Appending a string literal to an unbound charstring value.");
378 if (other_value != NULL) {
379 int other_n_chars = strlen(other_value);
380 if (other_n_chars > 0) {
381 if (val_ptr->ref_count > 1) {
382 charstring_struct *old_ptr = val_ptr;
383 old_ptr->ref_count--;
384 init_struct(old_ptr->n_chars + other_n_chars);
385 memcpy(val_ptr->chars_ptr, old_ptr->chars_ptr, old_ptr->n_chars);
386 memcpy(val_ptr->chars_ptr + old_ptr->n_chars, other_value,
387 other_n_chars);
388 } else {
389 if (other_value >= val_ptr->chars_ptr &&
390 other_value <= val_ptr->chars_ptr + val_ptr->n_chars) {
391 int offset = other_value - val_ptr->chars_ptr;
392 val_ptr = (charstring_struct*)
393 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars + other_n_chars));
394 memcpy(val_ptr->chars_ptr + val_ptr->n_chars,
395 val_ptr->chars_ptr + offset, other_n_chars);
396 } else {
397 val_ptr = (charstring_struct*)
398 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars + other_n_chars));
399 memcpy(val_ptr->chars_ptr + val_ptr->n_chars, other_value,
400 other_n_chars);
401 }
402 val_ptr->n_chars += other_n_chars;
403 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
404 }
405 }
406 }
407 return *this;
408 }
409
410 CHARSTRING& CHARSTRING::operator+=(const CHARSTRING& other_value)
411 {
412 must_bound("Appending a charstring value to an unbound charstring value.");
413 other_value.must_bound("Appending an unbound charstring value to another "
414 "charstring value.");
415 int other_n_chars = other_value.val_ptr->n_chars;
416 if (other_n_chars > 0) {
417 if (val_ptr->n_chars == 0) {
418 clean_up();
419 val_ptr = other_value.val_ptr;
420 val_ptr->ref_count++;
421 } else if (val_ptr->ref_count > 1) {
422 charstring_struct *old_ptr = val_ptr;
423 old_ptr->ref_count--;
424 init_struct(old_ptr->n_chars + other_n_chars);
425 memcpy(val_ptr->chars_ptr, old_ptr->chars_ptr, old_ptr->n_chars);
426 memcpy(val_ptr->chars_ptr + old_ptr->n_chars,
427 other_value.val_ptr->chars_ptr, other_n_chars);
428 } else {
429 val_ptr = (charstring_struct*)
430 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars + other_n_chars));
431 memcpy(val_ptr->chars_ptr + val_ptr->n_chars,
432 other_value.val_ptr->chars_ptr, other_n_chars);
433 val_ptr->n_chars += other_n_chars;
434 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
435 }
436 }
437 return *this;
438 }
439
440 CHARSTRING& CHARSTRING::operator+=(const CHARSTRING_ELEMENT& other_value)
441 {
442 must_bound("Appending a charstring element to an unbound charstring value.");
443 other_value.must_bound("Appending an unbound charstring element to a "
444 "charstring value.");
445 if (val_ptr->ref_count > 1) {
446 charstring_struct *old_ptr = val_ptr;
447 old_ptr->ref_count--;
448 init_struct(old_ptr->n_chars + 1);
449 memcpy(val_ptr->chars_ptr, old_ptr->chars_ptr, old_ptr->n_chars);
450 val_ptr->chars_ptr[old_ptr->n_chars] = other_value.get_char();
451 } else {
452 val_ptr = (charstring_struct*)
453 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars + 1));
454 val_ptr->chars_ptr[val_ptr->n_chars] = other_value.get_char();
455 val_ptr->n_chars++;
456 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
457 }
458 return *this;
459 }
460
461 CHARSTRING CHARSTRING::operator<<=(int rotate_count) const
462 {
463 must_bound("Unbound charstring operand of rotate left operator.");
464 if (val_ptr->n_chars == 0) return *this;
465 if (rotate_count >= 0) {
466 rotate_count %= val_ptr->n_chars;
467 if (rotate_count == 0) return *this;
468 CHARSTRING ret_val(val_ptr->n_chars);
469 memcpy(ret_val.val_ptr->chars_ptr, val_ptr->chars_ptr + rotate_count,
470 val_ptr->n_chars - rotate_count);
471 memcpy(ret_val.val_ptr->chars_ptr + val_ptr->n_chars - rotate_count,
472 val_ptr->chars_ptr, rotate_count);
473 return ret_val;
474 } else return *this >>= (-rotate_count);
475 }
476
477 CHARSTRING CHARSTRING::operator<<=(const INTEGER& rotate_count) const
478 {
479 rotate_count.must_bound("Unbound integer operand of rotate left "
480 "operator.");
481 return *this <<= (int)rotate_count;
482 }
483
484 CHARSTRING CHARSTRING::operator>>=(int rotate_count) const
485 {
486 must_bound("Unbound charstring operand of rotate right operator.");
487 if (val_ptr->n_chars == 0) return *this;
488 if (rotate_count >= 0) {
489 rotate_count %= val_ptr->n_chars;
490 if (rotate_count == 0) return *this;
491 CHARSTRING ret_val(val_ptr->n_chars);
492 memcpy(ret_val.val_ptr->chars_ptr, val_ptr->chars_ptr + val_ptr->n_chars -
493 rotate_count, rotate_count);
494 memcpy(ret_val.val_ptr->chars_ptr + rotate_count, val_ptr->chars_ptr,
495 val_ptr->n_chars - rotate_count);
496 return ret_val;
497 } else return *this <<= (-rotate_count);
498 }
499
500 CHARSTRING CHARSTRING::operator>>=(const INTEGER& rotate_count) const
501 {
502 rotate_count.must_bound("Unbound integer operand of rotate right "
503 "operator.");
504 return *this >>= (int)rotate_count;
505 }
506
507 CHARSTRING_ELEMENT CHARSTRING::operator[](int index_value)
508 {
509 if (val_ptr == NULL && index_value == 0) {
510 init_struct(1);
511 return CHARSTRING_ELEMENT(FALSE, *this, 0);
512 } else {
513 must_bound("Accessing an element of an unbound charstring value.");
514 if (index_value < 0) TTCN_error("Accessing a charstring element using a "
515 "negative index (%d).", index_value);
516 int n_chars = val_ptr->n_chars;
517 if (index_value > n_chars) TTCN_error("Index overflow when accessing a "
518 "charstring element: The index is %d, but the string has only %d "
519 "characters.", index_value, n_chars);
520 if (index_value == n_chars) {
521 if (val_ptr->ref_count == 1) {
522 val_ptr = (charstring_struct*)
523 Realloc(val_ptr, MEMORY_SIZE(n_chars + 1));
524 val_ptr->n_chars++;
525 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
526 } else {
527 charstring_struct *old_ptr = val_ptr;
528 old_ptr->ref_count--;
529 init_struct(n_chars + 1);
530 memcpy(val_ptr->chars_ptr, old_ptr->chars_ptr, n_chars);
531 }
532 return CHARSTRING_ELEMENT(FALSE, *this, index_value);
533 } else return CHARSTRING_ELEMENT(TRUE, *this, index_value);
534 }
535 }
536
537 CHARSTRING_ELEMENT CHARSTRING::operator[](const INTEGER& index_value)
538 {
539 index_value.must_bound("Indexing a charstring value with an unbound integer "
540 "value.");
541 return (*this)[(int)index_value];
542 }
543
544 const CHARSTRING_ELEMENT CHARSTRING::operator[](int index_value) const
545 {
546 must_bound("Accessing an element of an unbound charstring value.");
547 if (index_value < 0) TTCN_error("Accessing a charstring element using a "
548 "negative index (%d).", index_value);
549 if (index_value >= val_ptr->n_chars) TTCN_error("Index overflow when "
550 "accessing a charstring element: The index is %d, but the string has only "
551 "%d characters.", index_value, val_ptr->n_chars);
552 return CHARSTRING_ELEMENT(TRUE, const_cast<CHARSTRING&>(*this), index_value);
553 }
554
555 const CHARSTRING_ELEMENT CHARSTRING::operator[](const INTEGER& index_value) const
556 {
557 index_value.must_bound("Indexing a charstring value with an unbound integer "
558 "value.");
559 return (*this)[(int)index_value];
560 }
561
562 CHARSTRING::operator const char*() const
563 {
564 must_bound("Casting an unbound charstring value to const char*.");
565 return val_ptr->chars_ptr;
566 }
567
568 int CHARSTRING::lengthof() const
569 {
570 must_bound("Performing lengthof operation on an unbound charstring value.");
571 return val_ptr->n_chars;
572 }
573
574 void CHARSTRING::log() const
575 {
576 if (val_ptr != NULL) {
577 expstring_t buffer = 0;
578 enum { INIT, PCHAR, NPCHAR } state = INIT;
579 for (int i = 0; i < val_ptr->n_chars; i++) {
580 char c = val_ptr->chars_ptr[i];
581 if (TTCN_Logger::is_printable(c)) {
582 // the actual character is printable
583 switch (state) {
584 case NPCHAR: // concatenation sign if previous part was not printable
585 buffer = mputstr(buffer, " & ");
586 // no break
587 case INIT: // opening "
588 buffer = mputc(buffer, '"');
589 // no break
590 case PCHAR: // the character itself
591 TTCN_Logger::log_char_escaped(c, buffer);
592 break;
593 }
594 state = PCHAR;
595 } else {
596 // the actual character is not printable
597 switch (state) {
598 case PCHAR: // closing " if previous part was printable
599 buffer = mputc(buffer, '"');
600 // no break
601 case NPCHAR: // concatenation sign
602 buffer = mputstr(buffer, " & ");
603 // no break
604 case INIT: // the character itself
605 buffer = mputprintf(buffer, "char(0, 0, 0, %u)", (unsigned char)c);
606 break;
607 }
608 state = NPCHAR;
609 }
610 }
611 // final steps
612 switch (state) {
613 case INIT: // the string was empty
614 buffer = mputstr(buffer, "\"\"");
615 break;
616 case PCHAR: // last character was printable -> closing "
617 buffer = mputc(buffer, '"');
618 break;
619 default:
620 break;
621 }
622 TTCN_Logger::log_event_str(buffer);
623 Free(buffer);
624 } else {
625 TTCN_Logger::log_event_unbound();
626 }
627 }
628
629 boolean CHARSTRING::set_param_internal(Module_Param& param, boolean allow_pattern) {
630 boolean is_pattern = FALSE;
631 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "charstring value");
632 Module_Param_Ptr mp = &param;
633 if (param.get_type() == Module_Param::MP_Reference) {
634 mp = param.get_referenced_param();
635 }
636 switch (mp->get_type()) {
637 case Module_Param::MP_Universal_Charstring:
638 case Module_Param::MP_Charstring:
639 switch (param.get_operation_type()) {
640 case Module_Param::OT_ASSIGN:
641 clean_up();
642 // no break
643 case Module_Param::OT_CONCAT: {
644 // The universal charstring will decode the string value if it is UTF-8 encoded
645 UNIVERSAL_CHARSTRING ucs;
646 ucs.set_param(*mp);
647 if (ucs.charstring) {
648 // No special characters were found
649 if (is_bound()) {
650 *this = *this + ucs.cstr;
651 } else {
652 *this = ucs.cstr;
653 }
654 } else {
655 // Special characters found -> check if the UTF-8 decoding resulted in any multi-byte characters
656 for (int i = 0; i < ucs.val_ptr->n_uchars; ++i) {
657 if (0 != ucs.val_ptr->uchars_ptr[i].uc_group ||
658 0 != ucs.val_ptr->uchars_ptr[i].uc_plane ||
659 0 != ucs.val_ptr->uchars_ptr[i].uc_row) {
660 param.error("Type mismatch: a charstring value without multi-octet characters was expected.");
661 }
662 }
663 CHARSTRING new_cs(ucs.val_ptr->n_uchars);
664 for (int i = 0; i < ucs.val_ptr->n_uchars; ++i) {
665 new_cs.val_ptr->chars_ptr[i] = ucs.val_ptr->uchars_ptr[i].uc_cell;
666 }
667 if (is_bound()) {
668 *this = *this + new_cs;
669 } else {
670 *this = new_cs;
671 }
672 }
673 break; }
674 default:
675 TTCN_error("Internal error: CHARSTRING::set_param()");
676 }
677 break;
678 case Module_Param::MP_Expression:
679 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
680 // only allow string patterns for the first operand
681 CHARSTRING operand1, operand2;
682 is_pattern = operand1.set_param_internal(*mp->get_operand1(), allow_pattern);
683 operand2.set_param(*mp->get_operand2());
684 if (param.get_operation_type() == Module_Param::OT_CONCAT) {
685 *this = *this + operand1 + operand2;
686 }
687 else {
688 *this = operand1 + operand2;
689 }
690 }
691 else {
692 param.expr_type_error("a charstring");
693 }
694 break;
695 case Module_Param::MP_Pattern:
696 if (allow_pattern) {
697 *this = CHARSTRING(mp->get_pattern());
698 is_pattern = TRUE;
699 break;
700 }
701 // else fall through
702 default:
703 param.type_error("charstring value");
704 break;
705 }
706 return is_pattern;
707 }
708
709 void CHARSTRING::set_param(Module_Param& param) {
710 set_param_internal(param, FALSE);
711 }
712
713 Module_Param* CHARSTRING::get_param(Module_Param_Name& /* param_name */) const
714 {
715 if (!is_bound()) {
716 return new Module_Param_Unbound();
717 }
718 return new Module_Param_Charstring(val_ptr->n_chars, mcopystr(val_ptr->chars_ptr));
719 }
720
721 void CHARSTRING::encode_text(Text_Buf& text_buf) const
722 {
723 must_bound("Text encoder: Encoding an unbound charstring value.");
724 int n_chars = val_ptr->n_chars;
725 text_buf.push_int(n_chars);
726 if (n_chars > 0) text_buf.push_raw(n_chars, val_ptr->chars_ptr);
727 }
728
729 void CHARSTRING::decode_text(Text_Buf& text_buf)
730 {
731 int n_chars = text_buf.pull_int().get_val();
732 if (n_chars < 0)
733 TTCN_error("Text decoder: invalid length of a charstring.");
734 clean_up();
735 init_struct(n_chars);
736 if (n_chars > 0) text_buf.pull_raw(n_chars, val_ptr->chars_ptr);
737 }
738
739 void CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td,
740 TTCN_Buffer& p_buf,
741 TTCN_EncDec::coding_t p_coding, ...) const
742 {
743 va_list pvar;
744 va_start(pvar, p_coding);
745 switch(p_coding) {
746 case TTCN_EncDec::CT_BER: {
747 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
748 unsigned BER_coding=va_arg(pvar, unsigned);
749 BER_encode_chk_coding(BER_coding);
750 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
751 tlv->put_in_buffer(p_buf);
752 ASN_BER_TLV_t::destruct(tlv);
753 break;}
754 case TTCN_EncDec::CT_RAW: {
755 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
756 if(!p_td.raw)
757 TTCN_EncDec_ErrorContext::error_internal
758 ("No RAW descriptor available for type '%s'.", p_td.name);
759 RAW_enc_tr_pos rp;
760 rp.level=0;
761 rp.pos=NULL;
762 RAW_enc_tree root(TRUE,NULL,&rp,1,p_td.raw);
763 RAW_encode(p_td, root);
764 root.put_to_buf(p_buf);
765 break;}
766 case TTCN_EncDec::CT_TEXT: {
767 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
768 if(!p_td.text)
769 TTCN_EncDec_ErrorContext::error_internal
770 ("No TEXT descriptor available for type '%s'.", p_td.name);
771 TEXT_encode(p_td,p_buf);
772 break;}
773 case TTCN_EncDec::CT_XER: {
774 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
775 unsigned XER_coding=va_arg(pvar, unsigned);
776 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
777 p_buf.put_c('\n');
778 break;}
779 case TTCN_EncDec::CT_JSON: {
780 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
781 if(!p_td.json)
782 TTCN_EncDec_ErrorContext::error_internal
783 ("No JSON descriptor available for type '%s'.", p_td.name);
784 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
785 JSON_encode(p_td, tok);
786 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
787 break;}
788 default:
789 TTCN_error("Unknown coding method requested to encode type '%s'",
790 p_td.name);
791 }
792 va_end(pvar);
793 }
794
795 void CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td,
796 TTCN_Buffer& p_buf,
797 TTCN_EncDec::coding_t p_coding, ...)
798 {
799 va_list pvar;
800 va_start(pvar, p_coding);
801 switch(p_coding) {
802 case TTCN_EncDec::CT_BER: {
803 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
804 unsigned L_form=va_arg(pvar, unsigned);
805 ASN_BER_TLV_t tlv;
806 BER_decode_str2TLV(p_buf, tlv, L_form);
807 BER_decode_TLV(p_td, tlv, L_form);
808 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
809 break;}
810 case TTCN_EncDec::CT_RAW: {
811 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
812 if(!p_td.raw)
813 TTCN_EncDec_ErrorContext::error_internal
814 ("No RAW descriptor available for type '%s'.", p_td.name);
815 raw_order_t order;
816 switch(p_td.raw->top_bit_order){
817 case TOP_BIT_LEFT:
818 order=ORDER_LSB;
819 break;
820 case TOP_BIT_RIGHT:
821 default:
822 order=ORDER_MSB;
823 }
824 if(RAW_decode(p_td, p_buf, p_buf.get_len()*8, order)<0)
825 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
826 "Can not decode type '%s', because invalid or incomplete"
827 " message was received"
828 , p_td.name);
829 break;}
830 case TTCN_EncDec::CT_TEXT: {
831 Limit_Token_List limit;
832 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
833 if(!p_td.text)
834 TTCN_EncDec_ErrorContext::error_internal
835 ("No TEXT descriptor available for type '%s'.", p_td.name);
836 const unsigned char *b=p_buf.get_data();
837 if(b[p_buf.get_len()-1]!='\0'){
838 p_buf.set_pos(p_buf.get_len());
839 p_buf.put_zero(8,ORDER_LSB);
840 p_buf.rewind();
841 }
842 if(TEXT_decode(p_td,p_buf,limit)<0)
843 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
844 "Can not decode type '%s', because invalid or incomplete"
845 " message was received"
846 , p_td.name);
847 break;}
848 case TTCN_EncDec::CT_XER: {
849 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
850 unsigned XER_coding=va_arg(pvar, unsigned);
851 XmlReaderWrap reader(p_buf);
852 int success = reader.Read();
853 for (; success==1; success=reader.Read()) {
854 int type = reader.NodeType();
855 if (type==XML_READER_TYPE_ELEMENT)
856 break;
857 }
858 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
859 size_t bytes = reader.ByteConsumed();
860 p_buf.set_pos(bytes);
861 break;}
862 case TTCN_EncDec::CT_JSON: {
863 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
864 if(!p_td.json)
865 TTCN_EncDec_ErrorContext::error_internal
866 ("No JSON descriptor available for type '%s'.", p_td.name);
867 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
868 if(JSON_decode(p_td, tok, false)<0)
869 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
870 "Can not decode type '%s', because invalid or incomplete"
871 " message was received"
872 , p_td.name);
873 p_buf.set_pos(tok.get_buf_pos());
874 break;}
875 default:
876 TTCN_error("Unknown coding method requested to decode type '%s'",
877 p_td.name);
878 }
879 va_end(pvar);
880 }
881
882 ASN_BER_TLV_t*
883 CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
884 unsigned p_coding) const
885 {
886 BER_chk_descr(p_td);
887 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
888 if(!new_tlv) {
889 new_tlv=BER_encode_TLV_OCTETSTRING
890 (p_coding, val_ptr->n_chars,
891 (const unsigned char*)val_ptr->chars_ptr);
892 }
893 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
894 return new_tlv;
895 }
896
897 boolean CHARSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
898 const ASN_BER_TLV_t& p_tlv,
899 unsigned L_form)
900 {
901 clean_up();
902 BER_chk_descr(p_td);
903 ASN_BER_TLV_t stripped_tlv;
904 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
905 TTCN_EncDec_ErrorContext ec("While decoding CHARSTRING type: ");
906 /* Upper estimation for the length. */
907 size_t stripped_tlv_len = stripped_tlv.get_len();
908 if (stripped_tlv_len < 2) return FALSE;
909 int max_len = stripped_tlv_len - 2;
910 init_struct(max_len);
911 unsigned int octetnum_start = 0;
912 BER_decode_TLV_OCTETSTRING(stripped_tlv, L_form, octetnum_start,
913 val_ptr->n_chars,
914 (unsigned char*)val_ptr->chars_ptr);
915 if (val_ptr->n_chars < max_len) {
916 if (val_ptr->n_chars == 0) {
917 clean_up();
918 init_struct(0);
919 } else {
920 val_ptr = (charstring_struct*)
921 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars));
922 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
923 }
924 }
925 return TRUE;
926 }
927
928 int CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
929 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
930 {
931 int decoded_length = 0;
932 int str_len = 0;
933 clean_up();
934 if (p_td.text->begin_decode) {
935 int tl;
936 if ((tl = p_td.text->begin_decode->match_begin(buff)) < 0) {
937 if (no_err) return -1;
938 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
939 "The specified token '%s' not found for '%s': ",
940 (const char*) *(p_td.text->begin_decode), p_td.name);
941 return 0;
942 }
943 decoded_length += tl;
944 buff.increase_pos(tl);
945 }
946 // never return "not enough bits"
947 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
948
949 if (p_td.text->select_token) {
950 int tl;
951 if ((tl = p_td.text->select_token->match_begin(buff)) < 0) {
952 if (no_err) return -1;
953 else tl = 0;
954 }
955 str_len = tl;
956 }
957 else if ( p_td.text->val.parameters
958 && p_td.text->val.parameters->decoding_params.min_length != -1) {
959 str_len = p_td.text->val.parameters->decoding_params.min_length;
960 }
961 else if (p_td.text->end_decode) {
962 int tl;
963 if ((tl = p_td.text->end_decode->match_first(buff)) < 0) {
964 if (no_err) return -1;
965 else tl = 0;
966 }
967 str_len = tl;
968 }
969 else if (limit.has_token()) {
970 int tl;
971 if ((tl = limit.match(buff)) < 0) tl = buff.get_read_len() - 1;
972 str_len = tl;
973 }
974 else {
975 str_len = buff.get_read_len() - 1;
976 }
977
978 init_struct(str_len);
979 memcpy(val_ptr->chars_ptr, buff.get_read_data(), str_len);
980 decoded_length += str_len;
981 buff.increase_pos(str_len);
982
983 if ( p_td.text->val.parameters
984 && p_td.text->val.parameters->decoding_params.convert != 0) {
985 if (p_td.text->val.parameters->decoding_params.convert == 1) {
986 for (int a = 0; a < str_len; a++) {
987 val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
988 }
989 }
990 else {
991 for (int a = 0; a < str_len; a++) {
992 val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
993 }
994 }
995 }
996 if (p_td.text->end_decode) {
997 int tl;
998 if ((tl = p_td.text->end_decode->match_begin(buff)) < 0) {
999 if (no_err) return -1;
1000 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
1001 "The specified token '%s' not found for '%s': ",
1002 (const char*) *(p_td.text->end_decode), p_td.name);
1003 return 0;
1004 }
1005 decoded_length += tl;
1006 buff.increase_pos(tl);
1007 }
1008 return decoded_length;
1009 }
1010
1011 int CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
1012 TTCN_Buffer& buff) const{
1013 int encoded_length=0;
1014 if(p_td.text->begin_encode){
1015 buff.put_cs(*p_td.text->begin_encode);
1016 encoded_length+=p_td.text->begin_encode->lengthof();
1017 }
1018 if(!is_bound()) {
1019 TTCN_EncDec_ErrorContext::error
1020 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
1021 if(p_td.text->end_encode){
1022 buff.put_cs(*p_td.text->end_encode);
1023 encoded_length+=p_td.text->end_encode->lengthof();
1024 }
1025 return encoded_length;
1026 }
1027
1028 if(p_td.text->val.parameters==NULL){
1029 buff.put_cs(*this);
1030 encoded_length+=val_ptr->n_chars;
1031 } else {
1032 int chars_before=0;
1033 int chars_after=0;
1034 if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
1035 switch(p_td.text->val.parameters->coding_params.just){
1036 case -1: //left
1037 chars_after=p_td.text->
1038 val.parameters->coding_params.min_length-val_ptr->n_chars;
1039 break;
1040 case 0:{ // center
1041 int pad=p_td.text->
1042 val.parameters->coding_params.min_length-val_ptr->n_chars;
1043 chars_after=pad/2;
1044 chars_before=pad-chars_after;
1045 break;
1046 }
1047 case 1: // right
1048 default:
1049 chars_before=p_td.text->
1050 val.parameters->coding_params.min_length-val_ptr->n_chars;
1051 break;
1052 }
1053 }
1054 if(chars_before){
1055 unsigned char* p=NULL;
1056 size_t len=chars_before;
1057 buff.get_end(p,len);
1058 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
1059 buff.increase_length(chars_before);
1060 encoded_length+=chars_before;
1061 }
1062
1063 switch(p_td.text->val.parameters->coding_params.convert){
1064 case -1:{ //lower_case
1065 unsigned char* p=NULL;
1066 size_t len=val_ptr->n_chars;
1067 buff.get_end(p,len);
1068 for(int a=0;a<val_ptr->n_chars;a++)
1069 p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
1070 buff.increase_length(val_ptr->n_chars);
1071 break;
1072 }
1073 case 0:{ // no conversion
1074 buff.put_cs(*this);
1075 break;
1076 }
1077 case 1: // upper_case
1078 default:
1079 {
1080 unsigned char* p=NULL;
1081 size_t len=val_ptr->n_chars;
1082 buff.get_end(p,len);
1083 for(int a=0;a<val_ptr->n_chars;a++)
1084 p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
1085 buff.increase_length(val_ptr->n_chars);
1086 break;
1087 }
1088 }
1089 encoded_length+=val_ptr->n_chars;
1090
1091 if(chars_after){
1092 unsigned char* p=NULL;
1093 size_t len=chars_after;
1094 buff.get_end(p,len);
1095 for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
1096 buff.increase_length(chars_after);
1097 encoded_length+=chars_after;
1098 }
1099
1100 }
1101
1102 if(p_td.text->end_encode){
1103 buff.put_cs(*p_td.text->end_encode);
1104 encoded_length+=p_td.text->end_encode->lengthof();
1105 }
1106 return encoded_length;
1107 }
1108
1109 #ifdef TITAN_RUNTIME_2
1110 int CHARSTRING::encode_raw(TTCN_Buffer& p_buf) const
1111 {
1112 p_buf.put_string(*this);
1113 return val_ptr ? val_ptr->n_chars : 0;
1114 }
1115
1116 int CHARSTRING::JSON_encode_negtest_raw(JSON_Tokenizer& p_tok) const
1117 {
1118 if (val_ptr != NULL) {
1119 p_tok.put_raw_data(val_ptr->chars_ptr, val_ptr->n_chars);
1120 return val_ptr->n_chars;
1121 }
1122 return 0;
1123 }
1124 #endif
1125
1126
1127 void xml_escape(const unsigned int masked_c, TTCN_Buffer& p_buf)
1128 {
1129 size_t len = 6;
1130 // length of the majority of the names of control characters, +3 for </>
1131 static const char *escapes[32] = {
1132 "<nul/>","<soh/>","<stx/>","<etx/>","<eot/>","<enq/>","<ack/>","<bel/>",
1133 "<bs/>" ,"<tab/>","<lf/>" ,"<vt/>" ,"<ff/>" ,"<cr/>" ,"<so/>" ,"<si/>" ,
1134 "<dle/>","<dc1/>","<dc2/>","<dc3/>","<dc4/>","<nak/>","<syn/>","<etb/>",
1135 "<can/>","<em/>" ,"<sub/>","<esc/>","<is4/>","<is3/>","<is2/>","<is1/>",
1136 };
1137 unsigned int c = (masked_c & 0x7FFFFFFF); // unmasked
1138
1139 switch (c) {
1140 // XML's "own" characters, escaped according to X.680/2002, 11.15.4 b)
1141 case '<':
1142 p_buf.put_s(4, (cbyte*)"&lt;");
1143 break;
1144
1145 case '>':
1146 p_buf.put_s(4, (cbyte*)"&gt;");
1147 break;
1148
1149 case '&':
1150 p_buf.put_s(5, (cbyte*)"&amp;");
1151 break;
1152
1153 // Control characters, escaped according to X.680/2002, 11.15.5
1154 case 8: case 11: case 12: case 14: case 15: case 25:
1155 // the name of these control characters has only two letters
1156 --len;
1157 // no break
1158 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
1159 case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
1160 case 24: case 26: case 27: case 28: case 29: case 30: case 31:
1161 // 9=TAB 10=LF 13=CR are absent from this block altogether
1162 p_buf.put_s(len, (cbyte*)escapes[c]);
1163 break;
1164
1165 case '\"': // HR58225
1166 p_buf.put_s(6, (cbyte*)"&quot;");
1167 break;
1168
1169 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1170 // so if they appear in content they must be escaped.
1171 // Currently this happens even if the string is not an attribute.
1172 p_buf.put_s(6, (cbyte*)"&apos;");
1173 break;
1174
1175 case 9: case 10: case 13:
1176 c = masked_c; // put the mask back on (makes it >127)
1177 // no break
1178 default:
1179 if (c > 127) { // XML numeric entity, as in X.680/2002 11.15.8
1180 c &= 0x7FFFFFFF; // take it off again
1181 // Ensure that an even number of hex digits is produced
1182 int width = (1 + (c > 0xFF) + (c > 0xFFFF) + (c > 0xFFFFFF)) << 1;
1183 char escapade[16];
1184 len = snprintf(escapade, 16, "&#x%0*X;", width, c);
1185 p_buf.put_s(len, (cbyte*)(escapade+0));
1186 }
1187 else { // a plain old, unmolested character
1188 p_buf.put_c(c);
1189 }
1190 break;
1191 }
1192 }
1193
1194 // Base64 encoder table
1195 extern const char cb64[]=
1196 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1197
1198 int CHARSTRING::XER_encode(const XERdescriptor_t& p_td,
1199 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
1200 {
1201 if(!is_bound()) {
1202 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1203 "Encoding an unbound character string value.");
1204 }
1205 int exer = is_exer(flavor |= SIMPLE_TYPE);
1206 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1207 int encoded_length=(int)p_buf.get_len();
1208 bool do_empty_element = val_ptr==NULL || val_ptr->n_chars == 0;
1209
1210 flavor &= ~XER_RECOF; // charstring doesn't care
1211
1212 if (do_empty_element && exer && p_td.dfeValue != 0) {
1213 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR,
1214 "An encoded value with DEFAULT-FOR-EMPTY instruction applied should not be empty");
1215 }
1216 if (begin_xml(p_td, p_buf, flavor, indent, do_empty_element) == -1) {
1217 --encoded_length; // it was shortened by one
1218 }
1219
1220 if (!do_empty_element) {
1221 const char * current = val_ptr->chars_ptr;
1222 const char * const end = val_ptr->chars_ptr + val_ptr->n_chars;
1223 const char * to_escape;
1224 unsigned int mask;
1225 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1226 to_escape = "<&>'\"\x09\x0A\x0D";
1227 mask = 0x80000000; // guaranteed bigger than any Unicode character
1228 }
1229 else {
1230 to_escape = "<&>'\"";
1231 mask = 0;
1232 }
1233
1234 // If Base64 is needed, use a temporary buffer.
1235 TTCN_Buffer tmpbuf, &rbuf = (exer && (p_td.xer_bits & BASE_64)) ? tmpbuf : p_buf;
1236
1237 // This here is an optimization. Only &lt;&amp;&gt; need to be escaped.
1238 // Contiguous runs of "ordinary" characters are put in the buffer
1239 // with a single call.
1240 // TODO: is it really faster ? strpbrk is probably O(nm)
1241 while ( const char * trouble = strpbrk(current, to_escape) ) {
1242 rbuf.put_s((size_t)(trouble - current), (cbyte*)current);
1243 xml_escape(*trouble | mask, rbuf); // escape the troublesome character
1244 current = trouble+1;
1245 }
1246
1247 // put the remainder in the buffer
1248 rbuf.put_s( (size_t)(end - current), (cbyte*)current);
1249
1250 if (exer && (p_td.xer_bits & BASE_64)) {
1251 size_t clear_len = tmpbuf.get_len(); // the length before padding
1252 // Pad the temporary buffer so i+1 and i+2 don't go outside the buffer
1253 unsigned char zero[2] = {0,0};
1254 tmpbuf.put_s(2, zero);
1255 // Get the buffer after the possible realloc caused by the padding.
1256 cbyte * in = tmpbuf.get_data();
1257
1258 // Encode 3 bytes of cleartext into 4 bytes of Base64
1259 for (size_t i = 0; i < clear_len; i += 3) {
1260 p_buf.put_c( cb64[ in[i] >> 2 ] );
1261 p_buf.put_c( cb64[ ((in[i] & 0x03) << 4) | ((in[i+1] & 0xf0) >> 4) ]);
1262 p_buf.put_c( i+1 < clear_len
1263 ? cb64[ ((in[i+1] & 0x0f) << 2) | ((in[i+2] & 0xc0) >> 6) ]
1264 : '=' );
1265 p_buf.put_c( i+2 < clear_len ? cb64[ in[i+2] & 0x3f ] : '=' );
1266 } // next i
1267 } // if base64
1268 }
1269
1270 end_xml(p_td, p_buf, flavor, indent, do_empty_element);
1271 return (int)p_buf.get_len() - encoded_length;
1272 }
1273
1274 /**
1275 * Translates a Base64 value to either its 6-bit reconstruction value
1276 * or a negative number indicating some other meaning.
1277 * Public domain from http://iharder.net/base64 */
1278 char base64_decoder_table[256] =
1279 {
1280 -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
1281 -5,-5, // Whitespace: Tab and Linefeed
1282 -9,-9, // Decimal 11 - 12
1283 -5, // Whitespace: Carriage Return
1284 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
1285 -9,-9,-9,-9,-9, // Decimal 27 - 31
1286 -5, // Whitespace: Space
1287 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
1288 62, // Plus sign at decimal 43
1289 -9,-9,-9, // Decimal 44 - 46
1290 63, // Slash at decimal 47
1291 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
1292 -9,-9,-9, // Decimal 58 - 60
1293 -1, // Equals sign at decimal 61
1294 -9,-9,-9, // Decimal 62 - 64
1295 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
1296 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
1297 -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
1298 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
1299 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
1300 -9,-9,-9,-9,-9 // Decimal 123 - 127
1301 ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
1302 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
1303 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
1304 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
1305 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
1306 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
1307 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
1308 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
1309 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
1310 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255
1311 };
1312
1313 unsigned int xlate(cbyte*in, int phase, unsigned char*dest) {
1314 static unsigned char nbytes[4] = { 3,1,1,2 };
1315 unsigned char out[4];
1316 out[0] = in[0] << 2 | in[1] >> 4;
1317 out[1] = in[1] << 4 | in[2] >> 2;
1318 out[2] = in[2] << 6 | in[3] >> 0;
1319 memcpy(dest, out, nbytes[phase]);
1320 return nbytes[phase];
1321 }
1322
1323 int CHARSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
1324 unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*) {
1325 int exer = is_exer(flavor);
1326 int success = reader.Ok(), depth = -1;
1327
1328 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1329 const char * name = verify_name(reader, p_td, exer);
1330 (void)name;
1331 const char * value = (const char *)reader.Value();
1332 // FIXME copy & paste
1333 *this = value;
1334
1335 // Let the caller do reader.AdvanceAttribute();
1336 }
1337 else {
1338 bool omit_tag = exer
1339 && (p_td.xer_bits & UNTAGGED || flavor & (EMBED_VALUES|XER_LIST|USE_TYPE_ATTR|USE_NIL));
1340 for (; success == 1; success = reader.Read()) {
1341 int type = reader.NodeType();
1342 if (XML_READER_TYPE_ELEMENT == type) {
1343 verify_name(reader, p_td, exer);
1344 if (reader.IsEmptyElement()) { // has no text, needs special processing
1345 if (exer && p_td.dfeValue != 0) {
1346 *this = *static_cast<const CHARSTRING*>(p_td.dfeValue);
1347 }
1348 else init_struct(0);
1349 reader.Read();
1350 break; // exit the loop early
1351 } // if empty element
1352 // otherwise, not an empty element, stay in the loop
1353 depth = reader.Depth();
1354 }
1355 else if ((depth != -1 || omit_tag)
1356 && (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_CDATA == type))
1357 // Process #text node if we already processed the element node, or
1358 // there is no element node because UNTAGGED is in effect.
1359 {
1360 const xmlChar * value = reader.Value();
1361 size_t num_chars = strlen((const char*)value);
1362
1363 if (exer && (p_td.xer_bits & BASE_64)) {
1364 clean_up();
1365 init_struct(num_chars * 3 / 4);
1366 xmlChar in[4];
1367
1368 int phase = 0;
1369 unsigned char * dest = (unsigned char *)val_ptr->chars_ptr;
1370
1371 for (size_t o=0; o<num_chars; ++o) {
1372 xmlChar c = value[o];
1373 if(c == '=') { // Padding starts; decode last chunk and exit.
1374 dest += xlate(in,phase, dest);
1375 break;
1376 }
1377
1378 int val = base64_decoder_table[c];
1379 if(val >= 0) {
1380 in[phase] = val;
1381 phase = (phase + 1) % 4;
1382 if(phase == 0) {
1383 dest += xlate(in,phase, dest);
1384 in[0]=in[1]=in[2]=in[3]=0;
1385 }
1386 }
1387 else if (exer && (flavor & EXIT_ON_ERROR)) {
1388 clean_up();
1389 return -1;
1390 } else {
1391 TTCN_EncDec_ErrorContext::warning(
1392 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
1393 "Invalid character for Base64 '%02X'", c);
1394 }
1395 } // while
1396 // adjust
1397 val_ptr->n_chars = (char*)dest - val_ptr->chars_ptr;
1398 }
1399 else {
1400 clean_up();
1401 init_struct(num_chars);
1402 memcpy(val_ptr->chars_ptr, value, num_chars);
1403 } // if base64
1404
1405 if(!omit_tag) {
1406 // find the end element
1407 for (success = reader.Read(); success == 1; success = reader.Read()) {
1408 type = reader.NodeType();
1409 if (XML_READER_TYPE_END_ELEMENT == type) {
1410 verify_end(reader, p_td, depth, exer);
1411 reader.Read(); // one last time
1412 break;
1413 }
1414 }
1415 }
1416 break;
1417 }
1418 else if (XML_READER_TYPE_END_ELEMENT == type) {
1419 if (!omit_tag) {
1420 verify_end(reader, p_td, depth, exer);
1421 if (!val_ptr) {
1422 // We are at our end tag and no content
1423 if (exer && p_td.dfeValue != 0) {
1424 *this = *static_cast<const CHARSTRING*>(p_td.dfeValue);
1425 }
1426 else init_struct(0); // empty string
1427 }
1428 reader.Read();
1429 }
1430 break;
1431 } // if type
1432 } // next read
1433 } // if attribute
1434
1435 if (exer && p_td.whitespace >= WHITESPACE_REPLACE) { // includes _COLLAPSE
1436 for (int i=0; i<val_ptr->n_chars; ++i) { // first, _REPLACE
1437 switch (val_ptr->chars_ptr[i]) {
1438 case 9: // HORIZONTAL TAB
1439 case 10: // LINE FEED
1440 case 13: // CARRIAGE RETURN
1441 val_ptr->chars_ptr[i] = ' ';
1442 break;
1443 default:
1444 break;
1445 }
1446 } // next i
1447
1448 if (p_td.whitespace >= WHITESPACE_COLLAPSE) {
1449 char *to;
1450 const char *from, *end = val_ptr->chars_ptr + val_ptr->n_chars;
1451 for (from = to = val_ptr->chars_ptr; from < end;) {
1452 *to = *(from++);
1453 // If the copied character (*to) was a space,
1454 // and the next character to be copied (*from) is also a space
1455 // (continuous run of spaces)
1456 // or this was the first character (leading spaces to be trimmed),
1457 // then don't advance the destination (will be overwritten).
1458 if (*to != ' '
1459 || (from < end && *from != ' ' && to > val_ptr->chars_ptr)) ++to;
1460 }
1461 *to = 0;
1462 val_ptr->n_chars = to - val_ptr->chars_ptr; // truncate
1463 // TODO maybe realloc after truncation
1464 } // collapse
1465 } // if WHITESPACE
1466
1467 return 1;
1468 }
1469
1470 int CHARSTRING::RAW_encode(const TTCN_Typedescriptor_t& p_td,
1471 RAW_enc_tree& myleaf) const
1472 {
1473 int bl = val_ptr->n_chars * 8; // bit length
1474 int align_length = p_td.raw->fieldlength ? p_td.raw->fieldlength - bl : 0;
1475 if (!is_bound()) {
1476 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1477 "Encoding an unbound value.");
1478 }
1479 if ((bl + align_length) < val_ptr->n_chars * 8) {
1480 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1481 "There is no sufficient bits to encode '%s': ", p_td.name);
1482 bl = p_td.raw->fieldlength;
1483 align_length = 0;
1484 }
1485 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
1486 myleaf.must_free = FALSE;
1487 myleaf.data_ptr_used = TRUE;
1488 myleaf.body.leaf.data_ptr = (unsigned char*) val_ptr->chars_ptr;
1489 if (p_td.raw->endianness == ORDER_MSB) myleaf.align = -align_length;
1490 else myleaf.align = align_length;
1491 return myleaf.length = bl + align_length;
1492 }
1493
1494 int CHARSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td,
1495 TTCN_Buffer& buff, int limit, raw_order_t top_bit_ord, boolean no_err,
1496 int /*sel_field*/, boolean /*first_call*/)
1497 {
1498 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
1499 limit -= prepaddlength;
1500 int decode_length = p_td.raw->fieldlength == 0
1501 ? (limit / 8) * 8 : p_td.raw->fieldlength;
1502 if ( decode_length > limit
1503 || decode_length > (int) buff.unread_len_bit()) {
1504 if (no_err) return -TTCN_EncDec::ET_LEN_ERR;
1505 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1506 "There is not enough bits in the buffer to decode type %s.", p_td.name);
1507 decode_length = ((limit > (int) buff.unread_len_bit() ? (int)buff.unread_len_bit() : limit) / 8) * 8;
1508 }
1509 RAW_coding_par cp;
1510 boolean orders = FALSE;
1511 if (p_td.raw->bitorderinoctet == ORDER_MSB) orders = TRUE;
1512 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1513 cp.bitorder = orders ? ORDER_MSB : ORDER_LSB;
1514 orders = FALSE;
1515 if (p_td.raw->byteorder == ORDER_MSB) orders = TRUE;
1516 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1517 cp.byteorder = orders ? ORDER_MSB : ORDER_LSB;
1518 cp.fieldorder = p_td.raw->fieldorder;
1519 cp.hexorder = ORDER_LSB;
1520 clean_up();
1521 init_struct(decode_length / 8);
1522 buff.get_b((size_t) decode_length, (unsigned char*) val_ptr->chars_ptr, cp,
1523 top_bit_ord);
1524
1525 if (p_td.raw->length_restrition != -1) {
1526 val_ptr->n_chars = p_td.raw->length_restrition;
1527 if (p_td.raw->endianness == ORDER_MSB) memmove(val_ptr->chars_ptr,
1528 val_ptr->chars_ptr + (decode_length / 8 - val_ptr->n_chars),
1529 val_ptr->n_chars); // sizeof(char) == 1 by definition
1530 }
1531 decode_length += buff.increase_pos_padd(p_td.raw->padding);
1532 return decode_length + prepaddlength;
1533 }
1534
1535 char* CHARSTRING::to_JSON_string() const
1536 {
1537 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
1538 char* json_str = (char*)Malloc(val_ptr->n_chars + 3);
1539
1540 json_str[0] = 0;
1541 json_str = mputc(json_str, '\"');
1542
1543 for (int i = 0; i < val_ptr->n_chars; ++i) {
1544 // Increase the size of the buffer if it's not big enough to store the
1545 // characters remaining in the charstring plus 1 (for safety, in case this
1546 // character needs to be double-escaped).
1547 switch(val_ptr->chars_ptr[i]) {
1548 case '\\':
1549 json_str = mputstrn(json_str, "\\\\", 2);
1550 break;
1551 case '\n':
1552 json_str = mputstrn(json_str, "\\n", 2);
1553 break;
1554 case '\t':
1555 json_str = mputstrn(json_str, "\\t", 2);
1556 break;
1557 case '\r':
1558 json_str = mputstrn(json_str, "\\r", 2);
1559 break;
1560 case '\f':
1561 json_str = mputstrn(json_str, "\\f", 2);
1562 break;
1563 case '\b':
1564 json_str = mputstrn(json_str, "\\b", 2);
1565 break;
1566 case '\"':
1567 json_str = mputstrn(json_str, "\\\"", 2);
1568 break;
1569 default:
1570 json_str = mputc(json_str, val_ptr->chars_ptr[i]);
1571 break;
1572 }
1573 }
1574
1575 json_str = mputc(json_str, '\"');
1576 return json_str;
1577 }
1578
1579 boolean CHARSTRING::from_JSON_string(const char* p_value, size_t p_value_len, boolean check_quotes)
1580 {
1581 size_t start = 0;
1582 size_t end = p_value_len;
1583 if (check_quotes) {
1584 start = 1;
1585 end = p_value_len - 1;
1586 if (p_value[0] != '\"' || p_value[p_value_len - 1] != '\"') {
1587 return false;
1588 }
1589 }
1590
1591 // The charstring will be shorter than the JSON string, at least by the 2 quotes
1592 char* str = (char*)Malloc(end - start);
1593 size_t len = 0;
1594 boolean error = false;
1595
1596 for (size_t i = start; i < end; ++i) {
1597 if (0 > p_value[i]) {
1598 error = true;
1599 break;
1600 }
1601 if ('\\' == p_value[i]) {
1602 if (i == end - 1) {
1603 error = true;
1604 break;
1605 }
1606 switch(p_value[i + 1]) {
1607 case 'n':
1608 str[len++] = '\n';
1609 break;
1610 case 't':
1611 str[len++] = '\t';
1612 break;
1613 case 'r':
1614 str[len++] = '\r';
1615 break;
1616 case 'f':
1617 str[len++] = '\f';
1618 break;
1619 case 'b':
1620 str[len++] = '\b';
1621 break;
1622 case '\\':
1623 str[len++] = '\\';
1624 break;
1625 case '\"':
1626 str[len++] = '\"';
1627 break;
1628 case '/':
1629 str[len++] = '/';
1630 break;
1631 case 'u': {
1632 if (end - i >= 6 && '0' == p_value[i + 2] && '0' == p_value[i + 3]) {
1633 unsigned char upper_nibble = char_to_hexdigit(p_value[i + 4]);
1634 unsigned char lower_nibble = char_to_hexdigit(p_value[i + 5]);
1635 if (0x07 >= upper_nibble && 0x0F >= lower_nibble) {
1636 str[len++] = (upper_nibble << 4) | lower_nibble;
1637 // skip 4 extra characters (the 4 hex digits)
1638 i += 4;
1639 } else {
1640 // error (found something other than hex digits) -> leave the for cycle
1641 i = end;
1642 error = true;
1643 }
1644 } else {
1645 // error (not enough characters left or the first 2 hex digits are non-null) -> leave the for cycle
1646 i = end;
1647 error = true;
1648 }
1649 break;
1650 }
1651 default:
1652 // error (invalid escaped character) -> leave the for cycle
1653 i = end;
1654 error = true;
1655 break;
1656 }
1657 // skip an extra character (the \)
1658 ++i;
1659 } else {
1660 str[len++] = p_value[i];
1661 }
1662
1663 if (check_quotes && i == p_value_len - 1) {
1664 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
1665 error = true;
1666 }
1667 }
1668
1669 if (!error) {
1670 clean_up();
1671 init_struct(len);
1672 memcpy(val_ptr->chars_ptr, str, len);
1673 val_ptr->chars_ptr[len] = 0;
1674 }
1675 Free(str);
1676 return !error;
1677 }
1678
1679 int CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
1680 {
1681 if (!is_bound()) {
1682 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1683 "Encoding an unbound charstring value.");
1684 return -1;
1685 }
1686
1687 char* tmp_str = to_JSON_string();
1688 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
1689 Free(tmp_str);
1690 return enc_len;
1691 }
1692
1693 int CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
1694 {
1695 json_token_t token = JSON_TOKEN_NONE;
1696 char* value = 0;
1697 size_t value_len = 0;
1698 int dec_len = 0;
1699 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
1700 if (use_default) {
1701 // No JSON data in the buffer -> use default value
1702 value = (char*)p_td.json->default_value;
1703 value_len = strlen(value);
1704 } else {
1705 dec_len = p_tok.get_next_token(&token, &value, &value_len);
1706 }
1707 if (JSON_TOKEN_ERROR == token) {
1708 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
1709 return JSON_ERROR_FATAL;
1710 }
1711 else if (JSON_TOKEN_STRING == token || use_default) {
1712 if (!from_JSON_string(value, value_len, !use_default)) {
1713 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "charstring");
1714 clean_up();
1715 return JSON_ERROR_FATAL;
1716 }
1717 } else {
1718 return JSON_ERROR_INVALID_TOKEN;
1719 }
1720 return dec_len;
1721 }
1722
1723
1724 CHARSTRING_ELEMENT::CHARSTRING_ELEMENT(boolean par_bound_flag,
1725 CHARSTRING& par_str_val, int par_char_pos)
1726 : bound_flag(par_bound_flag), str_val(par_str_val), char_pos(par_char_pos)
1727 {
1728
1729 }
1730
1731 CHARSTRING_ELEMENT& CHARSTRING_ELEMENT::operator=(const char* other_value)
1732 {
1733 if (other_value == NULL ||
1734 other_value[0] == '\0' || other_value[1] != '\0')
1735 TTCN_error("Assignment of a charstring value with length other "
1736 "than 1 to a charstring element.");
1737 bound_flag = TRUE;
1738 str_val.copy_value();
1739 str_val.val_ptr->chars_ptr[char_pos] = other_value[0];
1740 return *this;
1741 }
1742
1743 CHARSTRING_ELEMENT& CHARSTRING_ELEMENT::operator=
1744 (const CHARSTRING& other_value)
1745 {
1746 other_value.must_bound("Assignment of an unbound charstring value to a "
1747 "charstring element.");
1748 if(other_value.val_ptr->n_chars != 1)
1749 TTCN_error("Assignment of a charstring value with length other than "
1750 "1 to a charstring element.");
1751 bound_flag = TRUE;
1752 str_val.copy_value();
1753 str_val.val_ptr->chars_ptr[char_pos] = other_value.val_ptr->chars_ptr[0];
1754 return *this;
1755 }
1756
1757 CHARSTRING_ELEMENT& CHARSTRING_ELEMENT::operator=
1758 (const CHARSTRING_ELEMENT& other_value)
1759 {
1760 other_value.must_bound("Assignment of an unbound charstring element.");
1761 if (&other_value != this) {
1762 bound_flag = TRUE;
1763 str_val.copy_value();
1764 str_val.val_ptr->chars_ptr[char_pos] =
1765 other_value.str_val.val_ptr->chars_ptr[other_value.char_pos];
1766 }
1767 return *this;
1768 }
1769
1770 boolean CHARSTRING_ELEMENT::operator==(const char *other_value) const
1771 {
1772 must_bound("Comparison of an unbound charstring element.");
1773 if (other_value == NULL || other_value[0] == '\0' ||
1774 other_value[1] != '\0') return FALSE;
1775 return str_val.val_ptr->chars_ptr[char_pos] == other_value[0];
1776 }
1777
1778 boolean CHARSTRING_ELEMENT::operator==(const CHARSTRING& other_value) const
1779 {
1780 must_bound("Comparison of an unbound charstring element.");
1781 other_value.must_bound("Comparison of an unbound charstring value.");
1782 if (other_value.val_ptr->n_chars != 1) return FALSE;
1783 return str_val.val_ptr->chars_ptr[char_pos] ==
1784 other_value.val_ptr->chars_ptr[0];
1785 }
1786
1787 boolean CHARSTRING_ELEMENT::operator==(const CHARSTRING_ELEMENT& other_value) const
1788 {
1789 must_bound("Comparison of an unbound charstring element.");
1790 other_value.must_bound("Comparison of an unbound charstring element.");
1791 return str_val.val_ptr->chars_ptr[char_pos] ==
1792 other_value.str_val.val_ptr->chars_ptr[other_value.char_pos];
1793 }
1794
1795 boolean CHARSTRING_ELEMENT::operator==(const UNIVERSAL_CHARSTRING& other_value)
1796 const
1797 {
1798 must_bound("The left operand of comparison is an unbound charstring "
1799 "element.");
1800 other_value.must_bound("The right operand of comparison is an unbound "
1801 "universal charstring value.");
1802 if (other_value.charstring) {
1803 if (other_value.cstr.val_ptr->n_chars != 1) return FALSE;
1804 return str_val.val_ptr->chars_ptr[char_pos] ==
1805 other_value.cstr.val_ptr->chars_ptr[0];
1806 }
1807 else {
1808 if (other_value.val_ptr->n_uchars != 1) return FALSE;
1809 return other_value.val_ptr->uchars_ptr[0].uc_group == 0 &&
1810 other_value.val_ptr->uchars_ptr[0].uc_plane == 0 &&
1811 other_value.val_ptr->uchars_ptr[0].uc_row == 0 &&
1812 other_value.val_ptr->uchars_ptr[0].uc_cell ==
1813 (cbyte)str_val.val_ptr->chars_ptr[char_pos];
1814 }
1815 }
1816
1817 boolean CHARSTRING_ELEMENT::operator==
1818 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
1819 {
1820 must_bound("The left operand of comparison is an unbound charstring "
1821 "element.");
1822 other_value.must_bound("The right operand of comparison is an unbound "
1823 "universal charstring element.");
1824 const universal_char& uchar = other_value.get_uchar();
1825 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
1826 uchar.uc_cell == (cbyte)str_val.val_ptr->chars_ptr[char_pos];
1827 }
1828
1829 CHARSTRING CHARSTRING_ELEMENT::operator+(const char *other_value) const
1830 {
1831 must_bound("Unbound operand of charstring element concatenation.");
1832 int other_len;
1833 if (other_value == NULL) other_len = 0;
1834 else other_len = strlen(other_value);
1835 CHARSTRING ret_val(other_len + 1);
1836 ret_val.val_ptr->chars_ptr[0] = str_val.val_ptr->chars_ptr[char_pos];
1837 memcpy(ret_val.val_ptr->chars_ptr + 1, other_value, other_len);
1838 return ret_val;
1839 }
1840
1841 CHARSTRING CHARSTRING_ELEMENT::operator+(const CHARSTRING& other_value) const
1842 {
1843 must_bound("Unbound operand of charstring element concatenation.");
1844 other_value.must_bound("Unbound operand of charstring concatenation.");
1845 int n_chars = other_value.val_ptr->n_chars;
1846 CHARSTRING ret_val(n_chars + 1);
1847 ret_val.val_ptr->chars_ptr[0] = str_val.val_ptr->chars_ptr[char_pos];
1848 memcpy(ret_val.val_ptr->chars_ptr + 1, other_value.val_ptr->chars_ptr,
1849 n_chars);
1850 return ret_val;
1851 }
1852
1853 CHARSTRING CHARSTRING_ELEMENT::operator+(const CHARSTRING_ELEMENT&
1854 other_value) const
1855 {
1856 must_bound("Unbound operand of charstring element concatenation.");
1857 other_value.must_bound("Unbound operand of charstring element "
1858 "concatenation.");
1859 char result[2];
1860 result[0] = str_val.val_ptr->chars_ptr[char_pos];
1861 result[1] = other_value.str_val.val_ptr->chars_ptr[other_value.char_pos];
1862 return CHARSTRING(2, result);
1863 }
1864
1865 UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+
1866 (const UNIVERSAL_CHARSTRING& other_value) const
1867 {
1868 must_bound("The left operand of concatenation is an unbound charstring "
1869 "element.");
1870 other_value.must_bound("The right operand of concatenation is an unbound "
1871 "universal charstring value.");
1872 if (other_value.charstring) {
1873 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1, true);
1874 ret_val.cstr.val_ptr->chars_ptr[0] = str_val.val_ptr->chars_ptr[char_pos];
1875 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1, other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
1876 return ret_val;
1877 } else {
1878 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
1879 ret_val.val_ptr->uchars_ptr[0].uc_group = 0;
1880 ret_val.val_ptr->uchars_ptr[0].uc_plane = 0;
1881 ret_val.val_ptr->uchars_ptr[0].uc_row = 0;
1882 ret_val.val_ptr->uchars_ptr[0].uc_cell = str_val.val_ptr->chars_ptr[char_pos];
1883 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
1884 other_value.val_ptr->n_uchars * sizeof(universal_char));
1885 return ret_val;
1886 }
1887 }
1888
1889 UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+
1890 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
1891 {
1892 must_bound("The left operand of concatenation is an unbound charstring "
1893 "element.");
1894 other_value.must_bound("The right operand of concatenation is an unbound "
1895 "universal charstring element.");
1896 universal_char result[2];
1897 result[0].uc_group = 0;
1898 result[0].uc_plane = 0;
1899 result[0].uc_row = 0;
1900 result[0].uc_cell = str_val.val_ptr->chars_ptr[char_pos];
1901 result[1] = other_value.get_uchar();
1902 return UNIVERSAL_CHARSTRING(2, result);
1903 }
1904
1905 char CHARSTRING_ELEMENT::get_char() const
1906 {
1907 return str_val.val_ptr->chars_ptr[char_pos];
1908 }
1909
1910 void CHARSTRING_ELEMENT::log() const
1911 {
1912 if (bound_flag) {
1913 char c = str_val.val_ptr->chars_ptr[char_pos];
1914 if (TTCN_Logger::is_printable(c)) {
1915 TTCN_Logger::log_char('"');
1916 TTCN_Logger::log_char_escaped(c);
1917 TTCN_Logger::log_char('"');
1918 } else TTCN_Logger::log_event("char(0, 0, 0, %u)", (unsigned char)c);
1919 } else TTCN_Logger::log_event_unbound();
1920 }
1921
1922 // global functions
1923
1924 boolean operator==(const char* string_value, const CHARSTRING& other_value)
1925 {
1926 other_value.must_bound("Unbound operand of charstring comparison.");
1927 if (string_value == NULL) string_value = "";
1928 return !strcmp(string_value, other_value.val_ptr->chars_ptr);
1929 }
1930
1931 boolean operator==(const char* string_value,
1932 const CHARSTRING_ELEMENT& other_value)
1933 {
1934 other_value.must_bound("Unbound operand of charstring element "
1935 "comparison.");
1936 if (string_value == NULL || string_value[0] == '\0' ||
1937 string_value[1] != '\0') return FALSE;
1938 return string_value[0] == other_value.get_char();
1939 }
1940
1941 CHARSTRING operator+(const char* string_value, const CHARSTRING& other_value)
1942 {
1943 other_value.must_bound("Unbound operand of charstring concatenation.");
1944 int string_len;
1945 if (string_value == NULL) string_len = 0;
1946 else string_len = strlen(string_value);
1947 if (string_len == 0) return other_value;
1948 CHARSTRING ret_val(string_len + other_value.val_ptr->n_chars);
1949 memcpy(ret_val.val_ptr->chars_ptr, string_value, string_len);
1950 memcpy(ret_val.val_ptr->chars_ptr + string_len,
1951 other_value.val_ptr->chars_ptr, other_value.val_ptr->n_chars);
1952 return ret_val;
1953 }
1954
1955 CHARSTRING operator+(const char* string_value,
1956 const CHARSTRING_ELEMENT& other_value)
1957 {
1958 other_value.must_bound("Unbound operand of charstring element "
1959 "concatenation.");
1960 int string_len;
1961 if (string_value == NULL) string_len = 0;
1962 else string_len = strlen(string_value);
1963 if (string_len == 0) return CHARSTRING(other_value);
1964 CHARSTRING ret_val(string_len + 1);
1965 memcpy(ret_val.val_ptr->chars_ptr, string_value, string_len);
1966 ret_val.val_ptr->chars_ptr[string_len] = other_value.get_char();
1967 return ret_val;
1968 }
1969
1970 CHARSTRING operator<<=(const char *string_value, const INTEGER& rotate_count)
1971 {
1972 return CHARSTRING(string_value) <<= rotate_count;
1973 }
1974
1975 CHARSTRING operator>>=(const char *string_value, const INTEGER& rotate_count)
1976 {
1977 return CHARSTRING(string_value) >>= rotate_count;
1978 }
1979
1980 // charstring template class
1981
1982 void CHARSTRING_template::clean_up()
1983 {
1984 switch(template_selection) {
1985 case VALUE_LIST:
1986 case COMPLEMENTED_LIST:
1987 delete [] value_list.list_value;
1988 break;
1989 case STRING_PATTERN:
1990 if (pattern_value.regexp_init) regfree(&pattern_value.posix_regexp);
1991 break;
1992 default:
1993 break;
1994 }
1995 template_selection = UNINITIALIZED_TEMPLATE;
1996 }
1997
1998 void CHARSTRING_template::copy_template(const CHARSTRING_template& other_value)
1999 {
2000 switch (other_value.template_selection) {
2001 case STRING_PATTERN:
2002 pattern_value.regexp_init = FALSE;
2003 /* no break */
2004 case SPECIFIC_VALUE:
2005 single_value = other_value.single_value;
2006 break;
2007 case OMIT_VALUE:
2008 case ANY_VALUE:
2009 case ANY_OR_OMIT:
2010 break;
2011 case VALUE_LIST:
2012 case COMPLEMENTED_LIST:
2013 value_list.n_values = other_value.value_list.n_values;
2014 value_list.list_value = new CHARSTRING_template[value_list.n_values];
2015 for (unsigned int i = 0; i < value_list.n_values; i++)
2016 value_list.list_value[i].copy_template(
2017 other_value.value_list.list_value[i]);
2018 break;
2019 case VALUE_RANGE:
2020 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
2021 "not set when copying a charstring value range template.");
2022 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
2023 "not set when copying a charstring value range template.");
2024 value_range = other_value.value_range;
2025 break;
2026 default:
2027 TTCN_error("Copying an uninitialized/unsupported charstring template.");
2028 }
2029 set_selection(other_value);
2030 }
2031
2032 CHARSTRING_template::CHARSTRING_template()
2033 {
2034 }
2035
2036 CHARSTRING_template::CHARSTRING_template(template_sel other_value)
2037 : Restricted_Length_Template(other_value)
2038 {
2039 check_single_selection(other_value);
2040 }
2041
2042 CHARSTRING_template::CHARSTRING_template(const CHARSTRING& other_value)
2043 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
2044 {
2045 }
2046
2047 CHARSTRING_template::CHARSTRING_template(const CHARSTRING_ELEMENT& other_value)
2048 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
2049 {
2050 }
2051
2052 CHARSTRING_template::CHARSTRING_template(const OPTIONAL<CHARSTRING>& other_value)
2053 {
2054 switch (other_value.get_selection()) {
2055 case OPTIONAL_PRESENT:
2056 set_selection(SPECIFIC_VALUE);
2057 single_value = (const CHARSTRING&)other_value;
2058 break;
2059 case OPTIONAL_OMIT:
2060 set_selection(OMIT_VALUE);
2061 break;
2062 default:
2063 TTCN_error("Creating a charstring template from an unbound optional "
2064 "field.");
2065 }
2066 }
2067
2068 CHARSTRING_template::CHARSTRING_template(template_sel p_sel,
2069 const CHARSTRING& p_str)
2070 : Restricted_Length_Template(STRING_PATTERN), single_value(p_str)
2071 {
2072 if(p_sel!=STRING_PATTERN)
2073 TTCN_error("Internal error: Initializing a charstring pattern template "
2074 "with invalid selection.");
2075 pattern_value.regexp_init=FALSE;
2076 }
2077
2078 CHARSTRING_template::CHARSTRING_template(const CHARSTRING_template& other_value)
2079 : Restricted_Length_Template()
2080 {
2081 copy_template(other_value);
2082 }
2083
2084 CHARSTRING_template::~CHARSTRING_template()
2085 {
2086 clean_up();
2087 }
2088
2089 CHARSTRING_template& CHARSTRING_template::operator=(template_sel other_value)
2090 {
2091 check_single_selection(other_value);
2092 clean_up();
2093 set_selection(other_value);
2094 return *this;
2095 }
2096
2097 CHARSTRING_template& CHARSTRING_template::operator=
2098 (const CHARSTRING& other_value)
2099 {
2100 other_value.must_bound("Assignment of an unbound charstring value to a "
2101 "template.");
2102 clean_up();
2103 set_selection(SPECIFIC_VALUE);
2104 single_value = other_value;
2105 return *this;
2106 }
2107
2108 CHARSTRING_template& CHARSTRING_template::operator=
2109 (const CHARSTRING_ELEMENT& other_value)
2110 {
2111 other_value.must_bound("Assignment of an unbound charstring element to a "
2112 "template.");
2113 clean_up();
2114 set_selection(SPECIFIC_VALUE);
2115 single_value = other_value;
2116 return *this;
2117 }
2118
2119 CHARSTRING_template& CHARSTRING_template::operator=
2120 (const OPTIONAL<CHARSTRING>& other_value)
2121 {
2122 clean_up();
2123 switch (other_value.get_selection()) {
2124 case OPTIONAL_PRESENT:
2125 set_selection(SPECIFIC_VALUE);
2126 single_value = (const CHARSTRING&)other_value;
2127 break;
2128 case OPTIONAL_OMIT:
2129 set_selection(OMIT_VALUE);
2130 break;
2131 default:
2132 TTCN_error("Assignment of an unbound optional field to a charstring "
2133 "template.");
2134 }
2135 return *this;
2136 }
2137
2138 CHARSTRING_template& CHARSTRING_template::operator=
2139 (const CHARSTRING_template& other_value)
2140 {
2141 if (&other_value != this) {
2142 clean_up();
2143 copy_template(other_value);
2144 }
2145 return *this;
2146 }
2147
2148 CHARSTRING_ELEMENT CHARSTRING_template::operator[](int index_value)
2149 {
2150 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2151 TTCN_error("Accessing a charstring element of a non-specific charstring "
2152 "template.");
2153 return single_value[index_value];
2154 }
2155
2156 CHARSTRING_ELEMENT CHARSTRING_template::operator[](const INTEGER& index_value)
2157 {
2158 index_value.must_bound("Indexing a charstring template with an unbound "
2159 "integer value.");
2160 return (*this)[(int)index_value];
2161 }
2162
2163 const CHARSTRING_ELEMENT CHARSTRING_template::operator[](int index_value) const
2164 {
2165 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2166 TTCN_error("Accessing a charstring element of a non-specific charstring "
2167 "template.");
2168 return single_value[index_value];
2169 }
2170
2171 const CHARSTRING_ELEMENT CHARSTRING_template::operator[](const INTEGER& index_value) const
2172 {
2173 index_value.must_bound("Indexing a charstring template with an unbound "
2174 "integer value.");
2175 return (*this)[(int)index_value];
2176 }
2177
2178 boolean CHARSTRING_template::match(const CHARSTRING& other_value,
2179 boolean /* legacy */) const
2180 {
2181 if (!other_value.is_bound()) return FALSE;
2182 int value_length = other_value.lengthof();
2183 if (!match_length(value_length)) return FALSE;
2184 switch (template_selection) {
2185 case SPECIFIC_VALUE:
2186 return single_value == other_value;
2187 case STRING_PATTERN: {
2188 if (!pattern_value.regexp_init) {
2189 char *posix_str=TTCN_pattern_to_regexp(single_value);
2190 if(posix_str==NULL) {
2191 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
2192 (const char*)single_value);
2193 }
2194 /*
2195 //TTCN_Logger::begin_event(TTCN_DEBUG);
2196 TTCN_Logger::log_event_str("POSIX ERE equivalent of pattern ");
2197 single_value.log();
2198 TTCN_Logger::log_event(" is: \"%s\"", posix_str);
2199 //TTCN_Logger::end_event();
2200 */
2201 int ret_val=regcomp(&pattern_value.posix_regexp, posix_str,
2202 REG_EXTENDED|REG_NOSUB);
2203 Free(posix_str);
2204 if(ret_val!=0) {
2205 /* regexp error */
2206 char msg[ERRMSG_BUFSIZE];
2207 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
2208 regfree(&pattern_value.posix_regexp);
2209 TTCN_error("Pattern matching error: %s", msg);
2210 }
2211 pattern_value.regexp_init=TRUE;
2212 }
2213 int ret_val=regexec(&pattern_value.posix_regexp, other_value, 0, NULL, 0);
2214 switch (ret_val) {
2215 case 0:
2216 return TRUE;
2217 case REG_NOMATCH:
2218 return FALSE;
2219 default:
2220 /* regexp error */
2221 char msg[ERRMSG_BUFSIZE];
2222 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
2223 TTCN_error("Pattern matching error: %s", msg);
2224 }
2225 break;}
2226 case OMIT_VALUE:
2227 return FALSE;
2228 case ANY_VALUE:
2229 case ANY_OR_OMIT:
2230 return TRUE;
2231 case VALUE_LIST:
2232 case COMPLEMENTED_LIST:
2233 for (unsigned int i = 0; i < value_list.n_values; i++)
2234 if (value_list.list_value[i].match(other_value))
2235 return template_selection == VALUE_LIST;
2236 return template_selection == COMPLEMENTED_LIST;
2237 case VALUE_RANGE: {
2238 if (!value_range.min_is_set) TTCN_error("The lower bound is not set when "
2239 "matching with a charstring value range template.");
2240 if (!value_range.max_is_set) TTCN_error("The upper bound is not set when "
2241 "matching with a charstring value range template.");
2242 if (value_range.min_value > value_range.max_value)
2243 TTCN_error("The lower bound (\"%c\") is greater than the upper bound "
2244 "(\"%c\") when matching with a charstring value range template.",
2245 value_range.min_value, value_range.max_value);
2246 const char *chars_ptr = other_value;
2247 for (int i = 0; i < value_length; i++) {
2248 if (chars_ptr[i] < value_range.min_value ||
2249 chars_ptr[i] > value_range.max_value) return FALSE;
2250 }
2251 return TRUE;
2252 break; }
2253 default:
2254 TTCN_error("Matching with an uninitialized/unsupported charstring "
2255 "template.");
2256 }
2257 return FALSE;
2258 }
2259
2260 const CHARSTRING& CHARSTRING_template::valueof() const
2261 {
2262 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2263 TTCN_error("Performing valueof or send operation on a non-specific "
2264 "charstring template.");
2265 return single_value;
2266 }
2267
2268 int CHARSTRING_template::lengthof() const
2269 {
2270 int min_length;
2271 boolean has_any_or_none;
2272 if (is_ifpresent)
2273 TTCN_error("Performing lengthof() operation on a charstring template "
2274 "which has an ifpresent attribute.");
2275 switch (template_selection)
2276 {
2277 case SPECIFIC_VALUE:
2278 min_length = single_value.lengthof();
2279 has_any_or_none = FALSE;
2280 break;
2281 case OMIT_VALUE:
2282 TTCN_error("Performing lengthof() operation on a charstring template "
2283 "containing omit value.");
2284 case ANY_VALUE:
2285 case ANY_OR_OMIT:
2286 case VALUE_RANGE:
2287 min_length = 0;
2288 has_any_or_none = TRUE; // max. length is infinity
2289 break;
2290 case VALUE_LIST:
2291 {
2292 // error if any element does not have length or the lengths differ
2293 if (value_list.n_values<1)
2294 TTCN_error("Internal error: "
2295 "Performing lengthof() operation on a charstring template "
2296 "containing an empty list.");
2297 int item_length = value_list.list_value[0].lengthof();
2298 for (unsigned int i = 1; i < value_list.n_values; i++) {
2299 if (value_list.list_value[i].lengthof()!=item_length)
2300 TTCN_error("Performing lengthof() operation on a charstring template "
2301 "containing a value list with different lengths.");
2302 }
2303 min_length = item_length;
2304 has_any_or_none = FALSE;
2305 break;
2306 }
2307 case COMPLEMENTED_LIST:
2308 TTCN_error("Performing lengthof() operation on a charstring template "
2309 "containing complemented list.");
2310 case STRING_PATTERN:
2311 TTCN_error("Performing lengthof() operation on a charstring template "
2312 "containing a pattern is not allowed.");
2313 default:
2314 TTCN_error("Performing lengthof() operation on an "
2315 "uninitialized/unsupported charstring template.");
2316 }
2317 return check_section_is_single(min_length, has_any_or_none,
2318 "length", "a", "charstring template");
2319 }
2320
2321 void CHARSTRING_template::set_type(template_sel template_type,
2322 unsigned int list_length)
2323 {
2324 clean_up();
2325 switch (template_type) {
2326 case VALUE_LIST:
2327 case COMPLEMENTED_LIST:
2328 set_selection(template_type);
2329 value_list.n_values = list_length;
2330 value_list.list_value = new CHARSTRING_template[list_length];
2331 break;
2332 case VALUE_RANGE:
2333 set_selection(VALUE_RANGE);
2334 value_range.min_is_set = FALSE;
2335 value_range.max_is_set = FALSE;
2336 break;
2337 default:
2338 TTCN_error("Setting an invalid type for a charstring template.");
2339 }
2340 }
2341
2342 CHARSTRING_template& CHARSTRING_template::list_item(unsigned int list_index)
2343 {
2344 if (template_selection != VALUE_LIST &&
2345 template_selection != COMPLEMENTED_LIST)
2346 TTCN_error("Internal error: Accessing a list element of a non-list "
2347 "charstring template.");
2348 if (list_index >= value_list.n_values)
2349 TTCN_error("Internal error: Index overflow in a charstring value list "
2350 "template.");
2351 return value_list.list_value[list_index];
2352 }
2353
2354 void CHARSTRING_template::set_min(const CHARSTRING& min_value)
2355 {
2356 if (template_selection != VALUE_RANGE)
2357 TTCN_error("Setting the lower bound for a non-range charstring template.");
2358 min_value.must_bound("Setting an unbound value as lower bound in a "
2359 "charstring value range template.");
2360 int length = min_value.lengthof();
2361 if (length != 1) TTCN_error("The length of the lower bound in a "
2362 "charstring value range template must be 1 instead of %d.", length);
2363 value_range.min_is_set = TRUE;
2364 value_range.min_value = *(const char*)min_value;
2365 if (value_range.max_is_set && value_range.min_value > value_range.max_value)
2366 TTCN_error("The lower bound (\"%c\") in a charstring value range template "
2367 "is greater than the upper bound (\"%c\").", value_range.min_value,
2368 value_range.max_value);
2369 }
2370
2371 void CHARSTRING_template::set_max(const CHARSTRING& max_value)
2372 {
2373 if (template_selection != VALUE_RANGE)
2374 TTCN_error("Setting the upper bound for a non-range charstring template.");
2375 max_value.must_bound("Setting an unbound value as upper bound in a "
2376 "charstring value range template.");
2377 int length = max_value.lengthof();
2378 if (length != 1) TTCN_error("The length of the upper bound in a "
2379 "charstring value range template must be 1 instead of %d.", length);
2380 value_range.max_is_set = TRUE;
2381 value_range.max_value = *(const char*)max_value;
2382 if (value_range.min_is_set && value_range.min_value > value_range.max_value)
2383 TTCN_error("The upper bound (\"%c\") in a charstring value range template "
2384 "is smaller than the lower bound (\"%c\").", value_range.max_value,
2385 value_range.min_value);
2386 }
2387
2388 void CHARSTRING_template::log_pattern(int n_chars, const char *chars_ptr)
2389 {
2390 TTCN_Logger::log_event_str("pattern \"");
2391 enum { INITIAL, BACKSLASH, BACKSLASH_Q, QUADRUPLE, HASHMARK, REPETITIONS }
2392 state = INITIAL;
2393 for (int i = 0; i < n_chars; i++) {
2394 unsigned char c = chars_ptr[i];
2395 // print the character
2396 if (isprint(c)) {
2397 switch (c) {
2398 case '"':
2399 TTCN_Logger::log_event_str("\\\"");
2400 break;
2401 case '{':
2402 if (state == BACKSLASH || state == BACKSLASH_Q)
2403 TTCN_Logger::log_char('{');
2404 else TTCN_Logger::log_event_str("\\{");
2405 break;
2406 case '}':
2407 if (state == BACKSLASH || state == QUADRUPLE)
2408 TTCN_Logger::log_char('}');
2409 else TTCN_Logger::log_event_str("\\}");
2410 break;
2411 case ' ':
2412 if (state != INITIAL && state != BACKSLASH) break;
2413 // no break
2414 default:
2415 TTCN_Logger::log_char(c);
2416 break;
2417 }
2418 } else {
2419 switch (c) {
2420 case '\t':
2421 if (state == INITIAL || state == BACKSLASH)
2422 TTCN_Logger::log_event_str("\\t");
2423 break;
2424 case '\r':
2425 if (state == INITIAL || state == BACKSLASH)
2426 TTCN_Logger::log_event_str("\\r");
2427 break;
2428 case '\n':
2429 case '\v':
2430 case '\f':
2431 if (state != INITIAL && state != BACKSLASH) break;
2432 // no break
2433 default:
2434 TTCN_Logger::log_event("\\q{0,0,0,%u}", c);
2435 break;
2436 }
2437 }
2438 // update the state
2439 switch (state) {
2440 case INITIAL:
2441 switch (c) {
2442 case '\\':
2443 state = BACKSLASH;
2444 break;
2445 case '#':
2446 state = HASHMARK;
2447 break;
2448 default:
2449 break;
2450 }
2451 break;
2452 case BACKSLASH:
2453 if (c == 'q') state = BACKSLASH_Q;
2454 else state = INITIAL;
2455 break;
2456 case BACKSLASH_Q:
2457 switch (c) {
2458 case '{':
2459 state = QUADRUPLE;
2460 break;
2461 case ' ':
2462 case '\t':
2463 case '\r':
2464 case '\n':
2465 case '\v':
2466 case '\f':
2467 break;
2468 default:
2469 state = INITIAL;
2470 break;
2471 }
2472 break;
2473 case HASHMARK:
2474 switch (c) {
2475 case '(':
2476 state = REPETITIONS;
2477 break;
2478 case ' ':
2479 case '\t':
2480 case '\r':
2481 case '\n':
2482 case '\v':
2483 case '\f':
2484 break;
2485 default:
2486 state = INITIAL;
2487 break;
2488 }
2489 break;
2490 case QUADRUPLE:
2491 case REPETITIONS:
2492 switch (c) {
2493 case ' ':
2494 case '\t':
2495 case '\r':
2496 case '\n':
2497 case '\v':
2498 case '\f':
2499 case ',':
2500 break;
2501 default:
2502 if (!isdigit(c)) state = INITIAL;
2503 break;
2504 }
2505 break;
2506 }
2507 }
2508 TTCN_Logger::log_char('"');
2509 }
2510
2511 void CHARSTRING_template::log() const
2512 {
2513 switch (template_selection) {
2514 case STRING_PATTERN:
2515 log_pattern(single_value.lengthof(), (const char*)single_value);
2516 break;
2517 case SPECIFIC_VALUE:
2518 single_value.log();
2519 break;
2520 case COMPLEMENTED_LIST:
2521 TTCN_Logger::log_event_str("complement ");
2522 // no break
2523 case VALUE_LIST:
2524 TTCN_Logger::log_char('(');
2525 for (unsigned int i = 0; i < value_list.n_values; i++) {
2526 if (i > 0) TTCN_Logger::log_event_str(", ");
2527 value_list.list_value[i].log();
2528 }
2529 TTCN_Logger::log_char(')');
2530 break;
2531 case VALUE_RANGE:
2532 TTCN_Logger::log_char('(');
2533 if (value_range.min_is_set) {
2534 if (TTCN_Logger::is_printable(value_range.min_value)) {
2535 TTCN_Logger::log_char('"');
2536 TTCN_Logger::log_char_escaped(value_range.min_value);
2537 TTCN_Logger::log_char('"');
2538 } else TTCN_Logger::log_event("char(0, 0, 0, %u)",
2539 (unsigned char)value_range.min_value);
2540 } else TTCN_Logger::log_event_str("<unknown lower bound>");
2541 TTCN_Logger::log_event_str(" .. ");
2542 if (value_range.max_is_set) {
2543 if (TTCN_Logger::is_printable(value_range.max_value)) {
2544 TTCN_Logger::log_char('"');
2545 TTCN_Logger::log_char_escaped(value_range.max_value);
2546 TTCN_Logger::log_char('"');
2547 } else TTCN_Logger::log_event("char(0, 0, 0, %u)",
2548 (unsigned char)value_range.max_value);
2549 } else TTCN_Logger::log_event_str("<unknown upper bound>");
2550 TTCN_Logger::log_char(')');
2551 break;
2552 default:
2553 log_generic();
2554 }
2555 log_restricted();
2556 log_ifpresent();
2557 }
2558
2559 void CHARSTRING_template::log_match(const CHARSTRING& match_value,
2560 boolean /* legacy */) const
2561 {
2562 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
2563 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
2564 TTCN_Logger::print_logmatch_buffer();
2565 TTCN_Logger::log_event_str(" := ");
2566 }
2567 match_value.log();
2568 TTCN_Logger::log_event_str(" with ");
2569 log();
2570 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
2571 else TTCN_Logger::log_event_str(" unmatched");
2572 }
2573
2574 void CHARSTRING_template::set_param(Module_Param& param) {
2575 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "charstring template");
2576 Module_Param_Ptr mp = &param;
2577 if (param.get_type() == Module_Param::MP_Reference) {
2578 mp = param.get_referenced_param();
2579 }
2580 switch (mp->get_type()) {
2581 case Module_Param::MP_Omit:
2582 *this = OMIT_VALUE;
2583 break;
2584 case Module_Param::MP_Any:
2585 *this = ANY_VALUE;
2586 break;
2587 case Module_Param::MP_AnyOrNone:
2588 *this = ANY_OR_OMIT;
2589 break;
2590 case Module_Param::MP_List_Template:
2591 case Module_Param::MP_ComplementList_Template: {
2592 CHARSTRING_template temp;
2593 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
2594 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
2595 for (size_t i=0; i<mp->get_size(); i++) {
2596 temp.list_item(i).set_param(*mp->get_elem(i));
2597 }
2598 *this = temp;
2599 break; }
2600 case Module_Param::MP_Charstring:
2601 *this = CHARSTRING(mp->get_string_size(), (char*)mp->get_string_data());
2602 break;
2603 case Module_Param::MP_StringRange: {
2604 universal_char lower_uchar = mp->get_lower_uchar();
2605 universal_char upper_uchar = mp->get_upper_uchar();
2606 if (!lower_uchar.is_char()) param.error("Lower bound of char range cannot be a multiple-byte character");
2607 if (!upper_uchar.is_char()) param.error("Upper bound of char range cannot be a multiple-byte character");
2608 clean_up();
2609 set_selection(VALUE_RANGE);
2610 value_range.min_is_set = TRUE;
2611 value_range.max_is_set = TRUE;
2612 value_range.min_value = (char)(lower_uchar.uc_cell);
2613 value_range.max_value = (char)(upper_uchar.uc_cell);
2614 } break;
2615 case Module_Param::MP_Pattern:
2616 clean_up();
2617 single_value = CHARSTRING(mp->get_pattern());
2618 pattern_value.regexp_init = FALSE;
2619 set_selection(STRING_PATTERN);
2620 break;
2621 case Module_Param::MP_Expression:
2622 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
2623 // only allow string patterns for the first operand
2624 CHARSTRING operand1, operand2, result;
2625 boolean is_pattern = operand1.set_param_internal(*mp->get_operand1(), TRUE);
2626 operand2.set_param(*mp->get_operand2());
2627 result = operand1 + operand2;
2628 if (is_pattern) {
2629 clean_up();
2630 single_value = result;
2631 pattern_value.regexp_init = FALSE;
2632 set_selection(STRING_PATTERN);
2633 }
2634 else {
2635 *this = result;
2636 }
2637 }
2638 else {
2639 param.expr_type_error("a charstring");
2640 }
2641 break;
2642 default:
2643 param.type_error("charstring template");
2644 }
2645 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
2646 if (param.get_length_restriction() != NULL) {
2647 set_length_range(param);
2648 }
2649 else {
2650 set_length_range(*mp);
2651 }
2652 }
2653
2654 Module_Param* CHARSTRING_template::get_param(Module_Param_Name& param_name) const
2655 {
2656 Module_Param* mp = NULL;
2657 switch (template_selection) {
2658 case UNINITIALIZED_TEMPLATE:
2659 mp = new Module_Param_Unbound();
2660 break;
2661 case OMIT_VALUE:
2662 mp = new Module_Param_Omit();
2663 break;
2664 case ANY_VALUE:
2665 mp = new Module_Param_Any();
2666 break;
2667 case ANY_OR_OMIT:
2668 mp = new Module_Param_AnyOrNone();
2669 break;
2670 case SPECIFIC_VALUE:
2671 mp = single_value.get_param(param_name);
2672 break;
2673 case VALUE_LIST:
2674 case COMPLEMENTED_LIST: {
2675 if (template_selection == VALUE_LIST) {
2676 mp = new Module_Param_List_Template();
2677 }
2678 else {
2679 mp = new Module_Param_ComplementList_Template();
2680 }
2681 for (size_t i = 0; i < value_list.n_values; ++i) {
2682 mp->add_elem(value_list.list_value[i].get_param(param_name));
2683 }
2684 break; }
2685 case VALUE_RANGE: {
2686 universal_char lower_bound = { 0, 0, 0, (unsigned char)value_range.min_value };
2687 universal_char upper_bound = { 0, 0, 0, (unsigned char)value_range.max_value };
2688 mp = new Module_Param_StringRange(lower_bound, upper_bound);
2689 break; }
2690 case STRING_PATTERN:
2691 mp = new Module_Param_Pattern(mcopystr(single_value));
2692 break;
2693 default:
2694 break;
2695 }
2696 if (is_ifpresent) {
2697 mp->set_ifpresent();
2698 }
2699 mp->set_length_restriction(get_length_range());
2700 return mp;
2701 }
2702
2703 void CHARSTRING_template::encode_text(Text_Buf& text_buf) const
2704 {
2705 encode_text_restricted(text_buf);
2706 switch (template_selection) {
2707 case OMIT_VALUE:
2708 case ANY_VALUE:
2709 case ANY_OR_OMIT:
2710 break;
2711 case SPECIFIC_VALUE:
2712 case STRING_PATTERN:
2713 single_value.encode_text(text_buf);
2714 break;
2715 case VALUE_LIST:
2716 case COMPLEMENTED_LIST:
2717 text_buf.push_int(value_list.n_values);
2718 for (unsigned int i = 0; i < value_list.n_values; i++)
2719 value_list.list_value[i].encode_text(text_buf);
2720 break;
2721 case VALUE_RANGE:
2722 if (!value_range.min_is_set) TTCN_error("Text encoder: The lower bound is "
2723 "not set in a charstring value range template.");
2724 if (!value_range.max_is_set) TTCN_error("Text encoder: The upper bound is "
2725 "not set in a charstring value range template.");
2726 text_buf.push_raw(1, &value_range.min_value);
2727 text_buf.push_raw(1, &value_range.max_value);
2728 break;
2729 default:
2730 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2731 "charstring template.");
2732 }
2733 }
2734
2735 void CHARSTRING_template::decode_text(Text_Buf& text_buf)
2736 {
2737 clean_up();
2738 decode_text_restricted(text_buf);
2739 switch (template_selection) {
2740 case OMIT_VALUE:
2741 case ANY_VALUE:
2742 case ANY_OR_OMIT:
2743 break;
2744 case STRING_PATTERN:
2745 pattern_value.regexp_init=FALSE;
2746 /* no break */
2747 case SPECIFIC_VALUE:
2748 single_value.decode_text(text_buf);
2749 break;
2750 case VALUE_LIST:
2751 case COMPLEMENTED_LIST:
2752 value_list.n_values = text_buf.pull_int().get_val();
2753 value_list.list_value = new CHARSTRING_template[value_list.n_values];
2754 for (unsigned int i = 0; i < value_list.n_values; i++)
2755 value_list.list_value[i].decode_text(text_buf);
2756 break;
2757 case VALUE_RANGE:
2758 text_buf.pull_raw(1, &value_range.min_value);
2759 text_buf.pull_raw(1, &value_range.max_value);
2760 if (value_range.min_value > value_range.max_value)
2761 TTCN_error("Text decoder: The received lower bound is greater than the "
2762 "upper bound in a charstring value range template.");
2763 value_range.min_is_set = TRUE;
2764 value_range.max_is_set = TRUE;
2765 break;
2766 default:
2767 TTCN_error("Text decoder: An unknown/unsupported selection was "
2768 "received for a charstring template.");
2769 }
2770 }
2771
2772 boolean CHARSTRING_template::is_present(boolean legacy /* = FALSE */) const
2773 {
2774 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
2775 return !match_omit(legacy);
2776 }
2777
2778 boolean CHARSTRING_template::match_omit(boolean legacy /* = FALSE */) const
2779 {
2780 if (is_ifpresent) return TRUE;
2781 switch (template_selection) {
2782 case OMIT_VALUE:
2783 case ANY_OR_OMIT:
2784 return TRUE;
2785 case VALUE_LIST:
2786 case COMPLEMENTED_LIST:
2787 if (legacy) {
2788 // legacy behavior: 'omit' can appear in the value/complement list
2789 for (unsigned int i=0; i<value_list.n_values; i++)
2790 if (value_list.list_value[i].match_omit())
2791 return template_selection==VALUE_LIST;
2792 return template_selection==COMPLEMENTED_LIST;
2793 }
2794 // else fall through
2795 default:
2796 return FALSE;
2797 }
2798 return FALSE;
2799 }
2800
2801 #ifndef TITAN_RUNTIME_2
2802 void CHARSTRING_template::check_restriction(template_res t_res, const char* t_name,
2803 boolean legacy /* = FALSE */) const
2804 {
2805 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2806 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2807 case TR_VALUE:
2808 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
2809 break;
2810 case TR_OMIT:
2811 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
2812 template_selection==SPECIFIC_VALUE)) return;
2813 break;
2814 case TR_PRESENT:
2815 if (!match_omit(legacy)) return;
2816 break;
2817 default:
2818 return;
2819 }
2820 TTCN_error("Restriction `%s' on template of type %s violated.",
2821 get_res_name(t_res), t_name ? t_name : "charstring");
2822 }
2823 #endif
2824
2825 const CHARSTRING& CHARSTRING_template::get_single_value() const {
2826 switch (template_selection) {
2827 case STRING_PATTERN:
2828 case SPECIFIC_VALUE:
2829 break;
2830 default:
2831 TTCN_error("This template does not have single value.");
2832 }
2833 return single_value;
2834 }
This page took 0.094191 seconds and 5 git commands to generate.