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