Remove iotcon_representation_del_state, Rename iotcon_representation_append_child
[platform/core/iot/iotcon.git] / lib / icl-representation.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <glib.h>
23
24 #include "iotcon-types.h"
25 #include "ic-utils.h"
26 #include "icl.h"
27 #include "icl-resource.h"
28 #include "icl-resource-types.h"
29 #include "icl-response.h"
30 #include "icl-list.h"
31 #include "icl-value.h"
32 #include "icl-state.h"
33 #include "icl-representation.h"
34
35 void icl_representation_inc_ref_count(iotcon_representation_h val)
36 {
37         RET_IF(NULL == val);
38         RETM_IF(val->ref_count < 0, "Invalid Count(%d)", val->ref_count);
39
40         val->ref_count++;
41 }
42
43
44 static bool _icl_representation_dec_ref_count(iotcon_representation_h val)
45 {
46         RETV_IF(NULL == val, false);
47         RETVM_IF(val->ref_count <= 0, false, "Invalid Count(%d)", val->ref_count);
48
49         val->ref_count--;
50         if (0 == val->ref_count)
51                 return true;
52
53         return false;
54 }
55
56
57 API int iotcon_representation_create(iotcon_representation_h *ret_repr)
58 {
59         errno = 0;
60         iotcon_representation_h repr;
61
62         RETV_IF(NULL == ret_repr, IOTCON_ERROR_INVALID_PARAMETER);
63
64         repr = calloc(1, sizeof(struct icl_representation_s));
65         if (NULL == repr) {
66                 ERR("calloc() Fail(%d)", errno);
67                 return IOTCON_ERROR_OUT_OF_MEMORY;
68         }
69
70         repr->visibility = (ICL_VISIBILITY_REPR | ICL_VISIBILITY_PROP);
71         icl_representation_inc_ref_count(repr);
72
73         *ret_repr = repr;
74
75         return IOTCON_ERROR_NONE;
76 }
77
78
79 API void iotcon_representation_destroy(iotcon_representation_h repr)
80 {
81         RET_IF(NULL == repr);
82
83         if (false == _icl_representation_dec_ref_count(repr))
84                 return;
85
86         free(repr->uri_path);
87
88         /* (GDestroyNotify) : iotcon_representation_h is proper type than gpointer */
89         g_list_free_full(repr->children, (GDestroyNotify)iotcon_representation_destroy);
90
91         /* null COULD be allowed */
92         if (repr->res_types)
93                 iotcon_resource_types_destroy(repr->res_types);
94
95         /* null COULD be allowed */
96         if (repr->state)
97                 iotcon_state_destroy(repr->state);
98
99         free(repr);
100 }
101
102
103 API int iotcon_representation_get_uri_path(iotcon_representation_h repr, char **uri_path)
104 {
105         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
106         RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
107
108         *uri_path = repr->uri_path;
109
110         return IOTCON_ERROR_NONE;
111 }
112
113 API int iotcon_representation_set_uri_path(iotcon_representation_h repr,
114                 const char *uri_path)
115 {
116         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
117         RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
118
119         free(repr->uri_path);
120         repr->uri_path = strdup(uri_path);
121         if (NULL == repr->uri_path) {
122                 ERR("strdup() Fail");
123                 return IOTCON_ERROR_OUT_OF_MEMORY;
124         }
125
126         return IOTCON_ERROR_NONE;
127 }
128
129 API int iotcon_representation_get_resource_types(iotcon_representation_h repr,
130                 iotcon_resource_types_h *types)
131 {
132         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
133         RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
134
135         *types = repr->res_types;
136
137         return IOTCON_ERROR_NONE;
138 }
139
140 API int iotcon_representation_set_resource_types(iotcon_representation_h repr,
141                 iotcon_resource_types_h types)
142 {
143         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
144
145         iotcon_resource_types_destroy(repr->res_types);
146         repr->res_types = NULL;
147
148         if (types)
149                 repr->res_types = icl_resource_types_ref(types);
150
151         return IOTCON_ERROR_NONE;
152 }
153
154 API int iotcon_representation_get_resource_interfaces(iotcon_representation_h repr,
155                 int *ifaces)
156 {
157         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
158
159         *ifaces = repr->interfaces;
160
161         return IOTCON_ERROR_NONE;
162 }
163
164 API int iotcon_representation_set_resource_interfaces(iotcon_representation_h repr,
165                 int ifaces)
166 {
167         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
168
169         RETV_IF(ifaces <= IOTCON_INTERFACE_NONE || IC_INTERFACE_MAX < ifaces,
170                         IOTCON_ERROR_INVALID_PARAMETER);
171
172         repr->interfaces = ifaces;
173
174         return IOTCON_ERROR_NONE;
175 }
176
177 API int iotcon_representation_set_state(iotcon_representation_h repr,
178                 iotcon_state_h state)
179 {
180         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
181
182         if (state == repr->state)
183                 return IOTCON_ERROR_NONE;
184
185         if (repr->state) {
186                 iotcon_state_destroy(repr->state);
187                 repr->state = NULL;
188         }
189
190         if (state)
191                 icl_state_inc_ref_count(state);
192
193         repr->state = state;
194
195         return IOTCON_ERROR_NONE;
196 }
197
198
199 API int iotcon_representation_get_state(iotcon_representation_h repr,
200                 iotcon_state_h *state)
201 {
202         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
203         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
204
205         *state = repr->state;
206
207         return IOTCON_ERROR_NONE;
208 }
209
210 API int iotcon_representation_add_child(iotcon_representation_h parent,
211                 iotcon_representation_h child)
212 {
213         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
214         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
215
216         icl_representation_inc_ref_count(child);
217         parent->children = g_list_append(parent->children, child);
218
219         return IOTCON_ERROR_NONE;
220 }
221
222
223 API int iotcon_representation_remove_child(iotcon_representation_h parent,
224                 iotcon_representation_h child)
225 {
226         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
227         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
228
229         parent->children = g_list_remove(parent->children, child);
230
231         return IOTCON_ERROR_NONE;
232 }
233
234
235 API int iotcon_representation_foreach_children(iotcon_representation_h parent,
236                 iotcon_children_cb cb, void *user_data)
237 {
238         GList *list, *next;
239
240         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
241         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
242
243         list = parent->children;
244         while (list) {
245                 next = list->next;
246                 if (IOTCON_FUNC_STOP == cb(list->data, user_data))
247                         break;
248                 list = next;
249         }
250
251         return IOTCON_ERROR_NONE;
252 }
253
254 API int iotcon_representation_get_children_count(iotcon_representation_h parent,
255                 unsigned int *count)
256 {
257         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
258         RETV_IF(NULL == parent->children, IOTCON_ERROR_INVALID_PARAMETER);
259
260         *count = g_list_length(parent->children);
261
262         return IOTCON_ERROR_NONE;
263 }
264
265 API int iotcon_representation_get_nth_child(iotcon_representation_h parent, int pos,
266                 iotcon_representation_h *child)
267 {
268         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
269         RETV_IF(NULL == parent->children, IOTCON_ERROR_INVALID_PARAMETER);
270         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
271
272         *child = g_list_nth_data(parent->children, pos);
273         if (NULL == *child) {
274                 ERR("g_list_nth_data() Fail");
275                 return IOTCON_ERROR_NO_DATA;
276         }
277
278         return IOTCON_ERROR_NONE;
279 }
280
281 API int iotcon_state_foreach(iotcon_state_h state, iotcon_state_cb cb, void *user_data)
282 {
283         GHashTableIter iter;
284         gpointer key;
285
286         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
287         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
288
289         g_hash_table_iter_init(&iter, state->hash_table);
290         while (g_hash_table_iter_next(&iter, &key, NULL)) {
291                 if (IOTCON_FUNC_STOP == cb(state, key, user_data))
292                         break;
293         }
294
295         return IOTCON_ERROR_NONE;
296 }
297
298
299 API int iotcon_state_get_keys_count(iotcon_state_h state, unsigned int *count)
300 {
301         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
302         RETV_IF(NULL == state->hash_table, IOTCON_ERROR_INVALID_PARAMETER);
303
304         *count = g_hash_table_size(state->hash_table);
305
306         return IOTCON_ERROR_NONE;
307 }
308
309
310 void icl_state_clone_foreach(char *key, iotcon_value_h src_val, iotcon_state_h dest_state)
311 {
312         FN_CALL;
313         int type, ret;
314         iotcon_value_h value, copied_val;
315         iotcon_list_h child_list, copied_list;
316         iotcon_state_h child_state;
317         iotcon_state_h copied_state = NULL;
318
319         type = src_val->type;
320         switch (type) {
321         case IOTCON_TYPE_INT:
322         case IOTCON_TYPE_BOOL:
323         case IOTCON_TYPE_DOUBLE:
324         case IOTCON_TYPE_STR:
325         case IOTCON_TYPE_NULL:
326                 copied_val = icl_value_clone(src_val);
327                 if (NULL == copied_val) {
328                         ERR("icl_value_clone() Fail");
329                         return;
330                 }
331
332                 icl_state_set_value(dest_state, key, copied_val);
333                 break;
334         case IOTCON_TYPE_LIST:
335                 ret = icl_value_get_list(src_val, &child_list);
336                 if (IOTCON_ERROR_NONE != ret) {
337                         ERR("icl_value_get_list() Fail(%d)", ret);
338                         return;
339                 }
340
341                 copied_list = icl_list_clone(child_list);
342                 if (NULL == copied_list) {
343                         ERR("icl_list_clone() Fail");
344                         return;
345                 }
346
347                 value = icl_value_create_list(copied_list);
348                 if (NULL == value) {
349                         ERR("icl_value_create_list() Fail");
350                         iotcon_list_destroy(copied_list);
351                         return;
352                 }
353
354                 icl_state_set_value(dest_state, key, value);
355                 break;
356         case IOTCON_TYPE_STATE:
357                 ret = icl_value_get_state(src_val, &child_state);
358                 if (IOTCON_ERROR_NONE != ret) {
359                         ERR("icl_value_get_state() Fail(%d)", ret);
360                         return;
361                 }
362
363                 g_hash_table_foreach(child_state->hash_table, (GHFunc)icl_state_clone_foreach,
364                                 copied_state);
365
366                 value = icl_value_create_state(copied_state);
367                 if (NULL == value) {
368                         ERR("icl_value_create_state(%p) Fail", copied_state);
369                         return;
370                 }
371
372                 icl_state_set_value(dest_state, key, value);
373                 break;
374         default:
375                 ERR("Invalid type(%d)", type);
376                 return;
377         }
378 }
379
380 API int iotcon_representation_clone(const iotcon_representation_h src,
381                 iotcon_representation_h *dest)
382 {
383         FN_CALL;
384         int ret;
385         GList *node;
386         iotcon_resource_types_h list;
387         iotcon_state_h ori_state;
388         iotcon_state_h cloned_state = NULL;
389         iotcon_representation_h cloned_repr, copied_repr;
390
391         RETV_IF(NULL == src, IOTCON_ERROR_INVALID_PARAMETER);
392
393         ret = iotcon_representation_create(&cloned_repr);
394         if (IOTCON_ERROR_NONE != ret) {
395                 ERR("iotcon_representation_create() Fail(%d)", ret);
396                 return ret;
397         }
398
399         if (src->uri_path) {
400                 cloned_repr->uri_path = strdup(src->uri_path);
401                 if (NULL == cloned_repr->uri_path) {
402                         ERR("strdup() Fail");
403                         iotcon_representation_destroy(cloned_repr);
404                         return IOTCON_ERROR_OUT_OF_MEMORY;
405                 }
406         }
407
408         if (src->interfaces)
409                 cloned_repr->interfaces = src->interfaces;
410
411         if (src->res_types) {
412                 ret = iotcon_resource_types_clone(src->res_types, &list);
413                 if (IOTCON_ERROR_NONE != ret) {
414                         ERR("iotcon_resource_types_clone() Fail");
415                         iotcon_representation_destroy(cloned_repr);
416                         return ret;
417                 }
418                 cloned_repr->res_types = list;
419         }
420
421         for (node = g_list_first(src->children); node; node = node->next) {
422                 ret = iotcon_representation_clone((iotcon_representation_h)node->data,
423                                 &copied_repr);
424                 if (IOTCON_ERROR_NONE != ret) {
425                         ERR("iotcon_representation_clone(child) Fail(%d)", ret);
426                         iotcon_representation_destroy(cloned_repr);
427                         return ret;
428                 }
429                 cloned_repr->children = g_list_append(cloned_repr->children, copied_repr);
430         }
431
432         ori_state = src->state;
433         if (ori_state->hash_table) {
434                 ret = iotcon_state_create(&cloned_state);
435                 if (IOTCON_ERROR_NONE != ret) {
436                         ERR("iotcon_state_create() Fail");
437                         iotcon_representation_destroy(cloned_repr);
438                         return ret;
439                 }
440                 g_hash_table_foreach(ori_state->hash_table, (GHFunc)icl_state_clone_foreach,
441                                 cloned_state);
442                 ret = iotcon_representation_set_state(cloned_repr, cloned_state);
443                 if (IOTCON_ERROR_NONE != ret) {
444                         ERR("iotcon_representation_set_state() Fail");
445                         iotcon_state_destroy(cloned_state);
446                         iotcon_representation_destroy(cloned_repr);
447                         return ret;
448                 }
449                 iotcon_state_destroy(cloned_state);
450         }
451
452         *dest = cloned_repr;
453
454         return IOTCON_ERROR_NONE;
455 }