1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
19 * Szabo, Janos Zoltan – initial implementation
24 ******************************************************************************/
25 #include "Octetstring.hh"
26 #include "../common/memory.h"
28 #include "String_struct.hh"
29 #include "Param_Types.hh"
38 #include "../common/dbgnew.hh"
41 // octetstring value class
43 /** The amount of memory needed for a string containing n octets. */
44 #define MEMORY_SIZE(n) (sizeof(octetstring_struct) - sizeof(int) + (n))
46 static const Token_Match
47 octetstring_value_match("^(([0-9A-Fa-f]{2})+).*$", TRUE
);
49 void OCTETSTRING::init_struct(int n_octets
)
53 TTCN_error("Initializing an octetstring with a negative length.");
54 } else if (n_octets
== 0) {
55 /* This will represent the empty strings so they won't need allocated
56 * memory, this delays the memory allocation until it is really needed.
58 static octetstring_struct empty_string
= { 1, 0, "" };
59 val_ptr
= &empty_string
;
60 empty_string
.ref_count
++;
62 val_ptr
= (octetstring_struct
*)Malloc(MEMORY_SIZE(n_octets
));
63 val_ptr
->ref_count
= 1;
64 val_ptr
->n_octets
= n_octets
;
68 void OCTETSTRING::copy_value()
70 if (val_ptr
== NULL
|| val_ptr
->n_octets
<= 0)
71 TTCN_error("Internal error: Invalid internal data structure when copying "
72 "the memory area of an octetstring value.");
73 if (val_ptr
->ref_count
> 1) {
74 octetstring_struct
*old_ptr
= val_ptr
;
76 init_struct(old_ptr
->n_octets
);
77 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, old_ptr
->n_octets
);
81 // Called by operator+, operator~, operator&, operator|
82 // to initialize the return value to the appropriate capacity
83 // without copying bytes (which will be altered).
84 OCTETSTRING::OCTETSTRING(int n_octets
)
86 init_struct(n_octets
);
89 OCTETSTRING::OCTETSTRING()
94 OCTETSTRING::OCTETSTRING(int n_octets
, const unsigned char* octets_ptr
)
96 init_struct(n_octets
);
97 memcpy(val_ptr
->octets_ptr
, octets_ptr
, n_octets
);
100 OCTETSTRING::OCTETSTRING(const OCTETSTRING
& other_value
)
101 : Base_Type(other_value
)
103 other_value
.must_bound("Copying an unbound octetstring value.");
104 val_ptr
= other_value
.val_ptr
;
105 val_ptr
->ref_count
++;
108 OCTETSTRING::OCTETSTRING(const OCTETSTRING_ELEMENT
& other_value
)
110 other_value
.must_bound("Copying an unbound octetstring element.");
112 val_ptr
->octets_ptr
[0] = other_value
.get_octet();
115 OCTETSTRING::~OCTETSTRING()
120 OCTETSTRING
& OCTETSTRING::operator=(const OCTETSTRING
& other_value
)
122 other_value
.must_bound("Assignment of an unbound octetstring value.");
123 if (&other_value
!= this) {
125 val_ptr
= other_value
.val_ptr
;
126 val_ptr
->ref_count
++;
131 OCTETSTRING
& OCTETSTRING::operator=(const OCTETSTRING_ELEMENT
& other_value
)
133 other_value
.must_bound("Assignment of an unbound octetstring element to an "
135 unsigned char octet_value
= other_value
.get_octet();
138 val_ptr
->octets_ptr
[0] = octet_value
;
142 boolean
OCTETSTRING::operator==(const OCTETSTRING
& other_value
) const
144 must_bound("Unbound left operand of octetstring comparison.");
145 other_value
.must_bound("Unbound right operand of octetstring comparison.");
146 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
) return FALSE
;
147 return !memcmp(val_ptr
->octets_ptr
, other_value
.val_ptr
->octets_ptr
,
151 boolean
OCTETSTRING::operator==(const OCTETSTRING_ELEMENT
& other_value
) const
153 must_bound("Unbound left operand of octetstring comparison.");
154 other_value
.must_bound("Unbound right operand of octetstring element "
156 if (val_ptr
->n_octets
!= 1) return FALSE
;
157 return val_ptr
->octets_ptr
[0] == other_value
.get_octet();
160 OCTETSTRING
OCTETSTRING::operator+(const OCTETSTRING
& other_value
) const
162 must_bound("Unbound left operand of octetstring concatenation.");
163 other_value
.must_bound("Unbound right operand of octetstring concatenation.");
164 int left_n_octets
= val_ptr
->n_octets
;
165 if (left_n_octets
== 0) return other_value
;
166 int right_n_octets
= other_value
.val_ptr
->n_octets
;
167 if (right_n_octets
== 0) return *this;
168 OCTETSTRING
ret_val(left_n_octets
+ right_n_octets
);
169 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
, left_n_octets
);
170 memcpy(ret_val
.val_ptr
->octets_ptr
+ left_n_octets
,
171 other_value
.val_ptr
->octets_ptr
, right_n_octets
);
175 OCTETSTRING
OCTETSTRING::operator+(const OCTETSTRING_ELEMENT
& other_value
) const
177 must_bound("Unbound left operand of octetstring concatenation.");
178 other_value
.must_bound("Unbound right operand of octetstring element "
180 OCTETSTRING
ret_val(val_ptr
->n_octets
+ 1);
181 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
, val_ptr
->n_octets
);
182 ret_val
.val_ptr
->octets_ptr
[val_ptr
->n_octets
] = other_value
.get_octet();
186 OCTETSTRING
& OCTETSTRING::operator+=(const OCTETSTRING
& other_value
)
188 must_bound("Appending an octetstring value to an unbound octetstring value.");
189 other_value
.must_bound("Appending an unbound octetstring value to another "
190 "octetstring value.");
191 int other_n_octets
= other_value
.val_ptr
->n_octets
;
192 if (other_n_octets
> 0) {
193 if (val_ptr
->n_octets
== 0) {
195 val_ptr
= other_value
.val_ptr
;
196 val_ptr
->ref_count
++;
197 } else if (val_ptr
->ref_count
> 1) {
198 octetstring_struct
*old_ptr
= val_ptr
;
199 old_ptr
->ref_count
--;
200 init_struct(old_ptr
->n_octets
+ other_n_octets
);
201 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, old_ptr
->n_octets
);
202 memcpy(val_ptr
->octets_ptr
+ old_ptr
->n_octets
,
203 other_value
.val_ptr
->octets_ptr
, other_n_octets
);
205 val_ptr
= (octetstring_struct
*)
206 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
+ other_n_octets
));
207 memcpy(val_ptr
->octets_ptr
+ val_ptr
->n_octets
,
208 other_value
.val_ptr
->octets_ptr
, other_n_octets
);
209 val_ptr
->n_octets
+= other_n_octets
;
215 OCTETSTRING
& OCTETSTRING::operator+=(const OCTETSTRING_ELEMENT
& other_value
)
217 must_bound("Appending an octetstring element to an unbound octetstring "
219 other_value
.must_bound("Appending an unbound octetstring element to an "
220 "octetstring value.");
221 if (val_ptr
->ref_count
> 1) {
222 octetstring_struct
*old_ptr
= val_ptr
;
223 old_ptr
->ref_count
--;
224 init_struct(old_ptr
->n_octets
+ 1);
225 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, old_ptr
->n_octets
);
226 val_ptr
->octets_ptr
[old_ptr
->n_octets
] = other_value
.get_octet();
228 val_ptr
= (octetstring_struct
*)
229 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
+ 1));
230 val_ptr
->octets_ptr
[val_ptr
->n_octets
] = other_value
.get_octet();
236 OCTETSTRING
OCTETSTRING::operator~() const
238 must_bound("Unbound octetstring operand of operator not4b.");
239 OCTETSTRING
ret_val(val_ptr
->n_octets
);
240 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
241 ret_val
.val_ptr
->octets_ptr
[i
] = ~val_ptr
->octets_ptr
[i
];
245 OCTETSTRING
OCTETSTRING::operator&(const OCTETSTRING
& other_value
) const
247 must_bound("Left operand of operator and4b is an unbound octetstring value.");
248 other_value
.must_bound("Right operand of operator and4b is an unbound "
249 "octetstring value.");
250 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
)
251 TTCN_error("The octetstring operands of operator and4b must have the "
253 OCTETSTRING
ret_val(val_ptr
->n_octets
);
254 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
255 ret_val
.val_ptr
->octets_ptr
[i
] =
256 val_ptr
->octets_ptr
[i
] & other_value
.val_ptr
->octets_ptr
[i
];
260 OCTETSTRING
OCTETSTRING::operator&(const OCTETSTRING_ELEMENT
& other_value
) const
262 must_bound("Left operand of operator and4b is an unbound octetstring value.");
263 other_value
.must_bound("Right operand of operator and4b is an unbound "
264 "octetstring element.");
265 if (val_ptr
->n_octets
!= 1)
266 TTCN_error("The octetstring operands of "
267 "operator and4b must have the same length.");
268 unsigned char result
= val_ptr
->octets_ptr
[0] & other_value
.get_octet();
269 return OCTETSTRING(1, &result
);
272 OCTETSTRING
OCTETSTRING::operator|(const OCTETSTRING
& other_value
) const
274 must_bound("Left operand of operator or4b is an unbound octetstring value.");
275 other_value
.must_bound("Right operand of operator or4b is an unbound "
276 "octetstring value.");
277 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
)
278 TTCN_error("The octetstring operands of operator or4b must have the "
280 OCTETSTRING
ret_val(val_ptr
->n_octets
);
281 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
282 ret_val
.val_ptr
->octets_ptr
[i
] =
283 val_ptr
->octets_ptr
[i
] | other_value
.val_ptr
->octets_ptr
[i
];
287 OCTETSTRING
OCTETSTRING::operator|(const OCTETSTRING_ELEMENT
& other_value
) const
289 must_bound("Left operand of operator or4b is an unbound octetstring value.");
290 other_value
.must_bound("Right operand of operator or4b is an unbound "
291 "octetstring element.");
292 if (val_ptr
->n_octets
!= 1)
293 TTCN_error("The octetstring operands of "
294 "operator or4b must have the same length.");
295 unsigned char result
= val_ptr
->octets_ptr
[0] | other_value
.get_octet();
296 return OCTETSTRING(1, &result
);
299 OCTETSTRING
OCTETSTRING::operator^(const OCTETSTRING
& other_value
) const
301 must_bound("Left operand of operator xor4b is an unbound octetstring value.");
302 other_value
.must_bound("Right operand of operator xor4b is an unbound "
303 "octetstring value.");
304 if (val_ptr
->n_octets
!= other_value
.val_ptr
->n_octets
)
305 TTCN_error("The octetstring operands of operator xor4b must have the "
307 OCTETSTRING
ret_val(val_ptr
->n_octets
);
308 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
309 ret_val
.val_ptr
->octets_ptr
[i
] =
310 val_ptr
->octets_ptr
[i
] ^ other_value
.val_ptr
->octets_ptr
[i
];
314 OCTETSTRING
OCTETSTRING::operator^(const OCTETSTRING_ELEMENT
& other_value
) const
316 must_bound("Left operand of operator xor4b is an unbound octetstring value.");
317 other_value
.must_bound("Right operand of operator xor4b is an unbound "
318 "octetstring element.");
319 if (val_ptr
->n_octets
!= 1)
320 TTCN_error("The octetstring operands of "
321 "operator xor4b must have the same length.");
322 unsigned char result
= val_ptr
->octets_ptr
[0] ^ other_value
.get_octet();
323 return OCTETSTRING(1, &result
);
326 OCTETSTRING
OCTETSTRING::operator<<(int shift_count
) const
328 must_bound("Unbound octetstring operand of shift left operator.");
329 if (shift_count
> 0) {
330 if (val_ptr
->n_octets
== 0) return *this;
331 OCTETSTRING
ret_val(val_ptr
->n_octets
);
332 if (shift_count
> val_ptr
->n_octets
) shift_count
= val_ptr
->n_octets
;
333 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
+ shift_count
,
334 val_ptr
->n_octets
- shift_count
);
335 memset(ret_val
.val_ptr
->octets_ptr
+ val_ptr
->n_octets
- shift_count
,
338 } else if (shift_count
== 0) return *this;
339 else return *this >> (-shift_count
);
342 OCTETSTRING
OCTETSTRING::operator<<(const INTEGER
& shift_count
) const
344 shift_count
.must_bound("Unbound right operand of octetstring shift left "
346 return *this << (int)shift_count
;
349 OCTETSTRING
OCTETSTRING::operator>>(int shift_count
) const
351 must_bound("Unbound octetstring operand of shift right operator.");
352 if (shift_count
> 0) {
353 if (val_ptr
->n_octets
== 0) return *this;
354 OCTETSTRING
ret_val(val_ptr
->n_octets
);
355 if (shift_count
> val_ptr
->n_octets
) shift_count
= val_ptr
->n_octets
;
356 memset(ret_val
.val_ptr
->octets_ptr
, 0, shift_count
);
357 memcpy(ret_val
.val_ptr
->octets_ptr
+ shift_count
, val_ptr
->octets_ptr
,
358 val_ptr
->n_octets
- shift_count
);
360 } else if (shift_count
== 0) return *this;
361 else return *this << (-shift_count
);
364 OCTETSTRING
OCTETSTRING::operator>>(const INTEGER
& shift_count
) const
366 shift_count
.must_bound("Unbound right operand of octetstring shift right "
368 return *this >> (int)shift_count
;
371 OCTETSTRING
OCTETSTRING::operator<<=(int rotate_count
) const
373 must_bound("Unbound octetstring operand of rotate left operator.");
374 if (val_ptr
->n_octets
== 0) return *this;
375 if (rotate_count
>= 0) {
376 rotate_count
%= val_ptr
->n_octets
;
377 if (rotate_count
== 0) return *this;
378 OCTETSTRING
ret_val(val_ptr
->n_octets
);
379 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
+
380 rotate_count
, val_ptr
->n_octets
- rotate_count
);
381 memcpy(ret_val
.val_ptr
->octets_ptr
+ val_ptr
->n_octets
- rotate_count
,
382 val_ptr
->octets_ptr
, rotate_count
);
384 } else return *this >>= (-rotate_count
);
387 OCTETSTRING
OCTETSTRING::operator<<=(const INTEGER
& rotate_count
) const
389 rotate_count
.must_bound("Unbound right operand of octetstring rotate left "
391 return *this <<= (int)rotate_count
;
394 OCTETSTRING
OCTETSTRING::operator>>=(int rotate_count
) const
396 must_bound("Unbound octetstring operand of rotate right operator.");
397 if (val_ptr
->n_octets
== 0) return *this;
398 if (rotate_count
>= 0) {
399 rotate_count
%= val_ptr
->n_octets
;
400 if (rotate_count
== 0) return *this;
401 OCTETSTRING
ret_val(val_ptr
->n_octets
);
402 memcpy(ret_val
.val_ptr
->octets_ptr
, val_ptr
->octets_ptr
+
403 val_ptr
->n_octets
- rotate_count
, rotate_count
);
404 memcpy(ret_val
.val_ptr
->octets_ptr
+ rotate_count
,
405 val_ptr
->octets_ptr
, val_ptr
->n_octets
- rotate_count
);
407 } else return *this <<= (-rotate_count
);
410 OCTETSTRING
OCTETSTRING::operator>>=(const INTEGER
& rotate_count
) const
412 rotate_count
.must_bound("Unbound right operand of octetstring rotate right "
414 return *this >>= (int)rotate_count
;
417 OCTETSTRING_ELEMENT
OCTETSTRING::operator[](int index_value
)
419 if (val_ptr
== NULL
&& index_value
== 0) {
421 return OCTETSTRING_ELEMENT(FALSE
, *this, 0);
423 must_bound("Accessing an element of an unbound octetstring value.");
424 if (index_value
< 0) TTCN_error("Accessing an octetstring element using "
425 "a negative index (%d).", index_value
);
426 int n_octets
= val_ptr
->n_octets
;
427 if (index_value
> n_octets
) TTCN_error("Index overflow when accessing a "
428 "octetstring element: The index is %d, but the string has only %d "
429 "octets.", index_value
, n_octets
);
430 if (index_value
== n_octets
) {
431 if (val_ptr
->ref_count
== 1) {
432 val_ptr
= (octetstring_struct
*)
433 Realloc(val_ptr
, MEMORY_SIZE(n_octets
+ 1));
436 octetstring_struct
*old_ptr
= val_ptr
;
437 old_ptr
->ref_count
--;
438 init_struct(n_octets
+ 1);
439 memcpy(val_ptr
->octets_ptr
, old_ptr
->octets_ptr
, n_octets
);
441 return OCTETSTRING_ELEMENT(FALSE
, *this, index_value
);
442 } else return OCTETSTRING_ELEMENT(TRUE
, *this, index_value
);
446 OCTETSTRING_ELEMENT
OCTETSTRING::operator[](const INTEGER
& index_value
)
448 index_value
.must_bound("Indexing a octetstring value with an unbound integer "
450 return (*this)[(int)index_value
];
453 const OCTETSTRING_ELEMENT
OCTETSTRING::operator[](int index_value
) const
455 must_bound("Accessing an element of an unbound octetstring value.");
456 if (index_value
< 0) TTCN_error("Accessing an octetstring element using a "
457 "negative index (%d).", index_value
);
458 if (index_value
>= val_ptr
->n_octets
) TTCN_error("Index overflow when "
459 "accessing a octetstring element: The index is %d, but the string has "
460 "only %d octets.", index_value
, val_ptr
->n_octets
);
461 return OCTETSTRING_ELEMENT(TRUE
, const_cast<OCTETSTRING
&>(*this),
465 const OCTETSTRING_ELEMENT
OCTETSTRING::operator[](const INTEGER
& index_value
)
468 index_value
.must_bound("Indexing a octetstring value with an unbound integer "
470 return (*this)[(int)index_value
];
473 void OCTETSTRING::clean_up()
475 if (val_ptr
!= NULL
) {
476 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
477 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
478 else TTCN_error("Internal error: Invalid reference counter in an "
479 "octetstring value.");
484 int OCTETSTRING::lengthof() const
486 must_bound("Getting the length of an unbound octetstring value.");
487 return val_ptr
->n_octets
;
490 OCTETSTRING::operator const unsigned char*() const
492 must_bound("Casting an unbound octetstring value to const unsigned char*.");
493 return val_ptr
->octets_ptr
;
496 void OCTETSTRING::log() const
498 if (val_ptr
!= NULL
) {
499 boolean only_printable
= TRUE
;
500 TTCN_Logger::log_char('\'');
501 for (int i
= 0; i
< val_ptr
->n_octets
; i
++) {
502 unsigned char octet
= val_ptr
->octets_ptr
[i
];
503 TTCN_Logger::log_octet(octet
);
504 if (only_printable
&& !TTCN_Logger::is_printable(octet
))
505 only_printable
= FALSE
;
507 TTCN_Logger::log_event_str("'O");
508 if (only_printable
&& val_ptr
->n_octets
> 0) {
509 TTCN_Logger::log_event_str(" (\"");
510 for (int i
= 0; i
< val_ptr
->n_octets
; i
++)
511 TTCN_Logger::log_char_escaped(val_ptr
->octets_ptr
[i
]);
512 TTCN_Logger::log_event_str("\")");
514 } else TTCN_Logger::log_event_unbound();
517 void OCTETSTRING::set_param(Module_Param
& param
) {
518 param
.basic_check(Module_Param::BC_VALUE
|Module_Param::BC_LIST
, "octetstring value");
519 Module_Param_Ptr mp
= ¶m
;
520 if (param
.get_type() == Module_Param::MP_Reference
) {
521 mp
= param
.get_referenced_param();
523 switch (mp
->get_type()) {
524 case Module_Param::MP_Octetstring
:
525 switch (param
.get_operation_type()) {
526 case Module_Param::OT_ASSIGN
:
528 init_struct(mp
->get_string_size());
529 memcpy(val_ptr
->octets_ptr
, mp
->get_string_data(), val_ptr
->n_octets
);
531 case Module_Param::OT_CONCAT
:
533 *this += OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
535 *this = OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
539 TTCN_error("Internal error: OCTETSTRING::set_param()");
542 case Module_Param::MP_Expression
:
543 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
544 OCTETSTRING operand1
, operand2
;
545 operand1
.set_param(*mp
->get_operand1());
546 operand2
.set_param(*mp
->get_operand2());
547 if (param
.get_operation_type() == Module_Param::OT_CONCAT
) {
548 *this = *this + operand1
+ operand2
;
551 *this = operand1
+ operand2
;
555 param
.expr_type_error("a octetstring");
559 param
.type_error("octetstring value");
564 Module_Param
* OCTETSTRING::get_param(Module_Param_Name
& /* param_name */) const
567 return new Module_Param_Unbound();
569 unsigned char* val_cpy
= (unsigned char *)Malloc(val_ptr
->n_octets
);
570 memcpy(val_cpy
, val_ptr
->octets_ptr
, val_ptr
->n_octets
);
571 return new Module_Param_Octetstring(val_ptr
->n_octets
, val_cpy
);
574 void OCTETSTRING::encode_text(Text_Buf
& text_buf
) const
576 must_bound("Text encoder: Encoding an unbound octetstring value.");
577 text_buf
.push_int(val_ptr
->n_octets
);
578 if(val_ptr
->n_octets
> 0)
579 text_buf
.push_raw(val_ptr
->n_octets
, val_ptr
->octets_ptr
);
582 void OCTETSTRING::decode_text(Text_Buf
& text_buf
)
584 int n_octets
= text_buf
.pull_int().get_val();
586 TTCN_error("Text decoder: Invalid length was received for an octetstring.");
588 init_struct(n_octets
);
589 if (n_octets
> 0) text_buf
.pull_raw(n_octets
, val_ptr
->octets_ptr
);
592 void OCTETSTRING::encode(const TTCN_Typedescriptor_t
& p_td
,
594 TTCN_EncDec::coding_t p_coding
, ...) const
597 va_start(pvar
, p_coding
);
599 case TTCN_EncDec::CT_BER
: {
600 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
601 unsigned BER_coding
=va_arg(pvar
, unsigned);
602 BER_encode_chk_coding(BER_coding
);
603 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
604 tlv
->put_in_buffer(p_buf
);
605 ASN_BER_TLV_t::destruct(tlv
);
607 case TTCN_EncDec::CT_RAW
: {
608 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
610 TTCN_EncDec_ErrorContext::error_internal
611 ("No RAW descriptor available for type '%s'.", p_td
.name
);
615 RAW_enc_tree
root(true,NULL
,&rp
,1,p_td
.raw
);
616 RAW_encode(p_td
, root
);
617 root
.put_to_buf(p_buf
);
619 case TTCN_EncDec::CT_TEXT
: {
620 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
622 TTCN_EncDec_ErrorContext::error_internal
623 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
624 TEXT_encode(p_td
,p_buf
);
626 case TTCN_EncDec::CT_XER
: {
627 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
628 unsigned XER_coding
=va_arg(pvar
, unsigned);
629 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
631 case TTCN_EncDec::CT_JSON
: {
632 TTCN_EncDec_ErrorContext
ec("While TEXT-encoding type '%s': ", p_td
.name
);
634 TTCN_EncDec_ErrorContext::error_internal
635 ("No JSON descriptor available for type '%s'.", p_td
.name
);
636 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
637 JSON_encode(p_td
, tok
);
638 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
641 TTCN_error("Unknown coding method requested to encode type '%s'",
647 void OCTETSTRING::decode(const TTCN_Typedescriptor_t
& p_td
,
649 TTCN_EncDec::coding_t p_coding
, ...)
652 va_start(pvar
, p_coding
);
654 case TTCN_EncDec::CT_BER
: {
655 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
656 unsigned L_form
=va_arg(pvar
, unsigned);
658 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
659 BER_decode_TLV(p_td
, tlv
, L_form
);
660 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
662 case TTCN_EncDec::CT_RAW
: {
663 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
665 TTCN_EncDec_ErrorContext::error_internal
666 ("No RAW descriptor available for type '%s'.", p_td
.name
);
668 switch(p_td
.raw
->top_bit_order
){
676 if(RAW_decode(p_td
, p_buf
, p_buf
.get_len()*8, order
)<0)
677 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
678 "Can not decode type '%s', because invalid or incomplete"
679 " message was received"
682 case TTCN_EncDec::CT_TEXT
: {
683 Limit_Token_List limit
;
684 TTCN_EncDec_ErrorContext
ec("While TEXT-decoding type '%s': ", p_td
.name
);
686 TTCN_EncDec_ErrorContext::error_internal
687 ("No TEXT descriptor available for type '%s'.", p_td
.name
);
688 const unsigned char *b
=p_buf
.get_data();
689 if(b
[p_buf
.get_len()-1]!='\0'){
690 p_buf
.set_pos(p_buf
.get_len());
691 p_buf
.put_zero(8,ORDER_LSB
);
694 if(TEXT_decode(p_td
,p_buf
,limit
)<0)
695 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
696 "Can not decode type '%s', because invalid or incomplete"
697 " message was received"
700 case TTCN_EncDec::CT_XER
: {
701 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
702 unsigned XER_coding
=va_arg(pvar
, unsigned);
703 XmlReaderWrap
reader(p_buf
);
704 int success
= reader
.Read();
705 for (; success
==1; success
=reader
.Read()) {
706 int type
= reader
.NodeType();
707 if (type
==XML_READER_TYPE_ELEMENT
)
710 XER_decode(*p_td
.xer
, reader
, XER_coding
, XER_NONE
, 0);
711 size_t bytes
= reader
.ByteConsumed();
712 p_buf
.set_pos(bytes
);
714 case TTCN_EncDec::CT_JSON
: {
715 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
717 TTCN_EncDec_ErrorContext::error_internal
718 ("No JSON descriptor available for type '%s'.", p_td
.name
);
719 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
720 if(JSON_decode(p_td
, tok
, false)<0)
721 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
722 "Can not decode type '%s', because invalid or incomplete"
723 " message was received"
725 p_buf
.set_pos(tok
.get_buf_pos());
728 TTCN_error("Unknown coding method requested to decode type '%s'",
735 OCTETSTRING::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
736 unsigned p_coding
) const
739 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
741 new_tlv
=BER_encode_TLV_OCTETSTRING
742 (p_coding
, val_ptr
->n_octets
, val_ptr
->octets_ptr
);
744 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
748 #ifdef TITAN_RUNTIME_2
749 ASN_BER_TLV_t
* OCTETSTRING::BER_encode_negtest_raw() const
751 unsigned char *p_Vstr
= (unsigned char *)Malloc(val_ptr
->n_octets
);
752 memcpy(p_Vstr
, val_ptr
->octets_ptr
, val_ptr
->n_octets
);
753 ASN_BER_TLV_t
* new_tlv
= ASN_BER_TLV_t::construct(val_ptr
->n_octets
, p_Vstr
);
757 int OCTETSTRING::encode_raw(TTCN_Buffer
& p_buf
) const
759 p_buf
.put_string(*this);
760 return val_ptr
? val_ptr
->n_octets
: 0;
763 int OCTETSTRING::RAW_encode_negtest_raw(RAW_enc_tree
& p_myleaf
) const
765 if (p_myleaf
.must_free
)
766 Free(p_myleaf
.body
.leaf
.data_ptr
);
767 p_myleaf
.must_free
= false;
768 p_myleaf
.data_ptr_used
= true;
769 p_myleaf
.body
.leaf
.data_ptr
= val_ptr
->octets_ptr
;
770 return p_myleaf
.length
= val_ptr
->n_octets
* 8;
773 int OCTETSTRING::JSON_encode_negtest_raw(JSON_Tokenizer
& p_tok
) const
775 if (val_ptr
!= NULL
) {
776 p_tok
.put_raw_data((const char*)val_ptr
->octets_ptr
, val_ptr
->n_octets
);
777 return val_ptr
->n_octets
;
783 boolean
OCTETSTRING::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
784 const ASN_BER_TLV_t
& p_tlv
,
789 ASN_BER_TLV_t stripped_tlv
;
790 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
791 TTCN_EncDec_ErrorContext
ec("While decoding OCTETSTRING type: ");
792 /* Upper estimation for the length. */
793 size_t stripped_tlv_len
= stripped_tlv
.get_len();
794 if (stripped_tlv_len
< 2) return FALSE
;
795 int max_len
= stripped_tlv_len
- 2;
796 init_struct(max_len
);
797 unsigned int octetnum_start
= 0;
798 BER_decode_TLV_OCTETSTRING(stripped_tlv
, L_form
, octetnum_start
,
799 val_ptr
->n_octets
, val_ptr
->octets_ptr
);
800 if (val_ptr
->n_octets
< max_len
) {
801 if (val_ptr
->n_octets
== 0) {
805 val_ptr
= (octetstring_struct
*)
806 Realloc(val_ptr
, MEMORY_SIZE(val_ptr
->n_octets
));
812 int OCTETSTRING::TEXT_decode(const TTCN_Typedescriptor_t
& p_td
,
813 TTCN_Buffer
& buff
, Limit_Token_List
& limit
,
814 boolean no_err
, boolean
/*first_call*/)
816 int decoded_length
=0;
819 if(p_td
.text
->begin_decode
){
821 if((tl
=p_td
.text
->begin_decode
->match_begin(buff
))<0){
823 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
824 "The specified token '%s' not found for '%s': ",
825 (const char*)*(p_td
.text
->begin_decode
), p_td
.name
);
829 buff
.increase_pos(tl
);
831 // never returns "too short"
832 // if(buff.get_read_len()<=1 && no_err) return -TTCN_EncDec::ET_LEN_ERR;
834 if(p_td
.text
->select_token
){
836 if((tl
=p_td
.text
->select_token
->match_begin(buff
))<0) {
837 if(no_err
) return -1;
842 if( p_td
.text
->val
.parameters
843 && p_td
.text
->val
.parameters
->decoding_params
.min_length
!=-1){
844 str_len
=p_td
.text
->val
.parameters
->decoding_params
.min_length
*2;
845 } else if(p_td
.text
->end_decode
){
847 if((tl
=p_td
.text
->end_decode
->match_first(buff
))<0) {
848 if(no_err
) return -1;
852 } else if (limit
.has_token()){
854 if((tl
=limit
.match(buff
))<0)
855 tl
=buff
.get_read_len()-1;;
859 if((tl
=octetstring_value_match
.match_begin(buff
))<0) {
860 if(no_err
) {return -1; }
865 str_len
=(str_len
/2)*2;
866 //printf("HALI chr:%d ",str_len);
867 int n_octets
= str_len
/ 2;
868 init_struct(n_octets
);
869 unsigned char *octets_ptr
= val_ptr
->octets_ptr
;
870 const char *value
=(const char*)buff
.get_read_data();
871 for (int i
= 0; i
< n_octets
; i
++) {
872 unsigned char upper_nibble
= char_to_hexdigit(value
[2 * i
]);
873 unsigned char lower_nibble
= char_to_hexdigit(value
[2 * i
+ 1]);
874 if (upper_nibble
> 0x0F){
875 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
876 "The octetstring value may contain hexadecimal digits only. "
877 "Character \"%c\" was found.", value
[2 * i
]);
880 if (lower_nibble
> 0x0F){
881 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
882 "The octetstring value str2oct() may contain hexadecimal digits only. "
883 "Character \"%c\" was found.", value
[2 * i
+ 1]);
886 octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
889 //printf("%s\n\r",val_ptr->chars_ptr);
890 decoded_length
+=str_len
;
891 buff
.increase_pos(str_len
);
893 if(p_td
.text
->end_decode
){
895 if((tl
=p_td
.text
->end_decode
->match_begin(buff
))<0){
897 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR
,
898 "The specified token '%s' not found for '%s': ",
899 (const char*)*(p_td
.text
->end_decode
), p_td
.name
);
903 buff
.increase_pos(tl
);
905 return decoded_length
;
908 // From Charstring.cc
909 extern char base64_decoder_table
[256];
910 extern unsigned int xlate(cbyte
* in
, int phase
, unsigned char* dest
);
911 extern const char cb64
[];
913 int OCTETSTRING::XER_encode(const XERdescriptor_t
& p_td
,
914 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
917 TTCN_EncDec_ErrorContext::error
918 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound octetstring value.");
920 int exer
= is_exer(flavor
|= SIMPLE_TYPE
);
921 // SIMPLE_TYPE has no influence on is_exer, we set it for later
922 int encoded_length
=(int)p_buf
.get_len();
923 int empty_element
= val_ptr
==NULL
|| val_ptr
->n_octets
== 0;
925 flavor
&= ~XER_RECOF
; // octetstring doesn't care
926 begin_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
928 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
930 size_t clear_len
= lengthof();
931 const unsigned char * in
= operator const unsigned char*();
933 /* Encode 3 bytes of cleartext into 4 bytes of Base64.
934 * Note that the algorithm is slightly different from Charstring.cc:
935 * we can't pad the source because it's const (this),
936 * so we need to check the indexes i+1 and i+2 before dereferencing */
937 for (size_t i
= 0; i
< clear_len
; i
+= 3) {
938 p_buf
.put_c( cb64
[ in
[i
] >> 2 ] );
939 p_buf
.put_c( cb64
[ ((in
[i
] & 0x03) << 4) | (i
+1 < clear_len
940 ? ((in
[i
+1] & 0xf0) >> 4)
942 p_buf
.put_c( i
+1 < clear_len
943 ? cb64
[ ((in
[i
+1] & 0x0f) << 2) | (i
+2 < clear_len
? ((in
[i
+2] & 0xc0) >> 6) :-0) ]
945 p_buf
.put_c( i
+2 < clear_len
? cb64
[ in
[i
+2] & 0x3f ] : '=' );
949 CHARSTRING val
= oct2str(*this);
950 p_buf
.put_string(val
);
953 end_xml(p_td
, p_buf
, flavor
, indent
, empty_element
);
955 return (int)p_buf
.get_len() - encoded_length
;
958 int OCTETSTRING::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
959 unsigned int flavor
, unsigned int /*flavor2*/, embed_values_dec_struct_t
*)
961 int exer
= is_exer(flavor
);
962 int success
= reader
.Ok(), depth
= -1, type
;
963 boolean own_tag
= !is_exerlist(flavor
) && !(exer
&& (p_td
.xer_bits
& UNTAGGED
));
965 const char * value
= 0;
966 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
967 const char * name
= verify_name(reader
, p_td
, exer
);
971 if (own_tag
) for (; success
== 1; success
= reader
.Read()) {
972 type
= reader
.NodeType();
973 if (XML_READER_TYPE_ELEMENT
== type
) {
974 verify_name(reader
, p_td
, exer
);
975 depth
= reader
.Depth();
976 if (reader
.IsEmptyElement()) {
977 if (exer
&& p_td
.dfeValue
!= 0) {
978 *this = *static_cast<const OCTETSTRING
*> (p_td
.dfeValue
);
985 else if (XML_READER_TYPE_TEXT
== type
&& depth
!= -1) break;
986 else if (XML_READER_TYPE_END_ELEMENT
== type
) {
987 // End tag without intervening #text == empty content
988 verify_end(reader
, p_td
, depth
, exer
);
989 if (exer
&& p_td
.dfeValue
!= 0) {
990 *this = *static_cast<const OCTETSTRING
*>(p_td
.dfeValue
);
998 type
= reader
.NodeType();
999 if (success
== 1 && (XML_READER_TYPE_TEXT
== type
|| XML_READER_TYPE_ATTRIBUTE
== type
)) {
1000 value
= (const char *)reader
.Value();
1001 size_t len
= value
? strlen(value
) : 0;
1003 if (exer
&& (p_td
.xer_bits
& BASE_64
)) {
1007 init_struct(len
* 3 / 4);
1008 unsigned char * dest
= val_ptr
->octets_ptr
;
1010 for (size_t o
=0; o
<len
; ++o
) {
1011 xmlChar c
= value
[o
];
1012 if(c
== '=') { // padding starts
1013 dest
+= xlate(in
, phase
, dest
);
1017 int val
= base64_decoder_table
[c
];
1020 phase
= (phase
+ 1) % 4;
1022 dest
+= xlate(in
,phase
, dest
);
1023 in
[0]=in
[1]=in
[2]=in
[3]=0;
1026 else if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1030 TTCN_EncDec_ErrorContext::warning(
1031 /* if this was an error... TTCN_EncDec::ET_INVAL_MSG,*/
1032 "Invalid character for Base64 '%02X'", c
);
1036 val_ptr
->n_octets
= dest
- val_ptr
->octets_ptr
;
1039 else { // not base64
1040 if (len
& 1) { // that's odd...
1041 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1045 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1046 "Odd number of characters in octetstring");
1047 len
&= ~1; // make it even
1050 size_t n_octets
= len
/ 2;
1051 init_struct(n_octets
);
1053 len
= 0; // will act as 2*i
1054 for (size_t i
= 0; i
< n_octets
; ++i
, ++++len
) {
1055 unsigned char upper_nibble
= char_to_hexdigit(value
[len
]);
1056 unsigned char lower_nibble
= char_to_hexdigit(value
[len
+1]);
1057 if (upper_nibble
> 0x0F) {
1058 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1062 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1063 "The octetstring value may contain hexadecimal digits only. "
1064 "Character \"%c\" was found.", value
[len
]);
1068 if (lower_nibble
> 0x0F) {
1069 if (exer
&& (flavor
& EXIT_ON_ERROR
)) {
1073 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
,
1074 "The octetstring value may contain hexadecimal digits only. "
1075 "Character \"%c\" was found.", value
[len
+1]);
1079 val_ptr
->octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
1084 if (exer
&& (p_td
.xer_bits
& XER_ATTRIBUTE
)) {
1085 // Let the caller do reader.AdvanceAttribute();
1088 if (own_tag
) for (success
= reader
.Read(); success
== 1; success
= reader
.Read()) {
1089 type
= reader
.NodeType();
1090 if (XML_READER_TYPE_END_ELEMENT
== type
) {
1091 verify_end(reader
, p_td
, depth
, exer
);
1092 if (val_ptr
== 0 && p_td
.dfeValue
!= 0) {
1093 // The end tag must have followed the start tag
1094 *this = *static_cast<const OCTETSTRING
*>(p_td
.dfeValue
);
1096 reader
.Read(); // one last time
1101 return 1; // decode successful
1104 int OCTETSTRING::TEXT_encode(const TTCN_Typedescriptor_t
& p_td
,
1105 TTCN_Buffer
& buff
) const{
1106 int encoded_length
=0;
1107 if(p_td
.text
->begin_encode
){
1108 buff
.put_cs(*p_td
.text
->begin_encode
);
1109 encoded_length
+=p_td
.text
->begin_encode
->lengthof();
1112 TTCN_EncDec_ErrorContext::error
1113 (TTCN_EncDec::ET_UNBOUND
, "Encoding an unbound value.");
1114 if(p_td
.text
->end_encode
){
1115 buff
.put_cs(*p_td
.text
->end_encode
);
1116 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1118 return encoded_length
;
1123 if(p_td
.text
->val
.parameters
){
1124 if(val_ptr
->n_octets
<p_td
.text
->val
.parameters
->coding_params
.min_length
){
1125 chars_before
=(p_td
.text
->
1126 val
.parameters
->coding_params
.min_length
-val_ptr
->n_octets
)*2;
1131 unsigned char* p
=NULL
;
1132 size_t len
=chars_before
;
1133 buff
.get_end(p
,len
);
1134 for(int a
=0;a
<chars_before
;a
++) p
[a
]=(unsigned char)'0';
1135 buff
.increase_length(chars_before
);
1136 encoded_length
+=chars_before
;
1139 if(val_ptr
->n_octets
){
1140 unsigned char* p
=NULL
;
1141 size_t len
=val_ptr
->n_octets
*2;
1142 buff
.get_end(p
,len
);
1143 len
=val_ptr
->n_octets
;
1144 for(size_t i
=0;i
<len
;i
++){
1145 p
[2 * i
] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] >> 4);
1146 p
[2 * i
+ 1] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] & 0x0F);
1148 buff
.increase_length(len
*2);
1149 encoded_length
+=len
*2;
1153 if(p_td
.text
->end_encode
){
1154 buff
.put_cs(*p_td
.text
->end_encode
);
1155 encoded_length
+=p_td
.text
->end_encode
->lengthof();
1157 return encoded_length
;
1160 int OCTETSTRING::RAW_encode(const TTCN_Typedescriptor_t
& p_td
,
1161 RAW_enc_tree
& myleaf
) const
1164 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1165 "Encoding an unbound value.");
1168 int bl
= val_ptr
->n_octets
* 8;
1169 int align_length
= p_td
.raw
->fieldlength
? p_td
.raw
->fieldlength
- bl
: 0;
1170 int blength
= val_ptr
->n_octets
;
1171 if ((bl
+ align_length
) < val_ptr
->n_octets
* 8) {
1172 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1173 "There are insufficient bits to encode '%s': ", p_td
.name
);
1174 blength
= p_td
.raw
->fieldlength
/ 8;
1175 bl
= p_td
.raw
->fieldlength
;
1178 if (myleaf
.must_free
) Free(myleaf
.body
.leaf
.data_ptr
);
1179 myleaf
.must_free
= false;
1180 myleaf
.data_ptr_used
= true;
1181 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
1182 && myleaf
.coding_par
.bitorder
== ORDER_MSB
) {
1183 if (blength
> RAW_INT_ENC_LENGTH
) {
1184 myleaf
.body
.leaf
.data_ptr
= bc
= (unsigned char*)Malloc(blength
*sizeof(*bc
));
1185 myleaf
.must_free
= true;
1186 myleaf
.data_ptr_used
= true;
1189 bc
= myleaf
.body
.leaf
.data_array
;
1190 myleaf
.data_ptr_used
= false;
1192 for (int a
= 0; a
< blength
; a
++) bc
[a
] = val_ptr
->octets_ptr
[a
] << 1;
1194 else myleaf
.body
.leaf
.data_ptr
= val_ptr
->octets_ptr
;
1195 if (p_td
.raw
->endianness
== ORDER_MSB
) myleaf
.align
= -align_length
;
1196 else myleaf
.align
= align_length
;
1197 return myleaf
.length
= bl
+ align_length
;
1200 int OCTETSTRING::RAW_decode(const TTCN_Typedescriptor_t
& p_td
,
1201 TTCN_Buffer
& buff
, int limit
, raw_order_t top_bit_ord
, boolean no_err
,
1202 int /*sel_field*/, boolean
/*first_call*/)
1204 int prepaddlength
= buff
.increase_pos_padd(p_td
.raw
->prepadding
);
1205 limit
-= prepaddlength
;
1206 int decode_length
= p_td
.raw
->fieldlength
== 0
1207 ? (limit
/ 8) * 8 : p_td
.raw
->fieldlength
;
1208 if (decode_length
> limit
|| decode_length
> (int) buff
.unread_len_bit()) {
1209 if (no_err
) return -TTCN_EncDec::ET_LEN_ERR
;
1210 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_LEN_ERR
,
1211 "There is not enough bits in the buffer to decode type %s.", p_td
.name
);
1212 decode_length
= ((limit
> (int) buff
.unread_len_bit()
1213 ? (int)buff
.unread_len_bit() : limit
) / 8) * 8;
1216 bool orders
= false;
1217 if (p_td
.raw
->bitorderinoctet
== ORDER_MSB
) orders
= true;
1218 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1219 cp
.bitorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1221 if (p_td
.raw
->byteorder
== ORDER_MSB
) orders
= true;
1222 if (p_td
.raw
->bitorderinfield
== ORDER_MSB
) orders
= !orders
;
1223 cp
.byteorder
= orders
? ORDER_MSB
: ORDER_LSB
;
1224 cp
.fieldorder
= p_td
.raw
->fieldorder
;
1225 cp
.hexorder
= ORDER_LSB
;
1226 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
) {
1227 const unsigned char* data
= buff
.get_read_data();
1229 int rot
= top_bit_ord
== ORDER_LSB
? 0 : 7;
1230 if (p_td
.raw
->extension_bit
== EXT_BIT_YES
) {
1231 while (((data
[count
- 1] >> rot
) & 0x01) == 0 && count
* 8 < decode_length
)
1235 while (((data
[count
- 1] >> rot
) & 0x01) == 1 && count
* 8 < decode_length
)
1238 decode_length
= count
* 8;
1241 init_struct(decode_length
/ 8);
1242 buff
.get_b((size_t) decode_length
, val_ptr
->octets_ptr
, cp
, top_bit_ord
);
1244 if (p_td
.raw
->length_restrition
!= -1) {
1245 val_ptr
->n_octets
= p_td
.raw
->length_restrition
;
1246 if (p_td
.raw
->endianness
== ORDER_MSB
) memmove(val_ptr
->octets_ptr
,
1247 val_ptr
->octets_ptr
+ (decode_length
/ 8 - val_ptr
->n_octets
),
1248 val_ptr
->n_octets
* sizeof(unsigned char));
1250 if (p_td
.raw
->extension_bit
!= EXT_BIT_NO
&& cp
.bitorder
== ORDER_MSB
) {
1251 for (int a
= 0; a
< decode_length
/ 8; a
++)
1252 val_ptr
->octets_ptr
[a
] = val_ptr
->octets_ptr
[a
] >> 1 | val_ptr
->octets_ptr
[a
] << 7;
1254 decode_length
+= buff
.increase_pos_padd(p_td
.raw
->padding
);
1255 return decode_length
+ prepaddlength
;
1258 void OCTETSTRING::dump () const
1260 if (val_ptr
!= NULL
) {
1261 printf("octetstring(%d) :\n", val_ptr
->n_octets
);
1262 for (int i
= 0; i
< val_ptr
->n_octets
; i
++) {
1263 printf("%02X ", val_ptr
->octets_ptr
[i
]);
1269 int OCTETSTRING::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
1272 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
1273 "Encoding an unbound octetstring value.");
1277 char* tmp_str
= (char*)Malloc(val_ptr
->n_octets
* 2 + 3);
1279 tmp_str
[val_ptr
->n_octets
* 2 + 1] = '\"';
1280 for(int i
= 0; i
< val_ptr
->n_octets
; ++i
) {
1281 tmp_str
[2 * i
+ 1] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] >> 4);
1282 tmp_str
[2 * i
+ 2] = hexdigit_to_char(val_ptr
->octets_ptr
[i
] & 0x0F);
1284 tmp_str
[val_ptr
->n_octets
* 2 + 2] = 0;
1285 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, tmp_str
);
1290 int OCTETSTRING::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
1292 json_token_t token
= JSON_TOKEN_NONE
;
1294 size_t value_len
= 0;
1295 boolean error
= false;
1297 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
1299 // No JSON data in the buffer -> use default value
1300 value
= (char*)p_td
.json
->default_value
;
1301 value_len
= strlen(value
);
1303 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
1305 if (JSON_TOKEN_ERROR
== token
) {
1306 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
1307 return JSON_ERROR_FATAL
;
1309 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
1310 if (0 == value_len
% 2 && (use_default
||
1311 (value_len
> 2 && value
[0] == '\"' && value
[value_len
- 1] == '\"'))) {
1313 // The default value doesn't have quotes around it
1317 size_t octets
= value_len
/ 2;
1318 init_struct(octets
);
1319 for (size_t i
= 0; i
< octets
; ++i
) {
1320 unsigned char upper_nibble
= char_to_hexdigit(value
[2 * i
]);
1321 unsigned char lower_nibble
= char_to_hexdigit(value
[2 * i
+ 1]);
1322 if (upper_nibble
<= 0x0F && lower_nibble
<= 0x0F) {
1323 val_ptr
->octets_ptr
[i
] = (upper_nibble
<< 4) | lower_nibble
;
1332 return JSON_ERROR_INVALID_TOKEN
;
1336 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "octetstring");
1340 return JSON_ERROR_FATAL
;
1345 // octetstring element class
1347 OCTETSTRING_ELEMENT::OCTETSTRING_ELEMENT(boolean par_bound_flag
,
1348 OCTETSTRING
& par_str_val
, int par_octet_pos
)
1349 : bound_flag(par_bound_flag
), str_val(par_str_val
), octet_pos(par_octet_pos
)
1353 OCTETSTRING_ELEMENT
& OCTETSTRING_ELEMENT::operator=
1354 (const OCTETSTRING
& other_value
)
1356 other_value
.must_bound("Assignment of an unbound octetstring value.");
1357 if(other_value
.val_ptr
->n_octets
!= 1)
1358 TTCN_error("Assignment of an octetstring "
1359 "with length other than 1 to an octetstring element.");
1361 str_val
.copy_value();
1362 str_val
.val_ptr
->octets_ptr
[octet_pos
] = other_value
.val_ptr
->octets_ptr
[0];
1366 OCTETSTRING_ELEMENT
& OCTETSTRING_ELEMENT::operator=
1367 (const OCTETSTRING_ELEMENT
& other_value
)
1369 other_value
.must_bound("Assignment of an unbound octetstring element.");
1370 if (&other_value
!= this) {
1372 str_val
.copy_value();
1373 str_val
.val_ptr
->octets_ptr
[octet_pos
] =
1374 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1379 boolean
OCTETSTRING_ELEMENT::operator==(const OCTETSTRING
& other_value
) const
1381 must_bound("Unbound left operand of octetstring element comparison.");
1382 other_value
.must_bound("Unbound right operand of octetstring comparison.");
1383 if(other_value
.val_ptr
->n_octets
!= 1) return FALSE
;
1384 return str_val
.val_ptr
->octets_ptr
[octet_pos
] ==
1385 other_value
.val_ptr
->octets_ptr
[0];
1388 boolean
OCTETSTRING_ELEMENT::operator==
1389 (const OCTETSTRING_ELEMENT
& other_value
) const
1391 must_bound("Unbound left operand of octetstring element comparison.");
1392 other_value
.must_bound("Unbound right operand of octetstring element "
1394 return str_val
.val_ptr
->octets_ptr
[octet_pos
] ==
1395 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1398 OCTETSTRING
OCTETSTRING_ELEMENT::operator+(const OCTETSTRING
& other_value
) const
1400 must_bound("Unbound left operand of octetstring element concatenation.");
1401 other_value
.must_bound("Unbound right operand of octetstring concatenation.");
1402 OCTETSTRING
ret_val(other_value
.val_ptr
->n_octets
+ 1);
1403 ret_val
.val_ptr
->octets_ptr
[0] = str_val
.val_ptr
->octets_ptr
[octet_pos
];
1404 memcpy(ret_val
.val_ptr
->octets_ptr
+ 1,
1405 other_value
.val_ptr
->octets_ptr
, other_value
.val_ptr
->n_octets
);
1409 OCTETSTRING
OCTETSTRING_ELEMENT::operator+
1410 (const OCTETSTRING_ELEMENT
& other_value
) const
1412 must_bound("Unbound left operand of octetstring element concatenation.");
1413 other_value
.must_bound("Unbound right operand of octetstring element "
1415 unsigned char result
[2];
1416 result
[0] = str_val
.val_ptr
->octets_ptr
[octet_pos
];
1417 result
[1] = other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1418 return OCTETSTRING(2, result
);
1421 OCTETSTRING
OCTETSTRING_ELEMENT::operator~() const
1423 must_bound("Unbound octetstring element operand of operator not4b.");
1424 unsigned char result
= ~str_val
.val_ptr
->octets_ptr
[octet_pos
];
1425 return OCTETSTRING(1, &result
);
1428 OCTETSTRING
OCTETSTRING_ELEMENT::operator&(const OCTETSTRING
& other_value
) const
1430 must_bound("Left operand of operator and4b is an unbound octetstring "
1432 other_value
.must_bound("Right operand of operator and4b is an unbound "
1433 "octetstring value.");
1434 if (other_value
.val_ptr
->n_octets
!= 1)
1435 TTCN_error("The octetstring "
1436 "operands of operator and4b 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 and4b is an unbound octetstring "
1447 other_value
.must_bound("Right operand of operator and4b 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 or4b is an unbound octetstring "
1458 other_value
.must_bound("Right operand of operator or4b is an unbound "
1459 "octetstring value.");
1460 if (other_value
.val_ptr
->n_octets
!= 1)
1461 TTCN_error("The octetstring "
1462 "operands of operator or4b 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 or4b is an unbound octetstring "
1473 other_value
.must_bound("Right operand of operator or4b 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 OCTETSTRING
OCTETSTRING_ELEMENT::operator^(const OCTETSTRING
& other_value
) const
1482 must_bound("Left operand of operator xor4b is an unbound octetstring "
1484 other_value
.must_bound("Right operand of operator xor4b is an unbound "
1485 "octetstring value.");
1486 if (other_value
.val_ptr
->n_octets
!= 1)
1487 TTCN_error("The octetstring "
1488 "operands of operator xor4b must have the same length.");
1489 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] ^
1490 other_value
.val_ptr
->octets_ptr
[0];
1491 return OCTETSTRING(1, &result
);
1494 OCTETSTRING
OCTETSTRING_ELEMENT::operator^
1495 (const OCTETSTRING_ELEMENT
& other_value
) const
1497 must_bound("Left operand of operator xor4b is an unbound octetstring "
1499 other_value
.must_bound("Right operand of operator xor4b is an unbound "
1500 "octetstring element.");
1501 unsigned char result
= str_val
.val_ptr
->octets_ptr
[octet_pos
] ^
1502 other_value
.str_val
.val_ptr
->octets_ptr
[other_value
.octet_pos
];
1503 return OCTETSTRING(1, &result
);
1506 unsigned char OCTETSTRING_ELEMENT::get_octet() const
1508 return str_val
.val_ptr
->octets_ptr
[octet_pos
];
1511 void OCTETSTRING_ELEMENT::log() const
1514 unsigned char octet
= str_val
.val_ptr
->octets_ptr
[octet_pos
];
1515 TTCN_Logger::log_char('\'');
1516 TTCN_Logger::log_octet(octet
);
1517 TTCN_Logger::log_event_str("'O");
1518 if (TTCN_Logger::is_printable(octet
)) {
1519 TTCN_Logger::log_event_str(" (\"");
1520 TTCN_Logger::log_char_escaped(octet
);
1521 TTCN_Logger::log_event_str("\")");
1523 } else TTCN_Logger::log_event_unbound();
1526 // octetstring template class
1528 void OCTETSTRING_template::clean_up()
1530 switch (template_selection
) {
1532 case COMPLEMENTED_LIST
:
1533 delete [] value_list
.list_value
;
1535 case STRING_PATTERN
:
1536 if (pattern_value
->ref_count
> 1) pattern_value
->ref_count
--;
1537 else if (pattern_value
->ref_count
== 1) Free(pattern_value
);
1538 else TTCN_error("Internal error: Invalid reference counter in an "
1539 "octetstring pattern.");
1542 if (dec_match
->ref_count
> 1) {
1543 dec_match
->ref_count
--;
1545 else if (dec_match
->ref_count
== 1) {
1546 delete dec_match
->instance
;
1550 TTCN_error("Internal error: Invalid reference counter in a "
1551 "decoded content match.");
1557 template_selection
= UNINITIALIZED_TEMPLATE
;
1560 void OCTETSTRING_template::copy_template
1561 (const OCTETSTRING_template
& other_value
)
1563 switch (other_value
.template_selection
) {
1564 case SPECIFIC_VALUE
:
1565 single_value
= other_value
.single_value
;
1572 case COMPLEMENTED_LIST
:
1573 value_list
.n_values
= other_value
.value_list
.n_values
;
1574 value_list
.list_value
= new OCTETSTRING_template
[value_list
.n_values
];
1575 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1576 value_list
.list_value
[i
].copy_template(
1577 other_value
.value_list
.list_value
[i
]);
1579 case STRING_PATTERN
:
1580 pattern_value
= other_value
.pattern_value
;
1581 pattern_value
->ref_count
++;
1584 dec_match
= other_value
.dec_match
;
1585 dec_match
->ref_count
++;
1588 TTCN_error("Copying an uninitialized/unsupported octetstring template.");
1590 set_selection(other_value
);
1594 This is the same algorithm that match_array uses
1595 to match 'record of' types.
1596 The only differences are: how two elements are matched and
1597 how an asterisk or ? is identified in the template
1599 boolean
OCTETSTRING_template::match_pattern(
1600 const octetstring_pattern_struct
*string_pattern
,
1601 const OCTETSTRING::octetstring_struct
*string_value
)
1603 // the empty pattern matches the empty octetstring only
1604 if (string_pattern
->n_elements
== 0) return string_value
->n_octets
== 0;
1606 int value_index
= 0;
1607 unsigned int template_index
= 0;
1608 int last_asterisk
= -1;
1609 int last_value_to_asterisk
= -1;
1610 //this variable is used to speed up the function
1611 unsigned short pattern_element
;
1615 pattern_element
= string_pattern
->elements_ptr
[template_index
];
1616 if( pattern_element
< 256){
1617 if(string_value
->octets_ptr
[value_index
] == pattern_element
)
1622 if(last_asterisk
== -1) return FALSE
;
1623 template_index
= last_asterisk
+1;
1624 value_index
= ++last_value_to_asterisk
;
1626 } else if(pattern_element
== 256)
1630 }else if(pattern_element
== 257)
1632 last_asterisk
= template_index
++;
1633 last_value_to_asterisk
= value_index
;
1634 } else TTCN_error("Internal error: invalid element in an octetstring "
1637 if(value_index
== string_value
->n_octets
1638 && template_index
== string_pattern
->n_elements
)
1641 }else if (template_index
== string_pattern
->n_elements
)
1643 if(string_pattern
->elements_ptr
[template_index
- 1] == 257)
1646 }else if(last_asterisk
== -1)
1650 template_index
= last_asterisk
+1;
1651 value_index
= ++last_value_to_asterisk
;
1653 }else if(value_index
== string_value
->n_octets
)
1655 while(template_index
< string_pattern
->n_elements
1656 && string_pattern
->elements_ptr
[template_index
] == 257)
1659 return template_index
== string_pattern
->n_elements
;
1664 OCTETSTRING_template::OCTETSTRING_template()
1668 OCTETSTRING_template::OCTETSTRING_template(template_sel other_value
)
1669 : Restricted_Length_Template(other_value
)
1671 check_single_selection(other_value
);
1674 OCTETSTRING_template::OCTETSTRING_template(const OCTETSTRING
& other_value
)
1675 : Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1679 OCTETSTRING_template::OCTETSTRING_template
1680 (const OCTETSTRING_ELEMENT
& other_value
)
1681 : Restricted_Length_Template(SPECIFIC_VALUE
), single_value(other_value
)
1685 OCTETSTRING_template::OCTETSTRING_template
1686 (const OPTIONAL
<OCTETSTRING
>& other_value
)
1688 switch (other_value
.get_selection()) {
1689 case OPTIONAL_PRESENT
:
1690 set_selection(SPECIFIC_VALUE
);
1691 single_value
= (const OCTETSTRING
&)other_value
;
1694 set_selection(OMIT_VALUE
);
1697 TTCN_error("Creating an octetstring template from an unbound optional "
1702 OCTETSTRING_template::OCTETSTRING_template(unsigned int n_elements
,
1703 const unsigned short *pattern_elements
)
1704 : Restricted_Length_Template(STRING_PATTERN
)
1706 pattern_value
= (octetstring_pattern_struct
*)
1707 Malloc(sizeof(octetstring_pattern_struct
) +
1708 (n_elements
- 1) * sizeof(unsigned short));
1709 pattern_value
->ref_count
= 1;
1710 pattern_value
->n_elements
= n_elements
;
1711 memcpy(pattern_value
->elements_ptr
, pattern_elements
,
1712 n_elements
* sizeof(unsigned short));
1715 OCTETSTRING_template::OCTETSTRING_template
1716 (const OCTETSTRING_template
& other_value
)
1717 : Restricted_Length_Template()
1719 copy_template(other_value
);
1722 OCTETSTRING_template::~OCTETSTRING_template()
1727 OCTETSTRING_template
& OCTETSTRING_template::operator=(template_sel other_value
)
1729 check_single_selection(other_value
);
1731 set_selection(other_value
);
1735 OCTETSTRING_template
& OCTETSTRING_template::operator=
1736 (const OCTETSTRING
& other_value
)
1738 other_value
.must_bound("Assignment of an unbound octetstring value to a "
1741 set_selection(SPECIFIC_VALUE
);
1742 single_value
= other_value
;
1746 OCTETSTRING_template
& OCTETSTRING_template::operator=
1747 (const OCTETSTRING_ELEMENT
& other_value
)
1749 other_value
.must_bound("Assignment of an unbound octetstring element to a "
1752 set_selection(SPECIFIC_VALUE
);
1753 single_value
= other_value
;
1757 OCTETSTRING_template
& OCTETSTRING_template::operator=
1758 (const OPTIONAL
<OCTETSTRING
>& other_value
)
1761 switch (other_value
.get_selection()) {
1762 case OPTIONAL_PRESENT
:
1763 set_selection(SPECIFIC_VALUE
);
1764 single_value
= (const OCTETSTRING
&)other_value
;
1767 set_selection(OMIT_VALUE
);
1770 TTCN_error("Assignment of an unbound optional field to an octetstring "
1776 OCTETSTRING_template
& OCTETSTRING_template::operator=
1777 (const OCTETSTRING_template
& other_value
)
1779 if (&other_value
!= this) {
1781 copy_template(other_value
);
1786 OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](int index_value
)
1788 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1789 TTCN_error("Accessing an octetstring element of a non-specific "
1790 "octetstring template.");
1791 return single_value
[index_value
];
1794 OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](const INTEGER
& index_value
)
1796 index_value
.must_bound("Indexing a octetstring value with an unbound "
1798 return (*this)[(int)index_value
];
1801 const OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](int index_value
) const
1803 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1804 TTCN_error("Accessing an octetstring element of a non-specific "
1805 "octetstring template.");
1806 return single_value
[index_value
];
1809 const OCTETSTRING_ELEMENT
OCTETSTRING_template::operator[](const INTEGER
& index_value
) const
1811 index_value
.must_bound("Indexing a octetstring template with an unbound "
1813 return (*this)[(int)index_value
];
1816 boolean
OCTETSTRING_template::match(const OCTETSTRING
& other_value
,
1817 boolean
/* legacy */) const
1819 if (!other_value
.is_bound()) return FALSE
;
1820 if (!match_length(other_value
.val_ptr
->n_octets
)) return FALSE
;
1821 switch (template_selection
) {
1822 case SPECIFIC_VALUE
:
1823 return single_value
== other_value
;
1830 case COMPLEMENTED_LIST
:
1831 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1832 if (value_list
.list_value
[i
].match(other_value
))
1833 return template_selection
== VALUE_LIST
;
1834 return template_selection
== COMPLEMENTED_LIST
;
1835 case STRING_PATTERN
:
1836 return match_pattern(pattern_value
, other_value
.val_ptr
);
1837 case DECODE_MATCH
: {
1838 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL
, TTCN_EncDec::EB_WARNING
);
1839 TTCN_EncDec::clear_error();
1840 TTCN_Buffer
buff(other_value
);
1841 boolean ret_val
= dec_match
->instance
->match(buff
);
1842 TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL
,TTCN_EncDec::EB_DEFAULT
);
1843 TTCN_EncDec::clear_error();
1846 TTCN_error("Matching an uninitialized/unsupported octetstring template.");
1851 const OCTETSTRING
& OCTETSTRING_template::valueof() const
1853 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
1854 TTCN_error("Performing a valueof or send operation on a non-specific "
1855 "octetstring template.");
1856 return single_value
;
1859 int OCTETSTRING_template::lengthof() const
1862 boolean has_any_or_none
;
1864 TTCN_error("Performing lengthof() operation on a octetstring template "
1865 "which has an ifpresent attribute.");
1866 switch (template_selection
)
1868 case SPECIFIC_VALUE
:
1869 min_length
= single_value
.lengthof();
1870 has_any_or_none
= FALSE
;
1873 TTCN_error("Performing lengthof() operation on an octetstring template "
1874 "containing omit value.");
1878 has_any_or_none
= TRUE
; // max. length is infinity
1882 // error if any element does not have length or the lengths differ
1883 if (value_list
.n_values
<1)
1884 TTCN_error("Internal error: "
1885 "Performing lengthof() operation on an octetstring template "
1886 "containing an empty list.");
1887 int item_length
= value_list
.list_value
[0].lengthof();
1888 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
1889 if (value_list
.list_value
[i
].lengthof()!=item_length
)
1890 TTCN_error("Performing lengthof() operation on an octetstring template "
1891 "containing a value list with different lengths.");
1893 min_length
= item_length
;
1894 has_any_or_none
= FALSE
;
1897 case COMPLEMENTED_LIST
:
1898 TTCN_error("Performing lengthof() operation on an octetstring template "
1899 "containing complemented list.");
1900 case STRING_PATTERN
:
1902 has_any_or_none
= FALSE
; // TRUE if * chars in the pattern
1903 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++)
1905 if (pattern_value
->elements_ptr
[i
] < 257) min_length
++;
1906 else has_any_or_none
= TRUE
; // case of * character
1910 TTCN_error("Performing lengthof() operation on an "
1911 "uninitialized/unsupported octetstring template.");
1913 return check_section_is_single(min_length
, has_any_or_none
,
1914 "length", "an", "octetstring template");
1917 void OCTETSTRING_template::set_type(template_sel template_type
,
1918 unsigned int list_length
)
1920 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
&&
1921 template_type
!= DECODE_MATCH
)
1922 TTCN_error("Setting an invalid type for an octetstring template.");
1924 set_selection(template_type
);
1925 if (template_type
!= DECODE_MATCH
) {
1926 value_list
.n_values
= list_length
;
1927 value_list
.list_value
= new OCTETSTRING_template
[list_length
];
1931 OCTETSTRING_template
& OCTETSTRING_template::list_item(unsigned int list_index
)
1933 if (template_selection
!= VALUE_LIST
&&
1934 template_selection
!= COMPLEMENTED_LIST
)
1935 TTCN_error("Accessing a list element of a non-list octetstring template.");
1936 if (list_index
>= value_list
.n_values
)
1937 TTCN_error("Index overflow in an octetstring value list template.");
1938 return value_list
.list_value
[list_index
];
1941 void OCTETSTRING_template::set_decmatch(Dec_Match_Interface
* new_instance
)
1943 if (template_selection
!= DECODE_MATCH
) {
1944 TTCN_error("Setting the decoded content matching mechanism of a non-decmatch "
1945 "octetstring template.");
1947 dec_match
= new decmatch_struct
;
1948 dec_match
->ref_count
= 1;
1949 dec_match
->instance
= new_instance
;
1952 void OCTETSTRING_template::log() const
1954 switch (template_selection
) {
1955 case SPECIFIC_VALUE
:
1958 case COMPLEMENTED_LIST
:
1959 TTCN_Logger::log_event_str("complement ");
1962 TTCN_Logger::log_char('(');
1963 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
1964 if (i
> 0) TTCN_Logger::log_event_str(", ");
1965 value_list
.list_value
[i
].log();
1967 TTCN_Logger::log_char(')');
1969 case STRING_PATTERN
:
1970 TTCN_Logger::log_char('\'');
1971 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++) {
1972 unsigned short pattern
= pattern_value
->elements_ptr
[i
];
1973 if (pattern
< 256) TTCN_Logger::log_octet(pattern
);
1974 else if (pattern
== 256) TTCN_Logger::log_char('?');
1975 else if (pattern
== 257) TTCN_Logger::log_char('*');
1976 else TTCN_Logger::log_event_str("<unknown>");
1978 TTCN_Logger::log_event_str("'O");
1981 TTCN_Logger::log_event_str("decmatch ");
1982 dec_match
->instance
->log();
1992 void OCTETSTRING_template::log_match(const OCTETSTRING
& match_value
,
1993 boolean
/* legacy */) const
1995 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
1996 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
1997 TTCN_Logger::print_logmatch_buffer();
1998 TTCN_Logger::log_event_str(" := ");
2001 TTCN_Logger::log_event_str(" with ");
2003 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
2004 else TTCN_Logger::log_event_str(" unmatched");
2007 void OCTETSTRING_template::set_param(Module_Param
& param
) {
2008 param
.basic_check(Module_Param::BC_TEMPLATE
|Module_Param::BC_LIST
, "octetstring template");
2009 Module_Param_Ptr mp
= ¶m
;
2010 if (param
.get_type() == Module_Param::MP_Reference
) {
2011 mp
= param
.get_referenced_param();
2013 switch (mp
->get_type()) {
2014 case Module_Param::MP_Omit
:
2017 case Module_Param::MP_Any
:
2020 case Module_Param::MP_AnyOrNone
:
2021 *this = ANY_OR_OMIT
;
2023 case Module_Param::MP_List_Template
:
2024 case Module_Param::MP_ComplementList_Template
: {
2025 OCTETSTRING_template temp
;
2026 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
2027 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
2028 for (size_t i
=0; i
<mp
->get_size(); i
++) {
2029 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
2033 case Module_Param::MP_Octetstring
:
2034 *this = OCTETSTRING(mp
->get_string_size(), (unsigned char*)mp
->get_string_data());
2036 case Module_Param::MP_Octetstring_Template
:
2037 *this = OCTETSTRING_template(mp
->get_string_size(), (unsigned short*)mp
->get_string_data());
2039 case Module_Param::MP_Expression
:
2040 if (mp
->get_expr_type() == Module_Param::EXPR_CONCATENATE
) {
2041 OCTETSTRING operand1
, operand2
;
2042 operand1
.set_param(*mp
->get_operand1());
2043 operand2
.set_param(*mp
->get_operand2());
2044 *this = operand1
+ operand2
;
2047 param
.expr_type_error("a bitstring");
2051 param
.type_error("octetstring template");
2053 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
2054 if (param
.get_length_restriction() != NULL
) {
2055 set_length_range(param
);
2058 set_length_range(*mp
);
2062 Module_Param
* OCTETSTRING_template::get_param(Module_Param_Name
& param_name
) const
2064 Module_Param
* mp
= NULL
;
2065 switch (template_selection
) {
2066 case UNINITIALIZED_TEMPLATE
:
2067 mp
= new Module_Param_Unbound();
2070 mp
= new Module_Param_Omit();
2073 mp
= new Module_Param_Any();
2076 mp
= new Module_Param_AnyOrNone();
2078 case SPECIFIC_VALUE
:
2079 mp
= single_value
.get_param(param_name
);
2082 case COMPLEMENTED_LIST
: {
2083 if (template_selection
== VALUE_LIST
) {
2084 mp
= new Module_Param_List_Template();
2087 mp
= new Module_Param_ComplementList_Template();
2089 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
2090 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
2093 case STRING_PATTERN
: {
2094 unsigned short* val_cpy
= (unsigned short*)Malloc(pattern_value
->n_elements
*
2095 sizeof(unsigned short));
2096 memcpy(val_cpy
, pattern_value
->elements_ptr
, pattern_value
->n_elements
*
2097 sizeof(unsigned short));
2098 mp
= new Module_Param_Octetstring_Template(pattern_value
->n_elements
, val_cpy
);
2101 mp
->error("Referencing a decoded content matching template is not supported.");
2107 mp
->set_ifpresent();
2109 mp
->set_length_restriction(get_length_range());
2113 void OCTETSTRING_template::encode_text(Text_Buf
& text_buf
) const
2115 encode_text_restricted(text_buf
);
2116 switch (template_selection
) {
2121 case SPECIFIC_VALUE
:
2122 single_value
.encode_text(text_buf
);
2125 case COMPLEMENTED_LIST
:
2126 text_buf
.push_int(value_list
.n_values
);
2127 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2128 value_list
.list_value
[i
].encode_text(text_buf
);
2130 case STRING_PATTERN
:
2131 text_buf
.push_int(pattern_value
->n_elements
);
2132 for (unsigned int i
= 0; i
< pattern_value
->n_elements
; i
++)
2133 text_buf
.push_int(pattern_value
->elements_ptr
[i
]);
2136 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
2137 "octetstring template.");
2141 void OCTETSTRING_template::decode_text(Text_Buf
& text_buf
)
2144 decode_text_restricted(text_buf
);
2145 switch (template_selection
) {
2150 case SPECIFIC_VALUE
:
2151 single_value
.decode_text(text_buf
);
2154 case COMPLEMENTED_LIST
:
2155 value_list
.n_values
= text_buf
.pull_int().get_val();
2156 value_list
.list_value
= new OCTETSTRING_template
[value_list
.n_values
];
2157 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
2158 value_list
.list_value
[i
].decode_text(text_buf
);
2160 case STRING_PATTERN
: {
2161 unsigned int n_elements
= text_buf
.pull_int().get_val();
2162 pattern_value
= (octetstring_pattern_struct
*)
2163 Malloc(sizeof(octetstring_pattern_struct
) + (n_elements
- 1) *
2164 sizeof(unsigned short));
2165 pattern_value
->ref_count
= 1;
2166 pattern_value
->n_elements
= n_elements
;
2167 for (unsigned int i
= 0; i
< n_elements
; i
++)
2168 pattern_value
->elements_ptr
[i
] = text_buf
.pull_int().get_val();
2171 TTCN_error("Text decoder: An unknown/unsupported selection was "
2172 "received for an octetstring template.");
2176 boolean
OCTETSTRING_template::is_present(boolean legacy
/* = FALSE */) const
2178 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
2179 return !match_omit(legacy
);
2182 boolean
OCTETSTRING_template::match_omit(boolean legacy
/* = FALSE */) const
2184 if (is_ifpresent
) return TRUE
;
2185 switch (template_selection
) {
2190 case COMPLEMENTED_LIST
:
2192 // legacy behavior: 'omit' can appear in the value/complement list
2193 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
2194 if (value_list
.list_value
[i
].match_omit())
2195 return template_selection
==VALUE_LIST
;
2196 return template_selection
==COMPLEMENTED_LIST
;
2198 // else fall through
2205 #ifndef TITAN_RUNTIME_2
2206 void OCTETSTRING_template::check_restriction(template_res t_res
, const char* t_name
,
2207 boolean legacy
/* = FALSE */) const
2209 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
2210 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
2212 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
2215 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
2216 template_selection
==SPECIFIC_VALUE
)) return;
2219 if (!match_omit(legacy
)) return;
2224 TTCN_error("Restriction `%s' on template of type %s violated.",
2225 get_res_name(t_res
), t_name
? t_name
: "octetstring");