Fix internal logic
[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
178 API int iotcon_representation_set_state(iotcon_representation_h repr,
179                 iotcon_state_h state)
180 {
181         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
182         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
183
184         if (repr->state) {
185                 ERR("state already set. Remove first !");
186                 return IOTCON_ERROR_ALREADY;
187         }
188
189         icl_state_inc_ref_count(state);
190         repr->state = state;
191
192         return IOTCON_ERROR_NONE;
193 }
194
195
196 API int iotcon_representation_get_state(iotcon_representation_h repr,
197                 iotcon_state_h *state)
198 {
199         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
200         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
201
202         *state = repr->state;
203
204         return IOTCON_ERROR_NONE;
205 }
206
207
208 API int iotcon_representation_del_state(iotcon_representation_h repr)
209 {
210         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
211
212         if (repr->state)
213                 iotcon_state_destroy(repr->state);
214
215         return IOTCON_ERROR_NONE;
216 }
217
218
219 API int iotcon_representation_append_child(iotcon_representation_h parent,
220                 iotcon_representation_h child)
221 {
222         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
223         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
224
225         icl_representation_inc_ref_count(child);
226         parent->children = g_list_append(parent->children, child);
227
228         return IOTCON_ERROR_NONE;
229 }
230
231
232 API int iotcon_representation_remove_child(iotcon_representation_h parent,
233                 iotcon_representation_h child)
234 {
235         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
236         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
237
238         parent->children = g_list_remove(parent->children, child);
239
240         return IOTCON_ERROR_NONE;
241 }
242
243
244 API int iotcon_representation_foreach_children(iotcon_representation_h parent,
245                 iotcon_children_cb cb, void *user_data)
246 {
247         GList *list, *next;
248
249         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
250         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
251
252         list = parent->children;
253         while (list) {
254                 next = list->next;
255                 if (IOTCON_FUNC_STOP == cb(list->data, user_data))
256                         break;
257                 list = next;
258         }
259
260         return IOTCON_ERROR_NONE;
261 }
262
263 API int iotcon_representation_get_children_count(iotcon_representation_h parent,
264                 unsigned int *count)
265 {
266         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
267         RETV_IF(NULL == parent->children, IOTCON_ERROR_INVALID_PARAMETER);
268
269         *count = g_list_length(parent->children);
270
271         return IOTCON_ERROR_NONE;
272 }
273
274 API int iotcon_representation_get_nth_child(iotcon_representation_h parent, int pos,
275                 iotcon_representation_h *child)
276 {
277         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
278         RETV_IF(NULL == parent->children, IOTCON_ERROR_INVALID_PARAMETER);
279         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
280
281         *child = g_list_nth_data(parent->children, pos);
282         if (NULL == *child) {
283                 ERR("g_list_nth_data() Fail");
284                 return IOTCON_ERROR_NO_DATA;
285         }
286
287         return IOTCON_ERROR_NONE;
288 }
289
290 API int iotcon_state_foreach(iotcon_state_h state, iotcon_state_cb cb, void *user_data)
291 {
292         GHashTableIter iter;
293         gpointer key;
294
295         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
296         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
297
298         g_hash_table_iter_init(&iter, state->hash_table);
299         while (g_hash_table_iter_next(&iter, &key, NULL)) {
300                 if (IOTCON_FUNC_STOP == cb(state, key, user_data))
301                         break;
302         }
303
304         return IOTCON_ERROR_NONE;
305 }
306
307
308 API int iotcon_state_get_keys_count(iotcon_state_h state, unsigned int *count)
309 {
310         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
311         RETV_IF(NULL == state->hash_table, IOTCON_ERROR_INVALID_PARAMETER);
312
313         *count = g_hash_table_size(state->hash_table);
314
315         return IOTCON_ERROR_NONE;
316 }
317
318
319 void icl_state_clone_foreach(char *key, iotcon_value_h src_val, iotcon_state_h dest_state)
320 {
321         FN_CALL;
322         int type, ret;
323         iotcon_value_h value, copied_val;
324         iotcon_list_h child_list, copied_list;
325         iotcon_state_h child_state;
326         iotcon_state_h copied_state = NULL;
327
328         type = src_val->type;
329         switch (type) {
330         case IOTCON_TYPE_INT:
331         case IOTCON_TYPE_BOOL:
332         case IOTCON_TYPE_DOUBLE:
333         case IOTCON_TYPE_STR:
334         case IOTCON_TYPE_NULL:
335                 copied_val = icl_value_clone(src_val);
336                 if (NULL == copied_val) {
337                         ERR("icl_value_clone() Fail");
338                         return;
339                 }
340
341                 icl_state_set_value(dest_state, key, copied_val);
342                 break;
343         case IOTCON_TYPE_LIST:
344                 ret = icl_value_get_list(src_val, &child_list);
345                 if (IOTCON_ERROR_NONE != ret) {
346                         ERR("icl_value_get_list() Fail(%d)", ret);
347                         return;
348                 }
349
350                 copied_list = icl_list_clone(child_list);
351                 if (NULL == copied_list) {
352                         ERR("icl_list_clone() Fail");
353                         return;
354                 }
355
356                 value = icl_value_create_list(copied_list);
357                 if (NULL == value) {
358                         ERR("icl_value_create_list() Fail");
359                         iotcon_list_destroy(copied_list);
360                         return;
361                 }
362
363                 icl_state_set_value(dest_state, key, value);
364                 break;
365         case IOTCON_TYPE_STATE:
366                 ret = icl_value_get_state(src_val, &child_state);
367                 if (IOTCON_ERROR_NONE != ret) {
368                         ERR("icl_value_get_state() Fail(%d)", ret);
369                         return;
370                 }
371
372                 g_hash_table_foreach(child_state->hash_table, (GHFunc)icl_state_clone_foreach,
373                                 copied_state);
374
375                 value = icl_value_create_state(copied_state);
376                 if (NULL == value) {
377                         ERR("icl_value_create_state(%p) Fail", copied_state);
378                         return;
379                 }
380
381                 icl_state_set_value(dest_state, key, value);
382                 break;
383         default:
384                 ERR("Invalid type(%d)", type);
385                 return;
386         }
387 }
388
389 API int iotcon_representation_clone(const iotcon_representation_h src,
390                 iotcon_representation_h *dest)
391 {
392         FN_CALL;
393         int ret;
394         GList *node;
395         iotcon_resource_types_h list;
396         iotcon_state_h ori_state;
397         iotcon_state_h cloned_state = NULL;
398         iotcon_representation_h cloned_repr, copied_repr;
399
400         RETV_IF(NULL == src, IOTCON_ERROR_INVALID_PARAMETER);
401
402         ret = iotcon_representation_create(&cloned_repr);
403         if (IOTCON_ERROR_NONE != ret) {
404                 ERR("iotcon_representation_create() Fail(%d)", ret);
405                 return ret;
406         }
407
408         if (src->uri_path) {
409                 cloned_repr->uri_path = strdup(src->uri_path);
410                 if (NULL == cloned_repr->uri_path) {
411                         ERR("strdup() Fail");
412                         iotcon_representation_destroy(cloned_repr);
413                         return IOTCON_ERROR_OUT_OF_MEMORY;
414                 }
415         }
416
417         if (src->interfaces)
418                 cloned_repr->interfaces = src->interfaces;
419
420         if (src->res_types) {
421                 ret = iotcon_resource_types_clone(src->res_types, &list);
422                 if (IOTCON_ERROR_NONE != ret) {
423                         ERR("iotcon_resource_types_clone() Fail");
424                         iotcon_representation_destroy(cloned_repr);
425                         return ret;
426                 }
427                 cloned_repr->res_types = list;
428         }
429
430         for (node = g_list_first(src->children); node; node = node->next) {
431                 ret = iotcon_representation_clone((iotcon_representation_h)node->data,
432                                 &copied_repr);
433                 if (IOTCON_ERROR_NONE != ret) {
434                         ERR("iotcon_representation_clone(child) Fail(%d)", ret);
435                         iotcon_representation_destroy(cloned_repr);
436                         return ret;
437                 }
438                 cloned_repr->children = g_list_append(cloned_repr->children, copied_repr);
439         }
440
441         ori_state = src->state;
442         if (ori_state->hash_table) {
443                 ret = iotcon_state_create(&cloned_state);
444                 if (IOTCON_ERROR_NONE != ret) {
445                         ERR("iotcon_state_create() Fail");
446                         iotcon_representation_destroy(cloned_repr);
447                         return ret;
448                 }
449                 g_hash_table_foreach(ori_state->hash_table, (GHFunc)icl_state_clone_foreach,
450                                 cloned_state);
451                 ret = iotcon_representation_set_state(cloned_repr, cloned_state);
452                 if (IOTCON_ERROR_NONE != ret) {
453                         ERR("iotcon_representation_set_state() Fail");
454                         iotcon_state_destroy(cloned_state);
455                         iotcon_representation_destroy(cloned_repr);
456                         return ret;
457                 }
458                 iotcon_state_destroy(cloned_state);
459         }
460
461         *dest = cloned_repr;
462
463         return IOTCON_ERROR_NONE;
464 }