Last sync 2016.04.01
[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 default:
1308 break;
1309 }
1310 template_selection = UNINITIALIZED_TEMPLATE;
1311 }
1312
1313 void HEXSTRING_template::copy_template(const HEXSTRING_template& other_value)
1314 {
1315 switch (other_value.template_selection) {
1316 case SPECIFIC_VALUE:
1317 single_value = other_value.single_value;
1318 break;
1319 case OMIT_VALUE:
1320 case ANY_VALUE:
1321 case ANY_OR_OMIT:
1322 break;
1323 case VALUE_LIST:
1324 case COMPLEMENTED_LIST:
1325 value_list.n_values = other_value.value_list.n_values;
1326 value_list.list_value = new HEXSTRING_template[value_list.n_values];
1327 for (unsigned int i = 0; i < value_list.n_values; i++)
1328 value_list.list_value[i].copy_template(
1329 other_value.value_list.list_value[i]);
1330 break;
1331 case STRING_PATTERN:
1332 pattern_value = other_value.pattern_value;
1333 pattern_value->ref_count++;
1334 break;
1335 default:
1336 TTCN_error("Copying an uninitialized/unsupported hexstring template.");
1337 }
1338 set_selection(other_value);
1339 }
1340
1341 /*
1342 This is the same algorithm that match_array uses
1343 to match 'record of' types.
1344 The only differences are: how two elements are matched and
1345 how an asterisk or ? is identified in the template
1346 */
1347 boolean HEXSTRING_template::match_pattern(
1348 const hexstring_pattern_struct *string_pattern,
1349 const HEXSTRING::hexstring_struct *string_value)
1350 {
1351 // the empty pattern matches the empty hexstring only
1352 if (string_pattern->n_elements == 0) return string_value->n_nibbles == 0;
1353
1354 int value_index = 0;
1355 unsigned int template_index = 0;
1356 int last_asterisk = -1;
1357 int last_value_to_asterisk = -1;
1358 //the following variables are just to speed up the function
1359 unsigned char pattern_element;
1360 unsigned char octet;
1361 unsigned char hex_digit;
1362
1363 for (;;) {
1364 pattern_element = string_pattern->elements_ptr[template_index];
1365 if (pattern_element < 16) {
1366 octet = string_value->nibbles_ptr[value_index / 2];
1367 if (value_index % 2)
1368 hex_digit = octet >> 4;
1369 else
1370 hex_digit = octet & 0x0F;
1371 if (hex_digit == pattern_element) {
1372 value_index++;
1373 template_index++;
1374 }
1375 else {
1376 if (last_asterisk == -1) return FALSE;
1377 template_index = last_asterisk + 1;
1378 value_index = ++last_value_to_asterisk;
1379 }
1380 }
1381 else if (pattern_element == 16) {//?
1382 value_index++;
1383 template_index++;
1384 }
1385 else if (pattern_element == 17) {//*
1386 last_asterisk = template_index++;
1387 last_value_to_asterisk = value_index;
1388 }
1389 else
1390 TTCN_error("Internal error: invalid element in a hexstring "
1391 "pattern.");
1392
1393 if (value_index == string_value->n_nibbles && template_index
1394 == string_pattern->n_elements) {
1395 return TRUE;
1396 }
1397 else if (template_index == string_pattern->n_elements) {
1398 if (string_pattern->elements_ptr[template_index - 1] == 17) {
1399 return TRUE;
1400 }
1401 else if (last_asterisk == -1) {
1402 return FALSE;
1403 }
1404 else {
1405 template_index = last_asterisk + 1;
1406 value_index = ++last_value_to_asterisk;
1407 }
1408 }
1409 else if (value_index == string_value->n_nibbles) {
1410 while (template_index < string_pattern->n_elements
1411 && string_pattern->elements_ptr[template_index] == 17)
1412 template_index++;
1413
1414 return template_index == string_pattern->n_elements;
1415 }
1416 }
1417 }
1418
1419 HEXSTRING_template::HEXSTRING_template()
1420 {
1421 }
1422
1423 HEXSTRING_template::HEXSTRING_template(template_sel other_value) :
1424 Restricted_Length_Template(other_value)
1425 {
1426 check_single_selection(other_value);
1427 }
1428
1429 HEXSTRING_template::HEXSTRING_template(const HEXSTRING& other_value) :
1430 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1431 {
1432 }
1433
1434 HEXSTRING_template::HEXSTRING_template(const HEXSTRING_ELEMENT& other_value) :
1435 Restricted_Length_Template(SPECIFIC_VALUE), single_value(other_value)
1436 {
1437 }
1438
1439 HEXSTRING_template::HEXSTRING_template(const OPTIONAL<HEXSTRING>& other_value)
1440 {
1441 switch (other_value.get_selection()) {
1442 case OPTIONAL_PRESENT:
1443 set_selection(SPECIFIC_VALUE);
1444 single_value = (const HEXSTRING&) other_value;
1445 break;
1446 case OPTIONAL_OMIT:
1447 set_selection(OMIT_VALUE);
1448 break;
1449 default:
1450 TTCN_error("Creating a hexstring template from an unbound optional field.");
1451 }
1452 }
1453
1454 HEXSTRING_template::HEXSTRING_template(unsigned int n_elements,
1455 const unsigned char *pattern_elements) :
1456 Restricted_Length_Template(STRING_PATTERN)
1457 {
1458 pattern_value
1459 = (hexstring_pattern_struct*) Malloc(sizeof(hexstring_pattern_struct) + n_elements - 1);
1460 pattern_value->ref_count = 1;
1461 pattern_value->n_elements = n_elements;
1462 memcpy(pattern_value->elements_ptr, pattern_elements, n_elements);
1463 }
1464
1465 HEXSTRING_template::HEXSTRING_template(const HEXSTRING_template& other_value) :
1466 Restricted_Length_Template()
1467 {
1468 copy_template(other_value);
1469 }
1470
1471 HEXSTRING_template::~HEXSTRING_template()
1472 {
1473 clean_up();
1474 }
1475
1476 HEXSTRING_template& HEXSTRING_template::operator=(template_sel other_value)
1477 {
1478 check_single_selection(other_value);
1479 clean_up();
1480 set_selection(other_value);
1481 return *this;
1482 }
1483
1484 HEXSTRING_template& HEXSTRING_template::operator=(const HEXSTRING& other_value)
1485 {
1486 other_value.must_bound("Assignment of an unbound hexstring value to a "
1487 "template.");
1488 clean_up();
1489 set_selection(SPECIFIC_VALUE);
1490 single_value = other_value;
1491 return *this;
1492 }
1493
1494 HEXSTRING_template& HEXSTRING_template::operator=(
1495 const HEXSTRING_ELEMENT& other_value)
1496 {
1497 other_value.must_bound("Assignment of an unbound hexstring element to a "
1498 "template.");
1499 clean_up();
1500 set_selection(SPECIFIC_VALUE);
1501 single_value = other_value;
1502 return *this;
1503 }
1504
1505 HEXSTRING_template& HEXSTRING_template::operator=(
1506 const OPTIONAL<HEXSTRING>& other_value)
1507 {
1508 clean_up();
1509 switch (other_value.get_selection()) {
1510 case OPTIONAL_PRESENT:
1511 set_selection(SPECIFIC_VALUE);
1512 single_value = (const HEXSTRING&) other_value;
1513 break;
1514 case OPTIONAL_OMIT:
1515 set_selection(OMIT_VALUE);
1516 break;
1517 default:
1518 TTCN_error("Assignment of an unbound optional field to a hexstring "
1519 "template.");
1520 }
1521 return *this;
1522 }
1523
1524 HEXSTRING_template& HEXSTRING_template::operator=(
1525 const HEXSTRING_template& other_value)
1526 {
1527 if (&other_value != this) {
1528 clean_up();
1529 copy_template(other_value);
1530 }
1531 return *this;
1532 }
1533
1534 HEXSTRING_ELEMENT HEXSTRING_template::operator[](int index_value)
1535 {
1536 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1537 TTCN_error("Accessing a hexstring element of a non-specific hexstring "
1538 "template.");
1539 return single_value[index_value];
1540 }
1541
1542 HEXSTRING_ELEMENT HEXSTRING_template::operator[](const INTEGER& index_value)
1543 {
1544 index_value.must_bound("Indexing a hexstring template with an unbound "
1545 "integer value.");
1546 return (*this)[(int)index_value];
1547 }
1548
1549 const HEXSTRING_ELEMENT HEXSTRING_template::operator[](int index_value) const
1550 {
1551 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1552 TTCN_error("Accessing a hexstring element of a non-specific hexstring "
1553 "template.");
1554 return single_value[index_value];
1555 }
1556
1557 const HEXSTRING_ELEMENT HEXSTRING_template::operator[](const INTEGER& index_value) const
1558 {
1559 index_value.must_bound("Indexing a hexstring template with an unbound "
1560 "integer value.");
1561 return (*this)[(int)index_value];
1562 }
1563
1564 boolean HEXSTRING_template::match(const HEXSTRING& other_value,
1565 boolean /* legacy */) const
1566 {
1567 if (!other_value.is_bound()) return FALSE;
1568 if (!match_length(other_value.val_ptr->n_nibbles)) return FALSE;
1569 switch (template_selection) {
1570 case SPECIFIC_VALUE:
1571 return single_value == other_value;
1572 case OMIT_VALUE:
1573 return FALSE;
1574 case ANY_VALUE:
1575 case ANY_OR_OMIT:
1576 return TRUE;
1577 case VALUE_LIST:
1578 case COMPLEMENTED_LIST:
1579 for (unsigned int i = 0; i < value_list.n_values; i++)
1580 if (value_list.list_value[i].match(other_value)) return template_selection
1581 == VALUE_LIST;
1582 return template_selection == COMPLEMENTED_LIST;
1583 case STRING_PATTERN:
1584 return match_pattern(pattern_value, other_value.val_ptr);
1585 default:
1586 TTCN_error("Matching an uninitialized/unsupported hexstring template.");
1587 }
1588 return FALSE;
1589 }
1590
1591 const HEXSTRING& HEXSTRING_template::valueof() const
1592 {
1593 if (template_selection != SPECIFIC_VALUE || is_ifpresent) TTCN_error(
1594 "Performing a valueof or send operation on a non-specific "
1595 "hexstring template.");
1596 return single_value;
1597 }
1598
1599 int HEXSTRING_template::lengthof() const
1600 {
1601 int min_length;
1602 boolean has_any_or_none;
1603 if (is_ifpresent) TTCN_error(
1604 "Performing lengthof() operation on a hexstring template "
1605 "which has an ifpresent attribute.");
1606 switch (template_selection) {
1607 case SPECIFIC_VALUE:
1608 min_length = single_value.lengthof();
1609 has_any_or_none = FALSE;
1610 break;
1611 case OMIT_VALUE:
1612 TTCN_error("Performing lengthof() operation on a hexstring template "
1613 "containing omit value.");
1614 case ANY_VALUE:
1615 case ANY_OR_OMIT:
1616 min_length = 0;
1617 has_any_or_none = TRUE; // max. length is infinity
1618 break;
1619 case VALUE_LIST: {
1620 // error if any element does not have length or the lengths differ
1621 if (value_list.n_values < 1) TTCN_error("Internal error: "
1622 "Performing lengthof() operation on a hexstring template "
1623 "containing an empty list.");
1624 int item_length = value_list.list_value[0].lengthof();
1625 for (unsigned int i = 1; i < value_list.n_values; i++) {
1626 if (value_list.list_value[i].lengthof() != item_length) TTCN_error(
1627 "Performing lengthof() operation on a hexstring template "
1628 "containing a value list with different lengths.");
1629 }
1630 min_length = item_length;
1631 has_any_or_none = FALSE;
1632 break;
1633 }
1634 case COMPLEMENTED_LIST:
1635 TTCN_error("Performing lengthof() operation on a hexstring template "
1636 "containing complemented list.");
1637 case STRING_PATTERN:
1638 min_length = 0;
1639 has_any_or_none = FALSE; // TRUE if * chars in the pattern
1640 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1641 if (pattern_value->elements_ptr[i] < 17)
1642 min_length++; // case of 0-F, ?
1643 else
1644 has_any_or_none = TRUE; // case of * character
1645 }
1646 break;
1647 default:
1648 TTCN_error("Performing lengthof() operation on an "
1649 "uninitialized/unsupported hexstring template.");
1650 }
1651 return check_section_is_single(min_length, has_any_or_none, "length", "a",
1652 "hexstring template");
1653 }
1654
1655 void HEXSTRING_template::set_type(template_sel template_type,
1656 unsigned int list_length)
1657 {
1658 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) TTCN_error(
1659 "Setting an invalid list type for a hexstring template.");
1660 clean_up();
1661 set_selection(template_type);
1662 value_list.n_values = list_length;
1663 value_list.list_value = new HEXSTRING_template[list_length];
1664 }
1665
1666 HEXSTRING_template& HEXSTRING_template::list_item(unsigned int list_index)
1667 {
1668 if (template_selection != VALUE_LIST && template_selection
1669 != COMPLEMENTED_LIST) TTCN_error(
1670 "Accessing a list element of a non-list hexstring template.");
1671 if (list_index >= value_list.n_values) TTCN_error(
1672 "Index overflow in a hexstring value list template.");
1673 return value_list.list_value[list_index];
1674 }
1675
1676 void HEXSTRING_template::log() const
1677 {
1678 switch (template_selection) {
1679 case SPECIFIC_VALUE:
1680 single_value.log();
1681 break;
1682 case COMPLEMENTED_LIST:
1683 TTCN_Logger::log_event_str("complement ");
1684 // no break
1685 case VALUE_LIST:
1686 TTCN_Logger::log_char('(');
1687 for (unsigned int i = 0; i < value_list.n_values; i++) {
1688 if (i > 0) TTCN_Logger::log_event_str(", ");
1689 value_list.list_value[i].log();
1690 }
1691 TTCN_Logger::log_char(')');
1692 break;
1693 case STRING_PATTERN:
1694 TTCN_Logger::log_char('\'');
1695 for (unsigned int i = 0; i < pattern_value->n_elements; i++) {
1696 unsigned char pattern = pattern_value->elements_ptr[i];
1697 if (pattern < 16)
1698 TTCN_Logger::log_hex(pattern);
1699 else if (pattern == 16)
1700 TTCN_Logger::log_char('?');
1701 else if (pattern == 17)
1702 TTCN_Logger::log_char('*');
1703 else
1704 TTCN_Logger::log_event_str("<unknown>");
1705 }
1706 TTCN_Logger::log_event_str("'H");
1707 break;
1708 default:
1709 log_generic();
1710 break;
1711 }
1712 log_restricted();
1713 log_ifpresent();
1714 }
1715
1716 void HEXSTRING_template::log_match(const HEXSTRING& match_value,
1717 boolean /* legacy */) const
1718 {
1719 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
1720 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1721 TTCN_Logger::print_logmatch_buffer();
1722 TTCN_Logger::log_event_str(" := ");
1723 }
1724 match_value.log();
1725 TTCN_Logger::log_event_str(" with ");
1726 log();
1727 if (match(match_value))
1728 TTCN_Logger::log_event_str(" matched");
1729 else
1730 TTCN_Logger::log_event_str(" unmatched");
1731 }
1732
1733 void HEXSTRING_template::set_param(Module_Param& param) {
1734 param.basic_check(Module_Param::BC_TEMPLATE|Module_Param::BC_LIST, "hexstring template");
1735 Module_Param_Ptr mp = &param;
1736 if (param.get_type() == Module_Param::MP_Reference) {
1737 mp = param.get_referenced_param();
1738 }
1739 switch (mp->get_type()) {
1740 case Module_Param::MP_Omit:
1741 *this = OMIT_VALUE;
1742 break;
1743 case Module_Param::MP_Any:
1744 *this = ANY_VALUE;
1745 break;
1746 case Module_Param::MP_AnyOrNone:
1747 *this = ANY_OR_OMIT;
1748 break;
1749 case Module_Param::MP_List_Template:
1750 case Module_Param::MP_ComplementList_Template: {
1751 HEXSTRING_template temp;
1752 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1753 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1754 for (size_t i=0; i<mp->get_size(); i++) {
1755 temp.list_item(i).set_param(*mp->get_elem(i));
1756 }
1757 *this = temp;
1758 break; }
1759 case Module_Param::MP_Hexstring:
1760 *this = HEXSTRING(mp->get_string_size(), (unsigned char*)mp->get_string_data());
1761 break;
1762 case Module_Param::MP_Hexstring_Template:
1763 *this = HEXSTRING_template(mp->get_string_size(), (unsigned char*)mp->get_string_data());
1764 break;
1765 case Module_Param::MP_Expression:
1766 if (mp->get_expr_type() == Module_Param::EXPR_CONCATENATE) {
1767 HEXSTRING operand1, operand2;
1768 operand1.set_param(*mp->get_operand1());
1769 operand2.set_param(*mp->get_operand2());
1770 *this = operand1 + operand2;
1771 }
1772 else {
1773 param.expr_type_error("a bitstring");
1774 }
1775 break;
1776 default:
1777 param.type_error("hexstring template");
1778 }
1779 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1780 if (param.get_length_restriction() != NULL) {
1781 set_length_range(param);
1782 }
1783 else {
1784 set_length_range(*mp);
1785 }
1786 }
1787
1788 Module_Param* HEXSTRING_template::get_param(Module_Param_Name& param_name) const
1789 {
1790 Module_Param* mp = NULL;
1791 switch (template_selection) {
1792 case UNINITIALIZED_TEMPLATE:
1793 mp = new Module_Param_Unbound();
1794 break;
1795 case OMIT_VALUE:
1796 mp = new Module_Param_Omit();
1797 break;
1798 case ANY_VALUE:
1799 mp = new Module_Param_Any();
1800 break;
1801 case ANY_OR_OMIT:
1802 mp = new Module_Param_AnyOrNone();
1803 break;
1804 case SPECIFIC_VALUE:
1805 mp = single_value.get_param(param_name);
1806 break;
1807 case VALUE_LIST:
1808 case COMPLEMENTED_LIST: {
1809 if (template_selection == VALUE_LIST) {
1810 mp = new Module_Param_List_Template();
1811 }
1812 else {
1813 mp = new Module_Param_ComplementList_Template();
1814 }
1815 for (size_t i = 0; i < value_list.n_values; ++i) {
1816 mp->add_elem(value_list.list_value[i].get_param(param_name));
1817 }
1818 break; }
1819 case STRING_PATTERN: {
1820 unsigned char* val_cpy = (unsigned char*)Malloc(pattern_value->n_elements);
1821 memcpy(val_cpy, pattern_value->elements_ptr, pattern_value->n_elements);
1822 mp = new Module_Param_Hexstring_Template(pattern_value->n_elements, val_cpy);
1823 break; }
1824 default:
1825 break;
1826 }
1827 if (is_ifpresent) {
1828 mp->set_ifpresent();
1829 }
1830 mp->set_length_restriction(get_length_range());
1831 return mp;
1832 }
1833
1834 void HEXSTRING_template::encode_text(Text_Buf& text_buf) const
1835 {
1836 encode_text_restricted(text_buf);
1837 switch (template_selection) {
1838 case OMIT_VALUE:
1839 case ANY_VALUE:
1840 case ANY_OR_OMIT:
1841 break;
1842 case SPECIFIC_VALUE:
1843 single_value.encode_text(text_buf);
1844 break;
1845 case VALUE_LIST:
1846 case COMPLEMENTED_LIST:
1847 text_buf.push_int(value_list.n_values);
1848 for (unsigned int i = 0; i < value_list.n_values; i++)
1849 value_list.list_value[i].encode_text(text_buf);
1850 break;
1851 case STRING_PATTERN:
1852 text_buf.push_int(pattern_value->n_elements);
1853 text_buf.push_raw(pattern_value->n_elements, pattern_value->elements_ptr);
1854 break;
1855 default:
1856 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1857 "hexstring template.");
1858 }
1859 }
1860
1861 void HEXSTRING_template::decode_text(Text_Buf& text_buf)
1862 {
1863 clean_up();
1864 decode_text_restricted(text_buf);
1865 switch (template_selection) {
1866 case OMIT_VALUE:
1867 case ANY_VALUE:
1868 case ANY_OR_OMIT:
1869 break;
1870 case SPECIFIC_VALUE:
1871 single_value.decode_text(text_buf);
1872 break;
1873 case VALUE_LIST:
1874 case COMPLEMENTED_LIST:
1875 value_list.n_values = text_buf.pull_int().get_val();
1876 value_list.list_value = new HEXSTRING_template[value_list.n_values];
1877 for (unsigned int i = 0; i < value_list.n_values; i++)
1878 value_list.list_value[i].decode_text(text_buf);
1879 break;
1880 case STRING_PATTERN: {
1881 unsigned int n_elements = text_buf.pull_int().get_val();
1882 pattern_value
1883 = (hexstring_pattern_struct*) Malloc(sizeof(hexstring_pattern_struct) + n_elements - 1);
1884 pattern_value->ref_count = 1;
1885 pattern_value->n_elements = n_elements;
1886 text_buf.pull_raw(n_elements, pattern_value->elements_ptr);
1887 break;
1888 }
1889 default:
1890 TTCN_error("Text decoder: An unknown/unsupported selection was "
1891 "received for a hexstring template.");
1892 }
1893 }
1894
1895 boolean HEXSTRING_template::is_present(boolean legacy /* = FALSE */) const
1896 {
1897 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1898 return !match_omit(legacy);
1899 }
1900
1901 boolean HEXSTRING_template::match_omit(boolean legacy /* = FALSE */) const
1902 {
1903 if (is_ifpresent) return TRUE;
1904 switch (template_selection) {
1905 case OMIT_VALUE:
1906 case ANY_OR_OMIT:
1907 return TRUE;
1908 case VALUE_LIST:
1909 case COMPLEMENTED_LIST:
1910 if (legacy) {
1911 // legacy behavior: 'omit' can appear in the value/complement list
1912 for (unsigned int i = 0; i < value_list.n_values; i++)
1913 if (value_list.list_value[i].match_omit()) return template_selection
1914 == VALUE_LIST;
1915 return template_selection == COMPLEMENTED_LIST;
1916 }
1917 // else fall through
1918 default:
1919 return FALSE;
1920 }
1921 return FALSE;
1922 }
1923
1924 #ifndef TITAN_RUNTIME_2
1925 void HEXSTRING_template::check_restriction(template_res t_res, const char* t_name,
1926 boolean legacy /* = FALSE */) const
1927 {
1928 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1929 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1930 case TR_VALUE:
1931 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
1932 break;
1933 case TR_OMIT:
1934 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
1935 template_selection==SPECIFIC_VALUE)) return;
1936 break;
1937 case TR_PRESENT:
1938 if (!match_omit(legacy)) return;
1939 break;
1940 default:
1941 return;
1942 }
1943 TTCN_error("Restriction `%s' on template of type %s violated.",
1944 get_res_name(t_res), t_name ? t_name : "hexstring");
1945 }
1946 #endif
This page took 0.07824 seconds and 5 git commands to generate.