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