Sync with 5.4.0
[deliverable/titan.core.git] / core / Objid.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
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
16static const size_t MIN_COMPONENTS = 2;
17
18struct 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
28void 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
43void 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
55void 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
66OBJID::OBJID()
67{
68 val_ptr = NULL; // unbound
69}
70
71OBJID::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
83OBJID::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
90OBJID::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
99OBJID::~OBJID()
100{
101 clean_up();
102}
103
104OBJID& 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
116boolean 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
129OBJID::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
161OBJID::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
174int 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
181OBJID::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
188OBJID::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
201void 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
216void OBJID::set_param(Module_Param& param) {
217 param.basic_check(Module_Param::BC_VALUE, "objid value");
3abe9331 218 Module_Param_Ptr mp = &param;
219 if (param.get_type() == Module_Param::MP_Reference) {
220 mp = param.get_referenced_param();
221 }
222 if (mp->get_type()!=Module_Param::MP_Objid) param.type_error("objid value");
970ed795
EL
223 if (sizeof(objid_element)!=sizeof(int)) TTCN_error("Internal error: OBJID::set_param()");
224 clean_up();
3abe9331 225 init_struct(mp->get_string_size());
226 memcpy(val_ptr->components_ptr, mp->get_string_data(), val_ptr->n_components * sizeof(objid_element));
227}
228
229Module_Param* OBJID::get_param(Module_Param_Name& /* param_name */) const
230{
231 if (!is_bound()) {
232 return new Module_Param_Unbound();
233 }
234 int* val_cpy = (int *)Malloc(val_ptr->n_components);
235 memcpy(val_cpy, val_ptr->components_ptr, val_ptr->n_components * sizeof(int));
236 return new Module_Param_Objid(val_ptr->n_components, val_cpy);
970ed795
EL
237}
238
239void OBJID::encode_text(Text_Buf& text_buf) const
240{
241 if (val_ptr == NULL)
242 TTCN_error("Text encoder: Encoding an unbound objid value.");
243 text_buf.push_int(val_ptr->n_components);
244 for (int i = 0; i < val_ptr->n_components; i++)
245 text_buf.push_int(val_ptr->components_ptr[i]);
246}
247
248void OBJID::decode_text(Text_Buf& text_buf)
249{
250 int n_components = text_buf.pull_int().get_val();
251 if (n_components < 0) TTCN_error("Text decoder: Negative number of "
252 "components was received for an objid value.");
253 clean_up();
254 init_struct(n_components);
255 for (int i = 0; i < n_components; i++)
256 val_ptr->components_ptr[i] = text_buf.pull_int().get_val();
257}
258
259void OBJID::encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
260 TTCN_EncDec::coding_t p_coding, ...) const
261{
262 va_list pvar;
263 va_start(pvar, p_coding);
264 switch(p_coding) {
265 case TTCN_EncDec::CT_BER: {
266 TTCN_EncDec_ErrorContext ec("While BER-encoding type '%s': ", p_td.name);
267 unsigned BER_coding=va_arg(pvar, unsigned);
268 BER_encode_chk_coding(BER_coding);
269 ASN_BER_TLV_t *tlv=BER_encode_TLV(p_td, BER_coding);
270 tlv->put_in_buffer(p_buf);
271 ASN_BER_TLV_t::destruct(tlv);
272 break;}
273 case TTCN_EncDec::CT_RAW: {
274 TTCN_EncDec_ErrorContext ec("While RAW-encoding type '%s': ", p_td.name);
275 TTCN_EncDec_ErrorContext::error_internal
276 ("No RAW descriptor available for type '%s'.", p_td.name);
277 break;}
278 case TTCN_EncDec::CT_XER: {
279 TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
280 unsigned XER_coding=va_arg(pvar, unsigned);
af710487 281 XER_encode(*p_td.xer, p_buf, XER_coding, 0, 0);
282 break;}
283 case TTCN_EncDec::CT_JSON: {
284 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
285 if(!p_td.json)
286 TTCN_EncDec_ErrorContext::error_internal
287 ("No JSON descriptor available for type '%s'.", p_td.name);
288 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
289 JSON_encode(p_td, tok);
290 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
970ed795
EL
291 break;}
292 default:
293 TTCN_error("Unknown coding method requested to encode type '%s'",
294 p_td.name);
295 }
296 va_end(pvar);
297}
298
299void OBJID::decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf,
300 TTCN_EncDec::coding_t p_coding, ...)
301{
302 va_list pvar;
303 va_start(pvar, p_coding);
304 switch(p_coding) {
305 case TTCN_EncDec::CT_BER: {
306 TTCN_EncDec_ErrorContext ec("While BER-decoding type '%s': ", p_td.name);
307 unsigned L_form=va_arg(pvar, unsigned);
308 ASN_BER_TLV_t tlv;
309 BER_decode_str2TLV(p_buf, tlv, L_form);
310 BER_decode_TLV(p_td, tlv, L_form);
311 if(tlv.isComplete) p_buf.increase_pos(tlv.get_len());
312 break;}
313 case TTCN_EncDec::CT_RAW: {
314 TTCN_EncDec_ErrorContext ec("While RAW-decoding type '%s': ", p_td.name);
315 TTCN_EncDec_ErrorContext::error_internal
316 ("No RAW descriptor available for type '%s'.", p_td.name);
317 break;}
318 case TTCN_EncDec::CT_XER: {
af710487 319 TTCN_EncDec_ErrorContext ec("While XER-decoding type '%s': ", p_td.name);
970ed795
EL
320 unsigned XER_coding=va_arg(pvar, unsigned);
321 XmlReaderWrap reader(p_buf);
322 int success = reader.Read();
323 for (; success==1; success=reader.Read()) {
324 int type = reader.NodeType();
325 if (type==XML_READER_TYPE_ELEMENT)
326 break;
327 }
af710487 328 XER_decode(*p_td.xer, reader, XER_coding, 0);
970ed795
EL
329 size_t bytes = reader.ByteConsumed();
330 p_buf.set_pos(bytes);
331 break;}
af710487 332 case TTCN_EncDec::CT_JSON: {
333 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
334 if(!p_td.json)
335 TTCN_EncDec_ErrorContext::error_internal
336 ("No JSON descriptor available for type '%s'.", p_td.name);
337 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
338 if(JSON_decode(p_td, tok, false)<0)
339 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,
340 "Can not decode type '%s', because invalid or incomplete"
341 " message was received"
342 , p_td.name);
343 p_buf.set_pos(tok.get_buf_pos());
344 break;}
970ed795
EL
345 default:
346 TTCN_error("Unknown coding method requested to decode type '%s'",
347 p_td.name);
348 }
349 va_end(pvar);
350}
351
352ASN_BER_TLV_t*
353OBJID::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
354 unsigned p_coding) const
355{
356 BER_chk_descr(p_td);
357 ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());
358 if(!new_tlv) {
359 size_t V_len=0;
360 switch(p_td.asnbasetype) {
361 case TTCN_Typedescriptor_t::OBJID:
362 if(val_ptr->n_components<2)
363 TTCN_EncDec_ErrorContext::error_internal
364 ("OBJID must have at least 2 components.");
365 V_len=(min_needed_bits(val_ptr->components_ptr[0]*40
366 +val_ptr->components_ptr[1])+6)/7;
367 for(int i=2; i<val_ptr->n_components; i++)
368 V_len+=(min_needed_bits(val_ptr->components_ptr[i])+6)/7;
369 break;
370 case TTCN_Typedescriptor_t::ROID:
371 for(int i=0; i<val_ptr->n_components; i++)
372 V_len+=(min_needed_bits(val_ptr->components_ptr[i])+6)/7;
373 break;
374 default:
375 TTCN_EncDec_ErrorContext::error_internal
376 ("Missing/wrong basetype info for type '%s'.", p_td.name);
377 } // switch
378 new_tlv=ASN_BER_TLV_t::construct(V_len, NULL);
379 unsigned char *Vptr=new_tlv->V.str.Vstr;
380 for(int i=0; i<val_ptr->n_components; i++) {
381 unsigned long ul;
382 if(i==0 && p_td.asnbasetype==TTCN_Typedescriptor_t::OBJID) {
383 ul=val_ptr->components_ptr[0]*40+val_ptr->components_ptr[1];
384 i++;
385 }
386 else ul=val_ptr->components_ptr[i];
387 size_t noo=(min_needed_bits(ul)+6)/7;
388 for(size_t j=noo; j>0; j--) {
389 Vptr[j-1]=(ul & 0x7F) | 0x80;
390 ul>>=7;
391 }
392 Vptr[noo-1]&=0x7F;
393 Vptr+=noo;
394 } // for i
395 }
396 new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);
397 return new_tlv;
398}
399
400
401boolean OBJID::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
402 const ASN_BER_TLV_t& p_tlv,
403 unsigned L_form)
404{
405 clean_up();
406 BER_chk_descr(p_td);
407 ASN_BER_TLV_t stripped_tlv;
408 BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
409 TTCN_EncDec_ErrorContext ec("While decoding OBJID type: ");
410 stripped_tlv.chk_constructed_flag(FALSE);
411 if (!stripped_tlv.isComplete) return FALSE;
412 if (!stripped_tlv.V_tlvs_selected && stripped_tlv.V.str.Vlen==0) {
413 ec.error(TTCN_EncDec::ET_INVAL_MSG, "Length of V-part is 0.");
414 return FALSE;
415 }
416 switch(p_td.asnbasetype) {
417 case TTCN_Typedescriptor_t::OBJID:
418 case TTCN_Typedescriptor_t::ROID:
419 break;
420 default:
421 TTCN_EncDec_ErrorContext::error_internal
422 ("Missing/wrong basetype info for type '%s'.", p_td.name);
423 } // switch
424 unsigned char *Vptr=stripped_tlv.V.str.Vstr;
425 boolean eoc=FALSE; // end-of-component
426 int i=0;
427 unsigned long long ull=0;
428 STATIC_ASSERT(sizeof(ull) > sizeof(objid_element));
429
430 boolean err_repr=FALSE;
431 while (Vptr < stripped_tlv.V.str.Vstr + stripped_tlv.V.str.Vlen) {
432 ull |= *Vptr & 0x7F;
433 if ((*Vptr & 0x80) && err_repr==FALSE) { // not-eoc
434 if (ull & unsigned_llong_7msb) {
435 ec.error(TTCN_EncDec::ET_REPR,
436 "Value of the #%d component is too big.", i+1);
437 err_repr=TRUE;
438 }
439 ull<<=7;
440 eoc=FALSE;
441 }
442 else { // eoc
443 if (i==0 && p_td.asnbasetype==TTCN_Typedescriptor_t::OBJID) {
444 // first two component of objid
445 switch(ull/40ul) {
446 case 0:
447 (*this)[0]=0; break;
448 case 1:
449 (*this)[0]=1; break;
450 default:
451 (*this)[0]=2; break;
452 }
453 (*this)[1]=(int)(ull-40*(*this)[0]);
454 i=1;
455 }
456 else { // other components (>2)
457 // objid_element is UINT/ULONG; the result of the cast is Uxxx_MAX.
458 // It's computed at compile time.
459 if(ull > ((objid_element)-1)) {
460 if(err_repr==FALSE)
461 ec.error(TTCN_EncDec::ET_REPR,
462 "Value of the #%d component is too big.", i+1);
463 (*this)[i]=(objid_element)-1;
464 // remember the first overflow
465 if (val_ptr->overflow_idx < 0) val_ptr->overflow_idx = i;
466 } // if ul too big
467 else
468 (*this)[i]=(objid_element)ull;
469 }
470 err_repr=FALSE;
471 ull=0;
472 eoc=TRUE;
473 i++;
474 } // eoc
475 Vptr++;
476 } // while Vptr...
477 if(eoc==FALSE)
478 ec.error(TTCN_EncDec::ET_INVAL_MSG,
479 "The last component (#%d) is unterminated.", i+1);
480 return TRUE;
481}
482
483
484int OBJID::XER_encode(const XERdescriptor_t& p_td,
af710487 485 TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
970ed795
EL
486{
487 if(!is_bound()) {
488 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
489 "Encoding an unbound object identifier value.");
490 }
491 int encoded_length=(int)p_buf.get_len();
492
493 flavor |= SIMPLE_TYPE;
494 flavor &= ~XER_RECOF; // object identifier doesn't care
495 begin_xml(p_td, p_buf, flavor, indent, false);
496
497 static char str_buf[64];
498 for (int i = 0; i < val_ptr->n_components; ++i ) {
499 // output dot before the second and subsequent components
500 if (i > 0) p_buf.put_c('.');
501 // output current component
502 int str_len = snprintf(str_buf, sizeof(str_buf), OBJID_FMT,
503 val_ptr->components_ptr[i]);
504 if (str_len < 0 || str_len >= (int)sizeof(str_buf)) {
505 TTCN_error("Internal error: system call snprintf() returned "
506 "unexpected status code %d when converting value " OBJID_FMT,
507 str_len, val_ptr->components_ptr[i]);
508 }
509 else p_buf.put_s(str_len, (const unsigned char*)str_buf);
510 }
511
512 end_xml(p_td, p_buf, flavor, indent, false);
513
514 return (int)p_buf.get_len() - encoded_length;
515}
516
af710487 517void OBJID::from_string(char* p_str)
518{
519 // Count dots to find number of components. (1 dot = 2 components, etc.)
520 unsigned comps = 1;
521 const char *p;
522 for (p = p_str; *p != 0; ++p) {
523 if (*p == '.') ++comps;
524 }
525 // p now points at the end of the string. If it was empty, then there were
526 // no components; compensate the fact that we started at 1.
527 init_struct((p != p_str) ? comps : 0);
528
529 char *beg, *end = 0;
530 comps = 0;
531 for (beg = p_str; beg < p; ++beg) {
532 errno = 0;
533 long ret = strtol(beg, &end, 10);
534 if (errno) break;
535
536 // TODO check value for too big ?
537 (*this)[comps++] = ret;
538 beg = end; // move to the dot; will move past it when incremented
539 }
540}
541
970ed795 542int OBJID::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
af710487 543 unsigned int flavor, embed_values_dec_struct_t*)
970ed795
EL
544{
545 int exer = is_exer(flavor);
546 int success = reader.Ok(), depth = -1;
547 for (; success == 1; success = reader.Read()) {
548 int type = reader.NodeType();
549 if (XML_READER_TYPE_ELEMENT == type) {
550 verify_name(reader, p_td, exer);
551 depth = reader.Depth();
552 break;
553 }
554 }
555 if (success == 1) {
556 char * val = (char *)reader.ReadString(); // We own this (writable) string
557 if (0 == val) {
558 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "Bogus object identifier");
559 return 0;
560 }
af710487 561
562 from_string(val);
970ed795
EL
563
564 xmlFree(val);
565 }
566 for (success = reader.Read(); success == 1; success = reader.Read()) {
567 int type = reader.NodeType();
568 if (XML_READER_TYPE_END_ELEMENT == type) {
569 verify_end(reader, p_td, depth, exer);
570 reader.Read();
571 break;
572 }
573 }
574 return 1; // decode successful
575}
576
af710487 577int OBJID::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
578{
579 if (!is_bound()) {
580 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
581 "Encoding an unbound object identifier value.");
582 return -1;
583 }
584
585 char* objid_str = mcopystrn("\"", 1);
586 for (int i = 0; i < val_ptr->n_components; ++i) {
587 objid_str = mputprintf(objid_str, "%s" OBJID_FMT, (i > 0 ? "." : ""), val_ptr->components_ptr[i]);
588 }
589 objid_str = mputstrn(objid_str, "\"", 1);
590 int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, objid_str);
591 Free(objid_str);
592 return enc_len;
593}
594
595int OBJID::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
596{
597 json_token_t token = JSON_TOKEN_NONE;
598 char* value = 0;
599 size_t value_len = 0;
600 boolean error = false;
601 int dec_len = 0;
602 boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();
603 if (use_default) {
604 // No JSON data in the buffer -> use default value
605 value = (char*)p_td.json->default_value;
606 value_len = strlen(value);
607 } else {
608 dec_len = p_tok.get_next_token(&token, &value, &value_len);
609 }
610 if (JSON_TOKEN_ERROR == token) {
611 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
612 return JSON_ERROR_FATAL;
613 }
614 else if (JSON_TOKEN_STRING == token || use_default) {
615 if (use_default || (value_len > 2 && value[0] == '\"' && value[value_len - 1] == '\"')) {
616 if (!use_default) {
617 // The default value doesn't have quotes around it
618 value_len -= 2;
619 ++value;
620 }
621 // need a null-terminated string
622 char* value2 = mcopystrn(value, value_len);
623 from_string(value2);
624 Free(value2);
625 }
626 }
627 else {
628 return JSON_ERROR_INVALID_TOKEN;
629 }
630
631 if (error) {
632 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, "string", "object identifier");
633 if (p_silent) {
634 clean_up();
635 }
636 return JSON_ERROR_FATAL;
637 }
638 return dec_len;
639}
970ed795
EL
640
641void OBJID_template::clean_up()
642{
643 if (template_selection == VALUE_LIST ||
644 template_selection == COMPLEMENTED_LIST) delete [] value_list.list_value;
645 template_selection = UNINITIALIZED_TEMPLATE;
646}
647
648void OBJID_template::copy_template(const OBJID_template& other_value)
649{
650 switch (other_value.template_selection) {
651 case SPECIFIC_VALUE:
652 single_value = other_value.single_value;
653 break;
654 case OMIT_VALUE:
655 case ANY_VALUE:
656 case ANY_OR_OMIT:
657 break;
658 case VALUE_LIST:
659 case COMPLEMENTED_LIST:
660 value_list.n_values = other_value.value_list.n_values;
661 value_list.list_value = new OBJID_template[value_list.n_values];
662 for (unsigned int i = 0; i < value_list.n_values; i++)
663 value_list.list_value[i].copy_template(
664 other_value.value_list.list_value[i]);
665 break;
666 default:
667 TTCN_error("Copying an uninitialized/unsupported objid template.");
668 }
669 set_selection(other_value);
670}
671
672OBJID_template::OBJID_template()
673{
674
675}
676
677OBJID_template::OBJID_template(template_sel other_value)
678 : Base_Template(other_value)
679{
680 check_single_selection(other_value);
681}
682
683OBJID_template::OBJID_template(const OBJID& other_value)
684 : Base_Template(SPECIFIC_VALUE), single_value(other_value)
685{
686
687}
688
689OBJID_template::OBJID_template(const OPTIONAL<OBJID>& other_value)
690{
691 switch (other_value.get_selection()) {
692 case OPTIONAL_PRESENT:
693 set_selection(SPECIFIC_VALUE);
694 single_value = (const OBJID&)other_value;
695 break;
696 case OPTIONAL_OMIT:
697 set_selection(OMIT_VALUE);
698 break;
699 default:
700 TTCN_error("Creating an objid template from an unbound optional field.");
701 }
702}
703
704OBJID_template::OBJID_template(const OBJID_template& other_value)
705: Base_Template()
706{
707 copy_template(other_value);
708}
709
710OBJID_template::~OBJID_template()
711{
712 clean_up();
713}
714
715OBJID_template& OBJID_template::operator=(template_sel other_value)
716{
717 check_single_selection(other_value);
718 clean_up();
719 set_selection(other_value);
720 return *this;
721}
722
723OBJID_template& OBJID_template::operator=(const OBJID& other_value)
724{
725 if (!other_value.is_bound())
726 TTCN_error("Assignment of an unbound objid value to a template.");
727 clean_up();
728 set_selection(SPECIFIC_VALUE);
729 single_value = other_value;
730 return *this;
731}
732
733OBJID_template& OBJID_template::operator=(const OPTIONAL<OBJID>& other_value)
734{
735 clean_up();
736 switch (other_value.get_selection()) {
737 case OPTIONAL_PRESENT:
738 set_selection(SPECIFIC_VALUE);
739 single_value = (const OBJID&)other_value;
740 break;
741 case OPTIONAL_OMIT:
742 set_selection(OMIT_VALUE);
743 break;
744 default:
745 TTCN_error("Assignment of an unbound optional field to an objid template.");
746 }
747 return *this;
748}
749
750OBJID_template& OBJID_template::operator=(const OBJID_template& other_value)
751{
752 if (&other_value != this) {
753 clean_up();
754 copy_template(other_value);
755 }
756 return *this;
757}
758
3abe9331 759boolean OBJID_template::match(const OBJID& other_value, boolean /* legacy */) const
970ed795
EL
760{
761 if (!other_value.is_bound()) return FALSE;
762 switch (template_selection) {
763 case SPECIFIC_VALUE:
764 return single_value == other_value;
765 case OMIT_VALUE:
766 return FALSE;
767 case ANY_VALUE:
768 case ANY_OR_OMIT:
769 return TRUE;
770 case VALUE_LIST:
771 case COMPLEMENTED_LIST:
772 for (unsigned int i = 0; i < value_list.n_values; i++)
773 if (value_list.list_value[i].match(other_value))
774 return template_selection == VALUE_LIST;
775 return template_selection == COMPLEMENTED_LIST;
776 default:
777 TTCN_error("Matching with an uninitialized/unsupported objid template.");
778 }
779 return FALSE;
780}
781
782const OBJID& OBJID_template::valueof() const
783{
784 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
785 TTCN_error("Performing a valueof "
786 "or send operation on a non-specific objid template.");
787 return single_value;
788}
789
790int OBJID_template::size_of() const
791{
792 switch (template_selection)
793 {
794 case SPECIFIC_VALUE:
795 return single_value.size_of();
796 case OMIT_VALUE:
797 TTCN_error("Performing sizeof() operation on an objid template "
798 "containing omit value.");
799 case ANY_VALUE:
800 case ANY_OR_OMIT:
801 TTCN_error("Performing sizeof() operation on a */? objid template.");
802 case VALUE_LIST:
803 {
804 if (value_list.n_values<1)
805 TTCN_error("Internal error: "
806 "Performing sizeof() operation on an objid template "
807 "containing an empty list.");
808 int item_size = value_list.list_value[0].size_of();
809 for (unsigned int i = 1; i < value_list.n_values; i++) {
810 if (value_list.list_value[i].size_of()!=item_size)
811 TTCN_error("Performing sizeof() operation on an objid template "
812 "containing a value list with different sizes.");
813 }
814 return item_size;
815 }
816 case COMPLEMENTED_LIST:
817 TTCN_error("Performing sizeof() operation on an objid template "
818 "containing complemented list.");
819 default:
820 TTCN_error("Performing sizeof() operation on an "
821 "uninitialized/unsupported objid template.");
822 }
823 return 0;
824}
825
826void OBJID_template::set_type(template_sel template_type,
827 unsigned int list_length)
828{
829 if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST)
830 TTCN_error("Setting an invalid list type for an objid template.");
831 clean_up();
832 set_selection(template_type);
833 value_list.n_values = list_length;
834 value_list.list_value = new OBJID_template[list_length];
835}
836
837OBJID_template& OBJID_template::list_item(unsigned int list_index)
838{
839 if (template_selection != VALUE_LIST &&
840 template_selection != COMPLEMENTED_LIST)
841 TTCN_error("Accessing a list element of a non-list objid template.");
842 if (list_index >= value_list.n_values)
843 TTCN_error("Index overflow in an objid value list template.");
844 return value_list.list_value[list_index];
845}
846
847void OBJID_template::log() const
848{
849 switch (template_selection) {
850 case SPECIFIC_VALUE:
851 single_value.log();
852 break;
853 case COMPLEMENTED_LIST:
854 TTCN_Logger::log_event_str("complement ");
855 // no break
856 case VALUE_LIST:
857 TTCN_Logger::log_char('(');
858 for(unsigned int i = 0; i < value_list.n_values; i++) {
859 if (i > 0) TTCN_Logger::log_event_str(", ");
860 value_list.list_value[i].log();
861 }
862 TTCN_Logger::log_char(')');
863 break;
864 default:
865 log_generic();
866 break;
867 }
868 log_ifpresent();
869}
870
3abe9331 871void OBJID_template::log_match(const OBJID& match_value,
872 boolean /* legacy */) const
970ed795
EL
873{
874 if (TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()
875 && TTCN_Logger::get_logmatch_buffer_len() != 0) {
876 TTCN_Logger::print_logmatch_buffer();
877 TTCN_Logger::log_event_str(" := ");
878 }
879 match_value.log();
880 TTCN_Logger::log_event_str(" with ");
881 log();
882 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
883 else TTCN_Logger::log_event_str(" unmatched");
884}
885
886void OBJID_template::set_param(Module_Param& param) {
887 param.basic_check(Module_Param::BC_TEMPLATE, "objid template");
3abe9331 888 Module_Param_Ptr mp = &param;
889 if (param.get_type() == Module_Param::MP_Reference) {
890 mp = param.get_referenced_param();
891 }
892 switch (mp->get_type()) {
970ed795
EL
893 case Module_Param::MP_Omit:
894 *this = OMIT_VALUE;
895 break;
896 case Module_Param::MP_Any:
897 *this = ANY_VALUE;
898 break;
899 case Module_Param::MP_AnyOrNone:
900 *this = ANY_OR_OMIT;
901 break;
902 case Module_Param::MP_List_Template:
3abe9331 903 case Module_Param::MP_ComplementList_Template: {
904 OBJID_template temp;
905 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
906 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
907 for (size_t i=0; i<mp->get_size(); i++) {
908 temp.list_item(i).set_param(*mp->get_elem(i));
970ed795 909 }
3abe9331 910 *this = temp;
911 break; }
970ed795
EL
912 case Module_Param::MP_Objid:
913 if (sizeof(OBJID::objid_element)!=sizeof(int)) TTCN_error("Internal error: OBJID_template::set_param()");
3abe9331 914 *this = OBJID(mp->get_string_size(), (OBJID::objid_element*)mp->get_string_data());
970ed795
EL
915 break;
916 //case Module_Param::MP_Objid_Template:
917 // TODO
918 //break;
919 default:
920 param.type_error("objid template");
921 }
3abe9331 922 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
923}
924
925Module_Param* OBJID_template::get_param(Module_Param_Name& param_name) const
926{
927 Module_Param* mp = NULL;
928 switch (template_selection) {
929 case UNINITIALIZED_TEMPLATE:
930 mp = new Module_Param_Unbound();
931 break;
932 case OMIT_VALUE:
933 mp = new Module_Param_Omit();
934 break;
935 case ANY_VALUE:
936 mp = new Module_Param_Any();
937 break;
938 case ANY_OR_OMIT:
939 mp = new Module_Param_AnyOrNone();
940 break;
941 case SPECIFIC_VALUE:
942 mp = single_value.get_param(param_name);
943 break;
944 case VALUE_LIST:
945 case COMPLEMENTED_LIST: {
946 if (template_selection == VALUE_LIST) {
947 mp = new Module_Param_List_Template();
948 }
949 else {
950 mp = new Module_Param_ComplementList_Template();
951 }
952 for (size_t i = 0; i < value_list.n_values; ++i) {
953 mp->add_elem(value_list.list_value[i].get_param(param_name));
954 }
955 break; }
956 default:
957 break;
958 }
959 if (is_ifpresent) {
960 mp->set_ifpresent();
961 }
962 return mp;
970ed795
EL
963}
964
965void OBJID_template::encode_text(Text_Buf& text_buf) const
966{
967 encode_text_base(text_buf);
968 switch (template_selection) {
969 case OMIT_VALUE:
970 case ANY_VALUE:
971 case ANY_OR_OMIT:
972 break;
973 case SPECIFIC_VALUE:
974 single_value.encode_text(text_buf);
975 break;
976 case VALUE_LIST:
977 case COMPLEMENTED_LIST:
978 text_buf.push_int(value_list.n_values);
979 for (unsigned int i = 0; i < value_list.n_values; i++)
980 value_list.list_value[i].encode_text(text_buf);
981 break;
982 default:
983 TTCN_error("Text encoder: Encoding an undefined/unsupported objid "
984 "template.");
985 }
986}
987
988void OBJID_template::decode_text(Text_Buf& text_buf)
989{
990 clean_up();
991 decode_text_base(text_buf);
992 switch (template_selection) {
993 case OMIT_VALUE:
994 case ANY_VALUE:
995 case ANY_OR_OMIT:
996 break;
997 case SPECIFIC_VALUE:
998 single_value.decode_text(text_buf);
999 break;
1000 case VALUE_LIST:
1001 case COMPLEMENTED_LIST:
1002 value_list.n_values = text_buf.pull_int().get_val();
1003 value_list.list_value = new OBJID_template[value_list.n_values];
1004 for (unsigned int i = 0; i < value_list.n_values; i++)
1005 value_list.list_value[i].decode_text(text_buf);
1006 break;
1007 default:
1008 TTCN_error("Text decoder: An unknown/unsupported selection was "
1009 "received for an objid template.");
1010 }
1011}
1012
3abe9331 1013boolean OBJID_template::is_present(boolean legacy /* = FALSE */) const
970ed795
EL
1014{
1015 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
3abe9331 1016 return !match_omit(legacy);
970ed795
EL
1017}
1018
3abe9331 1019boolean OBJID_template::match_omit(boolean legacy /* = FALSE */) const
970ed795
EL
1020{
1021 if (is_ifpresent) return TRUE;
1022 switch (template_selection) {
1023 case OMIT_VALUE:
1024 case ANY_OR_OMIT:
1025 return TRUE;
1026 case VALUE_LIST:
1027 case COMPLEMENTED_LIST:
3abe9331 1028 if (legacy) {
1029 // legacy behavior: 'omit' can appear in the value/complement list
1030 for (unsigned int i=0; i<value_list.n_values; i++)
1031 if (value_list.list_value[i].match_omit())
1032 return template_selection==VALUE_LIST;
1033 return template_selection==COMPLEMENTED_LIST;
1034 }
1035 // else fall through
970ed795
EL
1036 default:
1037 return FALSE;
1038 }
1039 return FALSE;
1040}
1041
1042#ifndef TITAN_RUNTIME_2
3abe9331 1043void OBJID_template::check_restriction(template_res t_res, const char* t_name,
1044 boolean legacy /* = FALSE */) const
970ed795
EL
1045{
1046 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1047 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1048 case TR_VALUE:
1049 if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;
1050 break;
1051 case TR_OMIT:
1052 if (!is_ifpresent && (template_selection==OMIT_VALUE ||
1053 template_selection==SPECIFIC_VALUE)) return;
1054 break;
1055 case TR_PRESENT:
3abe9331 1056 if (!match_omit(legacy)) return;
970ed795
EL
1057 break;
1058 default:
1059 return;
1060 }
1061 TTCN_error("Restriction `%s' on template of type %s violated.",
1062 get_res_name(t_res), t_name ? t_name : "objid");
1063}
1064#endif
This page took 0.064318 seconds and 5 git commands to generate.