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