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(" }");
90 extern unsigned int get_port_array_index(int index_value,
91 unsigned int array_size, int index_offset);
92 extern unsigned int get_port_array_index(const INTEGER& index_value,
93 unsigned int array_size, int index_offset);
95 template <typename T_type, unsigned int array_size, int index_offset>
97 T_type array_elements[array_size];
98 char * names[array_size];
100 /// Copy constructor disallowed.
101 PORT_ARRAY(const PORT_ARRAY& other_value);
102 /// Assignment disallowed.
103 PORT_ARRAY& operator=(const PORT_ARRAY& other_value);
109 for (size_t i = 0; i < array_size; ++i) {
114 T_type& operator[](int index_value) { return array_elements[
115 get_port_array_index(index_value, array_size, index_offset)]; }
116 T_type& operator[](const INTEGER& index_value) { return array_elements[
117 get_port_array_index(index_value, array_size, index_offset)]; }
119 int n_elem() const { return array_size; }
120 int size_of() const { return array_size; }
121 int lengthof()const { return array_size; }
123 void set_name(const char * name_string)
125 for (int i = 0; i < (int)array_size; ++i) {
126 // i must be int, see comment in TIMER_ARRAY::set_name
127 names[i] = mputprintf(mcopystr(name_string), "[%d]", index_offset+i);
128 array_elements[i].set_name(names[i]);
134 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
135 array_elements[v_index].activate_port();
141 TTCN_Logger::log_event_str("{ ");
142 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
143 if (v_index > 0) TTCN_Logger::log_event_str(", ");
144 array_elements[v_index].log();
146 TTCN_Logger::log_event_str(" }");
150 ////////////////////////////////////////////////////////////////////////////////
152 extern unsigned int get_array_index(int index_value,
153 unsigned int array_size, int index_offset);
154 extern unsigned int get_array_index(const INTEGER& index_value,
155 unsigned int array_size, int index_offset);
157 template <typename T_type, unsigned int array_size, int index_offset>
158 class VALUE_ARRAY : public Base_Type
160 T_type array_elements[array_size];
162 // This class use the compiler-generated copy constructor and
165 boolean operator==(const VALUE_ARRAY& other_value) const;
166 inline boolean operator!=(const VALUE_ARRAY& other_value) const
167 { return !(*this == other_value); }
169 T_type& operator[](int index_value) { return array_elements[
170 get_array_index(index_value, array_size, index_offset)]; }
171 T_type& operator[](const INTEGER& index_value) { return array_elements[
172 get_array_index(index_value, array_size, index_offset)]; }
173 const T_type& operator[](int index_value) const { return array_elements[
174 get_array_index(index_value, array_size, index_offset)]; }
175 const T_type& operator[](const INTEGER& index_value) const {
176 return array_elements[
177 get_array_index(index_value, array_size, index_offset)];
181 VALUE_ARRAY operator<<=(int rotate_count) const;
182 VALUE_ARRAY operator<<=(const INTEGER& rotate_count) const;
183 VALUE_ARRAY operator>>=(int rotate_count) const;
184 VALUE_ARRAY operator>>=(const INTEGER& rotate_count) const;
186 T_type& array_element(unsigned int index_value)
187 { return array_elements[index_value]; }
188 const T_type& array_element(unsigned int index_value) const
189 { return array_elements[index_value]; }
191 void set_implicit_omit();
193 boolean is_bound() const;
194 boolean is_value() const;
198 inline int n_elem() const { return array_size; }
199 inline int size_of() const { return array_size; }
200 int lengthof() const;
202 void set_param(Module_Param& param);
204 #ifdef TITAN_RUNTIME_2
205 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
206 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
207 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
208 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
210 inline boolean is_present() const { return is_bound(); }
213 void encode_text(Text_Buf& text_buf) const;
214 void decode_text(Text_Buf& text_buf);
216 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
217 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
219 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
220 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
222 /** Encodes accordingly to the JSON encoding rules.
223 * Returns the length of the encoded data. */
224 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
226 /** Decodes accordingly to the JSON encoding rules.
227 * Returns the length of the decoded data. */
228 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
230 // Dummy functions, only used in record of/set of (the referenced indices
231 // cannot be deleted, since arrays have a fixed size)
232 void add_refd_index(int) {}
233 void remove_refd_index(int) {}
236 template <typename T_type, unsigned int array_size, int index_offset>
237 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
238 (const VALUE_ARRAY& other_value) const
240 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
241 if (array_elements[elem_count] != other_value.array_elements[elem_count])
246 template <typename T_type, unsigned int array_size, int index_offset>
247 VALUE_ARRAY<T_type,array_size,index_offset>
248 VALUE_ARRAY<T_type,array_size,index_offset>::
249 operator<<=(int rotate_count) const {
250 return *this >>= (-rotate_count);
253 template <typename T_type, unsigned int array_size, int index_offset>
254 VALUE_ARRAY<T_type,array_size,index_offset>
255 VALUE_ARRAY<T_type,array_size,index_offset>::
256 operator<<=(const INTEGER& rotate_count) const {
257 rotate_count.must_bound("Unbound integer operand of rotate left "
259 return *this >>= (int)(-rotate_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 {
267 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
268 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
269 if (rc == 0) return *this;
270 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
271 for (unsigned int i=0; i<array_size; i++) {
272 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
277 template <typename T_type, unsigned int array_size, int index_offset>
278 VALUE_ARRAY<T_type,array_size,index_offset>
279 VALUE_ARRAY<T_type,array_size,index_offset>::
280 operator>>=(const INTEGER& rotate_count) const {
281 rotate_count.must_bound("Unbound integer operand of rotate right "
283 return *this >>= (int)rotate_count;
286 template <typename T_type, unsigned int array_size, int index_offset>
287 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
289 for (unsigned int i = 0; i < array_size; ++i) {
290 if (array_elements[i].is_bound())
291 array_elements[i].set_implicit_omit();
295 template <typename T_type, unsigned int array_size, int index_offset>
296 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
298 for (unsigned int i = 0; i < array_size; ++i) {
299 if (!array_elements[i].is_bound()) {
306 template <typename T_type, unsigned int array_size, int index_offset>
307 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
309 for (unsigned int i = 0; i < array_size; ++i) {
310 if (!array_elements[i].is_value()) {
317 template <typename T_type, unsigned int array_size, int index_offset>
318 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
320 for (unsigned int i = 0; i < array_size; ++i) {
321 array_elements[i].clean_up();
325 template <typename T_type, unsigned int array_size, int index_offset>
326 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
328 TTCN_Logger::log_event_str("{ ");
329 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
331 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
332 array_elements[elem_count].log();
334 TTCN_Logger::log_event_str(" }");
337 template <typename T_type, unsigned int array_size, int index_offset>
338 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
341 for (unsigned int my_length=array_size; my_length>0; my_length--)
343 if (array_elements[my_length-1].is_bound()) return my_length;
348 template <typename T_type, unsigned int array_size, int index_offset>
349 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
352 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
353 param.get_id()->next_name()) {
354 // Haven't reached the end of the module parameter name
355 // => the name refers to one of the elements, not to the whole array
356 char* param_field = param.get_id()->get_current_name();
357 if (param_field[0] < '0' || param_field[0] > '9') {
358 param.error("Unexpected record field name in module parameter, expected a valid"
361 unsigned int param_index = -1;
362 sscanf(param_field, "%u", ¶m_index);
363 if (param_index >= array_size) {
364 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
366 array_elements[param_index].set_param(param);
370 param.basic_check(Module_Param::BC_VALUE, "array value");
371 switch (param.get_type()) {
372 case Module_Param::MP_Value_List:
373 if (param.get_size()!=array_size) {
374 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);
376 for (size_t i=0; i<param.get_size(); ++i) {
377 Module_Param* const curr = param.get_elem(i);
378 if (curr->get_type()!=Module_Param::MP_NotUsed) {
379 array_elements[i].set_param(*curr);
383 case Module_Param::MP_Indexed_List:
384 for (size_t i=0; i<param.get_size(); ++i) {
385 Module_Param* const curr = param.get_elem(i);
386 array_elements[curr->get_id()->get_index()].set_param(*curr);
390 param.type_error("array value");
394 template <typename T_type, unsigned int array_size, int index_offset>
395 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
396 (Text_Buf& text_buf) const
398 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
399 array_elements[elem_count].encode_text(text_buf);
402 template <typename T_type, unsigned int array_size, int index_offset>
403 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
406 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
407 array_elements[elem_count].decode_text(text_buf);
410 template <typename T_type, unsigned int array_size, int index_offset>
411 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
412 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
415 va_start(pvar, p_coding);
417 case TTCN_EncDec::CT_JSON: {
418 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
419 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
420 ("No JSON descriptor available for type '%s'.", p_td.name);
421 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
422 JSON_encode(p_td, tok);
423 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
426 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
431 template <typename T_type, unsigned int array_size, int index_offset>
432 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
433 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
436 case TTCN_EncDec::CT_JSON: {
437 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
438 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
439 ("No JSON descriptor available for type '%s'.", p_td.name);
440 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
441 if(JSON_decode(p_td, tok, false)<0)
442 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
443 "because invalid or incomplete message was received", p_td.name);
444 p_buf.set_pos(tok.get_buf_pos());
447 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
451 template <typename T_type, unsigned int array_size, int index_offset>
452 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
453 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
456 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
457 "Encoding an unbound array value.");
461 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
463 for(unsigned int i = 0; i < array_size; ++i) {
464 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
465 if (0 > ret_val) break;
469 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
473 template <typename T_type, unsigned int array_size, int index_offset>
474 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
475 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)
477 json_token_t token = JSON_TOKEN_NONE;
478 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
479 if (JSON_TOKEN_ERROR == token) {
480 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
481 return JSON_ERROR_FATAL;
483 else if (JSON_TOKEN_ARRAY_START != token) {
484 return JSON_ERROR_INVALID_TOKEN;
487 for(unsigned int i = 0; i < array_size; ++i) {
488 int ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
489 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
490 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
491 array_size - i, (array_size - i > 1) ? "s" : "");
492 return JSON_ERROR_FATAL;
494 else if (JSON_ERROR_FATAL == ret_val) {
498 return JSON_ERROR_FATAL;
503 dec_len += p_tok.get_next_token(&token, NULL, NULL);
504 if (JSON_TOKEN_ARRAY_END != token) {
505 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
509 return JSON_ERROR_FATAL;
516 template <typename T_value_type, typename T_template_type,
517 unsigned int array_size, int index_offset>
518 class TEMPLATE_ARRAY : public Restricted_Length_Template
524 T_template_type **value_elements;
527 unsigned int n_values;
528 TEMPLATE_ARRAY *list_value;
532 struct Pair_of_elements;
533 Pair_of_elements *permutation_intervals;
534 unsigned int number_of_permutations;
536 void clean_up_intervals();
537 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
539 void copy_template(const TEMPLATE_ARRAY& other_value);
540 void set_selection(template_sel new_selection);
541 void set_selection(const TEMPLATE_ARRAY& other_value);
542 void encode_text_permutation(Text_Buf& text_buf) const;
543 void decode_text_permutation(Text_Buf& text_buf);
548 number_of_permutations = 0;
549 permutation_intervals = NULL;
551 TEMPLATE_ARRAY(template_sel other_value)
552 : Restricted_Length_Template(other_value)
554 check_single_selection(other_value);
555 number_of_permutations = 0;
556 permutation_intervals = NULL;
558 TEMPLATE_ARRAY(null_type other_value);
559 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
562 number_of_permutations = 0;
563 permutation_intervals = NULL;
564 copy_value(other_value);
567 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
568 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
569 : Restricted_Length_Template()
571 number_of_permutations = 0;
572 permutation_intervals = NULL;
573 copy_template(other_value);
578 clean_up_intervals();
583 TEMPLATE_ARRAY& operator=(template_sel other_value);
584 TEMPLATE_ARRAY& operator=(null_type other_value);
585 TEMPLATE_ARRAY& operator=(const
586 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
587 TEMPLATE_ARRAY& operator=(const
588 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
589 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
591 T_template_type& operator[](int index_value);
592 T_template_type& operator[](const INTEGER& index_value);
593 const T_template_type& operator[](int index_value) const;
594 const T_template_type& operator[](const INTEGER& index_value) const;
596 void set_size(int new_size);
599 int size_of(boolean is_size) const;
600 inline int size_of() const { return size_of(TRUE); }
601 inline int lengthof() const { return size_of(FALSE); }
603 void add_permutation(unsigned int start_index, unsigned int end_index);
605 /** Removes all permutations set on this template, used when template variables
606 * are given new values. */
607 void remove_all_permutations() { clean_up_intervals(); }
609 unsigned int get_number_of_permutations() const;
610 unsigned int get_permutation_start(unsigned int index_value) const;
611 unsigned int get_permutation_end(unsigned int index_value) const;
612 unsigned int get_permutation_size(unsigned int index_value) const;
613 boolean permutation_starts_at(unsigned int index_value) const;
614 boolean permutation_ends_at(unsigned int index_value) const;
617 static boolean match_function_specific(
618 const Base_Type *value_ptr, int value_index,
619 const Restricted_Length_Template *template_ptr, int template_index);
621 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
624 boolean is_value() const;
625 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
627 void set_type(template_sel template_type, unsigned int list_length);
628 TEMPLATE_ARRAY& list_item(unsigned int list_index);
631 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
634 void set_param(Module_Param& param);
636 void encode_text(Text_Buf& text_buf) const;
637 void decode_text(Text_Buf& text_buf);
639 boolean is_present() const;
640 boolean match_omit() const;
642 #ifdef TITAN_RUNTIME_2
643 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
644 void set_value(template_sel other_value) { *this = other_value; }
645 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
646 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
647 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
648 boolean matchv(const Base_Type* other_value) const { return match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value))); }
649 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))); }
651 void check_restriction(template_res t_res, const char* t_name=NULL) const;
655 template <typename T_value_type, typename T_template_type,
656 unsigned int array_size, int index_offset>
657 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
659 unsigned int start_index, end_index; //beginning and ending index
662 template <typename T_value_type, typename T_template_type,
663 unsigned int array_size, int index_offset>
664 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
667 switch (template_selection)
670 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
671 delete single_value.value_elements[elem_count];
672 free_pointers((void**)single_value.value_elements);
675 case COMPLEMENTED_LIST:
676 delete [] value_list.list_value;
681 template_selection = UNINITIALIZED_TEMPLATE;
684 template <typename T_value_type, typename T_template_type,
685 unsigned int array_size, int index_offset>
686 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
689 number_of_permutations = 0;
690 Free(permutation_intervals);
691 permutation_intervals = NULL;
694 template <typename T_value_type, typename T_template_type,
695 unsigned int array_size, int index_offset>
696 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
697 set_selection(template_sel other_value)
699 Restricted_Length_Template::set_selection(other_value);
700 clean_up_intervals();
703 template <typename T_value_type, typename T_template_type,
704 unsigned int array_size, int index_offset>
705 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
706 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
708 Restricted_Length_Template::set_selection(other_value);
709 clean_up_intervals();
710 if(other_value.template_selection == SPECIFIC_VALUE)
712 number_of_permutations = other_value.number_of_permutations;
713 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
714 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
718 template <typename T_value_type, typename T_template_type,
719 unsigned int array_size, int index_offset>
720 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
721 encode_text_permutation(Text_Buf& text_buf) const
723 encode_text_restricted(text_buf);
724 text_buf.push_int(number_of_permutations);
726 for(unsigned int i = 0; i < number_of_permutations; i++)
728 text_buf.push_int(permutation_intervals[i].start_index);
729 text_buf.push_int(permutation_intervals[i].end_index);
733 template <typename T_value_type, typename T_template_type,
734 unsigned int array_size, int index_offset>
735 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
736 decode_text_permutation(Text_Buf& text_buf)
738 decode_text_restricted(text_buf);
740 number_of_permutations = text_buf.pull_int().get_val();
741 permutation_intervals = (Pair_of_elements *)Malloc
742 (number_of_permutations * sizeof(Pair_of_elements));
744 for (unsigned int i = 0; i < number_of_permutations; i++)
746 permutation_intervals[i].start_index =
747 text_buf.pull_int().get_val();
748 permutation_intervals[i].end_index =
749 text_buf.pull_int().get_val();
753 template <typename T_value_type, typename T_template_type,
754 unsigned int array_size, int index_offset>
755 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
756 add_permutation(unsigned int start_index, unsigned int end_index)
758 if(start_index > end_index)
759 TTCN_error("wrong permutation interval settings start (%d)"
760 "can not be greater than end (%d)",start_index, end_index);
762 if(number_of_permutations > 0 &&
763 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
764 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
766 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
767 permutation_intervals[number_of_permutations].start_index = start_index;
768 permutation_intervals[number_of_permutations].end_index = end_index;
769 number_of_permutations++;
772 template <typename T_value_type, typename T_template_type,
773 unsigned int array_size, int index_offset>
774 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
775 get_number_of_permutations(void) const
777 return number_of_permutations;
780 template <typename T_value_type, typename T_template_type,
781 unsigned int array_size, int index_offset>
782 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
783 get_permutation_start(unsigned int index_value) const
785 if(index_value >= number_of_permutations)
786 TTCN_error("Index overflow (%d)", index_value);
788 return permutation_intervals[index_value].start_index;
791 template <typename T_value_type, typename T_template_type,
792 unsigned int array_size, int index_offset>
793 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
794 get_permutation_end(unsigned int index_value) const
796 if(index_value >= number_of_permutations)
797 TTCN_error("Index overflow (%d)", index_value);
799 return permutation_intervals[index_value].end_index;
802 template <typename T_value_type, typename T_template_type,
803 unsigned int array_size, int index_offset>
804 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
805 get_permutation_size(unsigned int index_value) const
807 if(index_value >= number_of_permutations)
808 TTCN_error("Index overflow (%d)", index_value);
810 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
813 template <typename T_value_type, typename T_template_type,
814 unsigned int array_size, int index_offset>
815 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
816 permutation_starts_at(unsigned int index_value) const
818 for(unsigned int i = 0; i < number_of_permutations; i++)
820 if(permutation_intervals[i].start_index == index_value)
827 template <typename T_value_type, typename T_template_type,
828 unsigned int array_size, int index_offset>
829 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
830 permutation_ends_at(unsigned int index_value) const
832 for(unsigned int i = 0; i < number_of_permutations; i++)
834 if(permutation_intervals[i].end_index == index_value)
841 template <typename T_value_type, typename T_template_type,
842 unsigned int array_size, int index_offset>
843 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
844 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
847 single_value.n_elements = array_size;
848 single_value.value_elements =
849 (T_template_type**)allocate_pointers(array_size);
850 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
851 single_value.value_elements[elem_count] =
852 new T_template_type(other_value.array_element(elem_count));
853 set_selection(SPECIFIC_VALUE);
856 template <typename T_value_type, typename T_template_type,
857 unsigned int array_size, int index_offset>
858 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
859 copy_template(const TEMPLATE_ARRAY& other_value)
861 switch (other_value.template_selection)
864 single_value.n_elements = other_value.single_value.n_elements;
865 single_value.value_elements =
866 (T_template_type**)allocate_pointers(single_value.n_elements);
867 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
868 single_value.value_elements[elem_count] = new
869 T_template_type(*other_value.single_value.value_elements[elem_count]);
876 case COMPLEMENTED_LIST:
877 value_list.n_values = other_value.value_list.n_values;
878 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
879 for (unsigned int list_count = 0; list_count < value_list.n_values;
881 value_list.list_value[list_count].copy_template(
882 other_value.value_list.list_value[list_count]);
885 TTCN_error("Copying an uninitialized/unsupported array template.");
887 set_selection(other_value);
890 template <typename T_value_type, typename T_template_type,
891 unsigned int array_size, int index_offset>
892 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
893 TEMPLATE_ARRAY(null_type)
894 : Restricted_Length_Template(SPECIFIC_VALUE)
896 single_value.n_elements = 0;
897 single_value.value_elements = NULL;
898 number_of_permutations = 0;
899 permutation_intervals = NULL;
902 template <typename T_value_type, typename T_template_type,
903 unsigned int array_size, int index_offset>
904 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
906 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
908 number_of_permutations = 0;
909 permutation_intervals = NULL;
910 switch (other_value.get_selection()) {
911 case OPTIONAL_PRESENT:
912 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
916 set_selection(OMIT_VALUE);
919 TTCN_error("Creating an array template from an unbound optional field.");
923 template <typename T_value_type, typename T_template_type,
924 unsigned int array_size, int index_offset>
925 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
926 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
927 operator=(template_sel other_value)
929 check_single_selection(other_value);
931 set_selection(other_value);
935 template <typename T_value_type, typename T_template_type,
936 unsigned int array_size, int index_offset>
937 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
938 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
942 set_selection(SPECIFIC_VALUE);
943 single_value.n_elements = 0;
944 single_value.value_elements = NULL;
948 template <typename T_value_type, typename T_template_type,
949 unsigned int array_size, int index_offset>
950 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
951 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
952 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
955 copy_value(other_value);
959 template <typename T_value_type, typename T_template_type,
960 unsigned int array_size, int index_offset>
961 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
962 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
964 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
967 switch (other_value.get_selection()) {
968 case OPTIONAL_PRESENT:
969 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
973 set_selection(OMIT_VALUE);
976 TTCN_error("Assignment of an unbound optional field to an array template.");
981 template <typename T_value_type, typename T_template_type,
982 unsigned int array_size, int index_offset>
983 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
984 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
986 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
989 if (&other_value != this)
992 copy_template(other_value);
997 template <typename T_value_type, typename T_template_type,
998 unsigned int array_size, int index_offset>
1000 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1003 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1005 "Accessing an element of an array template using invalid index: %d. "
1006 "Index range is [%d,%d].",
1007 index_value, index_offset, index_offset+(int)array_size);
1008 // transform index value according to given offset
1009 index_value -= index_offset;
1010 // the template of an array is not restricted to array_size, allow any length
1011 // in case of * or ? expand to full size to avoid uninitialized values
1012 switch (template_selection)
1014 case SPECIFIC_VALUE:
1015 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1019 set_size(array_size);
1022 set_size(index_value + 1);
1024 return *single_value.value_elements[index_value];
1027 template <typename T_value_type, typename T_template_type,
1028 unsigned int array_size, int index_offset>
1030 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1031 (const INTEGER& index_value)
1033 index_value.must_bound(
1034 "Using an unbound integer value for indexing an array template.");
1035 return (*this)[(int)index_value];
1038 template <typename T_value_type, typename T_template_type,
1039 unsigned int array_size, int index_offset>
1040 const T_template_type&
1041 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1042 (int index_value) const
1044 if (index_value < index_offset)
1046 "Accessing an element of an array template using invalid index: %d. "
1047 "Index range starts at %d.",
1048 index_value, index_offset);
1049 // transform index value according to given offset
1050 index_value -= index_offset;
1051 // const is specific template
1052 if (template_selection != SPECIFIC_VALUE)
1053 TTCN_error("Accessing an element of a non-specific array template.");
1054 if (index_value >= single_value.n_elements)
1055 TTCN_error("Index overflow in an array template: "
1056 "The index is %d (starting at %d),"
1057 " but the template has only %d elements.",
1058 index_value+index_offset, index_offset, single_value.n_elements);
1059 return *single_value.value_elements[index_value];
1062 template <typename T_value_type, typename T_template_type,
1063 unsigned int array_size, int index_offset>
1064 const T_template_type&
1065 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1066 (const INTEGER& index_value) const
1068 index_value.must_bound(
1069 "Using an unbound integer value for indexing an array template.");
1070 return (*this)[(int)index_value];
1073 template <typename T_value_type, typename T_template_type,
1074 unsigned int array_size, int index_offset>
1075 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1076 set_size(int new_size)
1078 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1079 "for an array template.");
1080 template_sel old_selection = template_selection;
1081 if (old_selection != SPECIFIC_VALUE)
1084 set_selection(SPECIFIC_VALUE);
1085 single_value.n_elements = 0;
1086 single_value.value_elements = NULL;
1088 if (new_size > single_value.n_elements)
1090 single_value.value_elements =
1091 (T_template_type**)reallocate_pointers(
1092 (void**)single_value.value_elements, single_value.n_elements, new_size);
1093 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1095 for (int elem_count = single_value.n_elements;
1096 elem_count < new_size; elem_count++)
1097 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
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;
1105 single_value.n_elements = new_size;
1107 else if (new_size < single_value.n_elements)
1109 for (int elem_count = new_size; elem_count < single_value.n_elements;
1111 delete single_value.value_elements[elem_count];
1112 single_value.value_elements =
1113 (T_template_type**)reallocate_pointers(
1114 (void**)single_value.value_elements, single_value.n_elements, new_size);
1115 single_value.n_elements = new_size;
1119 template <typename T_value_type, typename T_template_type,
1120 unsigned int array_size, int index_offset>
1121 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1124 switch (template_selection) {
1125 case SPECIFIC_VALUE:
1126 return single_value.n_elements;
1128 return value_list.n_values;
1130 TTCN_error("Performing n_elem");
1134 template <typename T_value_type, typename T_template_type,
1135 unsigned int array_size, int index_offset>
1136 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1137 size_of(boolean is_size) const
1139 const char* op_name = is_size ? "size" : "length";
1141 boolean has_any_or_none;
1143 TTCN_error("Performing %sof() operation on an array template "
1144 "which has an ifpresent attribute.", op_name);
1145 switch (template_selection)
1147 case SPECIFIC_VALUE: {
1149 has_any_or_none = FALSE;
1150 int elem_count = single_value.n_elements;
1151 if (!is_size) { // lengthof()
1152 while (elem_count>0 &&
1153 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1155 for (int i=0; i<elem_count; i++)
1157 switch (single_value.value_elements[i]->get_selection())
1160 TTCN_error("Performing %sof() operation on an array template "
1161 "containing omit element.", op_name);
1163 has_any_or_none = TRUE;
1172 TTCN_error("Performing %sof() operation on an array template "
1173 "containing omit value.", op_name);
1177 has_any_or_none = TRUE; // max. size is infinity
1180 // error if any element does not have size or the sizes differ
1181 if (value_list.n_values<1)
1182 TTCN_error("Performing %sof() operation on an array template "
1183 "containing an empty list.", op_name);
1184 int item_size = value_list.list_value[0].size_of(is_size);
1185 for (unsigned int i = 1; i < value_list.n_values; i++) {
1186 if (value_list.list_value[i].size_of(is_size)!=item_size)
1187 TTCN_error("Performing %sof() operation on an array template "
1188 "containing a value list with different sizes.", op_name);
1190 min_size = item_size;
1191 has_any_or_none = FALSE;
1193 case COMPLEMENTED_LIST:
1194 TTCN_error("Performing %sof() operation on an array template "
1195 "containing complemented list.", op_name);
1197 TTCN_error("Performing %sof() operation on an "
1198 "uninitialized/unsupported array template.", op_name);
1200 return check_section_is_single(min_size, has_any_or_none,
1201 op_name, "an", "array template");
1204 template <typename T_value_type, typename T_template_type,
1205 unsigned int array_size, int index_offset>
1206 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1207 match_function_specific(const Base_Type *value_ptr, int value_index,
1208 const Restricted_Length_Template *template_ptr,
1211 if (value_index >= 0)
1212 return ((const TEMPLATE_ARRAY*)template_ptr)->
1213 single_value.value_elements[template_index]->
1215 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1216 ->array_element(value_index));
1218 return ((const TEMPLATE_ARRAY*)template_ptr)->
1219 single_value.value_elements[template_index]->is_any_or_omit();
1222 template <typename T_value_type, typename T_template_type,
1223 unsigned int array_size, int index_offset>
1224 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1225 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1228 if (!match_length(array_size)) return FALSE;
1229 switch (template_selection)
1231 case SPECIFIC_VALUE:
1232 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1233 match_function_specific);
1240 case COMPLEMENTED_LIST:
1241 for (unsigned int list_count = 0; list_count < value_list.n_values;
1243 if (value_list.list_value[list_count].match(other_value))
1244 return template_selection == VALUE_LIST;
1245 return template_selection == COMPLEMENTED_LIST;
1247 TTCN_error("Matching with an uninitialized/unsupported array template.");
1252 template <typename T_value_type, typename T_template_type,
1253 unsigned int array_size, int index_offset>
1254 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1257 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1258 for (int i=0; i<single_value.n_elements; i++)
1259 if (!single_value.value_elements[i]->is_value()) return FALSE;
1263 template <typename T_value_type, typename T_template_type,
1264 unsigned int array_size, int index_offset>
1265 VALUE_ARRAY<T_value_type, array_size, index_offset>
1266 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1269 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1270 TTCN_error("Performing a valueof or send operation on a "
1271 "non-specific array template.");
1272 // the size of the template must be the size of the value
1273 if (single_value.n_elements!=array_size)
1274 TTCN_error("Performing a valueof or send operation on a "
1275 "specific array template with invalid size.");
1276 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1277 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1278 ret_val.array_element(elem_count) =
1279 single_value.value_elements[elem_count]->valueof();
1283 template <typename T_value_type, typename T_template_type,
1284 unsigned int array_size, int index_offset>
1285 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1286 set_type(template_sel template_type, unsigned int list_length)
1289 switch (template_type) {
1291 case COMPLEMENTED_LIST:
1292 value_list.n_values = list_length;
1293 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1297 "Internal error: Setting an invalid type for an array template.");
1299 set_selection(template_type);
1302 template <typename T_value_type, typename T_template_type,
1303 unsigned int array_size, int index_offset>
1304 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1305 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1306 list_item(unsigned int list_index)
1308 if (template_selection != VALUE_LIST &&
1309 template_selection != COMPLEMENTED_LIST)
1310 TTCN_error("Internal error: Accessing a list element of a non-list "
1312 if (list_index >= value_list.n_values)
1313 TTCN_error("Internal error: Index overflow in a value list "
1315 return value_list.list_value[list_index];
1318 template <typename T_value_type, typename T_template_type,
1319 unsigned int array_size, int index_offset>
1320 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1323 switch (template_selection)
1325 case SPECIFIC_VALUE:
1326 if (single_value.n_elements > 0)
1328 TTCN_Logger::log_event_str("{ ");
1329 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1331 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1332 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1333 single_value.value_elements[elem_count]->log();
1334 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1336 TTCN_Logger::log_event_str(" }");
1339 TTCN_Logger::log_event_str("{ }");
1341 case COMPLEMENTED_LIST:
1342 TTCN_Logger::log_event_str("complement");
1344 TTCN_Logger::log_char('(');
1345 for (unsigned int list_count = 0; list_count < value_list.n_values;
1348 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1349 value_list.list_value[list_count].log();
1351 TTCN_Logger::log_char(')');
1361 template <typename T_value_type, typename T_template_type,
1362 unsigned int array_size, int index_offset>
1363 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1364 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1367 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1368 if(match(match_value)){
1369 TTCN_Logger::print_logmatch_buffer();
1370 TTCN_Logger::log_event_str(" matched");
1372 if (template_selection == SPECIFIC_VALUE &&
1373 single_value.n_elements == array_size) {
1374 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1375 for (unsigned int elem_count = 0; elem_count < array_size;
1377 if(!single_value.value_elements[elem_count]->
1378 match(match_value.array_element(elem_count))){
1379 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1380 single_value.value_elements[elem_count]->
1381 log_match(match_value.array_element(elem_count));
1382 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1385 log_match_length(array_size);
1387 TTCN_Logger::print_logmatch_buffer();
1389 TTCN_Logger::log_event_str(" with ");
1391 TTCN_Logger::log_event_str(" unmatched");
1396 if (template_selection == SPECIFIC_VALUE &&
1397 single_value.n_elements == array_size) {
1398 TTCN_Logger::log_event_str("{ ");
1399 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1400 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1401 single_value.value_elements[elem_count]->log_match(match_value.array_element(elem_count));
1403 TTCN_Logger::log_event_str(" }");
1404 log_match_length(array_size);
1407 TTCN_Logger::log_event_str(" with ");
1409 if (match(match_value)) TTCN_Logger::log_event_str(" matched");
1410 else TTCN_Logger::log_event_str(" unmatched");
1414 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1415 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1417 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1418 param.get_id()->next_name()) {
1419 // Haven't reached the end of the module parameter name
1420 // => the name refers to one of the elements, not to the whole array
1421 char* param_field = param.get_id()->get_current_name();
1422 if (param_field[0] < '0' || param_field[0] > '9') {
1423 param.error("Unexpected record field name in module parameter, expected a valid"
1424 " array template index");
1426 unsigned int param_index = -1;
1427 sscanf(param_field, "%u", ¶m_index);
1428 if (param_index >= array_size) {
1429 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1431 (*this)[param_index].set_param(param);
1435 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1436 switch (param.get_type()) {
1437 case Module_Param::MP_Omit:
1440 case Module_Param::MP_Any:
1443 case Module_Param::MP_AnyOrNone:
1444 *this = ANY_OR_OMIT;
1446 case Module_Param::MP_List_Template:
1447 case Module_Param::MP_ComplementList_Template:
1448 set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());
1449 for (size_t i=0; i<param.get_size(); i++) {
1450 list_item(i).set_param(*param.get_elem(i));
1453 case Module_Param::MP_Value_List:
1454 set_size(param.get_size());
1455 for (size_t i=0; i<param.get_size(); ++i) {
1456 Module_Param* const curr = param.get_elem(i);
1457 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1458 (*this)[(int)i+index_offset].set_param(*curr);
1462 case Module_Param::MP_Indexed_List:
1463 for (size_t i=0; i<param.get_size(); ++i) {
1464 Module_Param* const curr = param.get_elem(i);
1465 (*this)[curr->get_id()->get_index()].set_param(*curr);
1469 param.type_error("array template");
1471 is_ifpresent = param.get_ifpresent();
1474 template <typename T_value_type, typename T_template_type,
1475 unsigned int array_size, int index_offset>
1476 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1477 encode_text(Text_Buf& text_buf) const
1479 encode_text_restricted(text_buf);
1480 switch (template_selection)
1482 case SPECIFIC_VALUE:
1483 text_buf.push_int(single_value.n_elements);
1484 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1485 single_value.value_elements[elem_count]->encode_text(text_buf);
1492 case COMPLEMENTED_LIST:
1493 text_buf.push_int(value_list.n_values);
1494 for (unsigned int list_count = 0; list_count < value_list.n_values;
1496 value_list.list_value[list_count].encode_text(text_buf);
1499 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1504 template <typename T_value_type, typename T_template_type,
1505 unsigned int array_size, int index_offset>
1506 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1507 decode_text(Text_Buf& text_buf)
1510 decode_text_restricted(text_buf);
1511 switch (template_selection)
1513 case SPECIFIC_VALUE:
1514 single_value.n_elements = text_buf.pull_int().get_val();
1515 if (single_value.n_elements < 0)
1516 TTCN_error("Text decoder: Negative size was received for an "
1518 single_value.value_elements =
1519 (T_template_type**)allocate_pointers(single_value.n_elements);
1520 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1522 single_value.value_elements[elem_count] = new T_template_type;
1523 single_value.value_elements[elem_count]->decode_text(text_buf);
1531 case COMPLEMENTED_LIST:
1532 value_list.n_values = text_buf.pull_int().get_val();
1533 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1534 for (unsigned int list_count = 0; list_count < value_list.n_values;
1536 value_list.list_value[list_count].decode_text(text_buf);
1539 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1540 "for an array template.");
1544 template <typename T_value_type, typename T_template_type,
1545 unsigned int array_size, int index_offset>
1546 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1549 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1550 return !match_omit();
1553 template <typename T_value_type, typename T_template_type,
1554 unsigned int array_size, int index_offset>
1555 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1558 if (is_ifpresent) return TRUE;
1559 switch (template_selection) {
1564 case COMPLEMENTED_LIST:
1565 for (unsigned int i=0; i<value_list.n_values; i++)
1566 if (value_list.list_value[i].match_omit())
1567 return template_selection==VALUE_LIST;
1568 return template_selection==COMPLEMENTED_LIST;
1575 #ifndef TITAN_RUNTIME_2
1576 template <typename T_value_type, typename T_template_type,
1577 unsigned int array_size, int index_offset>
1578 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1579 check_restriction(template_res t_res, const char* t_name) const
1581 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1582 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1584 if (template_selection==OMIT_VALUE) return;
1586 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1587 for (int i=0; i<single_value.n_elements; i++)
1588 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1591 if (!match_omit()) return;
1596 TTCN_error("Restriction `%s' on template of type %s violated.",
1597 get_res_name(t_res), t_name ? t_name : "array");
1601 template <typename T_value_type, typename T_template_type,
1602 unsigned int array_size, int index_offset>
1603 answer recursive_permutation_match(const Base_Type *value_ptr,
1604 unsigned int value_start_index,
1605 unsigned int value_size,
1606 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1607 unsigned int template_start_index,
1608 unsigned int template_size,
1609 unsigned int permutation_index,
1610 match_function_t match_function,
1611 unsigned int& shift_size)
1613 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1614 if (permutation_index > nof_permutations)
1615 TTCN_error("Internal error: recursive_permutation_match: "
1616 "invalid argument.");
1618 if (permutation_index < nof_permutations &&
1619 template_ptr->get_permutation_end(permutation_index) >
1620 template_start_index + template_size)
1621 TTCN_error("Internal error: recursive_permutation_match: wrong "
1622 "permutation interval settings for permutation %d.",
1628 if(template_size == 0)
1630 //reached the end of templates
1631 // if we reached the end of values => good
1639 //are we at an asterisk or at the beginning of a permutation interval
1640 boolean is_asterisk;
1641 boolean permutation_begins = permutation_index < nof_permutations &&
1642 template_start_index ==
1643 template_ptr->get_permutation_start(permutation_index);
1645 if (permutation_begins ||
1646 match_function(value_ptr, -1, template_ptr, template_start_index))
1648 unsigned int smallest_possible_size;
1649 unsigned int largest_possible_size;
1650 boolean has_asterisk;
1651 boolean already_superset;
1652 unsigned int permutation_size;
1654 //check how many values might be associated with this permutation
1655 //if we are at a permutation start
1656 if (permutation_begins)
1658 is_asterisk = FALSE;
1660 template_ptr->get_permutation_size(permutation_index);
1661 smallest_possible_size = 0;
1662 has_asterisk = FALSE;
1664 //count how many non asterisk elements are in the permutation
1665 for(unsigned int i = 0; i < permutation_size; i++)
1667 if(match_function(value_ptr, -1, template_ptr,
1668 i + template_start_index))
1670 has_asterisk = TRUE;
1672 smallest_possible_size++;
1676 //the real permutation size is bigger then the value size
1677 if(smallest_possible_size > value_size)
1680 //if the permutation has an asterisk then it can grow
1683 largest_possible_size = value_size;
1685 //if there are only asterisks in the permutation
1686 if(smallest_possible_size == 0)
1687 already_superset = TRUE;
1689 already_superset = FALSE;
1691 //without asterisks its size is fixed
1692 largest_possible_size = smallest_possible_size;
1693 already_superset = FALSE;
1698 already_superset = TRUE;
1699 permutation_size = 1;
1700 smallest_possible_size = 0;
1701 largest_possible_size = value_size;
1702 has_asterisk = TRUE;
1705 unsigned int temp_size = smallest_possible_size;
1708 //this is to make match_set_of incremental,
1709 // we store the already found pairs in this vector
1710 // so we wouldn't try to find a pair for those templates again
1711 // and we can set the covered state of values too
1712 // to not waste memory it is only created if needed
1713 int* pair_list = NULL;
1714 unsigned int old_temp_size = 0;
1716 if(!already_superset)
1718 pair_list = new int[permutation_size];
1719 for(unsigned int i = 0 ; i < permutation_size; i++)
1721 //in the beginning we haven't found a template to any values
1726 while(!already_superset)
1728 //must be a permutation having other values than asterisks
1732 //our set matching is extended with 2 more parameters
1733 // giving back how many templates
1734 // (other than asterisk) couldn't be matched
1735 // and setting / giving back the value-template pairs
1737 boolean found = match_set_of_internal(value_ptr, value_start_index,
1738 temp_size, template_ptr,
1739 template_start_index, permutation_size,
1740 match_function, SUPERSET, &x, pair_list,old_temp_size);
1744 already_superset = TRUE;
1746 //as we didn't found a match we have to try
1747 // a larger set of values
1748 //x is the number of templates we couldn't find
1749 // a matching pair for
1750 // the next must be at least this big to fully cover
1751 // on the other side if it would be bigger than it might miss
1752 // the smallest possible match.
1754 //if we can match with more values
1755 if(has_asterisk && temp_size + x <= largest_possible_size)
1757 old_temp_size = temp_size;
1761 return FAILURE; //else we failed
1769 //we reach here only if we found a match
1771 //can only go on recursively if we haven't reached the end
1773 //reached the end of templates
1774 if(permutation_size == template_size)
1776 if(has_asterisk || value_size == temp_size)
1782 for(unsigned int i = temp_size; i <= largest_possible_size;)
1788 //don't step the permutation index
1789 result = recursive_permutation_match(value_ptr,value_start_index+i,
1790 value_size - i, template_ptr,
1791 template_start_index +
1796 match_function, shift_size);
1798 //try with the next permutation
1799 result = recursive_permutation_match(value_ptr,value_start_index+i,
1800 value_size - i, template_ptr,
1801 template_start_index +
1803 template_size - permutation_size,
1804 permutation_index + 1,
1805 match_function, shift_size);
1808 if(result == SUCCESS)
1809 return SUCCESS; //we finished
1810 else if(result == NO_CHANCE)
1811 return NO_CHANCE; //matching is not possible
1812 else if(i == value_size) //we failed
1814 //if there is no chance of matching
1817 i += shift_size > 1 ? shift_size : 1;
1819 if(i > largest_possible_size)
1820 shift_size = i - largest_possible_size;
1826 //this level failed;
1829 //we are at the beginning of a non permutation, non asterisk interval
1831 //the distance to the next permutation or the end of templates
1832 // so the longest possible match
1833 unsigned int distance;
1835 if (permutation_index < nof_permutations)
1837 distance = template_ptr->get_permutation_start(permutation_index)
1838 - template_start_index;
1840 distance = template_size;
1843 //if there are no more values, but we still have templates
1844 // and the template is not an asterisk or a permutation start
1848 //we try to match as many values as possible
1849 //an asterisk is handled like a 0 length permutation
1853 good = match_function(value_ptr, value_start_index + i,
1854 template_ptr, template_start_index + i);
1856 //bad stop: something can't be matched
1857 //half bad half good stop: the end of values is reached
1858 //good stop: matching on the full distance or till an asterisk
1859 }while(good && i < value_size && i < distance &&
1860 !match_function(value_ptr, -1, template_ptr,
1861 template_start_index + i));
1863 //if we matched on the full distance or till an asterisk
1864 if(good && (i == distance ||
1865 match_function(value_ptr, -1, template_ptr,
1866 template_start_index + i)))
1868 //reached the end of the templates
1869 if(i == template_size)
1873 //the next level would return FAILURE so we don't step it
1876 //i == value_size, so we matched everything
1880 //we reached the next asterisk or permutation,
1881 // so step to the next level
1882 return recursive_permutation_match(value_ptr,value_start_index + i,
1885 template_start_index + i,
1888 match_function, shift_size);
1891 //something bad happened, so we have to check how bad the situation is
1892 if( i == value_size)
1894 //the aren't values left, meaning that the match is not possible
1897 //we couldn't match, but there is still a chance of matching
1899 //try to find a matching value for the last checked (and failed)
1901 // smaller jumps would fail so we skip them
1905 good = match_function(value_ptr,
1906 value_start_index + i + shift_size,
1907 template_ptr, template_start_index + i);
1909 }while(!good && i + shift_size < value_size);
1916 // the template can not be matched later
1924 template <typename T_value_type, typename T_template_type,
1925 unsigned int array_size, int index_offset>
1926 boolean match_permutation_array(const Base_Type *value_ptr,
1928 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
1930 match_function_t match_function)
1932 if (value_ptr == NULL || value_size < 0 ||
1933 template_ptr == NULL || template_size < 0 ||
1934 template_ptr->get_selection() != SPECIFIC_VALUE)
1935 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
1937 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1938 // use the simplified algorithm if the template does not contain permutation
1939 if (nof_permutations == 0)
1940 return match_array(value_ptr, value_size,
1941 template_ptr, template_size, match_function);
1942 // use 'set of' matching if all template elements are grouped into one
1944 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
1945 template_ptr->get_permutation_end(0) ==
1946 (unsigned int)(template_size - 1))
1947 return match_set_of(value_ptr, value_size, template_ptr, template_size,
1950 unsigned int shift_size = 0;
1951 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
1952 0, template_size, 0, match_function, shift_size) == SUCCESS;