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;
757 boolean
OCTETSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
758 const ASN_BER_TLV_t
& p_tlv
,
763 ASN_BER_TLV_t stripped_tlv
;
764 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
765 TTCN_EncDec_ErrorContext
ec("While decoding OCTETSTRING type: ");
766 /* Upper estimation for the length. */
767 size_t stripped_tlv_len
= stripped_tlv
.get_len();
768 if (stripped_tlv_len
< 2) return FALSE
;
769 int max_len
= stripped_tlv_len
- 2;
770 init_struct(max_len
);
771 unsigned int octetnum_start
= 0;
772 BER_decode_TLV_OCTETSTRING(stripped_tlv
, L_form
, octetnum_start
,
773 val_ptr
->n_octets
, val_ptr
->octets_ptr
);
774 if (val_ptr
->n_octets
< max_len
) {
775 if (val_ptr
->n_octets
== 0) {
779 val_ptr
= (octetstring_struct
*)
780 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
));
786 int OCTETSTRING::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
787 TTCN_Buffer
& buff
, Limit_Token_List
& limit
,
788 boolean no_err
, boolean
/*first_call*/)
790 int decoded_length
=0;
793 if(p_td
.text
->begin_decode
){
795 if((tl
=p_td
.text
->begin_decode
->match_begin(buff
))<0){
797 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
798 "The specified token '%s' not found for '%s': ",
799 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
803 buff
.increase_pos(tl
);
805 // never returns "too short"
806 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
808 if(p_td
.text
->select_token
){
810 if((tl
=p_td
.text
->select_token
->match_begin(buff
))<0) {
811 if(no_err
) return -1;
816 if( p_td
.text
->val
.parameters
817 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!=-1){
818 str_len
=p_td
.text
->val
.parameters
->decoding_params
.min_length
*2;
819 } else if(p_td
.text
->end_decode
){
821 if((tl
=p_td
.text
->end_decode
->match_first(buff
))<0) {
822 if(no_err
) return -1;
826 } else if (limit
.has_token()){
828 if((tl
=limit
.match(buff
))<0)
829 tl
=buff
.get_read_len()-1;;
833 if((tl
=octetstring_value_match
.match_begin(buff
))<0) {
834 if(no_err
) {return -1; }
839 str_len
=(str_len
/2)*2;
840 //printf("HALI chr:%d ",str_len);
841 int n_octets
= str_len
/ 2;
842 init_struct(n_octets
);
843 unsigned char *octets_ptr
= val_ptr
->octets_ptr
;
844 const char *value
=(const char*)buff
.get_read_data();
845 for (int i
= 0; i
< n_octets
; i
++) {
846 unsigned char upper_nibble
= char_to_hexdigit(value
[2 * i
]);
847 unsigned char lower_nibble
= char_to_hexdigit(value
[2 * i
+ 1]);
848 if (upper_nibble
> 0x0F){
849 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
850 "The octetstring value may contain hexadecimal digits only. "
851 "Character \"%c\" was found.", value
[2 * i
]);
854 if (lower_nibble
> 0x0F){
855 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
856 "The octetstring value str2oct() may contain hexadecimal digits only. "
857 "Character \"%c\" was found.", value
[2 * i
+ 1]);
860 octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
863 //printf("%s\n\r",val_ptr->chars_ptr);
864 decoded_length
+=str_len
;
865 buff
.increase_pos(str_len
);
867 if(p_td
.text
->end_decode
){
869 if((tl
=p_td
.text
->end_decode
->match_begin(buff
))<0){
871 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
872 "The specified token '%s' not found for '%s': ",
873 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
877 buff
.increase_pos(tl
);
879 return decoded_length
;
882 // From Charstring.cc
883 extern char base64_decoder_table
[256];
884 extern unsigned int xlate(cbyte
* in
, int phase
, unsigned char* dest
);
885 extern const char cb64
[];
887 int OCTETSTRING::XER_encode(const XERdescriptor_t
& p_td
,
888 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
891 TTCN_EncDec_ErrorContext::error
892 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound octetstring value.");
894 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
895 // SIMPLE_TYPE has no influence on is_exer, we set it for later
896 int encoded_length
=(int)p_buf
.get_len();
897 int empty_element
= val_ptr
==NULL
|| val_ptr
->n_octets
== 0;
899 flavor
&= ~XER_RECOF
; // octetstring doesn't care
900 begin_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
902 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
904 size_t clear_len
= lengthof();
905 const unsigned char * in
= operator const unsigned char*();
907 /* Encode 3 bytes of cleartext into 4 bytes of Base64.
908 * Note that the algorithm is slightly different from Charstring.cc:
909 * we can't pad the source because it's const (this),
910 * so we need to check the indexes i+1 and i+2 before dereferencing */
911 for (size_t i
= 0; i
< clear_len
; i
+= 3) {
912 p_buf
.put_c( cb64
[ in
[i
] >> 2 ] );
913 p_buf
.put_c( cb64
[ ((in
[i
] & 0x03) << 4) | (i
+1 < clear_len
914 ? ((in
[i
+1] & 0xf0) >> 4)
916 p_buf
.put_c( i
+1 < clear_len
917 ? cb64
[ ((in
[i
+1] & 0x0f) << 2) | (i
+2 < clear_len
? ((in
[i
+2] & 0xc0) >> 6) :-0) ]
919 p_buf
.put_c( i
+2 < clear_len
? cb64
[ in
[i
+2] & 0x3f ] : '=' );
923 CHARSTRING val
= oct2str(*this);
924 p_buf
.put_string(val
);
927 end_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
929 return (int)p_buf
.get_len() - encoded_length
;
932 int OCTETSTRING::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
933 unsigned int flavor
, embed_values_dec_struct_t
*)
935 int exer
= is_exer(flavor
);
936 int success
= reader
.Ok(), depth
= -1, type
;
937 boolean own_tag
= !is_exerlist(flavor
) && !(exer
&& (p_td
.xer_bits
& UNTAGGED
));
939 const char * value
= 0;
940 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
941 const char * name
= verify_name(reader
, p_td
, exer
);
945 if (own_tag
) for (; success
== 1; success
= reader
.Read()) {
946 type
= reader
.NodeType();
947 if (XML_READER_TYPE_ELEMENT
== type
) {
948 verify_name(reader
, p_td
, exer
);
949 depth
= reader
.Depth();
950 if (reader
.IsEmptyElement()) {
951 if (exer
&& p_td
.dfeValue
!= 0) {
952 *this = *static_cast<const OCTETSTRING
*> (p_td
.dfeValue
);
959 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) break;
960 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
961 // End tag without intervening #text == empty content
962 verify_end(reader
, p_td
, depth
, exer
);
963 if (exer
&& p_td
.dfeValue
!= 0) {
964 *this = *static_cast<const OCTETSTRING
*>(p_td
.dfeValue
);
972 type
= reader
.NodeType();
973 if (success
== 1 && (XML_READER_TYPE_TEXT
== type
|| XML_READER_TYPE_ATTRIBUTE
== type
)) {
974 value
= (const char *)reader
.Value();
975 size_t len
= value
? strlen(value
) : 0;
977 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
981 init_struct(len
* 3 / 4);
982 unsigned char * dest
= val_ptr
->octets_ptr
;
984 for (size_t o
=0; o
<len
; ++o
) {
985 xmlChar c
= value
[o
];
986 if(c
== '=') { // padding starts
987 dest
+= xlate(in
, phase
, dest
);
991 int val
= base64_decoder_table
[c
];
994 phase
= (phase
+ 1) % 4;
996 dest
+= xlate(in
,phase
, dest
);
997 in
[0]=in
[1]=in
[2]=in
[3]=0;
1000 else if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1004 TTCN_EncDec_ErrorContext::warning(
1005 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
1006 "Invalid character for Base64 '%02X'", c
);
1010 val_ptr
->n_octets
= dest
- val_ptr
->octets_ptr
;
1013 else { // not base64
1014 if (len
& 1) { // that's odd...
1015 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1019 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1020 "Odd number of characters in octetstring");
1021 len
&= ~1; // make it even
1024 size_t n_octets
= len
/ 2;
1025 init_struct(n_octets
);
1027 len
= 0; // will act as 2*i
1028 for (size_t i
= 0; i
< n_octets
; ++i
, ++++len
) {
1029 unsigned char upper_nibble
= char_to_hexdigit(value
[len
]);
1030 unsigned char lower_nibble
= char_to_hexdigit(value
[len
+1]);
1031 if (upper_nibble
> 0x0F) {
1032 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1036 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1037 "The octetstring value may contain hexadecimal digits only. "
1038 "Character \"%c\" was found.", value
[len
]);
1042 if (lower_nibble
> 0x0F) {
1043 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1047 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1048 "The octetstring value may contain hexadecimal digits only. "
1049 "Character \"%c\" was found.", value
[len
+1]);
1053 val_ptr
->octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
1058 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1059 // Let the caller do reader.AdvanceAttribute();
1062 if (own_tag
) for (success
= reader
.Read(); success
== 1; success
= reader
.Read()) {
1063 type
= reader
.NodeType();
1064 if (XML_READER_TYPE_END_ELEMENT
== type
) {
1065 verify_end(reader
, p_td
, depth
, exer
);
1066 if (val_ptr
== 0 && p_td
.dfeValue
!= 0) {
1067 // The end tag must have followed the start tag
1068 *this = *static_cast<const OCTETSTRING
*>(p_td
.dfeValue
);
1070 reader
.Read(); // one last time
1075 return 1; // decode successful
1078 int OCTETSTRING::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1079 TTCN_Buffer
& buff
) const{
1080 int encoded_length
=0;
1081 if(p_td
.text
->begin_encode
){
1082 buff
.put_cs(*p_td
.text
->begin_encode
);
1083 encoded_length
+=p_td
.text
->begin_encode
->lengthof();
1086 TTCN_EncDec_ErrorContext::error
1087 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound value.");
1088 if(p_td
.text
->end_encode
){
1089 buff
.put_cs(*p_td
.text
->end_encode
);
1090 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1092 return encoded_length
;
1097 if(p_td
.text
->val
.parameters
){
1098 if(val_ptr
->n_octets
<p_td
.text
->val
.parameters
->coding_params
.min_length
){
1099 chars_before
=(p_td
.text
->
1100 val
.parameters
->coding_params
.min_length
-val_ptr
->n_octets
)*2;
1105 unsigned char* p
=NULL
;
1106 size_t len
=chars_before
;
1107 buff
.get_end(p
,len
);
1108 for(int a
=0;a
<chars_before
;a
++) p
[a
]=(unsigned char)'0';
1109 buff
.increase_length(chars_before
);
1110 encoded_length
+=chars_before
;
1113 if(val_ptr
->n_octets
){
1114 unsigned char* p
=NULL
;
1115 size_t len
=val_ptr
->n_octets
*2;
1116 buff
.get_end(p
,len
);
1117 len
=val_ptr
->n_octets
;
1118 for(size_t i
=0;i
<len
;i
++){
1119 p
[2 * i
] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] >> 4);
1120 p
[2 * i
+ 1] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] & 0x0F);
1122 buff
.increase_length(len
*2);
1123 encoded_length
+=len
*2;
1127 if(p_td
.text
->end_encode
){
1128 buff
.put_cs(*p_td
.text
->end_encode
);
1129 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1131 return encoded_length
;
1134 int OCTETSTRING::RAW_encode(const TTCN_Typedescriptor_t
& p_td
,
1135 RAW_enc_tree
& myleaf
) const
1138 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1139 "Encoding an unbound value.");
1142 int bl
= val_ptr
->n_octets
* 8;
1143 int align_length
= p_td
.raw
->fieldlength
? p_td
.raw
->fieldlength
- bl
: 0;
1144 int blength
= val_ptr
->n_octets
;
1145 if ((bl
+ align_length
) < val_ptr
->n_octets
* 8) {
1146 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1147 "There are insufficient bits to encode '%s': ", p_td
.name
);
1148 blength
= p_td
.raw
->fieldlength
/ 8;
1149 bl
= p_td
.raw
->fieldlength
;
1152 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1153 myleaf
.must_free
= false;
1154 myleaf
.data_ptr_used
= true;
1155 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
1156 && myleaf
.coding_par
.bitorder
== ORDER_MSB
) {
1157 if (blength
> RAW_INT_ENC_LENGTH
) {
1158 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(blength
*sizeof(*bc
));
1159 myleaf
.must_free
= true;
1160 myleaf
.data_ptr_used
= true;
1163 bc
= myleaf
.body
.leaf
.data_array
;
1164 myleaf
.data_ptr_used
= false;
1166 for (int a
= 0; a
< blength
; a
++) bc
[a
] = val_ptr
->octets_ptr
[a
] << 1;
1168 else myleaf
.body
.leaf
.data_ptr
= val_ptr
->octets_ptr
;
1169 if (p_td
.raw
->endianness
== ORDER_MSB
) myleaf
.align
= -align_length
;
1170 else myleaf
.align
= align_length
;
1171 return myleaf
.length
= bl
+ align_length
;
1174 int OCTETSTRING::RAW_decode(const TTCN_Typedescriptor_t
& p_td
,
1175 TTCN_Buffer
& buff
, int limit
, raw_order_t top_bit_ord
, boolean no_err
,
1176 int /*sel_field*/, boolean
/*first_call*/)
1178 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1179 limit
-= prepaddlength
;
1180 int decode_length
= p_td
.raw
->fieldlength
== 0
1181 ? (limit
/ 8) * 8 : p_td
.raw
->fieldlength
;
1182 if (decode_length
> limit
|| decode_length
> (int) buff
.unread_len_bit()) {
1183 if (no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
1184 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1185 "There is not enough bits in the buffer to decode type %s.", p_td
.name
);
1186 decode_length
= ((limit
> (int) buff
.unread_len_bit()
1187 ? (int)buff
.unread_len_bit() : limit
) / 8) * 8;
1190 bool orders
= false;
1191 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= true;
1192 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1193 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1195 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= true;
1196 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1197 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1198 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1199 cp
.hexorder
= ORDER_LSB
;
1200 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
) {
1201 const unsigned char* data
= buff
.get_read_data();
1203 int rot
= top_bit_ord
== ORDER_LSB
? 0 : 7;
1204 if (p_td
.raw
->extension_bit
== EXT_BIT_YES
) {
1205 while (((data
[count
- 1] >> rot
) & 0x01) == 0 && count
* 8 < decode_length
)
1209 while (((data
[count
- 1] >> rot
) & 0x01) == 1 && count
* 8 < decode_length
)
1212 decode_length
= count
* 8;
1215 init_struct(decode_length
/ 8);
1216 buff
.get_b((size_t) decode_length
, val_ptr
->octets_ptr
, cp
, top_bit_ord
);
1218 if (p_td
.raw
->length_restrition
!= -1) {
1219 val_ptr
->n_octets
= p_td
.raw
->length_restrition
;
1220 if (p_td
.raw
->endianness
== ORDER_MSB
) memmove(val_ptr
->octets_ptr
,
1221 val_ptr
->octets_ptr
+ (decode_length
/ 8 - val_ptr
->n_octets
),
1222 val_ptr
->n_octets
* sizeof(unsigned char));
1224 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
&& cp
.bitorder
== ORDER_MSB
) {
1225 for (int a
= 0; a
< decode_length
/ 8; a
++)
1226 val_ptr
->octets_ptr
[a
] = val_ptr
->octets_ptr
[a
] >> 1 | val_ptr
->octets_ptr
[a
] << 7;
1228 decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1229 return decode_length
+ prepaddlength
;
1232 void OCTETSTRING::dump () const
1234 if (val_ptr
!= NULL
) {
1235 printf("octetstring(%d) :\n", val_ptr
->n_octets
);
1236 for (int i
= 0; i
< val_ptr
->n_octets
; i
++) {
1237 printf("%02X ", val_ptr
->octets_ptr
[i
]);
1243 int OCTETSTRING::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1246 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1247 "Encoding an unbound octetstring value.");
1251 char* tmp_str
= (char*)Malloc(val_ptr
->n_octets
* 2 + 3);
1253 tmp_str
[val_ptr
->n_octets
* 2 + 1] = '\"';
1254 for(int i
= 0; i
< val_ptr
->n_octets
; ++i
) {
1255 tmp_str
[2 * i
+ 1] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] >> 4);
1256 tmp_str
[2 * i
+ 2] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] & 0x0F);
1258 tmp_str
[val_ptr
->n_octets
* 2 + 2] = 0;
1259 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
1264 int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1266 json_token_t token
= JSON_TOKEN_NONE
;
1268 size_t value_len
= 0;
1269 boolean error
= false;
1271 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1273 // No JSON data in the buffer -> use default value
1274 value
= (char*)p_td
.json
->default_value
;
1275 value_len
= strlen(value
);
1277 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1279 if (JSON_TOKEN_ERROR
== token
) {
1280 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1281 return JSON_ERROR_FATAL
;
1283 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
1284 if (0 == value_len
% 2 && (use_default
||
1285 (value_len
> 2 && value
[0] == '\"' && value
[value_len
- 1] == '\"'))) {
1287 // The default value doesn't have quotes around it
1291 size_t octets
= value_len
/ 2;
1292 init_struct(octets
);
1293 for (size_t i
= 0; i
< octets
; ++i
) {
1294 unsigned char upper_nibble
= char_to_hexdigit(value
[2 * i
]);
1295 unsigned char lower_nibble
= char_to_hexdigit(value
[2 * i
+ 1]);
1296 if (upper_nibble
<= 0x0F && lower_nibble
<= 0x0F) {
1297 val_ptr
->octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
1306 return JSON_ERROR_INVALID_TOKEN
;
1310 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "octetstring");
1314 return JSON_ERROR_FATAL
;
1319 // octetstring element class
1321 OCTETSTRING_ELEMENT::OCTETSTRING_ELEMENT(boolean par_bound_flag
,
1322 OCTETSTRING
& par_str_val
, int par_octet_pos
)
1323 : bound_flag(par_bound_flag
), str_val(par_str_val
), octet_pos(par_octet_pos
)
1327 OCTETSTRING_ELEMENT
& OCTETSTRING_ELEMENT::operator=
1328 (const OCTETSTRING
& other_value
)
1330 other_value
.must_bound("Assignment of an unbound octetstring value.");
1331 if(other_value
.val_ptr
->n_octets
!= 1)
1332 TTCN_error("Assignment of an octetstring "
1333 "with length other than 1 to an octetstring element.");
1335 str_val
.copy_value();
1336 str_val
.val_ptr
->octets_ptr
[octet_pos
] = other_value
.val_ptr
->octets_ptr
[0];
1340 OCTETSTRING_ELEMENT
& OCTETSTRING_ELEMENT::operator=
1341 (const OCTETSTRING_ELEMENT
& other_value
)
1343 other_value
.must_bound("Assignment of an unbound octetstring element.");
1344 if (&other_value
!= this) {
1346 str_val
.copy_value();
1347 str_val
.val_ptr
->octets_ptr
[octet_pos
] =
1348 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1353 boolean
OCTETSTRING_ELEMENT::operator==(const OCTETSTRING
& other_value
) const
1355 must_bound("Unbound left operand of octetstring element comparison.");
1356 other_value
.must_bound("Unbound right operand of octetstring comparison.");
1357 if(other_value
.val_ptr
->n_octets
!= 1) return FALSE
;
1358 return str_val
.val_ptr
->octets_ptr
[octet_pos
] ==
1359 other_value
.val_ptr
->octets_ptr
[0];
1362 boolean
OCTETSTRING_ELEMENT::operator==
1363 (const OCTETSTRING_ELEMENT
& other_value
) const
1365 must_bound("Unbound left operand of octetstring element comparison.");
1366 other_value
.must_bound("Unbound right operand of octetstring element "
1368 return str_val
.val_ptr
->octets_ptr
[octet_pos
] ==
1369 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1372 OCTETSTRING
OCTETSTRING_ELEMENT::operator+(const OCTETSTRING
& other_value
) const
1374 must_bound("Unbound left operand of octetstring element concatenation.");
1375 other_value
.must_bound("Unbound right operand of octetstring concatenation.");
1376 OCTETSTRING
ret_val(other_value
.val_ptr
->n_octets
+ 1);
1377 ret_val
.val_ptr
->octets_ptr
[0] = str_val
.val_ptr
->octets_ptr
[octet_pos
];
1378 memcpy(ret_val
.val_ptr
->octets_ptr
+ 1,
1379 other_value
.val_ptr
->octets_ptr
, other_value
.val_ptr
->n_octets
);
1383 OCTETSTRING
OCTETSTRING_ELEMENT::operator+
1384 (const OCTETSTRING_ELEMENT
& other_value
) const
1386 must_bound("Unbound left operand of octetstring element concatenation.");
1387 other_value
.must_bound("Unbound right operand of octetstring element "
1389 unsigned char result
[2];
1390 result
[0] = str_val
.val_ptr
->octets_ptr
[octet_pos
];
1391 result
[1] = other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1392 return OCTETSTRING(2, result
);
1395 OCTETSTRING
OCTETSTRING_ELEMENT::operator~() const
1397 must_bound("Unbound octetstring element operand of operator not4b.");
1398 unsigned char result
= ~str_val
.val_ptr
->octets_ptr
[octet_pos
];
1399 return OCTETSTRING(1, &result
);
1402 OCTETSTRING
OCTETSTRING_ELEMENT::operator&(const OCTETSTRING
& other_value
) const
1404 must_bound("Left operand of operator and4b is an unbound octetstring "
1406 other_value
.must_bound("Right operand of operator and4b is an unbound "
1407 "octetstring value.");
1408 if (other_value
.val_ptr
->n_octets
!= 1)
1409 TTCN_error("The octetstring "
1410 "operands of operator and4b must have the same length.");
1411 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] &
1412 other_value
.val_ptr
->octets_ptr
[0];
1413 return OCTETSTRING(1, &result
);
1416 OCTETSTRING
OCTETSTRING_ELEMENT::operator&
1417 (const OCTETSTRING_ELEMENT
& other_value
) const
1419 must_bound("Left operand of operator and4b is an unbound octetstring "
1421 other_value
.must_bound("Right operand of operator and4b is an unbound "
1422 "octetstring element.");
1423 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] &
1424 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1425 return OCTETSTRING(1, &result
);
1428 OCTETSTRING
OCTETSTRING_ELEMENT::operator|(const OCTETSTRING
& other_value
) const
1430 must_bound("Left operand of operator or4b is an unbound octetstring "
1432 other_value
.must_bound("Right operand of operator or4b is an unbound "
1433 "octetstring value.");
1434 if (other_value
.val_ptr
->n_octets
!= 1)
1435 TTCN_error("The octetstring "
1436 "operands of operator or4b must have the same length.");
1437 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] |
1438 other_value
.val_ptr
->octets_ptr
[0];
1439 return OCTETSTRING(1, &result
);
1442 OCTETSTRING
OCTETSTRING_ELEMENT::operator|
1443 (const OCTETSTRING_ELEMENT
& other_value
) const
1445 must_bound("Left operand of operator or4b is an unbound octetstring "
1447 other_value
.must_bound("Right operand of operator or4b is an unbound "
1448 "octetstring element.");
1449 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] |
1450 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1451 return OCTETSTRING(1, &result
);
1454 OCTETSTRING
OCTETSTRING_ELEMENT::operator^(const OCTETSTRING
& other_value
) const
1456 must_bound("Left operand of operator xor4b is an unbound octetstring "
1458 other_value
.must_bound("Right operand of operator xor4b is an unbound "
1459 "octetstring value.");
1460 if (other_value
.val_ptr
->n_octets
!= 1)
1461 TTCN_error("The octetstring "
1462 "operands of operator xor4b must have the same length.");
1463 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] ^
1464 other_value
.val_ptr
->octets_ptr
[0];
1465 return OCTETSTRING(1, &result
);
1468 OCTETSTRING
OCTETSTRING_ELEMENT::operator^
1469 (const OCTETSTRING_ELEMENT
& other_value
) const
1471 must_bound("Left operand of operator xor4b is an unbound octetstring "
1473 other_value
.must_bound("Right operand of operator xor4b is an unbound "
1474 "octetstring element.");
1475 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] ^
1476 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1477 return OCTETSTRING(1, &result
);
1480 unsigned char OCTETSTRING_ELEMENT::get_octet() const
1482 return str_val
.val_ptr
->octets_ptr
[octet_pos
];
1485 void OCTETSTRING_ELEMENT::log() const
1488 unsigned char octet
= str_val
.val_ptr
->octets_ptr
[octet_pos
];
1489 TTCN_Logger::log_char('\'');
1490 TTCN_Logger::log_octet(octet
);
1491 TTCN_Logger::log_event_str("'O");
1492 if (TTCN_Logger::is_printable(octet
)) {
1493 TTCN_Logger::log_event_str(" (\"");
1494 TTCN_Logger::log_char_escaped(octet
);
1495 TTCN_Logger::log_event_str("\")");
1497 } else TTCN_Logger::log_event_unbound();
1500 // octetstring template class
1502 void OCTETSTRING_template::clean_up()
1504 switch (template_selection
) {
1506 case COMPLEMENTED_LIST
:
1507 delete [] value_list
.list_value
;
1509 case STRING_PATTERN
:
1510 if (pattern_value
->ref_count
> 1) pattern_value
->ref_count
--;
1511 else if (pattern_value
->ref_count
== 1) Free(pattern_value
);
1512 else TTCN_error("Internal error: Invalid reference counter in an "
1513 "octetstring pattern.");
1518 template_selection
= UNINITIALIZED_TEMPLATE
;
1521 void OCTETSTRING_template::copy_template
1522 (const OCTETSTRING_template
& other_value
)
1524 switch (other_value
.template_selection
) {
1525 case SPECIFIC_VALUE
:
1526 single_value
= other_value
.single_value
;
1533 case COMPLEMENTED_LIST
:
1534 value_list
.n_values
= other_value
.value_list
.n_values
;
1535 value_list
.list_value
= new OCTETSTRING_template
[value_list
.n_values
];
1536 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1537 value_list
.list_value
[i
].copy_template(
1538 other_value
.value_list
.list_value
[i
]);
1540 case STRING_PATTERN
:
1541 pattern_value
= other_value
.pattern_value
;
1542 pattern_value
->ref_count
++;
1545 TTCN_error("Copying an uninitialized/unsupported octetstring template.");
1547 set_selection(other_value
);
1551 This is the same algorithm that match_array uses
1552 to match 'record of' types.
1553 The only differences are: how two elements are matched and
1554 how an asterisk or ? is identified in the template
1556 boolean
OCTETSTRING_template::match_pattern(
1557 const octetstring_pattern_struct
*string_pattern
,
1558 const OCTETSTRING::octetstring_struct
*string_value
)
1560 // the empty pattern matches the empty octetstring only
1561 if (string_pattern
->n_elements
== 0) return string_value
->n_octets
== 0;
1563 int value_index
= 0;
1564 unsigned int template_index
= 0;
1565 int last_asterisk
= -1;
1566 int last_value_to_asterisk
= -1;
1567 //this variable is used to speed up the function
1568 unsigned short pattern_element
;
1572 pattern_element
= string_pattern
->elements_ptr
[template_index
];
1573 if( pattern_element
< 256){
1574 if(string_value
->octets_ptr
[value_index
] == pattern_element
)
1579 if(last_asterisk
== -1) return FALSE
;
1580 template_index
= last_asterisk
+1;
1581 value_index
= ++last_value_to_asterisk
;
1583 } else if(pattern_element
== 256)
1587 }else if(pattern_element
== 257)
1589 last_asterisk
= template_index
++;
1590 last_value_to_asterisk
= value_index
;
1591 } else TTCN_error("Internal error: invalid element in an octetstring "
1594 if(value_index
== string_value
->n_octets
1595 && template_index
== string_pattern
->n_elements
)
1598 }else if (template_index
== string_pattern
->n_elements
)
1600 if(string_pattern
->elements_ptr
[template_index
- 1] == 257)
1603 }else if(last_asterisk
== -1)
1607 template_index
= last_asterisk
+1;
1608 value_index
= ++last_value_to_asterisk
;
1610 }else if(value_index
== string_value
->n_octets
)
1612 while(template_index
< string_pattern
->n_elements
1613 && string_pattern
->elements_ptr
[template_index
] == 257)
1616 return template_index
== string_pattern
->n_elements
;
1621 OCTETSTRING_template::OCTETSTRING_template()
1625 OCTETSTRING_template::OCTETSTRING_template(template_sel other_value
)
1626 : Restricted_Length_Template(other_value
)
1628 check_single_selection(other_value
);
1631 OCTETSTRING_template::OCTETSTRING_template(const OCTETSTRING
& other_value
)
1632 : Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1636 OCTETSTRING_template::OCTETSTRING_template
1637 (const OCTETSTRING_ELEMENT
& other_value
)
1638 : Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1642 OCTETSTRING_template::OCTETSTRING_template
1643 (const OPTIONAL
<OCTETSTRING
>& other_value
)
1645 switch (other_value
.get_selection()) {
1646 case OPTIONAL_PRESENT
:
1647 set_selection(SPECIFIC_VALUE
);
1648 single_value
= (const OCTETSTRING
&)other_value
;
1651 set_selection(OMIT_VALUE
);
1654 TTCN_error("Creating an octetstring template from an unbound optional "
1659 OCTETSTRING_template::OCTETSTRING_template(unsigned int n_elements
,
1660 const unsigned short *pattern_elements
)
1661 : Restricted_Length_Template(STRING_PATTERN
)
1663 pattern_value
= (octetstring_pattern_struct
*)
1664 Malloc(sizeof(octetstring_pattern_struct
) +
1665 (n_elements
- 1) * sizeof(unsigned short));
1666 pattern_value
->ref_count
= 1;
1667 pattern_value
->n_elements
= n_elements
;
1668 memcpy(pattern_value
->elements_ptr
, pattern_elements
,
1669 n_elements
* sizeof(unsigned short));
1672 OCTETSTRING_template::OCTETSTRING_template
1673 (const OCTETSTRING_template
& other_value
)
1674 : Restricted_Length_Template()
1676 copy_template(other_value
);
1679 OCTETSTRING_template::~OCTETSTRING_template()
1684 OCTETSTRING_template
& OCTETSTRING_template::operator=(template_sel other_value
)
1686 check_single_selection(other_value
);
1688 set_selection(other_value
);
1692 OCTETSTRING_template
& OCTETSTRING_template::operator=
1693 (const OCTETSTRING
& other_value
)
1695 other_value
.must_bound("Assignment of an unbound octetstring value to a "
1698 set_selection(SPECIFIC_VALUE
);
1699 single_value
= other_value
;
1703 OCTETSTRING_template
& OCTETSTRING_template::operator=
1704 (const OCTETSTRING_ELEMENT
& other_value
)
1706 other_value
.must_bound("Assignment of an unbound octetstring element to a "
1709 set_selection(SPECIFIC_VALUE
);
1710 single_value
= other_value
;
1714 OCTETSTRING_template
& OCTETSTRING_template::operator=
1715 (const OPTIONAL
<OCTETSTRING
>& other_value
)
1718 switch (other_value
.get_selection()) {
1719 case OPTIONAL_PRESENT
:
1720 set_selection(SPECIFIC_VALUE
);
1721 single_value
= (const OCTETSTRING
&)other_value
;
1724 set_selection(OMIT_VALUE
);
1727 TTCN_error("Assignment of an unbound optional field to an octetstring "
1733 OCTETSTRING_template
& OCTETSTRING_template::operator=
1734 (const OCTETSTRING_template
& other_value
)
1736 if (&other_value
!= this) {
1738 copy_template(other_value
);
1743 OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](int index_value
)
1745 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1746 TTCN_error("Accessing an octetstring element of a non-specific "
1747 "octetstring template.");
1748 return single_value
[index_value
];
1751 OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](const INTEGER
& index_value
)
1753 index_value
.must_bound("Indexing a octetstring value with an unbound "
1755 return (*this)[(int)index_value
];
1758 const OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](int index_value
) const
1760 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1761 TTCN_error("Accessing an octetstring element of a non-specific "
1762 "octetstring template.");
1763 return single_value
[index_value
];
1766 const OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](const INTEGER
& index_value
) const
1768 index_value
.must_bound("Indexing a octetstring template with an unbound "
1770 return (*this)[(int)index_value
];
1773 boolean
OCTETSTRING_template::match(const OCTETSTRING
& other_value
,
1774 boolean
/* legacy */) const
1776 if (!other_value
.is_bound()) return FALSE
;
1777 if (!match_length(other_value
.val_ptr
->n_octets
)) return FALSE
;
1778 switch (template_selection
) {
1779 case SPECIFIC_VALUE
:
1780 return single_value
== other_value
;
1787 case COMPLEMENTED_LIST
:
1788 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1789 if (value_list
.list_value
[i
].match(other_value
))
1790 return template_selection
== VALUE_LIST
;
1791 return template_selection
== COMPLEMENTED_LIST
;
1792 case STRING_PATTERN
:
1793 return match_pattern(pattern_value
, other_value
.val_ptr
);
1795 TTCN_error("Matching an uninitialized/unsupported octetstring template.");
1800 const OCTETSTRING
& OCTETSTRING_template::valueof() const
1802 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1803 TTCN_error("Performing a valueof or send operation on a non-specific "
1804 "octetstring template.");
1805 return single_value
;
1808 int OCTETSTRING_template::lengthof() const
1811 boolean has_any_or_none
;
1813 TTCN_error("Performing lengthof() operation on a octetstring template "
1814 "which has an ifpresent attribute.");
1815 switch (template_selection
)
1817 case SPECIFIC_VALUE
:
1818 min_length
= single_value
.lengthof();
1819 has_any_or_none
= FALSE
;
1822 TTCN_error("Performing lengthof() operation on an octetstring template "
1823 "containing omit value.");
1827 has_any_or_none
= TRUE
; // max. length is infinity
1831 // error if any element does not have length or the lengths differ
1832 if (value_list
.n_values
<1)
1833 TTCN_error("Internal error: "
1834 "Performing lengthof() operation on an octetstring template "
1835 "containing an empty list.");
1836 int item_length
= value_list
.list_value
[0].lengthof();
1837 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
1838 if (value_list
.list_value
[i
].lengthof()!=item_length
)
1839 TTCN_error("Performing lengthof() operation on an octetstring template "
1840 "containing a value list with different lengths.");
1842 min_length
= item_length
;
1843 has_any_or_none
= FALSE
;
1846 case COMPLEMENTED_LIST
:
1847 TTCN_error("Performing lengthof() operation on an octetstring template "
1848 "containing complemented list.");
1849 case STRING_PATTERN
:
1851 has_any_or_none
= FALSE
; // TRUE if * chars in the pattern
1852 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++)
1854 if (pattern_value
->elements_ptr
[i
] < 257) min_length
++;
1855 else has_any_or_none
= TRUE
; // case of * character
1859 TTCN_error("Performing lengthof() operation on an "
1860 "uninitialized/unsupported octetstring template.");
1862 return check_section_is_single(min_length
, has_any_or_none
,
1863 "length", "an", "octetstring template");
1866 void OCTETSTRING_template::set_type(template_sel template_type
,
1867 unsigned int list_length
)
1869 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
1870 TTCN_error("Setting an invalid list type for an octetstring template.");
1872 set_selection(template_type
);
1873 value_list
.n_values
= list_length
;
1874 value_list
.list_value
= new OCTETSTRING_template
[list_length
];
1877 OCTETSTRING_template
& OCTETSTRING_template::list_item(unsigned int list_index
)
1879 if (template_selection
!= VALUE_LIST
&&
1880 template_selection
!= COMPLEMENTED_LIST
)
1881 TTCN_error("Accessing a list element of a non-list octetstring template.");
1882 if (list_index
>= value_list
.n_values
)
1883 TTCN_error("Index overflow in an octetstring value list template.");
1884 return value_list
.list_value
[list_index
];
1887 void OCTETSTRING_template::log() const
1889 switch (template_selection
) {
1890 case SPECIFIC_VALUE
:
1893 case COMPLEMENTED_LIST
:
1894 TTCN_Logger::log_event_str("complement ");
1897 TTCN_Logger::log_char('(');
1898 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
1899 if (i
> 0) TTCN_Logger::log_event_str(", ");
1900 value_list
.list_value
[i
].log();
1902 TTCN_Logger::log_char(')');
1904 case STRING_PATTERN
:
1905 TTCN_Logger::log_char('\'');
1906 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++) {
1907 unsigned short pattern
= pattern_value
->elements_ptr
[i
];
1908 if (pattern
< 256) TTCN_Logger::log_octet(pattern
);
1909 else if (pattern
== 256) TTCN_Logger::log_char('?');
1910 else if (pattern
== 257) TTCN_Logger::log_char('*');
1911 else TTCN_Logger::log_event_str("<unknown>");
1913 TTCN_Logger::log_event_str("'O");
1923 void OCTETSTRING_template::log_match(const OCTETSTRING
& match_value
,
1924 boolean
/* legacy */) const
1926 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
1927 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1928 TTCN_Logger::print_logmatch_buffer();
1929 TTCN_Logger::log_event_str(" := ");
1932 TTCN_Logger::log_event_str(" with ");
1934 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
1935 else TTCN_Logger::log_event_str(" unmatched");
1938 void OCTETSTRING_template::set_param(Module_Param
& param
) {
1939 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "octetstring template");
1940 Module_Param_Ptr mp
= ¶m
;
1941 if (param
.get_type() == Module_Param::MP_Reference
) {
1942 mp
= param
.get_referenced_param();
1944 switch (mp
->get_type()) {
1945 case Module_Param::MP_Omit
:
1948 case Module_Param::MP_Any
:
1951 case Module_Param::MP_AnyOrNone
:
1952 *this = ANY_OR_OMIT
;
1954 case Module_Param::MP_List_Template
:
1955 case Module_Param::MP_ComplementList_Template
: {
1956 OCTETSTRING_template temp
;
1957 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
1958 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
1959 for (size_t i
=0; i
<mp
->get_size(); i
++) {
1960 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
1964 case Module_Param::MP_Octetstring
:
1965 *this = OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
1967 case Module_Param::MP_Octetstring_Template
:
1968 *this = OCTETSTRING_template(mp
->get_string_size(), (unsigned short*)mp
->get_string_data());
1970 case Module_Param::MP_Expression
:
1971 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
1972 OCTETSTRING operand1
, operand2
;
1973 operand1
.set_param(*mp
->get_operand1());
1974 operand2
.set_param(*mp
->get_operand2());
1975 *this = operand1
+ operand2
;
1978 param
.expr_type_error("a bitstring");
1982 param
.type_error("octetstring template");
1984 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
1985 if (param
.get_length_restriction() != NULL
) {
1986 set_length_range(param
);
1989 set_length_range(*mp
);
1993 Module_Param
* OCTETSTRING_template::get_param(Module_Param_Name
& param_name
) const
1995 Module_Param
* mp
= NULL
;
1996 switch (template_selection
) {
1997 case UNINITIALIZED_TEMPLATE
:
1998 mp
= new Module_Param_Unbound();
2001 mp
= new Module_Param_Omit();
2004 mp
= new Module_Param_Any();
2007 mp
= new Module_Param_AnyOrNone();
2009 case SPECIFIC_VALUE
:
2010 mp
= single_value
.get_param(param_name
);
2013 case COMPLEMENTED_LIST
: {
2014 if (template_selection
== VALUE_LIST
) {
2015 mp
= new Module_Param_List_Template();
2018 mp
= new Module_Param_ComplementList_Template();
2020 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
2021 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
2024 case STRING_PATTERN
: {
2025 unsigned short* val_cpy
= (unsigned short*)Malloc(pattern_value
->n_elements
*
2026 sizeof(unsigned short));
2027 memcpy(val_cpy
, pattern_value
->elements_ptr
, pattern_value
->n_elements
*
2028 sizeof(unsigned short));
2029 mp
= new Module_Param_Octetstring_Template(pattern_value
->n_elements
, val_cpy
);
2035 mp
->set_ifpresent();
2037 mp
->set_length_restriction(get_length_range());
2041 void OCTETSTRING_template::encode_text(Text_Buf
& text_buf
) const
2043 encode_text_restricted(text_buf
);
2044 switch (template_selection
) {
2049 case SPECIFIC_VALUE
:
2050 single_value
.encode_text(text_buf
);
2053 case COMPLEMENTED_LIST
:
2054 text_buf
.push_int(value_list
.n_values
);
2055 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2056 value_list
.list_value
[i
].encode_text(text_buf
);
2058 case STRING_PATTERN
:
2059 text_buf
.push_int(pattern_value
->n_elements
);
2060 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++)
2061 text_buf
.push_int(pattern_value
->elements_ptr
[i
]);
2064 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2065 "octetstring template.");
2069 void OCTETSTRING_template::decode_text(Text_Buf
& text_buf
)
2072 decode_text_restricted(text_buf
);
2073 switch (template_selection
) {
2078 case SPECIFIC_VALUE
:
2079 single_value
.decode_text(text_buf
);
2082 case COMPLEMENTED_LIST
:
2083 value_list
.n_values
= text_buf
.pull_int().get_val();
2084 value_list
.list_value
= new OCTETSTRING_template
[value_list
.n_values
];
2085 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2086 value_list
.list_value
[i
].decode_text(text_buf
);
2088 case STRING_PATTERN
: {
2089 unsigned int n_elements
= text_buf
.pull_int().get_val();
2090 pattern_value
= (octetstring_pattern_struct
*)
2091 Malloc(sizeof(octetstring_pattern_struct
) + (n_elements
- 1) *
2092 sizeof(unsigned short));
2093 pattern_value
->ref_count
= 1;
2094 pattern_value
->n_elements
= n_elements
;
2095 for (unsigned int i
= 0; i
< n_elements
; i
++)
2096 pattern_value
->elements_ptr
[i
] = text_buf
.pull_int().get_val();
2099 TTCN_error("Text decoder: An unknown/unsupported selection was "
2100 "received for an octetstring template.");
2104 boolean
OCTETSTRING_template::is_present(boolean legacy
/* = FALSE */) const
2106 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2107 return !match_omit(legacy
);
2110 boolean
OCTETSTRING_template::match_omit(boolean legacy
/* = FALSE */) const
2112 if (is_ifpresent
) return TRUE
;
2113 switch (template_selection
) {
2118 case COMPLEMENTED_LIST
:
2120 // legacy behavior: 'omit' can appear in the value/complement list
2121 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2122 if (value_list
.list_value
[i
].match_omit())
2123 return template_selection
==VALUE_LIST
;
2124 return template_selection
==COMPLEMENTED_LIST
;
2126 // else fall through
2133 #ifndef TITAN_RUNTIME_2
2134 void OCTETSTRING_template::check_restriction(template_res t_res
, const char* t_name
,
2135 boolean legacy
/* = FALSE */) const
2137 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2138 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2140 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2143 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2144 template_selection
==SPECIFIC_VALUE
)) return;
2147 if (!match_omit(legacy
)) return;
2152 TTCN_error("Restriction `%s' on template of type %s violated.",
2153 get_res_name(t_res
), t_name
? t_name
: "octetstring");