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 #ifdef TITAN_RUNTIME_2
41 : public RefdIndexInterface
44 T_type array_elements[array_size];
45 char * names[array_size];
47 /// Copy constructor disallowed.
48 TIMER_ARRAY(const TIMER_ARRAY& other_value);
49 /// Assignment disallowed.
50 TIMER_ARRAY& operator=(const TIMER_ARRAY& other_value);
56 for (size_t i = 0; i < array_size; ++i) {
61 T_type& operator[](int index_value) { return array_elements[
62 get_timer_array_index(index_value, array_size, index_offset)]; }
63 T_type& operator[](const INTEGER& index_value) { return array_elements[
64 get_timer_array_index(index_value, array_size, index_offset)]; }
66 int n_elem() const { return array_size; }
67 int size_of() const { return array_size; }
68 int lengthof() const { return array_size; }
70 T_type& array_element(unsigned int index_value)
71 { return array_elements[index_value]; }
73 void set_name(const char * name_string)
75 for (int i = 0; i < (int)array_size; ++i) {
76 // index_offset may be negative, hence i must be int (not size_t)
77 // to ensure that signed arithmetic is used.
78 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
79 array_elements[i].set_name(names[i]);
85 TTCN_Logger::log_event_str("{ ");
86 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
87 if (v_index > 0) TTCN_Logger::log_event_str(", ");
88 array_elements[v_index].log();
90 TTCN_Logger::log_event_str(" }");
94 extern unsigned int get_port_array_index(int index_value,
95 unsigned int array_size, int index_offset);
96 extern unsigned int get_port_array_index(const INTEGER& index_value,
97 unsigned int array_size, int index_offset);
99 template <typename T_type, unsigned int array_size, int index_offset>
101 #ifdef TITAN_RUNTIME_2
102 : public RefdIndexInterface
105 T_type array_elements[array_size];
106 char * names[array_size];
108 /// Copy constructor disallowed.
109 PORT_ARRAY(const PORT_ARRAY& other_value);
110 /// Assignment disallowed.
111 PORT_ARRAY& operator=(const PORT_ARRAY& other_value);
117 for (size_t i = 0; i < array_size; ++i) {
122 T_type& operator[](int index_value) { return array_elements[
123 get_port_array_index(index_value, array_size, index_offset)]; }
124 T_type& operator[](const INTEGER& index_value) { return array_elements[
125 get_port_array_index(index_value, array_size, index_offset)]; }
127 int n_elem() const { return array_size; }
128 int size_of() const { return array_size; }
129 int lengthof()const { return array_size; }
131 void set_name(const char * name_string)
133 for (int i = 0; i < (int)array_size; ++i) {
134 // i must be int, see comment in TIMER_ARRAY::set_name
135 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
136 array_elements[i].set_name(names[i]);
142 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
143 array_elements[v_index].activate_port();
149 TTCN_Logger::log_event_str("{ ");
150 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
151 if (v_index > 0) TTCN_Logger::log_event_str(", ");
152 array_elements[v_index].log();
154 TTCN_Logger::log_event_str(" }");
158 ////////////////////////////////////////////////////////////////////////////////
160 extern unsigned int get_array_index(int index_value,
161 unsigned int array_size, int index_offset);
162 extern unsigned int get_array_index(const INTEGER& index_value,
163 unsigned int array_size, int index_offset);
165 template <typename T_type, unsigned int array_size, int index_offset>
166 class VALUE_ARRAY : public Base_Type
167 #ifdef TITAN_RUNTIME_2
168 , public RefdIndexInterface
171 T_type array_elements[array_size];
173 // This class use the compiler-generated copy constructor and
176 boolean operator==(const VALUE_ARRAY& other_value) const;
177 inline boolean operator!=(const VALUE_ARRAY& other_value) const
178 { return !(*this == other_value); }
180 T_type& operator[](int index_value) { return array_elements[
181 get_array_index(index_value, array_size, index_offset)]; }
182 T_type& operator[](const INTEGER& index_value) { return array_elements[
183 get_array_index(index_value, array_size, index_offset)]; }
184 const T_type& operator[](int index_value) const { return array_elements[
185 get_array_index(index_value, array_size, index_offset)]; }
186 const T_type& operator[](const INTEGER& index_value) const {
187 return array_elements[
188 get_array_index(index_value, array_size, index_offset)];
192 VALUE_ARRAY operator<<=(int rotate_count) const;
193 VALUE_ARRAY operator<<=(const INTEGER& rotate_count) const;
194 VALUE_ARRAY operator>>=(int rotate_count) const;
195 VALUE_ARRAY operator>>=(const INTEGER& rotate_count) const;
197 T_type& array_element(unsigned int index_value)
198 { return array_elements[index_value]; }
199 const T_type& array_element(unsigned int index_value) const
200 { return array_elements[index_value]; }
202 void set_implicit_omit();
204 boolean is_bound() const;
205 boolean is_value() const;
209 inline int n_elem() const { return array_size; }
210 inline int size_of() const { return array_size; }
211 int lengthof() const;
213 void set_param(Module_Param& param);
215 #ifdef TITAN_RUNTIME_2
216 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
217 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
218 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
219 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
221 inline boolean is_present() const { return is_bound(); }
224 void encode_text(Text_Buf& text_buf) const;
225 void decode_text(Text_Buf& text_buf);
227 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
228 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
230 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
231 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
233 /** Encodes accordingly to the JSON encoding rules.
234 * Returns the length of the encoded data. */
235 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
237 /** Decodes accordingly to the JSON encoding rules.
238 * Returns the length of the decoded data. */
239 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
242 template <typename T_type, unsigned int array_size, int index_offset>
243 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
244 (const VALUE_ARRAY& other_value) const
246 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
247 if (array_elements[elem_count] != other_value.array_elements[elem_count])
252 template <typename T_type, unsigned int array_size, int index_offset>
253 VALUE_ARRAY<T_type,array_size,index_offset>
254 VALUE_ARRAY<T_type,array_size,index_offset>::
255 operator<<=(int rotate_count) const {
256 return *this >>= (-rotate_count);
259 template <typename T_type, unsigned int array_size, int index_offset>
260 VALUE_ARRAY<T_type,array_size,index_offset>
261 VALUE_ARRAY<T_type,array_size,index_offset>::
262 operator<<=(const INTEGER& rotate_count) const {
263 rotate_count.must_bound("Unbound integer operand of rotate left "
265 return *this >>= (int)(-rotate_count);
268 template <typename T_type, unsigned int array_size, int index_offset>
269 VALUE_ARRAY<T_type,array_size,index_offset>
270 VALUE_ARRAY<T_type,array_size,index_offset>::
271 operator>>=(int rotate_count) const {
273 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
274 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
275 if (rc == 0) return *this;
276 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
277 for (unsigned int i=0; i<array_size; i++) {
278 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
283 template <typename T_type, unsigned int array_size, int index_offset>
284 VALUE_ARRAY<T_type,array_size,index_offset>
285 VALUE_ARRAY<T_type,array_size,index_offset>::
286 operator>>=(const INTEGER& rotate_count) const {
287 rotate_count.must_bound("Unbound integer operand of rotate right "
289 return *this >>= (int)rotate_count;
292 template <typename T_type, unsigned int array_size, int index_offset>
293 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
295 for (unsigned int i = 0; i < array_size; ++i) {
296 if (array_elements[i].is_bound())
297 array_elements[i].set_implicit_omit();
301 template <typename T_type, unsigned int array_size, int index_offset>
302 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
304 for (unsigned int i = 0; i < array_size; ++i) {
305 if (!array_elements[i].is_bound()) {
312 template <typename T_type, unsigned int array_size, int index_offset>
313 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
315 for (unsigned int i = 0; i < array_size; ++i) {
316 if (!array_elements[i].is_value()) {
323 template <typename T_type, unsigned int array_size, int index_offset>
324 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
326 for (unsigned int i = 0; i < array_size; ++i) {
327 array_elements[i].clean_up();
331 template <typename T_type, unsigned int array_size, int index_offset>
332 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
334 TTCN_Logger::log_event_str("{ ");
335 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
337 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
338 array_elements[elem_count].log();
340 TTCN_Logger::log_event_str(" }");
343 template <typename T_type, unsigned int array_size, int index_offset>
344 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
347 for (unsigned int my_length=array_size; my_length>0; my_length--)
349 if (array_elements[my_length-1].is_bound()) return my_length;
354 template <typename T_type, unsigned int array_size, int index_offset>
355 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
358 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
359 param.get_id()->next_name()) {
360 // Haven't reached the end of the module parameter name
361 // => the name refers to one of the elements, not to the whole array
362 char* param_field = param.get_id()->get_current_name();
363 if (param_field[0] < '0' || param_field[0] > '9') {
364 param.error("Unexpected record field name in module parameter, expected a valid"
367 unsigned int param_index = -1;
368 sscanf(param_field, "%u", ¶m_index);
369 if (param_index >= array_size) {
370 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
372 array_elements[param_index].set_param(param);
376 param.basic_check(Module_Param::BC_VALUE, "array value");
377 switch (param.get_type()) {
378 case Module_Param::MP_Value_List:
379 if (param.get_size()!=array_size) {
380 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);
382 for (size_t i=0; i<param.get_size(); ++i) {
383 Module_Param* const curr = param.get_elem(i);
384 if (curr->get_type()!=Module_Param::MP_NotUsed) {
385 array_elements[i].set_param(*curr);
389 case Module_Param::MP_Indexed_List:
390 for (size_t i=0; i<param.get_size(); ++i) {
391 Module_Param* const curr = param.get_elem(i);
392 array_elements[curr->get_id()->get_index()].set_param(*curr);
396 param.type_error("array value");
400 template <typename T_type, unsigned int array_size, int index_offset>
401 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
402 (Text_Buf& text_buf) const
404 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
405 array_elements[elem_count].encode_text(text_buf);
408 template <typename T_type, unsigned int array_size, int index_offset>
409 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
412 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
413 array_elements[elem_count].decode_text(text_buf);
416 template <typename T_type, unsigned int array_size, int index_offset>
417 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
418 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
421 va_start(pvar, p_coding);
423 case TTCN_EncDec::CT_JSON: {
424 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
425 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
426 ("No JSON descriptor available for type '%s'.", p_td.name);
427 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
428 JSON_encode(p_td, tok);
429 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
432 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
437 template <typename T_type, unsigned int array_size, int index_offset>
438 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
439 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
442 case TTCN_EncDec::CT_JSON: {
443 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
444 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
445 ("No JSON descriptor available for type '%s'.", p_td.name);
446 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
447 if(JSON_decode(p_td, tok, false)<0)
448 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
449 "because invalid or incomplete message was received", p_td.name);
450 p_buf.set_pos(tok.get_buf_pos());
453 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
457 template <typename T_type, unsigned int array_size, int index_offset>
458 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
459 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
462 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
463 "Encoding an unbound array value.");
467 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
469 for(unsigned int i = 0; i < array_size; ++i) {
470 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
471 if (0 > ret_val) break;
475 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
479 template <typename T_type, unsigned int array_size, int index_offset>
480 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
481 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)
483 json_token_t token = JSON_TOKEN_NONE;
484 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
485 if (JSON_TOKEN_ERROR == token) {
486 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
487 return JSON_ERROR_FATAL;
489 else if (JSON_TOKEN_ARRAY_START != token) {
490 return JSON_ERROR_INVALID_TOKEN;
493 for(unsigned int i = 0; i < array_size; ++i) {
494 int ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
495 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
496 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
497 array_size - i, (array_size - i > 1) ? "s" : "");
498 return JSON_ERROR_FATAL;
500 else if (JSON_ERROR_FATAL == ret_val) {
504 return JSON_ERROR_FATAL;
509 dec_len += p_tok.get_next_token(&token, NULL, NULL);
510 if (JSON_TOKEN_ARRAY_END != token) {
511 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
515 return JSON_ERROR_FATAL;
522 template <typename T_value_type, typename T_template_type,
523 unsigned int array_size, int index_offset>
524 class TEMPLATE_ARRAY : public Restricted_Length_Template
530 T_template_type **value_elements;
533 unsigned int n_values;
534 TEMPLATE_ARRAY *list_value;
538 struct Pair_of_elements;
539 Pair_of_elements *permutation_intervals;
540 unsigned int number_of_permutations;
542 void clean_up_intervals();
543 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
545 void copy_template(const TEMPLATE_ARRAY& other_value);
546 void set_selection(template_sel new_selection);
547 void set_selection(const TEMPLATE_ARRAY& other_value);
548 void encode_text_permutation(Text_Buf& text_buf) const;
549 void decode_text_permutation(Text_Buf& text_buf);
554 number_of_permutations = 0;
555 permutation_intervals = NULL;
557 TEMPLATE_ARRAY(template_sel other_value)
558 : Restricted_Length_Template(other_value)
560 check_single_selection(other_value);
561 number_of_permutations = 0;
562 permutation_intervals = NULL;
564 TEMPLATE_ARRAY(null_type other_value);
565 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
568 number_of_permutations = 0;
569 permutation_intervals = NULL;
570 copy_value(other_value);
573 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
574 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
575 : Restricted_Length_Template()
577 number_of_permutations = 0;
578 permutation_intervals = NULL;
579 copy_template(other_value);
584 clean_up_intervals();
589 TEMPLATE_ARRAY& operator=(template_sel other_value);
590 TEMPLATE_ARRAY& operator=(null_type other_value);
591 TEMPLATE_ARRAY& operator=(const
592 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
593 TEMPLATE_ARRAY& operator=(const
594 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
595 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
597 T_template_type& operator[](int index_value);
598 T_template_type& operator[](const INTEGER& index_value);
599 const T_template_type& operator[](int index_value) const;
600 const T_template_type& operator[](const INTEGER& index_value) const;
602 void set_size(int new_size);
605 int size_of(boolean is_size) const;
606 inline int size_of() const { return size_of(TRUE); }
607 inline int lengthof() const { return size_of(FALSE); }
609 void add_permutation(unsigned int start_index, unsigned int end_index);
611 /** Removes all permutations set on this template, used when template variables
612 * are given new values. */
613 void remove_all_permutations() { clean_up_intervals(); }
615 unsigned int get_number_of_permutations() const;
616 unsigned int get_permutation_start(unsigned int index_value) const;
617 unsigned int get_permutation_end(unsigned int index_value) const;
618 unsigned int get_permutation_size(unsigned int index_value) const;
619 boolean permutation_starts_at(unsigned int index_value) const;
620 boolean permutation_ends_at(unsigned int index_value) const;
623 static boolean match_function_specific(
624 const Base_Type *value_ptr, int value_index,
625 const Restricted_Length_Template *template_ptr, int template_index);
627 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
630 boolean is_value() const;
631 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
633 void set_type(template_sel template_type, unsigned int list_length);
634 TEMPLATE_ARRAY& list_item(unsigned int list_index);
637 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
640 void set_param(Module_Param& param);
642 void encode_text(Text_Buf& text_buf) const;
643 void decode_text(Text_Buf& text_buf);
645 boolean is_present() const;
646 boolean match_omit() const;
648 #ifdef TITAN_RUNTIME_2
649 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
650 void set_value(template_sel other_value) { *this = other_value; }
651 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
652 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
653 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
654 boolean matchv(const Base_Type* other_value) const { return match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value))); }
655 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))); }
657 void check_restriction(template_res t_res, const char* t_name=NULL) const;
661 template <typename T_value_type, typename T_template_type,
662 unsigned int array_size, int index_offset>
663 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
665 unsigned int start_index, end_index; //beginning and ending index
668 template <typename T_value_type, typename T_template_type,
669 unsigned int array_size, int index_offset>
670 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
673 switch (template_selection)
676 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
677 delete single_value.value_elements[elem_count];
678 free_pointers((void**)single_value.value_elements);
681 case COMPLEMENTED_LIST:
682 delete [] value_list.list_value;
687 template_selection = UNINITIALIZED_TEMPLATE;
690 template <typename T_value_type, typename T_template_type,
691 unsigned int array_size, int index_offset>
692 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
695 number_of_permutations = 0;
696 Free(permutation_intervals);
697 permutation_intervals = NULL;
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>::
703 set_selection(template_sel other_value)
705 Restricted_Length_Template::set_selection(other_value);
706 clean_up_intervals();
709 template <typename T_value_type, typename T_template_type,
710 unsigned int array_size, int index_offset>
711 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
712 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
714 Restricted_Length_Template::set_selection(other_value);
715 clean_up_intervals();
716 if(other_value.template_selection == SPECIFIC_VALUE)
718 number_of_permutations = other_value.number_of_permutations;
719 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
720 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
724 template <typename T_value_type, typename T_template_type,
725 unsigned int array_size, int index_offset>
726 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
727 encode_text_permutation(Text_Buf& text_buf) const
729 encode_text_restricted(text_buf);
730 text_buf.push_int(number_of_permutations);
732 for(unsigned int i = 0; i < number_of_permutations; i++)
734 text_buf.push_int(permutation_intervals[i].start_index);
735 text_buf.push_int(permutation_intervals[i].end_index);
739 template <typename T_value_type, typename T_template_type,
740 unsigned int array_size, int index_offset>
741 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
742 decode_text_permutation(Text_Buf& text_buf)
744 decode_text_restricted(text_buf);
746 number_of_permutations = text_buf.pull_int().get_val();
747 permutation_intervals = (Pair_of_elements *)Malloc
748 (number_of_permutations * sizeof(Pair_of_elements));
750 for (unsigned int i = 0; i < number_of_permutations; i++)
752 permutation_intervals[i].start_index =
753 text_buf.pull_int().get_val();
754 permutation_intervals[i].end_index =
755 text_buf.pull_int().get_val();
759 template <typename T_value_type, typename T_template_type,
760 unsigned int array_size, int index_offset>
761 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
762 add_permutation(unsigned int start_index, unsigned int end_index)
764 if(start_index > end_index)
765 TTCN_error("wrong permutation interval settings start (%d)"
766 "can not be greater than end (%d)",start_index, end_index);
768 if(number_of_permutations > 0 &&
769 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
770 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
772 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
773 permutation_intervals[number_of_permutations].start_index = start_index;
774 permutation_intervals[number_of_permutations].end_index = end_index;
775 number_of_permutations++;
778 template <typename T_value_type, typename T_template_type,
779 unsigned int array_size, int index_offset>
780 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
781 get_number_of_permutations(void) const
783 return number_of_permutations;
786 template <typename T_value_type, typename T_template_type,
787 unsigned int array_size, int index_offset>
788 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
789 get_permutation_start(unsigned int index_value) const
791 if(index_value >= number_of_permutations)
792 TTCN_error("Index overflow (%d)", index_value);
794 return permutation_intervals[index_value].start_index;
797 template <typename T_value_type, typename T_template_type,
798 unsigned int array_size, int index_offset>
799 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
800 get_permutation_end(unsigned int index_value) const
802 if(index_value >= number_of_permutations)
803 TTCN_error("Index overflow (%d)", index_value);
805 return permutation_intervals[index_value].end_index;
808 template <typename T_value_type, typename T_template_type,
809 unsigned int array_size, int index_offset>
810 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
811 get_permutation_size(unsigned int index_value) const
813 if(index_value >= number_of_permutations)
814 TTCN_error("Index overflow (%d)", index_value);
816 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
819 template <typename T_value_type, typename T_template_type,
820 unsigned int array_size, int index_offset>
821 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
822 permutation_starts_at(unsigned int index_value) const
824 for(unsigned int i = 0; i < number_of_permutations; i++)
826 if(permutation_intervals[i].start_index == index_value)
833 template <typename T_value_type, typename T_template_type,
834 unsigned int array_size, int index_offset>
835 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
836 permutation_ends_at(unsigned int index_value) const
838 for(unsigned int i = 0; i < number_of_permutations; i++)
840 if(permutation_intervals[i].end_index == index_value)
847 template <typename T_value_type, typename T_template_type,
848 unsigned int array_size, int index_offset>
849 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
850 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
853 single_value.n_elements = array_size;
854 single_value.value_elements =
855 (T_template_type**)allocate_pointers(array_size);
856 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
857 single_value.value_elements[elem_count] =
858 new T_template_type(other_value.array_element(elem_count));
859 set_selection(SPECIFIC_VALUE);
862 template <typename T_value_type, typename T_template_type,
863 unsigned int array_size, int index_offset>
864 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
865 copy_template(const TEMPLATE_ARRAY& other_value)
867 switch (other_value.template_selection)
870 single_value.n_elements = other_value.single_value.n_elements;
871 single_value.value_elements =
872 (T_template_type**)allocate_pointers(single_value.n_elements);
873 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
874 single_value.value_elements[elem_count] = new
875 T_template_type(*other_value.single_value.value_elements[elem_count]);
882 case COMPLEMENTED_LIST:
883 value_list.n_values = other_value.value_list.n_values;
884 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
885 for (unsigned int list_count = 0; list_count < value_list.n_values;
887 value_list.list_value[list_count].copy_template(
888 other_value.value_list.list_value[list_count]);
891 TTCN_error("Copying an uninitialized/unsupported array template.");
893 set_selection(other_value);
896 template <typename T_value_type, typename T_template_type,
897 unsigned int array_size, int index_offset>
898 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
899 TEMPLATE_ARRAY(null_type)
900 : Restricted_Length_Template(SPECIFIC_VALUE)
902 single_value.n_elements = 0;
903 single_value.value_elements = NULL;
904 number_of_permutations = 0;
905 permutation_intervals = NULL;
908 template <typename T_value_type, typename T_template_type,
909 unsigned int array_size, int index_offset>
910 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
912 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
914 number_of_permutations = 0;
915 permutation_intervals = NULL;
916 switch (other_value.get_selection()) {
917 case OPTIONAL_PRESENT:
918 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
922 set_selection(OMIT_VALUE);
925 TTCN_error("Creating an array template from an unbound optional field.");
929 template <typename T_value_type, typename T_template_type,
930 unsigned int array_size, int index_offset>
931 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
932 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
933 operator=(template_sel other_value)
935 check_single_selection(other_value);
937 set_selection(other_value);
941 template <typename T_value_type, typename T_template_type,
942 unsigned int array_size, int index_offset>
943 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
944 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
948 set_selection(SPECIFIC_VALUE);
949 single_value.n_elements = 0;
950 single_value.value_elements = NULL;
954 template <typename T_value_type, typename T_template_type,
955 unsigned int array_size, int index_offset>
956 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
957 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
958 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
961 copy_value(other_value);
965 template <typename T_value_type, typename T_template_type,
966 unsigned int array_size, int index_offset>
967 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
968 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
970 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
973 switch (other_value.get_selection()) {
974 case OPTIONAL_PRESENT:
975 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
979 set_selection(OMIT_VALUE);
982 TTCN_error("Assignment of an unbound optional field to an array template.");
987 template <typename T_value_type, typename T_template_type,
988 unsigned int array_size, int index_offset>
989 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
990 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
992 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
995 if (&other_value != this)
998 copy_template(other_value);
1003 template <typename T_value_type, typename T_template_type,
1004 unsigned int array_size, int index_offset>
1006 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1009 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1011 "Accessing an element of an array template using invalid index: %d. "
1012 "Index range is [%d,%d].",
1013 index_value, index_offset, index_offset+(int)array_size);
1014 // transform index value according to given offset
1015 index_value -= index_offset;
1016 // the template of an array is not restricted to array_size, allow any length
1017 // in case of * or ? expand to full size to avoid uninitialized values
1018 switch (template_selection)
1020 case SPECIFIC_VALUE:
1021 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1025 set_size(array_size);
1028 set_size(index_value + 1);
1030 return *single_value.value_elements[index_value];
1033 template <typename T_value_type, typename T_template_type,
1034 unsigned int array_size, int index_offset>
1036 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1037 (const INTEGER& index_value)
1039 index_value.must_bound(
1040 "Using an unbound integer value for indexing an array template.");
1041 return (*this)[(int)index_value];
1044 template <typename T_value_type, typename T_template_type,
1045 unsigned int array_size, int index_offset>
1046 const T_template_type&
1047 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1048 (int index_value) const
1050 if (index_value < index_offset)
1052 "Accessing an element of an array template using invalid index: %d. "
1053 "Index range starts at %d.",
1054 index_value, index_offset);
1055 // transform index value according to given offset
1056 index_value -= index_offset;
1057 // const is specific template
1058 if (template_selection != SPECIFIC_VALUE)
1059 TTCN_error("Accessing an element of a non-specific array template.");
1060 if (index_value >= single_value.n_elements)
1061 TTCN_error("Index overflow in an array template: "
1062 "The index is %d (starting at %d),"
1063 " but the template has only %d elements.",
1064 index_value+index_offset, index_offset, single_value.n_elements);
1065 return *single_value.value_elements[index_value];
1068 template <typename T_value_type, typename T_template_type,
1069 unsigned int array_size, int index_offset>
1070 const T_template_type&
1071 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1072 (const INTEGER& index_value) const
1074 index_value.must_bound(
1075 "Using an unbound integer value for indexing an array template.");
1076 return (*this)[(int)index_value];
1079 template <typename T_value_type, typename T_template_type,
1080 unsigned int array_size, int index_offset>
1081 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1082 set_size(int new_size)
1084 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1085 "for an array template.");
1086 template_sel old_selection = template_selection;
1087 if (old_selection != SPECIFIC_VALUE)
1090 set_selection(SPECIFIC_VALUE);
1091 single_value.n_elements = 0;
1092 single_value.value_elements = NULL;
1094 if (new_size > single_value.n_elements)
1096 single_value.value_elements =
1097 (T_template_type**)reallocate_pointers(
1098 (void**)single_value.value_elements, single_value.n_elements, new_size);
1099 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1101 for (int elem_count = single_value.n_elements;
1102 elem_count < new_size; elem_count++)
1103 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1107 for (int elem_count = single_value.n_elements;
1108 elem_count < new_size; elem_count++)
1109 single_value.value_elements[elem_count] = new T_template_type;
1111 single_value.n_elements = new_size;
1113 else if (new_size < single_value.n_elements)
1115 for (int elem_count = new_size; elem_count < single_value.n_elements;
1117 delete single_value.value_elements[elem_count];
1118 single_value.value_elements =
1119 (T_template_type**)reallocate_pointers(
1120 (void**)single_value.value_elements, single_value.n_elements, new_size);
1121 single_value.n_elements = new_size;
1125 template <typename T_value_type, typename T_template_type,
1126 unsigned int array_size, int index_offset>
1127 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1130 switch (template_selection) {
1131 case SPECIFIC_VALUE:
1132 return single_value.n_elements;
1134 return value_list.n_values;
1136 TTCN_error("Performing n_elem");
1140 template <typename T_value_type, typename T_template_type,
1141 unsigned int array_size, int index_offset>
1142 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1143 size_of(boolean is_size) const
1145 const char* op_name = is_size ? "size" : "length";
1147 boolean has_any_or_none;
1149 TTCN_error("Performing %sof() operation on an array template "
1150 "which has an ifpresent attribute.", op_name);
1151 switch (template_selection)
1153 case SPECIFIC_VALUE: {
1155 has_any_or_none = FALSE;
1156 int elem_count = single_value.n_elements;
1157 if (!is_size) { // lengthof()
1158 while (elem_count>0 &&
1159 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1161 for (int i=0; i<elem_count; i++)
1163 switch (single_value.value_elements[i]->get_selection())
1166 TTCN_error("Performing %sof() operation on an array template "
1167 "containing omit element.", op_name);
1169 has_any_or_none = TRUE;
1178 TTCN_error("Performing %sof() operation on an array template "
1179 "containing omit value.", op_name);
1183 has_any_or_none = TRUE; // max. size is infinity
1186 // error if any element does not have size or the sizes differ
1187 if (value_list.n_values<1)
1188 TTCN_error("Performing %sof() operation on an array template "
1189 "containing an empty list.", op_name);
1190 int item_size = value_list.list_value[0].size_of(is_size);
1191 for (unsigned int i = 1; i < value_list.n_values; i++) {
1192 if (value_list.list_value[i].size_of(is_size)!=item_size)
1193 TTCN_error("Performing %sof() operation on an array template "
1194 "containing a value list with different sizes.", op_name);
1196 min_size = item_size;
1197 has_any_or_none = FALSE;
1199 case COMPLEMENTED_LIST:
1200 TTCN_error("Performing %sof() operation on an array template "
1201 "containing complemented list.", op_name);
1203 TTCN_error("Performing %sof() operation on an "
1204 "uninitialized/unsupported array template.", op_name);
1206 return check_section_is_single(min_size, has_any_or_none,
1207 op_name, "an", "array template");
1210 template <typename T_value_type, typename T_template_type,
1211 unsigned int array_size, int index_offset>
1212 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1213 match_function_specific(const Base_Type *value_ptr, int value_index,
1214 const Restricted_Length_Template *template_ptr,
1217 if (value_index >= 0)
1218 return ((const TEMPLATE_ARRAY*)template_ptr)->
1219 single_value.value_elements[template_index]->
1221 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1222 ->array_element(value_index));
1224 return ((const TEMPLATE_ARRAY*)template_ptr)->
1225 single_value.value_elements[template_index]->is_any_or_omit();
1228 template <typename T_value_type, typename T_template_type,
1229 unsigned int array_size, int index_offset>
1230 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1231 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1234 if (!match_length(array_size)) return FALSE;
1235 switch (template_selection)
1237 case SPECIFIC_VALUE:
1238 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1239 match_function_specific);
1246 case COMPLEMENTED_LIST:
1247 for (unsigned int list_count = 0; list_count < value_list.n_values;
1249 if (value_list.list_value[list_count].match(other_value))
1250 return template_selection == VALUE_LIST;
1251 return template_selection == COMPLEMENTED_LIST;
1253 TTCN_error("Matching with an uninitialized/unsupported array template.");
1258 template <typename T_value_type, typename T_template_type,
1259 unsigned int array_size, int index_offset>
1260 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1263 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1264 for (int i=0; i<single_value.n_elements; i++)
1265 if (!single_value.value_elements[i]->is_value()) return FALSE;
1269 template <typename T_value_type, typename T_template_type,
1270 unsigned int array_size, int index_offset>
1271 VALUE_ARRAY<T_value_type, array_size, index_offset>
1272 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1275 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1276 TTCN_error("Performing a valueof or send operation on a "
1277 "non-specific array template.");
1278 // the size of the template must be the size of the value
1279 if (single_value.n_elements!=array_size)
1280 TTCN_error("Performing a valueof or send operation on a "
1281 "specific array template with invalid size.");
1282 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1283 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1284 ret_val.array_element(elem_count) =
1285 single_value.value_elements[elem_count]->valueof();
1289 template <typename T_value_type, typename T_template_type,
1290 unsigned int array_size, int index_offset>
1291 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1292 set_type(template_sel template_type, unsigned int list_length)
1295 switch (template_type) {
1297 case COMPLEMENTED_LIST:
1298 value_list.n_values = list_length;
1299 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1303 "Internal error: Setting an invalid type for an array template.");
1305 set_selection(template_type);
1308 template <typename T_value_type, typename T_template_type,
1309 unsigned int array_size, int index_offset>
1310 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1311 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1312 list_item(unsigned int list_index)
1314 if (template_selection != VALUE_LIST &&
1315 template_selection != COMPLEMENTED_LIST)
1316 TTCN_error("Internal error: Accessing a list element of a non-list "
1318 if (list_index >= value_list.n_values)
1319 TTCN_error("Internal error: Index overflow in a value list "
1321 return value_list.list_value[list_index];
1324 template <typename T_value_type, typename T_template_type,
1325 unsigned int array_size, int index_offset>
1326 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1329 switch (template_selection)
1331 case SPECIFIC_VALUE:
1332 if (single_value.n_elements > 0)
1334 TTCN_Logger::log_event_str("{ ");
1335 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1337 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1338 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1339 single_value.value_elements[elem_count]->log();
1340 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1342 TTCN_Logger::log_event_str(" }");
1345 TTCN_Logger::log_event_str("{ }");
1347 case COMPLEMENTED_LIST:
1348 TTCN_Logger::log_event_str("complement");
1350 TTCN_Logger::log_char('(');
1351 for (unsigned int list_count = 0; list_count < value_list.n_values;
1354 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1355 value_list.list_value[list_count].log();
1357 TTCN_Logger::log_char(')');
1367 template <typename T_value_type, typename T_template_type,
1368 unsigned int array_size, int index_offset>
1369 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1370 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1373 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1374 if(match(match_value)){
1375 TTCN_Logger::print_logmatch_buffer();
1376 TTCN_Logger::log_event_str(" matched");
1378 if (template_selection == SPECIFIC_VALUE &&
1379 single_value.n_elements == array_size) {
1380 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1381 for (unsigned int elem_count = 0; elem_count < array_size;
1383 if(!single_value.value_elements[elem_count]->
1384 match(match_value.array_element(elem_count))){
1385 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1386 single_value.value_elements[elem_count]->
1387 log_match(match_value.array_element(elem_count));
1388 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1391 log_match_length(array_size);
1393 TTCN_Logger::print_logmatch_buffer();
1395 TTCN_Logger::log_event_str(" with ");
1397 TTCN_Logger::log_event_str(" unmatched");
1402 if (template_selection == SPECIFIC_VALUE &&
1403 single_value.n_elements == array_size) {
1404 TTCN_Logger::log_event_str("{ ");
1405 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1406 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1407 single_value.value_elements[elem_count]->log_match(match_value.array_element(elem_count));
1409 TTCN_Logger::log_event_str(" }");
1410 log_match_length(array_size);
1413 TTCN_Logger::log_event_str(" with ");
1415 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
1416 else TTCN_Logger::log_event_str(" unmatched");
1420 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1421 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1423 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1424 param.get_id()->next_name()) {
1425 // Haven't reached the end of the module parameter name
1426 // => the name refers to one of the elements, not to the whole array
1427 char* param_field = param.get_id()->get_current_name();
1428 if (param_field[0] < '0' || param_field[0] > '9') {
1429 param.error("Unexpected record field name in module parameter, expected a valid"
1430 " array template index");
1432 unsigned int param_index = -1;
1433 sscanf(param_field, "%u", ¶m_index);
1434 if (param_index >= array_size) {
1435 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1437 (*this)[param_index].set_param(param);
1441 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1442 switch (param.get_type()) {
1443 case Module_Param::MP_Omit:
1446 case Module_Param::MP_Any:
1449 case Module_Param::MP_AnyOrNone:
1450 *this = ANY_OR_OMIT;
1452 case Module_Param::MP_List_Template:
1453 case Module_Param::MP_ComplementList_Template:
1454 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
1455 for (size_t i=0; i<param.get_size(); i++) {
1456 list_item(i).set_param(*param.get_elem(i));
1459 case Module_Param::MP_Value_List:
1460 set_size(param.get_size());
1461 for (size_t i=0; i<param.get_size(); ++i) {
1462 Module_Param* const curr = param.get_elem(i);
1463 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1464 (*this)[(int)i+index_offset].set_param(*curr);
1468 case Module_Param::MP_Indexed_List:
1469 for (size_t i=0; i<param.get_size(); ++i) {
1470 Module_Param* const curr = param.get_elem(i);
1471 (*this)[curr->get_id()->get_index()].set_param(*curr);
1475 param.type_error("array template");
1477 is_ifpresent = param.get_ifpresent();
1480 template <typename T_value_type, typename T_template_type,
1481 unsigned int array_size, int index_offset>
1482 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1483 encode_text(Text_Buf& text_buf) const
1485 encode_text_restricted(text_buf);
1486 switch (template_selection)
1488 case SPECIFIC_VALUE:
1489 text_buf.push_int(single_value.n_elements);
1490 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1491 single_value.value_elements[elem_count]->encode_text(text_buf);
1498 case COMPLEMENTED_LIST:
1499 text_buf.push_int(value_list.n_values);
1500 for (unsigned int list_count = 0; list_count < value_list.n_values;
1502 value_list.list_value[list_count].encode_text(text_buf);
1505 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1510 template <typename T_value_type, typename T_template_type,
1511 unsigned int array_size, int index_offset>
1512 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1513 decode_text(Text_Buf& text_buf)
1516 decode_text_restricted(text_buf);
1517 switch (template_selection)
1519 case SPECIFIC_VALUE:
1520 single_value.n_elements = text_buf.pull_int().get_val();
1521 if (single_value.n_elements < 0)
1522 TTCN_error("Text decoder: Negative size was received for an "
1524 single_value.value_elements =
1525 (T_template_type**)allocate_pointers(single_value.n_elements);
1526 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1528 single_value.value_elements[elem_count] = new T_template_type;
1529 single_value.value_elements[elem_count]->decode_text(text_buf);
1537 case COMPLEMENTED_LIST:
1538 value_list.n_values = text_buf.pull_int().get_val();
1539 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1540 for (unsigned int list_count = 0; list_count < value_list.n_values;
1542 value_list.list_value[list_count].decode_text(text_buf);
1545 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1546 "for an array template.");
1550 template <typename T_value_type, typename T_template_type,
1551 unsigned int array_size, int index_offset>
1552 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1555 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1556 return !match_omit();
1559 template <typename T_value_type, typename T_template_type,
1560 unsigned int array_size, int index_offset>
1561 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1564 if (is_ifpresent) return TRUE;
1565 switch (template_selection) {
1570 case COMPLEMENTED_LIST:
1571 for (unsigned int i=0; i<value_list.n_values; i++)
1572 if (value_list.list_value[i].match_omit())
1573 return template_selection==VALUE_LIST;
1574 return template_selection==COMPLEMENTED_LIST;
1581 #ifndef TITAN_RUNTIME_2
1582 template <typename T_value_type, typename T_template_type,
1583 unsigned int array_size, int index_offset>
1584 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1585 check_restriction(template_res t_res, const char* t_name) const
1587 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1588 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1590 if (template_selection==OMIT_VALUE) return;
1592 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1593 for (int i=0; i<single_value.n_elements; i++)
1594 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1597 if (!match_omit()) return;
1602 TTCN_error("Restriction `%s' on template of type %s violated.",
1603 get_res_name(t_res), t_name ? t_name : "array");
1607 template <typename T_value_type, typename T_template_type,
1608 unsigned int array_size, int index_offset>
1609 answer recursive_permutation_match(const Base_Type *value_ptr,
1610 unsigned int value_start_index,
1611 unsigned int value_size,
1612 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1613 unsigned int template_start_index,
1614 unsigned int template_size,
1615 unsigned int permutation_index,
1616 match_function_t match_function,
1617 unsigned int& shift_size)
1619 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1620 if (permutation_index > nof_permutations)
1621 TTCN_error("Internal error: recursive_permutation_match: "
1622 "invalid argument.");
1624 if (permutation_index < nof_permutations &&
1625 template_ptr->get_permutation_end(permutation_index) >
1626 template_start_index + template_size)
1627 TTCN_error("Internal error: recursive_permutation_match: wrong "
1628 "permutation interval settings for permutation %d.",
1634 if(template_size == 0)
1636 //reached the end of templates
1637 // if we reached the end of values => good
1645 //are we at an asterisk or at the beginning of a permutation interval
1646 boolean is_asterisk;
1647 boolean permutation_begins = permutation_index < nof_permutations &&
1648 template_start_index ==
1649 template_ptr->get_permutation_start(permutation_index);
1651 if (permutation_begins ||
1652 match_function(value_ptr, -1, template_ptr, template_start_index))
1654 unsigned int smallest_possible_size;
1655 unsigned int largest_possible_size;
1656 boolean has_asterisk;
1657 boolean already_superset;
1658 unsigned int permutation_size;
1660 //check how many values might be associated with this permutation
1661 //if we are at a permutation start
1662 if (permutation_begins)
1664 is_asterisk = FALSE;
1666 template_ptr->get_permutation_size(permutation_index);
1667 smallest_possible_size = 0;
1668 has_asterisk = FALSE;
1670 //count how many non asterisk elements are in the permutation
1671 for(unsigned int i = 0; i < permutation_size; i++)
1673 if(match_function(value_ptr, -1, template_ptr,
1674 i + template_start_index))
1676 has_asterisk = TRUE;
1678 smallest_possible_size++;
1682 //the real permutation size is bigger then the value size
1683 if(smallest_possible_size > value_size)
1686 //if the permutation has an asterisk then it can grow
1689 largest_possible_size = value_size;
1691 //if there are only asterisks in the permutation
1692 if(smallest_possible_size == 0)
1693 already_superset = TRUE;
1695 already_superset = FALSE;
1697 //without asterisks its size is fixed
1698 largest_possible_size = smallest_possible_size;
1699 already_superset = FALSE;
1704 already_superset = TRUE;
1705 permutation_size = 1;
1706 smallest_possible_size = 0;
1707 largest_possible_size = value_size;
1708 has_asterisk = TRUE;
1711 unsigned int temp_size = smallest_possible_size;
1714 //this is to make match_set_of incremental,
1715 // we store the already found pairs in this vector
1716 // so we wouldn't try to find a pair for those templates again
1717 // and we can set the covered state of values too
1718 // to not waste memory it is only created if needed
1719 int* pair_list = NULL;
1720 unsigned int old_temp_size = 0;
1722 if(!already_superset)
1724 pair_list = new int[permutation_size];
1725 for(unsigned int i = 0 ; i < permutation_size; i++)
1727 //in the beginning we haven't found a template to any values
1732 while(!already_superset)
1734 //must be a permutation having other values than asterisks
1738 //our set matching is extended with 2 more parameters
1739 // giving back how many templates
1740 // (other than asterisk) couldn't be matched
1741 // and setting / giving back the value-template pairs
1743 boolean found = match_set_of_internal(value_ptr, value_start_index,
1744 temp_size, template_ptr,
1745 template_start_index, permutation_size,
1746 match_function, SUPERSET, &x, pair_list,old_temp_size);
1750 already_superset = TRUE;
1752 //as we didn't found a match we have to try
1753 // a larger set of values
1754 //x is the number of templates we couldn't find
1755 // a matching pair for
1756 // the next must be at least this big to fully cover
1757 // on the other side if it would be bigger than it might miss
1758 // the smallest possible match.
1760 //if we can match with more values
1761 if(has_asterisk && temp_size + x <= largest_possible_size)
1763 old_temp_size = temp_size;
1767 return FAILURE; //else we failed
1775 //we reach here only if we found a match
1777 //can only go on recursively if we haven't reached the end
1779 //reached the end of templates
1780 if(permutation_size == template_size)
1782 if(has_asterisk || value_size == temp_size)
1788 for(unsigned int i = temp_size; i <= largest_possible_size;)
1794 //don't step the permutation index
1795 result = recursive_permutation_match(value_ptr,value_start_index+i,
1796 value_size - i, template_ptr,
1797 template_start_index +
1802 match_function, shift_size);
1804 //try with the next permutation
1805 result = recursive_permutation_match(value_ptr,value_start_index+i,
1806 value_size - i, template_ptr,
1807 template_start_index +
1809 template_size - permutation_size,
1810 permutation_index + 1,
1811 match_function, shift_size);
1814 if(result == SUCCESS)
1815 return SUCCESS; //we finished
1816 else if(result == NO_CHANCE)
1817 return NO_CHANCE; //matching is not possible
1818 else if(i == value_size) //we failed
1820 //if there is no chance of matching
1823 i += shift_size > 1 ? shift_size : 1;
1825 if(i > largest_possible_size)
1826 shift_size = i - largest_possible_size;
1832 //this level failed;
1835 //we are at the beginning of a non permutation, non asterisk interval
1837 //the distance to the next permutation or the end of templates
1838 // so the longest possible match
1839 unsigned int distance;
1841 if (permutation_index < nof_permutations)
1843 distance = template_ptr->get_permutation_start(permutation_index)
1844 - template_start_index;
1846 distance = template_size;
1849 //if there are no more values, but we still have templates
1850 // and the template is not an asterisk or a permutation start
1854 //we try to match as many values as possible
1855 //an asterisk is handled like a 0 length permutation
1859 good = match_function(value_ptr, value_start_index + i,
1860 template_ptr, template_start_index + i);
1862 //bad stop: something can't be matched
1863 //half bad half good stop: the end of values is reached
1864 //good stop: matching on the full distance or till an asterisk
1865 }while(good && i < value_size && i < distance &&
1866 !match_function(value_ptr, -1, template_ptr,
1867 template_start_index + i));
1869 //if we matched on the full distance or till an asterisk
1870 if(good && (i == distance ||
1871 match_function(value_ptr, -1, template_ptr,
1872 template_start_index + i)))
1874 //reached the end of the templates
1875 if(i == template_size)
1879 //the next level would return FAILURE so we don't step it
1882 //i == value_size, so we matched everything
1886 //we reached the next asterisk or permutation,
1887 // so step to the next level
1888 return recursive_permutation_match(value_ptr,value_start_index + i,
1891 template_start_index + i,
1894 match_function, shift_size);
1897 //something bad happened, so we have to check how bad the situation is
1898 if( i == value_size)
1900 //the aren't values left, meaning that the match is not possible
1903 //we couldn't match, but there is still a chance of matching
1905 //try to find a matching value for the last checked (and failed)
1907 // smaller jumps would fail so we skip them
1911 good = match_function(value_ptr,
1912 value_start_index + i + shift_size,
1913 template_ptr, template_start_index + i);
1915 }while(!good && i + shift_size < value_size);
1922 // the template can not be matched later
1930 template <typename T_value_type, typename T_template_type,
1931 unsigned int array_size, int index_offset>
1932 boolean match_permutation_array(const Base_Type *value_ptr,
1934 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
1936 match_function_t match_function)
1938 if (value_ptr == NULL || value_size < 0 ||
1939 template_ptr == NULL || template_size < 0 ||
1940 template_ptr->get_selection() != SPECIFIC_VALUE)
1941 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
1943 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1944 // use the simplified algorithm if the template does not contain permutation
1945 if (nof_permutations == 0)
1946 return match_array(value_ptr, value_size,
1947 template_ptr, template_size, match_function);
1948 // use 'set of' matching if all template elements are grouped into one
1950 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
1951 template_ptr->get_permutation_end(0) ==
1952 (unsigned int)(template_size - 1))
1953 return match_set_of(value_ptr, value_size, template_ptr, template_size,
1956 unsigned int shift_size = 0;
1957 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
1958 0, template_size, 0, match_function, shift_size) == SUCCESS;