This source file includes following definitions.
- G_GNUC_PRINTF
- go_to_end_of_serialized_string
- mc_serialize_str
- mc_deserialize_str
- mc_serialize_config
- mc_deserialize_config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <config.h>
31
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35
36 #include "lib/global.h"
37
38 #include "lib/serialize.h"
39
40
41
42
43
44 #define SRLZ_DELIM_C ':'
45 #define SRLZ_DELIM_S ":"
46
47
48
49
50
51
52
53
54
55
56
57 static void G_GNUC_PRINTF (2, 3)
58 prepend_error_message (GError **error, const char *format, ...)
59 {
60 char *prepend_str;
61 char *split_str;
62 va_list ap;
63
64 if ((error == NULL) || (*error == NULL))
65 return;
66
67 va_start (ap, format);
68 prepend_str = g_strdup_vprintf (format, ap);
69 va_end (ap);
70
71 split_str = g_strdup_printf ("%s: %s", prepend_str, (*error)->message);
72 g_free (prepend_str);
73 g_free ((*error)->message);
74 (*error)->message = split_str;
75 }
76
77
78
79 static const char *
80 go_to_end_of_serialized_string (const char *non_serialized_data,
81 const char *already_serialized_part, size_t *offset)
82 {
83 const char *semi_ptr = strchr (non_serialized_data + 1, SRLZ_DELIM_C);
84 const size_t calculated_offset =
85 (semi_ptr - non_serialized_data) + 1 + strlen (already_serialized_part);
86
87 if (calculated_offset >= strlen (non_serialized_data))
88 return NULL;
89
90 non_serialized_data += calculated_offset;
91 *offset += calculated_offset;
92
93 return non_serialized_data;
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 char *
111 mc_serialize_str (const char prefix, const char *data, GError **error)
112 {
113 if (data == NULL)
114 {
115 g_set_error (error, MC_ERROR, 0, "mc_serialize_str(): Input data is NULL.");
116 return NULL;
117 }
118 return g_strdup_printf ("%c%zu" SRLZ_DELIM_S "%s", prefix, strlen (data), data);
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132 #define FUNC_NAME "mc_serialize_str()"
133 char *
134 mc_deserialize_str (const char prefix, const char *data, GError **error)
135 {
136 size_t data_len;
137
138 if ((data == NULL) || (*data == '\0'))
139 {
140 g_set_error (error, MC_ERROR, 0, FUNC_NAME ": Input data is NULL or empty.");
141 return NULL;
142 }
143
144 if (*data != prefix)
145 {
146 g_set_error (error, MC_ERROR, 0, FUNC_NAME ": String prefix doesn't equal to '%c'", prefix);
147 return NULL;
148 }
149
150 {
151 char buffer[BUF_TINY];
152
153 const char *semi_ptr = strchr (data + 1, SRLZ_DELIM_C);
154 if (semi_ptr == NULL)
155 {
156 g_set_error (error, MC_ERROR, 0, FUNC_NAME ": Length delimiter '%c' doesn't exists",
157 SRLZ_DELIM_C);
158 return NULL;
159 }
160
161 const size_t semi_offset = semi_ptr - (data + 1);
162 if (semi_offset >= BUF_TINY)
163 {
164 g_set_error (error, MC_ERROR, 0, FUNC_NAME ": Too big string length");
165 return NULL;
166 }
167 strncpy (buffer, data + 1, semi_offset);
168 buffer[semi_offset] = '\0';
169 data_len = atol (buffer);
170 data += semi_offset + 2;
171 }
172
173 if (data_len > strlen (data))
174 {
175 g_set_error (error, MC_ERROR, 0,
176 FUNC_NAME
177 ": Specified data length (%zu) is greater than actual data length (%zu)",
178 data_len, strlen (data));
179 return NULL;
180 }
181 return g_strndup (data, data_len);
182 }
183
184 #undef FUNC_NAME
185
186
187
188
189
190
191
192
193
194
195
196 char *
197 mc_serialize_config (mc_config_t *data, GError **error)
198 {
199 gchar **groups, **group_iterator;
200 GString *buffer;
201
202 buffer = g_string_new ("");
203 groups = mc_config_get_groups (data, NULL);
204
205 for (group_iterator = groups; *group_iterator != NULL; group_iterator++)
206 {
207 char *serialized_str;
208 gchar **params, **param_iterator;
209
210 serialized_str = mc_serialize_str ('g', *group_iterator, error);
211 if (serialized_str == NULL)
212 {
213 g_string_free (buffer, TRUE);
214 g_strfreev (groups);
215 return NULL;
216 }
217 g_string_append (buffer, serialized_str);
218 g_free (serialized_str);
219
220 params = mc_config_get_keys (data, *group_iterator, NULL);
221
222 for (param_iterator = params; *param_iterator != NULL; param_iterator++)
223 {
224 char *value;
225
226 serialized_str = mc_serialize_str ('p', *param_iterator, error);
227 if (serialized_str == NULL)
228 {
229 g_string_free (buffer, TRUE);
230 g_strfreev (params);
231 g_strfreev (groups);
232 return NULL;
233 }
234 g_string_append (buffer, serialized_str);
235 g_free (serialized_str);
236
237 value = mc_config_get_string_raw (data, *group_iterator, *param_iterator, "");
238 serialized_str = mc_serialize_str ('v', value, error);
239 g_free (value);
240
241 if (serialized_str == NULL)
242 {
243 g_string_free (buffer, TRUE);
244 g_strfreev (params);
245 g_strfreev (groups);
246 return NULL;
247 }
248
249 g_string_append (buffer, serialized_str);
250 g_free (serialized_str);
251 }
252
253 g_strfreev (params);
254 }
255
256 g_strfreev (groups);
257
258 return g_string_free (buffer, FALSE);
259 }
260
261
262
263
264
265
266
267
268
269
270
271 #define FUNC_NAME "mc_deserialize_config()"
272 #define prepend_error_and_exit() \
273 { \
274 prepend_error_message (error, FUNC_NAME " at %zu", current_position + 1); \
275 mc_config_deinit (ret_data); \
276 return NULL; \
277 }
278
279 mc_config_t *
280 mc_deserialize_config (const char *data, GError **error)
281 {
282 char *current_group = NULL, *current_param = NULL, *current_value = NULL;
283 size_t current_position = 0;
284 mc_config_t *ret_data;
285 enum automat_status
286 {
287 WAIT_GROUP,
288 WAIT_PARAM,
289 WAIT_VALUE
290 } current_status = WAIT_GROUP;
291
292 ret_data = mc_config_init (NULL, FALSE);
293
294 while (data != NULL)
295 {
296 if ((current_status == WAIT_GROUP) && (*data == 'p') && (current_group != NULL))
297 current_status = WAIT_PARAM;
298
299 switch (current_status)
300 {
301 case WAIT_GROUP:
302 g_free (current_group);
303
304 current_group = mc_deserialize_str ('g', data, error);
305 if (current_group == NULL)
306 prepend_error_and_exit ();
307
308 data = go_to_end_of_serialized_string (data, current_group, ¤t_position);
309 current_status = WAIT_PARAM;
310 break;
311 case WAIT_PARAM:
312 g_free (current_param);
313
314 current_param = mc_deserialize_str ('p', data, error);
315 if (current_param == NULL)
316 {
317 g_free (current_group);
318 prepend_error_and_exit ();
319 }
320
321 data = go_to_end_of_serialized_string (data, current_param, ¤t_position);
322 current_status = WAIT_VALUE;
323 break;
324 case WAIT_VALUE:
325 current_value = mc_deserialize_str ('v', data, error);
326 if (current_value == NULL)
327 {
328 g_free (current_group);
329 g_free (current_param);
330 prepend_error_and_exit ();
331 }
332 mc_config_set_string (ret_data, current_group, current_param, current_value);
333
334 data = go_to_end_of_serialized_string (data, current_value, ¤t_position);
335 g_free (current_value);
336 current_status = WAIT_GROUP;
337 break;
338 default:
339 break;
340 }
341 }
342 g_free (current_group);
343 g_free (current_param);
344
345 return ret_data;
346 }
347
348 #undef FUNC_NAME
349
350