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