Sync with 5.2.0
[deliverable/titan.core.git] / core / Charstring.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "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 void CHARSTRING::set_param(Module_Param& param) {
630 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "charstring value");
631
632 switch (param.get_type()) {
633 case Module_Param::MP_Universal_Charstring:
634 case Module_Param::MP_Charstring:
635 switch (param.get_operation_type()) {
636 case Module_Param::OT_ASSIGN:
637 clean_up();
638 // no break
639 case Module_Param::OT_CONCAT: {
640 // The universal charstring will decode the string value if it is UTF-8 encoded
641 UNIVERSAL_CHARSTRING ucs;
642 ucs.set_param(param);
643 if (ucs.charstring) {
644 // No special characters were found
645 if (is_bound()) {
646 *this = *this + ucs.cstr;
647 } else {
648 *this = ucs.cstr;
649 }
650 } else {
651 // Special characters found -> check if the UTF-8 decoding resulted in any multi-byte characters
652 for (int i = 0; i < ucs.val_ptr->n_uchars; ++i) {
653 if (0 != ucs.val_ptr->uchars_ptr[i].uc_group ||
654 0 != ucs.val_ptr->uchars_ptr[i].uc_plane ||
655 0 != ucs.val_ptr->uchars_ptr[i].uc_row) {
656 param.error("Type mismatch: a charstring value without multi-octet characters was expected.");
657 }
658 }
659 CHARSTRING new_cs(ucs.val_ptr->n_uchars);
660 for (int i = 0; i < ucs.val_ptr->n_uchars; ++i) {
661 new_cs.val_ptr->chars_ptr[i] = ucs.val_ptr->uchars_ptr[i].uc_cell;
662 }
663 if (is_bound()) {
664 *this = *this + new_cs;
665 } else {
666 *this = new_cs;
667 }
668 }
669 break; }
670 default:
671 TTCN_error("Internal error: CHARSTRING::set_param()");
672 }
673 break;
674 default:
675 param.type_error("charstring value");
676 }
677 }
678
679 void CHARSTRING::encode_text(Text_Buf& text_buf) const
680 {
681 must_bound("Text encoder: Encoding an unbound charstring value.");
682 int n_chars = val_ptr->n_chars;
683 text_buf.push_int(n_chars);
684 if (n_chars > 0) text_buf.push_raw(n_chars, val_ptr->chars_ptr);
685 }
686
687 void CHARSTRING::decode_text(Text_Buf& text_buf)
688 {
689 int n_chars = text_buf.pull_int().get_val();
690 if (n_chars < 0)
691 TTCN_error("Text decoder: invalid length of a charstring.");
692 clean_up();
693 init_struct(n_chars);
694 if (n_chars > 0) text_buf.pull_raw(n_chars, val_ptr->chars_ptr);
695 }
696
697 void CHARSTRING::encode(const TTCN_Typedescriptor_t& p_td,
698 TTCN_Buffer& p_buf,
699 TTCN_EncDec::coding_t p_coding, ...) const
700 {
701 va_list pvar;
702 va_start(pvar, p_coding);
703 switch(p_coding) {
704 case TTCN_EncDec::CT_BER: {
705 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
706 unsigned BER_coding=va_arg(pvar, unsigned);
707 BER_encode_chk_coding(BER_coding);
708 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
709 tlv->put_in_buffer(p_buf);
710 ASN_BER_TLV_t::destruct(tlv);
711 break;}
712 case TTCN_EncDec::CT_RAW: {
713 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
714 if(!p_td.raw)
715 TTCN_EncDec_ErrorContext::error_internal
716 ("No RAW descriptor available for type '%s'.", p_td.name);
717 RAW_enc_tr_pos rp;
718 rp.level=0;
719 rp.pos=NULL;
720 RAW_enc_tree root(TRUE,NULL,&rp,1,p_td.raw);
721 RAW_encode(p_td, root);
722 root.put_to_buf(p_buf);
723 break;}
724 case TTCN_EncDec::CT_TEXT: {
725 TTCN_EncDec_ErrorContext ec("While TEXT-encoding type '%s': ", p_td.name);
726 if(!p_td.text)
727 TTCN_EncDec_ErrorContext::error_internal
728 ("No TEXT descriptor available for type '%s'.", p_td.name);
729 TEXT_encode(p_td,p_buf);
730 break;}
731 case TTCN_EncDec::CT_XER: {
732 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
733 unsigned XER_coding=va_arg(pvar, unsigned);
734 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
735 p_buf.put_c('\n');
736 break;}
737 case TTCN_EncDec::CT_JSON: {
738 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
739 if(!p_td.json)
740 TTCN_EncDec_ErrorContext::error_internal
741 ("No JSON descriptor available for type '%s'.", p_td.name);
742 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
743 JSON_encode(p_td, tok);
744 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
745 break;}
746 default:
747 TTCN_error("Unknown coding method requested to encode type '%s'",
748 p_td.name);
749 }
750 va_end(pvar);
751 }
752
753 void CHARSTRING::decode(const TTCN_Typedescriptor_t& p_td,
754 TTCN_Buffer& p_buf,
755 TTCN_EncDec::coding_t p_coding, ...)
756 {
757 va_list pvar;
758 va_start(pvar, p_coding);
759 switch(p_coding) {
760 case TTCN_EncDec::CT_BER: {
761 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
762 unsigned L_form=va_arg(pvar, unsigned);
763 ASN_BER_TLV_t tlv;
764 BER_decode_str2TLV(p_buf, tlv, L_form);
765 BER_decode_TLV(p_td, tlv, L_form);
766 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
767 break;}
768 case TTCN_EncDec::CT_RAW: {
769 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
770 if(!p_td.raw)
771 TTCN_EncDec_ErrorContext::error_internal
772 ("No RAW descriptor available for type '%s'.", p_td.name);
773 raw_order_t order;
774 switch(p_td.raw->top_bit_order){
775 case TOP_BIT_LEFT:
776 order=ORDER_LSB;
777 break;
778 case TOP_BIT_RIGHT:
779 default:
780 order=ORDER_MSB;
781 }
782 if(RAW_decode(p_td, p_buf, p_buf.get_len()*8, order)<0)
783 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
784 "Can not decode type '%s', because invalid or incomplete"
785 " message was received"
786 , p_td.name);
787 break;}
788 case TTCN_EncDec::CT_TEXT: {
789 Limit_Token_List limit;
790 TTCN_EncDec_ErrorContext ec("While TEXT-decoding type '%s': ", p_td.name);
791 if(!p_td.text)
792 TTCN_EncDec_ErrorContext::error_internal
793 ("No TEXT descriptor available for type '%s'.", p_td.name);
794 const unsigned char *b=p_buf.get_data();
795 if(b[p_buf.get_len()-1]!='\0'){
796 p_buf.set_pos(p_buf.get_len());
797 p_buf.put_zero(8,ORDER_LSB);
798 p_buf.rewind();
799 }
800 if(TEXT_decode(p_td,p_buf,limit)<0)
801 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
802 "Can not decode type '%s', because invalid or incomplete"
803 " message was received"
804 , p_td.name);
805 break;}
806 case TTCN_EncDec::CT_XER: {
807 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
808 unsigned XER_coding=va_arg(pvar, unsigned);
809 XmlReaderWrap reader(p_buf);
810 int success = reader.Read();
811 for (; success==1; success=reader.Read()) {
812 int type = reader.NodeType();
813 if (type==XML_READER_TYPE_ELEMENT)
814 break;
815 }
816 XER_decode(*p_td.xer, reader, XER_coding, 0);
817 size_t bytes = reader.ByteConsumed();
818 p_buf.set_pos(bytes);
819 break;}
820 case TTCN_EncDec::CT_JSON: {
821 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
822 if(!p_td.json)
823 TTCN_EncDec_ErrorContext::error_internal
824 ("No JSON descriptor available for type '%s'.", p_td.name);
825 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
826 if(JSON_decode(p_td, tok, false)<0)
827 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
828 "Can not decode type '%s', because invalid or incomplete"
829 " message was received"
830 , p_td.name);
831 p_buf.set_pos(tok.get_buf_pos());
832 break;}
833 default:
834 TTCN_error("Unknown coding method requested to decode type '%s'",
835 p_td.name);
836 }
837 va_end(pvar);
838 }
839
840 ASN_BER_TLV_t*
841 CHARSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
842 unsigned p_coding) const
843 {
844 BER_chk_descr(p_td);
845 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
846 if(!new_tlv) {
847 new_tlv=BER_encode_TLV_OCTETSTRING
848 (p_coding, val_ptr->n_chars,
849 (const unsigned char*)val_ptr->chars_ptr);
850 }
851 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
852 return new_tlv;
853 }
854
855 boolean CHARSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
856 const ASN_BER_TLV_t& p_tlv,
857 unsigned L_form)
858 {
859 clean_up();
860 BER_chk_descr(p_td);
861 ASN_BER_TLV_t stripped_tlv;
862 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
863 TTCN_EncDec_ErrorContext ec("While decoding CHARSTRING type: ");
864 /* Upper estimation for the length. */
865 size_t stripped_tlv_len = stripped_tlv.get_len();
866 if (stripped_tlv_len < 2) return FALSE;
867 int max_len = stripped_tlv_len - 2;
868 init_struct(max_len);
869 unsigned int octetnum_start = 0;
870 BER_decode_TLV_OCTETSTRING(stripped_tlv, L_form, octetnum_start,
871 val_ptr->n_chars,
872 (unsigned char*)val_ptr->chars_ptr);
873 if (val_ptr->n_chars < max_len) {
874 if (val_ptr->n_chars == 0) {
875 clean_up();
876 init_struct(0);
877 } else {
878 val_ptr = (charstring_struct*)
879 Realloc(val_ptr, MEMORY_SIZE(val_ptr->n_chars));
880 val_ptr->chars_ptr[val_ptr->n_chars] = '\0';
881 }
882 }
883 return TRUE;
884 }
885
886 int CHARSTRING::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
887 TTCN_Buffer& buff, Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
888 {
889 int decoded_length = 0;
890 int str_len = 0;
891 clean_up();
892 if (p_td.text->begin_decode) {
893 int tl;
894 if ((tl = p_td.text->begin_decode->match_begin(buff)) < 0) {
895 if (no_err) return -1;
896 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
897 "The specified token '%s' not found for '%s': ",
898 (const char*) *(p_td.text->begin_decode), p_td.name);
899 return 0;
900 }
901 decoded_length += tl;
902 buff.increase_pos(tl);
903 }
904 // never return "not enough bits"
905 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
906
907 if (p_td.text->select_token) {
908 int tl;
909 if ((tl = p_td.text->select_token->match_begin(buff)) < 0) {
910 if (no_err) return -1;
911 else tl = 0;
912 }
913 str_len = tl;
914 }
915 else if ( p_td.text->val.parameters
916 && p_td.text->val.parameters->decoding_params.min_length != -1) {
917 str_len = p_td.text->val.parameters->decoding_params.min_length;
918 }
919 else if (p_td.text->end_decode) {
920 int tl;
921 if ((tl = p_td.text->end_decode->match_first(buff)) < 0) {
922 if (no_err) return -1;
923 else tl = 0;
924 }
925 str_len = tl;
926 }
927 else if (limit.has_token()) {
928 int tl;
929 if ((tl = limit.match(buff)) < 0) tl = buff.get_read_len() - 1;
930 str_len = tl;
931 }
932 else {
933 str_len = buff.get_read_len() - 1;
934 }
935
936 init_struct(str_len);
937 memcpy(val_ptr->chars_ptr, buff.get_read_data(), str_len);
938 decoded_length += str_len;
939 buff.increase_pos(str_len);
940
941 if ( p_td.text->val.parameters
942 && p_td.text->val.parameters->decoding_params.convert != 0) {
943 if (p_td.text->val.parameters->decoding_params.convert == 1) {
944 for (int a = 0; a < str_len; a++) {
945 val_ptr->chars_ptr[a] = toupper(val_ptr->chars_ptr[a]);
946 }
947 }
948 else {
949 for (int a = 0; a < str_len; a++) {
950 val_ptr->chars_ptr[a] = tolower(val_ptr->chars_ptr[a]);
951 }
952 }
953 }
954 if (p_td.text->end_decode) {
955 int tl;
956 if ((tl = p_td.text->end_decode->match_begin(buff)) < 0) {
957 if (no_err) return -1;
958 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR,
959 "The specified token '%s' not found for '%s': ",
960 (const char*) *(p_td.text->end_decode), p_td.name);
961 return 0;
962 }
963 decoded_length += tl;
964 buff.increase_pos(tl);
965 }
966 return decoded_length;
967 }
968
969 int CHARSTRING::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
970 TTCN_Buffer& buff) const{
971 int encoded_length=0;
972 if(p_td.text->begin_encode){
973 buff.put_cs(*p_td.text->begin_encode);
974 encoded_length+=p_td.text->begin_encode->lengthof();
975 }
976 if(!is_bound()) {
977 TTCN_EncDec_ErrorContext::error
978 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound value.");
979 if(p_td.text->end_encode){
980 buff.put_cs(*p_td.text->end_encode);
981 encoded_length+=p_td.text->end_encode->lengthof();
982 }
983 return encoded_length;
984 }
985
986 if(p_td.text->val.parameters==NULL){
987 buff.put_cs(*this);
988 encoded_length+=val_ptr->n_chars;
989 } else {
990 int chars_before=0;
991 int chars_after=0;
992 if(val_ptr->n_chars<p_td.text->val.parameters->coding_params.min_length){
993 switch(p_td.text->val.parameters->coding_params.just){
994 case -1: //left
995 chars_after=p_td.text->
996 val.parameters->coding_params.min_length-val_ptr->n_chars;
997 break;
998 case 0:{ // center
999 int pad=p_td.text->
1000 val.parameters->coding_params.min_length-val_ptr->n_chars;
1001 chars_after=pad/2;
1002 chars_before=pad-chars_after;
1003 break;
1004 }
1005 case 1: // right
1006 default:
1007 chars_before=p_td.text->
1008 val.parameters->coding_params.min_length-val_ptr->n_chars;
1009 break;
1010 }
1011 }
1012 if(chars_before){
1013 unsigned char* p=NULL;
1014 size_t len=chars_before;
1015 buff.get_end(p,len);
1016 for(int a=0;a<chars_before;a++) p[a]=(unsigned char)' ';
1017 buff.increase_length(chars_before);
1018 encoded_length+=chars_before;
1019 }
1020
1021 switch(p_td.text->val.parameters->coding_params.convert){
1022 case -1:{ //lower_case
1023 unsigned char* p=NULL;
1024 size_t len=val_ptr->n_chars;
1025 buff.get_end(p,len);
1026 for(int a=0;a<val_ptr->n_chars;a++)
1027 p[a]=(unsigned char)tolower(val_ptr->chars_ptr[a]);
1028 buff.increase_length(val_ptr->n_chars);
1029 break;
1030 }
1031 case 0:{ // no conversion
1032 buff.put_cs(*this);
1033 break;
1034 }
1035 case 1: // upper_case
1036 default:
1037 {
1038 unsigned char* p=NULL;
1039 size_t len=val_ptr->n_chars;
1040 buff.get_end(p,len);
1041 for(int a=0;a<val_ptr->n_chars;a++)
1042 p[a]=(unsigned char)toupper(val_ptr->chars_ptr[a]);
1043 buff.increase_length(val_ptr->n_chars);
1044 break;
1045 }
1046 }
1047 encoded_length+=val_ptr->n_chars;
1048
1049 if(chars_after){
1050 unsigned char* p=NULL;
1051 size_t len=chars_after;
1052 buff.get_end(p,len);
1053 for(int a=0;a<chars_after;a++) p[a]=(unsigned char)' ';
1054 buff.increase_length(chars_after);
1055 encoded_length+=chars_after;
1056 }
1057
1058 }
1059
1060 if(p_td.text->end_encode){
1061 buff.put_cs(*p_td.text->end_encode);
1062 encoded_length+=p_td.text->end_encode->lengthof();
1063 }
1064 return encoded_length;
1065 }
1066
1067 #ifdef TITAN_RUNTIME_2
1068 int CHARSTRING::encode_raw(TTCN_Buffer& p_buf) const
1069 {
1070 p_buf.put_string(*this);
1071 return val_ptr ? val_ptr->n_chars : 0;
1072 }
1073 #endif
1074
1075
1076 void xml_escape(const unsigned int masked_c, TTCN_Buffer& p_buf)
1077 {
1078 size_t len = 6;
1079 // length of the majority of the names of control characters, +3 for </>
1080 static const char *escapes[32] = {
1081 "<nul/>","<soh/>","<stx/>","<etx/>","<eot/>","<enq/>","<ack/>","<bel/>",
1082 "<bs/>" ,"<tab/>","<lf/>" ,"<vt/>" ,"<ff/>" ,"<cr/>" ,"<so/>" ,"<si/>" ,
1083 "<dle/>","<dc1/>","<dc2/>","<dc3/>","<dc4/>","<nak/>","<syn/>","<etb/>",
1084 "<can/>","<em/>" ,"<sub/>","<esc/>","<is4/>","<is3/>","<is2/>","<is1/>",
1085 };
1086 unsigned int c = (masked_c & 0x7FFFFFFF); // unmasked
1087
1088 switch (c) {
1089 // XML's "own" characters, escaped according to X.680/2002, 11.15.4 b)
1090 case '<':
1091 p_buf.put_s(4, (cbyte*)"&lt;");
1092 break;
1093
1094 case '>':
1095 p_buf.put_s(4, (cbyte*)"&gt;");
1096 break;
1097
1098 case '&':
1099 p_buf.put_s(5, (cbyte*)"&amp;");
1100 break;
1101
1102 // Control characters, escaped according to X.680/2002, 11.15.5
1103 case 8: case 11: case 12: case 14: case 15: case 25:
1104 // the name of these control characters has only two letters
1105 --len;
1106 // no break
1107 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
1108 case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
1109 case 24: case 26: case 27: case 28: case 29: case 30: case 31:
1110 // 9=TAB 10=LF 13=CR are absent from this block altogether
1111 p_buf.put_s(len, (cbyte*)escapes[c]);
1112 break;
1113
1114 case '\"': // HR58225
1115 p_buf.put_s(6, (cbyte*)"&quot;");
1116 break;
1117
1118 case '\'': // X.693 20.3.13: Titan uses single quotes for attributes;
1119 // so if they appear in content they must be escaped.
1120 // Currently this happens even if the string is not an attribute.
1121 p_buf.put_s(6, (cbyte*)"&apos;");
1122 break;
1123
1124 case 9: case 10: case 13:
1125 c = masked_c; // put the mask back on (makes it >127)
1126 // no break
1127 default:
1128 if (c > 127) { // XML numeric entity, as in X.680/2002 11.15.8
1129 c &= 0x7FFFFFFF; // take it off again
1130 // Ensure that an even number of hex digits is produced
1131 int width = (1 + (c > 0xFF) + (c > 0xFFFF) + (c > 0xFFFFFF)) << 1;
1132 char escapade[16];
1133 len = snprintf(escapade, 16, "&#x%0*X;", width, c);
1134 p_buf.put_s(len, (cbyte*)(escapade+0));
1135 }
1136 else { // a plain old, unmolested character
1137 p_buf.put_c(c);
1138 }
1139 break;
1140 }
1141 }
1142
1143 // Base64 encoder table
1144 extern const char cb64[]=
1145 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1146
1147 int CHARSTRING::XER_encode(const XERdescriptor_t& p_td,
1148 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
1149 {
1150 if(!is_bound()) {
1151 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1152 "Encoding an unbound character string value.");
1153 }
1154 int exer = is_exer(flavor |= SIMPLE_TYPE);
1155 // SIMPLE_TYPE has no influence on is_exer, we set it for later
1156 int encoded_length=(int)p_buf.get_len();
1157 bool do_empty_element = val_ptr==NULL || val_ptr->n_chars == 0;
1158
1159 flavor &= ~XER_RECOF; // charstring doesn't care
1160
1161 if (do_empty_element && exer && p_td.dfeValue != 0) {
1162 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_REPR,
1163 "An encoded value with DEFAULT-FOR-EMPTY instruction applied should not be empty");
1164 }
1165 if (begin_xml(p_td, p_buf, flavor, indent, do_empty_element) == -1) {
1166 --encoded_length; // it was shortened by one
1167 }
1168
1169 if (!do_empty_element) {
1170 const char * current = val_ptr->chars_ptr;
1171 const char * const end = val_ptr->chars_ptr + val_ptr->n_chars;
1172 const char * to_escape;
1173 unsigned int mask;
1174 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1175 to_escape = "<&>'\"\x09\x0A\x0D";
1176 mask = 0x80000000; // guaranteed bigger than any Unicode character
1177 }
1178 else {
1179 to_escape = "<&>'\"";
1180 mask = 0;
1181 }
1182
1183 // If Base64 is needed, use a temporary buffer.
1184 TTCN_Buffer tmpbuf, &rbuf = (exer && (p_td.xer_bits & BASE_64)) ? tmpbuf : p_buf;
1185
1186 // This here is an optimization. Only &lt;&amp;&gt; need to be escaped.
1187 // Contiguous runs of "ordinary" characters are put in the buffer
1188 // with a single call.
1189 // TODO: is it really faster ? strpbrk is probably O(nm)
1190 while ( const char * trouble = strpbrk(current, to_escape) ) {
1191 rbuf.put_s((size_t)(trouble - current), (cbyte*)current);
1192 xml_escape(*trouble | mask, rbuf); // escape the troublesome character
1193 current = trouble+1;
1194 }
1195
1196 // put the remainder in the buffer
1197 rbuf.put_s( (size_t)(end - current), (cbyte*)current);
1198
1199 if (exer && (p_td.xer_bits & BASE_64)) {
1200 size_t clear_len = tmpbuf.get_len(); // the length before padding
1201 // Pad the temporary buffer so i+1 and i+2 don't go outside the buffer
1202 unsigned char zero[2] = {0,0};
1203 tmpbuf.put_s(2, zero);
1204 // Get the buffer after the possible realloc caused by the padding.
1205 cbyte * in = tmpbuf.get_data();
1206
1207 // Encode 3 bytes of cleartext into 4 bytes of Base64
1208 for (size_t i = 0; i < clear_len; i += 3) {
1209 p_buf.put_c( cb64[ in[i] >> 2 ] );
1210 p_buf.put_c( cb64[ ((in[i] & 0x03) << 4) | ((in[i+1] & 0xf0) >> 4) ]);
1211 p_buf.put_c( i+1 < clear_len
1212 ? cb64[ ((in[i+1] & 0x0f) << 2) | ((in[i+2] & 0xc0) >> 6) ]
1213 : '=' );
1214 p_buf.put_c( i+2 < clear_len ? cb64[ in[i+2] & 0x3f ] : '=' );
1215 } // next i
1216 } // if base64
1217 }
1218
1219 end_xml(p_td, p_buf, flavor, indent, do_empty_element);
1220 return (int)p_buf.get_len() - encoded_length;
1221 }
1222
1223 /**
1224 * Translates a Base64 value to either its 6-bit reconstruction value
1225 * or a negative number indicating some other meaning.
1226 * Public domain from http://iharder.net/base64 */
1227 char base64_decoder_table[256] =
1228 {
1229 -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
1230 -5,-5, // Whitespace: Tab and Linefeed
1231 -9,-9, // Decimal 11 - 12
1232 -5, // Whitespace: Carriage Return
1233 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26
1234 -9,-9,-9,-9,-9, // Decimal 27 - 31
1235 -5, // Whitespace: Space
1236 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42
1237 62, // Plus sign at decimal 43
1238 -9,-9,-9, // Decimal 44 - 46
1239 63, // Slash at decimal 47
1240 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine
1241 -9,-9,-9, // Decimal 58 - 60
1242 -1, // Equals sign at decimal 61
1243 -9,-9,-9, // Decimal 62 - 64
1244 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N'
1245 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z'
1246 -9,-9,-9,-9,-9,-9, // Decimal 91 - 96
1247 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm'
1248 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z'
1249 -9,-9,-9,-9,-9 // Decimal 123 - 127
1250 ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139
1251 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152
1252 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165
1253 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178
1254 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191
1255 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204
1256 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217
1257 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230
1258 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
1259 -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255
1260 };
1261
1262 unsigned int xlate(cbyte*in, int phase, unsigned char*dest) {
1263 static unsigned char nbytes[4] = { 3,1,1,2 };
1264 unsigned char out[4];
1265 out[0] = in[0] << 2 | in[1] >> 4;
1266 out[1] = in[1] << 4 | in[2] >> 2;
1267 out[2] = in[2] << 6 | in[3] >> 0;
1268 memcpy(dest, out, nbytes[phase]);
1269 return nbytes[phase];
1270 }
1271
1272 int CHARSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
1273 unsigned int flavor, embed_values_dec_struct_t*) {
1274 int exer = is_exer(flavor);
1275 int success = reader.Ok(), depth = -1;
1276
1277 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1278 const char * name = verify_name(reader, p_td, exer);
1279 (void)name;
1280 const char * value = (const char *)reader.Value();
1281 // FIXME copy & paste
1282 *this = value;
1283
1284 // Let the caller do reader.AdvanceAttribute();
1285 }
1286 else {
1287 bool omit_tag = exer
1288 && (p_td.xer_bits & UNTAGGED || flavor & (EMBED_VALUES|XER_LIST|USE_TYPE_ATTR|USE_NIL));
1289 for (; success == 1; success = reader.Read()) {
1290 int type = reader.NodeType();
1291 if (XML_READER_TYPE_ELEMENT == type) {
1292 verify_name(reader, p_td, exer);
1293 if (reader.IsEmptyElement()) { // has no text, needs special processing
1294 if (exer && p_td.dfeValue != 0) {
1295 *this = *static_cast<const CHARSTRING*>(p_td.dfeValue);
1296 }
1297 else init_struct(0);
1298 reader.Read();
1299 break; // exit the loop early
1300 } // if empty element
1301 // otherwise, not an empty element, stay in the loop
1302 depth = reader.Depth();
1303 }
1304 else if ((depth != -1 || omit_tag)
1305 && (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_CDATA == type))
1306 // Process #text node if we already processed the element node, or
1307 // there is no element node because UNTAGGED is in effect.
1308 {
1309 const xmlChar * value = reader.Value();
1310 size_t num_chars = strlen((const char*)value);
1311
1312 if (exer && (p_td.xer_bits & BASE_64)) {
1313 clean_up();
1314 init_struct(num_chars * 3 / 4);
1315 xmlChar in[4];
1316
1317 int phase = 0;
1318 unsigned char * dest = (unsigned char *)val_ptr->chars_ptr;
1319
1320 for (size_t o=0; o<num_chars; ++o) {
1321 xmlChar c = value[o];
1322 if(c == '=') { // Padding starts; decode last chunk and exit.
1323 dest += xlate(in,phase, dest);
1324 break;
1325 }
1326
1327 int val = base64_decoder_table[c];
1328 if(val >= 0) {
1329 in[phase] = val;
1330 phase = (phase + 1) % 4;
1331 if(phase == 0) {
1332 dest += xlate(in,phase, dest);
1333 in[0]=in[1]=in[2]=in[3]=0;
1334 }
1335 }
1336 else if (exer && (flavor & EXIT_ON_ERROR)) {
1337 clean_up();
1338 return -1;
1339 } else {
1340 TTCN_EncDec_ErrorContext::warning(
1341 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
1342 "Invalid character for Base64 '%02X'", c);
1343 }
1344 } // while
1345 // adjust
1346 val_ptr->n_chars = (char*)dest - val_ptr->chars_ptr;
1347 }
1348 else {
1349 clean_up();
1350 init_struct(num_chars);
1351 memcpy(val_ptr->chars_ptr, value, num_chars);
1352 } // if base64
1353
1354 if(!omit_tag) {
1355 // find the end element
1356 for (success = reader.Read(); success == 1; success = reader.Read()) {
1357 type = reader.NodeType();
1358 if (XML_READER_TYPE_END_ELEMENT == type) {
1359 verify_end(reader, p_td, depth, exer);
1360 reader.Read(); // one last time
1361 break;
1362 }
1363 }
1364 }
1365 break;
1366 }
1367 else if (XML_READER_TYPE_END_ELEMENT == type) {
1368 if (!omit_tag) {
1369 verify_end(reader, p_td, depth, exer);
1370 if (!val_ptr) {
1371 // We are at our end tag and no content
1372 if (exer && p_td.dfeValue != 0) {
1373 *this = *static_cast<const CHARSTRING*>(p_td.dfeValue);
1374 }
1375 else init_struct(0); // empty string
1376 }
1377 reader.Read();
1378 }
1379 break;
1380 } // if type
1381 } // next read
1382 } // if attribute
1383
1384 if (exer && p_td.whitespace >= WHITESPACE_REPLACE) { // includes _COLLAPSE
1385 for (int i=0; i<val_ptr->n_chars; ++i) { // first, _REPLACE
1386 switch (val_ptr->chars_ptr[i]) {
1387 case 9: // HORIZONTAL TAB
1388 case 10: // LINE FEED
1389 case 13: // CARRIAGE RETURN
1390 val_ptr->chars_ptr[i] = ' ';
1391 break;
1392 default:
1393 break;
1394 }
1395 } // next i
1396
1397 if (p_td.whitespace >= WHITESPACE_COLLAPSE) {
1398 char *to;
1399 const char *from, *end = val_ptr->chars_ptr + val_ptr->n_chars;
1400 for (from = to = val_ptr->chars_ptr; from < end;) {
1401 *to = *(from++);
1402 // If the copied character (*to) was a space,
1403 // and the next character to be copied (*from) is also a space
1404 // (continuous run of spaces)
1405 // or this was the first character (leading spaces to be trimmed),
1406 // then don't advance the destination (will be overwritten).
1407 if (*to != ' '
1408 || (from < end && *from != ' ' && to > val_ptr->chars_ptr)) ++to;
1409 }
1410 *to = 0;
1411 val_ptr->n_chars = to - val_ptr->chars_ptr; // truncate
1412 // TODO maybe realloc after truncation
1413 } // collapse
1414 } // if WHITESPACE
1415
1416 return 1;
1417 }
1418
1419 int CHARSTRING::RAW_encode(const TTCN_Typedescriptor_t& p_td,
1420 RAW_enc_tree& myleaf) const
1421 {
1422 int bl = val_ptr->n_chars * 8; // bit length
1423 int align_length = p_td.raw->fieldlength ? p_td.raw->fieldlength - bl : 0;
1424 if (!is_bound()) {
1425 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1426 "Encoding an unbound value.");
1427 }
1428 if ((bl + align_length) < val_ptr->n_chars * 8) {
1429 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1430 "There is no sufficient bits to encode '%s': ", p_td.name);
1431 bl = p_td.raw->fieldlength;
1432 align_length = 0;
1433 }
1434 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
1435 myleaf.must_free = FALSE;
1436 myleaf.data_ptr_used = TRUE;
1437 myleaf.body.leaf.data_ptr = (unsigned char*) val_ptr->chars_ptr;
1438 if (p_td.raw->endianness == ORDER_MSB) myleaf.align = -align_length;
1439 else myleaf.align = align_length;
1440 return myleaf.length = bl + align_length;
1441 }
1442
1443 int CHARSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td,
1444 TTCN_Buffer& buff, int limit, raw_order_t top_bit_ord, boolean no_err,
1445 int /*sel_field*/, boolean /*first_call*/)
1446 {
1447 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
1448 limit -= prepaddlength;
1449 int decode_length = p_td.raw->fieldlength == 0
1450 ? (limit / 8) * 8 : p_td.raw->fieldlength;
1451 if ( decode_length > limit
1452 || decode_length > (int) buff.unread_len_bit()) {
1453 if (no_err) return -TTCN_EncDec::ET_LEN_ERR;
1454 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
1455 "There is not enough bits in the buffer to decode type %s.", p_td.name);
1456 decode_length = ((limit > (int) buff.unread_len_bit() ? (int)buff.unread_len_bit() : limit) / 8) * 8;
1457 }
1458 RAW_coding_par cp;
1459 boolean orders = FALSE;
1460 if (p_td.raw->bitorderinoctet == ORDER_MSB) orders = TRUE;
1461 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1462 cp.bitorder = orders ? ORDER_MSB : ORDER_LSB;
1463 orders = FALSE;
1464 if (p_td.raw->byteorder == ORDER_MSB) orders = TRUE;
1465 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
1466 cp.byteorder = orders ? ORDER_MSB : ORDER_LSB;
1467 cp.fieldorder = p_td.raw->fieldorder;
1468 cp.hexorder = ORDER_LSB;
1469 clean_up();
1470 init_struct(decode_length / 8);
1471 buff.get_b((size_t) decode_length, (unsigned char*) val_ptr->chars_ptr, cp,
1472 top_bit_ord);
1473
1474 if (p_td.raw->length_restrition != -1) {
1475 val_ptr->n_chars = p_td.raw->length_restrition;
1476 if (p_td.raw->endianness == ORDER_MSB) memmove(val_ptr->chars_ptr,
1477 val_ptr->chars_ptr + (decode_length / 8 - val_ptr->n_chars),
1478 val_ptr->n_chars); // sizeof(char) == 1 by definition
1479 }
1480 decode_length += buff.increase_pos_padd(p_td.raw->padding);
1481 return decode_length + prepaddlength;
1482 }
1483
1484 char* CHARSTRING::to_JSON_string() const
1485 {
1486 // Need at least 3 more characters (the double quotes around the string and the terminating zero)
1487 char* json_str = (char*)Malloc(val_ptr->n_chars + 3);
1488
1489 json_str[0] = 0;
1490 json_str = mputc(json_str, '\"');
1491
1492 for (int i = 0; i < val_ptr->n_chars; ++i) {
1493 // Increase the size of the buffer if it's not big enough to store the
1494 // characters remaining in the charstring plus 1 (for safety, in case this
1495 // character needs to be double-escaped).
1496 switch(val_ptr->chars_ptr[i]) {
1497 case '\\':
1498 json_str = mputstrn(json_str, "\\\\", 2);
1499 break;
1500 case '\n':
1501 json_str = mputstrn(json_str, "\\n", 2);
1502 break;
1503 case '\t':
1504 json_str = mputstrn(json_str, "\\t", 2);
1505 break;
1506 case '\r':
1507 json_str = mputstrn(json_str, "\\r", 2);
1508 break;
1509 case '\f':
1510 json_str = mputstrn(json_str, "\\f", 2);
1511 break;
1512 case '\b':
1513 json_str = mputstrn(json_str, "\\b", 2);
1514 break;
1515 case '\"':
1516 json_str = mputstrn(json_str, "\\\"", 2);
1517 break;
1518 default:
1519 json_str = mputc(json_str, val_ptr->chars_ptr[i]);
1520 break;
1521 }
1522 }
1523
1524 json_str = mputc(json_str, '\"');
1525 return json_str;
1526 }
1527
1528 boolean CHARSTRING::from_JSON_string(const char* p_value, size_t p_value_len, boolean check_quotes)
1529 {
1530 size_t start = 0;
1531 size_t end = p_value_len;
1532 if (check_quotes) {
1533 start = 1;
1534 end = p_value_len - 1;
1535 if (p_value[0] != '\"' || p_value[p_value_len - 1] != '\"') {
1536 return false;
1537 }
1538 }
1539
1540 // The charstring will be shorter than the JSON string, at least by the 2 quotes
1541 char* str = (char*)Malloc(end - start);
1542 size_t len = 0;
1543 boolean error = false;
1544
1545 for (size_t i = start; i < end; ++i) {
1546 if (0 > p_value[i]) {
1547 error = true;
1548 break;
1549 }
1550 if ('\\' == p_value[i]) {
1551 if (i == end - 1) {
1552 error = true;
1553 break;
1554 }
1555 switch(p_value[i + 1]) {
1556 case 'n':
1557 str[len++] = '\n';
1558 break;
1559 case 't':
1560 str[len++] = '\t';
1561 break;
1562 case 'r':
1563 str[len++] = '\r';
1564 break;
1565 case 'f':
1566 str[len++] = '\f';
1567 break;
1568 case 'b':
1569 str[len++] = '\b';
1570 break;
1571 case '\\':
1572 str[len++] = '\\';
1573 break;
1574 case '\"':
1575 str[len++] = '\"';
1576 break;
1577 case '/':
1578 str[len++] = '/';
1579 break;
1580 case 'u': {
1581 if (end - i >= 6 && '0' == p_value[i + 2] && '0' == p_value[i + 3]) {
1582 unsigned char upper_nibble = char_to_hexdigit(p_value[i + 4]);
1583 unsigned char lower_nibble = char_to_hexdigit(p_value[i + 5]);
1584 if (0x07 >= upper_nibble && 0x0F >= lower_nibble) {
1585 str[len++] = (upper_nibble << 4) | lower_nibble;
1586 // skip 4 extra characters (the 4 hex digits)
1587 i += 4;
1588 } else {
1589 // error (found something other than hex digits) -> leave the for cycle
1590 i = end;
1591 error = true;
1592 }
1593 } else {
1594 // error (not enough characters left or the first 2 hex digits are non-null) -> leave the for cycle
1595 i = end;
1596 error = true;
1597 }
1598 break;
1599 }
1600 default:
1601 // error (invalid escaped character) -> leave the for cycle
1602 i = end;
1603 error = true;
1604 break;
1605 }
1606 // skip an extra character (the \)
1607 ++i;
1608 } else {
1609 str[len++] = p_value[i];
1610 }
1611
1612 if (check_quotes && i == p_value_len - 1) {
1613 // Special case: the last 2 characters are double escaped quotes ('\\' and '\"')
1614 error = true;
1615 }
1616 }
1617
1618 if (!error) {
1619 clean_up();
1620 init_struct(len);
1621 memcpy(val_ptr->chars_ptr, str, len);
1622 val_ptr->chars_ptr[len] = 0;
1623 }
1624 Free(str);
1625 return !error;
1626 }
1627
1628 int CHARSTRING::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
1629 {
1630 if (!is_bound()) {
1631 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1632 "Encoding an unbound charstring value.");
1633 return -1;
1634 }
1635
1636 char* tmp_str = to_JSON_string();
1637 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
1638 Free(tmp_str);
1639 return enc_len;
1640 }
1641
1642 int CHARSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
1643 {
1644 json_token_t token = JSON_TOKEN_NONE;
1645 char* value = 0;
1646 size_t value_len = 0;
1647 int dec_len = 0;
1648 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
1649 if (use_default) {
1650 // No JSON data in the buffer -> use default value
1651 value = (char*)p_td.json->default_value;
1652 value_len = strlen(value);
1653 } else {
1654 dec_len = p_tok.get_next_token(&token, &value, &value_len);
1655 }
1656 if (JSON_TOKEN_ERROR == token) {
1657 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
1658 return JSON_ERROR_FATAL;
1659 }
1660 else if (JSON_TOKEN_STRING == token || use_default) {
1661 if (!from_JSON_string(value, value_len, !use_default)) {
1662 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "charstring");
1663 clean_up();
1664 return JSON_ERROR_FATAL;
1665 }
1666 } else {
1667 return JSON_ERROR_INVALID_TOKEN;
1668 }
1669 return dec_len;
1670 }
1671
1672
1673 CHARSTRING_ELEMENT::CHARSTRING_ELEMENT(boolean par_bound_flag,
1674 CHARSTRING& par_str_val, int par_char_pos)
1675 : bound_flag(par_bound_flag), str_val(par_str_val), char_pos(par_char_pos)
1676 {
1677
1678 }
1679
1680 CHARSTRING_ELEMENT& CHARSTRING_ELEMENT::operator=(const char* other_value)
1681 {
1682 if (other_value == NULL ||
1683 other_value[0] == '\0' || other_value[1] != '\0')
1684 TTCN_error("Assignment of a charstring value with length other "
1685 "than 1 to a charstring element.");
1686 bound_flag = TRUE;
1687 str_val.copy_value();
1688 str_val.val_ptr->chars_ptr[char_pos] = other_value[0];
1689 return *this;
1690 }
1691
1692 CHARSTRING_ELEMENT& CHARSTRING_ELEMENT::operator=
1693 (const CHARSTRING& other_value)
1694 {
1695 other_value.must_bound("Assignment of an unbound charstring value to a "
1696 "charstring element.");
1697 if(other_value.val_ptr->n_chars != 1)
1698 TTCN_error("Assignment of a charstring value with length other than "
1699 "1 to a charstring element.");
1700 bound_flag = TRUE;
1701 str_val.copy_value();
1702 str_val.val_ptr->chars_ptr[char_pos] = other_value.val_ptr->chars_ptr[0];
1703 return *this;
1704 }
1705
1706 CHARSTRING_ELEMENT& CHARSTRING_ELEMENT::operator=
1707 (const CHARSTRING_ELEMENT& other_value)
1708 {
1709 other_value.must_bound("Assignment of an unbound charstring element.");
1710 if (&other_value != this) {
1711 bound_flag = TRUE;
1712 str_val.copy_value();
1713 str_val.val_ptr->chars_ptr[char_pos] =
1714 other_value.str_val.val_ptr->chars_ptr[other_value.char_pos];
1715 }
1716 return *this;
1717 }
1718
1719 boolean CHARSTRING_ELEMENT::operator==(const char *other_value) const
1720 {
1721 must_bound("Comparison of an unbound charstring element.");
1722 if (other_value == NULL || other_value[0] == '\0' ||
1723 other_value[1] != '\0') return FALSE;
1724 return str_val.val_ptr->chars_ptr[char_pos] == other_value[0];
1725 }
1726
1727 boolean CHARSTRING_ELEMENT::operator==(const CHARSTRING& other_value) const
1728 {
1729 must_bound("Comparison of an unbound charstring element.");
1730 other_value.must_bound("Comparison of an unbound charstring value.");
1731 if (other_value.val_ptr->n_chars != 1) return FALSE;
1732 return str_val.val_ptr->chars_ptr[char_pos] ==
1733 other_value.val_ptr->chars_ptr[0];
1734 }
1735
1736 boolean CHARSTRING_ELEMENT::operator==(const CHARSTRING_ELEMENT& other_value) const
1737 {
1738 must_bound("Comparison of an unbound charstring element.");
1739 other_value.must_bound("Comparison of an unbound charstring element.");
1740 return str_val.val_ptr->chars_ptr[char_pos] ==
1741 other_value.str_val.val_ptr->chars_ptr[other_value.char_pos];
1742 }
1743
1744 boolean CHARSTRING_ELEMENT::operator==(const UNIVERSAL_CHARSTRING& other_value)
1745 const
1746 {
1747 must_bound("The left operand of comparison is an unbound charstring "
1748 "element.");
1749 other_value.must_bound("The right operand of comparison is an unbound "
1750 "universal charstring value.");
1751 if (other_value.charstring) {
1752 if (other_value.cstr.val_ptr->n_chars != 1) return FALSE;
1753 return str_val.val_ptr->chars_ptr[char_pos] ==
1754 other_value.cstr.val_ptr->chars_ptr[0];
1755 }
1756 else {
1757 if (other_value.val_ptr->n_uchars != 1) return FALSE;
1758 return other_value.val_ptr->uchars_ptr[0].uc_group == 0 &&
1759 other_value.val_ptr->uchars_ptr[0].uc_plane == 0 &&
1760 other_value.val_ptr->uchars_ptr[0].uc_row == 0 &&
1761 other_value.val_ptr->uchars_ptr[0].uc_cell ==
1762 (cbyte)str_val.val_ptr->chars_ptr[char_pos];
1763 }
1764 }
1765
1766 boolean CHARSTRING_ELEMENT::operator==
1767 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
1768 {
1769 must_bound("The left operand of comparison is an unbound charstring "
1770 "element.");
1771 other_value.must_bound("The right operand of comparison is an unbound "
1772 "universal charstring element.");
1773 const universal_char& uchar = other_value.get_uchar();
1774 return uchar.uc_group == 0 && uchar.uc_plane == 0 && uchar.uc_row == 0 &&
1775 uchar.uc_cell == (cbyte)str_val.val_ptr->chars_ptr[char_pos];
1776 }
1777
1778 CHARSTRING CHARSTRING_ELEMENT::operator+(const char *other_value) const
1779 {
1780 must_bound("Unbound operand of charstring element concatenation.");
1781 int other_len;
1782 if (other_value == NULL) other_len = 0;
1783 else other_len = strlen(other_value);
1784 CHARSTRING ret_val(other_len + 1);
1785 ret_val.val_ptr->chars_ptr[0] = str_val.val_ptr->chars_ptr[char_pos];
1786 memcpy(ret_val.val_ptr->chars_ptr + 1, other_value, other_len);
1787 return ret_val;
1788 }
1789
1790 CHARSTRING CHARSTRING_ELEMENT::operator+(const CHARSTRING& other_value) const
1791 {
1792 must_bound("Unbound operand of charstring element concatenation.");
1793 other_value.must_bound("Unbound operand of charstring concatenation.");
1794 int n_chars = other_value.val_ptr->n_chars;
1795 CHARSTRING ret_val(n_chars + 1);
1796 ret_val.val_ptr->chars_ptr[0] = str_val.val_ptr->chars_ptr[char_pos];
1797 memcpy(ret_val.val_ptr->chars_ptr + 1, other_value.val_ptr->chars_ptr,
1798 n_chars);
1799 return ret_val;
1800 }
1801
1802 CHARSTRING CHARSTRING_ELEMENT::operator+(const CHARSTRING_ELEMENT&
1803 other_value) const
1804 {
1805 must_bound("Unbound operand of charstring element concatenation.");
1806 other_value.must_bound("Unbound operand of charstring element "
1807 "concatenation.");
1808 char result[2];
1809 result[0] = str_val.val_ptr->chars_ptr[char_pos];
1810 result[1] = other_value.str_val.val_ptr->chars_ptr[other_value.char_pos];
1811 return CHARSTRING(2, result);
1812 }
1813
1814 UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+
1815 (const UNIVERSAL_CHARSTRING& other_value) const
1816 {
1817 must_bound("The left operand of concatenation is an unbound charstring "
1818 "element.");
1819 other_value.must_bound("The right operand of concatenation is an unbound "
1820 "universal charstring value.");
1821 if (other_value.charstring) {
1822 UNIVERSAL_CHARSTRING ret_val(other_value.cstr.val_ptr->n_chars + 1, true);
1823 ret_val.cstr.val_ptr->chars_ptr[0] = str_val.val_ptr->chars_ptr[char_pos];
1824 memcpy(ret_val.cstr.val_ptr->chars_ptr + 1, other_value.cstr.val_ptr->chars_ptr, other_value.cstr.val_ptr->n_chars);
1825 return ret_val;
1826 } else {
1827 UNIVERSAL_CHARSTRING ret_val(other_value.val_ptr->n_uchars + 1);
1828 ret_val.val_ptr->uchars_ptr[0].uc_group = 0;
1829 ret_val.val_ptr->uchars_ptr[0].uc_plane = 0;
1830 ret_val.val_ptr->uchars_ptr[0].uc_row = 0;
1831 ret_val.val_ptr->uchars_ptr[0].uc_cell = str_val.val_ptr->chars_ptr[char_pos];
1832 memcpy(ret_val.val_ptr->uchars_ptr + 1, other_value.val_ptr->uchars_ptr,
1833 other_value.val_ptr->n_uchars * sizeof(universal_char));
1834 return ret_val;
1835 }
1836 }
1837
1838 UNIVERSAL_CHARSTRING CHARSTRING_ELEMENT::operator+
1839 (const UNIVERSAL_CHARSTRING_ELEMENT& other_value) const
1840 {
1841 must_bound("The left operand of concatenation is an unbound charstring "
1842 "element.");
1843 other_value.must_bound("The right operand of concatenation is an unbound "
1844 "universal charstring element.");
1845 universal_char result[2];
1846 result[0].uc_group = 0;
1847 result[0].uc_plane = 0;
1848 result[0].uc_row = 0;
1849 result[0].uc_cell = str_val.val_ptr->chars_ptr[char_pos];
1850 result[1] = other_value.get_uchar();
1851 return UNIVERSAL_CHARSTRING(2, result);
1852 }
1853
1854 char CHARSTRING_ELEMENT::get_char() const
1855 {
1856 return str_val.val_ptr->chars_ptr[char_pos];
1857 }
1858
1859 void CHARSTRING_ELEMENT::log() const
1860 {
1861 if (bound_flag) {
1862 char c = str_val.val_ptr->chars_ptr[char_pos];
1863 if (TTCN_Logger::is_printable(c)) {
1864 TTCN_Logger::log_char('"');
1865 TTCN_Logger::log_char_escaped(c);
1866 TTCN_Logger::log_char('"');
1867 } else TTCN_Logger::log_event("char(0, 0, 0, %u)", (unsigned char)c);
1868 } else TTCN_Logger::log_event_unbound();
1869 }
1870
1871 // global functions
1872
1873 boolean operator==(const char* string_value, const CHARSTRING& other_value)
1874 {
1875 other_value.must_bound("Unbound operand of charstring comparison.");
1876 if (string_value == NULL) string_value = "";
1877 return !strcmp(string_value, other_value.val_ptr->chars_ptr);
1878 }
1879
1880 boolean operator==(const char* string_value,
1881 const CHARSTRING_ELEMENT& other_value)
1882 {
1883 other_value.must_bound("Unbound operand of charstring element "
1884 "comparison.");
1885 if (string_value == NULL || string_value[0] == '\0' ||
1886 string_value[1] != '\0') return FALSE;
1887 return string_value[0] == other_value.get_char();
1888 }
1889
1890 CHARSTRING operator+(const char* string_value, const CHARSTRING& other_value)
1891 {
1892 other_value.must_bound("Unbound operand of charstring concatenation.");
1893 int string_len;
1894 if (string_value == NULL) string_len = 0;
1895 else string_len = strlen(string_value);
1896 if (string_len == 0) return other_value;
1897 CHARSTRING ret_val(string_len + other_value.val_ptr->n_chars);
1898 memcpy(ret_val.val_ptr->chars_ptr, string_value, string_len);
1899 memcpy(ret_val.val_ptr->chars_ptr + string_len,
1900 other_value.val_ptr->chars_ptr, other_value.val_ptr->n_chars);
1901 return ret_val;
1902 }
1903
1904 CHARSTRING operator+(const char* string_value,
1905 const CHARSTRING_ELEMENT& other_value)
1906 {
1907 other_value.must_bound("Unbound operand of charstring element "
1908 "concatenation.");
1909 int string_len;
1910 if (string_value == NULL) string_len = 0;
1911 else string_len = strlen(string_value);
1912 if (string_len == 0) return CHARSTRING(other_value);
1913 CHARSTRING ret_val(string_len + 1);
1914 memcpy(ret_val.val_ptr->chars_ptr, string_value, string_len);
1915 ret_val.val_ptr->chars_ptr[string_len] = other_value.get_char();
1916 return ret_val;
1917 }
1918
1919 CHARSTRING operator<<=(const char *string_value, const INTEGER& rotate_count)
1920 {
1921 return CHARSTRING(string_value) <<= rotate_count;
1922 }
1923
1924 CHARSTRING operator>>=(const char *string_value, const INTEGER& rotate_count)
1925 {
1926 return CHARSTRING(string_value) >>= rotate_count;
1927 }
1928
1929 // charstring template class
1930
1931 void CHARSTRING_template::clean_up()
1932 {
1933 switch(template_selection) {
1934 case VALUE_LIST:
1935 case COMPLEMENTED_LIST:
1936 delete [] value_list.list_value;
1937 break;
1938 case STRING_PATTERN:
1939 if (pattern_value.regexp_init) regfree(&pattern_value.posix_regexp);
1940 break;
1941 default:
1942 break;
1943 }
1944 template_selection = UNINITIALIZED_TEMPLATE;
1945 }
1946
1947 void CHARSTRING_template::copy_template(const CHARSTRING_template& other_value)
1948 {
1949 switch (other_value.template_selection) {
1950 case STRING_PATTERN:
1951 pattern_value.regexp_init = FALSE;
1952 /* no break */
1953 case SPECIFIC_VALUE:
1954 single_value = other_value.single_value;
1955 break;
1956 case OMIT_VALUE:
1957 case ANY_VALUE:
1958 case ANY_OR_OMIT:
1959 break;
1960 case VALUE_LIST:
1961 case COMPLEMENTED_LIST:
1962 value_list.n_values = other_value.value_list.n_values;
1963 value_list.list_value = new CHARSTRING_template[value_list.n_values];
1964 for (unsigned int i = 0; i < value_list.n_values; i++)
1965 value_list.list_value[i].copy_template(
1966 other_value.value_list.list_value[i]);
1967 break;
1968 case VALUE_RANGE:
1969 if (!other_value.value_range.min_is_set) TTCN_error("The lower bound is "
1970 "not set when copying a charstring value range template.");
1971 if (!other_value.value_range.max_is_set) TTCN_error("The upper bound is "
1972 "not set when copying a charstring value range template.");
1973 value_range = other_value.value_range;
1974 break;
1975 default:
1976 TTCN_error("Copying an uninitialized/unsupported charstring template.");
1977 }
1978 set_selection(other_value);
1979 }
1980
1981 CHARSTRING_template::CHARSTRING_template()
1982 {
1983 }
1984
1985 CHARSTRING_template::CHARSTRING_template(template_sel other_value)
1986 : Restricted_Length_Template(other_value)
1987 {
1988 check_single_selection(other_value);
1989 }
1990
1991 CHARSTRING_template::CHARSTRING_template(const CHARSTRING& other_value)
1992 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1993 {
1994 }
1995
1996 CHARSTRING_template::CHARSTRING_template(const CHARSTRING_ELEMENT& other_value)
1997 : Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1998 {
1999 }
2000
2001 CHARSTRING_template::CHARSTRING_template(const OPTIONAL<CHARSTRING>& other_value)
2002 {
2003 switch (other_value.get_selection()) {
2004 case OPTIONAL_PRESENT:
2005 set_selection(SPECIFIC_VALUE);
2006 single_value = (const CHARSTRING&)other_value;
2007 break;
2008 case OPTIONAL_OMIT:
2009 set_selection(OMIT_VALUE);
2010 break;
2011 default:
2012 TTCN_error("Creating a charstring template from an unbound optional "
2013 "field.");
2014 }
2015 }
2016
2017 CHARSTRING_template::CHARSTRING_template(template_sel p_sel,
2018 const CHARSTRING& p_str)
2019 : Restricted_Length_Template(STRING_PATTERN), single_value(p_str)
2020 {
2021 if(p_sel!=STRING_PATTERN)
2022 TTCN_error("Internal error: Initializing a charstring pattern template "
2023 "with invalid selection.");
2024 pattern_value.regexp_init=FALSE;
2025 }
2026
2027 CHARSTRING_template::CHARSTRING_template(const CHARSTRING_template& other_value)
2028 : Restricted_Length_Template()
2029 {
2030 copy_template(other_value);
2031 }
2032
2033 CHARSTRING_template::~CHARSTRING_template()
2034 {
2035 clean_up();
2036 }
2037
2038 CHARSTRING_template& CHARSTRING_template::operator=(template_sel other_value)
2039 {
2040 check_single_selection(other_value);
2041 clean_up();
2042 set_selection(other_value);
2043 return *this;
2044 }
2045
2046 CHARSTRING_template& CHARSTRING_template::operator=
2047 (const CHARSTRING& other_value)
2048 {
2049 other_value.must_bound("Assignment of an unbound charstring value to a "
2050 "template.");
2051 clean_up();
2052 set_selection(SPECIFIC_VALUE);
2053 single_value = other_value;
2054 return *this;
2055 }
2056
2057 CHARSTRING_template& CHARSTRING_template::operator=
2058 (const CHARSTRING_ELEMENT& other_value)
2059 {
2060 other_value.must_bound("Assignment of an unbound charstring element to a "
2061 "template.");
2062 clean_up();
2063 set_selection(SPECIFIC_VALUE);
2064 single_value = other_value;
2065 return *this;
2066 }
2067
2068 CHARSTRING_template& CHARSTRING_template::operator=
2069 (const OPTIONAL<CHARSTRING>& other_value)
2070 {
2071 clean_up();
2072 switch (other_value.get_selection()) {
2073 case OPTIONAL_PRESENT:
2074 set_selection(SPECIFIC_VALUE);
2075 single_value = (const CHARSTRING&)other_value;
2076 break;
2077 case OPTIONAL_OMIT:
2078 set_selection(OMIT_VALUE);
2079 break;
2080 default:
2081 TTCN_error("Assignment of an unbound optional field to a charstring "
2082 "template.");
2083 }
2084 return *this;
2085 }
2086
2087 CHARSTRING_template& CHARSTRING_template::operator=
2088 (const CHARSTRING_template& other_value)
2089 {
2090 if (&other_value != this) {
2091 clean_up();
2092 copy_template(other_value);
2093 }
2094 return *this;
2095 }
2096
2097 CHARSTRING_ELEMENT CHARSTRING_template::operator[](int index_value)
2098 {
2099 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2100 TTCN_error("Accessing a charstring element of a non-specific charstring "
2101 "template.");
2102 return single_value[index_value];
2103 }
2104
2105 CHARSTRING_ELEMENT CHARSTRING_template::operator[](const INTEGER& index_value)
2106 {
2107 index_value.must_bound("Indexing a charstring template with an unbound "
2108 "integer value.");
2109 return (*this)[(int)index_value];
2110 }
2111
2112 const CHARSTRING_ELEMENT CHARSTRING_template::operator[](int index_value) const
2113 {
2114 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2115 TTCN_error("Accessing a charstring element of a non-specific charstring "
2116 "template.");
2117 return single_value[index_value];
2118 }
2119
2120 const CHARSTRING_ELEMENT CHARSTRING_template::operator[](const INTEGER& index_value) const
2121 {
2122 index_value.must_bound("Indexing a charstring template with an unbound "
2123 "integer value.");
2124 return (*this)[(int)index_value];
2125 }
2126
2127 boolean CHARSTRING_template::match(const CHARSTRING& other_value) const
2128 {
2129 if (!other_value.is_bound()) return FALSE;
2130 int value_length = other_value.lengthof();
2131 if (!match_length(value_length)) return FALSE;
2132 switch (template_selection) {
2133 case SPECIFIC_VALUE:
2134 return single_value == other_value;
2135 case STRING_PATTERN: {
2136 if (!pattern_value.regexp_init) {
2137 char *posix_str=TTCN_pattern_to_regexp(single_value);
2138 if(posix_str==NULL) {
2139 TTCN_error("Cannot convert pattern \"%s\" to POSIX-equivalent.",
2140 (const char*)single_value);
2141 }
2142 /*
2143 //TTCN_Logger::begin_event(TTCN_DEBUG);
2144 TTCN_Logger::log_event_str("POSIX ERE equivalent of pattern ");
2145 single_value.log();
2146 TTCN_Logger::log_event(" is: \"%s\"", posix_str);
2147 //TTCN_Logger::end_event();
2148 */
2149 int ret_val=regcomp(&pattern_value.posix_regexp, posix_str,
2150 REG_EXTENDED|REG_NOSUB);
2151 Free(posix_str);
2152 if(ret_val!=0) {
2153 /* regexp error */
2154 char msg[ERRMSG_BUFSIZE];
2155 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
2156 regfree(&pattern_value.posix_regexp);
2157 TTCN_error("Pattern matching error: %s", msg);
2158 }
2159 pattern_value.regexp_init=TRUE;
2160 }
2161 int ret_val=regexec(&pattern_value.posix_regexp, other_value, 0, NULL, 0);
2162 switch (ret_val) {
2163 case 0:
2164 return TRUE;
2165 case REG_NOMATCH:
2166 return FALSE;
2167 default:
2168 /* regexp error */
2169 char msg[ERRMSG_BUFSIZE];
2170 regerror(ret_val, &pattern_value.posix_regexp, msg, ERRMSG_BUFSIZE);
2171 TTCN_error("Pattern matching error: %s", msg);
2172 }
2173 break;}
2174 case OMIT_VALUE:
2175 return FALSE;
2176 case ANY_VALUE:
2177 case ANY_OR_OMIT:
2178 return TRUE;
2179 case VALUE_LIST:
2180 case COMPLEMENTED_LIST:
2181 for (unsigned int i = 0; i < value_list.n_values; i++)
2182 if (value_list.list_value[i].match(other_value))
2183 return template_selection == VALUE_LIST;
2184 return template_selection == COMPLEMENTED_LIST;
2185 case VALUE_RANGE: {
2186 if (!value_range.min_is_set) TTCN_error("The lower bound is not set when "
2187 "matching with a charstring value range template.");
2188 if (!value_range.max_is_set) TTCN_error("The upper bound is not set when "
2189 "matching with a charstring value range template.");
2190 if (value_range.min_value > value_range.max_value)
2191 TTCN_error("The lower bound (\"%c\") is greater than the upper bound "
2192 "(\"%c\") when matching with a charstring value range template.",
2193 value_range.min_value, value_range.max_value);
2194 const char *chars_ptr = other_value;
2195 for (int i = 0; i < value_length; i++) {
2196 if (chars_ptr[i] < value_range.min_value ||
2197 chars_ptr[i] > value_range.max_value) return FALSE;
2198 }
2199 return TRUE;
2200 break; }
2201 default:
2202 TTCN_error("Matching with an uninitialized/unsupported charstring "
2203 "template.");
2204 }
2205 return FALSE;
2206 }
2207
2208 const CHARSTRING& CHARSTRING_template::valueof() const
2209 {
2210 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
2211 TTCN_error("Performing valueof or send operation on a non-specific "
2212 "charstring template.");
2213 return single_value;
2214 }
2215
2216 int CHARSTRING_template::lengthof() const
2217 {
2218 int min_length;
2219 boolean has_any_or_none;
2220 if (is_ifpresent)
2221 TTCN_error("Performing lengthof() operation on a charstring template "
2222 "which has an ifpresent attribute.");
2223 switch (template_selection)
2224 {
2225 case SPECIFIC_VALUE:
2226 min_length = single_value.lengthof();
2227 has_any_or_none = FALSE;
2228 break;
2229 case OMIT_VALUE:
2230 TTCN_error("Performing lengthof() operation on a charstring template "
2231 "containing omit value.");
2232 case ANY_VALUE:
2233 case ANY_OR_OMIT:
2234 case VALUE_RANGE:
2235 min_length = 0;
2236 has_any_or_none = TRUE; // max. length is infinity
2237 break;
2238 case VALUE_LIST:
2239 {
2240 // error if any element does not have length or the lengths differ
2241 if (value_list.n_values<1)
2242 TTCN_error("Internal error: "
2243 "Performing lengthof() operation on a charstring template "
2244 "containing an empty list.");
2245 int item_length = value_list.list_value[0].lengthof();
2246 for (unsigned int i = 1; i < value_list.n_values; i++) {
2247 if (value_list.list_value[i].lengthof()!=item_length)
2248 TTCN_error("Performing lengthof() operation on a charstring template "
2249 "containing a value list with different lengths.");
2250 }
2251 min_length = item_length;
2252 has_any_or_none = FALSE;
2253 break;
2254 }
2255 case COMPLEMENTED_LIST:
2256 TTCN_error("Performing lengthof() operation on a charstring template "
2257 "containing complemented list.");
2258 case STRING_PATTERN:
2259 TTCN_error("Performing lengthof() operation on a charstring template "
2260 "containing a pattern is not allowed.");
2261 default:
2262 TTCN_error("Performing lengthof() operation on an "
2263 "uninitialized/unsupported charstring template.");
2264 }
2265 return check_section_is_single(min_length, has_any_or_none,
2266 "length", "a", "charstring template");
2267 }
2268
2269 void CHARSTRING_template::set_type(template_sel template_type,
2270 unsigned int list_length)
2271 {
2272 clean_up();
2273 switch (template_type) {
2274 case VALUE_LIST:
2275 case COMPLEMENTED_LIST:
2276 set_selection(template_type);
2277 value_list.n_values = list_length;
2278 value_list.list_value = new CHARSTRING_template[list_length];
2279 break;
2280 case VALUE_RANGE:
2281 set_selection(VALUE_RANGE);
2282 value_range.min_is_set = FALSE;
2283 value_range.max_is_set = FALSE;
2284 break;
2285 default:
2286 TTCN_error("Setting an invalid type for a charstring template.");
2287 }
2288 }
2289
2290 CHARSTRING_template& CHARSTRING_template::list_item(unsigned int list_index)
2291 {
2292 if (template_selection != VALUE_LIST &&
2293 template_selection != COMPLEMENTED_LIST)
2294 TTCN_error("Internal error: Accessing a list element of a non-list "
2295 "charstring template.");
2296 if (list_index >= value_list.n_values)
2297 TTCN_error("Internal error: Index overflow in a charstring value list "
2298 "template.");
2299 return value_list.list_value[list_index];
2300 }
2301
2302 void CHARSTRING_template::set_min(const CHARSTRING& min_value)
2303 {
2304 if (template_selection != VALUE_RANGE)
2305 TTCN_error("Setting the lower bound for a non-range charstring template.");
2306 min_value.must_bound("Setting an unbound value as lower bound in a "
2307 "charstring value range template.");
2308 int length = min_value.lengthof();
2309 if (length != 1) TTCN_error("The length of the lower bound in a "
2310 "charstring value range template must be 1 instead of %d.", length);
2311 value_range.min_is_set = TRUE;
2312 value_range.min_value = *(const char*)min_value;
2313 if (value_range.max_is_set && value_range.min_value > value_range.max_value)
2314 TTCN_error("The lower bound (\"%c\") in a charstring value range template "
2315 "is greater than the upper bound (\"%c\").", value_range.min_value,
2316 value_range.max_value);
2317 }
2318
2319 void CHARSTRING_template::set_max(const CHARSTRING& max_value)
2320 {
2321 if (template_selection != VALUE_RANGE)
2322 TTCN_error("Setting the upper bound for a non-range charstring template.");
2323 max_value.must_bound("Setting an unbound value as upper bound in a "
2324 "charstring value range template.");
2325 int length = max_value.lengthof();
2326 if (length != 1) TTCN_error("The length of the upper bound in a "
2327 "charstring value range template must be 1 instead of %d.", length);
2328 value_range.max_is_set = TRUE;
2329 value_range.max_value = *(const char*)max_value;
2330 if (value_range.min_is_set && value_range.min_value > value_range.max_value)
2331 TTCN_error("The upper bound (\"%c\") in a charstring value range template "
2332 "is smaller than the lower bound (\"%c\").", value_range.max_value,
2333 value_range.min_value);
2334 }
2335
2336 void CHARSTRING_template::log_pattern(int n_chars, const char *chars_ptr)
2337 {
2338 TTCN_Logger::log_event_str("pattern \"");
2339 enum { INITIAL, BACKSLASH, BACKSLASH_Q, QUADRUPLE, HASHMARK, REPETITIONS }
2340 state = INITIAL;
2341 for (int i = 0; i < n_chars; i++) {
2342 unsigned char c = chars_ptr[i];
2343 // print the character
2344 if (isprint(c)) {
2345 switch (c) {
2346 case '"':
2347 TTCN_Logger::log_event_str("\\\"");
2348 break;
2349 case '{':
2350 if (state == BACKSLASH || state == BACKSLASH_Q)
2351 TTCN_Logger::log_char('{');
2352 else TTCN_Logger::log_event_str("\\{");
2353 break;
2354 case '}':
2355 if (state == BACKSLASH || state == QUADRUPLE)
2356 TTCN_Logger::log_char('}');
2357 else TTCN_Logger::log_event_str("\\}");
2358 break;
2359 case ' ':
2360 if (state != INITIAL && state != BACKSLASH) break;
2361 // no break
2362 default:
2363 TTCN_Logger::log_char(c);
2364 break;
2365 }
2366 } else {
2367 switch (c) {
2368 case '\t':
2369 if (state == INITIAL || state == BACKSLASH)
2370 TTCN_Logger::log_event_str("\\t");
2371 break;
2372 case '\r':
2373 if (state == INITIAL || state == BACKSLASH)
2374 TTCN_Logger::log_event_str("\\r");
2375 break;
2376 case '\n':
2377 case '\v':
2378 case '\f':
2379 if (state != INITIAL && state != BACKSLASH) break;
2380 // no break
2381 default:
2382 TTCN_Logger::log_event("\\q{0,0,0,%u}", c);
2383 break;
2384 }
2385 }
2386 // update the state
2387 switch (state) {
2388 case INITIAL:
2389 switch (c) {
2390 case '\\':
2391 state = BACKSLASH;
2392 break;
2393 case '#':
2394 state = HASHMARK;
2395 break;
2396 default:
2397 break;
2398 }
2399 break;
2400 case BACKSLASH:
2401 if (c == 'q') state = BACKSLASH_Q;
2402 else state = INITIAL;
2403 break;
2404 case BACKSLASH_Q:
2405 switch (c) {
2406 case '{':
2407 state = QUADRUPLE;
2408 break;
2409 case ' ':
2410 case '\t':
2411 case '\r':
2412 case '\n':
2413 case '\v':
2414 case '\f':
2415 break;
2416 default:
2417 state = INITIAL;
2418 break;
2419 }
2420 break;
2421 case HASHMARK:
2422 switch (c) {
2423 case '(':
2424 state = REPETITIONS;
2425 break;
2426 case ' ':
2427 case '\t':
2428 case '\r':
2429 case '\n':
2430 case '\v':
2431 case '\f':
2432 break;
2433 default:
2434 state = INITIAL;
2435 break;
2436 }
2437 break;
2438 case QUADRUPLE:
2439 case REPETITIONS:
2440 switch (c) {
2441 case ' ':
2442 case '\t':
2443 case '\r':
2444 case '\n':
2445 case '\v':
2446 case '\f':
2447 case ',':
2448 break;
2449 default:
2450 if (!isdigit(c)) state = INITIAL;
2451 break;
2452 }
2453 break;
2454 }
2455 }
2456 TTCN_Logger::log_char('"');
2457 }
2458
2459 void CHARSTRING_template::log() const
2460 {
2461 switch (template_selection) {
2462 case STRING_PATTERN:
2463 log_pattern(single_value.lengthof(), (const char*)single_value);
2464 break;
2465 case SPECIFIC_VALUE:
2466 single_value.log();
2467 break;
2468 case COMPLEMENTED_LIST:
2469 TTCN_Logger::log_event_str("complement ");
2470 // no break
2471 case VALUE_LIST:
2472 TTCN_Logger::log_char('(');
2473 for (unsigned int i = 0; i < value_list.n_values; i++) {
2474 if (i > 0) TTCN_Logger::log_event_str(", ");
2475 value_list.list_value[i].log();
2476 }
2477 TTCN_Logger::log_char(')');
2478 break;
2479 case VALUE_RANGE:
2480 TTCN_Logger::log_char('(');
2481 if (value_range.min_is_set) {
2482 if (TTCN_Logger::is_printable(value_range.min_value)) {
2483 TTCN_Logger::log_char('"');
2484 TTCN_Logger::log_char_escaped(value_range.min_value);
2485 TTCN_Logger::log_char('"');
2486 } else TTCN_Logger::log_event("char(0, 0, 0, %u)",
2487 (unsigned char)value_range.min_value);
2488 } else TTCN_Logger::log_event_str("<unknown lower bound>");
2489 TTCN_Logger::log_event_str(" .. ");
2490 if (value_range.max_is_set) {
2491 if (TTCN_Logger::is_printable(value_range.max_value)) {
2492 TTCN_Logger::log_char('"');
2493 TTCN_Logger::log_char_escaped(value_range.max_value);
2494 TTCN_Logger::log_char('"');
2495 } else TTCN_Logger::log_event("char(0, 0, 0, %u)",
2496 (unsigned char)value_range.max_value);
2497 } else TTCN_Logger::log_event_str("<unknown upper bound>");
2498 TTCN_Logger::log_char(')');
2499 break;
2500 default:
2501 log_generic();
2502 }
2503 log_restricted();
2504 log_ifpresent();
2505 }
2506
2507 void CHARSTRING_template::log_match(const CHARSTRING& match_value) const
2508 {
2509 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
2510 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
2511 TTCN_Logger::print_logmatch_buffer();
2512 TTCN_Logger::log_event_str(" := ");
2513 }
2514 match_value.log();
2515 TTCN_Logger::log_event_str(" with ");
2516 log();
2517 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
2518 else TTCN_Logger::log_event_str(" unmatched");
2519 }
2520
2521 void CHARSTRING_template::set_param(Module_Param& param) {
2522 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "charstring template");
2523 switch (param.get_type()) {
2524 case Module_Param::MP_Omit:
2525 *this = OMIT_VALUE;
2526 break;
2527 case Module_Param::MP_Any:
2528 *this = ANY_VALUE;
2529 break;
2530 case Module_Param::MP_AnyOrNone:
2531 *this = ANY_OR_OMIT;
2532 break;
2533 case Module_Param::MP_List_Template:
2534 case Module_Param::MP_ComplementList_Template:
2535 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
2536 for (size_t i=0; i<param.get_size(); i++) {
2537 list_item(i).set_param(*param.get_elem(i));
2538 }
2539 break;
2540 case Module_Param::MP_Charstring:
2541 *this = CHARSTRING(param.get_string_size(), (char*)param.get_string_data());
2542 break;
2543 case Module_Param::MP_StringRange: {
2544 universal_char lower_uchar = param.get_lower_uchar();
2545 universal_char upper_uchar = param.get_upper_uchar();
2546 if (!lower_uchar.is_char()) param.error("Lower bound of char range cannot be a multiple-byte character");
2547 if (!upper_uchar.is_char()) param.error("Upper bound of char range cannot be a multiple-byte character");
2548 clean_up();
2549 set_selection(VALUE_RANGE);
2550 value_range.min_is_set = TRUE;
2551 value_range.max_is_set = TRUE;
2552 value_range.min_value = (char)(lower_uchar.uc_cell);
2553 value_range.max_value = (char)(upper_uchar.uc_cell);
2554 } break;
2555 case Module_Param::MP_Pattern:
2556 clean_up();
2557 single_value = CHARSTRING(param.get_pattern());
2558 pattern_value.regexp_init = FALSE;
2559 set_selection(STRING_PATTERN);
2560 break;
2561 default:
2562 param.type_error("charstring template");
2563 }
2564 is_ifpresent = param.get_ifpresent();
2565 set_length_range(param);
2566 }
2567
2568 void CHARSTRING_template::encode_text(Text_Buf& text_buf) const
2569 {
2570 encode_text_restricted(text_buf);
2571 switch (template_selection) {
2572 case OMIT_VALUE:
2573 case ANY_VALUE:
2574 case ANY_OR_OMIT:
2575 break;
2576 case SPECIFIC_VALUE:
2577 case STRING_PATTERN:
2578 single_value.encode_text(text_buf);
2579 break;
2580 case VALUE_LIST:
2581 case COMPLEMENTED_LIST:
2582 text_buf.push_int(value_list.n_values);
2583 for (unsigned int i = 0; i < value_list.n_values; i++)
2584 value_list.list_value[i].encode_text(text_buf);
2585 break;
2586 case VALUE_RANGE:
2587 if (!value_range.min_is_set) TTCN_error("Text encoder: The lower bound is "
2588 "not set in a charstring value range template.");
2589 if (!value_range.max_is_set) TTCN_error("Text encoder: The upper bound is "
2590 "not set in a charstring value range template.");
2591 text_buf.push_raw(1, &value_range.min_value);
2592 text_buf.push_raw(1, &value_range.max_value);
2593 break;
2594 default:
2595 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2596 "charstring template.");
2597 }
2598 }
2599
2600 void CHARSTRING_template::decode_text(Text_Buf& text_buf)
2601 {
2602 clean_up();
2603 decode_text_restricted(text_buf);
2604 switch (template_selection) {
2605 case OMIT_VALUE:
2606 case ANY_VALUE:
2607 case ANY_OR_OMIT:
2608 break;
2609 case STRING_PATTERN:
2610 pattern_value.regexp_init=FALSE;
2611 /* no break */
2612 case SPECIFIC_VALUE:
2613 single_value.decode_text(text_buf);
2614 break;
2615 case VALUE_LIST:
2616 case COMPLEMENTED_LIST:
2617 value_list.n_values = text_buf.pull_int().get_val();
2618 value_list.list_value = new CHARSTRING_template[value_list.n_values];
2619 for (unsigned int i = 0; i < value_list.n_values; i++)
2620 value_list.list_value[i].decode_text(text_buf);
2621 break;
2622 case VALUE_RANGE:
2623 text_buf.pull_raw(1, &value_range.min_value);
2624 text_buf.pull_raw(1, &value_range.max_value);
2625 if (value_range.min_value > value_range.max_value)
2626 TTCN_error("Text decoder: The received lower bound is greater than the "
2627 "upper bound in a charstring value range template.");
2628 value_range.min_is_set = TRUE;
2629 value_range.max_is_set = TRUE;
2630 break;
2631 default:
2632 TTCN_error("Text decoder: An unknown/unsupported selection was "
2633 "received for a charstring template.");
2634 }
2635 }
2636
2637 boolean CHARSTRING_template::is_present() const
2638 {
2639 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
2640 return !match_omit();
2641 }
2642
2643 boolean CHARSTRING_template::match_omit() const
2644 {
2645 if (is_ifpresent) return TRUE;
2646 switch (template_selection) {
2647 case OMIT_VALUE:
2648 case ANY_OR_OMIT:
2649 return TRUE;
2650 case VALUE_LIST:
2651 case COMPLEMENTED_LIST:
2652 for (unsigned int i=0; i<value_list.n_values; i++)
2653 if (value_list.list_value[i].match_omit())
2654 return template_selection==VALUE_LIST;
2655 return template_selection==COMPLEMENTED_LIST;
2656 default:
2657 return FALSE;
2658 }
2659 return FALSE;
2660 }
2661
2662 #ifndef TITAN_RUNTIME_2
2663 void CHARSTRING_template::check_restriction(template_res t_res, const char* t_name) const
2664 {
2665 if (template_selection==UNINITIALIZED_TEMPLATE) return;
2666 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
2667 case TR_VALUE:
2668 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
2669 break;
2670 case TR_OMIT:
2671 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
2672 template_selection==SPECIFIC_VALUE)) return;
2673 break;
2674 case TR_PRESENT:
2675 if (!match_omit()) return;
2676 break;
2677 default:
2678 return;
2679 }
2680 TTCN_error("Restriction `%s' on template of type %s violated.",
2681 get_res_name(t_res), t_name ? t_name : "charstring");
2682 }
2683 #endif
2684
2685 const CHARSTRING& CHARSTRING_template::get_single_value() const {
2686 switch (template_selection) {
2687 case STRING_PATTERN:
2688 case SPECIFIC_VALUE:
2689 break;
2690 default:
2691 TTCN_error("This template does not have single value.");
2692 }
2693 return single_value;
2694 }
This page took 0.089887 seconds and 5 git commands to generate.