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 ///////////////////////////////////////////////////////////////////////////////
12 #include "Param_Types.hh"
15 #include "Basetype.hh"
16 #include "Template.hh"
17 #include "Optional.hh"
18 #include "Parameters.h"
20 #include "Struct_of.hh"
25 extern unsigned int get_timer_array_index(int index_value,
26 unsigned int array_size, int index_offset);
27 extern unsigned int get_timer_array_index(const INTEGER& index_value,
28 unsigned int array_size, int index_offset);
30 /** @brief Runtime implementation of timer arrays.
32 * @param T_type the type of the array element. This can be \c TIMER_ARRAY
33 * for multi-dimensional arrays.
34 * @param array_size the number of elements in the array
35 * @param index_offset the lowest index
38 template <typename T_type, unsigned int array_size, int index_offset>
40 T_type array_elements[array_size];
41 char * names[array_size];
43 /// Copy constructor disallowed.
44 TIMER_ARRAY(const TIMER_ARRAY& other_value);
45 /// Assignment disallowed.
46 TIMER_ARRAY& operator=(const TIMER_ARRAY& other_value);
52 for (size_t i = 0; i < array_size; ++i) {
57 T_type& operator[](int index_value) { return array_elements[
58 get_timer_array_index(index_value, array_size, index_offset)]; }
59 T_type& operator[](const INTEGER& index_value) { return array_elements[
60 get_timer_array_index(index_value, array_size, index_offset)]; }
62 int n_elem() const { return array_size; }
63 int size_of() const { return array_size; }
64 int lengthof() const { return array_size; }
66 T_type& array_element(unsigned int index_value)
67 { return array_elements[index_value]; }
69 void set_name(const char * name_string)
71 for (int i = 0; i < (int)array_size; ++i) {
72 // index_offset may be negative, hence i must be int (not size_t)
73 // to ensure that signed arithmetic is used.
74 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
75 array_elements[i].set_name(names[i]);
81 TTCN_Logger::log_event_str("{ ");
82 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
83 if (v_index > 0) TTCN_Logger::log_event_str(", ");
84 array_elements[v_index].log();
86 TTCN_Logger::log_event_str(" }");
89 #ifdef TITAN_RUNTIME_2
90 // Dummy functions, only used in record of/set of in RT2 (the referenced indices
91 // cannot be deleted, since arrays have a fixed size)
92 void add_refd_index(int) {}
93 void remove_refd_index(int) {}
97 extern unsigned int get_port_array_index(int index_value,
98 unsigned int array_size, int index_offset);
99 extern unsigned int get_port_array_index(const INTEGER& index_value,
100 unsigned int array_size, int index_offset);
102 template <typename T_type, unsigned int array_size, int index_offset>
104 T_type array_elements[array_size];
105 char * names[array_size];
107 /// Copy constructor disallowed.
108 PORT_ARRAY(const PORT_ARRAY& other_value);
109 /// Assignment disallowed.
110 PORT_ARRAY& operator=(const PORT_ARRAY& other_value);
116 for (size_t i = 0; i < array_size; ++i) {
121 T_type& operator[](int index_value) { return array_elements[
122 get_port_array_index(index_value, array_size, index_offset)]; }
123 T_type& operator[](const INTEGER& index_value) { return array_elements[
124 get_port_array_index(index_value, array_size, index_offset)]; }
126 int n_elem() const { return array_size; }
127 int size_of() const { return array_size; }
128 int lengthof()const { return array_size; }
130 void set_name(const char * name_string)
132 for (int i = 0; i < (int)array_size; ++i) {
133 // i must be int, see comment in TIMER_ARRAY::set_name
134 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
135 array_elements[i].set_name(names[i]);
141 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
142 array_elements[v_index].activate_port();
148 TTCN_Logger::log_event_str("{ ");
149 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
150 if (v_index > 0) TTCN_Logger::log_event_str(", ");
151 array_elements[v_index].log();
153 TTCN_Logger::log_event_str(" }");
156 #ifdef TITAN_RUNTIME_2
157 // Dummy functions, only used in record of/set of in RT2 (the referenced indices
158 // cannot be deleted, since arrays have a fixed size)
159 void add_refd_index(int) {}
160 void remove_refd_index(int) {}
164 ////////////////////////////////////////////////////////////////////////////////
166 extern unsigned int get_array_index(int index_value,
167 unsigned int array_size, int index_offset);
168 extern unsigned int get_array_index(const INTEGER& index_value,
169 unsigned int array_size, int index_offset);
171 template <typename T_type, unsigned int array_size, int index_offset>
172 class VALUE_ARRAY : public Base_Type
174 T_type array_elements[array_size];
176 // This class use the compiler-generated copy constructor and
179 boolean operator==(const VALUE_ARRAY& other_value) const;
180 inline boolean operator!=(const VALUE_ARRAY& other_value) const
181 { return !(*this == other_value); }
183 T_type& operator[](int index_value) { return array_elements[
184 get_array_index(index_value, array_size, index_offset)]; }
185 T_type& operator[](const INTEGER& index_value) { return array_elements[
186 get_array_index(index_value, array_size, index_offset)]; }
187 const T_type& operator[](int index_value) const { return array_elements[
188 get_array_index(index_value, array_size, index_offset)]; }
189 const T_type& operator[](const INTEGER& index_value) const {
190 return array_elements[
191 get_array_index(index_value, array_size, index_offset)];
195 VALUE_ARRAY operator<<=(int rotate_count) const;
196 VALUE_ARRAY operator<<=(const INTEGER& rotate_count) const;
197 VALUE_ARRAY operator>>=(int rotate_count) const;
198 VALUE_ARRAY operator>>=(const INTEGER& rotate_count) const;
200 T_type& array_element(unsigned int index_value)
201 { return array_elements[index_value]; }
202 const T_type& array_element(unsigned int index_value) const
203 { return array_elements[index_value]; }
205 void set_implicit_omit();
207 boolean is_bound() const;
208 boolean is_value() const;
212 inline int n_elem() const { return array_size; }
213 inline int size_of() const { return array_size; }
214 int lengthof() const;
216 void set_param(Module_Param& param);
218 #ifdef TITAN_RUNTIME_2
219 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
220 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
221 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
222 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
224 inline boolean is_present() const { return is_bound(); }
227 void encode_text(Text_Buf& text_buf) const;
228 void decode_text(Text_Buf& text_buf);
230 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
231 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
233 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
234 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
236 /** Encodes accordingly to the JSON encoding rules.
237 * Returns the length of the encoded data. */
238 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
240 /** Decodes accordingly to the JSON encoding rules.
241 * Returns the length of the decoded data. */
242 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
244 #ifdef TITAN_RUNTIME_2
245 // Dummy functions, only used in record of/set of in RT2 (the referenced indices
246 // cannot be deleted, since arrays have a fixed size)
247 void add_refd_index(int) {}
248 void remove_refd_index(int) {}
252 template <typename T_type, unsigned int array_size, int index_offset>
253 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
254 (const VALUE_ARRAY& other_value) const
256 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
257 if (array_elements[elem_count] != other_value.array_elements[elem_count])
262 template <typename T_type, unsigned int array_size, int index_offset>
263 VALUE_ARRAY<T_type,array_size,index_offset>
264 VALUE_ARRAY<T_type,array_size,index_offset>::
265 operator<<=(int rotate_count) const {
266 return *this >>= (-rotate_count);
269 template <typename T_type, unsigned int array_size, int index_offset>
270 VALUE_ARRAY<T_type,array_size,index_offset>
271 VALUE_ARRAY<T_type,array_size,index_offset>::
272 operator<<=(const INTEGER& rotate_count) const {
273 rotate_count.must_bound("Unbound integer operand of rotate left "
275 return *this >>= (int)(-rotate_count);
278 template <typename T_type, unsigned int array_size, int index_offset>
279 VALUE_ARRAY<T_type,array_size,index_offset>
280 VALUE_ARRAY<T_type,array_size,index_offset>::
281 operator>>=(int rotate_count) const {
283 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
284 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
285 if (rc == 0) return *this;
286 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
287 for (unsigned int i=0; i<array_size; i++) {
288 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
293 template <typename T_type, unsigned int array_size, int index_offset>
294 VALUE_ARRAY<T_type,array_size,index_offset>
295 VALUE_ARRAY<T_type,array_size,index_offset>::
296 operator>>=(const INTEGER& rotate_count) const {
297 rotate_count.must_bound("Unbound integer operand of rotate right "
299 return *this >>= (int)rotate_count;
302 template <typename T_type, unsigned int array_size, int index_offset>
303 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
305 for (unsigned int i = 0; i < array_size; ++i) {
306 if (array_elements[i].is_bound())
307 array_elements[i].set_implicit_omit();
311 template <typename T_type, unsigned int array_size, int index_offset>
312 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
314 for (unsigned int i = 0; i < array_size; ++i) {
315 if (!array_elements[i].is_bound()) {
322 template <typename T_type, unsigned int array_size, int index_offset>
323 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
325 for (unsigned int i = 0; i < array_size; ++i) {
326 if (!array_elements[i].is_value()) {
333 template <typename T_type, unsigned int array_size, int index_offset>
334 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
336 for (unsigned int i = 0; i < array_size; ++i) {
337 array_elements[i].clean_up();
341 template <typename T_type, unsigned int array_size, int index_offset>
342 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
344 TTCN_Logger::log_event_str("{ ");
345 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
347 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
348 array_elements[elem_count].log();
350 TTCN_Logger::log_event_str(" }");
353 template <typename T_type, unsigned int array_size, int index_offset>
354 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
357 for (unsigned int my_length=array_size; my_length>0; my_length--)
359 if (array_elements[my_length-1].is_bound()) return my_length;
364 template <typename T_type, unsigned int array_size, int index_offset>
365 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
368 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
369 param.get_id()->next_name()) {
370 // Haven't reached the end of the module parameter name
371 // => the name refers to one of the elements, not to the whole array
372 char* param_field = param.get_id()->get_current_name();
373 if (param_field[0] < '0' || param_field[0] > '9') {
374 param.error("Unexpected record field name in module parameter, expected a valid"
377 unsigned int param_index = -1;
378 sscanf(param_field, "%u", ¶m_index);
379 if (param_index >= array_size) {
380 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
382 array_elements[param_index].set_param(param);
386 param.basic_check(Module_Param::BC_VALUE, "array value");
387 switch (param.get_type()) {
388 case Module_Param::MP_Value_List:
389 if (param.get_size()!=array_size) {
390 param.error("The array value has incorrect number of elements: %lu was expected instead of %lu.", (unsigned long)param.get_size(), (unsigned long)array_size);
392 for (size_t i=0; i<param.get_size(); ++i) {
393 Module_Param* const curr = param.get_elem(i);
394 if (curr->get_type()!=Module_Param::MP_NotUsed) {
395 array_elements[i].set_param(*curr);
399 case Module_Param::MP_Indexed_List:
400 for (size_t i=0; i<param.get_size(); ++i) {
401 Module_Param* const curr = param.get_elem(i);
402 array_elements[curr->get_id()->get_index()].set_param(*curr);
406 param.type_error("array value");
410 template <typename T_type, unsigned int array_size, int index_offset>
411 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
412 (Text_Buf& text_buf) const
414 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
415 array_elements[elem_count].encode_text(text_buf);
418 template <typename T_type, unsigned int array_size, int index_offset>
419 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
422 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
423 array_elements[elem_count].decode_text(text_buf);
426 template <typename T_type, unsigned int array_size, int index_offset>
427 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
428 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
431 va_start(pvar, p_coding);
433 case TTCN_EncDec::CT_JSON: {
434 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
435 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
436 ("No JSON descriptor available for type '%s'.", p_td.name);
437 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
438 JSON_encode(p_td, tok);
439 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
442 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
447 template <typename T_type, unsigned int array_size, int index_offset>
448 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
449 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
452 case TTCN_EncDec::CT_JSON: {
453 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
454 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
455 ("No JSON descriptor available for type '%s'.", p_td.name);
456 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
457 if(JSON_decode(p_td, tok, false)<0)
458 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
459 "because invalid or incomplete message was received", p_td.name);
460 p_buf.set_pos(tok.get_buf_pos());
463 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
467 template <typename T_type, unsigned int array_size, int index_offset>
468 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
469 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
472 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
473 "Encoding an unbound array value.");
477 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
479 for(unsigned int i = 0; i < array_size; ++i) {
480 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
481 if (0 > ret_val) break;
485 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
489 template <typename T_type, unsigned int array_size, int index_offset>
490 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
491 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)
493 json_token_t token = JSON_TOKEN_NONE;
494 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
495 if (JSON_TOKEN_ERROR == token) {
496 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
497 return JSON_ERROR_FATAL;
499 else if (JSON_TOKEN_ARRAY_START != token) {
500 return JSON_ERROR_INVALID_TOKEN;
503 for(unsigned int i = 0; i < array_size; ++i) {
504 int ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
505 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
506 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
507 array_size - i, (array_size - i > 1) ? "s" : "");
508 return JSON_ERROR_FATAL;
510 else if (JSON_ERROR_FATAL == ret_val) {
514 return JSON_ERROR_FATAL;
519 dec_len += p_tok.get_next_token(&token, NULL, NULL);
520 if (JSON_TOKEN_ARRAY_END != token) {
521 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
525 return JSON_ERROR_FATAL;
532 template <typename T_value_type, typename T_template_type,
533 unsigned int array_size, int index_offset>
534 class TEMPLATE_ARRAY : public Restricted_Length_Template
540 T_template_type **value_elements;
543 unsigned int n_values;
544 TEMPLATE_ARRAY *list_value;
548 struct Pair_of_elements;
549 Pair_of_elements *permutation_intervals;
550 unsigned int number_of_permutations;
552 void clean_up_intervals();
553 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
555 void copy_template(const TEMPLATE_ARRAY& other_value);
556 void set_selection(template_sel new_selection);
557 void set_selection(const TEMPLATE_ARRAY& other_value);
558 void encode_text_permutation(Text_Buf& text_buf) const;
559 void decode_text_permutation(Text_Buf& text_buf);
564 number_of_permutations = 0;
565 permutation_intervals = NULL;
567 TEMPLATE_ARRAY(template_sel other_value)
568 : Restricted_Length_Template(other_value)
570 check_single_selection(other_value);
571 number_of_permutations = 0;
572 permutation_intervals = NULL;
574 TEMPLATE_ARRAY(null_type other_value);
575 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
578 number_of_permutations = 0;
579 permutation_intervals = NULL;
580 copy_value(other_value);
583 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
584 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
585 : Restricted_Length_Template()
587 number_of_permutations = 0;
588 permutation_intervals = NULL;
589 copy_template(other_value);
594 clean_up_intervals();
599 TEMPLATE_ARRAY& operator=(template_sel other_value);
600 TEMPLATE_ARRAY& operator=(null_type other_value);
601 TEMPLATE_ARRAY& operator=(const
602 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
603 TEMPLATE_ARRAY& operator=(const
604 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
605 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
607 T_template_type& operator[](int index_value);
608 T_template_type& operator[](const INTEGER& index_value);
609 const T_template_type& operator[](int index_value) const;
610 const T_template_type& operator[](const INTEGER& index_value) const;
612 void set_size(int new_size);
615 int size_of(boolean is_size) const;
616 inline int size_of() const { return size_of(TRUE); }
617 inline int lengthof() const { return size_of(FALSE); }
619 void add_permutation(unsigned int start_index, unsigned int end_index);
621 /** Removes all permutations set on this template, used when template variables
622 * are given new values. */
623 void remove_all_permutations() { clean_up_intervals(); }
625 unsigned int get_number_of_permutations() const;
626 unsigned int get_permutation_start(unsigned int index_value) const;
627 unsigned int get_permutation_end(unsigned int index_value) const;
628 unsigned int get_permutation_size(unsigned int index_value) const;
629 boolean permutation_starts_at(unsigned int index_value) const;
630 boolean permutation_ends_at(unsigned int index_value) const;
633 static boolean match_function_specific(
634 const Base_Type *value_ptr, int value_index,
635 const Restricted_Length_Template *template_ptr, int template_index);
637 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
640 boolean is_value() const;
641 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
643 void set_type(template_sel template_type, unsigned int list_length);
644 TEMPLATE_ARRAY& list_item(unsigned int list_index);
647 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
650 void set_param(Module_Param& param);
652 void encode_text(Text_Buf& text_buf) const;
653 void decode_text(Text_Buf& text_buf);
655 boolean is_present() const;
656 boolean match_omit() const;
658 #ifdef TITAN_RUNTIME_2
659 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
660 void set_value(template_sel other_value) { *this = other_value; }
661 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
662 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
663 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
664 boolean matchv(const Base_Type* other_value) const { return match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value))); }
665 void log_matchv(const Base_Type* match_value) const { log_match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(match_value))); }
667 void check_restriction(template_res t_res, const char* t_name=NULL) const;
671 template <typename T_value_type, typename T_template_type,
672 unsigned int array_size, int index_offset>
673 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
675 unsigned int start_index, end_index; //beginning and ending index
678 template <typename T_value_type, typename T_template_type,
679 unsigned int array_size, int index_offset>
680 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
683 switch (template_selection)
686 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
687 delete single_value.value_elements[elem_count];
688 free_pointers((void**)single_value.value_elements);
691 case COMPLEMENTED_LIST:
692 delete [] value_list.list_value;
697 template_selection = UNINITIALIZED_TEMPLATE;
700 template <typename T_value_type, typename T_template_type,
701 unsigned int array_size, int index_offset>
702 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
705 number_of_permutations = 0;
706 Free(permutation_intervals);
707 permutation_intervals = NULL;
710 template <typename T_value_type, typename T_template_type,
711 unsigned int array_size, int index_offset>
712 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
713 set_selection(template_sel other_value)
715 Restricted_Length_Template::set_selection(other_value);
716 clean_up_intervals();
719 template <typename T_value_type, typename T_template_type,
720 unsigned int array_size, int index_offset>
721 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
722 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
724 Restricted_Length_Template::set_selection(other_value);
725 clean_up_intervals();
726 if(other_value.template_selection == SPECIFIC_VALUE)
728 number_of_permutations = other_value.number_of_permutations;
729 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
730 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
734 template <typename T_value_type, typename T_template_type,
735 unsigned int array_size, int index_offset>
736 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
737 encode_text_permutation(Text_Buf& text_buf) const
739 encode_text_restricted(text_buf);
740 text_buf.push_int(number_of_permutations);
742 for(unsigned int i = 0; i < number_of_permutations; i++)
744 text_buf.push_int(permutation_intervals[i].start_index);
745 text_buf.push_int(permutation_intervals[i].end_index);
749 template <typename T_value_type, typename T_template_type,
750 unsigned int array_size, int index_offset>
751 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
752 decode_text_permutation(Text_Buf& text_buf)
754 decode_text_restricted(text_buf);
756 number_of_permutations = text_buf.pull_int().get_val();
757 permutation_intervals = (Pair_of_elements *)Malloc
758 (number_of_permutations * sizeof(Pair_of_elements));
760 for (unsigned int i = 0; i < number_of_permutations; i++)
762 permutation_intervals[i].start_index =
763 text_buf.pull_int().get_val();
764 permutation_intervals[i].end_index =
765 text_buf.pull_int().get_val();
769 template <typename T_value_type, typename T_template_type,
770 unsigned int array_size, int index_offset>
771 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
772 add_permutation(unsigned int start_index, unsigned int end_index)
774 if(start_index > end_index)
775 TTCN_error("wrong permutation interval settings start (%d)"
776 "can not be greater than end (%d)",start_index, end_index);
778 if(number_of_permutations > 0 &&
779 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
780 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
782 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
783 permutation_intervals[number_of_permutations].start_index = start_index;
784 permutation_intervals[number_of_permutations].end_index = end_index;
785 number_of_permutations++;
788 template <typename T_value_type, typename T_template_type,
789 unsigned int array_size, int index_offset>
790 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
791 get_number_of_permutations(void) const
793 return number_of_permutations;
796 template <typename T_value_type, typename T_template_type,
797 unsigned int array_size, int index_offset>
798 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
799 get_permutation_start(unsigned int index_value) const
801 if(index_value >= number_of_permutations)
802 TTCN_error("Index overflow (%d)", index_value);
804 return permutation_intervals[index_value].start_index;
807 template <typename T_value_type, typename T_template_type,
808 unsigned int array_size, int index_offset>
809 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
810 get_permutation_end(unsigned int index_value) const
812 if(index_value >= number_of_permutations)
813 TTCN_error("Index overflow (%d)", index_value);
815 return permutation_intervals[index_value].end_index;
818 template <typename T_value_type, typename T_template_type,
819 unsigned int array_size, int index_offset>
820 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
821 get_permutation_size(unsigned int index_value) const
823 if(index_value >= number_of_permutations)
824 TTCN_error("Index overflow (%d)", index_value);
826 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
829 template <typename T_value_type, typename T_template_type,
830 unsigned int array_size, int index_offset>
831 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
832 permutation_starts_at(unsigned int index_value) const
834 for(unsigned int i = 0; i < number_of_permutations; i++)
836 if(permutation_intervals[i].start_index == index_value)
843 template <typename T_value_type, typename T_template_type,
844 unsigned int array_size, int index_offset>
845 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
846 permutation_ends_at(unsigned int index_value) const
848 for(unsigned int i = 0; i < number_of_permutations; i++)
850 if(permutation_intervals[i].end_index == index_value)
857 template <typename T_value_type, typename T_template_type,
858 unsigned int array_size, int index_offset>
859 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
860 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
863 single_value.n_elements = array_size;
864 single_value.value_elements =
865 (T_template_type**)allocate_pointers(array_size);
866 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
867 single_value.value_elements[elem_count] =
868 new T_template_type(other_value.array_element(elem_count));
869 set_selection(SPECIFIC_VALUE);
872 template <typename T_value_type, typename T_template_type,
873 unsigned int array_size, int index_offset>
874 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
875 copy_template(const TEMPLATE_ARRAY& other_value)
877 switch (other_value.template_selection)
880 single_value.n_elements = other_value.single_value.n_elements;
881 single_value.value_elements =
882 (T_template_type**)allocate_pointers(single_value.n_elements);
883 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
884 single_value.value_elements[elem_count] = new
885 T_template_type(*other_value.single_value.value_elements[elem_count]);
892 case COMPLEMENTED_LIST:
893 value_list.n_values = other_value.value_list.n_values;
894 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
895 for (unsigned int list_count = 0; list_count < value_list.n_values;
897 value_list.list_value[list_count].copy_template(
898 other_value.value_list.list_value[list_count]);
901 TTCN_error("Copying an uninitialized/unsupported array template.");
903 set_selection(other_value);
906 template <typename T_value_type, typename T_template_type,
907 unsigned int array_size, int index_offset>
908 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
909 TEMPLATE_ARRAY(null_type)
910 : Restricted_Length_Template(SPECIFIC_VALUE)
912 single_value.n_elements = 0;
913 single_value.value_elements = NULL;
914 number_of_permutations = 0;
915 permutation_intervals = NULL;
918 template <typename T_value_type, typename T_template_type,
919 unsigned int array_size, int index_offset>
920 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
922 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
924 number_of_permutations = 0;
925 permutation_intervals = NULL;
926 switch (other_value.get_selection()) {
927 case OPTIONAL_PRESENT:
928 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
932 set_selection(OMIT_VALUE);
935 TTCN_error("Creating an array template from an unbound optional field.");
939 template <typename T_value_type, typename T_template_type,
940 unsigned int array_size, int index_offset>
941 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
942 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
943 operator=(template_sel other_value)
945 check_single_selection(other_value);
947 set_selection(other_value);
951 template <typename T_value_type, typename T_template_type,
952 unsigned int array_size, int index_offset>
953 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
954 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
958 set_selection(SPECIFIC_VALUE);
959 single_value.n_elements = 0;
960 single_value.value_elements = NULL;
964 template <typename T_value_type, typename T_template_type,
965 unsigned int array_size, int index_offset>
966 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
967 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
968 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
971 copy_value(other_value);
975 template <typename T_value_type, typename T_template_type,
976 unsigned int array_size, int index_offset>
977 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
978 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
980 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
983 switch (other_value.get_selection()) {
984 case OPTIONAL_PRESENT:
985 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
989 set_selection(OMIT_VALUE);
992 TTCN_error("Assignment of an unbound optional field to an array template.");
997 template <typename T_value_type, typename T_template_type,
998 unsigned int array_size, int index_offset>
999 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1000 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1002 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1005 if (&other_value != this)
1008 copy_template(other_value);
1013 template <typename T_value_type, typename T_template_type,
1014 unsigned int array_size, int index_offset>
1016 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1019 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1021 "Accessing an element of an array template using invalid index: %d. "
1022 "Index range is [%d,%d].",
1023 index_value, index_offset, index_offset+(int)array_size);
1024 // transform index value according to given offset
1025 index_value -= index_offset;
1026 // the template of an array is not restricted to array_size, allow any length
1027 // in case of * or ? expand to full size to avoid uninitialized values
1028 switch (template_selection)
1030 case SPECIFIC_VALUE:
1031 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1035 set_size(array_size);
1038 set_size(index_value + 1);
1040 return *single_value.value_elements[index_value];
1043 template <typename T_value_type, typename T_template_type,
1044 unsigned int array_size, int index_offset>
1046 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1047 (const INTEGER& index_value)
1049 index_value.must_bound(
1050 "Using an unbound integer value for indexing an array template.");
1051 return (*this)[(int)index_value];
1054 template <typename T_value_type, typename T_template_type,
1055 unsigned int array_size, int index_offset>
1056 const T_template_type&
1057 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1058 (int index_value) const
1060 if (index_value < index_offset)
1062 "Accessing an element of an array template using invalid index: %d. "
1063 "Index range starts at %d.",
1064 index_value, index_offset);
1065 // transform index value according to given offset
1066 index_value -= index_offset;
1067 // const is specific template
1068 if (template_selection != SPECIFIC_VALUE)
1069 TTCN_error("Accessing an element of a non-specific array template.");
1070 if (index_value >= single_value.n_elements)
1071 TTCN_error("Index overflow in an array template: "
1072 "The index is %d (starting at %d),"
1073 " but the template has only %d elements.",
1074 index_value+index_offset, index_offset, single_value.n_elements);
1075 return *single_value.value_elements[index_value];
1078 template <typename T_value_type, typename T_template_type,
1079 unsigned int array_size, int index_offset>
1080 const T_template_type&
1081 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1082 (const INTEGER& index_value) const
1084 index_value.must_bound(
1085 "Using an unbound integer value for indexing an array template.");
1086 return (*this)[(int)index_value];
1089 template <typename T_value_type, typename T_template_type,
1090 unsigned int array_size, int index_offset>
1091 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1092 set_size(int new_size)
1094 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1095 "for an array template.");
1096 template_sel old_selection = template_selection;
1097 if (old_selection != SPECIFIC_VALUE)
1100 set_selection(SPECIFIC_VALUE);
1101 single_value.n_elements = 0;
1102 single_value.value_elements = NULL;
1104 if (new_size > single_value.n_elements)
1106 single_value.value_elements =
1107 (T_template_type**)reallocate_pointers(
1108 (void**)single_value.value_elements, single_value.n_elements, new_size);
1109 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1111 for (int elem_count = single_value.n_elements;
1112 elem_count < new_size; elem_count++)
1113 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1117 for (int elem_count = single_value.n_elements;
1118 elem_count < new_size; elem_count++)
1119 single_value.value_elements[elem_count] = new T_template_type;
1121 single_value.n_elements = new_size;
1123 else if (new_size < single_value.n_elements)
1125 for (int elem_count = new_size; elem_count < single_value.n_elements;
1127 delete single_value.value_elements[elem_count];
1128 single_value.value_elements =
1129 (T_template_type**)reallocate_pointers(
1130 (void**)single_value.value_elements, single_value.n_elements, new_size);
1131 single_value.n_elements = new_size;
1135 template <typename T_value_type, typename T_template_type,
1136 unsigned int array_size, int index_offset>
1137 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1140 switch (template_selection) {
1141 case SPECIFIC_VALUE:
1142 return single_value.n_elements;
1144 return value_list.n_values;
1146 TTCN_error("Performing n_elem");
1150 template <typename T_value_type, typename T_template_type,
1151 unsigned int array_size, int index_offset>
1152 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1153 size_of(boolean is_size) const
1155 const char* op_name = is_size ? "size" : "length";
1157 boolean has_any_or_none;
1159 TTCN_error("Performing %sof() operation on an array template "
1160 "which has an ifpresent attribute.", op_name);
1161 switch (template_selection)
1163 case SPECIFIC_VALUE: {
1165 has_any_or_none = FALSE;
1166 int elem_count = single_value.n_elements;
1167 if (!is_size) { // lengthof()
1168 while (elem_count>0 &&
1169 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1171 for (int i=0; i<elem_count; i++)
1173 switch (single_value.value_elements[i]->get_selection())
1176 TTCN_error("Performing %sof() operation on an array template "
1177 "containing omit element.", op_name);
1179 has_any_or_none = TRUE;
1188 TTCN_error("Performing %sof() operation on an array template "
1189 "containing omit value.", op_name);
1193 has_any_or_none = TRUE; // max. size is infinity
1196 // error if any element does not have size or the sizes differ
1197 if (value_list.n_values<1)
1198 TTCN_error("Performing %sof() operation on an array template "
1199 "containing an empty list.", op_name);
1200 int item_size = value_list.list_value[0].size_of(is_size);
1201 for (unsigned int i = 1; i < value_list.n_values; i++) {
1202 if (value_list.list_value[i].size_of(is_size)!=item_size)
1203 TTCN_error("Performing %sof() operation on an array template "
1204 "containing a value list with different sizes.", op_name);
1206 min_size = item_size;
1207 has_any_or_none = FALSE;
1209 case COMPLEMENTED_LIST:
1210 TTCN_error("Performing %sof() operation on an array template "
1211 "containing complemented list.", op_name);
1213 TTCN_error("Performing %sof() operation on an "
1214 "uninitialized/unsupported array template.", op_name);
1216 return check_section_is_single(min_size, has_any_or_none,
1217 op_name, "an", "array template");
1220 template <typename T_value_type, typename T_template_type,
1221 unsigned int array_size, int index_offset>
1222 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1223 match_function_specific(const Base_Type *value_ptr, int value_index,
1224 const Restricted_Length_Template *template_ptr,
1227 if (value_index >= 0)
1228 return ((const TEMPLATE_ARRAY*)template_ptr)->
1229 single_value.value_elements[template_index]->
1231 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1232 ->array_element(value_index));
1234 return ((const TEMPLATE_ARRAY*)template_ptr)->
1235 single_value.value_elements[template_index]->is_any_or_omit();
1238 template <typename T_value_type, typename T_template_type,
1239 unsigned int array_size, int index_offset>
1240 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1241 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1244 if (!match_length(array_size)) return FALSE;
1245 switch (template_selection)
1247 case SPECIFIC_VALUE:
1248 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1249 match_function_specific);
1256 case COMPLEMENTED_LIST:
1257 for (unsigned int list_count = 0; list_count < value_list.n_values;
1259 if (value_list.list_value[list_count].match(other_value))
1260 return template_selection == VALUE_LIST;
1261 return template_selection == COMPLEMENTED_LIST;
1263 TTCN_error("Matching with an uninitialized/unsupported array template.");
1268 template <typename T_value_type, typename T_template_type,
1269 unsigned int array_size, int index_offset>
1270 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1273 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1274 for (int i=0; i<single_value.n_elements; i++)
1275 if (!single_value.value_elements[i]->is_value()) return FALSE;
1279 template <typename T_value_type, typename T_template_type,
1280 unsigned int array_size, int index_offset>
1281 VALUE_ARRAY<T_value_type, array_size, index_offset>
1282 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1285 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1286 TTCN_error("Performing a valueof or send operation on a "
1287 "non-specific array template.");
1288 // the size of the template must be the size of the value
1289 if (single_value.n_elements!=array_size)
1290 TTCN_error("Performing a valueof or send operation on a "
1291 "specific array template with invalid size.");
1292 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1293 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1294 ret_val.array_element(elem_count) =
1295 single_value.value_elements[elem_count]->valueof();
1299 template <typename T_value_type, typename T_template_type,
1300 unsigned int array_size, int index_offset>
1301 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1302 set_type(template_sel template_type, unsigned int list_length)
1305 switch (template_type) {
1307 case COMPLEMENTED_LIST:
1308 value_list.n_values = list_length;
1309 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1313 "Internal error: Setting an invalid type for an array template.");
1315 set_selection(template_type);
1318 template <typename T_value_type, typename T_template_type,
1319 unsigned int array_size, int index_offset>
1320 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1321 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1322 list_item(unsigned int list_index)
1324 if (template_selection != VALUE_LIST &&
1325 template_selection != COMPLEMENTED_LIST)
1326 TTCN_error("Internal error: Accessing a list element of a non-list "
1328 if (list_index >= value_list.n_values)
1329 TTCN_error("Internal error: Index overflow in a value list "
1331 return value_list.list_value[list_index];
1334 template <typename T_value_type, typename T_template_type,
1335 unsigned int array_size, int index_offset>
1336 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1339 switch (template_selection)
1341 case SPECIFIC_VALUE:
1342 if (single_value.n_elements > 0)
1344 TTCN_Logger::log_event_str("{ ");
1345 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1347 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1348 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1349 single_value.value_elements[elem_count]->log();
1350 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1352 TTCN_Logger::log_event_str(" }");
1355 TTCN_Logger::log_event_str("{ }");
1357 case COMPLEMENTED_LIST:
1358 TTCN_Logger::log_event_str("complement");
1360 TTCN_Logger::log_char('(');
1361 for (unsigned int list_count = 0; list_count < value_list.n_values;
1364 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1365 value_list.list_value[list_count].log();
1367 TTCN_Logger::log_char(')');
1377 template <typename T_value_type, typename T_template_type,
1378 unsigned int array_size, int index_offset>
1379 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1380 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1383 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1384 if(match(match_value)){
1385 TTCN_Logger::print_logmatch_buffer();
1386 TTCN_Logger::log_event_str(" matched");
1388 if (template_selection == SPECIFIC_VALUE &&
1389 single_value.n_elements == array_size) {
1390 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1391 for (unsigned int elem_count = 0; elem_count < array_size;
1393 if(!single_value.value_elements[elem_count]->
1394 match(match_value.array_element(elem_count))){
1395 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1396 single_value.value_elements[elem_count]->
1397 log_match(match_value.array_element(elem_count));
1398 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1401 log_match_length(array_size);
1403 TTCN_Logger::print_logmatch_buffer();
1405 TTCN_Logger::log_event_str(" with ");
1407 TTCN_Logger::log_event_str(" unmatched");
1412 if (template_selection == SPECIFIC_VALUE &&
1413 single_value.n_elements == array_size) {
1414 TTCN_Logger::log_event_str("{ ");
1415 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1416 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1417 single_value.value_elements[elem_count]->log_match(match_value.array_element(elem_count));
1419 TTCN_Logger::log_event_str(" }");
1420 log_match_length(array_size);
1423 TTCN_Logger::log_event_str(" with ");
1425 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
1426 else TTCN_Logger::log_event_str(" unmatched");
1430 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1431 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1433 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1434 param.get_id()->next_name()) {
1435 // Haven't reached the end of the module parameter name
1436 // => the name refers to one of the elements, not to the whole array
1437 char* param_field = param.get_id()->get_current_name();
1438 if (param_field[0] < '0' || param_field[0] > '9') {
1439 param.error("Unexpected record field name in module parameter, expected a valid"
1440 " array template index");
1442 unsigned int param_index = -1;
1443 sscanf(param_field, "%u", ¶m_index);
1444 if (param_index >= array_size) {
1445 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1447 (*this)[param_index].set_param(param);
1451 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1452 switch (param.get_type()) {
1453 case Module_Param::MP_Omit:
1456 case Module_Param::MP_Any:
1459 case Module_Param::MP_AnyOrNone:
1460 *this = ANY_OR_OMIT;
1462 case Module_Param::MP_List_Template:
1463 case Module_Param::MP_ComplementList_Template:
1464 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
1465 for (size_t i=0; i<param.get_size(); i++) {
1466 list_item(i).set_param(*param.get_elem(i));
1469 case Module_Param::MP_Value_List:
1470 set_size(param.get_size());
1471 for (size_t i=0; i<param.get_size(); ++i) {
1472 Module_Param* const curr = param.get_elem(i);
1473 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1474 (*this)[(int)i+index_offset].set_param(*curr);
1478 case Module_Param::MP_Indexed_List:
1479 for (size_t i=0; i<param.get_size(); ++i) {
1480 Module_Param* const curr = param.get_elem(i);
1481 (*this)[curr->get_id()->get_index()].set_param(*curr);
1485 param.type_error("array template");
1487 is_ifpresent = param.get_ifpresent();
1490 template <typename T_value_type, typename T_template_type,
1491 unsigned int array_size, int index_offset>
1492 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1493 encode_text(Text_Buf& text_buf) const
1495 encode_text_restricted(text_buf);
1496 switch (template_selection)
1498 case SPECIFIC_VALUE:
1499 text_buf.push_int(single_value.n_elements);
1500 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1501 single_value.value_elements[elem_count]->encode_text(text_buf);
1508 case COMPLEMENTED_LIST:
1509 text_buf.push_int(value_list.n_values);
1510 for (unsigned int list_count = 0; list_count < value_list.n_values;
1512 value_list.list_value[list_count].encode_text(text_buf);
1515 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1520 template <typename T_value_type, typename T_template_type,
1521 unsigned int array_size, int index_offset>
1522 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1523 decode_text(Text_Buf& text_buf)
1526 decode_text_restricted(text_buf);
1527 switch (template_selection)
1529 case SPECIFIC_VALUE:
1530 single_value.n_elements = text_buf.pull_int().get_val();
1531 if (single_value.n_elements < 0)
1532 TTCN_error("Text decoder: Negative size was received for an "
1534 single_value.value_elements =
1535 (T_template_type**)allocate_pointers(single_value.n_elements);
1536 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1538 single_value.value_elements[elem_count] = new T_template_type;
1539 single_value.value_elements[elem_count]->decode_text(text_buf);
1547 case COMPLEMENTED_LIST:
1548 value_list.n_values = text_buf.pull_int().get_val();
1549 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1550 for (unsigned int list_count = 0; list_count < value_list.n_values;
1552 value_list.list_value[list_count].decode_text(text_buf);
1555 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1556 "for an array template.");
1560 template <typename T_value_type, typename T_template_type,
1561 unsigned int array_size, int index_offset>
1562 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1565 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1566 return !match_omit();
1569 template <typename T_value_type, typename T_template_type,
1570 unsigned int array_size, int index_offset>
1571 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1574 if (is_ifpresent) return TRUE;
1575 switch (template_selection) {
1580 case COMPLEMENTED_LIST:
1581 for (unsigned int i=0; i<value_list.n_values; i++)
1582 if (value_list.list_value[i].match_omit())
1583 return template_selection==VALUE_LIST;
1584 return template_selection==COMPLEMENTED_LIST;
1591 #ifndef TITAN_RUNTIME_2
1592 template <typename T_value_type, typename T_template_type,
1593 unsigned int array_size, int index_offset>
1594 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1595 check_restriction(template_res t_res, const char* t_name) const
1597 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1598 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1600 if (template_selection==OMIT_VALUE) return;
1602 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1603 for (int i=0; i<single_value.n_elements; i++)
1604 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1607 if (!match_omit()) return;
1612 TTCN_error("Restriction `%s' on template of type %s violated.",
1613 get_res_name(t_res), t_name ? t_name : "array");
1617 template <typename T_value_type, typename T_template_type,
1618 unsigned int array_size, int index_offset>
1619 answer recursive_permutation_match(const Base_Type *value_ptr,
1620 unsigned int value_start_index,
1621 unsigned int value_size,
1622 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1623 unsigned int template_start_index,
1624 unsigned int template_size,
1625 unsigned int permutation_index,
1626 match_function_t match_function,
1627 unsigned int& shift_size)
1629 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1630 if (permutation_index > nof_permutations)
1631 TTCN_error("Internal error: recursive_permutation_match: "
1632 "invalid argument.");
1634 if (permutation_index < nof_permutations &&
1635 template_ptr->get_permutation_end(permutation_index) >
1636 template_start_index + template_size)
1637 TTCN_error("Internal error: recursive_permutation_match: wrong "
1638 "permutation interval settings for permutation %d.",
1644 if(template_size == 0)
1646 //reached the end of templates
1647 // if we reached the end of values => good
1655 //are we at an asterisk or at the beginning of a permutation interval
1656 boolean is_asterisk;
1657 boolean permutation_begins = permutation_index < nof_permutations &&
1658 template_start_index ==
1659 template_ptr->get_permutation_start(permutation_index);
1661 if (permutation_begins ||
1662 match_function(value_ptr, -1, template_ptr, template_start_index))
1664 unsigned int smallest_possible_size;
1665 unsigned int largest_possible_size;
1666 boolean has_asterisk;
1667 boolean already_superset;
1668 unsigned int permutation_size;
1670 //check how many values might be associated with this permutation
1671 //if we are at a permutation start
1672 if (permutation_begins)
1674 is_asterisk = FALSE;
1676 template_ptr->get_permutation_size(permutation_index);
1677 smallest_possible_size = 0;
1678 has_asterisk = FALSE;
1680 //count how many non asterisk elements are in the permutation
1681 for(unsigned int i = 0; i < permutation_size; i++)
1683 if(match_function(value_ptr, -1, template_ptr,
1684 i + template_start_index))
1686 has_asterisk = TRUE;
1688 smallest_possible_size++;
1692 //the real permutation size is bigger then the value size
1693 if(smallest_possible_size > value_size)
1696 //if the permutation has an asterisk then it can grow
1699 largest_possible_size = value_size;
1701 //if there are only asterisks in the permutation
1702 if(smallest_possible_size == 0)
1703 already_superset = TRUE;
1705 already_superset = FALSE;
1707 //without asterisks its size is fixed
1708 largest_possible_size = smallest_possible_size;
1709 already_superset = FALSE;
1714 already_superset = TRUE;
1715 permutation_size = 1;
1716 smallest_possible_size = 0;
1717 largest_possible_size = value_size;
1718 has_asterisk = TRUE;
1721 unsigned int temp_size = smallest_possible_size;
1724 //this is to make match_set_of incremental,
1725 // we store the already found pairs in this vector
1726 // so we wouldn't try to find a pair for those templates again
1727 // and we can set the covered state of values too
1728 // to not waste memory it is only created if needed
1729 int* pair_list = NULL;
1730 unsigned int old_temp_size = 0;
1732 if(!already_superset)
1734 pair_list = new int[permutation_size];
1735 for(unsigned int i = 0 ; i < permutation_size; i++)
1737 //in the beginning we haven't found a template to any values
1742 while(!already_superset)
1744 //must be a permutation having other values than asterisks
1748 //our set matching is extended with 2 more parameters
1749 // giving back how many templates
1750 // (other than asterisk) couldn't be matched
1751 // and setting / giving back the value-template pairs
1753 boolean found = match_set_of_internal(value_ptr, value_start_index,
1754 temp_size, template_ptr,
1755 template_start_index, permutation_size,
1756 match_function, SUPERSET, &x, pair_list,old_temp_size);
1760 already_superset = TRUE;
1762 //as we didn't found a match we have to try
1763 // a larger set of values
1764 //x is the number of templates we couldn't find
1765 // a matching pair for
1766 // the next must be at least this big to fully cover
1767 // on the other side if it would be bigger than it might miss
1768 // the smallest possible match.
1770 //if we can match with more values
1771 if(has_asterisk && temp_size + x <= largest_possible_size)
1773 old_temp_size = temp_size;
1777 return FAILURE; //else we failed
1785 //we reach here only if we found a match
1787 //can only go on recursively if we haven't reached the end
1789 //reached the end of templates
1790 if(permutation_size == template_size)
1792 if(has_asterisk || value_size == temp_size)
1798 for(unsigned int i = temp_size; i <= largest_possible_size;)
1804 //don't step the permutation index
1805 result = recursive_permutation_match(value_ptr,value_start_index+i,
1806 value_size - i, template_ptr,
1807 template_start_index +
1812 match_function, shift_size);
1814 //try with the next permutation
1815 result = recursive_permutation_match(value_ptr,value_start_index+i,
1816 value_size - i, template_ptr,
1817 template_start_index +
1819 template_size - permutation_size,
1820 permutation_index + 1,
1821 match_function, shift_size);
1824 if(result == SUCCESS)
1825 return SUCCESS; //we finished
1826 else if(result == NO_CHANCE)
1827 return NO_CHANCE; //matching is not possible
1828 else if(i == value_size) //we failed
1830 //if there is no chance of matching
1833 i += shift_size > 1 ? shift_size : 1;
1835 if(i > largest_possible_size)
1836 shift_size = i - largest_possible_size;
1842 //this level failed;
1845 //we are at the beginning of a non permutation, non asterisk interval
1847 //the distance to the next permutation or the end of templates
1848 // so the longest possible match
1849 unsigned int distance;
1851 if (permutation_index < nof_permutations)
1853 distance = template_ptr->get_permutation_start(permutation_index)
1854 - template_start_index;
1856 distance = template_size;
1859 //if there are no more values, but we still have templates
1860 // and the template is not an asterisk or a permutation start
1864 //we try to match as many values as possible
1865 //an asterisk is handled like a 0 length permutation
1869 good = match_function(value_ptr, value_start_index + i,
1870 template_ptr, template_start_index + i);
1872 //bad stop: something can't be matched
1873 //half bad half good stop: the end of values is reached
1874 //good stop: matching on the full distance or till an asterisk
1875 }while(good && i < value_size && i < distance &&
1876 !match_function(value_ptr, -1, template_ptr,
1877 template_start_index + i));
1879 //if we matched on the full distance or till an asterisk
1880 if(good && (i == distance ||
1881 match_function(value_ptr, -1, template_ptr,
1882 template_start_index + i)))
1884 //reached the end of the templates
1885 if(i == template_size)
1889 //the next level would return FAILURE so we don't step it
1892 //i == value_size, so we matched everything
1896 //we reached the next asterisk or permutation,
1897 // so step to the next level
1898 return recursive_permutation_match(value_ptr,value_start_index + i,
1901 template_start_index + i,
1904 match_function, shift_size);
1907 //something bad happened, so we have to check how bad the situation is
1908 if( i == value_size)
1910 //the aren't values left, meaning that the match is not possible
1913 //we couldn't match, but there is still a chance of matching
1915 //try to find a matching value for the last checked (and failed)
1917 // smaller jumps would fail so we skip them
1921 good = match_function(value_ptr,
1922 value_start_index + i + shift_size,
1923 template_ptr, template_start_index + i);
1925 }while(!good && i + shift_size < value_size);
1932 // the template can not be matched later
1940 template <typename T_value_type, typename T_template_type,
1941 unsigned int array_size, int index_offset>
1942 boolean match_permutation_array(const Base_Type *value_ptr,
1944 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
1946 match_function_t match_function)
1948 if (value_ptr == NULL || value_size < 0 ||
1949 template_ptr == NULL || template_size < 0 ||
1950 template_ptr->get_selection() != SPECIFIC_VALUE)
1951 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
1953 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1954 // use the simplified algorithm if the template does not contain permutation
1955 if (nof_permutations == 0)
1956 return match_array(value_ptr, value_size,
1957 template_ptr, template_size, match_function);
1958 // use 'set of' matching if all template elements are grouped into one
1960 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
1961 template_ptr->get_permutation_end(0) ==
1962 (unsigned int)(template_size - 1))
1963 return match_set_of(value_ptr, value_size, template_ptr, template_size,
1966 unsigned int shift_size = 0;
1967 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
1968 0, template_size, 0, match_function, shift_size) == SUCCESS;