Sync with 5.4.2
[deliverable/titan.core.git] / core / Array.hh
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #ifndef ARRAY_HH
9 #define ARRAY_HH
10
11 #include "Types.h"
12 #include "Param_Types.hh"
13 #include "Error.hh"
14 #include "Logger.hh"
15 #include "Basetype.hh"
16 #include "Template.hh"
17 #include "Optional.hh"
18 #include "Parameters.h"
19 #include "Integer.hh"
20 #include "Struct_of.hh"
21 #include "memory.h"
22
23 class INTEGER;
24
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);
29
30 /** @brief Runtime implementation of timer arrays.
31 *
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
36 *
37 * */
38 template <typename T_type, unsigned int array_size, int index_offset>
39 class TIMER_ARRAY
40 #ifdef TITAN_RUNTIME_2
41 : public RefdIndexInterface
42 #endif
43 {
44 T_type array_elements[array_size];
45 char * names[array_size];
46
47 /// Copy constructor disallowed.
48 TIMER_ARRAY(const TIMER_ARRAY& other_value);
49 /// Assignment disallowed.
50 TIMER_ARRAY& operator=(const TIMER_ARRAY& other_value);
51
52 public:
53 TIMER_ARRAY() { }
54
55 ~TIMER_ARRAY() {
56 for (size_t i = 0; i < array_size; ++i) {
57 Free(names[i]);
58 }
59 }
60
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)]; }
65
66 int n_elem() const { return array_size; }
67 int size_of() const { return array_size; }
68 int lengthof() const { return array_size; }
69
70 T_type& array_element(unsigned int index_value)
71 { return array_elements[index_value]; }
72
73 void set_name(const char * name_string)
74 {
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]);
80 }
81 }
82
83 void log() const
84 {
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();
89 }
90 TTCN_Logger::log_event_str(" }");
91 }
92 };
93
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);
98
99 template <typename T_type, unsigned int array_size, int index_offset>
100 class PORT_ARRAY
101 #ifdef TITAN_RUNTIME_2
102 : public RefdIndexInterface
103 #endif
104 {
105 T_type array_elements[array_size];
106 char * names[array_size];
107
108 /// Copy constructor disallowed.
109 PORT_ARRAY(const PORT_ARRAY& other_value);
110 /// Assignment disallowed.
111 PORT_ARRAY& operator=(const PORT_ARRAY& other_value);
112
113 public:
114 PORT_ARRAY() { }
115
116 ~PORT_ARRAY() {
117 for (size_t i = 0; i < array_size; ++i) {
118 Free(names[i]);
119 }
120 }
121
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)]; }
126
127 int n_elem() const { return array_size; }
128 int size_of() const { return array_size; }
129 int lengthof()const { return array_size; }
130
131 void set_name(const char * name_string)
132 {
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]);
137 }
138 }
139
140 void activate_port()
141 {
142 for (unsigned int v_index = 0; v_index < array_size; v_index++) {
143 array_elements[v_index].activate_port();
144 }
145 }
146
147 void log() const
148 {
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();
153 }
154 TTCN_Logger::log_event_str(" }");
155 }
156 };
157
158 ////////////////////////////////////////////////////////////////////////////////
159
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);
164
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
169 #endif
170 {
171 T_type array_elements[array_size];
172 public:
173 // This class use the compiler-generated copy constructor and
174 // copy assignment.
175
176 boolean operator==(const VALUE_ARRAY& other_value) const;
177 inline boolean operator!=(const VALUE_ARRAY& other_value) const
178 { return !(*this == other_value); }
179
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)];
189 }
190
191 // rotation
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;
196
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]; }
201
202 void set_implicit_omit();
203
204 boolean is_bound() const;
205 boolean is_value() const;
206 void clean_up();
207 void log() const;
208
209 inline int n_elem() const { return array_size; }
210 inline int size_of() const { return array_size; }
211 int lengthof() const;
212
213 void set_param(Module_Param& param);
214 Module_Param* get_param(Module_Param_Name& param_name) const;
215
216 #ifdef TITAN_RUNTIME_2
217 boolean is_equal(const Base_Type* other_value) const { return *this == *(static_cast<const VALUE_ARRAY*>(other_value)); }
218 void set_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY*>(other_value)); }
219 Base_Type* clone() const { return new VALUE_ARRAY(*this); }
220 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: VALUE_ARRAY<>::get_descriptor() called."); }
221 #else
222 inline boolean is_present() const { return is_bound(); }
223 #endif
224
225 void encode_text(Text_Buf& text_buf) const;
226 void decode_text(Text_Buf& text_buf);
227
228 void encode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...) const;
229 void decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, TTCN_EncDec::coding_t, ...);
230
231 virtual const TTCN_Typedescriptor_t* get_elem_descr() const
232 { TTCN_error("Internal error: VALUE_ARRAY<>::get_elem_descr() called."); }
233
234 virtual ~VALUE_ARRAY() { } // just to avoid warnings
235
236 /** Encodes accordingly to the JSON encoding rules.
237 * Returns the length of the encoded data. */
238 int JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;
239
240 /** Decodes accordingly to the JSON encoding rules.
241 * Returns the length of the decoded data. */
242 int JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer&, boolean);
243 };
244
245 template <typename T_type, unsigned int array_size, int index_offset>
246 boolean VALUE_ARRAY<T_type,array_size,index_offset>::operator==
247 (const VALUE_ARRAY& other_value) const
248 {
249 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
250 if (array_elements[elem_count] != other_value.array_elements[elem_count])
251 return FALSE;
252 return TRUE;
253 }
254
255 template <typename T_type, unsigned int array_size, int index_offset>
256 VALUE_ARRAY<T_type,array_size,index_offset>
257 VALUE_ARRAY<T_type,array_size,index_offset>::
258 operator<<=(int rotate_count) const {
259 return *this >>= (-rotate_count);
260 }
261
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<<=(const INTEGER& rotate_count) const {
266 rotate_count.must_bound("Unbound integer operand of rotate left "
267 "operator.");
268 return *this >>= (int)(-rotate_count);
269 }
270
271 template <typename T_type, unsigned int array_size, int index_offset>
272 VALUE_ARRAY<T_type,array_size,index_offset>
273 VALUE_ARRAY<T_type,array_size,index_offset>::
274 operator>>=(int rotate_count) const {
275 unsigned int rc;
276 if (rotate_count>=0) rc = (unsigned int)rotate_count % array_size;
277 else rc = array_size - ((unsigned int)(-rotate_count) % array_size);
278 if (rc == 0) return *this;
279 VALUE_ARRAY<T_type,array_size,index_offset> ret_val;
280 for (unsigned int i=0; i<array_size; i++) {
281 ret_val.array_elements[(i+rc)%array_size] = array_elements[i];
282 }
283 return ret_val;
284 }
285
286 template <typename T_type, unsigned int array_size, int index_offset>
287 VALUE_ARRAY<T_type,array_size,index_offset>
288 VALUE_ARRAY<T_type,array_size,index_offset>::
289 operator>>=(const INTEGER& rotate_count) const {
290 rotate_count.must_bound("Unbound integer operand of rotate right "
291 "operator.");
292 return *this >>= (int)rotate_count;
293 }
294
295 template <typename T_type, unsigned int array_size, int index_offset>
296 void VALUE_ARRAY<T_type,array_size,index_offset>::set_implicit_omit()
297 {
298 for (unsigned int i = 0; i < array_size; ++i) {
299 if (array_elements[i].is_bound())
300 array_elements[i].set_implicit_omit();
301 }
302 }
303
304 template <typename T_type, unsigned int array_size, int index_offset>
305 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_bound() const
306 {
307 for (unsigned int i = 0; i < array_size; ++i) {
308 if (!array_elements[i].is_bound()) {
309 return false;
310 }
311 }
312 return true;
313 }
314
315 template <typename T_type, unsigned int array_size, int index_offset>
316 boolean VALUE_ARRAY<T_type,array_size,index_offset>::is_value() const
317 {
318 for (unsigned int i = 0; i < array_size; ++i) {
319 if (!array_elements[i].is_value()) {
320 return false;
321 }
322 }
323 return true;
324 }
325
326 template <typename T_type, unsigned int array_size, int index_offset>
327 void VALUE_ARRAY<T_type,array_size,index_offset>::clean_up()
328 {
329 for (unsigned int i = 0; i < array_size; ++i) {
330 array_elements[i].clean_up();
331 }
332 }
333
334 template <typename T_type, unsigned int array_size, int index_offset>
335 void VALUE_ARRAY<T_type,array_size,index_offset>::log() const
336 {
337 TTCN_Logger::log_event_str("{ ");
338 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
339 {
340 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
341 array_elements[elem_count].log();
342 }
343 TTCN_Logger::log_event_str(" }");
344 }
345
346 template <typename T_type, unsigned int array_size, int index_offset>
347 int VALUE_ARRAY<T_type,array_size,index_offset>::lengthof() const
348 {
349
350 for (unsigned int my_length=array_size; my_length>0; my_length--)
351 {
352 if (array_elements[my_length-1].is_bound()) return my_length;
353 }
354 return 0;
355 }
356
357 template <typename T_type, unsigned int array_size, int index_offset>
358 void VALUE_ARRAY<T_type,array_size,index_offset>::set_param(
359 Module_Param& param)
360 {
361 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
362 param.get_id()->next_name()) {
363 // Haven't reached the end of the module parameter name
364 // => the name refers to one of the elements, not to the whole array
365 char* param_field = param.get_id()->get_current_name();
366 if (param_field[0] < '0' || param_field[0] > '9') {
367 param.error("Unexpected record field name in module parameter, expected a valid"
368 " array index");
369 }
370 unsigned int param_index = -1;
371 sscanf(param_field, "%u", &param_index);
372 if (param_index >= array_size) {
373 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
374 }
375 array_elements[param_index].set_param(param);
376 return;
377 }
378
379 param.basic_check(Module_Param::BC_VALUE, "array value");
380 Module_Param_Ptr mp = &param;
381 if (param.get_type() == Module_Param::MP_Reference) {
382 mp = param.get_referenced_param();
383 }
384 switch (mp->get_type()) {
385 case Module_Param::MP_Value_List:
386 if (mp->get_size()!=array_size) {
387 param.error("The array value has incorrect number of elements: %lu was expected instead of %lu.", (unsigned long)mp->get_size(), (unsigned long)array_size);
388 }
389 for (size_t i=0; i<mp->get_size(); ++i) {
390 Module_Param* const curr = mp->get_elem(i);
391 if (curr->get_type()!=Module_Param::MP_NotUsed) {
392 array_elements[i].set_param(*curr);
393 }
394 }
395 break;
396 case Module_Param::MP_Indexed_List:
397 for (size_t i=0; i<mp->get_size(); ++i) {
398 Module_Param* const curr = mp->get_elem(i);
399 array_elements[curr->get_id()->get_index()].set_param(*curr);
400 }
401 break;
402 default:
403 param.type_error("array value");
404 }
405 }
406
407 template <typename T_type, unsigned int array_size, int index_offset>
408 Module_Param* VALUE_ARRAY<T_type,array_size,index_offset>::get_param
409 (Module_Param_Name& param_name) const
410 {
411 if (!is_bound()) {
412 return new Module_Param_Unbound();
413 }
414 if (param_name.next_name()) {
415 // Haven't reached the end of the module parameter name
416 // => the name refers to one of the elements, not to the whole array
417 char* param_field = param_name.get_current_name();
418 if (param_field[0] < '0' || param_field[0] > '9') {
419 TTCN_error("Unexpected record field name in module parameter reference, "
420 "expected a valid array index");
421 }
422 unsigned int param_index = -1;
423 sscanf(param_field, "%u", &param_index);
424 if (param_index >= array_size) {
425 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
426 }
427 return array_elements[param_index].get_param(param_name);
428 }
429 Vector<Module_Param*> values;
430 for (int i = 0; i < array_size; ++i) {
431 values.push_back(array_elements[i].get_param(param_name));
432 }
433 Module_Param_Value_List* mp = new Module_Param_Value_List();
434 mp->add_list_with_implicit_ids(&values);
435 values.clear();
436 return mp;
437 }
438
439 template <typename T_type, unsigned int array_size, int index_offset>
440 void VALUE_ARRAY<T_type,array_size,index_offset>::encode_text
441 (Text_Buf& text_buf) const
442 {
443 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
444 array_elements[elem_count].encode_text(text_buf);
445 }
446
447 template <typename T_type, unsigned int array_size, int index_offset>
448 void VALUE_ARRAY<T_type,array_size,index_offset>::decode_text
449 (Text_Buf& text_buf)
450 {
451 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
452 array_elements[elem_count].decode_text(text_buf);
453 }
454
455 template <typename T_type, unsigned int array_size, int index_offset>
456 void VALUE_ARRAY<T_type,array_size,index_offset>::encode(
457 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...) const
458 {
459 va_list pvar;
460 va_start(pvar, p_coding);
461 switch(p_coding) {
462 case TTCN_EncDec::CT_JSON: {
463 TTCN_EncDec_ErrorContext ec("While JSON-encoding type '%s': ", p_td.name);
464 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
465 ("No JSON descriptor available for type '%s'.", p_td.name);
466 JSON_Tokenizer tok(va_arg(pvar, int) != 0);
467 JSON_encode(p_td, tok);
468 p_buf.put_s(tok.get_buffer_length(), (const unsigned char*)tok.get_buffer());
469 break;}
470 default:
471 TTCN_error("Unknown coding method requested to encode type '%s'", p_td.name);
472 }
473 va_end(pvar);
474 }
475
476 template <typename T_type, unsigned int array_size, int index_offset>
477 void VALUE_ARRAY<T_type,array_size,index_offset>::decode(
478 const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, TTCN_EncDec::coding_t p_coding, ...)
479 {
480 switch(p_coding) {
481 case TTCN_EncDec::CT_JSON: {
482 TTCN_EncDec_ErrorContext ec("While JSON-decoding type '%s': ", p_td.name);
483 if(!p_td.json) TTCN_EncDec_ErrorContext::error_internal
484 ("No JSON descriptor available for type '%s'.", p_td.name);
485 JSON_Tokenizer tok((const char*)p_buf.get_data(), p_buf.get_len());
486 if(JSON_decode(p_td, tok, false)<0)
487 ec.error(TTCN_EncDec::ET_INCOMPL_MSG,"Can not decode type '%s', "
488 "because invalid or incomplete message was received", p_td.name);
489 p_buf.set_pos(tok.get_buf_pos());
490 break;}
491 default:
492 TTCN_error("Unknown coding method requested to decode type '%s'", p_td.name);
493 }
494 }
495
496 template <typename T_type, unsigned int array_size, int index_offset>
497 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_encode(
498 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
499 {
500 if (!is_bound()) {
501 TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
502 "Encoding an unbound array value.");
503 return -1;
504 }
505
506 int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
507
508 for(unsigned int i = 0; i < array_size; ++i) {
509 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
510 if (0 > ret_val) break;
511 enc_len += ret_val;
512 }
513
514 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
515 return enc_len;
516 }
517
518 template <typename T_type, unsigned int array_size, int index_offset>
519 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
520 const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)
521 {
522 json_token_t token = JSON_TOKEN_NONE;
523 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
524 if (JSON_TOKEN_ERROR == token) {
525 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
526 return JSON_ERROR_FATAL;
527 }
528 else if (JSON_TOKEN_ARRAY_START != token) {
529 return JSON_ERROR_INVALID_TOKEN;
530 }
531
532 for(unsigned int i = 0; i < array_size; ++i) {
533 int ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
534 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
535 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
536 array_size - i, (array_size - i > 1) ? "s" : "");
537 return JSON_ERROR_FATAL;
538 }
539 else if (JSON_ERROR_FATAL == ret_val) {
540 if (p_silent) {
541 clean_up();
542 }
543 return JSON_ERROR_FATAL;
544 }
545 dec_len += ret_val;
546 }
547
548 dec_len += p_tok.get_next_token(&token, NULL, NULL);
549 if (JSON_TOKEN_ARRAY_END != token) {
550 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
551 if (p_silent) {
552 clean_up();
553 }
554 return JSON_ERROR_FATAL;
555 }
556
557 return dec_len;
558 }
559
560
561 template <typename T_value_type, typename T_template_type,
562 unsigned int array_size, int index_offset>
563 class TEMPLATE_ARRAY : public Restricted_Length_Template
564 {
565 private:
566 union {
567 struct {
568 int n_elements;
569 T_template_type **value_elements;
570 } single_value;
571 struct {
572 unsigned int n_values;
573 TEMPLATE_ARRAY *list_value;
574 } value_list;
575 };
576
577 struct Pair_of_elements;
578 Pair_of_elements *permutation_intervals;
579 unsigned int number_of_permutations;
580
581 void clean_up_intervals();
582 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
583 other_value);
584 void copy_template(const TEMPLATE_ARRAY& other_value);
585 void set_selection(template_sel new_selection);
586 void set_selection(const TEMPLATE_ARRAY& other_value);
587 void encode_text_permutation(Text_Buf& text_buf) const;
588 void decode_text_permutation(Text_Buf& text_buf);
589
590 public:
591 TEMPLATE_ARRAY()
592 {
593 number_of_permutations = 0;
594 permutation_intervals = NULL;
595 }
596 TEMPLATE_ARRAY(template_sel other_value)
597 : Restricted_Length_Template(other_value)
598 {
599 check_single_selection(other_value);
600 number_of_permutations = 0;
601 permutation_intervals = NULL;
602 }
603 TEMPLATE_ARRAY(null_type other_value);
604 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
605 other_value)
606 {
607 number_of_permutations = 0;
608 permutation_intervals = NULL;
609 copy_value(other_value);
610 }
611 TEMPLATE_ARRAY(const
612 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
613 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
614 : Restricted_Length_Template()
615 {
616 number_of_permutations = 0;
617 permutation_intervals = NULL;
618 copy_template(other_value);
619 }
620
621 ~TEMPLATE_ARRAY()
622 {
623 clean_up_intervals();
624 clean_up();
625 }
626 void clean_up();
627
628 TEMPLATE_ARRAY& operator=(template_sel other_value);
629 TEMPLATE_ARRAY& operator=(null_type other_value);
630 TEMPLATE_ARRAY& operator=(const
631 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
632 TEMPLATE_ARRAY& operator=(const
633 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
634 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
635
636 T_template_type& operator[](int index_value);
637 T_template_type& operator[](const INTEGER& index_value);
638 const T_template_type& operator[](int index_value) const;
639 const T_template_type& operator[](const INTEGER& index_value) const;
640
641 void set_size(int new_size);
642
643 int n_elem() const;
644 int size_of(boolean is_size) const;
645 inline int size_of() const { return size_of(TRUE); }
646 inline int lengthof() const { return size_of(FALSE); }
647
648 void add_permutation(unsigned int start_index, unsigned int end_index);
649
650 /** Removes all permutations set on this template, used when template variables
651 * are given new values. */
652 void remove_all_permutations() { clean_up_intervals(); }
653
654 unsigned int get_number_of_permutations() const;
655 unsigned int get_permutation_start(unsigned int index_value) const;
656 unsigned int get_permutation_end(unsigned int index_value) const;
657 unsigned int get_permutation_size(unsigned int index_value) const;
658 boolean permutation_starts_at(unsigned int index_value) const;
659 boolean permutation_ends_at(unsigned int index_value) const;
660
661 private:
662 static boolean match_function_specific(
663 const Base_Type *value_ptr, int value_index,
664 const Restricted_Length_Template *template_ptr, int template_index,
665 boolean legacy);
666 public:
667 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
668 other_value, boolean legacy = FALSE) const;
669
670 boolean is_value() const;
671 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
672
673 void set_type(template_sel template_type, unsigned int list_length);
674 TEMPLATE_ARRAY& list_item(unsigned int list_index);
675
676 void log() const;
677 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
678 match_value, boolean legacy = FALSE) const;
679
680 void set_param(Module_Param& param);
681 Module_Param* get_param(Module_Param_Name& param_name) const;
682
683 void encode_text(Text_Buf& text_buf) const;
684 void decode_text(Text_Buf& text_buf);
685
686 boolean is_present(boolean legacy = FALSE) const;
687 boolean match_omit(boolean legacy = FALSE) const;
688
689 #ifdef TITAN_RUNTIME_2
690 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
691 void set_value(template_sel other_value) { *this = other_value; }
692 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
693 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
694 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
695 boolean matchv(const Base_Type* other_value, boolean legacy) const { return match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)), legacy); }
696 void log_matchv(const Base_Type* match_value, boolean legacy) const { log_match(*(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(match_value)), legacy); }
697 #else
698 void check_restriction(template_res t_res, const char* t_name=NULL, boolean legacy = FALSE) const;
699 #endif
700 };
701
702 template <typename T_value_type, typename T_template_type,
703 unsigned int array_size, int index_offset>
704 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
705 Pair_of_elements{
706 unsigned int start_index, end_index; //beginning and ending index
707 };
708
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 clean_up()
713 {
714 switch (template_selection)
715 {
716 case SPECIFIC_VALUE:
717 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
718 delete single_value.value_elements[elem_count];
719 free_pointers((void**)single_value.value_elements);
720 break;
721 case VALUE_LIST:
722 case COMPLEMENTED_LIST:
723 delete [] value_list.list_value;
724 break;
725 default:
726 break;
727 }
728 template_selection = UNINITIALIZED_TEMPLATE;
729 }
730
731 template <typename T_value_type, typename T_template_type,
732 unsigned int array_size, int index_offset>
733 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
734 clean_up_intervals()
735 {
736 number_of_permutations = 0;
737 Free(permutation_intervals);
738 permutation_intervals = NULL;
739 }
740
741 template <typename T_value_type, typename T_template_type,
742 unsigned int array_size, int index_offset>
743 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
744 set_selection(template_sel other_value)
745 {
746 Restricted_Length_Template::set_selection(other_value);
747 clean_up_intervals();
748 }
749
750 template <typename T_value_type, typename T_template_type,
751 unsigned int array_size, int index_offset>
752 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
753 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
754 {
755 Restricted_Length_Template::set_selection(other_value);
756 clean_up_intervals();
757 if(other_value.template_selection == SPECIFIC_VALUE)
758 {
759 number_of_permutations = other_value.number_of_permutations;
760 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
761 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
762 }
763 }
764
765 template <typename T_value_type, typename T_template_type,
766 unsigned int array_size, int index_offset>
767 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
768 encode_text_permutation(Text_Buf& text_buf) const
769 {
770 encode_text_restricted(text_buf);
771 text_buf.push_int(number_of_permutations);
772
773 for(unsigned int i = 0; i < number_of_permutations; i++)
774 {
775 text_buf.push_int(permutation_intervals[i].start_index);
776 text_buf.push_int(permutation_intervals[i].end_index);
777 }
778 }
779
780 template <typename T_value_type, typename T_template_type,
781 unsigned int array_size, int index_offset>
782 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
783 decode_text_permutation(Text_Buf& text_buf)
784 {
785 decode_text_restricted(text_buf);
786
787 number_of_permutations = text_buf.pull_int().get_val();
788 permutation_intervals = (Pair_of_elements *)Malloc
789 (number_of_permutations * sizeof(Pair_of_elements));
790
791 for (unsigned int i = 0; i < number_of_permutations; i++)
792 {
793 permutation_intervals[i].start_index =
794 text_buf.pull_int().get_val();
795 permutation_intervals[i].end_index =
796 text_buf.pull_int().get_val();
797 }
798 }
799
800 template <typename T_value_type, typename T_template_type,
801 unsigned int array_size, int index_offset>
802 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
803 add_permutation(unsigned int start_index, unsigned int end_index)
804 {
805 if(start_index > end_index)
806 TTCN_error("wrong permutation interval settings start (%d)"
807 "can not be greater than end (%d)",start_index, end_index);
808
809 if(number_of_permutations > 0 &&
810 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
811 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
812
813 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
814 permutation_intervals[number_of_permutations].start_index = start_index;
815 permutation_intervals[number_of_permutations].end_index = end_index;
816 number_of_permutations++;
817 }
818
819 template <typename T_value_type, typename T_template_type,
820 unsigned int array_size, int index_offset>
821 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
822 get_number_of_permutations(void) const
823 {
824 return number_of_permutations;
825 }
826
827 template <typename T_value_type, typename T_template_type,
828 unsigned int array_size, int index_offset>
829 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
830 get_permutation_start(unsigned int index_value) const
831 {
832 if(index_value >= number_of_permutations)
833 TTCN_error("Index overflow (%d)", index_value);
834
835 return permutation_intervals[index_value].start_index;
836 }
837
838 template <typename T_value_type, typename T_template_type,
839 unsigned int array_size, int index_offset>
840 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
841 get_permutation_end(unsigned int index_value) const
842 {
843 if(index_value >= number_of_permutations)
844 TTCN_error("Index overflow (%d)", index_value);
845
846 return permutation_intervals[index_value].end_index;
847 }
848
849 template <typename T_value_type, typename T_template_type,
850 unsigned int array_size, int index_offset>
851 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
852 get_permutation_size(unsigned int index_value) const
853 {
854 if(index_value >= number_of_permutations)
855 TTCN_error("Index overflow (%d)", index_value);
856
857 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
858 }
859
860 template <typename T_value_type, typename T_template_type,
861 unsigned int array_size, int index_offset>
862 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
863 permutation_starts_at(unsigned int index_value) const
864 {
865 for(unsigned int i = 0; i < number_of_permutations; i++)
866 {
867 if(permutation_intervals[i].start_index == index_value)
868 return TRUE;
869 }
870
871 return FALSE;
872 }
873
874 template <typename T_value_type, typename T_template_type,
875 unsigned int array_size, int index_offset>
876 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
877 permutation_ends_at(unsigned int index_value) const
878 {
879 for(unsigned int i = 0; i < number_of_permutations; i++)
880 {
881 if(permutation_intervals[i].end_index == index_value)
882 return TRUE;
883 }
884
885 return FALSE;
886 }
887
888 template <typename T_value_type, typename T_template_type,
889 unsigned int array_size, int index_offset>
890 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
891 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
892 other_value)
893 {
894 single_value.n_elements = array_size;
895 single_value.value_elements =
896 (T_template_type**)allocate_pointers(array_size);
897 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
898 single_value.value_elements[elem_count] =
899 new T_template_type(other_value.array_element(elem_count));
900 set_selection(SPECIFIC_VALUE);
901 }
902
903 template <typename T_value_type, typename T_template_type,
904 unsigned int array_size, int index_offset>
905 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
906 copy_template(const TEMPLATE_ARRAY& other_value)
907 {
908 switch (other_value.template_selection)
909 {
910 case SPECIFIC_VALUE:
911 single_value.n_elements = other_value.single_value.n_elements;
912 single_value.value_elements =
913 (T_template_type**)allocate_pointers(single_value.n_elements);
914 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
915 single_value.value_elements[elem_count] = new
916 T_template_type(*other_value.single_value.value_elements[elem_count]);
917 break;
918 case OMIT_VALUE:
919 case ANY_VALUE:
920 case ANY_OR_OMIT:
921 break;
922 case VALUE_LIST:
923 case COMPLEMENTED_LIST:
924 value_list.n_values = other_value.value_list.n_values;
925 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
926 for (unsigned int list_count = 0; list_count < value_list.n_values;
927 list_count++)
928 value_list.list_value[list_count].copy_template(
929 other_value.value_list.list_value[list_count]);
930 break;
931 default:
932 TTCN_error("Copying an uninitialized/unsupported array template.");
933 }
934 set_selection(other_value);
935 }
936
937 template <typename T_value_type, typename T_template_type,
938 unsigned int array_size, int index_offset>
939 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
940 TEMPLATE_ARRAY(null_type)
941 : Restricted_Length_Template(SPECIFIC_VALUE)
942 {
943 single_value.n_elements = 0;
944 single_value.value_elements = NULL;
945 number_of_permutations = 0;
946 permutation_intervals = NULL;
947 }
948
949 template <typename T_value_type, typename T_template_type,
950 unsigned int array_size, int index_offset>
951 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
952 TEMPLATE_ARRAY(const
953 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
954 {
955 number_of_permutations = 0;
956 permutation_intervals = NULL;
957 switch (other_value.get_selection()) {
958 case OPTIONAL_PRESENT:
959 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
960 other_value);
961 break;
962 case OPTIONAL_OMIT:
963 set_selection(OMIT_VALUE);
964 break;
965 default:
966 TTCN_error("Creating an array template from an unbound optional field.");
967 }
968 }
969
970 template <typename T_value_type, typename T_template_type,
971 unsigned int array_size, int index_offset>
972 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
973 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
974 operator=(template_sel other_value)
975 {
976 check_single_selection(other_value);
977 clean_up();
978 set_selection(other_value);
979 return *this;
980 }
981
982 template <typename T_value_type, typename T_template_type,
983 unsigned int array_size, int index_offset>
984 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
985 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
986 operator=(null_type)
987 {
988 clean_up();
989 set_selection(SPECIFIC_VALUE);
990 single_value.n_elements = 0;
991 single_value.value_elements = NULL;
992 return *this;
993 }
994
995 template <typename T_value_type, typename T_template_type,
996 unsigned int array_size, int index_offset>
997 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
998 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
999 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
1000 {
1001 clean_up();
1002 copy_value(other_value);
1003 return *this;
1004 }
1005
1006 template <typename T_value_type, typename T_template_type,
1007 unsigned int array_size, int index_offset>
1008 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1009 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1010 operator=(const
1011 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1012 {
1013 clean_up();
1014 switch (other_value.get_selection()) {
1015 case OPTIONAL_PRESENT:
1016 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1017 other_value);
1018 break;
1019 case OPTIONAL_OMIT:
1020 set_selection(OMIT_VALUE);
1021 break;
1022 default:
1023 TTCN_error("Assignment of an unbound optional field to an array template.");
1024 }
1025 return *this;
1026 }
1027
1028 template <typename T_value_type, typename T_template_type,
1029 unsigned int array_size, int index_offset>
1030 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1031 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1032 operator=(const
1033 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1034 other_value)
1035 {
1036 if (&other_value != this)
1037 {
1038 clean_up();
1039 copy_template(other_value);
1040 }
1041 return *this;
1042 }
1043
1044 template <typename T_value_type, typename T_template_type,
1045 unsigned int array_size, int index_offset>
1046 T_template_type&
1047 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1048 (int index_value)
1049 {
1050 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1051 TTCN_error(
1052 "Accessing an element of an array template using invalid index: %d. "
1053 "Index range is [%d,%d].",
1054 index_value, index_offset, index_offset+(int)array_size);
1055 // transform index value according to given offset
1056 index_value -= index_offset;
1057 // the template of an array is not restricted to array_size, allow any length
1058 // in case of * or ? expand to full size to avoid uninitialized values
1059 switch (template_selection)
1060 {
1061 case SPECIFIC_VALUE:
1062 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1063 break;
1064 case ANY_VALUE:
1065 case ANY_OR_OMIT:
1066 set_size(array_size);
1067 break;
1068 default:
1069 set_size(index_value + 1);
1070 }
1071 return *single_value.value_elements[index_value];
1072 }
1073
1074 template <typename T_value_type, typename T_template_type,
1075 unsigned int array_size, int index_offset>
1076 T_template_type&
1077 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1078 (const INTEGER& index_value)
1079 {
1080 index_value.must_bound(
1081 "Using an unbound integer value for indexing an array template.");
1082 return (*this)[(int)index_value];
1083 }
1084
1085 template <typename T_value_type, typename T_template_type,
1086 unsigned int array_size, int index_offset>
1087 const T_template_type&
1088 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1089 (int index_value) const
1090 {
1091 if (index_value < index_offset)
1092 TTCN_error(
1093 "Accessing an element of an array template using invalid index: %d. "
1094 "Index range starts at %d.",
1095 index_value, index_offset);
1096 // transform index value according to given offset
1097 index_value -= index_offset;
1098 // const is specific template
1099 if (template_selection != SPECIFIC_VALUE)
1100 TTCN_error("Accessing an element of a non-specific array template.");
1101 if (index_value >= single_value.n_elements)
1102 TTCN_error("Index overflow in an array template: "
1103 "The index is %d (starting at %d),"
1104 " but the template has only %d elements.",
1105 index_value+index_offset, index_offset, single_value.n_elements);
1106 return *single_value.value_elements[index_value];
1107 }
1108
1109 template <typename T_value_type, typename T_template_type,
1110 unsigned int array_size, int index_offset>
1111 const T_template_type&
1112 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1113 (const INTEGER& index_value) const
1114 {
1115 index_value.must_bound(
1116 "Using an unbound integer value for indexing an array template.");
1117 return (*this)[(int)index_value];
1118 }
1119
1120 template <typename T_value_type, typename T_template_type,
1121 unsigned int array_size, int index_offset>
1122 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1123 set_size(int new_size)
1124 {
1125 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1126 "for an array template.");
1127 template_sel old_selection = template_selection;
1128 if (old_selection != SPECIFIC_VALUE)
1129 {
1130 clean_up();
1131 set_selection(SPECIFIC_VALUE);
1132 single_value.n_elements = 0;
1133 single_value.value_elements = NULL;
1134 }
1135 if (new_size > single_value.n_elements)
1136 {
1137 single_value.value_elements =
1138 (T_template_type**)reallocate_pointers(
1139 (void**)single_value.value_elements, single_value.n_elements, new_size);
1140 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1141 {
1142 for (int elem_count = single_value.n_elements;
1143 elem_count < new_size; elem_count++)
1144 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1145 }
1146 else
1147 {
1148 for (int elem_count = single_value.n_elements;
1149 elem_count < new_size; elem_count++)
1150 single_value.value_elements[elem_count] = new T_template_type;
1151 }
1152 single_value.n_elements = new_size;
1153 }
1154 else if (new_size < single_value.n_elements)
1155 {
1156 for (int elem_count = new_size; elem_count < single_value.n_elements;
1157 elem_count++)
1158 delete single_value.value_elements[elem_count];
1159 single_value.value_elements =
1160 (T_template_type**)reallocate_pointers(
1161 (void**)single_value.value_elements, single_value.n_elements, new_size);
1162 single_value.n_elements = new_size;
1163 }
1164 }
1165
1166 template <typename T_value_type, typename T_template_type,
1167 unsigned int array_size, int index_offset>
1168 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1169 n_elem() const
1170 {
1171 switch (template_selection) {
1172 case SPECIFIC_VALUE:
1173 return single_value.n_elements;
1174 case VALUE_LIST:
1175 return value_list.n_values;
1176 default:
1177 TTCN_error("Performing n_elem");
1178 }
1179 }
1180
1181 template <typename T_value_type, typename T_template_type,
1182 unsigned int array_size, int index_offset>
1183 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1184 size_of(boolean is_size) const
1185 {
1186 const char* op_name = is_size ? "size" : "length";
1187 int min_size;
1188 boolean has_any_or_none;
1189 if (is_ifpresent)
1190 TTCN_error("Performing %sof() operation on an array template "
1191 "which has an ifpresent attribute.", op_name);
1192 switch (template_selection)
1193 {
1194 case SPECIFIC_VALUE: {
1195 min_size = 0;
1196 has_any_or_none = FALSE;
1197 int elem_count = single_value.n_elements;
1198 if (!is_size) { // lengthof()
1199 while (elem_count>0 &&
1200 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1201 }
1202 for (int i=0; i<elem_count; i++)
1203 {
1204 switch (single_value.value_elements[i]->get_selection())
1205 {
1206 case OMIT_VALUE:
1207 TTCN_error("Performing %sof() operation on an array template "
1208 "containing omit element.", op_name);
1209 case ANY_OR_OMIT:
1210 has_any_or_none = TRUE;
1211 break;
1212 default:
1213 min_size++;
1214 break;
1215 }
1216 }
1217 } break;
1218 case OMIT_VALUE:
1219 TTCN_error("Performing %sof() operation on an array template "
1220 "containing omit value.", op_name);
1221 case ANY_VALUE:
1222 case ANY_OR_OMIT:
1223 min_size = 0;
1224 has_any_or_none = TRUE; // max. size is infinity
1225 break;
1226 case VALUE_LIST: {
1227 // error if any element does not have size or the sizes differ
1228 if (value_list.n_values<1)
1229 TTCN_error("Performing %sof() operation on an array template "
1230 "containing an empty list.", op_name);
1231 int item_size = value_list.list_value[0].size_of(is_size);
1232 for (unsigned int i = 1; i < value_list.n_values; i++) {
1233 if (value_list.list_value[i].size_of(is_size)!=item_size)
1234 TTCN_error("Performing %sof() operation on an array template "
1235 "containing a value list with different sizes.", op_name);
1236 }
1237 min_size = item_size;
1238 has_any_or_none = FALSE;
1239 } break;
1240 case COMPLEMENTED_LIST:
1241 TTCN_error("Performing %sof() operation on an array template "
1242 "containing complemented list.", op_name);
1243 default:
1244 TTCN_error("Performing %sof() operation on an "
1245 "uninitialized/unsupported array template.", op_name);
1246 }
1247 return check_section_is_single(min_size, has_any_or_none,
1248 op_name, "an", "array template");
1249 }
1250
1251 template <typename T_value_type, typename T_template_type,
1252 unsigned int array_size, int index_offset>
1253 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1254 match_function_specific(const Base_Type *value_ptr, int value_index,
1255 const Restricted_Length_Template *template_ptr,
1256 int template_index, boolean legacy)
1257 {
1258 if (value_index >= 0)
1259 return ((const TEMPLATE_ARRAY*)template_ptr)->
1260 single_value.value_elements[template_index]->
1261 match(
1262 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1263 ->array_element(value_index), legacy);
1264 else
1265 return ((const TEMPLATE_ARRAY*)template_ptr)->
1266 single_value.value_elements[template_index]->is_any_or_omit();
1267 }
1268
1269 template <typename T_value_type, typename T_template_type,
1270 unsigned int array_size, int index_offset>
1271 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1272 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1273 other_value, boolean legacy) const
1274 {
1275 if (!match_length(array_size)) return FALSE;
1276 switch (template_selection)
1277 {
1278 case SPECIFIC_VALUE:
1279 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1280 match_function_specific, legacy);
1281 case OMIT_VALUE:
1282 return FALSE;
1283 case ANY_VALUE:
1284 case ANY_OR_OMIT:
1285 return TRUE;
1286 case VALUE_LIST:
1287 case COMPLEMENTED_LIST:
1288 for (unsigned int list_count = 0; list_count < value_list.n_values;
1289 list_count++)
1290 if (value_list.list_value[list_count].match(other_value, legacy))
1291 return template_selection == VALUE_LIST;
1292 return template_selection == COMPLEMENTED_LIST;
1293 default:
1294 TTCN_error("Matching with an uninitialized/unsupported array template.");
1295 }
1296 return FALSE;
1297 }
1298
1299 template <typename T_value_type, typename T_template_type,
1300 unsigned int array_size, int index_offset>
1301 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1302 is_value() const
1303 {
1304 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1305 for (int i=0; i<single_value.n_elements; i++)
1306 if (!single_value.value_elements[i]->is_value()) return FALSE;
1307 return TRUE;
1308 }
1309
1310 template <typename T_value_type, typename T_template_type,
1311 unsigned int array_size, int index_offset>
1312 VALUE_ARRAY<T_value_type, array_size, index_offset>
1313 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1314 valueof() const
1315 {
1316 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1317 TTCN_error("Performing a valueof or send operation on a "
1318 "non-specific array template.");
1319 // the size of the template must be the size of the value
1320 if (single_value.n_elements!=array_size)
1321 TTCN_error("Performing a valueof or send operation on a "
1322 "specific array template with invalid size.");
1323 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1324 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1325 ret_val.array_element(elem_count) =
1326 single_value.value_elements[elem_count]->valueof();
1327 return ret_val;
1328 }
1329
1330 template <typename T_value_type, typename T_template_type,
1331 unsigned int array_size, int index_offset>
1332 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1333 set_type(template_sel template_type, unsigned int list_length)
1334 {
1335 clean_up();
1336 switch (template_type) {
1337 case VALUE_LIST:
1338 case COMPLEMENTED_LIST:
1339 value_list.n_values = list_length;
1340 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1341 break;
1342 default:
1343 TTCN_error(
1344 "Internal error: Setting an invalid type for an array template.");
1345 }
1346 set_selection(template_type);
1347 }
1348
1349 template <typename T_value_type, typename T_template_type,
1350 unsigned int array_size, int index_offset>
1351 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1352 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1353 list_item(unsigned int list_index)
1354 {
1355 if (template_selection != VALUE_LIST &&
1356 template_selection != COMPLEMENTED_LIST)
1357 TTCN_error("Internal error: Accessing a list element of a non-list "
1358 "array template.");
1359 if (list_index >= value_list.n_values)
1360 TTCN_error("Internal error: Index overflow in a value list "
1361 "array template.");
1362 return value_list.list_value[list_index];
1363 }
1364
1365 template <typename T_value_type, typename T_template_type,
1366 unsigned int array_size, int index_offset>
1367 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1368 log() const
1369 {
1370 switch (template_selection)
1371 {
1372 case SPECIFIC_VALUE:
1373 if (single_value.n_elements > 0)
1374 {
1375 TTCN_Logger::log_event_str("{ ");
1376 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1377 {
1378 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1379 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1380 single_value.value_elements[elem_count]->log();
1381 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1382 }
1383 TTCN_Logger::log_event_str(" }");
1384 }
1385 else
1386 TTCN_Logger::log_event_str("{ }");
1387 break;
1388 case COMPLEMENTED_LIST:
1389 TTCN_Logger::log_event_str("complement");
1390 case VALUE_LIST:
1391 TTCN_Logger::log_char('(');
1392 for (unsigned int list_count = 0; list_count < value_list.n_values;
1393 list_count++)
1394 {
1395 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1396 value_list.list_value[list_count].log();
1397 }
1398 TTCN_Logger::log_char(')');
1399 break;
1400 default:
1401 log_generic();
1402 break;
1403 }
1404 log_restricted();
1405 log_ifpresent();
1406 }
1407
1408 template <typename T_value_type, typename T_template_type,
1409 unsigned int array_size, int index_offset>
1410 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1411 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1412 match_value, boolean legacy) const
1413 {
1414 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1415 if(match(match_value, legacy)){
1416 TTCN_Logger::print_logmatch_buffer();
1417 TTCN_Logger::log_event_str(" matched");
1418 }else{
1419 if (template_selection == SPECIFIC_VALUE &&
1420 single_value.n_elements == array_size) {
1421 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1422 for (unsigned int elem_count = 0; elem_count < array_size;
1423 elem_count++) {
1424 if(!single_value.value_elements[elem_count]->
1425 match(match_value.array_element(elem_count), legacy)){
1426 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1427 single_value.value_elements[elem_count]->
1428 log_match(match_value.array_element(elem_count), legacy);
1429 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1430 }
1431 }
1432 log_match_length(array_size);
1433 } else {
1434 TTCN_Logger::print_logmatch_buffer();
1435 match_value.log();
1436 TTCN_Logger::log_event_str(" with ");
1437 log();
1438 TTCN_Logger::log_event_str(" unmatched");
1439 }
1440 }
1441 return;
1442 }
1443 if (template_selection == SPECIFIC_VALUE &&
1444 single_value.n_elements == array_size) {
1445 TTCN_Logger::log_event_str("{ ");
1446 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1447 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1448 single_value.value_elements[elem_count]->log_match(
1449 match_value.array_element(elem_count), legacy);
1450 }
1451 TTCN_Logger::log_event_str(" }");
1452 log_match_length(array_size);
1453 } else {
1454 match_value.log();
1455 TTCN_Logger::log_event_str(" with ");
1456 log();
1457 if (match(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1458 else TTCN_Logger::log_event_str(" unmatched");
1459 }
1460 }
1461
1462 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1463 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1464 {
1465 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1466 param.get_id()->next_name()) {
1467 // Haven't reached the end of the module parameter name
1468 // => the name refers to one of the elements, not to the whole array
1469 char* param_field = param.get_id()->get_current_name();
1470 if (param_field[0] < '0' || param_field[0] > '9') {
1471 param.error("Unexpected record field name in module parameter, expected a valid"
1472 " array template index");
1473 }
1474 unsigned int param_index = -1;
1475 sscanf(param_field, "%u", &param_index);
1476 if (param_index >= array_size) {
1477 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1478 }
1479 (*this)[param_index].set_param(param);
1480 return;
1481 }
1482
1483 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1484
1485 Module_Param_Ptr mp = &param;
1486 if (param.get_type() == Module_Param::MP_Reference) {
1487 mp = param.get_referenced_param();
1488 }
1489
1490 switch (mp->get_type()) {
1491 case Module_Param::MP_Omit:
1492 *this = OMIT_VALUE;
1493 break;
1494 case Module_Param::MP_Any:
1495 *this = ANY_VALUE;
1496 break;
1497 case Module_Param::MP_AnyOrNone:
1498 *this = ANY_OR_OMIT;
1499 break;
1500 case Module_Param::MP_List_Template:
1501 case Module_Param::MP_ComplementList_Template: {
1502 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset> temp;
1503 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1504 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1505 for (size_t i=0; i<mp->get_size(); i++) {
1506 temp.list_item(i).set_param(*mp->get_elem(i));
1507 }
1508 *this = temp;
1509 break; }
1510 case Module_Param::MP_Value_List:
1511 set_size(mp->get_size());
1512 for (size_t i=0; i<mp->get_size(); ++i) {
1513 Module_Param* const curr = mp->get_elem(i);
1514 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1515 (*this)[(int)i+index_offset].set_param(*curr);
1516 }
1517 }
1518 break;
1519 case Module_Param::MP_Indexed_List:
1520 for (size_t i=0; i<mp->get_size(); ++i) {
1521 Module_Param* const curr = mp->get_elem(i);
1522 (*this)[curr->get_id()->get_index()].set_param(*curr);
1523 }
1524 break;
1525 default:
1526 param.type_error("array template");
1527 }
1528 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1529 }
1530
1531 template <typename T_value_type, typename T_template_type,
1532 unsigned int array_size, int index_offset>
1533 Module_Param* TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1534 get_param(Module_Param_Name& param_name) const
1535 {
1536 if (param_name.next_name()) {
1537 // Haven't reached the end of the module parameter name
1538 // => the name refers to one of the elements, not to the whole record of
1539 char* param_field = param_name.get_current_name();
1540 if (param_field[0] < '0' || param_field[0] > '9') {
1541 TTCN_error("Unexpected record field name in module parameter reference, "
1542 "expected a valid array index");
1543 }
1544 unsigned int param_index = -1;
1545 sscanf(param_field, "%u", &param_index);
1546 if (param_index >= array_size) {
1547 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1548 }
1549 return single_value.value_elements[param_index]->get_param(param_name);
1550 }
1551 Module_Param* mp = NULL;
1552 switch (template_selection) {
1553 case UNINITIALIZED_TEMPLATE:
1554 mp = new Module_Param_Unbound();
1555 break;
1556 case OMIT_VALUE:
1557 mp = new Module_Param_Omit();
1558 break;
1559 case ANY_VALUE:
1560 mp = new Module_Param_Any();
1561 break;
1562 case ANY_OR_OMIT:
1563 mp = new Module_Param_AnyOrNone();
1564 break;
1565 case SPECIFIC_VALUE: {
1566 Vector<Module_Param*> values;
1567 for (int i = 0; i < array_size; ++i) {
1568 values.push_back(single_value.value_elements[i]->get_param(param_name));
1569 }
1570 mp = new Module_Param_Value_List();
1571 mp->add_list_with_implicit_ids(&values);
1572 values.clear();
1573 break; }
1574 case VALUE_LIST:
1575 case COMPLEMENTED_LIST: {
1576 if (template_selection == VALUE_LIST) {
1577 mp = new Module_Param_List_Template();
1578 }
1579 else {
1580 mp = new Module_Param_ComplementList_Template();
1581 }
1582 for (size_t i = 0; i < value_list.n_values; ++i) {
1583 mp->add_elem(value_list.list_value[i].get_param(param_name));
1584 }
1585 break; }
1586 default:
1587 break;
1588 }
1589 if (is_ifpresent) {
1590 mp->set_ifpresent();
1591 }
1592 return mp;
1593 }
1594
1595 template <typename T_value_type, typename T_template_type,
1596 unsigned int array_size, int index_offset>
1597 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1598 encode_text(Text_Buf& text_buf) const
1599 {
1600 encode_text_restricted(text_buf);
1601 switch (template_selection)
1602 {
1603 case SPECIFIC_VALUE:
1604 text_buf.push_int(single_value.n_elements);
1605 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1606 single_value.value_elements[elem_count]->encode_text(text_buf);
1607 break;
1608 case OMIT_VALUE:
1609 case ANY_VALUE:
1610 case ANY_OR_OMIT:
1611 break;
1612 case VALUE_LIST:
1613 case COMPLEMENTED_LIST:
1614 text_buf.push_int(value_list.n_values);
1615 for (unsigned int list_count = 0; list_count < value_list.n_values;
1616 list_count++)
1617 value_list.list_value[list_count].encode_text(text_buf);
1618 break;
1619 default:
1620 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1621 "array template.");
1622 }
1623 }
1624
1625 template <typename T_value_type, typename T_template_type,
1626 unsigned int array_size, int index_offset>
1627 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1628 decode_text(Text_Buf& text_buf)
1629 {
1630 clean_up();
1631 decode_text_restricted(text_buf);
1632 switch (template_selection)
1633 {
1634 case SPECIFIC_VALUE:
1635 single_value.n_elements = text_buf.pull_int().get_val();
1636 if (single_value.n_elements < 0)
1637 TTCN_error("Text decoder: Negative size was received for an "
1638 "array template.");
1639 single_value.value_elements =
1640 (T_template_type**)allocate_pointers(single_value.n_elements);
1641 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1642 {
1643 single_value.value_elements[elem_count] = new T_template_type;
1644 single_value.value_elements[elem_count]->decode_text(text_buf);
1645 }
1646 break;
1647 case OMIT_VALUE:
1648 case ANY_VALUE:
1649 case ANY_OR_OMIT:
1650 break;
1651 case VALUE_LIST:
1652 case COMPLEMENTED_LIST:
1653 value_list.n_values = text_buf.pull_int().get_val();
1654 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1655 for (unsigned int list_count = 0; list_count < value_list.n_values;
1656 list_count++)
1657 value_list.list_value[list_count].decode_text(text_buf);
1658 break;
1659 default:
1660 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1661 "for an array template.");
1662 }
1663 }
1664
1665 template <typename T_value_type, typename T_template_type,
1666 unsigned int array_size, int index_offset>
1667 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1668 is_present(boolean legacy /* = FALSE */) const
1669 {
1670 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1671 return !match_omit(legacy);
1672 }
1673
1674 template <typename T_value_type, typename T_template_type,
1675 unsigned int array_size, int index_offset>
1676 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1677 match_omit(boolean legacy /* = FALSE */) const
1678 {
1679 if (is_ifpresent) return TRUE;
1680 switch (template_selection) {
1681 case OMIT_VALUE:
1682 case ANY_OR_OMIT:
1683 return TRUE;
1684 case VALUE_LIST:
1685 case COMPLEMENTED_LIST:
1686 if (legacy) {
1687 // legacy behavior: 'omit' can appear in the value/complement list
1688 for (unsigned int i=0; i<value_list.n_values; i++)
1689 if (value_list.list_value[i].match_omit())
1690 return template_selection==VALUE_LIST;
1691 return template_selection==COMPLEMENTED_LIST;
1692 }
1693 // else fall through
1694 default:
1695 return FALSE;
1696 }
1697 return FALSE;
1698 }
1699
1700 #ifndef TITAN_RUNTIME_2
1701 template <typename T_value_type, typename T_template_type,
1702 unsigned int array_size, int index_offset>
1703 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1704 check_restriction(template_res t_res, const char* t_name, boolean legacy /* = FALSE */) const
1705 {
1706 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1707 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1708 case TR_OMIT:
1709 if (template_selection==OMIT_VALUE) return;
1710 case TR_VALUE:
1711 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1712 for (int i=0; i<single_value.n_elements; i++)
1713 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1714 return;
1715 case TR_PRESENT:
1716 if (!match_omit(legacy)) return;
1717 break;
1718 default:
1719 return;
1720 }
1721 TTCN_error("Restriction `%s' on template of type %s violated.",
1722 get_res_name(t_res), t_name ? t_name : "array");
1723 }
1724 #endif
1725
1726 template <typename T_value_type, typename T_template_type,
1727 unsigned int array_size, int index_offset>
1728 answer recursive_permutation_match(const Base_Type *value_ptr,
1729 unsigned int value_start_index,
1730 unsigned int value_size,
1731 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1732 unsigned int template_start_index,
1733 unsigned int template_size,
1734 unsigned int permutation_index,
1735 match_function_t match_function,
1736 unsigned int& shift_size,
1737 boolean legacy)
1738 {
1739 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1740 if (permutation_index > nof_permutations)
1741 TTCN_error("Internal error: recursive_permutation_match: "
1742 "invalid argument.");
1743
1744 if (permutation_index < nof_permutations &&
1745 template_ptr->get_permutation_end(permutation_index) >
1746 template_start_index + template_size)
1747 TTCN_error("Internal error: recursive_permutation_match: wrong "
1748 "permutation interval settings for permutation %d.",
1749 permutation_index);
1750
1751 shift_size = 0;
1752
1753 //trivial cases
1754 if(template_size == 0)
1755 {
1756 //reached the end of templates
1757 // if we reached the end of values => good
1758 // else => bad
1759 if(value_size == 0)
1760 return SUCCESS;
1761 else
1762 return FAILURE;
1763 }
1764
1765 //are we at an asterisk or at the beginning of a permutation interval
1766 boolean is_asterisk;
1767 boolean permutation_begins = permutation_index < nof_permutations &&
1768 template_start_index ==
1769 template_ptr->get_permutation_start(permutation_index);
1770
1771 if (permutation_begins ||
1772 match_function(value_ptr, -1, template_ptr, template_start_index, legacy))
1773 {
1774 unsigned int smallest_possible_size;
1775 unsigned int largest_possible_size;
1776 boolean has_asterisk;
1777 boolean already_superset;
1778 unsigned int permutation_size;
1779
1780 //check how many values might be associated with this permutation
1781 //if we are at a permutation start
1782 if (permutation_begins)
1783 {
1784 is_asterisk = FALSE;
1785 permutation_size =
1786 template_ptr->get_permutation_size(permutation_index);
1787 smallest_possible_size = 0;
1788 has_asterisk = FALSE;
1789
1790 //count how many non asterisk elements are in the permutation
1791 for(unsigned int i = 0; i < permutation_size; i++)
1792 {
1793 if(match_function(value_ptr, -1, template_ptr,
1794 i + template_start_index, legacy))
1795 {
1796 has_asterisk = TRUE;
1797 }else{
1798 smallest_possible_size++;
1799 }
1800 }
1801
1802 //the real permutation size is bigger then the value size
1803 if(smallest_possible_size > value_size)
1804 return NO_CHANCE;
1805
1806 //if the permutation has an asterisk then it can grow
1807 if(has_asterisk)
1808 {
1809 largest_possible_size = value_size;
1810
1811 //if there are only asterisks in the permutation
1812 if(smallest_possible_size == 0)
1813 already_superset = TRUE;
1814 else
1815 already_superset = FALSE;
1816 }else{
1817 //without asterisks its size is fixed
1818 largest_possible_size = smallest_possible_size;
1819 already_superset = FALSE;
1820 }
1821 }else{
1822 //or at an asterisk
1823 is_asterisk = TRUE;
1824 already_superset = TRUE;
1825 permutation_size = 1;
1826 smallest_possible_size = 0;
1827 largest_possible_size = value_size;
1828 has_asterisk = TRUE;
1829 }
1830
1831 unsigned int temp_size = smallest_possible_size;
1832
1833 {
1834 //this is to make match_set_of incremental,
1835 // we store the already found pairs in this vector
1836 // so we wouldn't try to find a pair for those templates again
1837 // and we can set the covered state of values too
1838 // to not waste memory it is only created if needed
1839 int* pair_list = NULL;
1840 unsigned int old_temp_size = 0;
1841
1842 if(!already_superset)
1843 {
1844 pair_list = new int[permutation_size];
1845 for(unsigned int i = 0 ; i < permutation_size; i++)
1846 {
1847 //in the beginning we haven't found a template to any values
1848 pair_list[i] = -1;
1849 }
1850 }
1851
1852 while(!already_superset)
1853 {
1854 //must be a permutation having other values than asterisks
1855
1856 int x = 0;
1857
1858 //our set matching is extended with 2 more parameters
1859 // giving back how many templates
1860 // (other than asterisk) couldn't be matched
1861 // and setting / giving back the value-template pairs
1862
1863 boolean found = match_set_of_internal(value_ptr, value_start_index,
1864 temp_size, template_ptr,
1865 template_start_index, permutation_size,
1866 match_function, SUPERSET, &x, pair_list, old_temp_size, legacy);
1867
1868 if(found)
1869 {
1870 already_superset = TRUE;
1871 }else{
1872 //as we didn't found a match we have to try
1873 // a larger set of values
1874 //x is the number of templates we couldn't find
1875 // a matching pair for
1876 // the next must be at least this big to fully cover
1877 // on the other side if it would be bigger than it might miss
1878 // the smallest possible match.
1879
1880 //if we can match with more values
1881 if(has_asterisk && temp_size + x <= largest_possible_size)
1882 {
1883 old_temp_size = temp_size;
1884 temp_size += x;
1885 }else{
1886 delete[] pair_list;
1887 return FAILURE; //else we failed
1888 }
1889 }
1890 }
1891
1892 delete[] pair_list;
1893 }
1894
1895 //we reach here only if we found a match
1896
1897 //can only go on recursively if we haven't reached the end
1898
1899 //reached the end of templates
1900 if(permutation_size == template_size)
1901 {
1902 if(has_asterisk || value_size == temp_size)
1903 return SUCCESS;
1904 else
1905 return FAILURE;
1906 }
1907
1908 for(unsigned int i = temp_size; i <= largest_possible_size;)
1909 {
1910 answer result;
1911
1912 if(is_asterisk)
1913 {
1914 //don't step the permutation index
1915 result = recursive_permutation_match(value_ptr,value_start_index+i,
1916 value_size - i, template_ptr,
1917 template_start_index +
1918 permutation_size,
1919 template_size -
1920 permutation_size,
1921 permutation_index,
1922 match_function, shift_size, legacy);
1923 }else{
1924 //try with the next permutation
1925 result = recursive_permutation_match(value_ptr,value_start_index+i,
1926 value_size - i, template_ptr,
1927 template_start_index +
1928 permutation_size,
1929 template_size - permutation_size,
1930 permutation_index + 1,
1931 match_function, shift_size, legacy);
1932 }
1933
1934 if(result == SUCCESS)
1935 return SUCCESS; //we finished
1936 else if(result == NO_CHANCE)
1937 return NO_CHANCE; //matching is not possible
1938 else if(i == value_size) //we failed
1939 {
1940 //if there is no chance of matching
1941 return NO_CHANCE;
1942 }else{
1943 i += shift_size > 1 ? shift_size : 1;
1944
1945 if(i > largest_possible_size)
1946 shift_size = i - largest_possible_size;
1947 else
1948 shift_size = 0;
1949 }
1950 }
1951
1952 //this level failed;
1953 return FAILURE;
1954 }else{
1955 //we are at the beginning of a non permutation, non asterisk interval
1956
1957 //the distance to the next permutation or the end of templates
1958 // so the longest possible match
1959 unsigned int distance;
1960
1961 if (permutation_index < nof_permutations)
1962 {
1963 distance = template_ptr->get_permutation_start(permutation_index)
1964 - template_start_index;
1965 }else{
1966 distance = template_size;
1967 }
1968
1969 //if there are no more values, but we still have templates
1970 // and the template is not an asterisk or a permutation start
1971 if(value_size == 0)
1972 return FAILURE;
1973
1974 //we try to match as many values as possible
1975 //an asterisk is handled like a 0 length permutation
1976 boolean good;
1977 unsigned int i = 0;
1978 do{
1979 good = match_function(value_ptr, value_start_index + i,
1980 template_ptr, template_start_index + i, legacy);
1981 i++;
1982 //bad stop: something can't be matched
1983 //half bad half good stop: the end of values is reached
1984 //good stop: matching on the full distance or till an asterisk
1985 }while(good && i < value_size && i < distance &&
1986 !match_function(value_ptr, -1, template_ptr,
1987 template_start_index + i, legacy));
1988
1989 //if we matched on the full distance or till an asterisk
1990 if(good && (i == distance ||
1991 match_function(value_ptr, -1, template_ptr,
1992 template_start_index + i, legacy)))
1993 {
1994 //reached the end of the templates
1995 if(i == template_size)
1996 {
1997 if(i < value_size)
1998 {
1999 //the next level would return FAILURE so we don't step it
2000 return FAILURE;
2001 }else{
2002 //i == value_size, so we matched everything
2003 return SUCCESS;
2004 }
2005 }else{
2006 //we reached the next asterisk or permutation,
2007 // so step to the next level
2008 return recursive_permutation_match(value_ptr,value_start_index + i,
2009 value_size - i,
2010 template_ptr,
2011 template_start_index + i,
2012 template_size - i,
2013 permutation_index,
2014 match_function, shift_size, legacy);
2015 }
2016 }else{
2017 //something bad happened, so we have to check how bad the situation is
2018 if( i == value_size)
2019 {
2020 //the aren't values left, meaning that the match is not possible
2021 return NO_CHANCE;
2022 }else{
2023 //we couldn't match, but there is still a chance of matching
2024
2025 //try to find a matching value for the last checked (and failed)
2026 // template.
2027 // smaller jumps would fail so we skip them
2028 shift_size = 0;
2029 i--;
2030 do{
2031 good = match_function(value_ptr,
2032 value_start_index + i + shift_size,
2033 template_ptr, template_start_index + i, legacy);
2034 shift_size++;
2035 }while(!good && i + shift_size < value_size);
2036
2037 if(good)
2038 {
2039 shift_size--;
2040 return FAILURE;
2041 }else{
2042 // the template can not be matched later
2043 return NO_CHANCE;
2044 }
2045 }
2046 }
2047 }
2048 }
2049
2050 template <typename T_value_type, typename T_template_type,
2051 unsigned int array_size, int index_offset>
2052 boolean match_permutation_array(const Base_Type *value_ptr,
2053 int value_size,
2054 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
2055 int template_size,
2056 match_function_t match_function,
2057 boolean legacy)
2058 {
2059 if (value_ptr == NULL || value_size < 0 ||
2060 template_ptr == NULL || template_size < 0 ||
2061 template_ptr->get_selection() != SPECIFIC_VALUE)
2062 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
2063
2064 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
2065 // use the simplified algorithm if the template does not contain permutation
2066 if (nof_permutations == 0)
2067 return match_array(value_ptr, value_size,
2068 template_ptr, template_size, match_function, legacy);
2069 // use 'set of' matching if all template elements are grouped into one
2070 // permutation
2071 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
2072 template_ptr->get_permutation_end(0) ==
2073 (unsigned int)(template_size - 1))
2074 return match_set_of(value_ptr, value_size, template_ptr, template_size,
2075 match_function, legacy);
2076
2077 unsigned int shift_size = 0;
2078 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
2079 0, template_size, 0, match_function, shift_size, legacy) == SUCCESS;
2080 }
2081
2082 #endif
This page took 0.074937 seconds and 5 git commands to generate.