1 // Copyright Maciej Sobczak 2008-2019.
2 // This file is part of YAMI4.
3 //
4 // YAMI4 is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // YAMI4 is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with YAMI4.  If not, see <http://www.gnu.org/licenses/>.
16 
17 #include "parameters.h"
18 #include "fatal_errors.h"
19 #include "parameter_entry.h"
20 #include "parameter_iterator.h"
21 #include "parameters-details.h"
22 #include <cstring>
23 #include <new>
24 
25 using namespace yami;
26 using namespace yami::core;
27 
parameters(void * working_area,std::size_t area_size)28 parameters::parameters(void * working_area, std::size_t area_size)
29     : own_allocator_(), allocator_(own_allocator_),
30       uses_private_area_(area_size > 0),
31       data_(NULL), num_of_entries_(0)
32 {
33     own_allocator_.set_working_area(working_area, area_size);
34 }
35 
parameters(details::allocator & alloc,bool private_area)36 parameters::parameters(details::allocator & alloc, bool private_area)
37     : own_allocator_(), allocator_(alloc),
38       uses_private_area_(private_area),
39       data_(NULL), num_of_entries_(0)
40 {
41 }
42 
~parameters()43 parameters::~parameters()
44 {
45     if (uses_private_area_ == false)
46     {
47         // this object uses global dynamic memory
48 
49         clear();
50     }
51 }
52 
clear()53 void parameters::clear()
54 {
55     for (size_t i = 0; i != num_of_entries_; ++i)
56     {
57         details::entry & e = data_[i];
58 
59         if (e.type != unused)
60         {
61             e.clear_name(allocator_);
62 
63             // this is recursive for nested parameters:
64             e.clear_item(allocator_);
65         }
66     }
67 
68     if (data_ != NULL)
69     {
70         allocator_.deallocate(data_);
71         data_ = NULL;
72 
73         num_of_entries_ = 0;
74     }
75 }
76 
set_boolean(const char * name,std::size_t name_length,bool value)77 result parameters::set_boolean(const char * name, std::size_t name_length,
78     bool value)
79 {
80     std::size_t index;
81     const result res = details::prepare_for_set(data_, num_of_entries_,
82         name, name_length, index, allocator_);
83 
84     if (res == ok)
85     {
86         details::entry & e = data_[index];
87 
88         e.type = boolean;
89         e.item.b = value;
90     }
91 
92     return res;
93 }
94 
set_boolean(const char * name,bool value)95 result parameters::set_boolean(const char * name, bool value)
96 {
97     return set_boolean(name, std::strlen(name), value);
98 }
99 
get_boolean(const char * name,std::size_t name_length,bool & value) const100 result parameters::get_boolean(const char * name, std::size_t name_length,
101     bool & value) const
102 {
103     result res;
104     const std::size_t index = details::find_entry(data_, num_of_entries_,
105         name, name_length);
106     if (index != num_of_entries_)
107     {
108         const details::entry & e = data_[index];
109         if (e.type == boolean)
110         {
111             value = e.item.b;
112             res = ok;
113         }
114         else
115         {
116             res = bad_type;
117         }
118     }
119     else
120     {
121         res = no_such_name;
122     }
123 
124     return res;
125 }
126 
get_boolean(const char * name,bool & value) const127 result parameters::get_boolean(const char * name, bool & value) const
128 {
129     return get_boolean(name, std::strlen(name), value);
130 }
131 
set_integer(const char * name,std::size_t name_length,int value)132 result parameters::set_integer(const char * name, std::size_t name_length,
133     int value)
134 {
135     std::size_t index;
136     const result res = details::prepare_for_set(data_, num_of_entries_,
137         name, name_length, index, allocator_);
138 
139     if (res == ok)
140     {
141         details::entry & e = data_[index];
142 
143         e.type = integer;
144         e.item.i = value;
145     }
146 
147     return res;
148 }
149 
set_integer(const char * name,int value)150 result parameters::set_integer(const char * name, int value)
151 {
152     return set_integer(name, std::strlen(name), value);
153 }
154 
get_integer(const char * name,std::size_t name_length,int & value) const155 result parameters::get_integer(const char * name, std::size_t name_length,
156     int & value) const
157 {
158     result res;
159     const std::size_t index = details::find_entry(data_, num_of_entries_,
160         name, name_length);
161     if (index != num_of_entries_)
162     {
163         const details::entry & e = data_[index];
164         if (e.type == integer)
165         {
166             value = e.item.i;
167             res = ok;
168         }
169         else
170         {
171             res = bad_type;
172         }
173     }
174     else
175     {
176         res = no_such_name;
177     }
178 
179     return res;
180 }
181 
get_integer(const char * name,int & value) const182 result parameters::get_integer(const char * name, int & value) const
183 {
184     return get_integer(name, std::strlen(name), value);
185 }
186 
set_long_long(const char * name,std::size_t name_length,long long value)187 result parameters::set_long_long(const char * name, std::size_t name_length,
188     long long value)
189 {
190     std::size_t index;
191     const result res = details::prepare_for_set(data_, num_of_entries_,
192         name, name_length, index, allocator_);
193 
194     if (res == ok)
195     {
196         details::entry & e = data_[index];
197 
198         e.type = long_long;
199         e.item.L = value;
200     }
201 
202     return res;
203 }
204 
set_long_long(const char * name,long long value)205 result parameters::set_long_long(const char * name, long long value)
206 {
207     return set_long_long(name, std::strlen(name), value);
208 }
209 
get_long_long(const char * name,std::size_t name_length,long long & value) const210 result parameters::get_long_long(const char * name, std::size_t name_length,
211     long long & value) const
212 {
213     result res;
214     const std::size_t index = details::find_entry(data_, num_of_entries_,
215         name, name_length);
216     if (index != num_of_entries_)
217     {
218         const details::entry & e = data_[index];
219         if (e.type == long_long)
220         {
221             value = e.item.L;
222             res = ok;
223         }
224         else
225         {
226             res = bad_type;
227         }
228     }
229     else
230     {
231         res = no_such_name;
232     }
233 
234     return res;
235 }
236 
get_long_long(const char * name,long long & value) const237 result parameters::get_long_long(const char * name, long long & value) const
238 {
239     return get_long_long(name, std::strlen(name), value);
240 }
241 
set_double_float(const char * name,std::size_t name_length,double value)242 result parameters::set_double_float(
243     const char * name, std::size_t name_length, double value)
244 {
245     std::size_t index;
246     const result res = details::prepare_for_set(data_, num_of_entries_,
247         name, name_length, index, allocator_);
248 
249     if (res == ok)
250     {
251         details::entry & e = data_[index];
252 
253         e.type = double_float;
254         e.item.d = value;
255     }
256 
257     return res;
258 }
259 
set_double_float(const char * name,double value)260 result parameters::set_double_float(const char * name, double value)
261 {
262     return set_double_float(name, std::strlen(name), value);
263 }
264 
get_double_float(const char * name,std::size_t name_length,double & value) const265 result parameters::get_double_float(
266     const char * name, std::size_t name_length, double & value) const
267 {
268     result res;
269     const std::size_t index = details::find_entry(data_, num_of_entries_,
270         name, name_length);
271     if (index != num_of_entries_)
272     {
273         const details::entry & e = data_[index];
274         if (e.type == double_float)
275         {
276             value = e.item.d;
277             res = ok;
278         }
279         else
280         {
281             res = bad_type;
282         }
283     }
284     else
285     {
286         res = no_such_name;
287     }
288 
289     return res;
290 }
291 
get_double_float(const char * name,double & value) const292 result parameters::get_double_float(const char * name, double & value) const
293 {
294     return get_double_float(name, std::strlen(name), value);
295 }
296 
set_string(const char * name,std::size_t name_length,const char * value,std::size_t value_length)297 result parameters::set_string(const char * name, std::size_t name_length,
298     const char * value, std::size_t value_length)
299 {
300     result res;
301 
302     char * new_buffer =
303         static_cast<char *>(allocator_.allocate(value_length));
304     if (new_buffer != NULL)
305     {
306         std::memcpy(new_buffer, value, value_length);
307 
308         res = details::do_set_string(name, name_length,
309             new_buffer, value_length,
310             data_, num_of_entries_, allocator_, true);
311 
312         if (res != ok)
313         {
314             allocator_.deallocate(new_buffer);
315         }
316     }
317     else
318     {
319         res = no_memory;
320     }
321 
322     return res;
323 }
324 
set_string(const char * name,const char * value)325 result parameters::set_string(const char * name, const char * value)
326 {
327     return set_string(name, std::strlen(name), value, std::strlen(value));
328 }
329 
set_string_shallow(const char * name,std::size_t name_length,const char * value,std::size_t value_length)330 result parameters::set_string_shallow(
331     const char * name, std::size_t name_length,
332     const char * value, std::size_t value_length)
333 {
334     const result res = details::do_set_string(name, name_length,
335         value, value_length,
336         data_, num_of_entries_, allocator_, false);
337 
338     return res;
339 }
340 
set_string_shallow(const char * name,const char * value)341 result parameters::set_string_shallow(const char * name, const char * value)
342 {
343     return set_string_shallow(name, std::strlen(name),
344         value, std::strlen(value));
345 }
346 
get_string(const char * name,std::size_t name_length,const char * & value,std::size_t & value_length) const347 result parameters::get_string(const char * name, std::size_t name_length,
348     const char * & value, std::size_t & value_length) const
349 {
350     result res;
351     const std::size_t index = details::find_entry(data_, num_of_entries_,
352         name, name_length);
353     if (index != num_of_entries_)
354     {
355         const details::entry & e = data_[index];
356         if (e.type == string)
357         {
358             value = e.item.str.value;
359             value_length = e.item.str.length;
360             res = ok;
361         }
362         else
363         {
364             res = bad_type;
365         }
366     }
367     else
368     {
369         res = no_such_name;
370     }
371 
372     return res;
373 }
374 
get_string(const char * name,const char * & value,std::size_t & value_length) const375 result parameters::get_string(const char * name,
376     const char * & value, std::size_t & value_length) const
377 {
378     return get_string(name, std::strlen(name), value, value_length);
379 }
380 
set_binary(const char * name,std::size_t name_length,const void * value,std::size_t value_length)381 result parameters::set_binary(const char * name, std::size_t name_length,
382     const void * value, std::size_t value_length)
383 {
384     result res;
385 
386     void * new_buffer = allocator_.allocate(value_length);
387     if (new_buffer != NULL)
388     {
389         std::memcpy(new_buffer, value, value_length);
390 
391         res = details::do_set_binary(name, name_length,
392             new_buffer, value_length,
393             data_, num_of_entries_, allocator_, true);
394 
395         if (res != ok)
396         {
397             allocator_.deallocate(new_buffer);
398         }
399     }
400     else
401     {
402         res = no_memory;
403     }
404 
405     return res;
406 }
407 
set_binary(const char * name,const void * value,std::size_t value_length)408 result parameters::set_binary(const char * name,
409     const void * value, std::size_t value_length)
410 {
411     return set_binary(name, std::strlen(name), value, value_length);
412 }
413 
set_binary_shallow(const char * name,std::size_t name_length,const void * value,std::size_t value_length)414 result parameters::set_binary_shallow(
415     const char * name, std::size_t name_length,
416     const void * value, std::size_t value_length)
417 {
418     const result res = details::do_set_binary(name, name_length,
419         value, value_length,
420         data_, num_of_entries_, allocator_, false);
421 
422     return res;
423 }
424 
set_binary_shallow(const char * name,const void * value,std::size_t value_length)425 result parameters::set_binary_shallow(const char * name,
426     const void * value, std::size_t value_length)
427 {
428     return set_binary_shallow(name, std::strlen(name),
429         value, value_length);
430 }
431 
get_binary(const char * name,std::size_t name_length,const void * & value,std::size_t & value_length) const432 result parameters::get_binary(const char * name, std::size_t name_length,
433     const void * & value, std::size_t & value_length) const
434 {
435     result res;
436     const std::size_t index = details::find_entry(data_, num_of_entries_,
437         name, name_length);
438     if (index != num_of_entries_)
439     {
440         const details::entry & e = data_[index];
441         if (e.type == binary)
442         {
443             value = e.item.bin.value;
444             value_length = e.item.bin.length;
445             res = ok;
446         }
447         else
448         {
449             res = bad_type;
450         }
451     }
452     else
453     {
454         res = no_such_name;
455     }
456 
457     return res;
458 }
459 
get_binary(const char * name,const void * & value,std::size_t & value_length) const460 result parameters::get_binary(const char * name,
461     const void * & value, std::size_t & value_length) const
462 {
463     return get_binary(name, std::strlen(name), value, value_length);
464 }
465 
set_boolean_array(const char * name,std::size_t name_length,const bool * values,std::size_t array_length)466 result parameters::set_boolean_array(
467     const char * name, std::size_t name_length,
468     const bool * values, std::size_t array_length)
469 {
470     result res;
471 
472     const std::size_t raw_length = array_length * sizeof(bool);
473     bool * new_array =
474         static_cast<bool *>(allocator_.allocate(raw_length));
475     if (new_array != NULL)
476     {
477         std::memcpy(new_array, values, raw_length);
478 
479         res = details::do_set_boolean_array(name, name_length,
480             new_array, array_length,
481             data_, num_of_entries_, allocator_, true);
482 
483         if (res != ok)
484         {
485             allocator_.deallocate(new_array);
486         }
487     }
488     else
489     {
490         res = no_memory;
491     }
492 
493     return res;
494 }
495 
set_boolean_array(const char * name,const bool * values,std::size_t array_length)496 result parameters::set_boolean_array(const char * name,
497     const bool * values, std::size_t array_length)
498 {
499     return set_boolean_array(name, std::strlen(name), values, array_length);
500 }
501 
set_boolean_array_shallow(const char * name,std::size_t name_length,const bool * values,std::size_t array_length)502 result parameters::set_boolean_array_shallow(
503     const char * name, std::size_t name_length,
504     const bool * values, std::size_t array_length)
505 {
506     const result res = details::do_set_boolean_array(name, name_length,
507         values, array_length,
508         data_, num_of_entries_, allocator_, false);
509 
510     return res;
511 }
512 
set_boolean_array_shallow(const char * name,const bool * values,std::size_t array_length)513 result parameters::set_boolean_array_shallow(const char * name,
514     const bool * values, std::size_t array_length)
515 {
516     return set_boolean_array_shallow(name, std::strlen(name),
517         values, array_length);
518 }
519 
create_boolean_array(const char * name,std::size_t name_length,std::size_t array_length,bool * & array)520 result parameters::create_boolean_array(
521     const char * name, std::size_t name_length,
522     std::size_t array_length, bool * & array)
523 {
524     result res;
525 
526     const std::size_t raw_length = array_length * sizeof(bool);
527     bool * new_array =
528         static_cast<bool *>(allocator_.allocate(raw_length));
529     if (new_array != NULL)
530     {
531         res = details::do_set_boolean_array(name, name_length,
532             new_array, array_length,
533             data_, num_of_entries_, allocator_, true);
534 
535         if (res == ok)
536         {
537             array = new_array;
538         }
539         else
540         {
541             allocator_.deallocate(new_array);
542         }
543     }
544     else
545     {
546         res = no_memory;
547     }
548 
549     return res;
550 }
551 
create_boolean_array(const char * name,std::size_t array_length,bool * & array)552 result parameters::create_boolean_array(const char * name,
553     std::size_t array_length, bool * & array)
554 {
555     return create_boolean_array(name, std::strlen(name), array_length, array);
556 }
557 
get_boolean_array(const char * name,std::size_t name_length,bool * & values,std::size_t & array_length) const558 result parameters::get_boolean_array(
559     const char * name, std::size_t name_length,
560     bool * & values, std::size_t & array_length) const
561 {
562     result res;
563     const std::size_t index = details::find_entry(data_, num_of_entries_,
564         name, name_length);
565     if (index != num_of_entries_)
566     {
567         const details::entry & e = data_[index];
568         if (e.type == boolean_array)
569         {
570             values = e.item.ba.values;
571             array_length = e.item.ba.length;
572             res = ok;
573         }
574         else
575         {
576             res = bad_type;
577         }
578     }
579     else
580     {
581         res = no_such_name;
582     }
583 
584     return res;
585 }
586 
get_boolean_array(const char * name,bool * & values,std::size_t & array_length) const587 result parameters::get_boolean_array(const char * name,
588     bool * & values, std::size_t & array_length) const
589 {
590     return get_boolean_array(name, std::strlen(name), values, array_length);
591 }
592 
set_integer_array(const char * name,std::size_t name_length,const int * values,std::size_t array_length)593 result parameters::set_integer_array(
594     const char * name, std::size_t name_length,
595     const int * values, std::size_t array_length)
596 {
597     result res;
598 
599     const std::size_t raw_length = array_length * sizeof(int);
600     int * new_array =
601         static_cast<int *>(allocator_.allocate(raw_length));
602     if (new_array != NULL)
603     {
604         std::memcpy(new_array, values, raw_length);
605 
606         res = details::do_set_integer_array(name, name_length,
607             new_array, array_length,
608             data_, num_of_entries_, allocator_, true);
609 
610         if (res != ok)
611         {
612             allocator_.deallocate(new_array);
613         }
614     }
615     else
616     {
617         res = no_memory;
618     }
619 
620     return res;
621 }
622 
set_integer_array(const char * name,const int * values,std::size_t array_length)623 result parameters::set_integer_array(const char * name,
624     const int * values, std::size_t array_length)
625 {
626     return set_integer_array(name, std::strlen(name), values, array_length);
627 }
628 
set_integer_array_shallow(const char * name,std::size_t name_length,const int * values,std::size_t array_length)629 result parameters::set_integer_array_shallow(
630     const char * name, std::size_t name_length,
631     const int * values, std::size_t array_length)
632 {
633     const result res = details::do_set_integer_array(name, name_length,
634         values, array_length,
635         data_, num_of_entries_, allocator_, false);
636 
637     return res;
638 }
639 
set_integer_array_shallow(const char * name,const int * values,std::size_t array_length)640 result parameters::set_integer_array_shallow(const char * name,
641     const int * values, std::size_t array_length)
642 {
643     return set_integer_array_shallow(name, std::strlen(name),
644         values, array_length);
645 }
646 
create_integer_array(const char * name,std::size_t name_length,std::size_t array_length,int * & array)647 result parameters::create_integer_array(
648     const char * name, std::size_t name_length,
649     std::size_t array_length, int * & array)
650 {
651     result res;
652 
653     const std::size_t raw_length = array_length * sizeof(int);
654     int * new_array =
655         static_cast<int *>(allocator_.allocate(raw_length));
656     if (new_array != NULL)
657     {
658         res = details::do_set_integer_array(name, name_length,
659             new_array, array_length,
660             data_, num_of_entries_, allocator_, true);
661 
662         if (res == ok)
663         {
664             array = new_array;
665         }
666         else
667         {
668             allocator_.deallocate(new_array);
669         }
670     }
671     else
672     {
673         res = no_memory;
674     }
675 
676     return res;
677 }
678 
create_integer_array(const char * name,std::size_t array_length,int * & array)679 result parameters::create_integer_array(const char * name,
680     std::size_t array_length, int * & array)
681 {
682     return create_integer_array(name, std::strlen(name), array_length, array);
683 }
684 
get_integer_array(const char * name,std::size_t name_length,int * & values,std::size_t & array_length) const685 result parameters::get_integer_array(
686     const char * name, std::size_t name_length,
687     int * & values, std::size_t & array_length) const
688 {
689     result res;
690     const std::size_t index = details::find_entry(data_, num_of_entries_,
691         name, name_length);
692     if (index != num_of_entries_)
693     {
694         const details::entry & e = data_[index];
695         if (e.type == integer_array)
696         {
697             values = e.item.ia.values;
698             array_length = e.item.ia.length;
699             res = ok;
700         }
701         else
702         {
703             res = bad_type;
704         }
705     }
706     else
707     {
708         res = no_such_name;
709     }
710 
711     return res;
712 }
713 
get_integer_array(const char * name,int * & values,std::size_t & array_length) const714 result parameters::get_integer_array(const char * name,
715     int * & values, std::size_t & array_length) const
716 {
717     return get_integer_array(name, std::strlen(name), values, array_length);
718 }
719 
set_long_long_array(const char * name,std::size_t name_length,const long long * values,std::size_t array_length)720 result parameters::set_long_long_array(
721     const char * name, std::size_t name_length,
722     const long long * values, std::size_t array_length)
723 {
724     result res;
725 
726     const std::size_t raw_length = array_length * sizeof(long long);
727     long long * new_array =
728         static_cast<long long *>(allocator_.allocate(raw_length));
729     if (new_array != NULL)
730     {
731         std::memcpy(new_array, values, raw_length);
732 
733         res = details::do_set_long_long_array(name, name_length,
734             new_array, array_length,
735             data_, num_of_entries_, allocator_, true);
736 
737         if (res != ok)
738         {
739             allocator_.deallocate(new_array);
740         }
741     }
742     else
743     {
744         res = no_memory;
745     }
746 
747     return res;
748 }
749 
set_long_long_array(const char * name,const long long * values,std::size_t array_length)750 result parameters::set_long_long_array(const char * name,
751     const long long * values, std::size_t array_length)
752 {
753     return set_long_long_array(name, std::strlen(name), values, array_length);
754 }
755 
set_long_long_array_shallow(const char * name,std::size_t name_length,const long long * values,std::size_t array_length)756 result parameters::set_long_long_array_shallow(
757     const char * name, std::size_t name_length,
758     const long long * values, std::size_t array_length)
759 {
760     const result res = details::do_set_long_long_array(name, name_length,
761         values, array_length,
762         data_, num_of_entries_, allocator_, false);
763 
764     return res;
765 }
766 
set_long_long_array_shallow(const char * name,const long long * values,std::size_t array_length)767 result parameters::set_long_long_array_shallow(const char * name,
768     const long long * values, std::size_t array_length)
769 {
770     return set_long_long_array_shallow(name, std::strlen(name),
771         values, array_length);
772 }
773 
create_long_long_array(const char * name,std::size_t name_length,std::size_t array_length,long long * & array)774 result parameters::create_long_long_array(
775     const char * name, std::size_t name_length,
776     std::size_t array_length, long long * & array)
777 {
778     result res;
779 
780     const std::size_t raw_length = array_length * sizeof(long long);
781     long long * new_array =
782         static_cast<long long *>(allocator_.allocate(raw_length));
783     if (new_array != NULL)
784     {
785         res = details::do_set_long_long_array(name, name_length,
786             new_array, array_length,
787             data_, num_of_entries_, allocator_, true);
788 
789         if (res == ok)
790         {
791             array = new_array;
792         }
793         else
794         {
795             allocator_.deallocate(new_array);
796         }
797     }
798     else
799     {
800         res = no_memory;
801     }
802 
803     return res;
804 }
805 
create_long_long_array(const char * name,std::size_t array_length,long long * & array)806 result parameters::create_long_long_array(const char * name,
807     std::size_t array_length, long long * & array)
808 {
809     return create_long_long_array(name, std::strlen(name),
810         array_length, array);
811 }
812 
get_long_long_array(const char * name,std::size_t name_length,long long * & values,std::size_t & array_length) const813 result parameters::get_long_long_array(
814     const char * name, std::size_t name_length,
815     long long * & values, std::size_t & array_length) const
816 {
817     result res;
818     const std::size_t index = details::find_entry(data_, num_of_entries_,
819         name, name_length);
820     if (index != num_of_entries_)
821     {
822         const details::entry & e = data_[index];
823         if (e.type == long_long_array)
824         {
825             values = e.item.La.values;
826             array_length = e.item.La.length;
827             res = ok;
828         }
829         else
830         {
831             res = bad_type;
832         }
833     }
834     else
835     {
836         res = no_such_name;
837     }
838 
839     return res;
840 }
841 
get_long_long_array(const char * name,long long * & values,std::size_t & array_length) const842 result parameters::get_long_long_array(const char * name,
843     long long * & values, std::size_t & array_length) const
844 {
845     return get_long_long_array(name, std::strlen(name), values, array_length);
846 }
847 
set_double_float_array(const char * name,std::size_t name_length,const double * values,std::size_t array_length)848 result parameters::set_double_float_array(
849     const char * name, std::size_t name_length,
850     const double * values, std::size_t array_length)
851 {
852     result res;
853 
854     const std::size_t raw_length = array_length * sizeof(double);
855     double * new_array =
856         static_cast<double *>(allocator_.allocate(raw_length));
857     if (new_array != NULL)
858     {
859         std::memcpy(new_array, values, raw_length);
860 
861         res = details::do_set_double_float_array(name, name_length,
862             new_array, array_length,
863             data_, num_of_entries_, allocator_, true);
864 
865         if (res != ok)
866         {
867             allocator_.deallocate(new_array);
868         }
869     }
870     else
871     {
872         res = no_memory;
873     }
874 
875     return res;
876 }
877 
set_double_float_array(const char * name,const double * values,std::size_t array_length)878 result parameters::set_double_float_array(const char * name,
879     const double * values, std::size_t array_length)
880 {
881     return set_double_float_array(
882         name, std::strlen(name), values, array_length);
883 }
884 
set_double_float_array_shallow(const char * name,std::size_t name_length,const double * values,std::size_t array_length)885 result parameters::set_double_float_array_shallow(
886     const char * name, std::size_t name_length,
887     const double * values, std::size_t array_length)
888 {
889     const result res = details::do_set_double_float_array(name, name_length,
890         values, array_length,
891         data_, num_of_entries_, allocator_, false);
892 
893     return res;
894 }
895 
set_double_float_array_shallow(const char * name,const double * values,std::size_t array_length)896 result parameters::set_double_float_array_shallow(const char * name,
897     const double * values, std::size_t array_length)
898 {
899     return set_double_float_array_shallow(name, std::strlen(name),
900         values, array_length);
901 }
902 
create_double_float_array(const char * name,std::size_t name_length,std::size_t array_length,double * & array)903 result parameters::create_double_float_array(
904     const char * name, std::size_t name_length,
905     std::size_t array_length, double * & array)
906 {
907     result res;
908 
909     const std::size_t raw_length = array_length * sizeof(double);
910     double * new_array =
911         static_cast<double *>(allocator_.allocate(raw_length));
912     if (new_array != NULL)
913     {
914         res = details::do_set_double_float_array(name, name_length,
915             new_array, array_length,
916             data_, num_of_entries_, allocator_, true);
917 
918         if (res == ok)
919         {
920             array = new_array;
921         }
922         else
923         {
924             allocator_.deallocate(new_array);
925         }
926     }
927     else
928     {
929         res = no_memory;
930     }
931 
932     return res;
933 }
934 
create_double_float_array(const char * name,std::size_t array_length,double * & array)935 result parameters::create_double_float_array(const char * name,
936     std::size_t array_length, double * & array)
937 {
938     return create_double_float_array(name, std::strlen(name),
939         array_length, array);
940 }
941 
get_double_float_array(const char * name,std::size_t name_length,double * & values,std::size_t & array_length) const942 result parameters::get_double_float_array(
943     const char * name, std::size_t name_length,
944     double * & values, std::size_t & array_length) const
945 {
946     result res;
947     const std::size_t index = details::find_entry(data_, num_of_entries_,
948         name, name_length);
949     if (index != num_of_entries_)
950     {
951         const details::entry & e = data_[index];
952         if (e.type == double_float_array)
953         {
954             values = e.item.da.values;
955             array_length = e.item.da.length;
956             res = ok;
957         }
958         else
959         {
960             res = bad_type;
961         }
962     }
963     else
964     {
965         res = no_such_name;
966     }
967 
968     return res;
969 }
970 
get_double_float_array(const char * name,double * & values,std::size_t & array_length) const971 result parameters::get_double_float_array(const char * name,
972     double * & values, std::size_t & array_length) const
973 {
974     return get_double_float_array(
975         name, std::strlen(name), values, array_length);
976 }
977 
create_string_array(const char * name,std::size_t name_length,std::size_t array_length)978 result parameters::create_string_array(
979     const char * name, std::size_t name_length,
980     std::size_t array_length)
981 {
982     std::size_t dummy_index;
983     const result res = details::do_create_string_array(
984         name, name_length, array_length, dummy_index,
985         data_, num_of_entries_, allocator_);
986 
987     return res;
988 }
989 
create_string_array(const char * name,std::size_t array_length)990 result parameters::create_string_array(
991     const char * name, std::size_t array_length)
992 {
993     return create_string_array(name, std::strlen(name), array_length);
994 }
995 
set_string_in_array(const char * name,std::size_t name_length,std::size_t index,const char * value,std::size_t value_length)996 result parameters::set_string_in_array(
997     const char * name, std::size_t name_length,
998     std::size_t index, const char * value, std::size_t value_length)
999 {
1000     result res;
1001     const std::size_t item_index = details::find_entry(
1002         data_, num_of_entries_, name, name_length);
1003     if (item_index != num_of_entries_)
1004     {
1005         res = details::do_set_string_in_array(item_index, index,
1006             value, value_length, data_, allocator_);
1007     }
1008     else
1009     {
1010         res = no_such_name;
1011     }
1012 
1013     return res;
1014 }
1015 
set_string_in_array(const char * name,std::size_t index,const char * value)1016 result parameters::set_string_in_array(const char * name,
1017     std::size_t index, const char * value)
1018 {
1019     return set_string_in_array(name, std::strlen(name),
1020         index, value, std::strlen(value));
1021 }
1022 
get_string_array_length(const char * name,std::size_t name_length,std::size_t & array_length) const1023 result parameters::get_string_array_length(
1024     const char * name, std::size_t name_length,
1025     std::size_t & array_length) const
1026 {
1027     result res;
1028     const std::size_t index = details::find_entry(data_, num_of_entries_,
1029         name, name_length);
1030     if (index != num_of_entries_)
1031     {
1032         const details::entry & e = data_[index];
1033         if (e.type == string_array)
1034         {
1035             array_length = e.item.sa.length;
1036             res = ok;
1037         }
1038         else
1039         {
1040             res = bad_type;
1041         }
1042     }
1043     else
1044     {
1045         res = no_such_name;
1046     }
1047 
1048     return res;
1049 }
1050 
get_string_array_length(const char * name,std::size_t & array_length) const1051 result parameters::get_string_array_length(const char * name,
1052     std::size_t & array_length) const
1053 {
1054     return get_string_array_length(name, std::strlen(name), array_length);
1055 }
1056 
get_string_in_array(const char * name,std::size_t name_length,std::size_t index,const char * & value,std::size_t & value_length) const1057 result parameters::get_string_in_array(
1058     const char * name, std::size_t name_length,
1059     std::size_t index,
1060     const char * & value, std::size_t & value_length) const
1061 {
1062     result res;
1063     const std::size_t item_index = details::find_entry(
1064         data_, num_of_entries_, name, name_length);
1065     if (item_index != num_of_entries_)
1066     {
1067         const details::entry & e = data_[item_index];
1068         if (e.type == string_array)
1069         {
1070             if (index < e.item.sa.length)
1071             {
1072                 value = e.item.sa.values[index].value;
1073                 value_length = e.item.sa.values[index].length;
1074                 res = ok;
1075             }
1076             else
1077             {
1078                 res = no_such_index;
1079             }
1080         }
1081         else
1082         {
1083             res = bad_type;
1084         }
1085     }
1086     else
1087     {
1088         res = no_such_name;
1089     }
1090 
1091     return res;
1092 }
1093 
get_string_in_array(const char * name,std::size_t index,const char * & value,std::size_t & value_length) const1094 result parameters::get_string_in_array(const char * name, std::size_t index,
1095     const char * & value, std::size_t & value_length) const
1096 {
1097     return get_string_in_array(name, std::strlen(name),
1098         index, value, value_length);
1099 }
1100 
create_binary_array(const char * name,std::size_t name_length,std::size_t array_length)1101 result parameters::create_binary_array(
1102     const char * name, std::size_t name_length,
1103     std::size_t array_length)
1104 {
1105     std::size_t dummy_index;
1106     const result res = details::do_create_binary_array(
1107         name, name_length, array_length, dummy_index,
1108         data_, num_of_entries_, allocator_);
1109 
1110     return res;
1111 }
1112 
create_binary_array(const char * name,std::size_t array_length)1113 result parameters::create_binary_array(
1114     const char * name, std::size_t array_length)
1115 {
1116     return create_binary_array(name, std::strlen(name), array_length);
1117 }
1118 
set_binary_in_array(const char * name,std::size_t name_length,std::size_t index,const void * value,std::size_t value_length)1119 result parameters::set_binary_in_array(
1120     const char * name, std::size_t name_length,
1121     std::size_t index, const void * value, std::size_t value_length)
1122 {
1123     result res;
1124     const std::size_t item_index = details::find_entry(
1125         data_, num_of_entries_, name, name_length);
1126     if (item_index != num_of_entries_)
1127     {
1128         res = details::do_set_binary_in_array(item_index, index,
1129             value, value_length, data_, allocator_);
1130     }
1131     else
1132     {
1133         res = no_such_name;
1134     }
1135 
1136     return res;
1137 }
1138 
set_binary_in_array(const char * name,std::size_t index,const void * value,std::size_t value_length)1139 result parameters::set_binary_in_array(const char * name,
1140     std::size_t index, const void * value, std::size_t value_length)
1141 {
1142     return set_binary_in_array(name, std::strlen(name),
1143         index, value, value_length);
1144 }
1145 
get_binary_array_length(const char * name,std::size_t name_length,std::size_t & array_length) const1146 result parameters::get_binary_array_length(
1147     const char * name, std::size_t name_length,
1148     std::size_t & array_length) const
1149 {
1150     result res;
1151     const std::size_t index = details::find_entry(data_, num_of_entries_,
1152         name, name_length);
1153     if (index != num_of_entries_)
1154     {
1155         const details::entry & e = data_[index];
1156         if (e.type == binary_array)
1157         {
1158             array_length = e.item.bina.length;
1159             res = ok;
1160         }
1161         else
1162         {
1163             res = bad_type;
1164         }
1165     }
1166     else
1167     {
1168         res = no_such_name;
1169     }
1170 
1171     return res;
1172 }
1173 
get_binary_array_length(const char * name,std::size_t & array_length) const1174 result parameters::get_binary_array_length(const char * name,
1175     std::size_t & array_length) const
1176 {
1177     return get_binary_array_length(name, std::strlen(name), array_length);
1178 }
1179 
get_binary_in_array(const char * name,std::size_t name_length,std::size_t index,const void * & value,std::size_t & value_length) const1180 result parameters::get_binary_in_array(
1181     const char * name, std::size_t name_length,
1182     std::size_t index,
1183     const void * & value, std::size_t & value_length) const
1184 {
1185     result res;
1186     const std::size_t item_index = details::find_entry(
1187         data_, num_of_entries_, name, name_length);
1188     if (item_index != num_of_entries_)
1189     {
1190         const details::entry & e = data_[item_index];
1191         if (e.type == binary_array)
1192         {
1193             if (index < e.item.bina.length)
1194             {
1195                 value = e.item.bina.values[index].value;
1196                 value_length = e.item.bina.values[index].length;
1197                 res = ok;
1198             }
1199             else
1200             {
1201                 res = no_such_index;
1202             }
1203         }
1204         else
1205         {
1206             res = bad_type;
1207         }
1208     }
1209     else
1210     {
1211         res = no_such_name;
1212     }
1213 
1214     return res;
1215 }
1216 
get_binary_in_array(const char * name,std::size_t index,const void * & value,std::size_t & value_length) const1217 result parameters::get_binary_in_array(const char * name, std::size_t index,
1218     const void * & value, std::size_t & value_length) const
1219 {
1220     return get_binary_in_array(name, std::strlen(name),
1221         index, value, value_length);
1222 }
1223 
create_nested_parameters(const char * name,std::size_t name_length,parameters * & params)1224 result parameters::create_nested_parameters(
1225     const char * name, std::size_t name_length, parameters * & params)
1226 {
1227     result res;
1228 
1229     void * new_buffer = allocator_.allocate(sizeof(parameters));
1230     if (new_buffer != NULL)
1231     {
1232         std::size_t index;
1233         res = details::prepare_for_set(data_, num_of_entries_,
1234             name, name_length, index, allocator_);
1235 
1236         if (res == ok)
1237         {
1238             parameters * nested =
1239                 new (new_buffer) parameters(allocator_, uses_private_area_);
1240 
1241             details::entry & e = data_[index];
1242 
1243             e.type = nested_parameters;
1244             e.item.nested = nested;
1245 
1246             params = nested;
1247         }
1248         else
1249         {
1250             allocator_.deallocate(new_buffer);
1251         }
1252     }
1253     else
1254     {
1255         res = no_memory;
1256     }
1257 
1258     return res;
1259 }
1260 
create_nested_parameters(const char * name,parameters * & params)1261 result parameters::create_nested_parameters(
1262     const char * name, parameters * & params)
1263 {
1264     return create_nested_parameters(name, std::strlen(name), params);
1265 }
1266 
get_nested_parameters(const char * name,std::size_t name_length,parameters * & params) const1267 result parameters::get_nested_parameters(
1268     const char * name, std::size_t name_length, parameters * & params) const
1269 {
1270     result res;
1271     const std::size_t index = details::find_entry(
1272         data_, num_of_entries_, name, name_length);
1273     if (index != num_of_entries_)
1274     {
1275         const details::entry & e = data_[index];
1276         if (e.type == nested_parameters)
1277         {
1278             params = e.item.nested;
1279             res = ok;
1280         }
1281         else
1282         {
1283             res = bad_type;
1284         }
1285     }
1286     else
1287     {
1288         res = no_such_name;
1289     }
1290 
1291     return res;
1292 }
1293 
get_nested_parameters(const char * name,parameters * & params) const1294 result parameters::get_nested_parameters(
1295     const char * name, parameters * & params) const
1296 {
1297     return get_nested_parameters(name, std::strlen(name), params);
1298 }
1299 
create_nested_array(const char * name,std::size_t name_length,std::size_t array_length)1300 result parameters::create_nested_array(
1301     const char * name, std::size_t name_length,
1302     std::size_t array_length)
1303 {
1304     std::size_t dummy_index;
1305     const result res = details::do_create_nested_array(
1306         name, name_length, array_length, dummy_index,
1307         data_, num_of_entries_, allocator_);
1308 
1309     return res;
1310 }
1311 
create_nested_array(const char * name,std::size_t array_length)1312 result parameters::create_nested_array(
1313     const char * name, std::size_t array_length)
1314 {
1315     return create_nested_array(name, std::strlen(name), array_length);
1316 }
1317 
get_nested_array_length(const char * name,std::size_t name_length,std::size_t & array_length) const1318 result parameters::get_nested_array_length(
1319     const char * name, std::size_t name_length,
1320     std::size_t & array_length) const
1321 {
1322     result res;
1323     const std::size_t index = details::find_entry(data_, num_of_entries_,
1324         name, name_length);
1325     if (index != num_of_entries_)
1326     {
1327         const details::entry & e = data_[index];
1328         if (e.type == nested_parameters_array)
1329         {
1330             array_length = e.item.nesteda.length;
1331             res = ok;
1332         }
1333         else
1334         {
1335             res = bad_type;
1336         }
1337     }
1338     else
1339     {
1340         res = no_such_name;
1341     }
1342 
1343     return res;
1344 }
1345 
get_nested_array_length(const char * name,std::size_t & array_length) const1346 result parameters::get_nested_array_length(const char * name,
1347     std::size_t & array_length) const
1348 {
1349     return get_nested_array_length(name, std::strlen(name), array_length);
1350 }
1351 
get_nested_in_array(const char * name,std::size_t name_length,std::size_t index,parameters * & nested) const1352 result parameters::get_nested_in_array(
1353     const char * name, std::size_t name_length,
1354     std::size_t index,
1355     parameters * & nested) const
1356 {
1357     result res;
1358     const std::size_t item_index = details::find_entry(
1359         data_, num_of_entries_, name, name_length);
1360     if (item_index != num_of_entries_)
1361     {
1362         const details::entry & e = data_[item_index];
1363         if (e.type == nested_parameters_array)
1364         {
1365             if (index < e.item.nesteda.length)
1366             {
1367                 nested = &e.item.nesteda.values[index];
1368                 res = ok;
1369             }
1370             else
1371             {
1372                 res = no_such_index;
1373             }
1374         }
1375         else
1376         {
1377             res = bad_type;
1378         }
1379     }
1380     else
1381     {
1382         res = no_such_name;
1383     }
1384 
1385     return res;
1386 }
1387 
get_nested_in_array(const char * name,std::size_t index,parameters * & nested) const1388 result parameters::get_nested_in_array(
1389     const char * name, std::size_t index,
1390     parameters * & nested) const
1391 {
1392     return get_nested_in_array(name, std::strlen(name), index, nested);
1393 }
1394 
remove(const char * name,std::size_t name_length)1395 result parameters::remove(const char * name, std::size_t name_length)
1396 {
1397     result res;
1398     const std::size_t index = details::find_entry(
1399         data_, num_of_entries_, name, name_length);
1400     if (index != num_of_entries_)
1401     {
1402         details::entry & e = data_[index];
1403 
1404 		e.clear_name(allocator_);
1405 		e.clear_item(allocator_);
1406 		e.type = unused;
1407 		res = ok;
1408     }
1409     else
1410     {
1411         res = no_such_name;
1412     }
1413 
1414     return res;
1415 }
1416 
remove(const char * name)1417 result parameters::remove(const char * name)
1418 {
1419     return remove(name, std::strlen(name));
1420 }
1421 
size() const1422 std::size_t parameters::size() const
1423 {
1424     std::size_t count = 0;
1425     for (std::size_t i = 0; i != num_of_entries_; ++i)
1426     {
1427         if (data_[i].type != unused)
1428         {
1429             ++count;
1430         }
1431     }
1432 
1433     return count;
1434 }
1435 
get_type(const char * name,std::size_t name_length,parameter_type & t) const1436 result parameters::get_type(const char * name, std::size_t name_length,
1437     parameter_type & t) const
1438 {
1439     result res;
1440     const std::size_t index = details::find_entry(
1441         data_, num_of_entries_, name, name_length);
1442     if (index != num_of_entries_)
1443     {
1444         t = data_[index].type;
1445         res = ok;
1446     }
1447     else
1448     {
1449         res = no_such_name;
1450     }
1451 
1452     return res;
1453 }
1454 
get_type(const char * name,parameter_type & t) const1455 result parameters::get_type(const char * name, parameter_type & t) const
1456 {
1457     return get_type(name, std::strlen(name), t);
1458 }
1459 
get_iterator(parameter_iterator & it) const1460 result parameters::get_iterator(parameter_iterator & it) const
1461 {
1462     result res;
1463 
1464     std::size_t first_used_index = num_of_entries_;
1465     for (std::size_t i = 0; i != num_of_entries_; ++i)
1466     {
1467         if (data_[i].type != unused)
1468         {
1469             first_used_index = i;
1470             break;
1471         }
1472     }
1473 
1474     if (first_used_index != num_of_entries_)
1475     {
1476         it.data_ = data_;
1477         it.current_index_ = first_used_index;
1478         it.num_of_entries_ = num_of_entries_;
1479         it.allocator_ = &allocator_;
1480         res = ok;
1481     }
1482     else
1483     {
1484         res = no_entries;
1485     }
1486 
1487     return res;
1488 }
1489 
find(const char * name,std::size_t name_length,parameter_entry & entry) const1490 result parameters::find(const char * name, std::size_t name_length,
1491     parameter_entry & entry) const
1492 {
1493     result res;
1494     const std::size_t index = details::find_entry(
1495         data_, num_of_entries_, name, name_length);
1496     if (index != num_of_entries_)
1497     {
1498         entry.e_ = data_ + index;
1499         res = ok;
1500     }
1501     else
1502     {
1503         res = no_such_name;
1504     }
1505 
1506     return res;
1507 }
1508 
find(const char * name,parameter_entry & entry) const1509 result parameters::find(const char * name, parameter_entry & entry) const
1510 {
1511     return find(name, std::strlen(name), entry);
1512 }
1513 
merge_from(const parameters & other)1514 result parameters::merge_from(const parameters & other)
1515 {
1516     // merge is performed as serialize of other
1517     // followed by deserialize into this
1518 
1519     result res = ok;
1520 
1521     if (other.size() != 0)
1522     {
1523         std::size_t buffer_size;
1524         res = other.get_serialize_buffer_size(buffer_size);
1525         if (res == ok)
1526         {
1527             char * buffer = static_cast<char *>(
1528                 allocator_.allocate(buffer_size));
1529             if (buffer != NULL)
1530             {
1531                 res = other.serialize(&buffer, &buffer_size, 1);
1532                 if (res == ok)
1533                 {
1534                     const char * buffers[1];
1535                     buffers[0] = buffer;
1536                     std::size_t buffer_sizes[1];
1537                     buffer_sizes[0] = buffer_size;
1538 
1539                     res = deserialize(buffers, buffer_sizes, 1);
1540                 }
1541 
1542                 allocator_.deallocate(buffer);
1543             }
1544             else
1545             {
1546                 res = no_memory;
1547             }
1548         }
1549     }
1550 
1551     return res;
1552 }
1553 
get_serialize_buffer_size(std::size_t & buffer_size) const1554 result parameters::get_serialize_buffer_size(std::size_t & buffer_size) const
1555 {
1556     // the serialized format is:
1557     // 1. number of entries
1558     // 2. for each entry:
1559     //    1. name length
1560     //    2. name
1561     //    3. type
1562     //    4. value
1563     // depending on type, value is:
1564     // - boolean: 0 or 1 in 4 bytes
1565     // - integer: as is 4 bytets
1566     // - long_long: as is 8 bytes
1567     // - double_float: as is 8 bytes
1568     // - string: length followed by value
1569     // - boolean_array: length followed by packed (per bit) values
1570     // - integer_array: length followed by values
1571     // - long_long_array: length followed by values
1572     // - double_float_array: length followed by values
1573     // - string_array: length followed by values as for string
1574     // - nested: as the whole
1575 
1576     // recurively for nested parameters:
1577 
1578     buffer_size = 0;
1579     details::get_serialize_buffer_size(*this, buffer_size);
1580 
1581     return ok;
1582 }
1583 
serialize(char ** buffers,const std::size_t * buffer_sizes,std::size_t num_of_buffers) const1584 result parameters::serialize(char * * buffers,
1585     const std::size_t * buffer_sizes,
1586     std::size_t num_of_buffers) const
1587 {
1588     std::size_t current_buffer = 0;
1589     char * buffer_position = &buffers[0][0];
1590 
1591     return details::serialize(*this,
1592         buffers, buffer_sizes, num_of_buffers,
1593         current_buffer, buffer_position);
1594 }
1595 
deserialize(const char ** buffers,const std::size_t * buffer_sizes,std::size_t num_of_buffers)1596 result parameters::deserialize(
1597     const char * * buffers, const std::size_t * buffer_sizes,
1598     std::size_t num_of_buffers)
1599 {
1600     std::size_t current_buffer = 0;
1601     const char * buffer_position = &buffers[0][0];
1602 
1603     return details::deserialize(*this,
1604         buffers, buffer_sizes, num_of_buffers,
1605         current_buffer, buffer_position);
1606 }
1607 
dump(details::dump_sink & sink,std::size_t indent_length) const1608 void parameters::dump(
1609     details::dump_sink & sink, std::size_t indent_length) const
1610 {
1611     for (std::size_t i = 0; i != num_of_entries_; ++i)
1612     {
1613         bool add_newline = true;
1614         sink.indent(indent_length);
1615         sink.dump("entry ");
1616         sink.dump(i);
1617         sink.dump(":\n");
1618         switch (data_[i].type)
1619         {
1620         case unused:
1621             sink.indent(indent_length);
1622             sink.dump("unused");
1623             break;
1624         case boolean:
1625             sink.indent(indent_length);
1626             sink.dump("name: ");
1627             data_[i].name.dump(sink);
1628             sink.dump("\n");
1629             sink.indent(indent_length);
1630             sink.dump("boolean: ");
1631             sink.dump(data_[i].item.b);
1632             break;
1633         case integer:
1634             sink.indent(indent_length);
1635             sink.dump("name: ");
1636             data_[i].name.dump(sink);
1637             sink.dump("\n");
1638             sink.indent(indent_length);
1639             sink.dump("integer: ");
1640             sink.dump(data_[i].item.i);
1641             break;
1642         case long_long:
1643             sink.indent(indent_length);
1644             sink.dump("name: ");
1645             data_[i].name.dump(sink);
1646             sink.dump("\n");
1647             sink.indent(indent_length);
1648             sink.dump("long_long: ");
1649             sink.dump(data_[i].item.L);
1650             break;
1651         case double_float:
1652             sink.indent(indent_length);
1653             sink.dump("name: ");
1654             data_[i].name.dump(sink);
1655             sink.dump("\n");
1656             sink.indent(indent_length);
1657             sink.dump("double: ");
1658             sink.dump(data_[i].item.d);
1659             break;
1660         case string:
1661             sink.indent(indent_length);
1662             sink.dump("name: ");
1663             data_[i].name.dump(sink);
1664             sink.dump("\n");
1665             sink.indent(indent_length);
1666             sink.dump("string: ");
1667             sink.dump(data_[i].item.str.value,
1668                 data_[i].item.str.length);
1669             break;
1670         case binary:
1671             sink.indent(indent_length);
1672             sink.dump("name: ");
1673             data_[i].name.dump(sink);
1674             sink.dump("\n");
1675             sink.indent(indent_length);
1676             sink.dump("binary of length ");
1677             sink.dump(data_[i].item.bin.length);
1678             break;
1679         case boolean_array:
1680             sink.indent(indent_length);
1681             sink.dump("name: ");
1682             data_[i].name.dump(sink);
1683             sink.dump("\n");
1684             sink.indent(indent_length);
1685             sink.dump("boolean array:");
1686             for (std::size_t j = 0; j != data_[i].item.ba.length; ++j)
1687             {
1688                 sink.dump(" ");
1689                 sink.dump(data_[i].item.ba.values[j]);
1690             }
1691             break;
1692         case integer_array:
1693             sink.indent(indent_length);
1694             sink.dump("name: ");
1695             data_[i].name.dump(sink);
1696             sink.dump("\n");
1697             sink.indent(indent_length);
1698             sink.dump("integer array:");
1699             for (std::size_t j = 0; j != data_[i].item.ia.length; ++j)
1700             {
1701                 sink.dump(" ");
1702                 sink.dump(data_[i].item.ia.values[j]);
1703             }
1704             break;
1705         case long_long_array:
1706             sink.indent(indent_length);
1707             sink.dump("name: ");
1708             data_[i].name.dump(sink);
1709             sink.dump("\n");
1710             sink.indent(indent_length);
1711             sink.dump("long_long array:");
1712             for (std::size_t j = 0; j != data_[i].item.La.length; ++j)
1713             {
1714                 sink.dump(" ");
1715                 sink.dump(data_[i].item.La.values[j]);
1716             }
1717             break;
1718         case double_float_array:
1719             sink.indent(indent_length);
1720             sink.dump("name: ");
1721             data_[i].name.dump(sink);
1722             sink.dump("\n");
1723             sink.indent(indent_length);
1724             sink.dump("double array:");
1725             for (std::size_t j = 0; j != data_[i].item.da.length; ++j)
1726             {
1727                 sink.dump(" ");
1728                 sink.dump(data_[i].item.da.values[j]);
1729             }
1730             break;
1731         case string_array:
1732             sink.indent(indent_length);
1733             sink.dump("name: ");
1734             data_[i].name.dump(sink);
1735             sink.dump("\n");
1736             sink.indent(indent_length);
1737             sink.dump("string array:");
1738             for (std::size_t j = 0; j != data_[i].item.sa.length; ++j)
1739             {
1740                 sink.dump(" ");
1741                 sink.dump(data_[i].item.sa.values[j].value,
1742                     data_[i].item.sa.values[j].length);
1743             }
1744             break;
1745         case binary_array:
1746             sink.indent(indent_length);
1747             sink.dump("name: ");
1748             data_[i].name.dump(sink);
1749             sink.dump("\n");
1750             sink.indent(indent_length);
1751             sink.dump("binary array of length ");
1752             sink.dump(data_[i].item.bina.length);
1753             break;
1754         case nested_parameters:
1755             sink.indent(indent_length);
1756             sink.dump("name: ");
1757             data_[i].name.dump(sink);
1758             sink.dump("\n");
1759             sink.indent(indent_length);
1760             sink.dump("nested parameters:\n");
1761             data_[i].item.nested->dump(sink, indent_length + 2);
1762             add_newline = false;
1763             break;
1764         case nested_parameters_array:
1765             sink.indent(indent_length);
1766             sink.dump("name: ");
1767             data_[i].name.dump(sink);
1768             sink.dump("\n");
1769             sink.indent(indent_length);
1770             sink.dump("nested parameters array of length ");
1771             sink.dump(data_[i].item.nesteda.length);
1772             sink.dump(":\n");
1773             for (std::size_t j = 0; j != data_[i].item.nesteda.length; ++j)
1774             {
1775                 sink.indent(indent_length);
1776                 sink.dump("  nested at index ");
1777                 sink.dump(j);
1778                 sink.dump(":\n");
1779                 data_[i].item.nesteda.values[j].dump(sink, indent_length + 4);
1780             }
1781             add_newline = false;
1782             break;
1783         default:
1784             details::fatal_failure(__FILE__, __LINE__);
1785         }
1786 
1787         if (add_newline)
1788         {
1789             sink.dump("\n");
1790         }
1791     }
1792 }
1793 
1794