implemented decmatch (artf724241)
[deliverable/titan.core.git] / core / Hexstring.cc
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 *
10 * Baji, Laszlo
11 * Balasko, Jeno
12 * Baranyi, Botond
13 * Beres, Szabolcs
14 * Delic, Adam
15 * Forstner, Matyas
16 * Kovacs, Ferenc
17 * Raduly, Csaba
18 * Szabados, Kristof
19 * Szabo, Bence Janos
20 * Szabo, Janos Zoltan – initial implementation
21 * Szalai, Gabor
22 * Tatarka, Gabor
23 *
24 ******************************************************************************/
25 #include "Hexstring.hh"
26 #include "../common/memory.h"
27 #include "Integer.hh"
28 #include "String_struct.hh"
29 #include "Param_Types.hh"
30 #include "Error.hh"
31 #include "Logger.hh"
32 #include "Encdec.hh"
33 #include "RAW.hh"
34 #include "Addfunc.hh"
35
36 #include "../common/dbgnew.hh"
37
38 #include <string.h>
39
40 // hexstring value class
41
42 /** The amount of memory needed for a string containing n hexadecimal digits. */
43 #define MEMORY_SIZE(n) (sizeof(hexstring_struct) - sizeof(int) + ((n) + 1) / 2)
44
45 void HEXSTRING::init_struct(int n_nibbles)
46 {
47 if (n_nibbles < 0) {
48 val_ptr = NULL;
49 TTCN_error("Initializing an hexstring with a negative length.");
50 }
51 else if (n_nibbles == 0) {
52 /** This will represent the empty strings so they won't need allocated
53 * memory, this delays the memory allocation until it is really needed.
54 */
55 static hexstring_struct empty_string = { 1, 0, "" };
56 val_ptr = &empty_string;
57 empty_string.ref_count++;
58 }
59 else {
60 val_ptr = (hexstring_struct*) Malloc(MEMORY_SIZE(n_nibbles));
61 val_ptr->ref_count = 1;
62 val_ptr->n_nibbles = n_nibbles;
63 }
64 }
65
66 /** Return the nibble at index i
67 *
68 * @param nibble_index
69 * @return
70 */
71 unsigned char HEXSTRING::get_nibble(int nibble_index) const
72 {
73 unsigned char octet = val_ptr->nibbles_ptr[nibble_index / 2];
74 if (nibble_index % 2)
75 return octet >> 4; // odd nibble -> top
76 else
77 return octet & 0x0F; // even nibble -> bottom
78 }
79
80 void HEXSTRING::set_nibble(int nibble_index, unsigned char new_value)
81 {
82 unsigned char old_octet = val_ptr->nibbles_ptr[nibble_index / 2];
83 if (nibble_index % 2) {
84 val_ptr->nibbles_ptr[nibble_index / 2] = (old_octet & 0x0F) | (new_value
85 << 4);
86 }
87 else {
88 val_ptr->nibbles_ptr[nibble_index / 2] = (old_octet & 0xF0) | (new_value
89 & 0x0F);
90 }
91 }
92
93 void HEXSTRING::copy_value()
94 {
95 if (val_ptr == NULL || val_ptr->n_nibbles <= 0) TTCN_error(
96 "Internal error: Invalid internal data structure when copying "
97 "the memory area of a hexstring value.");
98 if (val_ptr->ref_count > 1) {
99 hexstring_struct *old_ptr = val_ptr;
100 old_ptr->ref_count--;
101 init_struct(old_ptr->n_nibbles);
102 memcpy(val_ptr->nibbles_ptr, old_ptr->nibbles_ptr, (old_ptr->n_nibbles + 1)
103 / 2);
104 }
105 }
106
107 void HEXSTRING::clear_unused_nibble() const
108 {
109 if (val_ptr->n_nibbles % 2) val_ptr->nibbles_ptr[val_ptr->n_nibbles / 2]
110 &= 0x0F;
111 }
112
113 HEXSTRING::HEXSTRING(int n_nibbles)
114 {
115 init_struct(n_nibbles);
116 }
117
118 HEXSTRING::HEXSTRING()
119 {
120 val_ptr = NULL;
121 }
122
123 HEXSTRING::HEXSTRING(int init_n_nibbles, const unsigned char* init_nibbles)
124 {
125 init_struct(init_n_nibbles);
126 memcpy(val_ptr->nibbles_ptr, init_nibbles, (init_n_nibbles + 1) / 2);
127 clear_unused_nibble();
128 }
129
130 HEXSTRING::HEXSTRING(const HEXSTRING& other_value) :
131 Base_Type(other_value)
132 {
133 other_value.must_bound("Initialization from an unbound hexstring value.");
134 val_ptr = other_value.val_ptr;
135 val_ptr->ref_count++;
136 }
137
138 HEXSTRING::HEXSTRING(const HEXSTRING_ELEMENT& other_value)
139 {
140 other_value.must_bound("Initialization from an unbound hexstring element.");
141 init_struct(1);
142 val_ptr->nibbles_ptr[0] = other_value.get_nibble();
143 }
144
145 HEXSTRING::~HEXSTRING()
146 {
147 clean_up();
148 }
149
150 void HEXSTRING::clean_up()
151 {
152 if (val_ptr != NULL) {
153 if (val_ptr->ref_count > 1)
154 val_ptr->ref_count--;
155 else if (val_ptr->ref_count == 1)
156 Free(val_ptr);
157 else
158 TTCN_error("Internal error: Invalid reference counter in a hexstring "
159 "value.");
160 val_ptr = NULL;
161 }
162 }
163
164 HEXSTRING& HEXSTRING::operator=(const HEXSTRING& other_value)
165 {
166 other_value.must_bound("Assignment of an unbound hexstring value.");
167 if (&other_value != this) {
168 clean_up();
169 val_ptr = other_value.val_ptr;
170 val_ptr->ref_count++;
171 }
172 return *this;
173 }
174
175 HEXSTRING& HEXSTRING::operator=(const HEXSTRING_ELEMENT& other_value)
176 {
177 other_value.must_bound("Assignment of an unbound hexstring element to a "
178 "hexstring.");
179 unsigned char nibble_value = other_value.get_nibble();
180 clean_up();
181 init_struct(1);
182 val_ptr->nibbles_ptr[0] = nibble_value;
183 return *this;
184 }
185
186 boolean HEXSTRING::operator==(const HEXSTRING& other_value) const
187 {
188 must_bound("Unbound left operand of hexstring comparison.");
189 other_value.must_bound("Unbound right operand of hexstring comparison.");
190 if (val_ptr->n_nibbles != other_value.val_ptr->n_nibbles) return FALSE;
191 if (val_ptr->n_nibbles == 0) return TRUE;
192 clear_unused_nibble();
193 other_value.clear_unused_nibble();
194 return !memcmp(val_ptr->nibbles_ptr, other_value.val_ptr->nibbles_ptr,
195 (val_ptr->n_nibbles + 1) / 2);
196 }
197
198 boolean HEXSTRING::operator==(const HEXSTRING_ELEMENT& other_value) const
199 {
200 must_bound("Unbound left operand of hexstring comparison.");
201 other_value.must_bound("Unbound right operand of hexstring element "
202 "comparison.");
203 if (val_ptr->n_nibbles != 1) return FALSE;
204 return get_nibble(0) == other_value.get_nibble();
205 }
206
207 HEXSTRING HEXSTRING::operator+(const HEXSTRING& other_value) const
208 {
209 must_bound("Unbound left operand of hexstring concatenation.");
210 other_value.must_bound("Unbound right operand of hexstring concatenation.");
211
212 int left_n_nibbles = val_ptr->n_nibbles;
213 if (left_n_nibbles == 0) return other_value;
214
215 int right_n_nibbles = other_value.val_ptr->n_nibbles;
216 if (right_n_nibbles == 0) return *this;
217
218 int n_nibbles = left_n_nibbles + right_n_nibbles;
219 // the result
220 HEXSTRING ret_val(n_nibbles);
221
222 // the number of bytes used
223 int left_n_bytes = (left_n_nibbles + 1) / 2;
224 int right_n_bytes = (right_n_nibbles + 1) / 2;
225
226 // pointers to the data areas
227 const unsigned char *left_ptr = val_ptr->nibbles_ptr;
228 const unsigned char *right_ptr = other_value.val_ptr->nibbles_ptr;
229 unsigned char *dest_ptr = ret_val.val_ptr->nibbles_ptr;
230
231 memcpy(dest_ptr, left_ptr, left_n_bytes);
232
233 if (left_n_nibbles % 2) {
234 dest_ptr[left_n_bytes - 1] &= 0x0F;
235 int n_bytes = (n_nibbles + 1) / 2;
236 for (int i = left_n_bytes; i < n_bytes; i++) {
237 unsigned char right_byte = right_ptr[i - left_n_bytes];
238 dest_ptr[i - 1] |= right_byte << 4;
239 dest_ptr[i] = right_byte >> 4;
240 }
241 if (right_n_nibbles % 2) dest_ptr[n_bytes - 1] |= right_ptr[right_n_bytes
242 - 1] << 4;
243 }
244 else {
245 memcpy(dest_ptr + left_n_bytes, right_ptr, right_n_bytes);
246 ret_val.clear_unused_nibble();
247 }
248 return ret_val;
249 }
250
251 HEXSTRING HEXSTRING::operator+(const HEXSTRING_ELEMENT& other_value) const
252 {
253 must_bound("Unbound left operand of hexstring concatenation.");
254 other_value.must_bound("Unbound right operand of hexstring element "
255 "concatenation.");
256 int n_nibbles = val_ptr->n_nibbles;
257 HEXSTRING ret_val(n_nibbles + 1);
258 memcpy(ret_val.val_ptr->nibbles_ptr, val_ptr->nibbles_ptr, (n_nibbles + 1)
259 / 2);
260 ret_val.set_nibble(n_nibbles, other_value.get_nibble());
261 return ret_val;
262 }
263
264 HEXSTRING HEXSTRING::operator~() const
265 {
266 must_bound("Unbound hexstring operand of operator not4b.");
267
268 int n_bytes = (val_ptr->n_nibbles + 1) / 2;
269 if (n_bytes == 0) return *this;
270 HEXSTRING ret_val(val_ptr->n_nibbles);
271 for (int i = 0; i < n_bytes; i++) {
272 ret_val.val_ptr->nibbles_ptr[i] = ~val_ptr->nibbles_ptr[i];
273 }
274 ret_val.clear_unused_nibble();
275 return ret_val;
276 }
277
278 HEXSTRING HEXSTRING::operator&(const HEXSTRING& other_value) const
279 {
280 must_bound("Left operand of operator and4b is an unbound hexstring value.");
281 other_value.must_bound("Right operand of operator and4b is an unbound "
282 "hexstring value.");
283 int n_nibbles = val_ptr->n_nibbles;
284 if (n_nibbles != other_value.val_ptr->n_nibbles) TTCN_error("The hexstring "
285 "operands of operator and4b must have the same length.");
286 if (n_nibbles == 0) return *this;
287 HEXSTRING ret_val(n_nibbles);
288 int n_bytes = (n_nibbles + 1) / 2;
289 for (int i = 0; i < n_bytes; i++) {
290 ret_val.val_ptr->nibbles_ptr[i] = val_ptr->nibbles_ptr[i]
291 & other_value.val_ptr->nibbles_ptr[i];
292 }
293 ret_val.clear_unused_nibble();
294 return ret_val;
295 }
296
297 HEXSTRING HEXSTRING::operator&(const HEXSTRING_ELEMENT& other_value) const
298 {
299 must_bound("Left operand of operator and4b is an unbound hexstring value.");
300 other_value.must_bound("Right operand of operator and4b is an unbound "
301 "hexstring element.");
302 if (val_ptr->n_nibbles != 1) TTCN_error("The hexstring operands of operator "
303 "and4b must have the same length.");
304 unsigned char result = get_nibble(0) & other_value.get_nibble();
305 return HEXSTRING(1, &result);
306 }
307
308 HEXSTRING HEXSTRING::operator|(const HEXSTRING& other_value) const
309 {
310 must_bound("Left operand of operator or4b is an unbound hexstring value.");
311 other_value.must_bound("Right operand of operator or4b is an unbound "
312 "hexstring value.");
313 int n_nibbles = val_ptr->n_nibbles;
314 if (n_nibbles != other_value.val_ptr->n_nibbles) TTCN_error("The hexstring "
315 "operands of operator or4b must have the same length.");
316 if (n_nibbles == 0) return *this;
317 HEXSTRING ret_val(n_nibbles);
318 int n_bytes = (n_nibbles + 1) / 2;
319 for (int i = 0; i < n_bytes; i++) {
320 ret_val.val_ptr->nibbles_ptr[i] = val_ptr->nibbles_ptr[i]
321 | other_value.val_ptr->nibbles_ptr[i];
322 }
323 ret_val.clear_unused_nibble();
324 return ret_val;
325 }
326
327 HEXSTRING HEXSTRING::operator|(const HEXSTRING_ELEMENT& other_value) const
328 {
329 must_bound("Left operand of operator or4b is an unbound hexstring value.");
330 other_value.must_bound("Right operand of operator or4b is an unbound "
331 "hexstring element.");
332 if (val_ptr->n_nibbles != 1) TTCN_error("The hexstring operands of operator "
333 "or4b must have the same length.");
334 unsigned char result = get_nibble(0) | other_value.get_nibble();
335 return HEXSTRING(1, &result);
336 }
337
338 HEXSTRING HEXSTRING::operator^(const HEXSTRING& other_value) const
339 {
340 must_bound("Left operand of operator xor4b is an unbound hexstring value.");
341 other_value.must_bound("Right operand of operator xor4b is an unbound "
342 "hexstring value.");
343 int n_nibbles = val_ptr->n_nibbles;
344 if (n_nibbles != other_value.val_ptr->n_nibbles) TTCN_error("The hexstring "
345 "operands of operator xor4b must have the same length.");
346 if (n_nibbles == 0) return *this;
347 HEXSTRING ret_val(n_nibbles);
348 int n_bytes = (n_nibbles + 1) / 2;
349 for (int i = 0; i < n_bytes; i++) {
350 ret_val.val_ptr->nibbles_ptr[i] = val_ptr->nibbles_ptr[i]
351 ^ other_value.val_ptr->nibbles_ptr[i];
352 }
353 ret_val.clear_unused_nibble();
354 return ret_val;
355 }
356
357 HEXSTRING HEXSTRING::operator^(const HEXSTRING_ELEMENT& other_value) const
358 {
359 must_bound("Left operand of operator xor4b is an unbound hexstring value.");
360 other_value.must_bound("Right operand of operator xor4b is an unbound "
361 "hexstring element.");
362 if (val_ptr->n_nibbles != 1) TTCN_error("The hexstring operands of operator "
363 "xor4b must have the same length.");
364 unsigned char result = get_nibble(0) ^ other_value.get_nibble();
365 return HEXSTRING(1, &result);
366 }
367
368 HEXSTRING HEXSTRING::operator<<(int shift_count) const
369 {
370 must_bound("Unbound hexstring operand of shift left operator.");
371
372 if (shift_count > 0) {
373 int n_nibbles = val_ptr->n_nibbles;
374 if (n_nibbles == 0) return *this;
375 HEXSTRING ret_val(n_nibbles);
376 int n_bytes = (n_nibbles + 1) / 2;
377 clear_unused_nibble();
378 if (shift_count > n_nibbles) shift_count = n_nibbles;
379 int shift_bytes = shift_count / 2;
380 if (shift_count % 2) {
381 int byte_count = 0;
382 for (; byte_count < n_bytes - shift_bytes - 1; byte_count++) {
383 ret_val.val_ptr->nibbles_ptr[byte_count]
384 = (val_ptr->nibbles_ptr[byte_count + shift_bytes] >> 4)
385 | (val_ptr->nibbles_ptr[byte_count + shift_bytes + 1] << 4);
386 }
387 ret_val.val_ptr->nibbles_ptr[n_bytes - shift_bytes - 1]
388 = val_ptr->nibbles_ptr[n_bytes - 1] >> 4;
389 }
390 else {
391 memcpy(ret_val.val_ptr->nibbles_ptr, &val_ptr->nibbles_ptr[shift_count
392 / 2], (n_nibbles - shift_count + 1) / 2);
393 }
394 memset(ret_val.val_ptr->nibbles_ptr + n_bytes - shift_bytes, 0, shift_bytes);
395 return ret_val;
396 }
397 else if (shift_count == 0)
398 return *this;
399 else
400 return *this >> (-shift_count);
401 }
402
403 HEXSTRING HEXSTRING::operator<<(const INTEGER& shift_count) const
404 {
405 shift_count.must_bound("Unbound right operand of hexstring shift left "
406 "operator.");
407 return *this << (int) shift_count;
408 }
409
410 HEXSTRING HEXSTRING::operator>>(int shift_count) const
411 {
412 must_bound("Unbound operand of hexstring shift right operator.");
413
414 if (shift_count > 0) {
415 int n_nibbles = val_ptr->n_nibbles;
416 if (n_nibbles == 0) return *this;
417 HEXSTRING ret_val(n_nibbles);
418 int n_bytes = (n_nibbles + 1) / 2;
419 clear_unused_nibble();
420 if (shift_count > n_nibbles) shift_count = n_nibbles;
421 int shift_bytes = shift_count / 2;
422 memset(ret_val.val_ptr->nibbles_ptr, 0, shift_bytes);
423 if (shift_count % 2) {
424 ret_val.val_ptr->nibbles_ptr[shift_bytes] = val_ptr->nibbles_ptr[0] << 4;
425 int byte_count = shift_bytes + 1;
426 for (; byte_count < n_bytes; byte_count++) {
427 ret_val.val_ptr->nibbles_ptr[byte_count]
428 = (val_ptr->nibbles_ptr[byte_count - shift_bytes - 1] >> 4)
429 | (val_ptr->nibbles_ptr[byte_count - shift_bytes] << 4);
430 }
431 }
432 else {
433 memcpy(&ret_val.val_ptr->nibbles_ptr[shift_bytes], val_ptr->nibbles_ptr,
434 (n_nibbles - shift_count + 1) / 2);
435 }
436 ret_val.clear_unused_nibble();
437 return ret_val;
438 }
439 else if (shift_count == 0)
440 return *this;
441 else
442 return *this << (-shift_count);
443 }
444
445 HEXSTRING HEXSTRING::operator>>(const INTEGER& shift_count) const
446 {
447 shift_count.must_bound("Unbound right operand of hexstring shift right "
448 "operator.");
449 return *this >> (int) shift_count;
450 }
451
452 HEXSTRING HEXSTRING::operator<<=(int rotate_count) const
453 {
454 must_bound("Unbound hexstring operand of rotate left operator.");
455 if (val_ptr->n_nibbles == 0) return *this;
456 if (rotate_count >= 0) {
457 rotate_count %= val_ptr->n_nibbles;
458 if (rotate_count == 0) return *this;
459 return ((*this) << rotate_count) | ((*this) >> (val_ptr->n_nibbles
460 - rotate_count));
461 }
462 else
463 return *this >>= (-rotate_count);
464 }
465
466 HEXSTRING HEXSTRING::operator<<=(const INTEGER& rotate_count) const
467 {
468 rotate_count.must_bound("Unbound right operand of hexstring rotate left "
469 "operator.");
470 return *this <<= (int) rotate_count;
471 }
472
473 HEXSTRING HEXSTRING::operator>>=(int rotate_count) const
474 {
475 must_bound("Unbound hexstring operand of rotate right operator.");
476 if (val_ptr->n_nibbles == 0) return *this;
477 if (rotate_count >= 0) {
478 rotate_count %= val_ptr->n_nibbles;
479 if (rotate_count == 0) return *this;
480 return ((*this) >> rotate_count) | ((*this) << (val_ptr->n_nibbles
481 - rotate_count));
482 }
483 else
484 return *this <<= (-rotate_count);
485 }
486
487 HEXSTRING HEXSTRING::operator>>=(const INTEGER& rotate_count) const
488 {
489 rotate_count.must_bound("Unbound right operand of hexstring rotate right "
490 "operator.");
491 return *this >>= (int) rotate_count;
492 }
493
494 HEXSTRING_ELEMENT HEXSTRING::operator[](int index_value)
495 {
496 if (val_ptr == NULL && index_value == 0) {
497 init_struct(1);
498 clear_unused_nibble();
499 return HEXSTRING_ELEMENT(FALSE, *this, 0);
500 }
501 else {
502 must_bound("Accessing an element of an unbound hexstring value.");
503 if (index_value < 0) TTCN_error("Accessing an hexstring element using "
504 "a negative index (%d).", index_value);
505 int n_nibbles = val_ptr->n_nibbles;
506 if (index_value > n_nibbles) TTCN_error("Index overflow when accessing a "
507 "hexstring element: The index is %d, but the string has only %d "
508 "hexadecimal digits.", index_value, n_nibbles);
509 if (index_value == n_nibbles) {
510 if (val_ptr->ref_count == 1) {
511 if (n_nibbles % 2 == 0) val_ptr
512 = (hexstring_struct*) Realloc(val_ptr, MEMORY_SIZE(n_nibbles + 1));
513 val_ptr->n_nibbles++;
514 }
515 else {
516 hexstring_struct *old_ptr = val_ptr;
517 old_ptr->ref_count--;
518 init_struct(n_nibbles + 1);
519 memcpy(val_ptr->nibbles_ptr, old_ptr->nibbles_ptr, (n_nibbles + 1) / 2);
520 }
521 return HEXSTRING_ELEMENT(FALSE, *this, index_value);
522 }
523 else
524 return HEXSTRING_ELEMENT(TRUE, *this, index_value);
525 }
526 }
527
528 HEXSTRING_ELEMENT HEXSTRING::operator[](const INTEGER& index_value)
529 {
530 index_value.must_bound("Indexing a hexstring value with an unbound integer "
531 "value.");
532 return (*this)[(int) index_value];
533 }
534
535 const HEXSTRING_ELEMENT HEXSTRING::operator[](int index_value) const
536 {
537 must_bound("Accessing an element of an unbound hexstring value.");
538 if (index_value < 0) TTCN_error("Accessing an hexstring element using a "
539 "negative index (%d).", index_value);
540 if (index_value >= val_ptr->n_nibbles) TTCN_error("Index overflow when "
541 "accessing a hexstring element: The index is %d, but the string has only "
542 "%d hexadecimal digits.", index_value, val_ptr->n_nibbles);
543 return HEXSTRING_ELEMENT(TRUE, const_cast<HEXSTRING&> (*this), index_value);
544 }
545
546 const HEXSTRING_ELEMENT HEXSTRING::operator[](const INTEGER& index_value) const
547 {
548 index_value.must_bound("Indexing a hexstring value with an unbound integer "
549 "value.");
550 return (*this)[(int) index_value];
551 }
552
553 int HEXSTRING::lengthof() const
554 {
555 must_bound("Getting the length of an unbound hexstring value.");
556 return val_ptr->n_nibbles;
557 }
558
559 HEXSTRING::operator const unsigned char*() const
560 {
561 must_bound("Casting an unbound hexstring value to const unsigned char*.");
562 return val_ptr->nibbles_ptr;
563 }
564
565 void HEXSTRING::log() const
566 {
567 if (val_ptr != NULL) {
568 TTCN_Logger::log_char('\'');
569 for (int i = 0; i < val_ptr->n_nibbles; i++)
570 TTCN_Logger::log_hex(get_nibble(i));
571 TTCN_Logger::log_event_str("'H");
572 }
573 else {
574 TTCN_Logger::log_event_unbound();
575 }
576 }
577
578 void HEXSTRING::encode_text(Text_Buf& text_buf) const
579 {
580 must_bound("Text encoder: Encoding an unbound hexstring value");
581 int n_nibbles = val_ptr->n_nibbles;
582 text_buf.push_int(n_nibbles);
583 if (n_nibbles > 0) text_buf.push_raw((n_nibbles + 1) / 2,
584 val_ptr->nibbles_ptr);
585 }
586
587 void HEXSTRING::decode_text(Text_Buf& text_buf)
588 {
589 int n_nibbles = text_buf.pull_int().get_val();
590 if (n_nibbles < 0) TTCN_error(
591 "Text decoder: Invalid length was received for a hexstring.");
592 clean_up();
593 init_struct(n_nibbles);
594 if (n_nibbles > 0) {
595 text_buf.pull_raw((n_nibbles + 1) / 2, val_ptr->nibbles_ptr);
596 clear_unused_nibble();
597 }
598 }
599
600 void HEXSTRING::set_param(Module_Param& param) {
601 param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, "hexstring value");
602 Module_Param_Ptr mp = &param;
603 if (param.get_type() == Module_Param::MP_Reference) {
604 mp = param.get_referenced_param();
605 }
606 switch (mp->get_type()) {
607 case Module_Param::MP_Hexstring:
608 switch (param.get_operation_type()) {
609 case Module_Param::OT_ASSIGN: {
610 clean_up();
611 int n_nibbles = mp->get_string_size();
612 init_struct(n_nibbles);
613 memcpy(val_ptr->nibbles_ptr, mp->get_string_data(), (n_nibbles + 1) / 2);
614 clear_unused_nibble();
615 } break;
616 case Module_Param::OT_CONCAT:
617 if (is_bound()) {
618 *this = *this + HEXSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
619 } else {
620 *this = HEXSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
621 }
622 break;
623 default:
624 TTCN_error("Internal error: HEXSTRING::set_param()");
625 }
626 break;
627 case Module_Param::MP_Expression:
628 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
629 HEXSTRING operand1, operand2;
630 operand1.set_param(*mp->get_operand1());
631 operand2.set_param(*mp->get_operand2());
632 if (param.get_operation_type() == Module_Param::OT_CONCAT) {
633 *this = *this + operand1 + operand2;
634 }
635 else {
636 *this = operand1 + operand2;
637 }
638 }
639 else {
640 param.expr_type_error("a hexstring");
641 }
642 break;
643 default:
644 param.type_error("hexstring value");
645 break;
646 }
647 }
648
649 Module_Param* HEXSTRING::get_param(Module_Param_Name& /* param_name */) const
650 {
651 if (!is_bound()) {
652 return new Module_Param_Unbound();
653 }
654 int n_bytes = (val_ptr->n_nibbles + 1) / 2;
655 unsigned char* val_cpy = (unsigned char *)Malloc(n_bytes);
656 memcpy(val_cpy, val_ptr->nibbles_ptr, n_bytes);
657 return new Module_Param_Hexstring(val_ptr->n_nibbles, val_cpy);
658 }
659
660 void HEXSTRING::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
661 TTCN_EncDec::coding_t p_coding, ...) const
662 {
663 va_list pvar;
664 va_start(pvar, p_coding);
665 switch (p_coding) {
666 case TTCN_EncDec::CT_RAW: {
667 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
668 if (!p_td.raw) TTCN_EncDec_ErrorContext::error_internal(
669 "No RAW descriptor available for type '%s'.", p_td.name);
670 RAW_enc_tr_pos rp;
671 rp.level = 0;
672 rp.pos = NULL;
673 RAW_enc_tree root(true, NULL, &rp, 1, p_td.raw);
674 RAW_encode(p_td, root);
675 root.put_to_buf(p_buf);
676 break;}
677 case TTCN_EncDec::CT_XER: {
678 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
679 unsigned XER_coding=va_arg(pvar, unsigned);
680 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
681 break;}
682 case TTCN_EncDec::CT_JSON: {
683 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
684 if(!p_td.json)
685 TTCN_EncDec_ErrorContext::error_internal
686 ("No JSON descriptor available for type '%s'.", p_td.name);
687 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
688 JSON_encode(p_td, tok);
689 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
690 break;}
691 default:
692 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
693 }
694 va_end(pvar);
695 }
696
697 void HEXSTRING::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
698 TTCN_EncDec::coding_t p_coding, ...)
699 {
700 va_list pvar;
701 va_start(pvar, p_coding);
702 switch (p_coding) {
703 case TTCN_EncDec::CT_RAW: {
704 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
705 if (!p_td.raw) TTCN_EncDec_ErrorContext::error_internal(
706 "No RAW descriptor available for type '%s'.", p_td.name);
707 raw_order_t order;
708 switch (p_td.raw->top_bit_order) {
709 case TOP_BIT_LEFT:
710 order = ORDER_LSB;
711 break;
712 case TOP_BIT_RIGHT:
713 default:
714 order = ORDER_MSB;
715 }
716 if (RAW_decode(p_td, p_buf, p_buf.get_len() * 8, order) < 0) ec.error(
717 TTCN_EncDec::ET_INCOMPL_MSG,
718 "Can not decode type '%s', because invalid or incomplete"
719 " message was received", p_td.name);
720 break;}
721 case TTCN_EncDec::CT_XER: {
722 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
723 unsigned XER_coding=va_arg(pvar, unsigned);
724 XmlReaderWrap reader(p_buf);
725 int success = reader.Read();
726 for (; success==1; success=reader.Read()) {
727 int type = reader.NodeType();
728 if (type==XML_READER_TYPE_ELEMENT)
729 break;
730 }
731 XER_decode(*p_td.xer, reader, XER_coding, XER_NONE, 0);
732 size_t bytes = reader.ByteConsumed();
733 p_buf.set_pos(bytes);
734 break;}
735 case TTCN_EncDec::CT_JSON: {
736 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
737 if(!p_td.json)
738 TTCN_EncDec_ErrorContext::error_internal
739 ("No JSON descriptor available for type '%s'.", p_td.name);
740 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
741 if(JSON_decode(p_td, tok, false)<0)
742 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
743 "Can not decode type '%s', because invalid or incomplete"
744 " message was received"
745 , p_td.name);
746 p_buf.set_pos(tok.get_buf_pos());
747 break;}
748 default:
749 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
750 }
751 va_end(pvar);
752 }
753
754 int HEXSTRING::RAW_encode(const TTCN_Typedescriptor_t& p_td,
755 RAW_enc_tree& myleaf) const
756 {
757 // unsigned char *bc;
758 if (!is_bound()) {
759 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
760 "Encoding an unbound value.");
761 }
762 int nbits = val_ptr->n_nibbles * 4;
763 int align_length = p_td.raw->fieldlength ? p_td.raw->fieldlength - nbits : 0;
764 if ((nbits + align_length) < val_ptr->n_nibbles * 4) {
765 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
766 "There is no sufficient bits to encode '%s': ", p_td.name);
767 nbits = p_td.raw->fieldlength;
768 align_length = 0;
769 }
770
771 if (myleaf.must_free) Free(myleaf.body.leaf.data_ptr);
772
773 myleaf.must_free = false;
774 myleaf.data_ptr_used = true;
775 myleaf.body.leaf.data_ptr = val_ptr->nibbles_ptr;
776
777 if (p_td.raw->endianness == ORDER_MSB)
778 myleaf.align = -align_length;
779 else
780 myleaf.align = align_length;
781 return myleaf.length = nbits + align_length;
782 }
783
784 int HEXSTRING::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
785 int limit, raw_order_t top_bit_ord, boolean no_err, int /*sel_field*/,
786 boolean /*first_call*/)
787 {
788 int prepaddlength = buff.increase_pos_padd(p_td.raw->prepadding);
789 limit -= prepaddlength;
790 int decode_length = p_td.raw->fieldlength == 0
791 ? (limit / 4) * 4 : p_td.raw->fieldlength;
792 if ( p_td.raw->fieldlength > limit
793 || p_td.raw->fieldlength > (int) buff.unread_len_bit()) {
794 if (no_err) return -TTCN_EncDec::ET_LEN_ERR;
795 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR,
796 "There is not enough bits in the buffer to decode type %s.", p_td.name);
797 decode_length = ((limit > (int) buff.unread_len_bit()
798 ? (int)buff.unread_len_bit() : limit) / 4) * 4;
799 }
800 RAW_coding_par cp;
801 bool orders = false;
802 if (p_td.raw->bitorderinoctet == ORDER_MSB) orders = true;
803 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
804 cp.bitorder = orders ? ORDER_MSB : ORDER_LSB;
805 orders = false;
806 if (p_td.raw->byteorder == ORDER_MSB) orders = true;
807 if (p_td.raw->bitorderinfield == ORDER_MSB) orders = !orders;
808 cp.byteorder = orders ? ORDER_MSB : ORDER_LSB;
809 cp.fieldorder = p_td.raw->fieldorder;
810 cp.hexorder = p_td.raw->hexorder;
811 clean_up();
812 init_struct(decode_length / 4);
813 buff.get_b((size_t) decode_length, val_ptr->nibbles_ptr, cp, top_bit_ord);
814
815 if (p_td.raw->length_restrition != -1) {
816 val_ptr->n_nibbles = p_td.raw->length_restrition;
817 if (p_td.raw->endianness == ORDER_MSB) {
818 if ((decode_length - val_ptr->n_nibbles * 4) % 8) {
819 int bound = (decode_length - val_ptr->n_nibbles * 4) % 8;
820 int maxindex = (decode_length - 1) / 8;
821 for (int a = 0, b = (decode_length - val_ptr->n_nibbles * 4 - 1) / 8; a
822 < (val_ptr->n_nibbles * 4 + 7) / 8; a++, b++) {
823 val_ptr->nibbles_ptr[a] = val_ptr->nibbles_ptr[b] >> bound;
824 if (b < maxindex)
825 val_ptr->nibbles_ptr[a] = val_ptr->nibbles_ptr[b + 1] << (8 - bound);
826 }
827 }
828 else memmove(val_ptr->nibbles_ptr,
829 val_ptr->nibbles_ptr + (decode_length - val_ptr->n_nibbles * 4) / 8,
830 val_ptr->n_nibbles * 8 * sizeof(unsigned char));
831 }
832 }
833
834 /* for(int a=0; a<decode_length/8; a++)
835 val_ptr->nibbles_ptr[a]= ((val_ptr->nibbles_ptr[a]<<4)&0xf0) |
836 ((val_ptr->nibbles_ptr[a]>>4)&0x0f);*/
837 decode_length += buff.increase_pos_padd(p_td.raw->padding);
838 clear_unused_nibble();
839 return decode_length + prepaddlength;
840 }
841
842 // From Charstring.cc
843 extern char base64_decoder_table[256];
844 extern const char cb64[];
845
846 int HEXSTRING::XER_encode(const XERdescriptor_t& p_td,
847 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
848 {
849 if(!is_bound()) {
850 TTCN_EncDec_ErrorContext::error
851 (TTCN_EncDec::ET_UNBOUND, "Encoding an unbound hexstring value.");
852 }
853 int exer = is_exer(flavor |= SIMPLE_TYPE);
854 // SIMPLE_TYPE has no influence on is_exer, we set it for later
855 int encoded_length=(int)p_buf.get_len();
856 int empty_element = val_ptr==NULL || val_ptr->n_nibbles == 0;
857
858 flavor &= ~XER_RECOF; // octetstring doesn't care
859 begin_xml(p_td, p_buf, flavor, indent, empty_element);
860
861 if (exer && (p_td.xer_bits & BASE_64)) {
862 // bit more work
863 size_t clear_len = (val_ptr->n_nibbles + 1) / 2; // lengthof is in nibbles
864 const unsigned char * in = val_ptr->nibbles_ptr;
865
866 /* Encode (up to) 6 nibbles of cleartext into 4 bytes of base64.
867 * This is different from Octetstring.cc because hexstring's
868 * big-endian data storage. */
869 for (size_t i = 0; i < clear_len; i += 3) {
870 unsigned char first = in[i],
871 second = ((i+1 < clear_len) ? in[i+1] :0),
872 third = ((i+2 < clear_len) ? in[i+2] :0);
873
874 p_buf.put_c(cb64[(first & 0x0F) << 2 | first >> 6]);
875 p_buf.put_c(cb64[(first & 0x30) | (second & 0x0F)]);
876 p_buf.put_c(i+1 >= clear_len ? '='
877 : cb64[(second & 0xF0) >> 2 | (third & 0x0C) >> 2]);
878 p_buf.put_c( i+2 >= clear_len ? '='
879 : cb64[(third & 0x03) << 4 | (third & 0xF0) >> 4]);
880 } // next i
881 }
882 else {
883 CHARSTRING val = hex2str(*this);
884 p_buf.put_string(val);
885 }
886
887 end_xml(p_td, p_buf, flavor, indent, empty_element);
888
889 return (int)p_buf.get_len() - encoded_length;
890
891 }
892
893 unsigned int xlate_hs(cbyte*in, int phase, unsigned char*dest) {
894 static unsigned char nbytes[4] = { 3,1,1,2 };
895 unsigned char out[4];
896
897 out[0] = in[0] >> 2 | (in[0] & 3) << 6 | (in[1] & 0x30);
898 out[1] = (in[1] & 0x0F) | (in[2] & 0x3C) << 2;
899 out[2] = (in[3] & 0x0F) << 4 | (in[3] & 0x30) >> 4 | (in[2] & 3) << 2;
900 memcpy(dest, out, nbytes[phase]);
901 return nbytes[phase];
902 }
903
904
905 /* Here's how the bits get transferred to and from Base64:
906
907 Titan stores the hex digits in "little endian order", the first (index 0)
908 goes into the lower nibble, the second goes into the high nibble
909 of the first byte. So, For the hexstring value 'DECAFBAD'H,
910 Titan stores the following bytes: ED AC BF DA
911
912 Because of this, the bit shifting is different. The first three bytes
913
914 3x8 bits: eeeedddd aaaacccc bbbbffff
915
916 4x6 bits: ddddee eecccc aaaaff ffbbbb
917
918 */
919
920 int HEXSTRING::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
921 unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
922 {
923 int exer = is_exer(flavor);
924 int success = reader.Ok(), depth = -1, type;
925 boolean own_tag = !is_exerlist(flavor) && !(exer && (p_td.xer_bits & UNTAGGED));
926
927 const char * value = 0;
928 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
929 const char * name = verify_name(reader, p_td, exer);
930 (void)name;
931 }
932 else
933 if (own_tag) for (; success == 1; success = reader.Read()) {
934 type = reader.NodeType();
935 if (XML_READER_TYPE_ELEMENT == type) {
936 verify_name(reader, p_td, exer);
937 depth = reader.Depth();
938 if (reader.IsEmptyElement()) {
939 if (exer && p_td.dfeValue != 0) {
940 *this = *static_cast<const HEXSTRING*> (p_td.dfeValue);
941 }
942 else init_struct(0);
943 reader.Read();
944 goto finished;
945 }
946 }
947 else if (XML_READER_TYPE_TEXT == type && depth != -1) break;
948 else if (XML_READER_TYPE_END_ELEMENT == type) {
949 // End tag without intervening #text == empty content
950 verify_end(reader, p_td, depth, exer);
951 if (exer && p_td.dfeValue != 0) {
952 *this = *static_cast<const HEXSTRING*>(p_td.dfeValue);
953 }
954 else init_struct(0);
955 reader.Read();
956 goto finished;
957 }
958 }
959
960 type = reader.NodeType();
961 if (success == 1 && (XML_READER_TYPE_TEXT == type || XML_READER_TYPE_ATTRIBUTE == type)) {
962 value = (const char *)reader.Value();
963 size_t len = value ? strlen(value) : 0;
964
965 if (exer && (p_td.xer_bits & BASE_64)) {
966 xmlChar in[4];
967
968 int phase = 0;
969 init_struct(len * 3 / 2); // 4 bytes decoded into 3 octets (6 nibbles)
970 unsigned char * dest = val_ptr->nibbles_ptr;
971
972 for (size_t o=0; o<len; ++o) {
973 xmlChar c = value[o];
974 if(c == '=') { // padding starts
975 dest += xlate_hs(in, phase, dest);
976 break;
977 }
978
979 int val = base64_decoder_table[c];
980 if(val >= 0) {
981 in[phase] = val;
982 phase = (phase + 1) % 4;
983 if(phase == 0) {
984 dest += xlate_hs(in,phase, dest);
985 in[0]=in[1]=in[2]=in[3]=0;
986 }
987 }
988 else if (exer && (flavor & EXIT_ON_ERROR)) {
989 clean_up();
990 return -1;
991 } else {
992 TTCN_EncDec_ErrorContext::warning(
993 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
994 "Invalid character for Base64 '%02X'", c);
995 }
996 } // while
997 // adjust
998 val_ptr->n_nibbles = (dest - val_ptr->nibbles_ptr) * 2;
999
1000 }
1001 else { // not base64
1002 init_struct(len);
1003
1004 for (size_t i = 0; i < len; ++i) {
1005 unsigned char nibble = char_to_hexdigit(value[i]);
1006 if (nibble > 0x0F) {
1007 if (exer && (flavor & EXIT_ON_ERROR)) {
1008 clean_up();
1009 return -1;
1010 } else {
1011 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
1012 "The hexstring value may contain hexadecimal digits only. "
1013 "Character \"%c\" was found.", value[i]);
1014 nibble=0;
1015 }
1016 }
1017 //val_ptr->nibbles_ptr[i] = nibble;
1018 set_nibble(i, nibble);
1019 } // next
1020 } // if base64
1021 } // if success
1022
1023 if (exer && (p_td.xer_bits & XER_ATTRIBUTE)) {
1024 // Let the caller do reader.AdvanceAttribute();
1025 }
1026 else
1027 if (own_tag) for (success = reader.Read(); success == 1; success = reader.Read()) {
1028 type = reader.NodeType();
1029 if (XML_READER_TYPE_END_ELEMENT == type) {
1030 verify_end(reader, p_td, depth, exer);
1031 if (val_ptr == 0 && p_td.dfeValue != 0) {
1032 // The end tag must have followed the start tag
1033 *this = *static_cast<const HEXSTRING*>(p_td.dfeValue);
1034 }
1035 reader.Read(); // one last time
1036 break;
1037 }
1038 }
1039 finished:
1040 return 1; // decode successful
1041 }
1042
1043 int HEXSTRING::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
1044 {
1045 if (!is_bound()) {
1046 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
1047 "Encoding an unbound hexstring value.");
1048 return -1;
1049 }
1050
1051 char* tmp_str = (char*)Malloc(val_ptr->n_nibbles + 3);
1052 tmp_str[0] = '\"';
1053 tmp_str[val_ptr->n_nibbles + 1] = '\"';
1054 for(int i = 0; i < val_ptr->n_nibbles; ++i) {
1055 if (i % 2) {
1056 tmp_str[i + 1] = hexdigit_to_char(val_ptr->nibbles_ptr[i / 2] >> 4);
1057 } else {
1058 tmp_str[i + 1] = hexdigit_to_char(val_ptr->nibbles_ptr[i / 2] & 0x0F);
1059 }
1060 }
1061 tmp_str[val_ptr->n_nibbles + 2] = 0;
1062 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);
1063 Free(tmp_str);
1064 return enc_len;
1065 }
1066
1067 int HEXSTRING::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
1068 {
1069 json_token_t token = JSON_TOKEN_NONE;
1070 char* value = 0;
1071 size_t value_len = 0;
1072 boolean error = false;
1073 int dec_len = 0;
1074 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
1075 if (use_default) {
1076 // No JSON data in the buffer -> use default value
1077 value = (char*)p_td.json->default_value;
1078 value_len = strlen(value);
1079 } else {
1080 dec_len = p_tok.get_next_token(&token, &value, &value_len);
1081 }
1082 if (JSON_TOKEN_ERROR == token) {
1083 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
1084 return JSON_ERROR_FATAL;
1085 }
1086 else if (JSON_TOKEN_STRING == token || use_default) {
1087 if (use_default || (value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"')) {
1088 if (!use_default) {
1089 // The default value doesn't have quotes around it
1090 value_len -= 2;
1091 ++value;
1092 }
1093 init_struct(value_len);
1094 for (size_t i = 0; i < value_len; ++i) {
1095 unsigned char nibble = char_to_hexdigit(value[i]);
1096 if (nibble <= 0x0F) {
1097 set_nibble(i, nibble);
1098 } else {
1099 error = true;
1100 }
1101 }
1102 } else {
1103 error = true;
1104 }
1105 } else {
1106 return JSON_ERROR_INVALID_TOKEN;
1107 }
1108
1109 if (error) {
1110 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "hexstring");
1111 if (p_silent) {
1112 clean_up();
1113 }
1114 return JSON_ERROR_FATAL;
1115 }
1116 return dec_len;
1117 }
1118
1119
1120 //---------------------- hexstring element class ----------------------
1121
1122 HEXSTRING_ELEMENT::HEXSTRING_ELEMENT(boolean par_bound_flag,
1123 HEXSTRING& par_str_val, int par_nibble_pos) :
1124 bound_flag(par_bound_flag), str_val(par_str_val), nibble_pos(par_nibble_pos)
1125 {
1126 }
1127
1128 HEXSTRING_ELEMENT& HEXSTRING_ELEMENT::operator=(
1129 const HEXSTRING_ELEMENT& other_value)
1130 {
1131 other_value.must_bound("Assignment of an unbound hexstring element.");
1132 bound_flag = TRUE;
1133 str_val.copy_value();
1134 str_val.set_nibble(nibble_pos, other_value.str_val.get_nibble(
1135 other_value.nibble_pos));
1136 return *this;
1137 }
1138
1139 HEXSTRING_ELEMENT& HEXSTRING_ELEMENT::operator=(const HEXSTRING& other_value)
1140 {
1141 other_value.must_bound("Assignment of unbound hexstring value.");
1142 if (other_value.lengthof() != 1) TTCN_error(
1143 "Assignment of a hexstring value "
1144 "with length other than 1 to a hexstring element.");
1145 bound_flag = TRUE;
1146 str_val.copy_value();
1147 str_val.set_nibble(nibble_pos, other_value.get_nibble(0));
1148 return *this;
1149 }
1150
1151 boolean HEXSTRING_ELEMENT::operator==(const HEXSTRING_ELEMENT& other_value) const
1152 {
1153 must_bound("Unbound left operand of hexstring element comparison.");
1154 other_value.must_bound("Unbound right operand of hexstring comparison.");
1155 return str_val.get_nibble(nibble_pos) == other_value.str_val.get_nibble(
1156 other_value.nibble_pos);
1157 }
1158
1159 boolean HEXSTRING_ELEMENT::operator==(const HEXSTRING& other_value) const
1160 {
1161 must_bound("Unbound left operand of hexstring element comparison.");
1162 other_value.must_bound("Unbound right operand of hexstring element "
1163 "comparison.");
1164 if (other_value.val_ptr->n_nibbles != 1) return FALSE;
1165 return str_val.get_nibble(nibble_pos) == other_value.get_nibble(0);
1166 }
1167
1168 HEXSTRING HEXSTRING_ELEMENT::operator+(const HEXSTRING& other_value) const
1169 {
1170 must_bound("Unbound left operand of hexstring element concatenation.");
1171 other_value.must_bound("Unbound right operand of hexstring concatenation.");
1172 int n_nibbles = other_value.val_ptr->n_nibbles;
1173 HEXSTRING ret_val(n_nibbles + 1);
1174 const unsigned char *src_ptr = other_value.val_ptr->nibbles_ptr;
1175 unsigned char *dest_ptr = ret_val.val_ptr->nibbles_ptr;
1176 dest_ptr[0] = str_val.get_nibble(nibble_pos);
1177 // bytes in the result minus 1
1178 int n_complete_bytes = n_nibbles / 2;
1179 for (int i = 0; i < n_complete_bytes; i++) {
1180 unsigned char right_octet = src_ptr[i];
1181 dest_ptr[i] |= right_octet << 4;
1182 dest_ptr[i + 1] = right_octet >> 4;
1183 }
1184 if (n_nibbles % 2) dest_ptr[n_complete_bytes] |= src_ptr[n_complete_bytes]
1185 << 4;
1186 return ret_val;
1187 }
1188
1189 HEXSTRING HEXSTRING_ELEMENT::operator+(const HEXSTRING_ELEMENT& other_value) const
1190 {
1191 must_bound("Unbound left operand of hexstring element concatenation.");
1192 other_value.must_bound("Unbound right operand of hexstring element "
1193 "concatenation.");
1194 unsigned char result = str_val.get_nibble(nibble_pos)
1195 | (other_value.str_val.get_nibble(other_value.nibble_pos) << 4);
1196 return HEXSTRING(2, &result);
1197 }
1198
1199 HEXSTRING HEXSTRING_ELEMENT::operator~() const
1200 {
1201 must_bound("Unbound hexstring element operand of operator not4b.");
1202 unsigned char result = ~str_val.get_nibble(nibble_pos) & 0x0F;
1203 return HEXSTRING(1, &result);
1204 }
1205
1206 HEXSTRING HEXSTRING_ELEMENT::operator&(const HEXSTRING& other_value) const
1207 {
1208 must_bound("Left operand of operator and4b is an unbound hexstring element.");
1209 other_value.must_bound("Right operand of operator and4b is an unbound "
1210 "hexstring value.");
1211 if (other_value.val_ptr->n_nibbles != 1) TTCN_error("The hexstring operands "
1212 "of operator and4b must have the same length.");
1213 unsigned char result = str_val.get_nibble(nibble_pos)
1214 & other_value.get_nibble(0);
1215 return HEXSTRING(1, &result);
1216 }
1217
1218 HEXSTRING HEXSTRING_ELEMENT::operator&(const HEXSTRING_ELEMENT& other_value) const
1219 {
1220 must_bound("Left operand of operator and4b is an unbound hexstring element.");
1221 other_value.must_bound("Right operand of operator and4b is an unbound "
1222 "hexstring element.");
1223 unsigned char result = str_val.get_nibble(nibble_pos)
1224 & other_value.str_val.get_nibble(other_value.nibble_pos);
1225 return HEXSTRING(1, &result);
1226 }
1227
1228 HEXSTRING HEXSTRING_ELEMENT::operator|(const HEXSTRING& other_value) const
1229 {
1230 must_bound("Left operand of operator or4b is an unbound hexstring element.");
1231 other_value.must_bound("Right operand of operator or4b is an unbound "
1232 "hexstring value.");
1233 if (other_value.val_ptr->n_nibbles != 1) TTCN_error("The hexstring operands "
1234 "of operator or4b must have the same length.");
1235 unsigned char result = str_val.get_nibble(nibble_pos)
1236 | other_value.get_nibble(0);
1237 return HEXSTRING(1, &result);
1238 }
1239
1240 HEXSTRING HEXSTRING_ELEMENT::operator|(const HEXSTRING_ELEMENT& other_value) const
1241 {
1242 must_bound("Left operand of operator or4b is an unbound hexstring element.");
1243 other_value.must_bound("Right operand of operator or4b is an unbound "
1244 "hexstring element.");
1245 unsigned char result = str_val.get_nibble(nibble_pos)
1246 | other_value.str_val.get_nibble(other_value.nibble_pos);
1247 return HEXSTRING(1, &result);
1248 }
1249
1250 HEXSTRING HEXSTRING_ELEMENT::operator^(const HEXSTRING& other_value) const
1251 {
1252 must_bound("Left operand of operator xor4b is an unbound hexstring element.");
1253 other_value.must_bound("Right operand of operator xor4b is an unbound "
1254 "hexstring value.");
1255 if (other_value.val_ptr->n_nibbles != 1) TTCN_error("The hexstring operands "
1256 "of operator xor4b must have the same length.");
1257 unsigned char result = str_val.get_nibble(nibble_pos)
1258 ^ other_value.get_nibble(0);
1259 return HEXSTRING(1, &result);
1260 }
1261
1262 HEXSTRING HEXSTRING_ELEMENT::operator^(const HEXSTRING_ELEMENT& other_value) const
1263 {
1264 must_bound("Left operand of operator xor4b is an unbound hexstring element.");
1265 other_value.must_bound("Right operand of operator xor4b is an unbound "
1266 "hexstring element.");
1267 unsigned char result = str_val.get_nibble(nibble_pos)
1268 ^ other_value.str_val.get_nibble(other_value.nibble_pos);
1269 return HEXSTRING(1, &result);
1270 }
1271
1272 unsigned char HEXSTRING_ELEMENT::get_nibble() const
1273 {
1274 return str_val.get_nibble(nibble_pos);
1275 }
1276
1277 void HEXSTRING_ELEMENT::log() const
1278 {
1279 if (bound_flag) {
1280 TTCN_Logger::log_char('\'');
1281 TTCN_Logger::log_hex(str_val.get_nibble(nibble_pos));
1282 TTCN_Logger::log_event_str("'H");
1283 }
1284 else {
1285 TTCN_Logger::log_event_unbound();
1286 }
1287 }
1288
1289 //---------------------- hexstring template class ----------------------
1290
1291 void HEXSTRING_template::clean_up()
1292 {
1293 switch (template_selection) {
1294 case VALUE_LIST:
1295 case COMPLEMENTED_LIST:
1296 delete[] value_list.list_value;
1297 break;
1298 case STRING_PATTERN:
1299 if (pattern_value->ref_count > 1)
1300 pattern_value->ref_count--;
1301 else if (pattern_value->ref_count == 1)
1302 Free(pattern_value);
1303 else
1304 TTCN_error("Internal error: Invalid reference counter in a hexstring "
1305 "pattern.");
1306 break;
1307 case DECODE_MATCH:
1308 if (dec_match->ref_count > 1) {
1309 dec_match->ref_count--;
1310 }
1311 else if (dec_match->ref_count == 1) {
1312 delete dec_match->instance;
1313 delete dec_match;
1314 }
1315 else {
1316 TTCN_error("Internal error: Invalid reference counter in a "
1317 "decoded content match.");
1318 }
1319 break;
1320 default:
1321 break;
1322 }
1323 template_selection = UNINITIALIZED_TEMPLATE;
1324 }
1325
1326 void HEXSTRING_template::copy_template(const HEXSTRING_template& other_value)
1327 {
1328 switch (other_value.template_selection) {
1329 case SPECIFIC_VALUE:
1330 single_value = other_value.single_value;
1331 break;
1332 case OMIT_VALUE:
1333 case ANY_VALUE:
1334 case ANY_OR_OMIT:
1335 break;
1336 case VALUE_LIST:
1337 case COMPLEMENTED_LIST:
1338 value_list.n_values = other_value.value_list.n_values;
1339 value_list.list_value = new HEXSTRING_template[value_list.n_values];
1340 for (unsigned int i = 0; i < value_list.n_values; i++)
1341 value_list.list_value[i].copy_template(
1342 other_value.value_list.list_value[i]);
1343 break;
1344 case STRING_PATTERN:
1345 pattern_value = other_value.pattern_value;
1346 pattern_value->ref_count++;
1347 break;
1348 case DECODE_MATCH:
1349 dec_match = other_value.dec_match;
1350 dec_match->ref_count++;
1351 break;
1352 default:
1353 TTCN_error("Copying an uninitialized/unsupported hexstring template.");
1354 }
1355 set_selection(other_value);
1356 }
1357
1358 /*
1359 This is the same algorithm that match_array uses
1360 to match 'record of' types.
1361 The only differences are: how two elements are matched and
1362 how an asterisk or ? is identified in the template
1363 */
1364 boolean HEXSTRING_template::match_pattern(
1365 const hexstring_pattern_struct *string_pattern,
1366 const HEXSTRING::hexstring_struct *string_value)
1367 {
1368 // the empty pattern matches the empty hexstring only
1369 if (string_pattern->n_elements == 0) return string_value->n_nibbles == 0;
1370
1371 int value_index = 0;
1372 unsigned int template_index = 0;
1373 int last_asterisk = -1;
1374 int last_value_to_asterisk = -1;
1375 //the following variables are just to speed up the function
1376 unsigned char pattern_element;
1377 unsigned char octet;
1378 unsigned char hex_digit;
1379
1380 for (;;) {
1381 pattern_element = string_pattern->elements_ptr[template_index];
1382 if (pattern_element < 16) {
1383 octet = string_value->nibbles_ptr[value_index / 2];
1384 if (value_index % 2)
1385 hex_digit = octet >> 4;
1386 else
1387 hex_digit = octet & 0x0F;
1388 if (hex_digit == pattern_element) {
1389 value_index++;
1390 template_index++;
1391 }
1392 else {
1393 if (last_asterisk == -1) return FALSE;
1394 template_index = last_asterisk + 1;
1395 value_index = ++last_value_to_asterisk;
1396 }
1397 }
1398 else if (pattern_element == 16) {//?
1399 value_index++;
1400 template_index++;
1401 }
1402 else if (pattern_element == 17) {//*
1403 last_asterisk = template_index++;
1404 last_value_to_asterisk = value_index;
1405 }
1406 else
1407 TTCN_error("Internal error: invalid element in a hexstring "
1408 "pattern.");
1409
1410 if (value_index == string_value->n_nibbles && template_index
1411 == string_pattern->n_elements) {
1412 return TRUE;
1413 }
1414 else if (template_index == string_pattern->n_elements) {
1415 if (string_pattern->elements_ptr[template_index - 1] == 17) {
1416 return TRUE;
1417 }
1418 else if (last_asterisk == -1) {
1419 return FALSE;
1420 }
1421 else {
1422 template_index = last_asterisk + 1;
1423 value_index = ++last_value_to_asterisk;
1424 }
1425 }
1426 else if (value_index == string_value->n_nibbles) {
1427 while (template_index < string_pattern->n_elements
1428 && string_pattern->elements_ptr[template_index] == 17)
1429 template_index++;
1430
1431 return template_index == string_pattern->n_elements;
1432 }
1433 }
1434 }
1435
1436 HEXSTRING_template::HEXSTRING_template()
1437 {
1438 }
1439
1440 HEXSTRING_template::HEXSTRING_template(template_sel other_value) :
1441 Restricted_Length_Template(other_value)
1442 {
1443 check_single_selection(other_value);
1444 }
1445
1446 HEXSTRING_template::HEXSTRING_template(const HEXSTRING& other_value) :
1447 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1448 {
1449 }
1450
1451 HEXSTRING_template::HEXSTRING_template(const HEXSTRING_ELEMENT& other_value) :
1452 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1453 {
1454 }
1455
1456 HEXSTRING_template::HEXSTRING_template(const OPTIONAL<HEXSTRING>& other_value)
1457 {
1458 switch (other_value.get_selection()) {
1459 case OPTIONAL_PRESENT:
1460 set_selection(SPECIFIC_VALUE);
1461 single_value = (const HEXSTRING&) other_value;
1462 break;
1463 case OPTIONAL_OMIT:
1464 set_selection(OMIT_VALUE);
1465 break;
1466 default:
1467 TTCN_error("Creating a hexstring template from an unbound optional field.");
1468 }
1469 }
1470
1471 HEXSTRING_template::HEXSTRING_template(unsigned int n_elements,
1472 const unsigned char *pattern_elements) :
1473 Restricted_Length_Template(STRING_PATTERN)
1474 {
1475 pattern_value
1476 = (hexstring_pattern_struct*) Malloc(sizeof(hexstring_pattern_struct) + n_elements - 1);
1477 pattern_value->ref_count = 1;
1478 pattern_value->n_elements = n_elements;
1479 memcpy(pattern_value->elements_ptr, pattern_elements, n_elements);
1480 }
1481
1482 HEXSTRING_template::HEXSTRING_template(const HEXSTRING_template& other_value) :
1483 Restricted_Length_Template()
1484 {
1485 copy_template(other_value);
1486 }
1487
1488 HEXSTRING_template::~HEXSTRING_template()
1489 {
1490 clean_up();
1491 }
1492
1493 HEXSTRING_template& HEXSTRING_template::operator=(template_sel other_value)
1494 {
1495 check_single_selection(other_value);
1496 clean_up();
1497 set_selection(other_value);
1498 return *this;
1499 }
1500
1501 HEXSTRING_template& HEXSTRING_template::operator=(const HEXSTRING& other_value)
1502 {
1503 other_value.must_bound("Assignment of an unbound hexstring value to a "
1504 "template.");
1505 clean_up();
1506 set_selection(SPECIFIC_VALUE);
1507 single_value = other_value;
1508 return *this;
1509 }
1510
1511 HEXSTRING_template& HEXSTRING_template::operator=(
1512 const HEXSTRING_ELEMENT& other_value)
1513 {
1514 other_value.must_bound("Assignment of an unbound hexstring element to a "
1515 "template.");
1516 clean_up();
1517 set_selection(SPECIFIC_VALUE);
1518 single_value = other_value;
1519 return *this;
1520 }
1521
1522 HEXSTRING_template& HEXSTRING_template::operator=(
1523 const OPTIONAL<HEXSTRING>& other_value)
1524 {
1525 clean_up();
1526 switch (other_value.get_selection()) {
1527 case OPTIONAL_PRESENT:
1528 set_selection(SPECIFIC_VALUE);
1529 single_value = (const HEXSTRING&) other_value;
1530 break;
1531 case OPTIONAL_OMIT:
1532 set_selection(OMIT_VALUE);
1533 break;
1534 default:
1535 TTCN_error("Assignment of an unbound optional field to a hexstring "
1536 "template.");
1537 }
1538 return *this;
1539 }
1540
1541 HEXSTRING_template& HEXSTRING_template::operator=(
1542 const HEXSTRING_template& other_value)
1543 {
1544 if (&other_value != this) {
1545 clean_up();
1546 copy_template(other_value);
1547 }
1548 return *this;
1549 }
1550
1551 HEXSTRING_ELEMENT HEXSTRING_template::operator[](int index_value)
1552 {
1553 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1554 TTCN_error("Accessing a hexstring element of a non-specific hexstring "
1555 "template.");
1556 return single_value[index_value];
1557 }
1558
1559 HEXSTRING_ELEMENT HEXSTRING_template::operator[](const INTEGER& index_value)
1560 {
1561 index_value.must_bound("Indexing a hexstring template with an unbound "
1562 "integer value.");
1563 return (*this)[(int)index_value];
1564 }
1565
1566 const HEXSTRING_ELEMENT HEXSTRING_template::operator[](int index_value) const
1567 {
1568 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1569 TTCN_error("Accessing a hexstring element of a non-specific hexstring "
1570 "template.");
1571 return single_value[index_value];
1572 }
1573
1574 const HEXSTRING_ELEMENT HEXSTRING_template::operator[](const INTEGER& index_value) const
1575 {
1576 index_value.must_bound("Indexing a hexstring template with an unbound "
1577 "integer value.");
1578 return (*this)[(int)index_value];
1579 }
1580
1581 boolean HEXSTRING_template::match(const HEXSTRING& other_value,
1582 boolean /* legacy */) const
1583 {
1584 if (!other_value.is_bound()) return FALSE;
1585 if (!match_length(other_value.val_ptr->n_nibbles)) return FALSE;
1586 switch (template_selection) {
1587 case SPECIFIC_VALUE:
1588 return single_value == other_value;
1589 case OMIT_VALUE:
1590 return FALSE;
1591 case ANY_VALUE:
1592 case ANY_OR_OMIT:
1593 return TRUE;
1594 case VALUE_LIST:
1595 case COMPLEMENTED_LIST:
1596 for (unsigned int i = 0; i < value_list.n_values; i++)
1597 if (value_list.list_value[i].match(other_value)) return template_selection
1598 == VALUE_LIST;
1599 return template_selection == COMPLEMENTED_LIST;
1600 case STRING_PATTERN:
1601 return match_pattern(pattern_value, other_value.val_ptr);
1602 case DECODE_MATCH: {
1603 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);
1604 TTCN_EncDec::clear_error();
1605 OCTETSTRING os(hex2oct(other_value));
1606 TTCN_Buffer buff(os);
1607 boolean ret_val = dec_match->instance->match(buff);
1608 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT);
1609 TTCN_EncDec::clear_error();
1610 return ret_val; }
1611 default:
1612 TTCN_error("Matching an uninitialized/unsupported hexstring template.");
1613 }
1614 return FALSE;
1615 }
1616
1617 const HEXSTRING& HEXSTRING_template::valueof() const
1618 {
1619 if (template_selection != SPECIFIC_VALUE || is_ifpresent) TTCN_error(
1620 "Performing a valueof or send operation on a non-specific "
1621 "hexstring template.");
1622 return single_value;
1623 }
1624
1625 int HEXSTRING_template::lengthof() const
1626 {
1627 int min_length;
1628 boolean has_any_or_none;
1629 if (is_ifpresent) TTCN_error(
1630 "Performing lengthof() operation on a hexstring template "
1631 "which has an ifpresent attribute.");
1632 switch (template_selection) {
1633 case SPECIFIC_VALUE:
1634 min_length = single_value.lengthof();
1635 has_any_or_none = FALSE;
1636 break;
1637 case OMIT_VALUE:
1638 TTCN_error("Performing lengthof() operation on a hexstring template "
1639 "containing omit value.");
1640 case ANY_VALUE:
1641 case ANY_OR_OMIT:
1642 min_length = 0;
1643 has_any_or_none = TRUE; // max. length is infinity
1644 break;
1645 case VALUE_LIST: {
1646 // error if any element does not have length or the lengths differ
1647 if (value_list.n_values < 1) TTCN_error("Internal error: "
1648 "Performing lengthof() operation on a hexstring template "
1649 "containing an empty list.");
1650 int item_length = value_list.list_value[0].lengthof();
1651 for (unsigned int i = 1; i < value_list.n_values; i++) {
1652 if (value_list.list_value[i].lengthof() != item_length) TTCN_error(
1653 "Performing lengthof() operation on a hexstring template "
1654 "containing a value list with different lengths.");
1655 }
1656 min_length = item_length;
1657 has_any_or_none = FALSE;
1658 break;
1659 }
1660 case COMPLEMENTED_LIST:
1661 TTCN_error("Performing lengthof() operation on a hexstring template "
1662 "containing complemented list.");
1663 case STRING_PATTERN:
1664 min_length = 0;
1665 has_any_or_none = FALSE; // TRUE if * chars in the pattern
1666 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1667 if (pattern_value->elements_ptr[i] < 17)
1668 min_length++; // case of 0-F, ?
1669 else
1670 has_any_or_none = TRUE; // case of * character
1671 }
1672 break;
1673 default:
1674 TTCN_error("Performing lengthof() operation on an "
1675 "uninitialized/unsupported hexstring template.");
1676 }
1677 return check_section_is_single(min_length, has_any_or_none, "length", "a",
1678 "hexstring template");
1679 }
1680
1681 void HEXSTRING_template::set_type(template_sel template_type,
1682 unsigned int list_length)
1683 {
1684 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST &&
1685 template_type != DECODE_MATCH) TTCN_error(
1686 "Setting an invalid list type for a hexstring template.");
1687 clean_up();
1688 set_selection(template_type);
1689 if (template_type != DECODE_MATCH) {
1690 value_list.n_values = list_length;
1691 value_list.list_value = new HEXSTRING_template[list_length];
1692 }
1693 }
1694
1695 HEXSTRING_template& HEXSTRING_template::list_item(unsigned int list_index)
1696 {
1697 if (template_selection != VALUE_LIST && template_selection
1698 != COMPLEMENTED_LIST) TTCN_error(
1699 "Accessing a list element of a non-list hexstring template.");
1700 if (list_index >= value_list.n_values) TTCN_error(
1701 "Index overflow in a hexstring value list template.");
1702 return value_list.list_value[list_index];
1703 }
1704
1705 void HEXSTRING_template::set_decmatch(Dec_Match_Interface* new_instance)
1706 {
1707 if (template_selection != DECODE_MATCH) {
1708 TTCN_error("Setting the decoded content matching mechanism of a non-decmatch "
1709 "hexstring template.");
1710 }
1711 dec_match = new decmatch_struct;
1712 dec_match->ref_count = 1;
1713 dec_match->instance = new_instance;
1714 }
1715
1716 void HEXSTRING_template::log() const
1717 {
1718 switch (template_selection) {
1719 case SPECIFIC_VALUE:
1720 single_value.log();
1721 break;
1722 case COMPLEMENTED_LIST:
1723 TTCN_Logger::log_event_str("complement ");
1724 // no break
1725 case VALUE_LIST:
1726 TTCN_Logger::log_char('(');
1727 for (unsigned int i = 0; i < value_list.n_values; i++) {
1728 if (i > 0) TTCN_Logger::log_event_str(", ");
1729 value_list.list_value[i].log();
1730 }
1731 TTCN_Logger::log_char(')');
1732 break;
1733 case STRING_PATTERN:
1734 TTCN_Logger::log_char('\'');
1735 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1736 unsigned char pattern = pattern_value->elements_ptr[i];
1737 if (pattern < 16)
1738 TTCN_Logger::log_hex(pattern);
1739 else if (pattern == 16)
1740 TTCN_Logger::log_char('?');
1741 else if (pattern == 17)
1742 TTCN_Logger::log_char('*');
1743 else
1744 TTCN_Logger::log_event_str("<unknown>");
1745 }
1746 TTCN_Logger::log_event_str("'H");
1747 break;
1748 case DECODE_MATCH:
1749 TTCN_Logger::log_event_str("decmatch ");
1750 dec_match->instance->log();
1751 break;
1752 default:
1753 log_generic();
1754 break;
1755 }
1756 log_restricted();
1757 log_ifpresent();
1758 }
1759
1760 void HEXSTRING_template::log_match(const HEXSTRING& match_value,
1761 boolean /* legacy */) const
1762 {
1763 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
1764 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1765 TTCN_Logger::print_logmatch_buffer();
1766 TTCN_Logger::log_event_str(" := ");
1767 }
1768 match_value.log();
1769 TTCN_Logger::log_event_str(" with ");
1770 log();
1771 if (match(match_value))
1772 TTCN_Logger::log_event_str(" matched");
1773 else
1774 TTCN_Logger::log_event_str(" unmatched");
1775 }
1776
1777 void HEXSTRING_template::set_param(Module_Param& param) {
1778 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "hexstring template");
1779 Module_Param_Ptr mp = &param;
1780 if (param.get_type() == Module_Param::MP_Reference) {
1781 mp = param.get_referenced_param();
1782 }
1783 switch (mp->get_type()) {
1784 case Module_Param::MP_Omit:
1785 *this = OMIT_VALUE;
1786 break;
1787 case Module_Param::MP_Any:
1788 *this = ANY_VALUE;
1789 break;
1790 case Module_Param::MP_AnyOrNone:
1791 *this = ANY_OR_OMIT;
1792 break;
1793 case Module_Param::MP_List_Template:
1794 case Module_Param::MP_ComplementList_Template: {
1795 HEXSTRING_template temp;
1796 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1797 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1798 for (size_t i=0; i<mp->get_size(); i++) {
1799 temp.list_item(i).set_param(*mp->get_elem(i));
1800 }
1801 *this = temp;
1802 break; }
1803 case Module_Param::MP_Hexstring:
1804 *this = HEXSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
1805 break;
1806 case Module_Param::MP_Hexstring_Template:
1807 *this = HEXSTRING_template(mp->get_string_size(), (unsigned char*)mp->get_string_data());
1808 break;
1809 case Module_Param::MP_Expression:
1810 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
1811 HEXSTRING operand1, operand2;
1812 operand1.set_param(*mp->get_operand1());
1813 operand2.set_param(*mp->get_operand2());
1814 *this = operand1 + operand2;
1815 }
1816 else {
1817 param.expr_type_error("a bitstring");
1818 }
1819 break;
1820 default:
1821 param.type_error("hexstring template");
1822 }
1823 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1824 if (param.get_length_restriction() != NULL) {
1825 set_length_range(param);
1826 }
1827 else {
1828 set_length_range(*mp);
1829 }
1830 }
1831
1832 Module_Param* HEXSTRING_template::get_param(Module_Param_Name& param_name) const
1833 {
1834 Module_Param* mp = NULL;
1835 switch (template_selection) {
1836 case UNINITIALIZED_TEMPLATE:
1837 mp = new Module_Param_Unbound();
1838 break;
1839 case OMIT_VALUE:
1840 mp = new Module_Param_Omit();
1841 break;
1842 case ANY_VALUE:
1843 mp = new Module_Param_Any();
1844 break;
1845 case ANY_OR_OMIT:
1846 mp = new Module_Param_AnyOrNone();
1847 break;
1848 case SPECIFIC_VALUE:
1849 mp = single_value.get_param(param_name);
1850 break;
1851 case VALUE_LIST:
1852 case COMPLEMENTED_LIST: {
1853 if (template_selection == VALUE_LIST) {
1854 mp = new Module_Param_List_Template();
1855 }
1856 else {
1857 mp = new Module_Param_ComplementList_Template();
1858 }
1859 for (size_t i = 0; i < value_list.n_values; ++i) {
1860 mp->add_elem(value_list.list_value[i].get_param(param_name));
1861 }
1862 break; }
1863 case STRING_PATTERN: {
1864 unsigned char* val_cpy = (unsigned char*)Malloc(pattern_value->n_elements);
1865 memcpy(val_cpy, pattern_value->elements_ptr, pattern_value->n_elements);
1866 mp = new Module_Param_Hexstring_Template(pattern_value->n_elements, val_cpy);
1867 break; }
1868 case DECODE_MATCH:
1869 mp->error("Referencing a decoded content matching template is not supported.");
1870 break;
1871 default:
1872 break;
1873 }
1874 if (is_ifpresent) {
1875 mp->set_ifpresent();
1876 }
1877 mp->set_length_restriction(get_length_range());
1878 return mp;
1879 }
1880
1881 void HEXSTRING_template::encode_text(Text_Buf& text_buf) const
1882 {
1883 encode_text_restricted(text_buf);
1884 switch (template_selection) {
1885 case OMIT_VALUE:
1886 case ANY_VALUE:
1887 case ANY_OR_OMIT:
1888 break;
1889 case SPECIFIC_VALUE:
1890 single_value.encode_text(text_buf);
1891 break;
1892 case VALUE_LIST:
1893 case COMPLEMENTED_LIST:
1894 text_buf.push_int(value_list.n_values);
1895 for (unsigned int i = 0; i < value_list.n_values; i++)
1896 value_list.list_value[i].encode_text(text_buf);
1897 break;
1898 case STRING_PATTERN:
1899 text_buf.push_int(pattern_value->n_elements);
1900 text_buf.push_raw(pattern_value->n_elements, pattern_value->elements_ptr);
1901 break;
1902 default:
1903 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1904 "hexstring template.");
1905 }
1906 }
1907
1908 void HEXSTRING_template::decode_text(Text_Buf& text_buf)
1909 {
1910 clean_up();
1911 decode_text_restricted(text_buf);
1912 switch (template_selection) {
1913 case OMIT_VALUE:
1914 case ANY_VALUE:
1915 case ANY_OR_OMIT:
1916 break;
1917 case SPECIFIC_VALUE:
1918 single_value.decode_text(text_buf);
1919 break;
1920 case VALUE_LIST:
1921 case COMPLEMENTED_LIST:
1922 value_list.n_values = text_buf.pull_int().get_val();
1923 value_list.list_value = new HEXSTRING_template[value_list.n_values];
1924 for (unsigned int i = 0; i < value_list.n_values; i++)
1925 value_list.list_value[i].decode_text(text_buf);
1926 break;
1927 case STRING_PATTERN: {
1928 unsigned int n_elements = text_buf.pull_int().get_val();
1929 pattern_value
1930 = (hexstring_pattern_struct*) Malloc(sizeof(hexstring_pattern_struct) + n_elements - 1);
1931 pattern_value->ref_count = 1;
1932 pattern_value->n_elements = n_elements;
1933 text_buf.pull_raw(n_elements, pattern_value->elements_ptr);
1934 break;
1935 }
1936 default:
1937 TTCN_error("Text decoder: An unknown/unsupported selection was "
1938 "received for a hexstring template.");
1939 }
1940 }
1941
1942 boolean HEXSTRING_template::is_present(boolean legacy /* = FALSE */) const
1943 {
1944 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1945 return !match_omit(legacy);
1946 }
1947
1948 boolean HEXSTRING_template::match_omit(boolean legacy /* = FALSE */) const
1949 {
1950 if (is_ifpresent) return TRUE;
1951 switch (template_selection) {
1952 case OMIT_VALUE:
1953 case ANY_OR_OMIT:
1954 return TRUE;
1955 case VALUE_LIST:
1956 case COMPLEMENTED_LIST:
1957 if (legacy) {
1958 // legacy behavior: 'omit' can appear in the value/complement list
1959 for (unsigned int i = 0; i < value_list.n_values; i++)
1960 if (value_list.list_value[i].match_omit()) return template_selection
1961 == VALUE_LIST;
1962 return template_selection == COMPLEMENTED_LIST;
1963 }
1964 // else fall through
1965 default:
1966 return FALSE;
1967 }
1968 return FALSE;
1969 }
1970
1971 #ifndef TITAN_RUNTIME_2
1972 void HEXSTRING_template::check_restriction(template_res t_res, const char* t_name,
1973 boolean legacy /* = FALSE */) const
1974 {
1975 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1976 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1977 case TR_VALUE:
1978 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
1979 break;
1980 case TR_OMIT:
1981 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
1982 template_selection==SPECIFIC_VALUE)) return;
1983 break;
1984 case TR_PRESENT:
1985 if (!match_omit(legacy)) return;
1986 break;
1987 default:
1988 return;
1989 }
1990 TTCN_error("Restriction `%s' on template of type %s violated.",
1991 get_res_name(t_res), t_name ? t_name : "hexstring");
1992 }
1993 #endif
This page took 0.120525 seconds and 5 git commands to generate.