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