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 #ifndef YAMICORE_PARAMETERS_DETAILS_H_INCLUDED
18 #define YAMICORE_PARAMETERS_DETAILS_H_INCLUDED
19 
20 #include "core.h"
21 #include "details-fwd.h"
22 #include "parameter_type.h"
23 #include <cstddef>
24 
25 namespace yami
26 {
27 
28 namespace core
29 {
30 class parameters;
31 } // namespace core
32 
33 namespace details
34 {
35 
36 const std::size_t short_name_optimization_threshold = 16;
37 const std::size_t initial_number_of_entries = 4;
38 const std::size_t max_nesting_level = 5;
39 
40 struct entry_name
41 {
42     std::size_t name_length;
43     union packed
44     {
45         const char * long_value;
46         char short_value[short_name_optimization_threshold];
47     } buffer;
48 
49     core::result set(const char * value, std::size_t length,
50         allocator & alloc);
51 
52     const char * value() const;
53 
54     void clear(allocator & alloc);
55 
56     bool equals(const char * value, std::size_t length) const;
57 
58     // for unit tests
59     void dump(details::dump_sink & sink) const;
60 };
61 
62 struct string_array_element
63 {
64     const char * value;
65     std::size_t length;
66 
67     void clear(allocator & alloc);
68 };
69 
70 struct binary_array_element
71 {
72     const void * value;
73     std::size_t length;
74 
75     void clear(allocator & alloc);
76 };
77 
78 struct entry
79 {
80     entry_name name;
81 
82     core::parameter_type type;
83 
84     union packed
85     {
86         bool b;
87         int i;
88         long long L;
89         double d;
90         struct string_data
91         {
92             const char * value;
93             std::size_t length;
94             bool own;
95         } str;
96         struct binary_data
97         {
98             const void * value;
99             std::size_t length;
100             bool own;
101         } bin;
102         struct boolean_array_data
103         {
104             bool * values;
105             std::size_t length;
106             bool own;
107         } ba;
108         struct integer_array_data
109         {
110             int * values;
111             std::size_t length;
112             bool own;
113         } ia;
114         struct long_long_array_data
115         {
116             long long * values;
117             std::size_t length;
118             bool own;
119         } La;
120         struct double_float_array_data
121         {
122             double * values;
123             std::size_t length;
124             bool own;
125         } da;
126         struct string_array_data
127         {
128             string_array_element * values;
129             std::size_t length;
130             bool own;
131         } sa;
132         struct binary_array_data
133         {
134             binary_array_element * values;
135             std::size_t length;
136             bool own;
137         } bina;
138         core::parameters * nested;
139         struct nested_array_data
140         {
141             core::parameters * values;
142             std::size_t length;
143             bool own;
144         } nesteda;
145     } item;
146 
set_nameentry147     core::result set_name(const char * value, std::size_t length,
148         allocator & alloc)
149     {
150         return name.set(value, length, alloc);
151     }
152 
clear_nameentry153     void clear_name(allocator & alloc)
154     {
155         name.clear(alloc);
156     }
157 
name_equalsentry158     bool name_equals(const char * value, std::size_t length) const
159     {
160         return name.equals(value, length);
161     }
162 
163     void clear_item(allocator & alloc);
164 };
165 
166 void get_serialize_buffer_size(
167     const core::parameters & params,
168     std::size_t & size); // starts with 0 (for root) and gets updated
169 
170 core::result serialize_entry(
171     const details::entry & e,
172 	char * * buffers,
173     const std::size_t * buffer_sizes,
174     std::size_t num_of_buffers,
175     std::size_t & current_buffer, char * & buffer_position);
176 
177 core::result serialize(
178     const core::parameters & params,
179 	char * * buffers,
180     const std::size_t * buffer_sizes,
181     std::size_t num_of_buffers,
182     std::size_t & current_buffer, char * & buffer_position);
183 
184 core::result deserialize_entry(
185     core::parameters & params,
186 	const char * * buffers,
187     const std::size_t * buffer_sizes,
188     std::size_t num_of_buffers,
189     std::size_t & current_buffer, const char * & buffer_position);
190 
191 core::result deserialize(
192     core::parameters & params,
193 	const char * * buffers,
194     const std::size_t * buffer_sizes,
195     std::size_t num_of_buffers,
196     std::size_t & current_buffer, const char * & buffer_position);
197 
198 int type_code(core::parameter_type t);
199 
200 core::result get_type_from_code(int code, core::parameter_type & type);
201 
202 // find the entry with given name
203 // returns the index or num_of_entries if not found
204 std::size_t find_entry(const entry * data, std::size_t num_of_entries,
205     const char * name, std::size_t name_length);
206 
207 // find an appropriate place for a new entry
208 // by either locating an unused entry
209 // or by extending the set
210 core::result find_empty_entry(entry * & data, std::size_t & num_of_entries,
211     std::size_t & index, allocator & alloc);
212 
213 // finds an existing entry with the given name and clears its item
214 // or creates a new entry with this name already set
215 core::result prepare_for_set(entry * & data, std::size_t & num_of_entries,
216     const char * name, std::size_t name_length,
217     std::size_t & index, allocator & alloc);
218 
219 // finds the next used entry or returns num_of_entries if nothing was found
220 std::size_t find_next_used(const entry * data, std::size_t num_of_entries,
221     std::size_t current_index);
222 
223 core::result do_set_string(const char * name, std::size_t name_length,
224     const char * value, std::size_t value_length,
225     entry * & data, std::size_t & num_of_entries,
226     allocator & alloc, bool own);
227 
228 core::result do_set_binary(const char * name, std::size_t name_length,
229     const void * value, std::size_t value_length,
230     entry * & data, std::size_t & num_of_entries,
231     allocator & alloc, bool own);
232 
233 core::result do_set_boolean_array(const char * name, std::size_t name_length,
234     const bool * values, std::size_t array_length,
235     entry * & data, std::size_t & num_of_entries,
236     allocator & alloc, bool own);
237 
238 core::result do_set_integer_array(const char * name, std::size_t name_length,
239     const int * values, std::size_t array_length,
240     entry * & data, std::size_t & num_of_entries,
241     allocator & alloc, bool own);
242 
243 core::result do_set_long_long_array(
244     const char * name, std::size_t name_length,
245     const long long * values, std::size_t array_length,
246     entry * & data, std::size_t & num_of_entries,
247     allocator & alloc, bool own);
248 
249 core::result do_set_double_float_array(
250     const char * name, std::size_t name_length,
251     const double * values, std::size_t array_length,
252     entry * & data, std::size_t & num_of_entries,
253     allocator & alloc, bool own);
254 
255 core::result do_create_string_array(
256     const char * name, std::size_t name_length,
257     std::size_t array_length, std::size_t & index,
258     entry * & data, std::size_t & num_of_entries,
259     allocator & alloc);
260 
261 core::result do_set_string_in_array(
262     std::size_t item_index, std::size_t array_index,
263     const char * value, std::size_t value_length,
264     entry * data, allocator & alloc);
265 
266 core::result do_place_string_in_array(
267     std::size_t item_index, std::size_t array_index,
268     const char * value, std::size_t value_length,
269     entry * data, allocator & alloc);
270 
271 core::result do_create_binary_array(
272     const char * name, std::size_t name_length,
273     std::size_t array_length, std::size_t & index,
274     entry * & data, std::size_t & num_of_entries,
275     allocator & alloc);
276 
277 core::result do_set_binary_in_array(
278     std::size_t item_index, std::size_t array_index,
279     const void * value, std::size_t value_length,
280     entry * data, allocator & alloc);
281 
282 core::result do_place_binary_in_array(
283     std::size_t item_index, std::size_t array_index,
284     const void * value, std::size_t value_length,
285     entry * data, allocator & alloc);
286 
287 core::result do_create_nested_array(
288     const char * name, std::size_t name_length,
289     std::size_t array_length, std::size_t & index,
290     entry * & data, std::size_t & num_of_entries,
291     allocator & alloc);
292 
293 core::result do_access_nested_in_array(
294     std::size_t item_index, std::size_t array_index,
295     core::parameters * & nested,
296     entry * data);
297 
298 } // namespace details
299 
300 } // namespace yami
301 
302 #endif // YAMICORE_PARAMETERS_DETAILS_H_INCLUDED
303