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