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
18 * Szabo, Janos Zoltan – initial implementation
22 ******************************************************************************/
25 #include "../common/dbgnew.hh"
28 #include "../common/static_check.h"
31 static const size_t MIN_COMPONENTS
= 2;
33 struct OBJID::objid_struct
{
34 unsigned int ref_count
;
35 int n_components
; ///< number of elements in \a components_ptr (min. 2)
36 int overflow_idx
; ///< index of the first overflow, or -1
37 objid_element components_ptr
[MIN_COMPONENTS
];
40 #define OBJID_FMT "%u"
41 //#define OBJID_FMT "%lu"
43 void OBJID::init_struct(int n_components
)
45 if (n_components
< 0) {
47 TTCN_error("Initializing an objid value with a negative number of "
50 // TODO check n_components >= 2
51 val_ptr
= (objid_struct
*)Malloc(sizeof(objid_struct
)
52 + (n_components
- MIN_COMPONENTS
) * sizeof(objid_element
));
53 val_ptr
->ref_count
= 1;
54 val_ptr
->n_components
= n_components
;
55 val_ptr
->overflow_idx
= -1;
58 void OBJID::copy_value()
60 if (val_ptr
!= NULL
&& val_ptr
->ref_count
> 1) {
61 objid_struct
*old_ptr
= val_ptr
;
63 init_struct(old_ptr
->n_components
); // val_ptr reallocated
64 memcpy(val_ptr
->components_ptr
, old_ptr
->components_ptr
,
65 old_ptr
->n_components
* sizeof(objid_element
));
66 val_ptr
->overflow_idx
= old_ptr
->overflow_idx
;
70 void OBJID::clean_up()
72 if (val_ptr
!= NULL
) {
73 if (val_ptr
->ref_count
> 1) val_ptr
->ref_count
--;
74 else if (val_ptr
->ref_count
== 1) Free(val_ptr
);
75 else TTCN_error("Internal error: Invalid reference counter in an objid "
83 val_ptr
= NULL
; // unbound
86 OBJID::OBJID(int init_n_components
, ...)
88 init_struct(init_n_components
);
90 va_start(ap
, init_n_components
);
91 for (int i
= 0; i
< init_n_components
; i
++) {
92 val_ptr
->components_ptr
[i
] = va_arg(ap
, objid_element
);
98 OBJID::OBJID(int init_n_components
, const objid_element
*init_components
)
100 init_struct(init_n_components
);
101 memcpy(val_ptr
->components_ptr
, init_components
, init_n_components
*
102 sizeof(objid_element
));
105 OBJID::OBJID(const OBJID
& other_value
)
106 : Base_Type(other_value
)
108 if (other_value
.val_ptr
== NULL
)
109 TTCN_error("Copying an unbound objid value.");
110 val_ptr
= other_value
.val_ptr
;
111 val_ptr
->ref_count
++;
119 OBJID
& OBJID::operator=(const OBJID
& other_value
)
121 if (other_value
.val_ptr
== NULL
)
122 TTCN_error("Assignment of an unbound objid value.");
123 if (&other_value
!= this) {
125 val_ptr
= other_value
.val_ptr
;
126 val_ptr
->ref_count
++;
131 boolean
OBJID::operator==(const OBJID
& other_value
) const
133 if (val_ptr
== NULL
) TTCN_error("The left operand of comparison is an "
134 "unbound objid value.");
135 if (other_value
.val_ptr
== NULL
) TTCN_error("The right operand of comparison "
136 "is an unbound objid value.");
137 if (val_ptr
->n_components
!= other_value
.val_ptr
->n_components
) return FALSE
;
138 if (val_ptr
->overflow_idx
!= other_value
.val_ptr
->overflow_idx
) return FALSE
;
139 return !memcmp(val_ptr
->components_ptr
,
140 other_value
.val_ptr
->components_ptr
,
141 val_ptr
->n_components
* sizeof(objid_element
));
144 OBJID::objid_element
& OBJID::operator[](int index_value
)
146 if (val_ptr
== NULL
) {
147 if (index_value
!= 0)
148 TTCN_error("Accessing a component of an unbound objid value.");
150 return val_ptr
->components_ptr
[0];
152 if (index_value
< 0) TTCN_error("Accessing an objid component using "
153 "a negative index (%d).", index_value
);
154 int n_components
= val_ptr
->n_components
;
155 if (index_value
> n_components
) TTCN_error("Index overflow when accessing "
156 "an objid component: the index is %d, but the value has only %d "
157 "components.", index_value
, n_components
);
158 else if (index_value
== n_components
) {
159 if (val_ptr
->ref_count
== 1) {
160 val_ptr
= (objid_struct
*)
161 Realloc(val_ptr
, sizeof(objid_struct
)
162 + n_components
* sizeof(objid_element
));
163 val_ptr
->n_components
++;
165 objid_struct
*old_ptr
= val_ptr
;
166 old_ptr
->ref_count
--;
167 init_struct(n_components
+ 1);
168 memcpy(val_ptr
->components_ptr
, old_ptr
->components_ptr
,
169 n_components
* sizeof(objid_element
));
172 return val_ptr
->components_ptr
[index_value
];
176 OBJID::objid_element
OBJID::operator[](int index_value
) const
179 TTCN_error("Accessing a component of an unbound objid value.");
181 TTCN_error("Accessing an objid component using a negative index (%d).",
183 if (index_value
>= val_ptr
->n_components
) TTCN_error("Index overflow when "
184 "accessing an objid component: the index is %d, but the value has only %d "
185 "components.", index_value
, val_ptr
->n_components
);
186 return val_ptr
->components_ptr
[index_value
];
189 int OBJID::size_of() const
192 TTCN_error("Getting the size of an unbound objid value.");
193 return val_ptr
->n_components
;
196 OBJID::operator const objid_element
*() const
199 TTCN_error("Casting an unbound objid value to const int*.");
200 return val_ptr
->components_ptr
;
203 OBJID::objid_element
OBJID::from_INTEGER(const INTEGER
& p_int
)
205 int_val_t i_val
= p_int
.get_val();
206 if (i_val
.is_negative()) {
207 TTCN_error("An OBJECT IDENTIFIER component cannot be negative");
209 if (!i_val
.is_native()) {
210 TTCN_error("The value of an OBJECT IDENTIFIER component cannot exceed %u",
213 return (OBJID::objid_element
)i_val
.get_val();
216 void OBJID::log() const
218 if (val_ptr
!= NULL
) {
219 TTCN_Logger::log_event_str("objid { ");
220 for (int i
= 0; i
< val_ptr
->n_components
; i
++) {
221 if (i
== val_ptr
->overflow_idx
) {
222 TTCN_Logger::log_event_str("overflow:");
225 TTCN_Logger::log_event(OBJID_FMT
" ", val_ptr
->components_ptr
[i
]);
227 TTCN_Logger::log_char('}');
228 } else TTCN_Logger::log_event_unbound();
231 void OBJID::set_param(Module_Param
& param
) {
232 param
.basic_check(Module_Param::BC_VALUE
, "objid value");
233 Module_Param_Ptr mp
= ¶m
;
234 if (param
.get_type() == Module_Param::MP_Reference
) {
235 mp
= param
.get_referenced_param();
237 if (mp
->get_type()!=Module_Param::MP_Objid
) param
.type_error("objid value");
238 if (sizeof(objid_element
)!=sizeof(int)) TTCN_error("Internal error: OBJID::set_param()");
240 init_struct(mp
->get_string_size());
241 memcpy(val_ptr
->components_ptr
, mp
->get_string_data(), val_ptr
->n_components
* sizeof(objid_element
));
244 Module_Param
* OBJID::get_param(Module_Param_Name
& /* param_name */) const
247 return new Module_Param_Unbound();
249 int* val_cpy
= (int *)Malloc(val_ptr
->n_components
);
250 memcpy(val_cpy
, val_ptr
->components_ptr
, val_ptr
->n_components
* sizeof(int));
251 return new Module_Param_Objid(val_ptr
->n_components
, val_cpy
);
254 void OBJID::encode_text(Text_Buf
& text_buf
) const
257 TTCN_error("Text encoder: Encoding an unbound objid value.");
258 text_buf
.push_int(val_ptr
->n_components
);
259 for (int i
= 0; i
< val_ptr
->n_components
; i
++)
260 text_buf
.push_int(val_ptr
->components_ptr
[i
]);
263 void OBJID::decode_text(Text_Buf
& text_buf
)
265 int n_components
= text_buf
.pull_int().get_val();
266 if (n_components
< 0) TTCN_error("Text decoder: Negative number of "
267 "components was received for an objid value.");
269 init_struct(n_components
);
270 for (int i
= 0; i
< n_components
; i
++)
271 val_ptr
->components_ptr
[i
] = text_buf
.pull_int().get_val();
274 void OBJID::encode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
275 TTCN_EncDec::coding_t p_coding
, ...) const
278 va_start(pvar
, p_coding
);
280 case TTCN_EncDec::CT_BER
: {
281 TTCN_EncDec_ErrorContext
ec("While BER-encoding type '%s': ", p_td
.name
);
282 unsigned BER_coding
=va_arg(pvar
, unsigned);
283 BER_encode_chk_coding(BER_coding
);
284 ASN_BER_TLV_t
*tlv
=BER_encode_TLV(p_td
, BER_coding
);
285 tlv
->put_in_buffer(p_buf
);
286 ASN_BER_TLV_t::destruct(tlv
);
288 case TTCN_EncDec::CT_RAW
: {
289 TTCN_EncDec_ErrorContext
ec("While RAW-encoding type '%s': ", p_td
.name
);
290 TTCN_EncDec_ErrorContext::error_internal
291 ("No RAW descriptor available for type '%s'.", p_td
.name
);
293 case TTCN_EncDec::CT_XER
: {
294 TTCN_EncDec_ErrorContext
ec("While XER-encoding type '%s': ", p_td
.name
);
295 unsigned XER_coding
=va_arg(pvar
, unsigned);
296 XER_encode(*p_td
.xer
, p_buf
, XER_coding
, 0, 0);
298 case TTCN_EncDec::CT_JSON
: {
299 TTCN_EncDec_ErrorContext
ec("While JSON-encoding type '%s': ", p_td
.name
);
301 TTCN_EncDec_ErrorContext::error_internal
302 ("No JSON descriptor available for type '%s'.", p_td
.name
);
303 JSON_Tokenizer
tok(va_arg(pvar
, int) != 0);
304 JSON_encode(p_td
, tok
);
305 p_buf
.put_s(tok
.get_buffer_length(), (const unsigned char*)tok
.get_buffer());
308 TTCN_error("Unknown coding method requested to encode type '%s'",
314 void OBJID::decode(const TTCN_Typedescriptor_t
& p_td
, TTCN_Buffer
& p_buf
,
315 TTCN_EncDec::coding_t p_coding
, ...)
318 va_start(pvar
, p_coding
);
320 case TTCN_EncDec::CT_BER
: {
321 TTCN_EncDec_ErrorContext
ec("While BER-decoding type '%s': ", p_td
.name
);
322 unsigned L_form
=va_arg(pvar
, unsigned);
324 BER_decode_str2TLV(p_buf
, tlv
, L_form
);
325 BER_decode_TLV(p_td
, tlv
, L_form
);
326 if(tlv
.isComplete
) p_buf
.increase_pos(tlv
.get_len());
328 case TTCN_EncDec::CT_RAW
: {
329 TTCN_EncDec_ErrorContext
ec("While RAW-decoding type '%s': ", p_td
.name
);
330 TTCN_EncDec_ErrorContext::error_internal
331 ("No RAW descriptor available for type '%s'.", p_td
.name
);
333 case TTCN_EncDec::CT_XER
: {
334 TTCN_EncDec_ErrorContext
ec("While XER-decoding type '%s': ", p_td
.name
);
335 unsigned XER_coding
=va_arg(pvar
, unsigned);
336 XmlReaderWrap
reader(p_buf
);
337 int success
= reader
.Read();
338 for (; success
==1; success
=reader
.Read()) {
339 int type
= reader
.NodeType();
340 if (type
==XML_READER_TYPE_ELEMENT
)
343 XER_decode(*p_td
.xer
, reader
, XER_coding
, XER_NONE
, 0);
344 size_t bytes
= reader
.ByteConsumed();
345 p_buf
.set_pos(bytes
);
347 case TTCN_EncDec::CT_JSON
: {
348 TTCN_EncDec_ErrorContext
ec("While JSON-decoding type '%s': ", p_td
.name
);
350 TTCN_EncDec_ErrorContext::error_internal
351 ("No JSON descriptor available for type '%s'.", p_td
.name
);
352 JSON_Tokenizer
tok((const char*)p_buf
.get_data(), p_buf
.get_len());
353 if(JSON_decode(p_td
, tok
, false)<0)
354 ec
.error(TTCN_EncDec::ET_INCOMPL_MSG
,
355 "Can not decode type '%s', because invalid or incomplete"
356 " message was received"
358 p_buf
.set_pos(tok
.get_buf_pos());
361 TTCN_error("Unknown coding method requested to decode type '%s'",
368 OBJID::BER_encode_TLV(const TTCN_Typedescriptor_t
& p_td
,
369 unsigned p_coding
) const
372 ASN_BER_TLV_t
*new_tlv
=BER_encode_chk_bound(is_bound());
375 switch(p_td
.asnbasetype
) {
376 case TTCN_Typedescriptor_t::OBJID
:
377 if(val_ptr
->n_components
<2)
378 TTCN_EncDec_ErrorContext::error_internal
379 ("OBJID must have at least 2 components.");
380 V_len
=(min_needed_bits(val_ptr
->components_ptr
[0]*40
381 +val_ptr
->components_ptr
[1])+6)/7;
382 for(int i
=2; i
<val_ptr
->n_components
; i
++)
383 V_len
+=(min_needed_bits(val_ptr
->components_ptr
[i
])+6)/7;
385 case TTCN_Typedescriptor_t::ROID
:
386 for(int i
=0; i
<val_ptr
->n_components
; i
++)
387 V_len
+=(min_needed_bits(val_ptr
->components_ptr
[i
])+6)/7;
390 TTCN_EncDec_ErrorContext::error_internal
391 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
393 new_tlv
=ASN_BER_TLV_t::construct(V_len
, NULL
);
394 unsigned char *Vptr
=new_tlv
->V
.str
.Vstr
;
395 for(int i
=0; i
<val_ptr
->n_components
; i
++) {
397 if(i
==0 && p_td
.asnbasetype
==TTCN_Typedescriptor_t::OBJID
) {
398 ul
=val_ptr
->components_ptr
[0]*40+val_ptr
->components_ptr
[1];
401 else ul
=val_ptr
->components_ptr
[i
];
402 size_t noo
=(min_needed_bits(ul
)+6)/7;
403 for(size_t j
=noo
; j
>0; j
--) {
404 Vptr
[j
-1]=(ul
& 0x7F) | 0x80;
411 new_tlv
=ASN_BER_V2TLV(new_tlv
, p_td
, p_coding
);
416 boolean
OBJID::BER_decode_TLV(const TTCN_Typedescriptor_t
& p_td
,
417 const ASN_BER_TLV_t
& p_tlv
,
422 ASN_BER_TLV_t stripped_tlv
;
423 BER_decode_strip_tags(*p_td
.ber
, p_tlv
, L_form
, stripped_tlv
);
424 TTCN_EncDec_ErrorContext
ec("While decoding OBJID type: ");
425 stripped_tlv
.chk_constructed_flag(FALSE
);
426 if (!stripped_tlv
.isComplete
) return FALSE
;
427 if (!stripped_tlv
.V_tlvs_selected
&& stripped_tlv
.V
.str
.Vlen
==0) {
428 ec
.error(TTCN_EncDec::ET_INVAL_MSG
, "Length of V-part is 0.");
431 switch(p_td
.asnbasetype
) {
432 case TTCN_Typedescriptor_t::OBJID
:
433 case TTCN_Typedescriptor_t::ROID
:
436 TTCN_EncDec_ErrorContext::error_internal
437 ("Missing/wrong basetype info for type '%s'.", p_td
.name
);
439 unsigned char *Vptr
=stripped_tlv
.V
.str
.Vstr
;
440 boolean eoc
=FALSE
; // end-of-component
442 unsigned long long ull
=0;
443 STATIC_ASSERT(sizeof(ull
) > sizeof(objid_element
));
445 boolean err_repr
=FALSE
;
446 while (Vptr
< stripped_tlv
.V
.str
.Vstr
+ stripped_tlv
.V
.str
.Vlen
) {
448 if ((*Vptr
& 0x80) && err_repr
==FALSE
) { // not-eoc
449 if (ull
& unsigned_llong_7msb
) {
450 ec
.error(TTCN_EncDec::ET_REPR
,
451 "Value of the #%d component is too big.", i
+1);
458 if (i
==0 && p_td
.asnbasetype
==TTCN_Typedescriptor_t::OBJID
) {
459 // first two component of objid
468 (*this)[1]=(int)(ull
-40*(*this)[0]);
471 else { // other components (>2)
472 // objid_element is UINT/ULONG; the result of the cast is Uxxx_MAX.
473 // It's computed at compile time.
474 if(ull
> ((objid_element
)-1)) {
476 ec
.error(TTCN_EncDec::ET_REPR
,
477 "Value of the #%d component is too big.", i
+1);
478 (*this)[i
]=(objid_element
)-1;
479 // remember the first overflow
480 if (val_ptr
->overflow_idx
< 0) val_ptr
->overflow_idx
= i
;
483 (*this)[i
]=(objid_element
)ull
;
493 ec
.error(TTCN_EncDec::ET_INVAL_MSG
,
494 "The last component (#%d) is unterminated.", i
+1);
499 int OBJID::XER_encode(const XERdescriptor_t
& p_td
,
500 TTCN_Buffer
& p_buf
, unsigned int flavor
, int indent
, embed_values_enc_struct_t
*) const
503 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
504 "Encoding an unbound object identifier value.");
506 int encoded_length
=(int)p_buf
.get_len();
508 flavor
|= SIMPLE_TYPE
;
509 flavor
&= ~XER_RECOF
; // object identifier doesn't care
510 begin_xml(p_td
, p_buf
, flavor
, indent
, false);
512 static char str_buf
[64];
513 for (int i
= 0; i
< val_ptr
->n_components
; ++i
) {
514 // output dot before the second and subsequent components
515 if (i
> 0) p_buf
.put_c('.');
516 // output current component
517 int str_len
= snprintf(str_buf
, sizeof(str_buf
), OBJID_FMT
,
518 val_ptr
->components_ptr
[i
]);
519 if (str_len
< 0 || str_len
>= (int)sizeof(str_buf
)) {
520 TTCN_error("Internal error: system call snprintf() returned "
521 "unexpected status code %d when converting value " OBJID_FMT
,
522 str_len
, val_ptr
->components_ptr
[i
]);
524 else p_buf
.put_s(str_len
, (const unsigned char*)str_buf
);
527 end_xml(p_td
, p_buf
, flavor
, indent
, false);
529 return (int)p_buf
.get_len() - encoded_length
;
532 void OBJID::from_string(char* p_str
)
534 // Count dots to find number of components. (1 dot = 2 components, etc.)
537 for (p
= p_str
; *p
!= 0; ++p
) {
538 if (*p
== '.') ++comps
;
540 // p now points at the end of the string. If it was empty, then there were
541 // no components; compensate the fact that we started at 1.
542 init_struct((p
!= p_str
) ? comps
: 0);
546 for (beg
= p_str
; beg
< p
; ++beg
) {
548 long ret
= strtol(beg
, &end
, 10);
551 // TODO check value for too big ?
552 (*this)[comps
++] = ret
;
553 beg
= end
; // move to the dot; will move past it when incremented
557 int OBJID::XER_decode(const XERdescriptor_t
& p_td
, XmlReaderWrap
& reader
,
558 unsigned int flavor
, unsigned int /*flavor2*/, embed_values_dec_struct_t
*)
560 int exer
= is_exer(flavor
);
561 int success
= reader
.Ok(), depth
= -1;
562 for (; success
== 1; success
= reader
.Read()) {
563 int type
= reader
.NodeType();
564 if (XML_READER_TYPE_ELEMENT
== type
) {
565 verify_name(reader
, p_td
, exer
);
566 depth
= reader
.Depth();
571 char * val
= (char *)reader
.ReadString(); // We own this (writable) string
573 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG
, "Bogus object identifier");
581 for (success
= reader
.Read(); success
== 1; success
= reader
.Read()) {
582 int type
= reader
.NodeType();
583 if (XML_READER_TYPE_END_ELEMENT
== type
) {
584 verify_end(reader
, p_td
, depth
, exer
);
589 return 1; // decode successful
592 int OBJID::JSON_encode(const TTCN_Typedescriptor_t
&, JSON_Tokenizer
& p_tok
) const
595 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND
,
596 "Encoding an unbound object identifier value.");
600 char* objid_str
= mcopystrn("\"", 1);
601 for (int i
= 0; i
< val_ptr
->n_components
; ++i
) {
602 objid_str
= mputprintf(objid_str
, "%s" OBJID_FMT
, (i
> 0 ? "." : ""), val_ptr
->components_ptr
[i
]);
604 objid_str
= mputstrn(objid_str
, "\"", 1);
605 int enc_len
= p_tok
.put_next_token(JSON_TOKEN_STRING
, objid_str
);
610 int OBJID::JSON_decode(const TTCN_Typedescriptor_t
& p_td
, JSON_Tokenizer
& p_tok
, boolean p_silent
)
612 json_token_t token
= JSON_TOKEN_NONE
;
614 size_t value_len
= 0;
615 boolean error
= false;
617 boolean use_default
= p_td
.json
->default_value
&& 0 == p_tok
.get_buffer_length();
619 // No JSON data in the buffer -> use default value
620 value
= (char*)p_td
.json
->default_value
;
621 value_len
= strlen(value
);
623 dec_len
= p_tok
.get_next_token(&token
, &value
, &value_len
);
625 if (JSON_TOKEN_ERROR
== token
) {
626 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_BAD_TOKEN_ERROR
, "");
627 return JSON_ERROR_FATAL
;
629 else if (JSON_TOKEN_STRING
== token
|| use_default
) {
630 if (use_default
|| (value_len
> 2 && value
[0] == '\"' && value
[value_len
- 1] == '\"')) {
632 // The default value doesn't have quotes around it
636 // need a null-terminated string
637 char* value2
= mcopystrn(value
, value_len
);
643 return JSON_ERROR_INVALID_TOKEN
;
647 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG
, JSON_DEC_FORMAT_ERROR
, "string", "object identifier");
651 return JSON_ERROR_FATAL
;
656 void OBJID_template::clean_up()
658 if (template_selection
== VALUE_LIST
||
659 template_selection
== COMPLEMENTED_LIST
) delete [] value_list
.list_value
;
660 template_selection
= UNINITIALIZED_TEMPLATE
;
663 void OBJID_template::copy_template(const OBJID_template
& other_value
)
665 switch (other_value
.template_selection
) {
667 single_value
= other_value
.single_value
;
674 case COMPLEMENTED_LIST
:
675 value_list
.n_values
= other_value
.value_list
.n_values
;
676 value_list
.list_value
= new OBJID_template
[value_list
.n_values
];
677 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
678 value_list
.list_value
[i
].copy_template(
679 other_value
.value_list
.list_value
[i
]);
682 TTCN_error("Copying an uninitialized/unsupported objid template.");
684 set_selection(other_value
);
687 OBJID_template::OBJID_template()
692 OBJID_template::OBJID_template(template_sel other_value
)
693 : Base_Template(other_value
)
695 check_single_selection(other_value
);
698 OBJID_template::OBJID_template(const OBJID
& other_value
)
699 : Base_Template(SPECIFIC_VALUE
), single_value(other_value
)
704 OBJID_template::OBJID_template(const OPTIONAL
<OBJID
>& other_value
)
706 switch (other_value
.get_selection()) {
707 case OPTIONAL_PRESENT
:
708 set_selection(SPECIFIC_VALUE
);
709 single_value
= (const OBJID
&)other_value
;
712 set_selection(OMIT_VALUE
);
715 TTCN_error("Creating an objid template from an unbound optional field.");
719 OBJID_template::OBJID_template(const OBJID_template
& other_value
)
722 copy_template(other_value
);
725 OBJID_template::~OBJID_template()
730 OBJID_template
& OBJID_template::operator=(template_sel other_value
)
732 check_single_selection(other_value
);
734 set_selection(other_value
);
738 OBJID_template
& OBJID_template::operator=(const OBJID
& other_value
)
740 if (!other_value
.is_bound())
741 TTCN_error("Assignment of an unbound objid value to a template.");
743 set_selection(SPECIFIC_VALUE
);
744 single_value
= other_value
;
748 OBJID_template
& OBJID_template::operator=(const OPTIONAL
<OBJID
>& other_value
)
751 switch (other_value
.get_selection()) {
752 case OPTIONAL_PRESENT
:
753 set_selection(SPECIFIC_VALUE
);
754 single_value
= (const OBJID
&)other_value
;
757 set_selection(OMIT_VALUE
);
760 TTCN_error("Assignment of an unbound optional field to an objid template.");
765 OBJID_template
& OBJID_template::operator=(const OBJID_template
& other_value
)
767 if (&other_value
!= this) {
769 copy_template(other_value
);
774 boolean
OBJID_template::match(const OBJID
& other_value
, boolean
/* legacy */) const
776 if (!other_value
.is_bound()) return FALSE
;
777 switch (template_selection
) {
779 return single_value
== other_value
;
786 case COMPLEMENTED_LIST
:
787 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
788 if (value_list
.list_value
[i
].match(other_value
))
789 return template_selection
== VALUE_LIST
;
790 return template_selection
== COMPLEMENTED_LIST
;
792 TTCN_error("Matching with an uninitialized/unsupported objid template.");
797 const OBJID
& OBJID_template::valueof() const
799 if (template_selection
!= SPECIFIC_VALUE
|| is_ifpresent
)
800 TTCN_error("Performing a valueof "
801 "or send operation on a non-specific objid template.");
805 int OBJID_template::size_of() const
807 switch (template_selection
)
810 return single_value
.size_of();
812 TTCN_error("Performing sizeof() operation on an objid template "
813 "containing omit value.");
816 TTCN_error("Performing sizeof() operation on a */? objid template.");
819 if (value_list
.n_values
<1)
820 TTCN_error("Internal error: "
821 "Performing sizeof() operation on an objid template "
822 "containing an empty list.");
823 int item_size
= value_list
.list_value
[0].size_of();
824 for (unsigned int i
= 1; i
< value_list
.n_values
; i
++) {
825 if (value_list
.list_value
[i
].size_of()!=item_size
)
826 TTCN_error("Performing sizeof() operation on an objid template "
827 "containing a value list with different sizes.");
831 case COMPLEMENTED_LIST
:
832 TTCN_error("Performing sizeof() operation on an objid template "
833 "containing complemented list.");
835 TTCN_error("Performing sizeof() operation on an "
836 "uninitialized/unsupported objid template.");
841 void OBJID_template::set_type(template_sel template_type
,
842 unsigned int list_length
)
844 if (template_type
!= VALUE_LIST
&& template_type
!= COMPLEMENTED_LIST
)
845 TTCN_error("Setting an invalid list type for an objid template.");
847 set_selection(template_type
);
848 value_list
.n_values
= list_length
;
849 value_list
.list_value
= new OBJID_template
[list_length
];
852 OBJID_template
& OBJID_template::list_item(unsigned int list_index
)
854 if (template_selection
!= VALUE_LIST
&&
855 template_selection
!= COMPLEMENTED_LIST
)
856 TTCN_error("Accessing a list element of a non-list objid template.");
857 if (list_index
>= value_list
.n_values
)
858 TTCN_error("Index overflow in an objid value list template.");
859 return value_list
.list_value
[list_index
];
862 void OBJID_template::log() const
864 switch (template_selection
) {
868 case COMPLEMENTED_LIST
:
869 TTCN_Logger::log_event_str("complement ");
872 TTCN_Logger::log_char('(');
873 for(unsigned int i
= 0; i
< value_list
.n_values
; i
++) {
874 if (i
> 0) TTCN_Logger::log_event_str(", ");
875 value_list
.list_value
[i
].log();
877 TTCN_Logger::log_char(')');
886 void OBJID_template::log_match(const OBJID
& match_value
,
887 boolean
/* legacy */) const
889 if (TTCN_Logger::VERBOSITY_COMPACT
== TTCN_Logger::get_matching_verbosity()
890 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
891 TTCN_Logger::print_logmatch_buffer();
892 TTCN_Logger::log_event_str(" := ");
895 TTCN_Logger::log_event_str(" with ");
897 if (match(match_value
)) TTCN_Logger::log_event_str(" matched");
898 else TTCN_Logger::log_event_str(" unmatched");
901 void OBJID_template::set_param(Module_Param
& param
) {
902 param
.basic_check(Module_Param::BC_TEMPLATE
, "objid template");
903 Module_Param_Ptr mp
= ¶m
;
904 if (param
.get_type() == Module_Param::MP_Reference
) {
905 mp
= param
.get_referenced_param();
907 switch (mp
->get_type()) {
908 case Module_Param::MP_Omit
:
911 case Module_Param::MP_Any
:
914 case Module_Param::MP_AnyOrNone
:
917 case Module_Param::MP_List_Template
:
918 case Module_Param::MP_ComplementList_Template
: {
920 temp
.set_type(mp
->get_type() == Module_Param::MP_List_Template
?
921 VALUE_LIST
: COMPLEMENTED_LIST
, mp
->get_size());
922 for (size_t i
=0; i
<mp
->get_size(); i
++) {
923 temp
.list_item(i
).set_param(*mp
->get_elem(i
));
927 case Module_Param::MP_Objid
:
928 if (sizeof(OBJID::objid_element
)!=sizeof(int)) TTCN_error("Internal error: OBJID_template::set_param()");
929 *this = OBJID(mp
->get_string_size(), (OBJID::objid_element
*)mp
->get_string_data());
931 //case Module_Param::MP_Objid_Template:
935 param
.type_error("objid template");
937 is_ifpresent
= param
.get_ifpresent() || mp
->get_ifpresent();
940 Module_Param
* OBJID_template::get_param(Module_Param_Name
& param_name
) const
942 Module_Param
* mp
= NULL
;
943 switch (template_selection
) {
944 case UNINITIALIZED_TEMPLATE
:
945 mp
= new Module_Param_Unbound();
948 mp
= new Module_Param_Omit();
951 mp
= new Module_Param_Any();
954 mp
= new Module_Param_AnyOrNone();
957 mp
= single_value
.get_param(param_name
);
960 case COMPLEMENTED_LIST
: {
961 if (template_selection
== VALUE_LIST
) {
962 mp
= new Module_Param_List_Template();
965 mp
= new Module_Param_ComplementList_Template();
967 for (size_t i
= 0; i
< value_list
.n_values
; ++i
) {
968 mp
->add_elem(value_list
.list_value
[i
].get_param(param_name
));
980 void OBJID_template::encode_text(Text_Buf
& text_buf
) const
982 encode_text_base(text_buf
);
983 switch (template_selection
) {
989 single_value
.encode_text(text_buf
);
992 case COMPLEMENTED_LIST
:
993 text_buf
.push_int(value_list
.n_values
);
994 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
995 value_list
.list_value
[i
].encode_text(text_buf
);
998 TTCN_error("Text encoder: Encoding an undefined/unsupported objid "
1003 void OBJID_template::decode_text(Text_Buf
& text_buf
)
1006 decode_text_base(text_buf
);
1007 switch (template_selection
) {
1012 case SPECIFIC_VALUE
:
1013 single_value
.decode_text(text_buf
);
1016 case COMPLEMENTED_LIST
:
1017 value_list
.n_values
= text_buf
.pull_int().get_val();
1018 value_list
.list_value
= new OBJID_template
[value_list
.n_values
];
1019 for (unsigned int i
= 0; i
< value_list
.n_values
; i
++)
1020 value_list
.list_value
[i
].decode_text(text_buf
);
1023 TTCN_error("Text decoder: An unknown/unsupported selection was "
1024 "received for an objid template.");
1028 boolean
OBJID_template::is_present(boolean legacy
/* = FALSE */) const
1030 if (template_selection
==UNINITIALIZED_TEMPLATE
) return FALSE
;
1031 return !match_omit(legacy
);
1034 boolean
OBJID_template::match_omit(boolean legacy
/* = FALSE */) const
1036 if (is_ifpresent
) return TRUE
;
1037 switch (template_selection
) {
1042 case COMPLEMENTED_LIST
:
1044 // legacy behavior: 'omit' can appear in the value/complement list
1045 for (unsigned int i
=0; i
<value_list
.n_values
; i
++)
1046 if (value_list
.list_value
[i
].match_omit())
1047 return template_selection
==VALUE_LIST
;
1048 return template_selection
==COMPLEMENTED_LIST
;
1050 // else fall through
1057 #ifndef TITAN_RUNTIME_2
1058 void OBJID_template::check_restriction(template_res t_res
, const char* t_name
,
1059 boolean legacy
/* = FALSE */) const
1061 if (template_selection
==UNINITIALIZED_TEMPLATE
) return;
1062 switch ((t_name
&&(t_res
==TR_VALUE
))?TR_OMIT
:t_res
) {
1064 if (!is_ifpresent
&& template_selection
==SPECIFIC_VALUE
) return;
1067 if (!is_ifpresent
&& (template_selection
==OMIT_VALUE
||
1068 template_selection
==SPECIFIC_VALUE
)) return;
1071 if (!match_omit(legacy
)) return;
1076 TTCN_error("Restriction `%s' on template of type %s violated.",
1077 get_res_name(t_res
), t_name
? t_name
: "objid");