00d37bab4372bca4e60343e515824218692d264e
[deliverable/titan.core.git] / core / Objid.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "Objid.hh"
9
10 #include "../common/dbgnew.hh"
11 #include <errno.h>
12 #include <limits.h>
13 #include "../common/static_check.h"
14 #include "Integer.hh"
15
16 static const size_t MIN_COMPONENTS = 2;
17
18 struct OBJID::objid_struct {
19 unsigned int ref_count;
20 int n_components; ///< number of elements in \a components_ptr (min. 2)
21 int overflow_idx; ///< index of the first overflow, or -1
22 objid_element components_ptr[MIN_COMPONENTS];
23 };
24
25 #define OBJID_FMT "%u"
26 //#define OBJID_FMT "%lu"
27
28 void OBJID::init_struct(int n_components)
29 {
30 if (n_components < 0) {
31 val_ptr = NULL;
32 TTCN_error("Initializing an objid value with a negative number of "
33 "components.");
34 }
35 // TODO check n_components >= 2
36 val_ptr = (objid_struct*)Malloc(sizeof(objid_struct)
37 + (n_components - MIN_COMPONENTS) * sizeof(objid_element));
38 val_ptr->ref_count = 1;
39 val_ptr->n_components = n_components;
40 val_ptr->overflow_idx = -1;
41 }
42
43 void OBJID::copy_value()
44 {
45 if (val_ptr != NULL && val_ptr->ref_count > 1) {
46 objid_struct *old_ptr = val_ptr;
47 old_ptr->ref_count--;
48 init_struct(old_ptr->n_components); // val_ptr reallocated
49 memcpy(val_ptr->components_ptr, old_ptr->components_ptr,
50 old_ptr->n_components * sizeof(objid_element));
51 val_ptr->overflow_idx = old_ptr->overflow_idx;
52 }
53 }
54
55 void OBJID::clean_up()
56 {
57 if (val_ptr != NULL) {
58 if (val_ptr->ref_count > 1) val_ptr->ref_count--;
59 else if (val_ptr->ref_count == 1) Free(val_ptr);
60 else TTCN_error("Internal error: Invalid reference counter in an objid "
61 "value.");
62 val_ptr = NULL;
63 }
64 }
65
66 OBJID::OBJID()
67 {
68 val_ptr = NULL; // unbound
69 }
70
71 OBJID::OBJID(int init_n_components, ...)
72 {
73 init_struct(init_n_components);
74 va_list ap;
75 va_start(ap, init_n_components);
76 for (int i = 0; i < init_n_components; i++) {
77 val_ptr->components_ptr[i] = va_arg(ap, objid_element);
78 }
79 va_end(ap);
80 }
81
82
83 OBJID::OBJID(int init_n_components, const objid_element *init_components)
84 {
85 init_struct(init_n_components);
86 memcpy(val_ptr->components_ptr, init_components, init_n_components *
87 sizeof(objid_element));
88 }
89
90 OBJID::OBJID(const OBJID& other_value)
91 : Base_Type(other_value)
92 {
93 if (other_value.val_ptr == NULL)
94 TTCN_error("Copying an unbound objid value.");
95 val_ptr = other_value.val_ptr;
96 val_ptr->ref_count++;
97 }
98
99 OBJID::~OBJID()
100 {
101 clean_up();
102 }
103
104 OBJID& OBJID::operator=(const OBJID& other_value)
105 {
106 if (other_value.val_ptr == NULL)
107 TTCN_error("Assignment of an unbound objid value.");
108 if (&other_value != this) {
109 clean_up();
110 val_ptr = other_value.val_ptr;
111 val_ptr->ref_count++;
112 }
113 return *this;
114 }
115
116 boolean OBJID::operator==(const OBJID& other_value) const
117 {
118 if (val_ptr == NULL) TTCN_error("The left operand of comparison is an "
119 "unbound objid value.");
120 if (other_value.val_ptr == NULL) TTCN_error("The right operand of comparison "
121 "is an unbound objid value.");
122 if (val_ptr->n_components != other_value.val_ptr->n_components) return FALSE;
123 if (val_ptr->overflow_idx != other_value.val_ptr->overflow_idx) return FALSE;
124 return !memcmp(val_ptr->components_ptr,
125 other_value.val_ptr->components_ptr,
126 val_ptr->n_components * sizeof(objid_element));
127 }
128
129 OBJID::objid_element& OBJID::operator[](int index_value)
130 {
131 if (val_ptr == NULL) {
132 if (index_value != 0)
133 TTCN_error("Accessing a component of an unbound objid value.");
134 init_struct(1);
135 return val_ptr->components_ptr[0];
136 } else {
137 if (index_value < 0) TTCN_error("Accessing an objid component using "
138 "a negative index (%d).", index_value);
139 int n_components = val_ptr->n_components;
140 if (index_value > n_components) TTCN_error("Index overflow when accessing "
141 "an objid component: the index is %d, but the value has only %d "
142 "components.", index_value, n_components);
143 else if (index_value == n_components) {
144 if (val_ptr->ref_count == 1) {
145 val_ptr = (objid_struct*)
146 Realloc(val_ptr, sizeof(objid_struct)
147 + n_components * sizeof(objid_element));
148 val_ptr->n_components++;
149 } else {
150 objid_struct *old_ptr = val_ptr;
151 old_ptr->ref_count--;
152 init_struct(n_components + 1);
153 memcpy(val_ptr->components_ptr, old_ptr->components_ptr,
154 n_components * sizeof(objid_element));
155 }
156 }
157 return val_ptr->components_ptr[index_value];
158 }
159 }
160
161 OBJID::objid_element OBJID::operator[](int index_value) const
162 {
163 if (val_ptr == NULL)
164 TTCN_error("Accessing a component of an unbound objid value.");
165 if (index_value < 0)
166 TTCN_error("Accessing an objid component using a negative index (%d).",
167 index_value);
168 if (index_value >= val_ptr->n_components) TTCN_error("Index overflow when "
169 "accessing an objid component: the index is %d, but the value has only %d "
170 "components.", index_value, val_ptr->n_components);
171 return val_ptr->components_ptr[index_value];
172 }
173
174 int OBJID::size_of() const
175 {
176 if (val_ptr == NULL)
177 TTCN_error("Getting the size of an unbound objid value.");
178 return val_ptr->n_components;
179 }
180
181 OBJID::operator const objid_element*() const
182 {
183 if (val_ptr == NULL)
184 TTCN_error("Casting an unbound objid value to const int*.");
185 return val_ptr->components_ptr;
186 }
187
188 OBJID::objid_element OBJID::from_INTEGER(const INTEGER& p_int)
189 {
190 int_val_t i_val = p_int.get_val();
191 if (i_val.is_negative()) {
192 TTCN_error("An OBJECT IDENTIFIER component cannot be negative");
193 }
194 if (!i_val.is_native()) {
195 TTCN_error("The value of an OBJECT IDENTIFIER component cannot exceed %u",
196 INT_MAX);
197 }
198 return (OBJID::objid_element)i_val.get_val();
199 }
200
201 void OBJID::log() const
202 {
203 if (val_ptr != NULL) {
204 TTCN_Logger::log_event_str("objid { ");
205 for (int i = 0; i < val_ptr->n_components; i++) {
206 if (i == val_ptr->overflow_idx) {
207 TTCN_Logger::log_event_str("overflow:");
208 }
209
210 TTCN_Logger::log_event(OBJID_FMT " ", val_ptr->components_ptr[i]);
211 }
212 TTCN_Logger::log_char('}');
213 } else TTCN_Logger::log_event_unbound();
214 }
215
216 void OBJID::set_param(Module_Param& param) {
217 param.basic_check(Module_Param::BC_VALUE, "objid value");
218 if (param.get_type()!=Module_Param::MP_Objid) param.type_error("objid value");
219 if (sizeof(objid_element)!=sizeof(int)) TTCN_error("Internal error: OBJID::set_param()");
220 clean_up();
221 init_struct(param.get_string_size());
222 memcpy(val_ptr->components_ptr, param.get_string_data(), val_ptr->n_components * sizeof(objid_element));
223 }
224
225 void OBJID::encode_text(Text_Buf& text_buf) const
226 {
227 if (val_ptr == NULL)
228 TTCN_error("Text encoder: Encoding an unbound objid value.");
229 text_buf.push_int(val_ptr->n_components);
230 for (int i = 0; i < val_ptr->n_components; i++)
231 text_buf.push_int(val_ptr->components_ptr[i]);
232 }
233
234 void OBJID::decode_text(Text_Buf& text_buf)
235 {
236 int n_components = text_buf.pull_int().get_val();
237 if (n_components < 0) TTCN_error("Text decoder: Negative number of "
238 "components was received for an objid value.");
239 clean_up();
240 init_struct(n_components);
241 for (int i = 0; i < n_components; i++)
242 val_ptr->components_ptr[i] = text_buf.pull_int().get_val();
243 }
244
245 void OBJID::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
246 TTCN_EncDec::coding_t p_coding, ...) const
247 {
248 va_list pvar;
249 va_start(pvar, p_coding);
250 switch(p_coding) {
251 case TTCN_EncDec::CT_BER: {
252 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
253 unsigned BER_coding=va_arg(pvar, unsigned);
254 BER_encode_chk_coding(BER_coding);
255 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
256 tlv->put_in_buffer(p_buf);
257 ASN_BER_TLV_t::destruct(tlv);
258 break;}
259 case TTCN_EncDec::CT_RAW: {
260 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
261 TTCN_EncDec_ErrorContext::error_internal
262 ("No RAW descriptor available for type '%s'.", p_td.name);
263 break;}
264 case TTCN_EncDec::CT_XER: {
265 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
266 unsigned XER_coding=va_arg(pvar, unsigned);
267 XER_encode(*p_td.xer, p_buf, XER_coding, 0);
268 break;}
269 default:
270 TTCN_error("Unknown coding method requested to encode type '%s'",
271 p_td.name);
272 }
273 va_end(pvar);
274 }
275
276 void OBJID::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
277 TTCN_EncDec::coding_t p_coding, ...)
278 {
279 va_list pvar;
280 va_start(pvar, p_coding);
281 switch(p_coding) {
282 case TTCN_EncDec::CT_BER: {
283 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
284 unsigned L_form=va_arg(pvar, unsigned);
285 ASN_BER_TLV_t tlv;
286 BER_decode_str2TLV(p_buf, tlv, L_form);
287 BER_decode_TLV(p_td, tlv, L_form);
288 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
289 break;}
290 case TTCN_EncDec::CT_RAW: {
291 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
292 TTCN_EncDec_ErrorContext::error_internal
293 ("No RAW descriptor available for type '%s'.", p_td.name);
294 break;}
295 case TTCN_EncDec::CT_XER: {
296 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
297 unsigned XER_coding=va_arg(pvar, unsigned);
298 XmlReaderWrap reader(p_buf);
299 int success = reader.Read();
300 for (; success==1; success=reader.Read()) {
301 int type = reader.NodeType();
302 if (type==XML_READER_TYPE_ELEMENT)
303 break;
304 }
305 XER_decode(*p_td.xer, reader, XER_coding);
306 size_t bytes = reader.ByteConsumed();
307 p_buf.set_pos(bytes);
308 break;}
309 default:
310 TTCN_error("Unknown coding method requested to decode type '%s'",
311 p_td.name);
312 }
313 va_end(pvar);
314 }
315
316 ASN_BER_TLV_t*
317 OBJID::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
318 unsigned p_coding) const
319 {
320 BER_chk_descr(p_td);
321 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
322 if(!new_tlv) {
323 size_t V_len=0;
324 switch(p_td.asnbasetype) {
325 case TTCN_Typedescriptor_t::OBJID:
326 if(val_ptr->n_components<2)
327 TTCN_EncDec_ErrorContext::error_internal
328 ("OBJID must have at least 2 components.");
329 V_len=(min_needed_bits(val_ptr->components_ptr[0]*40
330 +val_ptr->components_ptr[1])+6)/7;
331 for(int i=2; i<val_ptr->n_components; i++)
332 V_len+=(min_needed_bits(val_ptr->components_ptr[i])+6)/7;
333 break;
334 case TTCN_Typedescriptor_t::ROID:
335 for(int i=0; i<val_ptr->n_components; i++)
336 V_len+=(min_needed_bits(val_ptr->components_ptr[i])+6)/7;
337 break;
338 default:
339 TTCN_EncDec_ErrorContext::error_internal
340 ("Missing/wrong basetype info for type '%s'.", p_td.name);
341 } // switch
342 new_tlv=ASN_BER_TLV_t::construct(V_len, NULL);
343 unsigned char *Vptr=new_tlv->V.str.Vstr;
344 for(int i=0; i<val_ptr->n_components; i++) {
345 unsigned long ul;
346 if(i==0 && p_td.asnbasetype==TTCN_Typedescriptor_t::OBJID) {
347 ul=val_ptr->components_ptr[0]*40+val_ptr->components_ptr[1];
348 i++;
349 }
350 else ul=val_ptr->components_ptr[i];
351 size_t noo=(min_needed_bits(ul)+6)/7;
352 for(size_t j=noo; j>0; j--) {
353 Vptr[j-1]=(ul & 0x7F) | 0x80;
354 ul>>=7;
355 }
356 Vptr[noo-1]&=0x7F;
357 Vptr+=noo;
358 } // for i
359 }
360 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
361 return new_tlv;
362 }
363
364
365 boolean OBJID::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
366 const ASN_BER_TLV_t& p_tlv,
367 unsigned L_form)
368 {
369 clean_up();
370 BER_chk_descr(p_td);
371 ASN_BER_TLV_t stripped_tlv;
372 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
373 TTCN_EncDec_ErrorContext ec("While decoding OBJID type: ");
374 stripped_tlv.chk_constructed_flag(FALSE);
375 if (!stripped_tlv.isComplete) return FALSE;
376 if (!stripped_tlv.V_tlvs_selected && stripped_tlv.V.str.Vlen==0) {
377 ec.error(TTCN_EncDec::ET_INVAL_MSG, "Length of V-part is 0.");
378 return FALSE;
379 }
380 switch(p_td.asnbasetype) {
381 case TTCN_Typedescriptor_t::OBJID:
382 case TTCN_Typedescriptor_t::ROID:
383 break;
384 default:
385 TTCN_EncDec_ErrorContext::error_internal
386 ("Missing/wrong basetype info for type '%s'.", p_td.name);
387 } // switch
388 unsigned char *Vptr=stripped_tlv.V.str.Vstr;
389 boolean eoc=FALSE; // end-of-component
390 int i=0;
391 unsigned long long ull=0;
392 STATIC_ASSERT(sizeof(ull) > sizeof(objid_element));
393
394 boolean err_repr=FALSE;
395 while (Vptr < stripped_tlv.V.str.Vstr + stripped_tlv.V.str.Vlen) {
396 ull |= *Vptr & 0x7F;
397 if ((*Vptr & 0x80) && err_repr==FALSE) { // not-eoc
398 if (ull & unsigned_llong_7msb) {
399 ec.error(TTCN_EncDec::ET_REPR,
400 "Value of the #%d component is too big.", i+1);
401 err_repr=TRUE;
402 }
403 ull<<=7;
404 eoc=FALSE;
405 }
406 else { // eoc
407 if (i==0 && p_td.asnbasetype==TTCN_Typedescriptor_t::OBJID) {
408 // first two component of objid
409 switch(ull/40ul) {
410 case 0:
411 (*this)[0]=0; break;
412 case 1:
413 (*this)[0]=1; break;
414 default:
415 (*this)[0]=2; break;
416 }
417 (*this)[1]=(int)(ull-40*(*this)[0]);
418 i=1;
419 }
420 else { // other components (>2)
421 // objid_element is UINT/ULONG; the result of the cast is Uxxx_MAX.
422 // It's computed at compile time.
423 if(ull > ((objid_element)-1)) {
424 if(err_repr==FALSE)
425 ec.error(TTCN_EncDec::ET_REPR,
426 "Value of the #%d component is too big.", i+1);
427 (*this)[i]=(objid_element)-1;
428 // remember the first overflow
429 if (val_ptr->overflow_idx < 0) val_ptr->overflow_idx = i;
430 } // if ul too big
431 else
432 (*this)[i]=(objid_element)ull;
433 }
434 err_repr=FALSE;
435 ull=0;
436 eoc=TRUE;
437 i++;
438 } // eoc
439 Vptr++;
440 } // while Vptr...
441 if(eoc==FALSE)
442 ec.error(TTCN_EncDec::ET_INVAL_MSG,
443 "The last component (#%d) is unterminated.", i+1);
444 return TRUE;
445 }
446
447
448 int OBJID::XER_encode(const XERdescriptor_t& p_td,
449 TTCN_Buffer& p_buf, unsigned int flavor, int indent ) const
450 {
451 if(!is_bound()) {
452 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
453 "Encoding an unbound object identifier value.");
454 }
455 int encoded_length=(int)p_buf.get_len();
456
457 flavor |= SIMPLE_TYPE;
458 flavor &= ~XER_RECOF; // object identifier doesn't care
459 begin_xml(p_td, p_buf, flavor, indent, false);
460
461 static char str_buf[64];
462 for (int i = 0; i < val_ptr->n_components; ++i ) {
463 // output dot before the second and subsequent components
464 if (i > 0) p_buf.put_c('.');
465 // output current component
466 int str_len = snprintf(str_buf, sizeof(str_buf), OBJID_FMT,
467 val_ptr->components_ptr[i]);
468 if (str_len < 0 || str_len >= (int)sizeof(str_buf)) {
469 TTCN_error("Internal error: system call snprintf() returned "
470 "unexpected status code %d when converting value " OBJID_FMT,
471 str_len, val_ptr->components_ptr[i]);
472 }
473 else p_buf.put_s(str_len, (const unsigned char*)str_buf);
474 }
475
476 end_xml(p_td, p_buf, flavor, indent, false);
477
478 return (int)p_buf.get_len() - encoded_length;
479 }
480
481 int OBJID::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
482 unsigned int flavor)
483 {
484 int exer = is_exer(flavor);
485 int success = reader.Ok(), depth = -1;
486 for (; success == 1; success = reader.Read()) {
487 int type = reader.NodeType();
488 if (XML_READER_TYPE_ELEMENT == type) {
489 verify_name(reader, p_td, exer);
490 depth = reader.Depth();
491 break;
492 }
493 }
494 if (success == 1) {
495 char * val = (char *)reader.ReadString(); // We own this (writable) string
496 if (0 == val) {
497 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "Bogus object identifier");
498 return 0;
499 }
500 // Count dots to find number of components. (1 dot = 2 components, etc.)
501 unsigned comps = 1;
502 const char *p;
503 for (p = val; *p != 0; ++p) {
504 if (*p == '.') ++comps;
505 }
506 // p now points at the end of the string. If it was empty, then there were
507 // no components; compensate the fact that we started at 1.
508 init_struct((p != val) ? comps : 0);
509
510 char *beg, *end = 0;
511 comps = 0;
512 for (beg = val; beg < p; ++beg) {
513 errno = 0;
514 long ret = strtol(beg, &end, 10);
515 if (errno) break;
516
517 // TODO check value for too big ?
518 (*this)[comps++] = ret;
519 beg = end; // move to the dot; will move past it when incremented
520 }
521
522 xmlFree(val);
523 }
524 for (success = reader.Read(); success == 1; success = reader.Read()) {
525 int type = reader.NodeType();
526 if (XML_READER_TYPE_END_ELEMENT == type) {
527 verify_end(reader, p_td, depth, exer);
528 reader.Read();
529 break;
530 }
531 }
532 return 1; // decode successful
533 }
534
535
536 void OBJID_template::clean_up()
537 {
538 if (template_selection == VALUE_LIST ||
539 template_selection == COMPLEMENTED_LIST) delete [] value_list.list_value;
540 template_selection = UNINITIALIZED_TEMPLATE;
541 }
542
543 void OBJID_template::copy_template(const OBJID_template& other_value)
544 {
545 switch (other_value.template_selection) {
546 case SPECIFIC_VALUE:
547 single_value = other_value.single_value;
548 break;
549 case OMIT_VALUE:
550 case ANY_VALUE:
551 case ANY_OR_OMIT:
552 break;
553 case VALUE_LIST:
554 case COMPLEMENTED_LIST:
555 value_list.n_values = other_value.value_list.n_values;
556 value_list.list_value = new OBJID_template[value_list.n_values];
557 for (unsigned int i = 0; i < value_list.n_values; i++)
558 value_list.list_value[i].copy_template(
559 other_value.value_list.list_value[i]);
560 break;
561 default:
562 TTCN_error("Copying an uninitialized/unsupported objid template.");
563 }
564 set_selection(other_value);
565 }
566
567 OBJID_template::OBJID_template()
568 {
569
570 }
571
572 OBJID_template::OBJID_template(template_sel other_value)
573 : Base_Template(other_value)
574 {
575 check_single_selection(other_value);
576 }
577
578 OBJID_template::OBJID_template(const OBJID& other_value)
579 : Base_Template(SPECIFIC_VALUE), single_value(other_value)
580 {
581
582 }
583
584 OBJID_template::OBJID_template(const OPTIONAL<OBJID>& other_value)
585 {
586 switch (other_value.get_selection()) {
587 case OPTIONAL_PRESENT:
588 set_selection(SPECIFIC_VALUE);
589 single_value = (const OBJID&)other_value;
590 break;
591 case OPTIONAL_OMIT:
592 set_selection(OMIT_VALUE);
593 break;
594 default:
595 TTCN_error("Creating an objid template from an unbound optional field.");
596 }
597 }
598
599 OBJID_template::OBJID_template(const OBJID_template& other_value)
600 : Base_Template()
601 {
602 copy_template(other_value);
603 }
604
605 OBJID_template::~OBJID_template()
606 {
607 clean_up();
608 }
609
610 OBJID_template& OBJID_template::operator=(template_sel other_value)
611 {
612 check_single_selection(other_value);
613 clean_up();
614 set_selection(other_value);
615 return *this;
616 }
617
618 OBJID_template& OBJID_template::operator=(const OBJID& other_value)
619 {
620 if (!other_value.is_bound())
621 TTCN_error("Assignment of an unbound objid value to a template.");
622 clean_up();
623 set_selection(SPECIFIC_VALUE);
624 single_value = other_value;
625 return *this;
626 }
627
628 OBJID_template& OBJID_template::operator=(const OPTIONAL<OBJID>& other_value)
629 {
630 clean_up();
631 switch (other_value.get_selection()) {
632 case OPTIONAL_PRESENT:
633 set_selection(SPECIFIC_VALUE);
634 single_value = (const OBJID&)other_value;
635 break;
636 case OPTIONAL_OMIT:
637 set_selection(OMIT_VALUE);
638 break;
639 default:
640 TTCN_error("Assignment of an unbound optional field to an objid template.");
641 }
642 return *this;
643 }
644
645 OBJID_template& OBJID_template::operator=(const OBJID_template& other_value)
646 {
647 if (&other_value != this) {
648 clean_up();
649 copy_template(other_value);
650 }
651 return *this;
652 }
653
654 boolean OBJID_template::match(const OBJID& other_value) const
655 {
656 if (!other_value.is_bound()) return FALSE;
657 switch (template_selection) {
658 case SPECIFIC_VALUE:
659 return single_value == other_value;
660 case OMIT_VALUE:
661 return FALSE;
662 case ANY_VALUE:
663 case ANY_OR_OMIT:
664 return TRUE;
665 case VALUE_LIST:
666 case COMPLEMENTED_LIST:
667 for (unsigned int i = 0; i < value_list.n_values; i++)
668 if (value_list.list_value[i].match(other_value))
669 return template_selection == VALUE_LIST;
670 return template_selection == COMPLEMENTED_LIST;
671 default:
672 TTCN_error("Matching with an uninitialized/unsupported objid template.");
673 }
674 return FALSE;
675 }
676
677 const OBJID& OBJID_template::valueof() const
678 {
679 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
680 TTCN_error("Performing a valueof "
681 "or send operation on a non-specific objid template.");
682 return single_value;
683 }
684
685 int OBJID_template::size_of() const
686 {
687 switch (template_selection)
688 {
689 case SPECIFIC_VALUE:
690 return single_value.size_of();
691 case OMIT_VALUE:
692 TTCN_error("Performing sizeof() operation on an objid template "
693 "containing omit value.");
694 case ANY_VALUE:
695 case ANY_OR_OMIT:
696 TTCN_error("Performing sizeof() operation on a */? objid template.");
697 case VALUE_LIST:
698 {
699 if (value_list.n_values<1)
700 TTCN_error("Internal error: "
701 "Performing sizeof() operation on an objid template "
702 "containing an empty list.");
703 int item_size = value_list.list_value[0].size_of();
704 for (unsigned int i = 1; i < value_list.n_values; i++) {
705 if (value_list.list_value[i].size_of()!=item_size)
706 TTCN_error("Performing sizeof() operation on an objid template "
707 "containing a value list with different sizes.");
708 }
709 return item_size;
710 }
711 case COMPLEMENTED_LIST:
712 TTCN_error("Performing sizeof() operation on an objid template "
713 "containing complemented list.");
714 default:
715 TTCN_error("Performing sizeof() operation on an "
716 "uninitialized/unsupported objid template.");
717 }
718 return 0;
719 }
720
721 void OBJID_template::set_type(template_sel template_type,
722 unsigned int list_length)
723 {
724 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
725 TTCN_error("Setting an invalid list type for an objid template.");
726 clean_up();
727 set_selection(template_type);
728 value_list.n_values = list_length;
729 value_list.list_value = new OBJID_template[list_length];
730 }
731
732 OBJID_template& OBJID_template::list_item(unsigned int list_index)
733 {
734 if (template_selection != VALUE_LIST &&
735 template_selection != COMPLEMENTED_LIST)
736 TTCN_error("Accessing a list element of a non-list objid template.");
737 if (list_index >= value_list.n_values)
738 TTCN_error("Index overflow in an objid value list template.");
739 return value_list.list_value[list_index];
740 }
741
742 void OBJID_template::log() const
743 {
744 switch (template_selection) {
745 case SPECIFIC_VALUE:
746 single_value.log();
747 break;
748 case COMPLEMENTED_LIST:
749 TTCN_Logger::log_event_str("complement ");
750 // no break
751 case VALUE_LIST:
752 TTCN_Logger::log_char('(');
753 for(unsigned int i = 0; i < value_list.n_values; i++) {
754 if (i > 0) TTCN_Logger::log_event_str(", ");
755 value_list.list_value[i].log();
756 }
757 TTCN_Logger::log_char(')');
758 break;
759 default:
760 log_generic();
761 break;
762 }
763 log_ifpresent();
764 }
765
766 void OBJID_template::log_match(const OBJID& match_value) const
767 {
768 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
769 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
770 TTCN_Logger::print_logmatch_buffer();
771 TTCN_Logger::log_event_str(" := ");
772 }
773 match_value.log();
774 TTCN_Logger::log_event_str(" with ");
775 log();
776 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
777 else TTCN_Logger::log_event_str(" unmatched");
778 }
779
780 void OBJID_template::set_param(Module_Param& param) {
781 param.basic_check(Module_Param::BC_TEMPLATE, "objid template");
782 switch (param.get_type()) {
783 case Module_Param::MP_Omit:
784 *this = OMIT_VALUE;
785 break;
786 case Module_Param::MP_Any:
787 *this = ANY_VALUE;
788 break;
789 case Module_Param::MP_AnyOrNone:
790 *this = ANY_OR_OMIT;
791 break;
792 case Module_Param::MP_List_Template:
793 case Module_Param::MP_ComplementList_Template:
794 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
795 for (size_t i=0; i<param.get_size(); i++) {
796 list_item(i).set_param(*param.get_elem(i));
797 }
798 break;
799 case Module_Param::MP_Objid:
800 if (sizeof(OBJID::objid_element)!=sizeof(int)) TTCN_error("Internal error: OBJID_template::set_param()");
801 *this = OBJID(param.get_string_size(), (OBJID::objid_element*)param.get_string_data());
802 break;
803 //case Module_Param::MP_Objid_Template:
804 // TODO
805 //break;
806 default:
807 param.type_error("objid template");
808 }
809 is_ifpresent = param.get_ifpresent();
810 }
811
812 void OBJID_template::encode_text(Text_Buf& text_buf) const
813 {
814 encode_text_base(text_buf);
815 switch (template_selection) {
816 case OMIT_VALUE:
817 case ANY_VALUE:
818 case ANY_OR_OMIT:
819 break;
820 case SPECIFIC_VALUE:
821 single_value.encode_text(text_buf);
822 break;
823 case VALUE_LIST:
824 case COMPLEMENTED_LIST:
825 text_buf.push_int(value_list.n_values);
826 for (unsigned int i = 0; i < value_list.n_values; i++)
827 value_list.list_value[i].encode_text(text_buf);
828 break;
829 default:
830 TTCN_error("Text encoder: Encoding an undefined/unsupported objid "
831 "template.");
832 }
833 }
834
835 void OBJID_template::decode_text(Text_Buf& text_buf)
836 {
837 clean_up();
838 decode_text_base(text_buf);
839 switch (template_selection) {
840 case OMIT_VALUE:
841 case ANY_VALUE:
842 case ANY_OR_OMIT:
843 break;
844 case SPECIFIC_VALUE:
845 single_value.decode_text(text_buf);
846 break;
847 case VALUE_LIST:
848 case COMPLEMENTED_LIST:
849 value_list.n_values = text_buf.pull_int().get_val();
850 value_list.list_value = new OBJID_template[value_list.n_values];
851 for (unsigned int i = 0; i < value_list.n_values; i++)
852 value_list.list_value[i].decode_text(text_buf);
853 break;
854 default:
855 TTCN_error("Text decoder: An unknown/unsupported selection was "
856 "received for an objid template.");
857 }
858 }
859
860 boolean OBJID_template::is_present() const
861 {
862 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
863 return !match_omit();
864 }
865
866 boolean OBJID_template::match_omit() const
867 {
868 if (is_ifpresent) return TRUE;
869 switch (template_selection) {
870 case OMIT_VALUE:
871 case ANY_OR_OMIT:
872 return TRUE;
873 case VALUE_LIST:
874 case COMPLEMENTED_LIST:
875 for (unsigned int i=0; i<value_list.n_values; i++)
876 if (value_list.list_value[i].match_omit())
877 return template_selection==VALUE_LIST;
878 return template_selection==COMPLEMENTED_LIST;
879 default:
880 return FALSE;
881 }
882 return FALSE;
883 }
884
885 #ifndef TITAN_RUNTIME_2
886 void OBJID_template::check_restriction(template_res t_res, const char* t_name) const
887 {
888 if (template_selection==UNINITIALIZED_TEMPLATE) return;
889 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
890 case TR_VALUE:
891 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
892 break;
893 case TR_OMIT:
894 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
895 template_selection==SPECIFIC_VALUE)) return;
896 break;
897 case TR_PRESENT:
898 if (!match_omit()) return;
899 break;
900 default:
901 return;
902 }
903 TTCN_error("Restriction `%s' on template of type %s violated.",
904 get_res_name(t_res), t_name ? t_name : "objid");
905 }
906 #endif
This page took 0.050555 seconds and 4 git commands to generate.