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