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"
11 #include "String_struct.hh"
12 #include "Param_Types.hh"
19 #include "../common/dbgnew.hh"
23 // hexstring value class
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)
28 void HEXSTRING::init_struct(int n_nibbles
)
32 TTCN_error("Initializing an hexstring with a negative length.");
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.
38 static hexstring_struct empty_string
= { 1, 0, "" };
39 val_ptr
= &empty_string
;
40 empty_string
.ref_count
++;
43 val_ptr
= (hexstring_struct
*) Malloc(MEMORY_SIZE(n_nibbles
));
44 val_ptr
->ref_count
= 1;
45 val_ptr
->n_nibbles
= n_nibbles
;
49 /** Return the nibble at index i
54 unsigned char HEXSTRING::get_nibble(int nibble_index
) const
56 unsigned char octet
= val_ptr
->nibbles_ptr
[nibble_index
/ 2];
58 return octet
>> 4; // odd nibble -> top
60 return octet
& 0x0F; // even nibble -> bottom
63 void HEXSTRING::set_nibble(int nibble_index
, unsigned char new_value
)
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
71 val_ptr
->nibbles_ptr
[nibble_index
/ 2] = (old_octet
& 0xF0) | (new_value
76 void HEXSTRING::copy_value()
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
;
84 init_struct(old_ptr
->n_nibbles
);
85 memcpy(val_ptr
->nibbles_ptr
, old_ptr
->nibbles_ptr
, (old_ptr
->n_nibbles
+ 1)
90 void HEXSTRING::clear_unused_nibble() const
92 if (val_ptr
->n_nibbles
% 2) val_ptr
->nibbles_ptr
[val_ptr
->n_nibbles
/ 2]
96 HEXSTRING::HEXSTRING(int n_nibbles
)
98 init_struct(n_nibbles
);
101 HEXSTRING::HEXSTRING()
106 HEXSTRING::HEXSTRING(int init_n_nibbles
, const unsigned char* init_nibbles
)
108 init_struct(init_n_nibbles
);
109 memcpy(val_ptr
->nibbles_ptr
, init_nibbles
, (init_n_nibbles
+ 1) / 2);
110 clear_unused_nibble();
113 HEXSTRING::HEXSTRING(const HEXSTRING
& other_value
) :
114 Base_Type(other_value
)
116 other_value
.must_bound("Initialization from an unbound hexstring value.");
117 val_ptr
= other_value
.val_ptr
;
118 val_ptr
->ref_count
++;
121 HEXSTRING::HEXSTRING(const HEXSTRING_ELEMENT
& other_value
)
123 other_value
.must_bound("Initialization from an unbound hexstring element.");
125 val_ptr
->nibbles_ptr
[0] = other_value
.get_nibble();
128 HEXSTRING::~HEXSTRING()
133 void HEXSTRING::clean_up()
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)
141 TTCN_error("Internal error: Invalid reference counter in a hexstring "
147 HEXSTRING
& HEXSTRING::operator=(const HEXSTRING
& other_value
)
149 other_value
.must_bound("Assignment of an unbound hexstring value.");
150 if (&other_value
!= this) {
152 val_ptr
= other_value
.val_ptr
;
153 val_ptr
->ref_count
++;
158 HEXSTRING
& HEXSTRING::operator=(const HEXSTRING_ELEMENT
& other_value
)
160 other_value
.must_bound("Assignment of an unbound hexstring element to a "
162 unsigned char nibble_value
= other_value
.get_nibble();
165 val_ptr
->nibbles_ptr
[0] = nibble_value
;
169 boolean
HEXSTRING::operator==(const HEXSTRING
& other_value
) const
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);
181 boolean
HEXSTRING::operator==(const HEXSTRING_ELEMENT
& other_value
) const
183 must_bound("Unbound left operand of hexstring comparison.");
184 other_value
.must_bound("Unbound right operand of hexstring element "
186 if (val_ptr
->n_nibbles
!= 1) return FALSE
;
187 return get_nibble(0) == other_value
.get_nibble();
190 HEXSTRING
HEXSTRING::operator+(const HEXSTRING
& other_value
) const
192 must_bound("Unbound left operand of hexstring concatenation.");
193 other_value
.must_bound("Unbound right operand of hexstring concatenation.");
195 int left_n_nibbles
= val_ptr
->n_nibbles
;
196 if (left_n_nibbles
== 0) return other_value
;
198 int right_n_nibbles
= other_value
.val_ptr
->n_nibbles
;
199 if (right_n_nibbles
== 0) return *this;
201 int n_nibbles
= left_n_nibbles
+ right_n_nibbles
;
203 HEXSTRING
ret_val(n_nibbles
);
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;
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
;
214 memcpy(dest_ptr
, left_ptr
, left_n_bytes
);
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;
224 if (right_n_nibbles
% 2) dest_ptr
[n_bytes
- 1] |= right_ptr
[right_n_bytes
228 memcpy(dest_ptr
+ left_n_bytes
, right_ptr
, right_n_bytes
);
229 ret_val
.clear_unused_nibble();
234 HEXSTRING
HEXSTRING::operator+(const HEXSTRING_ELEMENT
& other_value
) const
236 must_bound("Unbound left operand of hexstring concatenation.");
237 other_value
.must_bound("Unbound right operand of hexstring element "
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)
243 ret_val
.set_nibble(n_nibbles
, other_value
.get_nibble());
247 HEXSTRING
HEXSTRING::operator~() const
249 must_bound("Unbound hexstring operand of operator not4b.");
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
];
257 ret_val
.clear_unused_nibble();
261 HEXSTRING
HEXSTRING::operator&(const HEXSTRING
& other_value
) const
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 "
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
];
276 ret_val
.clear_unused_nibble();
280 HEXSTRING
HEXSTRING::operator&(const HEXSTRING_ELEMENT
& other_value
) const
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
);
291 HEXSTRING
HEXSTRING::operator|(const HEXSTRING
& other_value
) const
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 "
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
];
306 ret_val
.clear_unused_nibble();
310 HEXSTRING
HEXSTRING::operator|(const HEXSTRING_ELEMENT
& other_value
) const
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
);
321 HEXSTRING
HEXSTRING::operator^(const HEXSTRING
& other_value
) const
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 "
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
];
336 ret_val
.clear_unused_nibble();
340 HEXSTRING
HEXSTRING::operator^(const HEXSTRING_ELEMENT
& other_value
) const
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
);
351 HEXSTRING
HEXSTRING::operator<<(int shift_count
) const
353 must_bound("Unbound hexstring operand of shift left operator.");
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) {
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);
370 ret_val
.val_ptr
->nibbles_ptr
[n_bytes
- shift_bytes
- 1]
371 = val_ptr
->nibbles_ptr
[n_bytes
- 1] >> 4;
374 memcpy(ret_val
.val_ptr
->nibbles_ptr
, &val_ptr
->nibbles_ptr
[shift_count
375 / 2], (n_nibbles
- shift_count
+ 1) / 2);
377 memset(ret_val
.val_ptr
->nibbles_ptr
+ n_bytes
- shift_bytes
, 0, shift_bytes
);
380 else if (shift_count
== 0)
383 return *this >> (-shift_count
);
386 HEXSTRING
HEXSTRING::operator<<(const INTEGER
& shift_count
) const
388 shift_count
.must_bound("Unbound right operand of hexstring shift left "
390 return *this << (int) shift_count
;
393 HEXSTRING
HEXSTRING::operator>>(int shift_count
) const
395 must_bound("Unbound operand of hexstring shift right operator.");
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);
416 memcpy(&ret_val
.val_ptr
->nibbles_ptr
[shift_bytes
], val_ptr
->nibbles_ptr
,
417 (n_nibbles
- shift_count
+ 1) / 2);
419 ret_val
.clear_unused_nibble();
422 else if (shift_count
== 0)
425 return *this << (-shift_count
);
428 HEXSTRING
HEXSTRING::operator>>(const INTEGER
& shift_count
) const
430 shift_count
.must_bound("Unbound right operand of hexstring shift right "
432 return *this >> (int) shift_count
;
435 HEXSTRING
HEXSTRING::operator<<=(int rotate_count
) const
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
446 return *this >>= (-rotate_count
);
449 HEXSTRING
HEXSTRING::operator<<=(const INTEGER
& rotate_count
) const
451 rotate_count
.must_bound("Unbound right operand of hexstring rotate left "
453 return *this <<= (int) rotate_count
;
456 HEXSTRING
HEXSTRING::operator>>=(int rotate_count
) const
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
467 return *this <<= (-rotate_count
);
470 HEXSTRING
HEXSTRING::operator>>=(const INTEGER
& rotate_count
) const
472 rotate_count
.must_bound("Unbound right operand of hexstring rotate right "
474 return *this >>= (int) rotate_count
;
477 HEXSTRING_ELEMENT
HEXSTRING::operator[](int index_value
)
479 if (val_ptr
== NULL
&& index_value
== 0) {
481 clear_unused_nibble();
482 return HEXSTRING_ELEMENT(FALSE
, *this, 0);
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
++;
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);
504 return HEXSTRING_ELEMENT(FALSE
, *this, index_value
);
507 return HEXSTRING_ELEMENT(TRUE
, *this, index_value
);
511 HEXSTRING_ELEMENT
HEXSTRING::operator[](const INTEGER
& index_value
)
513 index_value
.must_bound("Indexing a hexstring value with an unbound integer "
515 return (*this)[(int) index_value
];
518 const HEXSTRING_ELEMENT
HEXSTRING::operator[](int index_value
) const
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
);
529 const HEXSTRING_ELEMENT
HEXSTRING::operator[](const INTEGER
& index_value
) const
531 index_value
.must_bound("Indexing a hexstring value with an unbound integer "
533 return (*this)[(int) index_value
];
536 int HEXSTRING::lengthof() const
538 must_bound("Getting the length of an unbound hexstring value.");
539 return val_ptr
->n_nibbles
;
542 HEXSTRING::operator const unsigned char*() const
544 must_bound("Casting an unbound hexstring value to const unsigned char*.");
545 return val_ptr
->nibbles_ptr
;
548 void HEXSTRING::log() const
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");
557 TTCN_Logger::log_event_unbound();
561 void HEXSTRING::encode_text(Text_Buf
& text_buf
) const
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
);
570 void HEXSTRING::decode_text(Text_Buf
& text_buf
)
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.");
576 init_struct(n_nibbles
);
578 text_buf
.pull_raw((n_nibbles
+ 1) / 2, val_ptr
->nibbles_ptr
);
579 clear_unused_nibble();
583 void 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
: {
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();
594 case Module_Param::OT_CONCAT
:
596 *this = *this + HEXSTRING(param
.get_string_size(), (unsigned char*)param
.get_string_data());
598 *this = HEXSTRING(param
.get_string_size(), (unsigned char*)param
.get_string_data());
602 TTCN_error("Internal error: HEXSTRING::set_param()");
606 void HEXSTRING::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
607 TTCN_EncDec::coding_t p_coding
, ...) const
610 va_start(pvar
, 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
);
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
);
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);
626 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0);
628 case TTCN_EncDec::CT_JSON
: {
629 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
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());
638 TTCN_error("Unknown coding method requested to encode type '%s'", p_td
.name
);
643 void HEXSTRING::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
644 TTCN_EncDec::coding_t p_coding
, ...)
647 va_start(pvar
, 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
);
654 switch (p_td
.raw
->top_bit_order
) {
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
);
667 case TTCN_EncDec::CT_XER
: {
668 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
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
)
677 XER_decode(*p_td
.xer
, reader
, XER_coding
);
678 size_t bytes
= reader
.ByteConsumed();
679 p_buf
.set_pos(bytes
);
681 case TTCN_EncDec::CT_JSON
: {
682 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
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"
692 p_buf
.set_pos(tok
.get_buf_pos());
695 TTCN_error("Unknown coding method requested to decode type '%s'", p_td
.name
);
700 int HEXSTRING::RAW_encode(const TTCN_Typedescriptor_t
& p_td
,
701 RAW_enc_tree
& myleaf
) const
703 // unsigned char *bc;
705 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
706 "Encoding an unbound value.");
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
;
717 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
719 myleaf
.must_free
= false;
720 myleaf
.data_ptr_used
= true;
721 myleaf
.body
.leaf
.data_ptr
= val_ptr
->nibbles_ptr
;
723 if (p_td
.raw
->endianness
== ORDER_MSB
)
724 myleaf
.align
= -align_length
;
726 myleaf
.align
= align_length
;
727 return myleaf
.length
= nbits
+ align_length
;
730 int 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*/)
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;
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
;
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
;
758 init_struct(decode_length
/ 4);
759 buff
.get_b((size_t) decode_length
, val_ptr
->nibbles_ptr
, cp
, top_bit_ord
);
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
;
771 val_ptr
->nibbles_ptr
[a
] = val_ptr
->nibbles_ptr
[b
+ 1] << (8 - bound
);
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));
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
;
788 // From Charstring.cc
789 extern char base64_decoder_table
[256];
790 extern const char cb64
[];
792 int HEXSTRING::XER_encode(const XERdescriptor_t
& p_td
,
793 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
) const
796 TTCN_EncDec_ErrorContext::error
797 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound hexstring value.");
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;
804 flavor
&= ~XER_RECOF
; // octetstring doesn't care
805 begin_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
807 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
809 size_t clear_len
= (val_ptr
->n_nibbles
+ 1) / 2; // lengthof is in nibbles
810 const unsigned char * in
= val_ptr
->nibbles_ptr
;
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);
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]);
829 CHARSTRING val
= hex2str(*this);
830 p_buf
.put_string(val
);
833 end_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
835 return (int)p_buf
.get_len() - encoded_length
;
839 unsigned 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];
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
];
851 /* Here's how the bits get transferred to and from Base64:
853 Titan stores the hex digits in "little endian order", the first (index 0)
854 goes into the lower nibble, the second goes into the high nibble
855 of the first byte. So, For the hexstring value 'DECAFBAD'H,
856 Titan stores the following bytes: ED AC BF DA
858 Because of this, the bit shifting is different. The first three bytes
860 3x8 bits: eeeedddd aaaacccc bbbbffff
862 4x6 bits: ddddee eecccc aaaaff ffbbbb
866 int HEXSTRING::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
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
));
873 const char * value
= 0;
874 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
875 const char * name
= verify_name(reader
, p_td
, exer
);
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
);
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
);
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;
911 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
915 init_struct(len
* 3 / 2); // 4 bytes decoded into 3 octets (6 nibbles)
916 unsigned char * dest
= val_ptr
->nibbles_ptr
;
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
);
925 int val
= base64_decoder_table
[c
];
928 phase
= (phase
+ 1) % 4;
930 dest
+= xlate_hs(in
,phase
, dest
);
931 in
[0]=in
[1]=in
[2]=in
[3]=0;
934 else if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
938 TTCN_EncDec_ErrorContext::warning(
939 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
940 "Invalid character for Base64 '%02X'", c
);
944 val_ptr
->n_nibbles
= (dest
- val_ptr
->nibbles_ptr
) * 2;
950 for (size_t i
= 0; i
< len
; ++i
) {
951 unsigned char nibble
= char_to_hexdigit(value
[i
]);
953 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
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
]);
963 //val_ptr->nibbles_ptr[i] = nibble;
964 set_nibble(i
, nibble
);
969 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
970 // Let the caller do reader.AdvanceAttribute();
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
);
981 reader
.Read(); // one last time
986 return 1; // decode successful
989 int HEXSTRING::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
992 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
993 "Encoding an unbound hexstring value.");
997 char* tmp_str
= (char*)Malloc(val_ptr
->n_nibbles
+ 3);
999 tmp_str
[val_ptr
->n_nibbles
+ 1] = '\"';
1000 for(int i
= 0; i
< val_ptr
->n_nibbles
; ++i
) {
1002 tmp_str
[i
+ 1] = hexdigit_to_char(val_ptr
->nibbles_ptr
[i
/ 2] >> 4);
1004 tmp_str
[i
+ 1] = hexdigit_to_char(val_ptr
->nibbles_ptr
[i
/ 2] & 0x0F);
1007 tmp_str
[val_ptr
->n_nibbles
+ 2] = 0;
1008 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
1013 int HEXSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1015 json_token_t token
= JSON_TOKEN_NONE
;
1017 size_t value_len
= 0;
1018 boolean error
= false;
1020 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1022 // No JSON data in the buffer -> use default value
1023 value
= (char*)p_td
.json
->default_value
;
1024 value_len
= strlen(value
);
1026 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1028 if (JSON_TOKEN_ERROR
== token
) {
1029 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1030 return JSON_ERROR_FATAL
;
1032 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
1033 if (use_default
|| (value_len
> 2 && value
[0] == '\"' && value
[value_len
- 1] == '\"')) {
1035 // The default value doesn't have quotes around it
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
);
1052 return JSON_ERROR_INVALID_TOKEN
;
1056 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "hexstring");
1060 return JSON_ERROR_FATAL
;
1066 //---------------------- hexstring element class ----------------------
1068 HEXSTRING_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
)
1074 HEXSTRING_ELEMENT
& HEXSTRING_ELEMENT::operator=(
1075 const HEXSTRING_ELEMENT
& other_value
)
1077 other_value
.must_bound("Assignment of an unbound hexstring element.");
1079 str_val
.copy_value();
1080 str_val
.set_nibble(nibble_pos
, other_value
.str_val
.get_nibble(
1081 other_value
.nibble_pos
));
1085 HEXSTRING_ELEMENT
& HEXSTRING_ELEMENT::operator=(const HEXSTRING
& other_value
)
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.");
1092 str_val
.copy_value();
1093 str_val
.set_nibble(nibble_pos
, other_value
.get_nibble(0));
1097 boolean
HEXSTRING_ELEMENT::operator==(const HEXSTRING_ELEMENT
& other_value
) const
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
);
1105 boolean
HEXSTRING_ELEMENT::operator==(const HEXSTRING
& other_value
) const
1107 must_bound("Unbound left operand of hexstring element comparison.");
1108 other_value
.must_bound("Unbound right operand of hexstring element "
1110 if (other_value
.val_ptr
->n_nibbles
!= 1) return FALSE
;
1111 return str_val
.get_nibble(nibble_pos
) == other_value
.get_nibble(0);
1114 HEXSTRING
HEXSTRING_ELEMENT::operator+(const HEXSTRING
& other_value
) const
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;
1130 if (n_nibbles
% 2) dest_ptr
[n_complete_bytes
] |= src_ptr
[n_complete_bytes
]
1135 HEXSTRING
HEXSTRING_ELEMENT::operator+(const HEXSTRING_ELEMENT
& other_value
) const
1137 must_bound("Unbound left operand of hexstring element concatenation.");
1138 other_value
.must_bound("Unbound right operand of hexstring element "
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
);
1145 HEXSTRING
HEXSTRING_ELEMENT::operator~() const
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
);
1152 HEXSTRING
HEXSTRING_ELEMENT::operator&(const HEXSTRING
& other_value
) const
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
);
1164 HEXSTRING
HEXSTRING_ELEMENT::operator&(const HEXSTRING_ELEMENT
& other_value
) const
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
);
1174 HEXSTRING
HEXSTRING_ELEMENT::operator|(const HEXSTRING
& other_value
) const
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
);
1186 HEXSTRING
HEXSTRING_ELEMENT::operator|(const HEXSTRING_ELEMENT
& other_value
) const
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
);
1196 HEXSTRING
HEXSTRING_ELEMENT::operator^(const HEXSTRING
& other_value
) const
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
);
1208 HEXSTRING
HEXSTRING_ELEMENT::operator^(const HEXSTRING_ELEMENT
& other_value
) const
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
);
1218 unsigned char HEXSTRING_ELEMENT::get_nibble() const
1220 return str_val
.get_nibble(nibble_pos
);
1223 void HEXSTRING_ELEMENT::log() const
1226 TTCN_Logger::log_char('\'');
1227 TTCN_Logger::log_hex(str_val
.get_nibble(nibble_pos
));
1228 TTCN_Logger::log_event_str("'H");
1231 TTCN_Logger::log_event_unbound();
1235 //---------------------- hexstring template class ----------------------
1237 void HEXSTRING_template::clean_up()
1239 switch (template_selection
) {
1241 case COMPLEMENTED_LIST
:
1242 delete[] value_list
.list_value
;
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
);
1250 TTCN_error("Internal error: Invalid reference counter in a hexstring "
1256 template_selection
= UNINITIALIZED_TEMPLATE
;
1259 void HEXSTRING_template::copy_template(const HEXSTRING_template
& other_value
)
1261 switch (other_value
.template_selection
) {
1262 case SPECIFIC_VALUE
:
1263 single_value
= other_value
.single_value
;
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
]);
1277 case STRING_PATTERN
:
1278 pattern_value
= other_value
.pattern_value
;
1279 pattern_value
->ref_count
++;
1282 TTCN_error("Copying an uninitialized/unsupported hexstring template.");
1284 set_selection(other_value
);
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
1293 boolean
HEXSTRING_template::match_pattern(
1294 const hexstring_pattern_struct
*string_pattern
,
1295 const HEXSTRING::hexstring_struct
*string_value
)
1297 // the empty pattern matches the empty hexstring only
1298 if (string_pattern
->n_elements
== 0) return string_value
->n_nibbles
== 0;
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
;
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;
1316 hex_digit
= octet
& 0x0F;
1317 if (hex_digit
== pattern_element
) {
1322 if (last_asterisk
== -1) return FALSE
;
1323 template_index
= last_asterisk
+ 1;
1324 value_index
= ++last_value_to_asterisk
;
1327 else if (pattern_element
== 16) {//?
1331 else if (pattern_element
== 17) {//*
1332 last_asterisk
= template_index
++;
1333 last_value_to_asterisk
= value_index
;
1336 TTCN_error("Internal error: invalid element in a hexstring "
1339 if (value_index
== string_value
->n_nibbles
&& template_index
1340 == string_pattern
->n_elements
) {
1343 else if (template_index
== string_pattern
->n_elements
) {
1344 if (string_pattern
->elements_ptr
[template_index
- 1] == 17) {
1347 else if (last_asterisk
== -1) {
1351 template_index
= last_asterisk
+ 1;
1352 value_index
= ++last_value_to_asterisk
;
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)
1360 return template_index
== string_pattern
->n_elements
;
1365 HEXSTRING_template::HEXSTRING_template()
1369 HEXSTRING_template::HEXSTRING_template(template_sel other_value
) :
1370 Restricted_Length_Template(other_value
)
1372 check_single_selection(other_value
);
1375 HEXSTRING_template::HEXSTRING_template(const HEXSTRING
& other_value
) :
1376 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1380 HEXSTRING_template::HEXSTRING_template(const HEXSTRING_ELEMENT
& other_value
) :
1381 Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1385 HEXSTRING_template::HEXSTRING_template(const OPTIONAL
<HEXSTRING
>& other_value
)
1387 switch (other_value
.get_selection()) {
1388 case OPTIONAL_PRESENT
:
1389 set_selection(SPECIFIC_VALUE
);
1390 single_value
= (const HEXSTRING
&) other_value
;
1393 set_selection(OMIT_VALUE
);
1396 TTCN_error("Creating a hexstring template from an unbound optional field.");
1400 HEXSTRING_template::HEXSTRING_template(unsigned int n_elements
,
1401 const unsigned char *pattern_elements
) :
1402 Restricted_Length_Template(STRING_PATTERN
)
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
);
1411 HEXSTRING_template::HEXSTRING_template(const HEXSTRING_template
& other_value
) :
1412 Restricted_Length_Template()
1414 copy_template(other_value
);
1417 HEXSTRING_template::~HEXSTRING_template()
1422 HEXSTRING_template
& HEXSTRING_template::operator=(template_sel other_value
)
1424 check_single_selection(other_value
);
1426 set_selection(other_value
);
1430 HEXSTRING_template
& HEXSTRING_template::operator=(const HEXSTRING
& other_value
)
1432 other_value
.must_bound("Assignment of an unbound hexstring value to a "
1435 set_selection(SPECIFIC_VALUE
);
1436 single_value
= other_value
;
1440 HEXSTRING_template
& HEXSTRING_template::operator=(
1441 const HEXSTRING_ELEMENT
& other_value
)
1443 other_value
.must_bound("Assignment of an unbound hexstring element to a "
1446 set_selection(SPECIFIC_VALUE
);
1447 single_value
= other_value
;
1451 HEXSTRING_template
& HEXSTRING_template::operator=(
1452 const OPTIONAL
<HEXSTRING
>& other_value
)
1455 switch (other_value
.get_selection()) {
1456 case OPTIONAL_PRESENT
:
1457 set_selection(SPECIFIC_VALUE
);
1458 single_value
= (const HEXSTRING
&) other_value
;
1461 set_selection(OMIT_VALUE
);
1464 TTCN_error("Assignment of an unbound optional field to a hexstring "
1470 HEXSTRING_template
& HEXSTRING_template::operator=(
1471 const HEXSTRING_template
& other_value
)
1473 if (&other_value
!= this) {
1475 copy_template(other_value
);
1480 HEXSTRING_ELEMENT
HEXSTRING_template::operator[](int index_value
)
1482 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1483 TTCN_error("Accessing a hexstring element of a non-specific hexstring "
1485 return single_value
[index_value
];
1488 HEXSTRING_ELEMENT
HEXSTRING_template::operator[](const INTEGER
& index_value
)
1490 index_value
.must_bound("Indexing a hexstring template with an unbound "
1492 return (*this)[(int)index_value
];
1495 const HEXSTRING_ELEMENT
HEXSTRING_template::operator[](int index_value
) const
1497 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1498 TTCN_error("Accessing a hexstring element of a non-specific hexstring "
1500 return single_value
[index_value
];
1503 const HEXSTRING_ELEMENT
HEXSTRING_template::operator[](const INTEGER
& index_value
) const
1505 index_value
.must_bound("Indexing a hexstring template with an unbound "
1507 return (*this)[(int)index_value
];
1510 boolean
HEXSTRING_template::match(const HEXSTRING
& other_value
) const
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
;
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
1527 return template_selection
== COMPLEMENTED_LIST
;
1528 case STRING_PATTERN
:
1529 return match_pattern(pattern_value
, other_value
.val_ptr
);
1531 TTCN_error("Matching an uninitialized/unsupported hexstring template.");
1536 const HEXSTRING
& HEXSTRING_template::valueof() const
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
;
1544 int HEXSTRING_template::lengthof() const
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
;
1557 TTCN_error("Performing lengthof() operation on a hexstring template "
1558 "containing omit value.");
1562 has_any_or_none
= TRUE
; // max. length is infinity
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.");
1575 min_length
= item_length
;
1576 has_any_or_none
= FALSE
;
1579 case COMPLEMENTED_LIST
:
1580 TTCN_error("Performing lengthof() operation on a hexstring template "
1581 "containing complemented list.");
1582 case STRING_PATTERN
:
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, ?
1589 has_any_or_none
= TRUE
; // case of * character
1593 TTCN_error("Performing lengthof() operation on an "
1594 "uninitialized/unsupported hexstring template.");
1596 return check_section_is_single(min_length
, has_any_or_none
, "length", "a",
1597 "hexstring template");
1600 void HEXSTRING_template::set_type(template_sel template_type
,
1601 unsigned int list_length
)
1603 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
) TTCN_error(
1604 "Setting an invalid list type for a hexstring template.");
1606 set_selection(template_type
);
1607 value_list
.n_values
= list_length
;
1608 value_list
.list_value
= new HEXSTRING_template
[list_length
];
1611 HEXSTRING_template
& HEXSTRING_template::list_item(unsigned int list_index
)
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
];
1621 void HEXSTRING_template::log() const
1623 switch (template_selection
) {
1624 case SPECIFIC_VALUE
:
1627 case COMPLEMENTED_LIST
:
1628 TTCN_Logger::log_event_str("complement ");
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();
1636 TTCN_Logger::log_char(')');
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
];
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('*');
1649 TTCN_Logger::log_event_str("<unknown>");
1651 TTCN_Logger::log_event_str("'H");
1661 void HEXSTRING_template::log_match(const HEXSTRING
& match_value
) const
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(" := ");
1669 TTCN_Logger::log_event_str(" with ");
1671 if (match(match_value
))
1672 TTCN_Logger::log_event_str(" matched");
1674 TTCN_Logger::log_event_str(" unmatched");
1677 void 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
:
1683 case Module_Param::MP_Any
:
1686 case Module_Param::MP_AnyOrNone
:
1687 *this = ANY_OR_OMIT
;
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
));
1696 case Module_Param::MP_Hexstring
:
1697 *this = HEXSTRING(param
.get_string_size(), (unsigned char*)param
.get_string_data());
1699 case Module_Param::MP_Hexstring_Template
:
1700 *this = HEXSTRING_template(param
.get_string_size(), (unsigned char*)param
.get_string_data());
1703 param
.type_error("hexstring template");
1705 is_ifpresent
= param
.get_ifpresent();
1706 set_length_range(param
);
1709 void HEXSTRING_template::encode_text(Text_Buf
& text_buf
) const
1711 encode_text_restricted(text_buf
);
1712 switch (template_selection
) {
1717 case SPECIFIC_VALUE
:
1718 single_value
.encode_text(text_buf
);
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
);
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
);
1731 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1732 "hexstring template.");
1736 void HEXSTRING_template::decode_text(Text_Buf
& text_buf
)
1739 decode_text_restricted(text_buf
);
1740 switch (template_selection
) {
1745 case SPECIFIC_VALUE
:
1746 single_value
.decode_text(text_buf
);
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
);
1755 case STRING_PATTERN
: {
1756 unsigned int n_elements
= text_buf
.pull_int().get_val();
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
);
1765 TTCN_error("Text decoder: An unknown/unsupported selection was "
1766 "received for a hexstring template.");
1770 boolean
HEXSTRING_template::is_present() const
1772 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
1773 return !match_omit();
1776 boolean
HEXSTRING_template::match_omit() const
1778 if (is_ifpresent
) return TRUE
;
1779 switch (template_selection
) {
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
1788 return template_selection
== COMPLEMENTED_LIST
;
1795 #ifndef TITAN_RUNTIME_2
1796 void HEXSTRING_template::check_restriction(template_res t_res
, const char* t_name
) const
1798 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
1799 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
1801 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
1804 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
1805 template_selection
==SPECIFIC_VALUE
)) return;
1808 if (!match_omit()) return;
1813 TTCN_error("Restriction `%s' on template of type %s violated.",
1814 get_res_name(t_res
), t_name
? t_name
: "hexstring");