Sync with 5.4.3
[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& p_td, JSON_Tokenizer& p_tok) const
499 {
500 if (!is_bound() && (NULL == p_td.json || !p_td.json->metainfo_unbound)) {
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 if (NULL != p_td.json && p_td.json->metainfo_unbound && !array_elements[i].is_bound()) {
510 // unbound elements are encoded as { "metainfo []" : "unbound" }
511 enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
512 enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
513 enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
514 enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
515 }
516 else {
517 int ret_val = array_elements[i].JSON_encode(*get_elem_descr(), p_tok);
518 if (0 > ret_val) break;
519 enc_len += ret_val;
520 }
521 }
522
523 enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
524 return enc_len;
525 }
526
527 template <typename T_type, unsigned int array_size, int index_offset>
528 int VALUE_ARRAY<T_type,array_size,index_offset>::JSON_decode(
529 const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)
530 {
531 json_token_t token = JSON_TOKEN_NONE;
532 int dec_len = p_tok.get_next_token(&token, NULL, NULL);
533 if (JSON_TOKEN_ERROR == token) {
534 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, "");
535 return JSON_ERROR_FATAL;
536 }
537 else if (JSON_TOKEN_ARRAY_START != token) {
538 return JSON_ERROR_INVALID_TOKEN;
539 }
540
541 for (unsigned int i = 0; i < array_size; ++i) {
542 size_t buf_pos = p_tok.get_buf_pos();
543 int ret_val;
544 if (NULL != p_td.json && p_td.json->metainfo_unbound) {
545 // check for metainfo object
546 ret_val = p_tok.get_next_token(&token, NULL, NULL);
547 if (JSON_TOKEN_OBJECT_START == token) {
548 char* value = NULL;
549 size_t value_len = 0;
550 ret_val += p_tok.get_next_token(&token, &value, &value_len);
551 if (JSON_TOKEN_NAME == token && 11 == value_len &&
552 0 == strncmp(value, "metainfo []", 11)) {
553 ret_val += p_tok.get_next_token(&token, &value, &value_len);
554 if (JSON_TOKEN_STRING == token && 9 == value_len &&
555 0 == strncmp(value, "\"unbound\"", 9)) {
556 ret_val = p_tok.get_next_token(&token, NULL, NULL);
557 if (JSON_TOKEN_OBJECT_END == token) {
558 dec_len += ret_val;
559 continue;
560 }
561 }
562 }
563 }
564 // metainfo object not found, jump back and let the element type decode it
565 p_tok.set_buf_pos(buf_pos);
566 }
567 ret_val = array_elements[i].JSON_decode(*get_elem_descr(), p_tok, p_silent);
568 if (JSON_ERROR_INVALID_TOKEN == ret_val) {
569 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_ELEM_TOKEN_ERROR,
570 array_size - i, (array_size - i > 1) ? "s" : "");
571 return JSON_ERROR_FATAL;
572 }
573 else if (JSON_ERROR_FATAL == ret_val) {
574 if (p_silent) {
575 clean_up();
576 }
577 return JSON_ERROR_FATAL;
578 }
579 dec_len += ret_val;
580 }
581
582 dec_len += p_tok.get_next_token(&token, NULL, NULL);
583 if (JSON_TOKEN_ARRAY_END != token) {
584 JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_ARRAY_END_TOKEN_ERROR, "");
585 if (p_silent) {
586 clean_up();
587 }
588 return JSON_ERROR_FATAL;
589 }
590
591 return dec_len;
592 }
593
594
595 template <typename T_value_type, typename T_template_type,
596 unsigned int array_size, int index_offset>
597 class TEMPLATE_ARRAY : public Restricted_Length_Template
598 {
599 private:
600 union {
601 struct {
602 int n_elements;
603 T_template_type **value_elements;
604 } single_value;
605 struct {
606 unsigned int n_values;
607 TEMPLATE_ARRAY *list_value;
608 } value_list;
609 };
610
611 struct Pair_of_elements;
612 Pair_of_elements *permutation_intervals;
613 unsigned int number_of_permutations;
614
615 void clean_up_intervals();
616 void copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
617 other_value);
618 void copy_template(const TEMPLATE_ARRAY& other_value);
619 void set_selection(template_sel new_selection);
620 void set_selection(const TEMPLATE_ARRAY& other_value);
621 void encode_text_permutation(Text_Buf& text_buf) const;
622 void decode_text_permutation(Text_Buf& text_buf);
623
624 public:
625 TEMPLATE_ARRAY()
626 {
627 number_of_permutations = 0;
628 permutation_intervals = NULL;
629 }
630 TEMPLATE_ARRAY(template_sel other_value)
631 : Restricted_Length_Template(other_value)
632 {
633 check_single_selection(other_value);
634 number_of_permutations = 0;
635 permutation_intervals = NULL;
636 }
637 TEMPLATE_ARRAY(null_type other_value);
638 TEMPLATE_ARRAY(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
639 other_value)
640 {
641 number_of_permutations = 0;
642 permutation_intervals = NULL;
643 copy_value(other_value);
644 }
645 TEMPLATE_ARRAY(const
646 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
647 TEMPLATE_ARRAY(const TEMPLATE_ARRAY& other_value)
648 : Restricted_Length_Template()
649 {
650 number_of_permutations = 0;
651 permutation_intervals = NULL;
652 copy_template(other_value);
653 }
654
655 ~TEMPLATE_ARRAY()
656 {
657 clean_up_intervals();
658 clean_up();
659 }
660 void clean_up();
661
662 TEMPLATE_ARRAY& operator=(template_sel other_value);
663 TEMPLATE_ARRAY& operator=(null_type other_value);
664 TEMPLATE_ARRAY& operator=(const
665 VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value);
666 TEMPLATE_ARRAY& operator=(const
667 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value);
668 TEMPLATE_ARRAY& operator=(const TEMPLATE_ARRAY& other_value);
669
670 T_template_type& operator[](int index_value);
671 T_template_type& operator[](const INTEGER& index_value);
672 const T_template_type& operator[](int index_value) const;
673 const T_template_type& operator[](const INTEGER& index_value) const;
674
675 void set_size(int new_size);
676
677 int n_elem() const;
678 int size_of(boolean is_size) const;
679 inline int size_of() const { return size_of(TRUE); }
680 inline int lengthof() const { return size_of(FALSE); }
681
682 void add_permutation(unsigned int start_index, unsigned int end_index);
683
684 /** Removes all permutations set on this template, used when template variables
685 * are given new values. */
686 void remove_all_permutations() { clean_up_intervals(); }
687
688 unsigned int get_number_of_permutations() const;
689 unsigned int get_permutation_start(unsigned int index_value) const;
690 unsigned int get_permutation_end(unsigned int index_value) const;
691 unsigned int get_permutation_size(unsigned int index_value) const;
692 boolean permutation_starts_at(unsigned int index_value) const;
693 boolean permutation_ends_at(unsigned int index_value) const;
694
695 private:
696 static boolean match_function_specific(
697 const Base_Type *value_ptr, int value_index,
698 const Restricted_Length_Template *template_ptr, int template_index,
699 boolean legacy);
700 public:
701 boolean match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
702 other_value, boolean legacy = FALSE) const;
703
704 boolean is_value() const;
705 VALUE_ARRAY<T_value_type, array_size, index_offset> valueof() const;
706
707 void set_type(template_sel template_type, unsigned int list_length);
708 TEMPLATE_ARRAY& list_item(unsigned int list_index);
709
710 void log() const;
711 void log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
712 match_value, boolean legacy = FALSE) const;
713
714 void set_param(Module_Param& param);
715 Module_Param* get_param(Module_Param_Name& param_name) const;
716
717 void encode_text(Text_Buf& text_buf) const;
718 void decode_text(Text_Buf& text_buf);
719
720 boolean is_present(boolean legacy = FALSE) const;
721 boolean match_omit(boolean legacy = FALSE) const;
722
723 #ifdef TITAN_RUNTIME_2
724 void valueofv(Base_Type* value) const { *(static_cast<VALUE_ARRAY<T_value_type, array_size, index_offset>*>(value)) = valueof(); }
725 void set_value(template_sel other_value) { *this = other_value; }
726 void copy_value(const Base_Type* other_value) { *this = *(static_cast<const VALUE_ARRAY<T_value_type, array_size, index_offset>*>(other_value)); }
727 Base_Template* clone() const { return new TEMPLATE_ARRAY(*this); }
728 const TTCN_Typedescriptor_t* get_descriptor() const { TTCN_error("Internal error: TEMPLATE_ARRAY<>::get_descriptor() called."); }
729 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); }
730 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); }
731 #else
732 void check_restriction(template_res t_res, const char* t_name=NULL, boolean legacy = FALSE) const;
733 #endif
734 };
735
736 template <typename T_value_type, typename T_template_type,
737 unsigned int array_size, int index_offset>
738 struct TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
739 Pair_of_elements{
740 unsigned int start_index, end_index; //beginning and ending index
741 };
742
743 template <typename T_value_type, typename T_template_type,
744 unsigned int array_size, int index_offset>
745 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
746 clean_up()
747 {
748 switch (template_selection)
749 {
750 case SPECIFIC_VALUE:
751 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
752 delete single_value.value_elements[elem_count];
753 free_pointers((void**)single_value.value_elements);
754 break;
755 case VALUE_LIST:
756 case COMPLEMENTED_LIST:
757 delete [] value_list.list_value;
758 break;
759 default:
760 break;
761 }
762 template_selection = UNINITIALIZED_TEMPLATE;
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 clean_up_intervals()
769 {
770 number_of_permutations = 0;
771 Free(permutation_intervals);
772 permutation_intervals = NULL;
773 }
774
775 template <typename T_value_type, typename T_template_type,
776 unsigned int array_size, int index_offset>
777 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
778 set_selection(template_sel other_value)
779 {
780 Restricted_Length_Template::set_selection(other_value);
781 clean_up_intervals();
782 }
783
784 template <typename T_value_type, typename T_template_type,
785 unsigned int array_size, int index_offset>
786 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
787 set_selection(const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>& other_value)
788 {
789 Restricted_Length_Template::set_selection(other_value);
790 clean_up_intervals();
791 if(other_value.template_selection == SPECIFIC_VALUE)
792 {
793 number_of_permutations = other_value.number_of_permutations;
794 permutation_intervals = (Pair_of_elements*) Malloc(number_of_permutations * sizeof(Pair_of_elements));
795 memcpy(permutation_intervals,other_value.permutation_intervals,number_of_permutations*sizeof(Pair_of_elements));
796 }
797 }
798
799 template <typename T_value_type, typename T_template_type,
800 unsigned int array_size, int index_offset>
801 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
802 encode_text_permutation(Text_Buf& text_buf) const
803 {
804 encode_text_restricted(text_buf);
805 text_buf.push_int(number_of_permutations);
806
807 for(unsigned int i = 0; i < number_of_permutations; i++)
808 {
809 text_buf.push_int(permutation_intervals[i].start_index);
810 text_buf.push_int(permutation_intervals[i].end_index);
811 }
812 }
813
814 template <typename T_value_type, typename T_template_type,
815 unsigned int array_size, int index_offset>
816 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
817 decode_text_permutation(Text_Buf& text_buf)
818 {
819 decode_text_restricted(text_buf);
820
821 number_of_permutations = text_buf.pull_int().get_val();
822 permutation_intervals = (Pair_of_elements *)Malloc
823 (number_of_permutations * sizeof(Pair_of_elements));
824
825 for (unsigned int i = 0; i < number_of_permutations; i++)
826 {
827 permutation_intervals[i].start_index =
828 text_buf.pull_int().get_val();
829 permutation_intervals[i].end_index =
830 text_buf.pull_int().get_val();
831 }
832 }
833
834 template <typename T_value_type, typename T_template_type,
835 unsigned int array_size, int index_offset>
836 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
837 add_permutation(unsigned int start_index, unsigned int end_index)
838 {
839 if(start_index > end_index)
840 TTCN_error("wrong permutation interval settings start (%d)"
841 "can not be greater than end (%d)",start_index, end_index);
842
843 if(number_of_permutations > 0 &&
844 permutation_intervals[number_of_permutations - 1].end_index >= start_index)
845 TTCN_error("the %dth permutation overlaps the previous one", number_of_permutations);
846
847 permutation_intervals = (Pair_of_elements*)Realloc(permutation_intervals, (number_of_permutations + 1) * sizeof(Pair_of_elements));
848 permutation_intervals[number_of_permutations].start_index = start_index;
849 permutation_intervals[number_of_permutations].end_index = end_index;
850 number_of_permutations++;
851 }
852
853 template <typename T_value_type, typename T_template_type,
854 unsigned int array_size, int index_offset>
855 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
856 get_number_of_permutations(void) const
857 {
858 return number_of_permutations;
859 }
860
861 template <typename T_value_type, typename T_template_type,
862 unsigned int array_size, int index_offset>
863 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
864 get_permutation_start(unsigned int index_value) const
865 {
866 if(index_value >= number_of_permutations)
867 TTCN_error("Index overflow (%d)", index_value);
868
869 return permutation_intervals[index_value].start_index;
870 }
871
872 template <typename T_value_type, typename T_template_type,
873 unsigned int array_size, int index_offset>
874 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
875 get_permutation_end(unsigned int index_value) const
876 {
877 if(index_value >= number_of_permutations)
878 TTCN_error("Index overflow (%d)", index_value);
879
880 return permutation_intervals[index_value].end_index;
881 }
882
883 template <typename T_value_type, typename T_template_type,
884 unsigned int array_size, int index_offset>
885 unsigned int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
886 get_permutation_size(unsigned int index_value) const
887 {
888 if(index_value >= number_of_permutations)
889 TTCN_error("Index overflow (%d)", index_value);
890
891 return permutation_intervals[index_value].end_index - permutation_intervals[index_value].start_index + 1;
892 }
893
894 template <typename T_value_type, typename T_template_type,
895 unsigned int array_size, int index_offset>
896 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
897 permutation_starts_at(unsigned int index_value) const
898 {
899 for(unsigned int i = 0; i < number_of_permutations; i++)
900 {
901 if(permutation_intervals[i].start_index == index_value)
902 return TRUE;
903 }
904
905 return FALSE;
906 }
907
908 template <typename T_value_type, typename T_template_type,
909 unsigned int array_size, int index_offset>
910 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
911 permutation_ends_at(unsigned int index_value) const
912 {
913 for(unsigned int i = 0; i < number_of_permutations; i++)
914 {
915 if(permutation_intervals[i].end_index == index_value)
916 return TRUE;
917 }
918
919 return FALSE;
920 }
921
922 template <typename T_value_type, typename T_template_type,
923 unsigned int array_size, int index_offset>
924 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
925 copy_value(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
926 other_value)
927 {
928 single_value.n_elements = array_size;
929 single_value.value_elements =
930 (T_template_type**)allocate_pointers(array_size);
931 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
932 single_value.value_elements[elem_count] =
933 new T_template_type(other_value.array_element(elem_count));
934 set_selection(SPECIFIC_VALUE);
935 }
936
937 template <typename T_value_type, typename T_template_type,
938 unsigned int array_size, int index_offset>
939 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
940 copy_template(const TEMPLATE_ARRAY& other_value)
941 {
942 switch (other_value.template_selection)
943 {
944 case SPECIFIC_VALUE:
945 single_value.n_elements = other_value.single_value.n_elements;
946 single_value.value_elements =
947 (T_template_type**)allocate_pointers(single_value.n_elements);
948 for (int elem_count = 0; elem_count < single_value.n_elements; elem_count++)
949 single_value.value_elements[elem_count] = new
950 T_template_type(*other_value.single_value.value_elements[elem_count]);
951 break;
952 case OMIT_VALUE:
953 case ANY_VALUE:
954 case ANY_OR_OMIT:
955 break;
956 case VALUE_LIST:
957 case COMPLEMENTED_LIST:
958 value_list.n_values = other_value.value_list.n_values;
959 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
960 for (unsigned int list_count = 0; list_count < value_list.n_values;
961 list_count++)
962 value_list.list_value[list_count].copy_template(
963 other_value.value_list.list_value[list_count]);
964 break;
965 default:
966 TTCN_error("Copying an uninitialized/unsupported array template.");
967 }
968 set_selection(other_value);
969 }
970
971 template <typename T_value_type, typename T_template_type,
972 unsigned int array_size, int index_offset>
973 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
974 TEMPLATE_ARRAY(null_type)
975 : Restricted_Length_Template(SPECIFIC_VALUE)
976 {
977 single_value.n_elements = 0;
978 single_value.value_elements = NULL;
979 number_of_permutations = 0;
980 permutation_intervals = NULL;
981 }
982
983 template <typename T_value_type, typename T_template_type,
984 unsigned int array_size, int index_offset>
985 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
986 TEMPLATE_ARRAY(const
987 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
988 {
989 number_of_permutations = 0;
990 permutation_intervals = NULL;
991 switch (other_value.get_selection()) {
992 case OPTIONAL_PRESENT:
993 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
994 other_value);
995 break;
996 case OPTIONAL_OMIT:
997 set_selection(OMIT_VALUE);
998 break;
999 default:
1000 TTCN_error("Creating an array template from an unbound optional field.");
1001 }
1002 }
1003
1004 template <typename T_value_type, typename T_template_type,
1005 unsigned int array_size, int index_offset>
1006 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1007 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1008 operator=(template_sel other_value)
1009 {
1010 check_single_selection(other_value);
1011 clean_up();
1012 set_selection(other_value);
1013 return *this;
1014 }
1015
1016 template <typename T_value_type, typename T_template_type,
1017 unsigned int array_size, int index_offset>
1018 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1019 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1020 operator=(null_type)
1021 {
1022 clean_up();
1023 set_selection(SPECIFIC_VALUE);
1024 single_value.n_elements = 0;
1025 single_value.value_elements = NULL;
1026 return *this;
1027 }
1028
1029 template <typename T_value_type, typename T_template_type,
1030 unsigned int array_size, int index_offset>
1031 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1032 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator=
1033 (const VALUE_ARRAY<T_value_type, array_size, index_offset>& other_value)
1034 {
1035 clean_up();
1036 copy_value(other_value);
1037 return *this;
1038 }
1039
1040 template <typename T_value_type, typename T_template_type,
1041 unsigned int array_size, int index_offset>
1042 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1043 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1044 operator=(const
1045 OPTIONAL< VALUE_ARRAY<T_value_type,array_size,index_offset> >& other_value)
1046 {
1047 clean_up();
1048 switch (other_value.get_selection()) {
1049 case OPTIONAL_PRESENT:
1050 copy_value((const VALUE_ARRAY<T_value_type, array_size, index_offset>&)
1051 other_value);
1052 break;
1053 case OPTIONAL_OMIT:
1054 set_selection(OMIT_VALUE);
1055 break;
1056 default:
1057 TTCN_error("Assignment of an unbound optional field to an array template.");
1058 }
1059 return *this;
1060 }
1061
1062 template <typename T_value_type, typename T_template_type,
1063 unsigned int array_size, int index_offset>
1064 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1065 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1066 operator=(const
1067 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1068 other_value)
1069 {
1070 if (&other_value != this)
1071 {
1072 clean_up();
1073 copy_template(other_value);
1074 }
1075 return *this;
1076 }
1077
1078 template <typename T_value_type, typename T_template_type,
1079 unsigned int array_size, int index_offset>
1080 T_template_type&
1081 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1082 (int index_value)
1083 {
1084 if (index_value < index_offset || index_value >= index_offset+(int)array_size)
1085 TTCN_error(
1086 "Accessing an element of an array template using invalid index: %d. "
1087 "Index range is [%d,%d].",
1088 index_value, index_offset, index_offset+(int)array_size);
1089 // transform index value according to given offset
1090 index_value -= index_offset;
1091 // the template of an array is not restricted to array_size, allow any length
1092 // in case of * or ? expand to full size to avoid uninitialized values
1093 switch (template_selection)
1094 {
1095 case SPECIFIC_VALUE:
1096 if (index_value >= single_value.n_elements) set_size(index_value + 1);
1097 break;
1098 case ANY_VALUE:
1099 case ANY_OR_OMIT:
1100 set_size(array_size);
1101 break;
1102 default:
1103 set_size(index_value + 1);
1104 }
1105 return *single_value.value_elements[index_value];
1106 }
1107
1108 template <typename T_value_type, typename T_template_type,
1109 unsigned int array_size, int index_offset>
1110 T_template_type&
1111 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1112 (const INTEGER& index_value)
1113 {
1114 index_value.must_bound(
1115 "Using an unbound integer value for indexing an array template.");
1116 return (*this)[(int)index_value];
1117 }
1118
1119 template <typename T_value_type, typename T_template_type,
1120 unsigned int array_size, int index_offset>
1121 const T_template_type&
1122 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1123 (int index_value) const
1124 {
1125 if (index_value < index_offset)
1126 TTCN_error(
1127 "Accessing an element of an array template using invalid index: %d. "
1128 "Index range starts at %d.",
1129 index_value, index_offset);
1130 // transform index value according to given offset
1131 index_value -= index_offset;
1132 // const is specific template
1133 if (template_selection != SPECIFIC_VALUE)
1134 TTCN_error("Accessing an element of a non-specific array template.");
1135 if (index_value >= single_value.n_elements)
1136 TTCN_error("Index overflow in an array template: "
1137 "The index is %d (starting at %d),"
1138 " but the template has only %d elements.",
1139 index_value+index_offset, index_offset, single_value.n_elements);
1140 return *single_value.value_elements[index_value];
1141 }
1142
1143 template <typename T_value_type, typename T_template_type,
1144 unsigned int array_size, int index_offset>
1145 const T_template_type&
1146 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::operator[]
1147 (const INTEGER& index_value) const
1148 {
1149 index_value.must_bound(
1150 "Using an unbound integer value for indexing an array template.");
1151 return (*this)[(int)index_value];
1152 }
1153
1154 template <typename T_value_type, typename T_template_type,
1155 unsigned int array_size, int index_offset>
1156 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1157 set_size(int new_size)
1158 {
1159 if (new_size < 0) TTCN_error("Internal error: Setting a negative size "
1160 "for an array template.");
1161 template_sel old_selection = template_selection;
1162 if (old_selection != SPECIFIC_VALUE)
1163 {
1164 clean_up();
1165 set_selection(SPECIFIC_VALUE);
1166 single_value.n_elements = 0;
1167 single_value.value_elements = NULL;
1168 }
1169 if (new_size > single_value.n_elements)
1170 {
1171 single_value.value_elements =
1172 (T_template_type**)reallocate_pointers(
1173 (void**)single_value.value_elements, single_value.n_elements, new_size);
1174 if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT)
1175 {
1176 for (int elem_count = single_value.n_elements;
1177 elem_count < new_size; elem_count++)
1178 single_value.value_elements[elem_count] = new T_template_type(ANY_VALUE);
1179 }
1180 else
1181 {
1182 for (int elem_count = single_value.n_elements;
1183 elem_count < new_size; elem_count++)
1184 single_value.value_elements[elem_count] = new T_template_type;
1185 }
1186 single_value.n_elements = new_size;
1187 }
1188 else if (new_size < single_value.n_elements)
1189 {
1190 for (int elem_count = new_size; elem_count < single_value.n_elements;
1191 elem_count++)
1192 delete single_value.value_elements[elem_count];
1193 single_value.value_elements =
1194 (T_template_type**)reallocate_pointers(
1195 (void**)single_value.value_elements, single_value.n_elements, new_size);
1196 single_value.n_elements = new_size;
1197 }
1198 }
1199
1200 template <typename T_value_type, typename T_template_type,
1201 unsigned int array_size, int index_offset>
1202 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1203 n_elem() const
1204 {
1205 switch (template_selection) {
1206 case SPECIFIC_VALUE:
1207 return single_value.n_elements;
1208 case VALUE_LIST:
1209 return value_list.n_values;
1210 default:
1211 TTCN_error("Performing n_elem");
1212 }
1213 }
1214
1215 template <typename T_value_type, typename T_template_type,
1216 unsigned int array_size, int index_offset>
1217 int TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1218 size_of(boolean is_size) const
1219 {
1220 const char* op_name = is_size ? "size" : "length";
1221 int min_size;
1222 boolean has_any_or_none;
1223 if (is_ifpresent)
1224 TTCN_error("Performing %sof() operation on an array template "
1225 "which has an ifpresent attribute.", op_name);
1226 switch (template_selection)
1227 {
1228 case SPECIFIC_VALUE: {
1229 min_size = 0;
1230 has_any_or_none = FALSE;
1231 int elem_count = single_value.n_elements;
1232 if (!is_size) { // lengthof()
1233 while (elem_count>0 &&
1234 !single_value.value_elements[elem_count-1]->is_bound()) elem_count--;
1235 }
1236 for (int i=0; i<elem_count; i++)
1237 {
1238 switch (single_value.value_elements[i]->get_selection())
1239 {
1240 case OMIT_VALUE:
1241 TTCN_error("Performing %sof() operation on an array template "
1242 "containing omit element.", op_name);
1243 case ANY_OR_OMIT:
1244 has_any_or_none = TRUE;
1245 break;
1246 default:
1247 min_size++;
1248 break;
1249 }
1250 }
1251 } break;
1252 case OMIT_VALUE:
1253 TTCN_error("Performing %sof() operation on an array template "
1254 "containing omit value.", op_name);
1255 case ANY_VALUE:
1256 case ANY_OR_OMIT:
1257 min_size = 0;
1258 has_any_or_none = TRUE; // max. size is infinity
1259 break;
1260 case VALUE_LIST: {
1261 // error if any element does not have size or the sizes differ
1262 if (value_list.n_values<1)
1263 TTCN_error("Performing %sof() operation on an array template "
1264 "containing an empty list.", op_name);
1265 int item_size = value_list.list_value[0].size_of(is_size);
1266 for (unsigned int i = 1; i < value_list.n_values; i++) {
1267 if (value_list.list_value[i].size_of(is_size)!=item_size)
1268 TTCN_error("Performing %sof() operation on an array template "
1269 "containing a value list with different sizes.", op_name);
1270 }
1271 min_size = item_size;
1272 has_any_or_none = FALSE;
1273 } break;
1274 case COMPLEMENTED_LIST:
1275 TTCN_error("Performing %sof() operation on an array template "
1276 "containing complemented list.", op_name);
1277 default:
1278 TTCN_error("Performing %sof() operation on an "
1279 "uninitialized/unsupported array template.", op_name);
1280 }
1281 return check_section_is_single(min_size, has_any_or_none,
1282 op_name, "an", "array template");
1283 }
1284
1285 template <typename T_value_type, typename T_template_type,
1286 unsigned int array_size, int index_offset>
1287 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1288 match_function_specific(const Base_Type *value_ptr, int value_index,
1289 const Restricted_Length_Template *template_ptr,
1290 int template_index, boolean legacy)
1291 {
1292 if (value_index >= 0)
1293 return ((const TEMPLATE_ARRAY*)template_ptr)->
1294 single_value.value_elements[template_index]->
1295 match(
1296 ((const VALUE_ARRAY<T_value_type,array_size,index_offset>*)value_ptr)
1297 ->array_element(value_index), legacy);
1298 else
1299 return ((const TEMPLATE_ARRAY*)template_ptr)->
1300 single_value.value_elements[template_index]->is_any_or_omit();
1301 }
1302
1303 template <typename T_value_type, typename T_template_type,
1304 unsigned int array_size, int index_offset>
1305 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1306 match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1307 other_value, boolean legacy) const
1308 {
1309 if (!match_length(array_size)) return FALSE;
1310 switch (template_selection)
1311 {
1312 case SPECIFIC_VALUE:
1313 return match_permutation_array(&other_value, array_size, this, single_value.n_elements,
1314 match_function_specific, legacy);
1315 case OMIT_VALUE:
1316 return FALSE;
1317 case ANY_VALUE:
1318 case ANY_OR_OMIT:
1319 return TRUE;
1320 case VALUE_LIST:
1321 case COMPLEMENTED_LIST:
1322 for (unsigned int list_count = 0; list_count < value_list.n_values;
1323 list_count++)
1324 if (value_list.list_value[list_count].match(other_value, legacy))
1325 return template_selection == VALUE_LIST;
1326 return template_selection == COMPLEMENTED_LIST;
1327 default:
1328 TTCN_error("Matching with an uninitialized/unsupported array template.");
1329 }
1330 return FALSE;
1331 }
1332
1333 template <typename T_value_type, typename T_template_type,
1334 unsigned int array_size, int index_offset>
1335 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1336 is_value() const
1337 {
1338 if (template_selection != SPECIFIC_VALUE || is_ifpresent) return FALSE;
1339 for (int i=0; i<single_value.n_elements; i++)
1340 if (!single_value.value_elements[i]->is_value()) return FALSE;
1341 return TRUE;
1342 }
1343
1344 template <typename T_value_type, typename T_template_type,
1345 unsigned int array_size, int index_offset>
1346 VALUE_ARRAY<T_value_type, array_size, index_offset>
1347 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1348 valueof() const
1349 {
1350 if (template_selection != SPECIFIC_VALUE || is_ifpresent)
1351 TTCN_error("Performing a valueof or send operation on a "
1352 "non-specific array template.");
1353 // the size of the template must be the size of the value
1354 if (single_value.n_elements!=array_size)
1355 TTCN_error("Performing a valueof or send operation on a "
1356 "specific array template with invalid size.");
1357 VALUE_ARRAY<T_value_type, array_size, index_offset> ret_val;
1358 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++)
1359 ret_val.array_element(elem_count) =
1360 single_value.value_elements[elem_count]->valueof();
1361 return ret_val;
1362 }
1363
1364 template <typename T_value_type, typename T_template_type,
1365 unsigned int array_size, int index_offset>
1366 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1367 set_type(template_sel template_type, unsigned int list_length)
1368 {
1369 clean_up();
1370 switch (template_type) {
1371 case VALUE_LIST:
1372 case COMPLEMENTED_LIST:
1373 value_list.n_values = list_length;
1374 value_list.list_value = new TEMPLATE_ARRAY[list_length];
1375 break;
1376 default:
1377 TTCN_error(
1378 "Internal error: Setting an invalid type for an array template.");
1379 }
1380 set_selection(template_type);
1381 }
1382
1383 template <typename T_value_type, typename T_template_type,
1384 unsigned int array_size, int index_offset>
1385 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>&
1386 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1387 list_item(unsigned int list_index)
1388 {
1389 if (template_selection != VALUE_LIST &&
1390 template_selection != COMPLEMENTED_LIST)
1391 TTCN_error("Internal error: Accessing a list element of a non-list "
1392 "array template.");
1393 if (list_index >= value_list.n_values)
1394 TTCN_error("Internal error: Index overflow in a value list "
1395 "array template.");
1396 return value_list.list_value[list_index];
1397 }
1398
1399 template <typename T_value_type, typename T_template_type,
1400 unsigned int array_size, int index_offset>
1401 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1402 log() const
1403 {
1404 switch (template_selection)
1405 {
1406 case SPECIFIC_VALUE:
1407 if (single_value.n_elements > 0)
1408 {
1409 TTCN_Logger::log_event_str("{ ");
1410 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1411 {
1412 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1413 if (permutation_starts_at(elem_count)) TTCN_Logger::log_event_str("permutation(");
1414 single_value.value_elements[elem_count]->log();
1415 if (permutation_ends_at(elem_count)) TTCN_Logger::log_char(')');
1416 }
1417 TTCN_Logger::log_event_str(" }");
1418 }
1419 else
1420 TTCN_Logger::log_event_str("{ }");
1421 break;
1422 case COMPLEMENTED_LIST:
1423 TTCN_Logger::log_event_str("complement");
1424 case VALUE_LIST:
1425 TTCN_Logger::log_char('(');
1426 for (unsigned int list_count = 0; list_count < value_list.n_values;
1427 list_count++)
1428 {
1429 if (list_count > 0) TTCN_Logger::log_event_str(", ");
1430 value_list.list_value[list_count].log();
1431 }
1432 TTCN_Logger::log_char(')');
1433 break;
1434 default:
1435 log_generic();
1436 break;
1437 }
1438 log_restricted();
1439 log_ifpresent();
1440 }
1441
1442 template <typename T_value_type, typename T_template_type,
1443 unsigned int array_size, int index_offset>
1444 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1445 log_match(const VALUE_ARRAY<T_value_type, array_size, index_offset>&
1446 match_value, boolean legacy) const
1447 {
1448 if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){
1449 if(match(match_value, legacy)){
1450 TTCN_Logger::print_logmatch_buffer();
1451 TTCN_Logger::log_event_str(" matched");
1452 }else{
1453 if (template_selection == SPECIFIC_VALUE &&
1454 single_value.n_elements == array_size) {
1455 size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();
1456 for (unsigned int elem_count = 0; elem_count < array_size;
1457 elem_count++) {
1458 if(!single_value.value_elements[elem_count]->
1459 match(match_value.array_element(elem_count), legacy)){
1460 TTCN_Logger::log_logmatch_info("[%d]", elem_count);
1461 single_value.value_elements[elem_count]->
1462 log_match(match_value.array_element(elem_count), legacy);
1463 TTCN_Logger::set_logmatch_buffer_len(previous_size);
1464 }
1465 }
1466 log_match_length(array_size);
1467 } else {
1468 TTCN_Logger::print_logmatch_buffer();
1469 match_value.log();
1470 TTCN_Logger::log_event_str(" with ");
1471 log();
1472 TTCN_Logger::log_event_str(" unmatched");
1473 }
1474 }
1475 return;
1476 }
1477 if (template_selection == SPECIFIC_VALUE &&
1478 single_value.n_elements == array_size) {
1479 TTCN_Logger::log_event_str("{ ");
1480 for (unsigned int elem_count = 0; elem_count < array_size; elem_count++) {
1481 if (elem_count > 0) TTCN_Logger::log_event_str(", ");
1482 single_value.value_elements[elem_count]->log_match(
1483 match_value.array_element(elem_count), legacy);
1484 }
1485 TTCN_Logger::log_event_str(" }");
1486 log_match_length(array_size);
1487 } else {
1488 match_value.log();
1489 TTCN_Logger::log_event_str(" with ");
1490 log();
1491 if (match(match_value, legacy)) TTCN_Logger::log_event_str(" matched");
1492 else TTCN_Logger::log_event_str(" unmatched");
1493 }
1494 }
1495
1496 template <typename T_value_type, typename T_template_type, unsigned int array_size, int index_offset>
1497 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::set_param(Module_Param& param)
1498 {
1499 if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
1500 param.get_id()->next_name()) {
1501 // Haven't reached the end of the module parameter name
1502 // => the name refers to one of the elements, not to the whole array
1503 char* param_field = param.get_id()->get_current_name();
1504 if (param_field[0] < '0' || param_field[0] > '9') {
1505 param.error("Unexpected record field name in module parameter, expected a valid"
1506 " array template index");
1507 }
1508 unsigned int param_index = -1;
1509 sscanf(param_field, "%u", &param_index);
1510 if (param_index >= array_size) {
1511 param.error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1512 }
1513 (*this)[param_index].set_param(param);
1514 return;
1515 }
1516
1517 param.basic_check(Module_Param::BC_TEMPLATE, "array template");
1518
1519 Module_Param_Ptr mp = &param;
1520 if (param.get_type() == Module_Param::MP_Reference) {
1521 mp = param.get_referenced_param();
1522 }
1523
1524 switch (mp->get_type()) {
1525 case Module_Param::MP_Omit:
1526 *this = OMIT_VALUE;
1527 break;
1528 case Module_Param::MP_Any:
1529 *this = ANY_VALUE;
1530 break;
1531 case Module_Param::MP_AnyOrNone:
1532 *this = ANY_OR_OMIT;
1533 break;
1534 case Module_Param::MP_List_Template:
1535 case Module_Param::MP_ComplementList_Template: {
1536 TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset> temp;
1537 temp.set_type(mp->get_type() == Module_Param::MP_List_Template ?
1538 VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());
1539 for (size_t i=0; i<mp->get_size(); i++) {
1540 temp.list_item(i).set_param(*mp->get_elem(i));
1541 }
1542 *this = temp;
1543 break; }
1544 case Module_Param::MP_Value_List:
1545 set_size(mp->get_size());
1546 for (size_t i=0; i<mp->get_size(); ++i) {
1547 Module_Param* const curr = mp->get_elem(i);
1548 if (curr->get_type()!=Module_Param::MP_NotUsed) {
1549 (*this)[(int)i+index_offset].set_param(*curr);
1550 }
1551 }
1552 break;
1553 case Module_Param::MP_Indexed_List:
1554 for (size_t i=0; i<mp->get_size(); ++i) {
1555 Module_Param* const curr = mp->get_elem(i);
1556 (*this)[curr->get_id()->get_index()].set_param(*curr);
1557 }
1558 break;
1559 default:
1560 param.type_error("array template");
1561 }
1562 is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();
1563 }
1564
1565 template <typename T_value_type, typename T_template_type,
1566 unsigned int array_size, int index_offset>
1567 Module_Param* TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1568 get_param(Module_Param_Name& param_name) const
1569 {
1570 if (param_name.next_name()) {
1571 // Haven't reached the end of the module parameter name
1572 // => the name refers to one of the elements, not to the whole record of
1573 char* param_field = param_name.get_current_name();
1574 if (param_field[0] < '0' || param_field[0] > '9') {
1575 TTCN_error("Unexpected record field name in module parameter reference, "
1576 "expected a valid array index");
1577 }
1578 unsigned int param_index = -1;
1579 sscanf(param_field, "%u", &param_index);
1580 if (param_index >= array_size) {
1581 TTCN_error("Invalid array index: %u. The array only has %u elements.", param_index, array_size);
1582 }
1583 return single_value.value_elements[param_index]->get_param(param_name);
1584 }
1585 Module_Param* mp = NULL;
1586 switch (template_selection) {
1587 case UNINITIALIZED_TEMPLATE:
1588 mp = new Module_Param_Unbound();
1589 break;
1590 case OMIT_VALUE:
1591 mp = new Module_Param_Omit();
1592 break;
1593 case ANY_VALUE:
1594 mp = new Module_Param_Any();
1595 break;
1596 case ANY_OR_OMIT:
1597 mp = new Module_Param_AnyOrNone();
1598 break;
1599 case SPECIFIC_VALUE: {
1600 Vector<Module_Param*> values;
1601 for (int i = 0; i < array_size; ++i) {
1602 values.push_back(single_value.value_elements[i]->get_param(param_name));
1603 }
1604 mp = new Module_Param_Value_List();
1605 mp->add_list_with_implicit_ids(&values);
1606 values.clear();
1607 break; }
1608 case VALUE_LIST:
1609 case COMPLEMENTED_LIST: {
1610 if (template_selection == VALUE_LIST) {
1611 mp = new Module_Param_List_Template();
1612 }
1613 else {
1614 mp = new Module_Param_ComplementList_Template();
1615 }
1616 for (size_t i = 0; i < value_list.n_values; ++i) {
1617 mp->add_elem(value_list.list_value[i].get_param(param_name));
1618 }
1619 break; }
1620 default:
1621 break;
1622 }
1623 if (is_ifpresent) {
1624 mp->set_ifpresent();
1625 }
1626 return mp;
1627 }
1628
1629 template <typename T_value_type, typename T_template_type,
1630 unsigned int array_size, int index_offset>
1631 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1632 encode_text(Text_Buf& text_buf) const
1633 {
1634 encode_text_restricted(text_buf);
1635 switch (template_selection)
1636 {
1637 case SPECIFIC_VALUE:
1638 text_buf.push_int(single_value.n_elements);
1639 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1640 single_value.value_elements[elem_count]->encode_text(text_buf);
1641 break;
1642 case OMIT_VALUE:
1643 case ANY_VALUE:
1644 case ANY_OR_OMIT:
1645 break;
1646 case VALUE_LIST:
1647 case COMPLEMENTED_LIST:
1648 text_buf.push_int(value_list.n_values);
1649 for (unsigned int list_count = 0; list_count < value_list.n_values;
1650 list_count++)
1651 value_list.list_value[list_count].encode_text(text_buf);
1652 break;
1653 default:
1654 TTCN_error("Text encoder: Encoding an uninitialized/unsupported "
1655 "array template.");
1656 }
1657 }
1658
1659 template <typename T_value_type, typename T_template_type,
1660 unsigned int array_size, int index_offset>
1661 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1662 decode_text(Text_Buf& text_buf)
1663 {
1664 clean_up();
1665 decode_text_restricted(text_buf);
1666 switch (template_selection)
1667 {
1668 case SPECIFIC_VALUE:
1669 single_value.n_elements = text_buf.pull_int().get_val();
1670 if (single_value.n_elements < 0)
1671 TTCN_error("Text decoder: Negative size was received for an "
1672 "array template.");
1673 single_value.value_elements =
1674 (T_template_type**)allocate_pointers(single_value.n_elements);
1675 for (int elem_count=0; elem_count < single_value.n_elements; elem_count++)
1676 {
1677 single_value.value_elements[elem_count] = new T_template_type;
1678 single_value.value_elements[elem_count]->decode_text(text_buf);
1679 }
1680 break;
1681 case OMIT_VALUE:
1682 case ANY_VALUE:
1683 case ANY_OR_OMIT:
1684 break;
1685 case VALUE_LIST:
1686 case COMPLEMENTED_LIST:
1687 value_list.n_values = text_buf.pull_int().get_val();
1688 value_list.list_value = new TEMPLATE_ARRAY[value_list.n_values];
1689 for (unsigned int list_count = 0; list_count < value_list.n_values;
1690 list_count++)
1691 value_list.list_value[list_count].decode_text(text_buf);
1692 break;
1693 default:
1694 TTCN_error("Text decoder: An unknown/unsupported selection was received "
1695 "for an array template.");
1696 }
1697 }
1698
1699 template <typename T_value_type, typename T_template_type,
1700 unsigned int array_size, int index_offset>
1701 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1702 is_present(boolean legacy /* = FALSE */) const
1703 {
1704 if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;
1705 return !match_omit(legacy);
1706 }
1707
1708 template <typename T_value_type, typename T_template_type,
1709 unsigned int array_size, int index_offset>
1710 boolean TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1711 match_omit(boolean legacy /* = FALSE */) const
1712 {
1713 if (is_ifpresent) return TRUE;
1714 switch (template_selection) {
1715 case OMIT_VALUE:
1716 case ANY_OR_OMIT:
1717 return TRUE;
1718 case VALUE_LIST:
1719 case COMPLEMENTED_LIST:
1720 if (legacy) {
1721 // legacy behavior: 'omit' can appear in the value/complement list
1722 for (unsigned int i=0; i<value_list.n_values; i++)
1723 if (value_list.list_value[i].match_omit())
1724 return template_selection==VALUE_LIST;
1725 return template_selection==COMPLEMENTED_LIST;
1726 }
1727 // else fall through
1728 default:
1729 return FALSE;
1730 }
1731 return FALSE;
1732 }
1733
1734 #ifndef TITAN_RUNTIME_2
1735 template <typename T_value_type, typename T_template_type,
1736 unsigned int array_size, int index_offset>
1737 void TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>::
1738 check_restriction(template_res t_res, const char* t_name, boolean legacy /* = FALSE */) const
1739 {
1740 if (template_selection==UNINITIALIZED_TEMPLATE) return;
1741 switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {
1742 case TR_OMIT:
1743 if (template_selection==OMIT_VALUE) return;
1744 case TR_VALUE:
1745 if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;
1746 for (int i=0; i<single_value.n_elements; i++)
1747 single_value.value_elements[i]->check_restriction(t_res, t_name ? t_name : "array");
1748 return;
1749 case TR_PRESENT:
1750 if (!match_omit(legacy)) return;
1751 break;
1752 default:
1753 return;
1754 }
1755 TTCN_error("Restriction `%s' on template of type %s violated.",
1756 get_res_name(t_res), t_name ? t_name : "array");
1757 }
1758 #endif
1759
1760 template <typename T_value_type, typename T_template_type,
1761 unsigned int array_size, int index_offset>
1762 answer recursive_permutation_match(const Base_Type *value_ptr,
1763 unsigned int value_start_index,
1764 unsigned int value_size,
1765 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>*template_ptr,
1766 unsigned int template_start_index,
1767 unsigned int template_size,
1768 unsigned int permutation_index,
1769 match_function_t match_function,
1770 unsigned int& shift_size,
1771 boolean legacy)
1772 {
1773 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
1774 if (permutation_index > nof_permutations)
1775 TTCN_error("Internal error: recursive_permutation_match: "
1776 "invalid argument.");
1777
1778 if (permutation_index < nof_permutations &&
1779 template_ptr->get_permutation_end(permutation_index) >
1780 template_start_index + template_size)
1781 TTCN_error("Internal error: recursive_permutation_match: wrong "
1782 "permutation interval settings for permutation %d.",
1783 permutation_index);
1784
1785 shift_size = 0;
1786
1787 //trivial cases
1788 if(template_size == 0)
1789 {
1790 //reached the end of templates
1791 // if we reached the end of values => good
1792 // else => bad
1793 if(value_size == 0)
1794 return SUCCESS;
1795 else
1796 return FAILURE;
1797 }
1798
1799 //are we at an asterisk or at the beginning of a permutation interval
1800 boolean is_asterisk;
1801 boolean permutation_begins = permutation_index < nof_permutations &&
1802 template_start_index ==
1803 template_ptr->get_permutation_start(permutation_index);
1804
1805 if (permutation_begins ||
1806 match_function(value_ptr, -1, template_ptr, template_start_index, legacy))
1807 {
1808 unsigned int smallest_possible_size;
1809 unsigned int largest_possible_size;
1810 boolean has_asterisk;
1811 boolean already_superset;
1812 unsigned int permutation_size;
1813
1814 //check how many values might be associated with this permutation
1815 //if we are at a permutation start
1816 if (permutation_begins)
1817 {
1818 is_asterisk = FALSE;
1819 permutation_size =
1820 template_ptr->get_permutation_size(permutation_index);
1821 smallest_possible_size = 0;
1822 has_asterisk = FALSE;
1823
1824 //count how many non asterisk elements are in the permutation
1825 for(unsigned int i = 0; i < permutation_size; i++)
1826 {
1827 if(match_function(value_ptr, -1, template_ptr,
1828 i + template_start_index, legacy))
1829 {
1830 has_asterisk = TRUE;
1831 }else{
1832 smallest_possible_size++;
1833 }
1834 }
1835
1836 //the real permutation size is bigger then the value size
1837 if(smallest_possible_size > value_size)
1838 return NO_CHANCE;
1839
1840 //if the permutation has an asterisk then it can grow
1841 if(has_asterisk)
1842 {
1843 largest_possible_size = value_size;
1844
1845 //if there are only asterisks in the permutation
1846 if(smallest_possible_size == 0)
1847 already_superset = TRUE;
1848 else
1849 already_superset = FALSE;
1850 }else{
1851 //without asterisks its size is fixed
1852 largest_possible_size = smallest_possible_size;
1853 already_superset = FALSE;
1854 }
1855 }else{
1856 //or at an asterisk
1857 is_asterisk = TRUE;
1858 already_superset = TRUE;
1859 permutation_size = 1;
1860 smallest_possible_size = 0;
1861 largest_possible_size = value_size;
1862 has_asterisk = TRUE;
1863 }
1864
1865 unsigned int temp_size = smallest_possible_size;
1866
1867 {
1868 //this is to make match_set_of incremental,
1869 // we store the already found pairs in this vector
1870 // so we wouldn't try to find a pair for those templates again
1871 // and we can set the covered state of values too
1872 // to not waste memory it is only created if needed
1873 int* pair_list = NULL;
1874 unsigned int old_temp_size = 0;
1875
1876 if(!already_superset)
1877 {
1878 pair_list = new int[permutation_size];
1879 for(unsigned int i = 0 ; i < permutation_size; i++)
1880 {
1881 //in the beginning we haven't found a template to any values
1882 pair_list[i] = -1;
1883 }
1884 }
1885
1886 while(!already_superset)
1887 {
1888 //must be a permutation having other values than asterisks
1889
1890 int x = 0;
1891
1892 //our set matching is extended with 2 more parameters
1893 // giving back how many templates
1894 // (other than asterisk) couldn't be matched
1895 // and setting / giving back the value-template pairs
1896
1897 boolean found = match_set_of_internal(value_ptr, value_start_index,
1898 temp_size, template_ptr,
1899 template_start_index, permutation_size,
1900 match_function, SUPERSET, &x, pair_list, old_temp_size, legacy);
1901
1902 if(found)
1903 {
1904 already_superset = TRUE;
1905 }else{
1906 //as we didn't found a match we have to try
1907 // a larger set of values
1908 //x is the number of templates we couldn't find
1909 // a matching pair for
1910 // the next must be at least this big to fully cover
1911 // on the other side if it would be bigger than it might miss
1912 // the smallest possible match.
1913
1914 //if we can match with more values
1915 if(has_asterisk && temp_size + x <= largest_possible_size)
1916 {
1917 old_temp_size = temp_size;
1918 temp_size += x;
1919 }else{
1920 delete[] pair_list;
1921 return FAILURE; //else we failed
1922 }
1923 }
1924 }
1925
1926 delete[] pair_list;
1927 }
1928
1929 //we reach here only if we found a match
1930
1931 //can only go on recursively if we haven't reached the end
1932
1933 //reached the end of templates
1934 if(permutation_size == template_size)
1935 {
1936 if(has_asterisk || value_size == temp_size)
1937 return SUCCESS;
1938 else
1939 return FAILURE;
1940 }
1941
1942 for(unsigned int i = temp_size; i <= largest_possible_size;)
1943 {
1944 answer result;
1945
1946 if(is_asterisk)
1947 {
1948 //don't step the permutation index
1949 result = recursive_permutation_match(value_ptr,value_start_index+i,
1950 value_size - i, template_ptr,
1951 template_start_index +
1952 permutation_size,
1953 template_size -
1954 permutation_size,
1955 permutation_index,
1956 match_function, shift_size, legacy);
1957 }else{
1958 //try with the next permutation
1959 result = recursive_permutation_match(value_ptr,value_start_index+i,
1960 value_size - i, template_ptr,
1961 template_start_index +
1962 permutation_size,
1963 template_size - permutation_size,
1964 permutation_index + 1,
1965 match_function, shift_size, legacy);
1966 }
1967
1968 if(result == SUCCESS)
1969 return SUCCESS; //we finished
1970 else if(result == NO_CHANCE)
1971 return NO_CHANCE; //matching is not possible
1972 else if(i == value_size) //we failed
1973 {
1974 //if there is no chance of matching
1975 return NO_CHANCE;
1976 }else{
1977 i += shift_size > 1 ? shift_size : 1;
1978
1979 if(i > largest_possible_size)
1980 shift_size = i - largest_possible_size;
1981 else
1982 shift_size = 0;
1983 }
1984 }
1985
1986 //this level failed;
1987 return FAILURE;
1988 }else{
1989 //we are at the beginning of a non permutation, non asterisk interval
1990
1991 //the distance to the next permutation or the end of templates
1992 // so the longest possible match
1993 unsigned int distance;
1994
1995 if (permutation_index < nof_permutations)
1996 {
1997 distance = template_ptr->get_permutation_start(permutation_index)
1998 - template_start_index;
1999 }else{
2000 distance = template_size;
2001 }
2002
2003 //if there are no more values, but we still have templates
2004 // and the template is not an asterisk or a permutation start
2005 if(value_size == 0)
2006 return FAILURE;
2007
2008 //we try to match as many values as possible
2009 //an asterisk is handled like a 0 length permutation
2010 boolean good;
2011 unsigned int i = 0;
2012 do{
2013 good = match_function(value_ptr, value_start_index + i,
2014 template_ptr, template_start_index + i, legacy);
2015 i++;
2016 //bad stop: something can't be matched
2017 //half bad half good stop: the end of values is reached
2018 //good stop: matching on the full distance or till an asterisk
2019 }while(good && i < value_size && i < distance &&
2020 !match_function(value_ptr, -1, template_ptr,
2021 template_start_index + i, legacy));
2022
2023 //if we matched on the full distance or till an asterisk
2024 if(good && (i == distance ||
2025 match_function(value_ptr, -1, template_ptr,
2026 template_start_index + i, legacy)))
2027 {
2028 //reached the end of the templates
2029 if(i == template_size)
2030 {
2031 if(i < value_size)
2032 {
2033 //the next level would return FAILURE so we don't step it
2034 return FAILURE;
2035 }else{
2036 //i == value_size, so we matched everything
2037 return SUCCESS;
2038 }
2039 }else{
2040 //we reached the next asterisk or permutation,
2041 // so step to the next level
2042 return recursive_permutation_match(value_ptr,value_start_index + i,
2043 value_size - i,
2044 template_ptr,
2045 template_start_index + i,
2046 template_size - i,
2047 permutation_index,
2048 match_function, shift_size, legacy);
2049 }
2050 }else{
2051 //something bad happened, so we have to check how bad the situation is
2052 if( i == value_size)
2053 {
2054 //the aren't values left, meaning that the match is not possible
2055 return NO_CHANCE;
2056 }else{
2057 //we couldn't match, but there is still a chance of matching
2058
2059 //try to find a matching value for the last checked (and failed)
2060 // template.
2061 // smaller jumps would fail so we skip them
2062 shift_size = 0;
2063 i--;
2064 do{
2065 good = match_function(value_ptr,
2066 value_start_index + i + shift_size,
2067 template_ptr, template_start_index + i, legacy);
2068 shift_size++;
2069 }while(!good && i + shift_size < value_size);
2070
2071 if(good)
2072 {
2073 shift_size--;
2074 return FAILURE;
2075 }else{
2076 // the template can not be matched later
2077 return NO_CHANCE;
2078 }
2079 }
2080 }
2081 }
2082 }
2083
2084 template <typename T_value_type, typename T_template_type,
2085 unsigned int array_size, int index_offset>
2086 boolean match_permutation_array(const Base_Type *value_ptr,
2087 int value_size,
2088 const TEMPLATE_ARRAY<T_value_type,T_template_type,array_size,index_offset>* template_ptr,
2089 int template_size,
2090 match_function_t match_function,
2091 boolean legacy)
2092 {
2093 if (value_ptr == NULL || value_size < 0 ||
2094 template_ptr == NULL || template_size < 0 ||
2095 template_ptr->get_selection() != SPECIFIC_VALUE)
2096 TTCN_error("Internal error: match_permutation_arry: invalid argument.");
2097
2098 unsigned int nof_permutations = template_ptr->get_number_of_permutations();
2099 // use the simplified algorithm if the template does not contain permutation
2100 if (nof_permutations == 0)
2101 return match_array(value_ptr, value_size,
2102 template_ptr, template_size, match_function, legacy);
2103 // use 'set of' matching if all template elements are grouped into one
2104 // permutation
2105 if (nof_permutations == 1 && template_ptr->get_permutation_start(0) == 0 &&
2106 template_ptr->get_permutation_end(0) ==
2107 (unsigned int)(template_size - 1))
2108 return match_set_of(value_ptr, value_size, template_ptr, template_size,
2109 match_function, legacy);
2110
2111 unsigned int shift_size = 0;
2112 return recursive_permutation_match(value_ptr, 0, value_size, template_ptr,
2113 0, template_size, 0, match_function, shift_size, legacy) == SUCCESS;
2114 }
2115
2116 #endif
This page took 0.072134 seconds and 6 git commands to generate.