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