1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 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 "Octetstring.hh"
9 #include "../common/memory.h"
11 #include "String_struct.hh"
12 #include "Param_Types.hh"
21 #include "../common/dbgnew.hh"
24 // octetstring value class
26 /** The amount of memory needed for a string containing n octets. */
27 #define MEMORY_SIZE(n) (sizeof(octetstring_struct) - sizeof(int) + (n))
29 static const Token_Match
30 octetstring_value_match("^(([0-9A-Fa-f]{2})+).*$", TRUE
);
32 void OCTETSTRING::init_struct(int n_octets
)
36 TTCN_error("Initializing an octetstring with a negative length.");
37 } else if (n_octets
== 0) {
38 /* This will represent the empty strings so they won't need allocated
39 * memory, this delays the memory allocation until it is really needed.
41 static octetstring_struct empty_string
= { 1, 0, "" };
42 val_ptr
= &empty_string
;
43 empty_string
.ref_count
++;
45 val_ptr
= (octetstring_struct
*)Malloc(MEMORY_SIZE(n_octets
));
46 val_ptr
->ref_count
= 1;
47 val_ptr
->n_octets
= n_octets
;
51 void OCTETSTRING::copy_value()
53 if (val_ptr
== NULL
|| val_ptr
->n_octets
<= 0)
54 TTCN_error("Internal error: Invalid internal data structure when copying "
55 "the memory area of an octetstring value.");
56 if (val_ptr
->ref_count
> 1) {
57 octetstring_struct
*old_ptr
= val_ptr
;
59 init_struct(old_ptr
->n_octets
);
60 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, old_ptr
->n_octets
);
64 // Called by operator+, operator~, operator&, operator|
65 // to initialize the return value to the appropriate capacity
66 // without copying bytes (which will be altered).
67 OCTETSTRING::OCTETSTRING(int n_octets
)
69 init_struct(n_octets
);
72 OCTETSTRING::OCTETSTRING()
77 OCTETSTRING::OCTETSTRING(int n_octets
, const unsigned char* octets_ptr
)
79 init_struct(n_octets
);
80 memcpy(val_ptr
->octets_ptr
, octets_ptr
, n_octets
);
83 OCTETSTRING::OCTETSTRING(const OCTETSTRING
& other_value
)
84 : Base_Type(other_value
)
86 other_value
.must_bound("Copying an unbound octetstring value.");
87 val_ptr
= other_value
.val_ptr
;
91 OCTETSTRING::OCTETSTRING(const OCTETSTRING_ELEMENT
& other_value
)
93 other_value
.must_bound("Copying an unbound octetstring element.");
95 val_ptr
->octets_ptr
[0] = other_value
.get_octet();
98 OCTETSTRING::~OCTETSTRING()
103 OCTETSTRING
& OCTETSTRING::operator=(const OCTETSTRING
& other_value
)
105 other_value
.must_bound("Assignment of an unbound octetstring value.");
106 if (&other_value
!= this) {
108 val_ptr
= other_value
.val_ptr
;
109 val_ptr
->ref_count
++;
114 OCTETSTRING
& OCTETSTRING::operator=(const OCTETSTRING_ELEMENT
& other_value
)
116 other_value
.must_bound("Assignment of an unbound octetstring element to an "
118 unsigned char octet_value
= other_value
.get_octet();
121 val_ptr
->octets_ptr
[0] = octet_value
;
125 boolean
OCTETSTRING::operator==(const OCTETSTRING
& other_value
) const
127 must_bound("Unbound left operand of octetstring comparison.");
128 other_value
.must_bound("Unbound right operand of octetstring comparison.");
129 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
) return FALSE
;
130 return !memcmp(val_ptr
->octets_ptr
, other_value
.val_ptr
->octets_ptr
,
134 boolean
OCTETSTRING::operator==(const OCTETSTRING_ELEMENT
& other_value
) const
136 must_bound("Unbound left operand of octetstring comparison.");
137 other_value
.must_bound("Unbound right operand of octetstring element "
139 if (val_ptr
->n_octets
!= 1) return FALSE
;
140 return val_ptr
->octets_ptr
[0] == other_value
.get_octet();
143 OCTETSTRING
OCTETSTRING::operator+(const OCTETSTRING
& other_value
) const
145 must_bound("Unbound left operand of octetstring concatenation.");
146 other_value
.must_bound("Unbound right operand of octetstring concatenation.");
147 int left_n_octets
= val_ptr
->n_octets
;
148 if (left_n_octets
== 0) return other_value
;
149 int right_n_octets
= other_value
.val_ptr
->n_octets
;
150 if (right_n_octets
== 0) return *this;
151 OCTETSTRING
ret_val(left_n_octets
+ right_n_octets
);
152 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
, left_n_octets
);
153 memcpy(ret_val
.val_ptr
->octets_ptr
+ left_n_octets
,
154 other_value
.val_ptr
->octets_ptr
, right_n_octets
);
158 OCTETSTRING
OCTETSTRING::operator+(const OCTETSTRING_ELEMENT
& other_value
) const
160 must_bound("Unbound left operand of octetstring concatenation.");
161 other_value
.must_bound("Unbound right operand of octetstring element "
163 OCTETSTRING
ret_val(val_ptr
->n_octets
+ 1);
164 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
, val_ptr
->n_octets
);
165 ret_val
.val_ptr
->octets_ptr
[val_ptr
->n_octets
] = other_value
.get_octet();
169 OCTETSTRING
& OCTETSTRING::operator+=(const OCTETSTRING
& other_value
)
171 must_bound("Appending an octetstring value to an unbound octetstring value.");
172 other_value
.must_bound("Appending an unbound octetstring value to another "
173 "octetstring value.");
174 int other_n_octets
= other_value
.val_ptr
->n_octets
;
175 if (other_n_octets
> 0) {
176 if (val_ptr
->n_octets
== 0) {
178 val_ptr
= other_value
.val_ptr
;
179 val_ptr
->ref_count
++;
180 } else if (val_ptr
->ref_count
> 1) {
181 octetstring_struct
*old_ptr
= val_ptr
;
182 old_ptr
->ref_count
--;
183 init_struct(old_ptr
->n_octets
+ other_n_octets
);
184 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, old_ptr
->n_octets
);
185 memcpy(val_ptr
->octets_ptr
+ old_ptr
->n_octets
,
186 other_value
.val_ptr
->octets_ptr
, other_n_octets
);
188 val_ptr
= (octetstring_struct
*)
189 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
+ other_n_octets
));
190 memcpy(val_ptr
->octets_ptr
+ val_ptr
->n_octets
,
191 other_value
.val_ptr
->octets_ptr
, other_n_octets
);
192 val_ptr
->n_octets
+= other_n_octets
;
198 OCTETSTRING
& OCTETSTRING::operator+=(const OCTETSTRING_ELEMENT
& other_value
)
200 must_bound("Appending an octetstring element to an unbound octetstring "
202 other_value
.must_bound("Appending an unbound octetstring element to an "
203 "octetstring value.");
204 if (val_ptr
->ref_count
> 1) {
205 octetstring_struct
*old_ptr
= val_ptr
;
206 old_ptr
->ref_count
--;
207 init_struct(old_ptr
->n_octets
+ 1);
208 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, old_ptr
->n_octets
);
209 val_ptr
->octets_ptr
[old_ptr
->n_octets
] = other_value
.get_octet();
211 val_ptr
= (octetstring_struct
*)
212 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
+ 1));
213 val_ptr
->octets_ptr
[val_ptr
->n_octets
] = other_value
.get_octet();
219 OCTETSTRING
OCTETSTRING::operator~() const
221 must_bound("Unbound octetstring operand of operator not4b.");
222 OCTETSTRING
ret_val(val_ptr
->n_octets
);
223 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
224 ret_val
.val_ptr
->octets_ptr
[i
] = ~val_ptr
->octets_ptr
[i
];
228 OCTETSTRING
OCTETSTRING::operator&(const OCTETSTRING
& other_value
) const
230 must_bound("Left operand of operator and4b is an unbound octetstring value.");
231 other_value
.must_bound("Right operand of operator and4b is an unbound "
232 "octetstring value.");
233 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
)
234 TTCN_error("The octetstring operands of operator and4b must have the "
236 OCTETSTRING
ret_val(val_ptr
->n_octets
);
237 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
238 ret_val
.val_ptr
->octets_ptr
[i
] =
239 val_ptr
->octets_ptr
[i
] & other_value
.val_ptr
->octets_ptr
[i
];
243 OCTETSTRING
OCTETSTRING::operator&(const OCTETSTRING_ELEMENT
& other_value
) const
245 must_bound("Left operand of operator and4b is an unbound octetstring value.");
246 other_value
.must_bound("Right operand of operator and4b is an unbound "
247 "octetstring element.");
248 if (val_ptr
->n_octets
!= 1)
249 TTCN_error("The octetstring operands of "
250 "operator and4b must have the same length.");
251 unsigned char result
= val_ptr
->octets_ptr
[0] & other_value
.get_octet();
252 return OCTETSTRING(1, &result
);
255 OCTETSTRING
OCTETSTRING::operator|(const OCTETSTRING
& other_value
) const
257 must_bound("Left operand of operator or4b is an unbound octetstring value.");
258 other_value
.must_bound("Right operand of operator or4b is an unbound "
259 "octetstring value.");
260 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
)
261 TTCN_error("The octetstring operands of operator or4b must have the "
263 OCTETSTRING
ret_val(val_ptr
->n_octets
);
264 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
265 ret_val
.val_ptr
->octets_ptr
[i
] =
266 val_ptr
->octets_ptr
[i
] | other_value
.val_ptr
->octets_ptr
[i
];
270 OCTETSTRING
OCTETSTRING::operator|(const OCTETSTRING_ELEMENT
& other_value
) const
272 must_bound("Left operand of operator or4b is an unbound octetstring value.");
273 other_value
.must_bound("Right operand of operator or4b is an unbound "
274 "octetstring element.");
275 if (val_ptr
->n_octets
!= 1)
276 TTCN_error("The octetstring operands of "
277 "operator or4b must have the same length.");
278 unsigned char result
= val_ptr
->octets_ptr
[0] | other_value
.get_octet();
279 return OCTETSTRING(1, &result
);
282 OCTETSTRING
OCTETSTRING::operator^(const OCTETSTRING
& other_value
) const
284 must_bound("Left operand of operator xor4b is an unbound octetstring value.");
285 other_value
.must_bound("Right operand of operator xor4b is an unbound "
286 "octetstring value.");
287 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
)
288 TTCN_error("The octetstring operands of operator xor4b must have the "
290 OCTETSTRING
ret_val(val_ptr
->n_octets
);
291 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
292 ret_val
.val_ptr
->octets_ptr
[i
] =
293 val_ptr
->octets_ptr
[i
] ^ other_value
.val_ptr
->octets_ptr
[i
];
297 OCTETSTRING
OCTETSTRING::operator^(const OCTETSTRING_ELEMENT
& other_value
) const
299 must_bound("Left operand of operator xor4b is an unbound octetstring value.");
300 other_value
.must_bound("Right operand of operator xor4b is an unbound "
301 "octetstring element.");
302 if (val_ptr
->n_octets
!= 1)
303 TTCN_error("The octetstring operands of "
304 "operator xor4b must have the same length.");
305 unsigned char result
= val_ptr
->octets_ptr
[0] ^ other_value
.get_octet();
306 return OCTETSTRING(1, &result
);
309 OCTETSTRING
OCTETSTRING::operator<<(int shift_count
) const
311 must_bound("Unbound octetstring operand of shift left operator.");
312 if (shift_count
> 0) {
313 if (val_ptr
->n_octets
== 0) return *this;
314 OCTETSTRING
ret_val(val_ptr
->n_octets
);
315 if (shift_count
> val_ptr
->n_octets
) shift_count
= val_ptr
->n_octets
;
316 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
+ shift_count
,
317 val_ptr
->n_octets
- shift_count
);
318 memset(ret_val
.val_ptr
->octets_ptr
+ val_ptr
->n_octets
- shift_count
,
321 } else if (shift_count
== 0) return *this;
322 else return *this >> (-shift_count
);
325 OCTETSTRING
OCTETSTRING::operator<<(const INTEGER
& shift_count
) const
327 shift_count
.must_bound("Unbound right operand of octetstring shift left "
329 return *this << (int)shift_count
;
332 OCTETSTRING
OCTETSTRING::operator>>(int shift_count
) const
334 must_bound("Unbound octetstring operand of shift right operator.");
335 if (shift_count
> 0) {
336 if (val_ptr
->n_octets
== 0) return *this;
337 OCTETSTRING
ret_val(val_ptr
->n_octets
);
338 if (shift_count
> val_ptr
->n_octets
) shift_count
= val_ptr
->n_octets
;
339 memset(ret_val
.val_ptr
->octets_ptr
, 0, shift_count
);
340 memcpy(ret_val
.val_ptr
->octets_ptr
+ shift_count
, val_ptr
->octets_ptr
,
341 val_ptr
->n_octets
- shift_count
);
343 } else if (shift_count
== 0) return *this;
344 else return *this << (-shift_count
);
347 OCTETSTRING
OCTETSTRING::operator>>(const INTEGER
& shift_count
) const
349 shift_count
.must_bound("Unbound right operand of octetstring shift right "
351 return *this >> (int)shift_count
;
354 OCTETSTRING
OCTETSTRING::operator<<=(int rotate_count
) const
356 must_bound("Unbound octetstring operand of rotate left operator.");
357 if (val_ptr
->n_octets
== 0) return *this;
358 if (rotate_count
>= 0) {
359 rotate_count
%= val_ptr
->n_octets
;
360 if (rotate_count
== 0) return *this;
361 OCTETSTRING
ret_val(val_ptr
->n_octets
);
362 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
+
363 rotate_count
, val_ptr
->n_octets
- rotate_count
);
364 memcpy(ret_val
.val_ptr
->octets_ptr
+ val_ptr
->n_octets
- rotate_count
,
365 val_ptr
->octets_ptr
, rotate_count
);
367 } else return *this >>= (-rotate_count
);
370 OCTETSTRING
OCTETSTRING::operator<<=(const INTEGER
& rotate_count
) const
372 rotate_count
.must_bound("Unbound right operand of octetstring rotate left "
374 return *this <<= (int)rotate_count
;
377 OCTETSTRING
OCTETSTRING::operator>>=(int rotate_count
) const
379 must_bound("Unbound octetstring operand of rotate right operator.");
380 if (val_ptr
->n_octets
== 0) return *this;
381 if (rotate_count
>= 0) {
382 rotate_count
%= val_ptr
->n_octets
;
383 if (rotate_count
== 0) return *this;
384 OCTETSTRING
ret_val(val_ptr
->n_octets
);
385 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
+
386 val_ptr
->n_octets
- rotate_count
, rotate_count
);
387 memcpy(ret_val
.val_ptr
->octets_ptr
+ rotate_count
,
388 val_ptr
->octets_ptr
, val_ptr
->n_octets
- rotate_count
);
390 } else return *this <<= (-rotate_count
);
393 OCTETSTRING
OCTETSTRING::operator>>=(const INTEGER
& rotate_count
) const
395 rotate_count
.must_bound("Unbound right operand of octetstring rotate right "
397 return *this >>= (int)rotate_count
;
400 OCTETSTRING_ELEMENT
OCTETSTRING::operator[](int index_value
)
402 if (val_ptr
== NULL
&& index_value
== 0) {
404 return OCTETSTRING_ELEMENT(FALSE
, *this, 0);
406 must_bound("Accessing an element of an unbound octetstring value.");
407 if (index_value
< 0) TTCN_error("Accessing an octetstring element using "
408 "a negative index (%d).", index_value
);
409 int n_octets
= val_ptr
->n_octets
;
410 if (index_value
> n_octets
) TTCN_error("Index overflow when accessing a "
411 "octetstring element: The index is %d, but the string has only %d "
412 "octets.", index_value
, n_octets
);
413 if (index_value
== n_octets
) {
414 if (val_ptr
->ref_count
== 1) {
415 val_ptr
= (octetstring_struct
*)
416 Realloc(val_ptr
, MEMORY_SIZE(n_octets
+ 1));
419 octetstring_struct
*old_ptr
= val_ptr
;
420 old_ptr
->ref_count
--;
421 init_struct(n_octets
+ 1);
422 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, n_octets
);
424 return OCTETSTRING_ELEMENT(FALSE
, *this, index_value
);
425 } else return OCTETSTRING_ELEMENT(TRUE
, *this, index_value
);
429 OCTETSTRING_ELEMENT
OCTETSTRING::operator[](const INTEGER
& index_value
)
431 index_value
.must_bound("Indexing a octetstring value with an unbound integer "
433 return (*this)[(int)index_value
];
436 const OCTETSTRING_ELEMENT
OCTETSTRING::operator[](int index_value
) const
438 must_bound("Accessing an element of an unbound octetstring value.");
439 if (index_value
< 0) TTCN_error("Accessing an octetstring element using a "
440 "negative index (%d).", index_value
);
441 if (index_value
>= val_ptr
->n_octets
) TTCN_error("Index overflow when "
442 "accessing a octetstring element: The index is %d, but the string has "
443 "only %d octets.", index_value
, val_ptr
->n_octets
);
444 return OCTETSTRING_ELEMENT(TRUE
, const_cast<OCTETSTRING
&>(*this),
448 const OCTETSTRING_ELEMENT
OCTETSTRING::operator[](const INTEGER
& index_value
)
451 index_value
.must_bound("Indexing a octetstring value with an unbound integer "
453 return (*this)[(int)index_value
];
456 void OCTETSTRING::clean_up()
458 if (val_ptr
!= NULL
) {
459 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
460 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
461 else TTCN_error("Internal error: Invalid reference counter in an "
462 "octetstring value.");
467 int OCTETSTRING::lengthof() const
469 must_bound("Getting the length of an unbound octetstring value.");
470 return val_ptr
->n_octets
;
473 OCTETSTRING::operator const unsigned char*() const
475 must_bound("Casting an unbound octetstring value to const unsigned char*.");
476 return val_ptr
->octets_ptr
;
479 void OCTETSTRING::log() const
481 if (val_ptr
!= NULL
) {
482 boolean only_printable
= TRUE
;
483 TTCN_Logger::log_char('\'');
484 for (int i
= 0; i
< val_ptr
->n_octets
; i
++) {
485 unsigned char octet
= val_ptr
->octets_ptr
[i
];
486 TTCN_Logger::log_octet(octet
);
487 if (only_printable
&& !TTCN_Logger::is_printable(octet
))
488 only_printable
= FALSE
;
490 TTCN_Logger::log_event_str("'O");
491 if (only_printable
&& val_ptr
->n_octets
> 0) {
492 TTCN_Logger::log_event_str(" (\"");
493 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
494 TTCN_Logger::log_char_escaped(val_ptr
->octets_ptr
[i
]);
495 TTCN_Logger::log_event_str("\")");
497 } else TTCN_Logger::log_event_unbound();
500 void OCTETSTRING::set_param(Module_Param
& param
) {
501 param
.basic_check(Module_Param::BC_VALUE
|Module_Param::BC_LIST
, "octetstring value");
502 Module_Param_Ptr mp
= ¶m
;
503 if (param
.get_type() == Module_Param::MP_Reference
) {
504 mp
= param
.get_referenced_param();
506 switch (mp
->get_type()) {
507 case Module_Param::MP_Octetstring
:
508 switch (param
.get_operation_type()) {
509 case Module_Param::OT_ASSIGN
:
511 init_struct(mp
->get_string_size());
512 memcpy(val_ptr
->octets_ptr
, mp
->get_string_data(), val_ptr
->n_octets
);
514 case Module_Param::OT_CONCAT
:
516 *this += OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
518 *this = OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
522 TTCN_error("Internal error: OCTETSTRING::set_param()");
525 case Module_Param::MP_Expression
:
526 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
527 OCTETSTRING operand1
, operand2
;
528 operand1
.set_param(*mp
->get_operand1());
529 operand2
.set_param(*mp
->get_operand2());
530 if (param
.get_operation_type() == Module_Param::OT_CONCAT
) {
531 *this = *this + operand1
+ operand2
;
534 *this = operand1
+ operand2
;
538 param
.expr_type_error("a octetstring");
542 param
.type_error("octetstring value");
547 Module_Param
* OCTETSTRING::get_param(Module_Param_Name
& /* param_name */) const
550 return new Module_Param_Unbound();
552 unsigned char* val_cpy
= (unsigned char *)Malloc(val_ptr
->n_octets
);
553 memcpy(val_cpy
, val_ptr
->octets_ptr
, val_ptr
->n_octets
);
554 return new Module_Param_Octetstring(val_ptr
->n_octets
, val_cpy
);
557 void OCTETSTRING::encode_text(Text_Buf
& text_buf
) const
559 must_bound("Text encoder: Encoding an unbound octetstring value.");
560 text_buf
.push_int(val_ptr
->n_octets
);
561 if(val_ptr
->n_octets
> 0)
562 text_buf
.push_raw(val_ptr
->n_octets
, val_ptr
->octets_ptr
);
565 void OCTETSTRING::decode_text(Text_Buf
& text_buf
)
567 int n_octets
= text_buf
.pull_int().get_val();
569 TTCN_error("Text decoder: Invalid length was received for an octetstring.");
571 init_struct(n_octets
);
572 if (n_octets
> 0) text_buf
.pull_raw(n_octets
, val_ptr
->octets_ptr
);
575 void OCTETSTRING::encode(const TTCN_Typedescriptor_t
& p_td
,
577 TTCN_EncDec::coding_t p_coding
, ...) const
580 va_start(pvar
, p_coding
);
582 case TTCN_EncDec::CT_BER
: {
583 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
584 unsigned BER_coding
=va_arg(pvar
, unsigned);
585 BER_encode_chk_coding(BER_coding
);
586 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
587 tlv
->put_in_buffer(p_buf
);
588 ASN_BER_TLV_t::destruct(tlv
);
590 case TTCN_EncDec::CT_RAW
: {
591 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
593 TTCN_EncDec_ErrorContext::error_internal
594 ("No RAW descriptor available for type '%s'.", p_td
.name
);
598 RAW_enc_tree
root(true,NULL
,&rp
,1,p_td
.raw
);
599 RAW_encode(p_td
, root
);
600 root
.put_to_buf(p_buf
);
602 case TTCN_EncDec::CT_TEXT
: {
603 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
605 TTCN_EncDec_ErrorContext::error_internal
606 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
607 TEXT_encode(p_td
,p_buf
);
609 case TTCN_EncDec::CT_XER
: {
610 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
611 unsigned XER_coding
=va_arg(pvar
, unsigned);
612 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
614 case TTCN_EncDec::CT_JSON
: {
615 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
617 TTCN_EncDec_ErrorContext::error_internal
618 ("No JSON descriptor available for type '%s'.", p_td
.name
);
619 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
620 JSON_encode(p_td
, tok
);
621 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
624 TTCN_error("Unknown coding method requested to encode type '%s'",
630 void OCTETSTRING::decode(const TTCN_Typedescriptor_t
& p_td
,
632 TTCN_EncDec::coding_t p_coding
, ...)
635 va_start(pvar
, p_coding
);
637 case TTCN_EncDec::CT_BER
: {
638 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
639 unsigned L_form
=va_arg(pvar
, unsigned);
641 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
642 BER_decode_TLV(p_td
, tlv
, L_form
);
643 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
645 case TTCN_EncDec::CT_RAW
: {
646 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
648 TTCN_EncDec_ErrorContext::error_internal
649 ("No RAW descriptor available for type '%s'.", p_td
.name
);
651 switch(p_td
.raw
->top_bit_order
){
659 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
660 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
661 "Can not decode type '%s', because invalid or incomplete"
662 " message was received"
665 case TTCN_EncDec::CT_TEXT
: {
666 Limit_Token_List limit
;
667 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
669 TTCN_EncDec_ErrorContext::error_internal
670 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
671 const unsigned char *b
=p_buf
.get_data();
672 if(b
[p_buf
.get_len()-1]!='\0'){
673 p_buf
.set_pos(p_buf
.get_len());
674 p_buf
.put_zero(8,ORDER_LSB
);
677 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
678 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
679 "Can not decode type '%s', because invalid or incomplete"
680 " message was received"
683 case TTCN_EncDec::CT_XER
: {
684 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
685 unsigned XER_coding
=va_arg(pvar
, unsigned);
686 XmlReaderWrap
reader(p_buf
);
687 int success
= reader
.Read();
688 for (; success
==1; success
=reader
.Read()) {
689 int type
= reader
.NodeType();
690 if (type
==XML_READER_TYPE_ELEMENT
)
693 XER_decode(*p_td
.xer
, reader
, XER_coding
, 0);
694 size_t bytes
= reader
.ByteConsumed();
695 p_buf
.set_pos(bytes
);
697 case TTCN_EncDec::CT_JSON
: {
698 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
700 TTCN_EncDec_ErrorContext::error_internal
701 ("No JSON descriptor available for type '%s'.", p_td
.name
);
702 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
703 if(JSON_decode(p_td
, tok
, false)<0)
704 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
705 "Can not decode type '%s', because invalid or incomplete"
706 " message was received"
708 p_buf
.set_pos(tok
.get_buf_pos());
711 TTCN_error("Unknown coding method requested to decode type '%s'",
718 OCTETSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
719 unsigned p_coding
) const
722 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
724 new_tlv
=BER_encode_TLV_OCTETSTRING
725 (p_coding
, val_ptr
->n_octets
, val_ptr
->octets_ptr
);
727 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
731 #ifdef TITAN_RUNTIME_2
732 ASN_BER_TLV_t
* OCTETSTRING::BER_encode_negtest_raw() const
734 unsigned char *p_Vstr
= (unsigned char *)Malloc(val_ptr
->n_octets
);
735 memcpy(p_Vstr
, val_ptr
->octets_ptr
, val_ptr
->n_octets
);
736 ASN_BER_TLV_t
* new_tlv
= ASN_BER_TLV_t::construct(val_ptr
->n_octets
, p_Vstr
);
740 int OCTETSTRING::encode_raw(TTCN_Buffer
& p_buf
) const
742 p_buf
.put_string(*this);
743 return val_ptr
? val_ptr
->n_octets
: 0;
746 int OCTETSTRING::RAW_encode_negtest_raw(RAW_enc_tree
& p_myleaf
) const
748 if (p_myleaf
.must_free
)
749 Free(p_myleaf
.body
.leaf
.data_ptr
);
750 p_myleaf
.must_free
= false;
751 p_myleaf
.data_ptr_used
= true;
752 p_myleaf
.body
.leaf
.data_ptr
= val_ptr
->octets_ptr
;
753 return p_myleaf
.length
= val_ptr
->n_octets
* 8;
756 int OCTETSTRING::JSON_encode_negtest_raw(JSON_Tokenizer
& p_tok
) const
758 if (val_ptr
!= NULL
) {
759 p_tok
.put_raw_data((const char*)val_ptr
->octets_ptr
, val_ptr
->n_octets
);
760 return val_ptr
->n_octets
;
766 boolean
OCTETSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
767 const ASN_BER_TLV_t
& p_tlv
,
772 ASN_BER_TLV_t stripped_tlv
;
773 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
774 TTCN_EncDec_ErrorContext
ec("While decoding OCTETSTRING type: ");
775 /* Upper estimation for the length. */
776 size_t stripped_tlv_len
= stripped_tlv
.get_len();
777 if (stripped_tlv_len
< 2) return FALSE
;
778 int max_len
= stripped_tlv_len
- 2;
779 init_struct(max_len
);
780 unsigned int octetnum_start
= 0;
781 BER_decode_TLV_OCTETSTRING(stripped_tlv
, L_form
, octetnum_start
,
782 val_ptr
->n_octets
, val_ptr
->octets_ptr
);
783 if (val_ptr
->n_octets
< max_len
) {
784 if (val_ptr
->n_octets
== 0) {
788 val_ptr
= (octetstring_struct
*)
789 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
));
795 int OCTETSTRING::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
796 TTCN_Buffer
& buff
, Limit_Token_List
& limit
,
797 boolean no_err
, boolean
/*first_call*/)
799 int decoded_length
=0;
802 if(p_td
.text
->begin_decode
){
804 if((tl
=p_td
.text
->begin_decode
->match_begin(buff
))<0){
806 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
807 "The specified token '%s' not found for '%s': ",
808 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
812 buff
.increase_pos(tl
);
814 // never returns "too short"
815 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
817 if(p_td
.text
->select_token
){
819 if((tl
=p_td
.text
->select_token
->match_begin(buff
))<0) {
820 if(no_err
) return -1;
825 if( p_td
.text
->val
.parameters
826 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!=-1){
827 str_len
=p_td
.text
->val
.parameters
->decoding_params
.min_length
*2;
828 } else if(p_td
.text
->end_decode
){
830 if((tl
=p_td
.text
->end_decode
->match_first(buff
))<0) {
831 if(no_err
) return -1;
835 } else if (limit
.has_token()){
837 if((tl
=limit
.match(buff
))<0)
838 tl
=buff
.get_read_len()-1;;
842 if((tl
=octetstring_value_match
.match_begin(buff
))<0) {
843 if(no_err
) {return -1; }
848 str_len
=(str_len
/2)*2;
849 //printf("HALI chr:%d ",str_len);
850 int n_octets
= str_len
/ 2;
851 init_struct(n_octets
);
852 unsigned char *octets_ptr
= val_ptr
->octets_ptr
;
853 const char *value
=(const char*)buff
.get_read_data();
854 for (int i
= 0; i
< n_octets
; i
++) {
855 unsigned char upper_nibble
= char_to_hexdigit(value
[2 * i
]);
856 unsigned char lower_nibble
= char_to_hexdigit(value
[2 * i
+ 1]);
857 if (upper_nibble
> 0x0F){
858 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
859 "The octetstring value may contain hexadecimal digits only. "
860 "Character \"%c\" was found.", value
[2 * i
]);
863 if (lower_nibble
> 0x0F){
864 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
865 "The octetstring value str2oct() may contain hexadecimal digits only. "
866 "Character \"%c\" was found.", value
[2 * i
+ 1]);
869 octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
872 //printf("%s\n\r",val_ptr->chars_ptr);
873 decoded_length
+=str_len
;
874 buff
.increase_pos(str_len
);
876 if(p_td
.text
->end_decode
){
878 if((tl
=p_td
.text
->end_decode
->match_begin(buff
))<0){
880 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
881 "The specified token '%s' not found for '%s': ",
882 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
886 buff
.increase_pos(tl
);
888 return decoded_length
;
891 // From Charstring.cc
892 extern char base64_decoder_table
[256];
893 extern unsigned int xlate(cbyte
* in
, int phase
, unsigned char* dest
);
894 extern const char cb64
[];
896 int OCTETSTRING::XER_encode(const XERdescriptor_t
& p_td
,
897 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
900 TTCN_EncDec_ErrorContext::error
901 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound octetstring value.");
903 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
904 // SIMPLE_TYPE has no influence on is_exer, we set it for later
905 int encoded_length
=(int)p_buf
.get_len();
906 int empty_element
= val_ptr
==NULL
|| val_ptr
->n_octets
== 0;
908 flavor
&= ~XER_RECOF
; // octetstring doesn't care
909 begin_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
911 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
913 size_t clear_len
= lengthof();
914 const unsigned char * in
= operator const unsigned char*();
916 /* Encode 3 bytes of cleartext into 4 bytes of Base64.
917 * Note that the algorithm is slightly different from Charstring.cc:
918 * we can't pad the source because it's const (this),
919 * so we need to check the indexes i+1 and i+2 before dereferencing */
920 for (size_t i
= 0; i
< clear_len
; i
+= 3) {
921 p_buf
.put_c( cb64
[ in
[i
] >> 2 ] );
922 p_buf
.put_c( cb64
[ ((in
[i
] & 0x03) << 4) | (i
+1 < clear_len
923 ? ((in
[i
+1] & 0xf0) >> 4)
925 p_buf
.put_c( i
+1 < clear_len
926 ? cb64
[ ((in
[i
+1] & 0x0f) << 2) | (i
+2 < clear_len
? ((in
[i
+2] & 0xc0) >> 6) :-0) ]
928 p_buf
.put_c( i
+2 < clear_len
? cb64
[ in
[i
+2] & 0x3f ] : '=' );
932 CHARSTRING val
= oct2str(*this);
933 p_buf
.put_string(val
);
936 end_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
938 return (int)p_buf
.get_len() - encoded_length
;
941 int OCTETSTRING::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
942 unsigned int flavor
, embed_values_dec_struct_t
*)
944 int exer
= is_exer(flavor
);
945 int success
= reader
.Ok(), depth
= -1, type
;
946 boolean own_tag
= !is_exerlist(flavor
) && !(exer
&& (p_td
.xer_bits
& UNTAGGED
));
948 const char * value
= 0;
949 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
950 const char * name
= verify_name(reader
, p_td
, exer
);
954 if (own_tag
) for (; success
== 1; success
= reader
.Read()) {
955 type
= reader
.NodeType();
956 if (XML_READER_TYPE_ELEMENT
== type
) {
957 verify_name(reader
, p_td
, exer
);
958 depth
= reader
.Depth();
959 if (reader
.IsEmptyElement()) {
960 if (exer
&& p_td
.dfeValue
!= 0) {
961 *this = *static_cast<const OCTETSTRING
*> (p_td
.dfeValue
);
968 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) break;
969 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
970 // End tag without intervening #text == empty content
971 verify_end(reader
, p_td
, depth
, exer
);
972 if (exer
&& p_td
.dfeValue
!= 0) {
973 *this = *static_cast<const OCTETSTRING
*>(p_td
.dfeValue
);
981 type
= reader
.NodeType();
982 if (success
== 1 && (XML_READER_TYPE_TEXT
== type
|| XML_READER_TYPE_ATTRIBUTE
== type
)) {
983 value
= (const char *)reader
.Value();
984 size_t len
= value
? strlen(value
) : 0;
986 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
990 init_struct(len
* 3 / 4);
991 unsigned char * dest
= val_ptr
->octets_ptr
;
993 for (size_t o
=0; o
<len
; ++o
) {
994 xmlChar c
= value
[o
];
995 if(c
== '=') { // padding starts
996 dest
+= xlate(in
, phase
, dest
);
1000 int val
= base64_decoder_table
[c
];
1003 phase
= (phase
+ 1) % 4;
1005 dest
+= xlate(in
,phase
, dest
);
1006 in
[0]=in
[1]=in
[2]=in
[3]=0;
1009 else if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1013 TTCN_EncDec_ErrorContext::warning(
1014 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
1015 "Invalid character for Base64 '%02X'", c
);
1019 val_ptr
->n_octets
= dest
- val_ptr
->octets_ptr
;
1022 else { // not base64
1023 if (len
& 1) { // that's odd...
1024 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1028 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1029 "Odd number of characters in octetstring");
1030 len
&= ~1; // make it even
1033 size_t n_octets
= len
/ 2;
1034 init_struct(n_octets
);
1036 len
= 0; // will act as 2*i
1037 for (size_t i
= 0; i
< n_octets
; ++i
, ++++len
) {
1038 unsigned char upper_nibble
= char_to_hexdigit(value
[len
]);
1039 unsigned char lower_nibble
= char_to_hexdigit(value
[len
+1]);
1040 if (upper_nibble
> 0x0F) {
1041 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1045 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1046 "The octetstring value may contain hexadecimal digits only. "
1047 "Character \"%c\" was found.", value
[len
]);
1051 if (lower_nibble
> 0x0F) {
1052 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1056 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1057 "The octetstring value may contain hexadecimal digits only. "
1058 "Character \"%c\" was found.", value
[len
+1]);
1062 val_ptr
->octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
1067 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1068 // Let the caller do reader.AdvanceAttribute();
1071 if (own_tag
) for (success
= reader
.Read(); success
== 1; success
= reader
.Read()) {
1072 type
= reader
.NodeType();
1073 if (XML_READER_TYPE_END_ELEMENT
== type
) {
1074 verify_end(reader
, p_td
, depth
, exer
);
1075 if (val_ptr
== 0 && p_td
.dfeValue
!= 0) {
1076 // The end tag must have followed the start tag
1077 *this = *static_cast<const OCTETSTRING
*>(p_td
.dfeValue
);
1079 reader
.Read(); // one last time
1084 return 1; // decode successful
1087 int OCTETSTRING::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1088 TTCN_Buffer
& buff
) const{
1089 int encoded_length
=0;
1090 if(p_td
.text
->begin_encode
){
1091 buff
.put_cs(*p_td
.text
->begin_encode
);
1092 encoded_length
+=p_td
.text
->begin_encode
->lengthof();
1095 TTCN_EncDec_ErrorContext::error
1096 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound value.");
1097 if(p_td
.text
->end_encode
){
1098 buff
.put_cs(*p_td
.text
->end_encode
);
1099 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1101 return encoded_length
;
1106 if(p_td
.text
->val
.parameters
){
1107 if(val_ptr
->n_octets
<p_td
.text
->val
.parameters
->coding_params
.min_length
){
1108 chars_before
=(p_td
.text
->
1109 val
.parameters
->coding_params
.min_length
-val_ptr
->n_octets
)*2;
1114 unsigned char* p
=NULL
;
1115 size_t len
=chars_before
;
1116 buff
.get_end(p
,len
);
1117 for(int a
=0;a
<chars_before
;a
++) p
[a
]=(unsigned char)'0';
1118 buff
.increase_length(chars_before
);
1119 encoded_length
+=chars_before
;
1122 if(val_ptr
->n_octets
){
1123 unsigned char* p
=NULL
;
1124 size_t len
=val_ptr
->n_octets
*2;
1125 buff
.get_end(p
,len
);
1126 len
=val_ptr
->n_octets
;
1127 for(size_t i
=0;i
<len
;i
++){
1128 p
[2 * i
] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] >> 4);
1129 p
[2 * i
+ 1] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] & 0x0F);
1131 buff
.increase_length(len
*2);
1132 encoded_length
+=len
*2;
1136 if(p_td
.text
->end_encode
){
1137 buff
.put_cs(*p_td
.text
->end_encode
);
1138 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1140 return encoded_length
;
1143 int OCTETSTRING::RAW_encode(const TTCN_Typedescriptor_t
& p_td
,
1144 RAW_enc_tree
& myleaf
) const
1147 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1148 "Encoding an unbound value.");
1151 int bl
= val_ptr
->n_octets
* 8;
1152 int align_length
= p_td
.raw
->fieldlength
? p_td
.raw
->fieldlength
- bl
: 0;
1153 int blength
= val_ptr
->n_octets
;
1154 if ((bl
+ align_length
) < val_ptr
->n_octets
* 8) {
1155 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1156 "There are insufficient bits to encode '%s': ", p_td
.name
);
1157 blength
= p_td
.raw
->fieldlength
/ 8;
1158 bl
= p_td
.raw
->fieldlength
;
1161 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1162 myleaf
.must_free
= false;
1163 myleaf
.data_ptr_used
= true;
1164 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
1165 && myleaf
.coding_par
.bitorder
== ORDER_MSB
) {
1166 if (blength
> RAW_INT_ENC_LENGTH
) {
1167 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(blength
*sizeof(*bc
));
1168 myleaf
.must_free
= true;
1169 myleaf
.data_ptr_used
= true;
1172 bc
= myleaf
.body
.leaf
.data_array
;
1173 myleaf
.data_ptr_used
= false;
1175 for (int a
= 0; a
< blength
; a
++) bc
[a
] = val_ptr
->octets_ptr
[a
] << 1;
1177 else myleaf
.body
.leaf
.data_ptr
= val_ptr
->octets_ptr
;
1178 if (p_td
.raw
->endianness
== ORDER_MSB
) myleaf
.align
= -align_length
;
1179 else myleaf
.align
= align_length
;
1180 return myleaf
.length
= bl
+ align_length
;
1183 int OCTETSTRING::RAW_decode(const TTCN_Typedescriptor_t
& p_td
,
1184 TTCN_Buffer
& buff
, int limit
, raw_order_t top_bit_ord
, boolean no_err
,
1185 int /*sel_field*/, boolean
/*first_call*/)
1187 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1188 limit
-= prepaddlength
;
1189 int decode_length
= p_td
.raw
->fieldlength
== 0
1190 ? (limit
/ 8) * 8 : p_td
.raw
->fieldlength
;
1191 if (decode_length
> limit
|| decode_length
> (int) buff
.unread_len_bit()) {
1192 if (no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
1193 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1194 "There is not enough bits in the buffer to decode type %s.", p_td
.name
);
1195 decode_length
= ((limit
> (int) buff
.unread_len_bit()
1196 ? (int)buff
.unread_len_bit() : limit
) / 8) * 8;
1199 bool orders
= false;
1200 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= true;
1201 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1202 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1204 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= true;
1205 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1206 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1207 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1208 cp
.hexorder
= ORDER_LSB
;
1209 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
) {
1210 const unsigned char* data
= buff
.get_read_data();
1212 int rot
= top_bit_ord
== ORDER_LSB
? 0 : 7;
1213 if (p_td
.raw
->extension_bit
== EXT_BIT_YES
) {
1214 while (((data
[count
- 1] >> rot
) & 0x01) == 0 && count
* 8 < decode_length
)
1218 while (((data
[count
- 1] >> rot
) & 0x01) == 1 && count
* 8 < decode_length
)
1221 decode_length
= count
* 8;
1224 init_struct(decode_length
/ 8);
1225 buff
.get_b((size_t) decode_length
, val_ptr
->octets_ptr
, cp
, top_bit_ord
);
1227 if (p_td
.raw
->length_restrition
!= -1) {
1228 val_ptr
->n_octets
= p_td
.raw
->length_restrition
;
1229 if (p_td
.raw
->endianness
== ORDER_MSB
) memmove(val_ptr
->octets_ptr
,
1230 val_ptr
->octets_ptr
+ (decode_length
/ 8 - val_ptr
->n_octets
),
1231 val_ptr
->n_octets
* sizeof(unsigned char));
1233 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
&& cp
.bitorder
== ORDER_MSB
) {
1234 for (int a
= 0; a
< decode_length
/ 8; a
++)
1235 val_ptr
->octets_ptr
[a
] = val_ptr
->octets_ptr
[a
] >> 1 | val_ptr
->octets_ptr
[a
] << 7;
1237 decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1238 return decode_length
+ prepaddlength
;
1241 void OCTETSTRING::dump () const
1243 if (val_ptr
!= NULL
) {
1244 printf("octetstring(%d) :\n", val_ptr
->n_octets
);
1245 for (int i
= 0; i
< val_ptr
->n_octets
; i
++) {
1246 printf("%02X ", val_ptr
->octets_ptr
[i
]);
1252 int OCTETSTRING::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1255 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1256 "Encoding an unbound octetstring value.");
1260 char* tmp_str
= (char*)Malloc(val_ptr
->n_octets
* 2 + 3);
1262 tmp_str
[val_ptr
->n_octets
* 2 + 1] = '\"';
1263 for(int i
= 0; i
< val_ptr
->n_octets
; ++i
) {
1264 tmp_str
[2 * i
+ 1] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] >> 4);
1265 tmp_str
[2 * i
+ 2] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] & 0x0F);
1267 tmp_str
[val_ptr
->n_octets
* 2 + 2] = 0;
1268 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
1273 int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1275 json_token_t token
= JSON_TOKEN_NONE
;
1277 size_t value_len
= 0;
1278 boolean error
= false;
1280 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1282 // No JSON data in the buffer -> use default value
1283 value
= (char*)p_td
.json
->default_value
;
1284 value_len
= strlen(value
);
1286 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1288 if (JSON_TOKEN_ERROR
== token
) {
1289 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1290 return JSON_ERROR_FATAL
;
1292 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
1293 if (0 == value_len
% 2 && (use_default
||
1294 (value_len
> 2 && value
[0] == '\"' && value
[value_len
- 1] == '\"'))) {
1296 // The default value doesn't have quotes around it
1300 size_t octets
= value_len
/ 2;
1301 init_struct(octets
);
1302 for (size_t i
= 0; i
< octets
; ++i
) {
1303 unsigned char upper_nibble
= char_to_hexdigit(value
[2 * i
]);
1304 unsigned char lower_nibble
= char_to_hexdigit(value
[2 * i
+ 1]);
1305 if (upper_nibble
<= 0x0F && lower_nibble
<= 0x0F) {
1306 val_ptr
->octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
1315 return JSON_ERROR_INVALID_TOKEN
;
1319 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "octetstring");
1323 return JSON_ERROR_FATAL
;
1328 // octetstring element class
1330 OCTETSTRING_ELEMENT::OCTETSTRING_ELEMENT(boolean par_bound_flag
,
1331 OCTETSTRING
& par_str_val
, int par_octet_pos
)
1332 : bound_flag(par_bound_flag
), str_val(par_str_val
), octet_pos(par_octet_pos
)
1336 OCTETSTRING_ELEMENT
& OCTETSTRING_ELEMENT::operator=
1337 (const OCTETSTRING
& other_value
)
1339 other_value
.must_bound("Assignment of an unbound octetstring value.");
1340 if(other_value
.val_ptr
->n_octets
!= 1)
1341 TTCN_error("Assignment of an octetstring "
1342 "with length other than 1 to an octetstring element.");
1344 str_val
.copy_value();
1345 str_val
.val_ptr
->octets_ptr
[octet_pos
] = other_value
.val_ptr
->octets_ptr
[0];
1349 OCTETSTRING_ELEMENT
& OCTETSTRING_ELEMENT::operator=
1350 (const OCTETSTRING_ELEMENT
& other_value
)
1352 other_value
.must_bound("Assignment of an unbound octetstring element.");
1353 if (&other_value
!= this) {
1355 str_val
.copy_value();
1356 str_val
.val_ptr
->octets_ptr
[octet_pos
] =
1357 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1362 boolean
OCTETSTRING_ELEMENT::operator==(const OCTETSTRING
& other_value
) const
1364 must_bound("Unbound left operand of octetstring element comparison.");
1365 other_value
.must_bound("Unbound right operand of octetstring comparison.");
1366 if(other_value
.val_ptr
->n_octets
!= 1) return FALSE
;
1367 return str_val
.val_ptr
->octets_ptr
[octet_pos
] ==
1368 other_value
.val_ptr
->octets_ptr
[0];
1371 boolean
OCTETSTRING_ELEMENT::operator==
1372 (const OCTETSTRING_ELEMENT
& other_value
) const
1374 must_bound("Unbound left operand of octetstring element comparison.");
1375 other_value
.must_bound("Unbound right operand of octetstring element "
1377 return str_val
.val_ptr
->octets_ptr
[octet_pos
] ==
1378 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1381 OCTETSTRING
OCTETSTRING_ELEMENT::operator+(const OCTETSTRING
& other_value
) const
1383 must_bound("Unbound left operand of octetstring element concatenation.");
1384 other_value
.must_bound("Unbound right operand of octetstring concatenation.");
1385 OCTETSTRING
ret_val(other_value
.val_ptr
->n_octets
+ 1);
1386 ret_val
.val_ptr
->octets_ptr
[0] = str_val
.val_ptr
->octets_ptr
[octet_pos
];
1387 memcpy(ret_val
.val_ptr
->octets_ptr
+ 1,
1388 other_value
.val_ptr
->octets_ptr
, other_value
.val_ptr
->n_octets
);
1392 OCTETSTRING
OCTETSTRING_ELEMENT::operator+
1393 (const OCTETSTRING_ELEMENT
& other_value
) const
1395 must_bound("Unbound left operand of octetstring element concatenation.");
1396 other_value
.must_bound("Unbound right operand of octetstring element "
1398 unsigned char result
[2];
1399 result
[0] = str_val
.val_ptr
->octets_ptr
[octet_pos
];
1400 result
[1] = other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1401 return OCTETSTRING(2, result
);
1404 OCTETSTRING
OCTETSTRING_ELEMENT::operator~() const
1406 must_bound("Unbound octetstring element operand of operator not4b.");
1407 unsigned char result
= ~str_val
.val_ptr
->octets_ptr
[octet_pos
];
1408 return OCTETSTRING(1, &result
);
1411 OCTETSTRING
OCTETSTRING_ELEMENT::operator&(const OCTETSTRING
& other_value
) const
1413 must_bound("Left operand of operator and4b is an unbound octetstring "
1415 other_value
.must_bound("Right operand of operator and4b is an unbound "
1416 "octetstring value.");
1417 if (other_value
.val_ptr
->n_octets
!= 1)
1418 TTCN_error("The octetstring "
1419 "operands of operator and4b must have the same length.");
1420 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] &
1421 other_value
.val_ptr
->octets_ptr
[0];
1422 return OCTETSTRING(1, &result
);
1425 OCTETSTRING
OCTETSTRING_ELEMENT::operator&
1426 (const OCTETSTRING_ELEMENT
& other_value
) const
1428 must_bound("Left operand of operator and4b is an unbound octetstring "
1430 other_value
.must_bound("Right operand of operator and4b is an unbound "
1431 "octetstring element.");
1432 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] &
1433 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1434 return OCTETSTRING(1, &result
);
1437 OCTETSTRING
OCTETSTRING_ELEMENT::operator|(const OCTETSTRING
& other_value
) const
1439 must_bound("Left operand of operator or4b is an unbound octetstring "
1441 other_value
.must_bound("Right operand of operator or4b is an unbound "
1442 "octetstring value.");
1443 if (other_value
.val_ptr
->n_octets
!= 1)
1444 TTCN_error("The octetstring "
1445 "operands of operator or4b must have the same length.");
1446 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] |
1447 other_value
.val_ptr
->octets_ptr
[0];
1448 return OCTETSTRING(1, &result
);
1451 OCTETSTRING
OCTETSTRING_ELEMENT::operator|
1452 (const OCTETSTRING_ELEMENT
& other_value
) const
1454 must_bound("Left operand of operator or4b is an unbound octetstring "
1456 other_value
.must_bound("Right operand of operator or4b is an unbound "
1457 "octetstring element.");
1458 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] |
1459 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1460 return OCTETSTRING(1, &result
);
1463 OCTETSTRING
OCTETSTRING_ELEMENT::operator^(const OCTETSTRING
& other_value
) const
1465 must_bound("Left operand of operator xor4b is an unbound octetstring "
1467 other_value
.must_bound("Right operand of operator xor4b is an unbound "
1468 "octetstring value.");
1469 if (other_value
.val_ptr
->n_octets
!= 1)
1470 TTCN_error("The octetstring "
1471 "operands of operator xor4b must have the same length.");
1472 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] ^
1473 other_value
.val_ptr
->octets_ptr
[0];
1474 return OCTETSTRING(1, &result
);
1477 OCTETSTRING
OCTETSTRING_ELEMENT::operator^
1478 (const OCTETSTRING_ELEMENT
& other_value
) const
1480 must_bound("Left operand of operator xor4b is an unbound octetstring "
1482 other_value
.must_bound("Right operand of operator xor4b is an unbound "
1483 "octetstring element.");
1484 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] ^
1485 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1486 return OCTETSTRING(1, &result
);
1489 unsigned char OCTETSTRING_ELEMENT::get_octet() const
1491 return str_val
.val_ptr
->octets_ptr
[octet_pos
];
1494 void OCTETSTRING_ELEMENT::log() const
1497 unsigned char octet
= str_val
.val_ptr
->octets_ptr
[octet_pos
];
1498 TTCN_Logger::log_char('\'');
1499 TTCN_Logger::log_octet(octet
);
1500 TTCN_Logger::log_event_str("'O");
1501 if (TTCN_Logger::is_printable(octet
)) {
1502 TTCN_Logger::log_event_str(" (\"");
1503 TTCN_Logger::log_char_escaped(octet
);
1504 TTCN_Logger::log_event_str("\")");
1506 } else TTCN_Logger::log_event_unbound();
1509 // octetstring template class
1511 void OCTETSTRING_template::clean_up()
1513 switch (template_selection
) {
1515 case COMPLEMENTED_LIST
:
1516 delete [] value_list
.list_value
;
1518 case STRING_PATTERN
:
1519 if (pattern_value
->ref_count
> 1) pattern_value
->ref_count
--;
1520 else if (pattern_value
->ref_count
== 1) Free(pattern_value
);
1521 else TTCN_error("Internal error: Invalid reference counter in an "
1522 "octetstring pattern.");
1527 template_selection
= UNINITIALIZED_TEMPLATE
;
1530 void OCTETSTRING_template::copy_template
1531 (const OCTETSTRING_template
& other_value
)
1533 switch (other_value
.template_selection
) {
1534 case SPECIFIC_VALUE
:
1535 single_value
= other_value
.single_value
;
1542 case COMPLEMENTED_LIST
:
1543 value_list
.n_values
= other_value
.value_list
.n_values
;
1544 value_list
.list_value
= new OCTETSTRING_template
[value_list
.n_values
];
1545 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1546 value_list
.list_value
[i
].copy_template(
1547 other_value
.value_list
.list_value
[i
]);
1549 case STRING_PATTERN
:
1550 pattern_value
= other_value
.pattern_value
;
1551 pattern_value
->ref_count
++;
1554 TTCN_error("Copying an uninitialized/unsupported octetstring template.");
1556 set_selection(other_value
);
1560 This is the same algorithm that match_array uses
1561 to match 'record of' types.
1562 The only differences are: how two elements are matched and
1563 how an asterisk or ? is identified in the template
1565 boolean
OCTETSTRING_template::match_pattern(
1566 const octetstring_pattern_struct
*string_pattern
,
1567 const OCTETSTRING::octetstring_struct
*string_value
)
1569 // the empty pattern matches the empty octetstring only
1570 if (string_pattern
->n_elements
== 0) return string_value
->n_octets
== 0;
1572 int value_index
= 0;
1573 unsigned int template_index
= 0;
1574 int last_asterisk
= -1;
1575 int last_value_to_asterisk
= -1;
1576 //this variable is used to speed up the function
1577 unsigned short pattern_element
;
1581 pattern_element
= string_pattern
->elements_ptr
[template_index
];
1582 if( pattern_element
< 256){
1583 if(string_value
->octets_ptr
[value_index
] == pattern_element
)
1588 if(last_asterisk
== -1) return FALSE
;
1589 template_index
= last_asterisk
+1;
1590 value_index
= ++last_value_to_asterisk
;
1592 } else if(pattern_element
== 256)
1596 }else if(pattern_element
== 257)
1598 last_asterisk
= template_index
++;
1599 last_value_to_asterisk
= value_index
;
1600 } else TTCN_error("Internal error: invalid element in an octetstring "
1603 if(value_index
== string_value
->n_octets
1604 && template_index
== string_pattern
->n_elements
)
1607 }else if (template_index
== string_pattern
->n_elements
)
1609 if(string_pattern
->elements_ptr
[template_index
- 1] == 257)
1612 }else if(last_asterisk
== -1)
1616 template_index
= last_asterisk
+1;
1617 value_index
= ++last_value_to_asterisk
;
1619 }else if(value_index
== string_value
->n_octets
)
1621 while(template_index
< string_pattern
->n_elements
1622 && string_pattern
->elements_ptr
[template_index
] == 257)
1625 return template_index
== string_pattern
->n_elements
;
1630 OCTETSTRING_template::OCTETSTRING_template()
1634 OCTETSTRING_template::OCTETSTRING_template(template_sel other_value
)
1635 : Restricted_Length_Template(other_value
)
1637 check_single_selection(other_value
);
1640 OCTETSTRING_template::OCTETSTRING_template(const OCTETSTRING
& other_value
)
1641 : Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1645 OCTETSTRING_template::OCTETSTRING_template
1646 (const OCTETSTRING_ELEMENT
& other_value
)
1647 : Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1651 OCTETSTRING_template::OCTETSTRING_template
1652 (const OPTIONAL
<OCTETSTRING
>& other_value
)
1654 switch (other_value
.get_selection()) {
1655 case OPTIONAL_PRESENT
:
1656 set_selection(SPECIFIC_VALUE
);
1657 single_value
= (const OCTETSTRING
&)other_value
;
1660 set_selection(OMIT_VALUE
);
1663 TTCN_error("Creating an octetstring template from an unbound optional "
1668 OCTETSTRING_template::OCTETSTRING_template(unsigned int n_elements
,
1669 const unsigned short *pattern_elements
)
1670 : Restricted_Length_Template(STRING_PATTERN
)
1672 pattern_value
= (octetstring_pattern_struct
*)
1673 Malloc(sizeof(octetstring_pattern_struct
) +
1674 (n_elements
- 1) * sizeof(unsigned short));
1675 pattern_value
->ref_count
= 1;
1676 pattern_value
->n_elements
= n_elements
;
1677 memcpy(pattern_value
->elements_ptr
, pattern_elements
,
1678 n_elements
* sizeof(unsigned short));
1681 OCTETSTRING_template::OCTETSTRING_template
1682 (const OCTETSTRING_template
& other_value
)
1683 : Restricted_Length_Template()
1685 copy_template(other_value
);
1688 OCTETSTRING_template::~OCTETSTRING_template()
1693 OCTETSTRING_template
& OCTETSTRING_template::operator=(template_sel other_value
)
1695 check_single_selection(other_value
);
1697 set_selection(other_value
);
1701 OCTETSTRING_template
& OCTETSTRING_template::operator=
1702 (const OCTETSTRING
& other_value
)
1704 other_value
.must_bound("Assignment of an unbound octetstring value to a "
1707 set_selection(SPECIFIC_VALUE
);
1708 single_value
= other_value
;
1712 OCTETSTRING_template
& OCTETSTRING_template::operator=
1713 (const OCTETSTRING_ELEMENT
& other_value
)
1715 other_value
.must_bound("Assignment of an unbound octetstring element to a "
1718 set_selection(SPECIFIC_VALUE
);
1719 single_value
= other_value
;
1723 OCTETSTRING_template
& OCTETSTRING_template::operator=
1724 (const OPTIONAL
<OCTETSTRING
>& other_value
)
1727 switch (other_value
.get_selection()) {
1728 case OPTIONAL_PRESENT
:
1729 set_selection(SPECIFIC_VALUE
);
1730 single_value
= (const OCTETSTRING
&)other_value
;
1733 set_selection(OMIT_VALUE
);
1736 TTCN_error("Assignment of an unbound optional field to an octetstring "
1742 OCTETSTRING_template
& OCTETSTRING_template::operator=
1743 (const OCTETSTRING_template
& other_value
)
1745 if (&other_value
!= this) {
1747 copy_template(other_value
);
1752 OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](int index_value
)
1754 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1755 TTCN_error("Accessing an octetstring element of a non-specific "
1756 "octetstring template.");
1757 return single_value
[index_value
];
1760 OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](const INTEGER
& index_value
)
1762 index_value
.must_bound("Indexing a octetstring value with an unbound "
1764 return (*this)[(int)index_value
];
1767 const OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](int index_value
) const
1769 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1770 TTCN_error("Accessing an octetstring element of a non-specific "
1771 "octetstring template.");
1772 return single_value
[index_value
];
1775 const OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](const INTEGER
& index_value
) const
1777 index_value
.must_bound("Indexing a octetstring template with an unbound "
1779 return (*this)[(int)index_value
];
1782 boolean
OCTETSTRING_template::match(const OCTETSTRING
& other_value
,
1783 boolean
/* legacy */) const
1785 if (!other_value
.is_bound()) return FALSE
;
1786 if (!match_length(other_value
.val_ptr
->n_octets
)) return FALSE
;
1787 switch (template_selection
) {
1788 case SPECIFIC_VALUE
:
1789 return single_value
== other_value
;
1796 case COMPLEMENTED_LIST
:
1797 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1798 if (value_list
.list_value
[i
].match(other_value
))
1799 return template_selection
== VALUE_LIST
;
1800 return template_selection
== COMPLEMENTED_LIST
;
1801 case STRING_PATTERN
:
1802 return match_pattern(pattern_value
, other_value
.val_ptr
);
1804 TTCN_error("Matching an uninitialized/unsupported octetstring template.");
1809 const OCTETSTRING
& OCTETSTRING_template::valueof() const
1811 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1812 TTCN_error("Performing a valueof or send operation on a non-specific "
1813 "octetstring template.");
1814 return single_value
;
1817 int OCTETSTRING_template::lengthof() const
1820 boolean has_any_or_none
;
1822 TTCN_error("Performing lengthof() operation on a octetstring template "
1823 "which has an ifpresent attribute.");
1824 switch (template_selection
)
1826 case SPECIFIC_VALUE
:
1827 min_length
= single_value
.lengthof();
1828 has_any_or_none
= FALSE
;
1831 TTCN_error("Performing lengthof() operation on an octetstring template "
1832 "containing omit value.");
1836 has_any_or_none
= TRUE
; // max. length is infinity
1840 // error if any element does not have length or the lengths differ
1841 if (value_list
.n_values
<1)
1842 TTCN_error("Internal error: "
1843 "Performing lengthof() operation on an octetstring template "
1844 "containing an empty list.");
1845 int item_length
= value_list
.list_value
[0].lengthof();
1846 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
1847 if (value_list
.list_value
[i
].lengthof()!=item_length
)
1848 TTCN_error("Performing lengthof() operation on an octetstring template "
1849 "containing a value list with different lengths.");
1851 min_length
= item_length
;
1852 has_any_or_none
= FALSE
;
1855 case COMPLEMENTED_LIST
:
1856 TTCN_error("Performing lengthof() operation on an octetstring template "
1857 "containing complemented list.");
1858 case STRING_PATTERN
:
1860 has_any_or_none
= FALSE
; // TRUE if * chars in the pattern
1861 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++)
1863 if (pattern_value
->elements_ptr
[i
] < 257) min_length
++;
1864 else has_any_or_none
= TRUE
; // case of * character
1868 TTCN_error("Performing lengthof() operation on an "
1869 "uninitialized/unsupported octetstring template.");
1871 return check_section_is_single(min_length
, has_any_or_none
,
1872 "length", "an", "octetstring template");
1875 void OCTETSTRING_template::set_type(template_sel template_type
,
1876 unsigned int list_length
)
1878 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
1879 TTCN_error("Setting an invalid list type for an octetstring template.");
1881 set_selection(template_type
);
1882 value_list
.n_values
= list_length
;
1883 value_list
.list_value
= new OCTETSTRING_template
[list_length
];
1886 OCTETSTRING_template
& OCTETSTRING_template::list_item(unsigned int list_index
)
1888 if (template_selection
!= VALUE_LIST
&&
1889 template_selection
!= COMPLEMENTED_LIST
)
1890 TTCN_error("Accessing a list element of a non-list octetstring template.");
1891 if (list_index
>= value_list
.n_values
)
1892 TTCN_error("Index overflow in an octetstring value list template.");
1893 return value_list
.list_value
[list_index
];
1896 void OCTETSTRING_template::log() const
1898 switch (template_selection
) {
1899 case SPECIFIC_VALUE
:
1902 case COMPLEMENTED_LIST
:
1903 TTCN_Logger::log_event_str("complement ");
1906 TTCN_Logger::log_char('(');
1907 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
1908 if (i
> 0) TTCN_Logger::log_event_str(", ");
1909 value_list
.list_value
[i
].log();
1911 TTCN_Logger::log_char(')');
1913 case STRING_PATTERN
:
1914 TTCN_Logger::log_char('\'');
1915 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++) {
1916 unsigned short pattern
= pattern_value
->elements_ptr
[i
];
1917 if (pattern
< 256) TTCN_Logger::log_octet(pattern
);
1918 else if (pattern
== 256) TTCN_Logger::log_char('?');
1919 else if (pattern
== 257) TTCN_Logger::log_char('*');
1920 else TTCN_Logger::log_event_str("<unknown>");
1922 TTCN_Logger::log_event_str("'O");
1932 void OCTETSTRING_template::log_match(const OCTETSTRING
& match_value
,
1933 boolean
/* legacy */) const
1935 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
1936 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1937 TTCN_Logger::print_logmatch_buffer();
1938 TTCN_Logger::log_event_str(" := ");
1941 TTCN_Logger::log_event_str(" with ");
1943 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
1944 else TTCN_Logger::log_event_str(" unmatched");
1947 void OCTETSTRING_template::set_param(Module_Param
& param
) {
1948 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "octetstring template");
1949 Module_Param_Ptr mp
= ¶m
;
1950 if (param
.get_type() == Module_Param::MP_Reference
) {
1951 mp
= param
.get_referenced_param();
1953 switch (mp
->get_type()) {
1954 case Module_Param::MP_Omit
:
1957 case Module_Param::MP_Any
:
1960 case Module_Param::MP_AnyOrNone
:
1961 *this = ANY_OR_OMIT
;
1963 case Module_Param::MP_List_Template
:
1964 case Module_Param::MP_ComplementList_Template
: {
1965 OCTETSTRING_template temp
;
1966 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
1967 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
1968 for (size_t i
=0; i
<mp
->get_size(); i
++) {
1969 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
1973 case Module_Param::MP_Octetstring
:
1974 *this = OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
1976 case Module_Param::MP_Octetstring_Template
:
1977 *this = OCTETSTRING_template(mp
->get_string_size(), (unsigned short*)mp
->get_string_data());
1979 case Module_Param::MP_Expression
:
1980 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
1981 OCTETSTRING operand1
, operand2
;
1982 operand1
.set_param(*mp
->get_operand1());
1983 operand2
.set_param(*mp
->get_operand2());
1984 *this = operand1
+ operand2
;
1987 param
.expr_type_error("a bitstring");
1991 param
.type_error("octetstring template");
1993 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
1994 if (param
.get_length_restriction() != NULL
) {
1995 set_length_range(param
);
1998 set_length_range(*mp
);
2002 Module_Param
* OCTETSTRING_template::get_param(Module_Param_Name
& param_name
) const
2004 Module_Param
* mp
= NULL
;
2005 switch (template_selection
) {
2006 case UNINITIALIZED_TEMPLATE
:
2007 mp
= new Module_Param_Unbound();
2010 mp
= new Module_Param_Omit();
2013 mp
= new Module_Param_Any();
2016 mp
= new Module_Param_AnyOrNone();
2018 case SPECIFIC_VALUE
:
2019 mp
= single_value
.get_param(param_name
);
2022 case COMPLEMENTED_LIST
: {
2023 if (template_selection
== VALUE_LIST
) {
2024 mp
= new Module_Param_List_Template();
2027 mp
= new Module_Param_ComplementList_Template();
2029 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
2030 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
2033 case STRING_PATTERN
: {
2034 unsigned short* val_cpy
= (unsigned short*)Malloc(pattern_value
->n_elements
*
2035 sizeof(unsigned short));
2036 memcpy(val_cpy
, pattern_value
->elements_ptr
, pattern_value
->n_elements
*
2037 sizeof(unsigned short));
2038 mp
= new Module_Param_Octetstring_Template(pattern_value
->n_elements
, val_cpy
);
2044 mp
->set_ifpresent();
2046 mp
->set_length_restriction(get_length_range());
2050 void OCTETSTRING_template::encode_text(Text_Buf
& text_buf
) const
2052 encode_text_restricted(text_buf
);
2053 switch (template_selection
) {
2058 case SPECIFIC_VALUE
:
2059 single_value
.encode_text(text_buf
);
2062 case COMPLEMENTED_LIST
:
2063 text_buf
.push_int(value_list
.n_values
);
2064 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2065 value_list
.list_value
[i
].encode_text(text_buf
);
2067 case STRING_PATTERN
:
2068 text_buf
.push_int(pattern_value
->n_elements
);
2069 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++)
2070 text_buf
.push_int(pattern_value
->elements_ptr
[i
]);
2073 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2074 "octetstring template.");
2078 void OCTETSTRING_template::decode_text(Text_Buf
& text_buf
)
2081 decode_text_restricted(text_buf
);
2082 switch (template_selection
) {
2087 case SPECIFIC_VALUE
:
2088 single_value
.decode_text(text_buf
);
2091 case COMPLEMENTED_LIST
:
2092 value_list
.n_values
= text_buf
.pull_int().get_val();
2093 value_list
.list_value
= new OCTETSTRING_template
[value_list
.n_values
];
2094 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2095 value_list
.list_value
[i
].decode_text(text_buf
);
2097 case STRING_PATTERN
: {
2098 unsigned int n_elements
= text_buf
.pull_int().get_val();
2099 pattern_value
= (octetstring_pattern_struct
*)
2100 Malloc(sizeof(octetstring_pattern_struct
) + (n_elements
- 1) *
2101 sizeof(unsigned short));
2102 pattern_value
->ref_count
= 1;
2103 pattern_value
->n_elements
= n_elements
;
2104 for (unsigned int i
= 0; i
< n_elements
; i
++)
2105 pattern_value
->elements_ptr
[i
] = text_buf
.pull_int().get_val();
2108 TTCN_error("Text decoder: An unknown/unsupported selection was "
2109 "received for an octetstring template.");
2113 boolean
OCTETSTRING_template::is_present(boolean legacy
/* = FALSE */) const
2115 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2116 return !match_omit(legacy
);
2119 boolean
OCTETSTRING_template::match_omit(boolean legacy
/* = FALSE */) const
2121 if (is_ifpresent
) return TRUE
;
2122 switch (template_selection
) {
2127 case COMPLEMENTED_LIST
:
2129 // legacy behavior: 'omit' can appear in the value/complement list
2130 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2131 if (value_list
.list_value
[i
].match_omit())
2132 return template_selection
==VALUE_LIST
;
2133 return template_selection
==COMPLEMENTED_LIST
;
2135 // else fall through
2142 #ifndef TITAN_RUNTIME_2
2143 void OCTETSTRING_template::check_restriction(template_res t_res
, const char* t_name
,
2144 boolean legacy
/* = FALSE */) const
2146 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2147 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2149 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2152 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2153 template_selection
==SPECIFIC_VALUE
)) return;
2156 if (!match_omit(legacy
)) return;
2161 TTCN_error("Restriction `%s' on template of type %s violated.",
2162 get_res_name(t_res
), t_name
? t_name
: "octetstring");