revise header hierarchy
[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         bool ret;
47
48         RETV_IF(NULL == val, -1);
49         RETVM_IF(val->ref_count <= 0, false, "Invalid Count(%d)", val->ref_count);
50
51         val->ref_count--;
52         if (0 == val->ref_count)
53                 ret = true;
54         else
55                 ret = false;
56
57         return ret;
58 }
59
60
61 API int iotcon_representation_create(iotcon_representation_h *ret_repr)
62 {
63         errno = 0;
64         iotcon_representation_h repr;
65
66         RETV_IF(NULL == ret_repr, IOTCON_ERROR_INVALID_PARAMETER);
67
68         repr = calloc(1, sizeof(struct icl_representation_s));
69         if (NULL == repr) {
70                 ERR("calloc() Fail(%d)", errno);
71                 return IOTCON_ERROR_OUT_OF_MEMORY;
72         }
73
74         repr->visibility = (ICL_VISIBILITY_REPR | ICL_VISIBILITY_PROP);
75         icl_representation_inc_ref_count(repr);
76
77         *ret_repr = repr;
78
79         return IOTCON_ERROR_NONE;
80 }
81
82
83 API void iotcon_representation_destroy(iotcon_representation_h repr)
84 {
85         RET_IF(NULL == repr);
86
87         if (false == _icl_representation_dec_ref_count(repr))
88                 return;
89
90         free(repr->uri_path);
91
92         /* (GDestroyNotify) : iotcon_representation_h is proper type than gpointer */
93         g_list_free_full(repr->children, (GDestroyNotify)iotcon_representation_destroy);
94
95         /* null COULD be allowed */
96         if (repr->res_types)
97                 iotcon_resource_types_destroy(repr->res_types);
98
99         /* null COULD be allowed */
100         if (repr->state)
101                 iotcon_state_destroy(repr->state);
102
103         free(repr);
104 }
105
106
107 API int iotcon_representation_get_uri_path(iotcon_representation_h repr, char **uri_path)
108 {
109         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
110         RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
111
112         *uri_path = repr->uri_path;
113
114         return IOTCON_ERROR_NONE;
115 }
116
117 API int iotcon_representation_set_uri_path(iotcon_representation_h repr,
118                 const char *uri_path)
119 {
120         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
121
122         free(repr->uri_path);
123         repr->uri_path = NULL;
124
125         if (NULL == uri_path)
126                 return IOTCON_ERROR_INVALID_PARAMETER;
127
128         repr->uri_path = strdup(uri_path);
129         if (NULL == repr->uri_path) {
130                 ERR("strdup() Fail");
131                 return IOTCON_ERROR_OUT_OF_MEMORY;
132         }
133
134         return IOTCON_ERROR_NONE;
135 }
136
137 API int iotcon_representation_get_resource_types(iotcon_representation_h repr,
138                 iotcon_resource_types_h *types)
139 {
140         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
141         RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
142
143         *types = repr->res_types;
144
145         return IOTCON_ERROR_NONE;
146 }
147
148 API int iotcon_representation_set_resource_types(iotcon_representation_h repr,
149                 iotcon_resource_types_h types)
150 {
151         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
152
153         iotcon_resource_types_destroy(repr->res_types);
154         repr->res_types = NULL;
155
156         if (types)
157                 repr->res_types = icl_resource_types_ref(types);
158
159         return IOTCON_ERROR_NONE;
160 }
161
162 API int iotcon_representation_get_resource_interfaces(iotcon_representation_h repr,
163                 int *ifaces)
164 {
165         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
166
167         *ifaces = repr->interfaces;
168
169         return IOTCON_ERROR_NONE;
170 }
171
172 API int iotcon_representation_set_resource_interfaces(iotcon_representation_h repr,
173                 int ifaces)
174 {
175         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
176
177         RETV_IF(ifaces <= IOTCON_INTERFACE_NONE || IC_INTERFACE_MAX < ifaces,
178                         IOTCON_ERROR_INVALID_PARAMETER);
179
180         repr->interfaces = ifaces;
181
182         return IOTCON_ERROR_NONE;
183 }
184
185
186 API int iotcon_representation_set_state(iotcon_representation_h repr,
187                 iotcon_state_h state)
188 {
189         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
190         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
191
192         if (repr->state) {
193                 ERR("state already set. Remove first !");
194                 return IOTCON_ERROR_ALREADY;
195         }
196
197         icl_state_inc_ref_count(state);
198         repr->state = state;
199
200         return IOTCON_ERROR_NONE;
201 }
202
203
204 API int iotcon_representation_get_state(iotcon_representation_h repr,
205                 iotcon_state_h *state)
206 {
207         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
208         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
209
210         *state = repr->state;
211
212         return IOTCON_ERROR_NONE;
213 }
214
215
216 API int iotcon_representation_del_state(iotcon_representation_h repr)
217 {
218         RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
219
220         if (repr->state)
221                 iotcon_state_destroy(repr->state);
222
223         return IOTCON_ERROR_NONE;
224 }
225
226
227 API int iotcon_representation_append_child(iotcon_representation_h parent,
228                 iotcon_representation_h child)
229 {
230         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
231         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
232
233         icl_representation_inc_ref_count(child);
234         parent->children = g_list_append(parent->children, child);
235
236         return IOTCON_ERROR_NONE;
237 }
238
239
240 API int iotcon_representation_remove_child(iotcon_representation_h parent,
241                 iotcon_representation_h child)
242 {
243         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
244         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
245
246         parent->children = g_list_remove(parent->children, child);
247
248         return IOTCON_ERROR_NONE;
249 }
250
251
252 API int iotcon_representation_foreach_children(iotcon_representation_h parent,
253                 iotcon_children_cb cb, void *user_data)
254 {
255         GList *list, *next;
256
257         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
258         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
259
260         list = parent->children;
261         while (list) {
262                 next = list->next;
263                 if (IOTCON_FUNC_STOP == cb(list->data, user_data))
264                         break;
265                 list = next;
266         }
267
268         return IOTCON_ERROR_NONE;
269 }
270
271 API int iotcon_representation_get_children_count(iotcon_representation_h parent,
272                 unsigned int *count)
273 {
274         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
275         RETV_IF(NULL == parent->children, IOTCON_ERROR_INVALID_PARAMETER);
276
277         *count = g_list_length(parent->children);
278
279         return IOTCON_ERROR_NONE;
280 }
281
282 API int iotcon_representation_get_nth_child(iotcon_representation_h parent, int pos,
283                 iotcon_representation_h *child)
284 {
285         RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
286         RETV_IF(NULL == parent->children, IOTCON_ERROR_INVALID_PARAMETER);
287         RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
288
289         *child = g_list_nth_data(parent->children, pos);
290         if (NULL == *child) {
291                 ERR("g_list_nth_data() Fail");
292                 return IOTCON_ERROR_NO_DATA;
293         }
294
295         return IOTCON_ERROR_NONE;
296 }
297
298 API int iotcon_state_foreach(iotcon_state_h state, iotcon_state_cb cb, void *user_data)
299 {
300         GHashTableIter iter;
301         gpointer key;
302
303         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
304         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
305
306         g_hash_table_iter_init(&iter, state->hash_table);
307         while (g_hash_table_iter_next(&iter, &key, NULL)) {
308                 if (IOTCON_FUNC_STOP == cb(state, key, user_data))
309                         break;
310         }
311
312         return IOTCON_ERROR_NONE;
313 }
314
315
316 API int iotcon_state_get_keys_count(iotcon_state_h state, unsigned int *count)
317 {
318         RETV_IF(NULL == state, IOTCON_ERROR_INVALID_PARAMETER);
319         RETV_IF(NULL == state->hash_table, IOTCON_ERROR_INVALID_PARAMETER);
320
321         *count = g_hash_table_size(state->hash_table);
322
323         return IOTCON_ERROR_NONE;
324 }
325
326
327 void icl_state_clone_foreach(char *key, iotcon_value_h src_val, iotcon_state_h dest_state)
328 {
329         FN_CALL;
330         int type, ret;
331         iotcon_value_h value, copied_val;
332         iotcon_list_h child_list, copied_list;
333         iotcon_state_h child_state;
334         iotcon_state_h copied_state = NULL;
335
336         type = src_val->type;
337         switch (type) {
338         case IOTCON_TYPE_INT:
339         case IOTCON_TYPE_BOOL:
340         case IOTCON_TYPE_DOUBLE:
341         case IOTCON_TYPE_STR:
342         case IOTCON_TYPE_NULL:
343                 copied_val = icl_value_clone(src_val);
344                 if (NULL == copied_val) {
345                         ERR("icl_value_clone() Fail");
346                         return;
347                 }
348
349                 icl_state_set_value(dest_state, key, copied_val);
350                 break;
351         case IOTCON_TYPE_LIST:
352                 ret = icl_value_get_list(src_val, &child_list);
353                 if (IOTCON_ERROR_NONE != ret) {
354                         ERR("icl_value_get_list() Fail(%d)", ret);
355                         return;
356                 }
357
358                 copied_list = icl_list_clone(child_list);
359                 if (NULL == copied_list) {
360                         ERR("icl_list_clone() Fail");
361                         return;
362                 }
363
364                 value = icl_value_create_list(copied_list);
365                 if (NULL == value) {
366                         ERR("icl_value_create_list() Fail");
367                         iotcon_list_destroy(copied_list);
368                         return;
369                 }
370
371                 icl_state_set_value(dest_state, key, value);
372                 break;
373         case IOTCON_TYPE_STATE:
374                 ret = icl_value_get_state(src_val, &child_state);
375                 if (IOTCON_ERROR_NONE != ret) {
376                         ERR("icl_value_get_state() Fail(%d)", ret);
377                         return;
378                 }
379
380                 g_hash_table_foreach(child_state->hash_table, (GHFunc)icl_state_clone_foreach,
381                                 copied_state);
382
383                 value = icl_value_create_state(copied_state);
384                 if (NULL == value) {
385                         ERR("icl_value_create_state(%p) Fail", copied_state);
386                         return;
387                 }
388
389                 icl_state_set_value(dest_state, key, value);
390                 break;
391         default:
392                 ERR("Invalid type(%d)", type);
393                 return;
394         }
395 }
396
397 API int iotcon_representation_clone(const iotcon_representation_h src,
398                 iotcon_representation_h *dest)
399 {
400         FN_CALL;
401         int ret;
402         GList *node;
403         iotcon_resource_types_h list;
404         iotcon_state_h ori_state;
405         iotcon_state_h cloned_state = NULL;
406         iotcon_representation_h cloned_repr, copied_repr;
407
408         RETV_IF(NULL == src, IOTCON_ERROR_INVALID_PARAMETER);
409
410         ret = iotcon_representation_create(&cloned_repr);
411         if (IOTCON_ERROR_NONE != ret) {
412                 ERR("iotcon_representation_create() Fail(%d)", ret);
413                 return ret;
414         }
415
416         if (src->uri_path) {
417                 cloned_repr->uri_path = strdup(src->uri_path);
418                 if (NULL == cloned_repr->uri_path) {
419                         ERR("strdup() Fail");
420                         iotcon_representation_destroy(cloned_repr);
421                         return IOTCON_ERROR_OUT_OF_MEMORY;
422                 }
423         }
424
425         if (src->interfaces)
426                 cloned_repr->interfaces = src->interfaces;
427
428         if (src->res_types) {
429                 ret = iotcon_resource_types_clone(src->res_types, &list);
430                 if (IOTCON_ERROR_NONE != ret) {
431                         ERR("iotcon_resource_types_clone() Fail");
432                         iotcon_representation_destroy(cloned_repr);
433                         return ret;
434                 }
435                 cloned_repr->res_types = list;
436         }
437
438         for (node = g_list_first(src->children); node; node = node->next) {
439                 ret = iotcon_representation_clone((iotcon_representation_h)node->data,
440                                 &copied_repr);
441                 if (IOTCON_ERROR_NONE != ret) {
442                         ERR("iotcon_representation_clone(child) Fail(%d)", ret);
443                         iotcon_representation_destroy(cloned_repr);
444                         return ret;
445                 }
446                 cloned_repr->children = g_list_append(cloned_repr->children, copied_repr);
447         }
448
449         ori_state = src->state;
450         if (ori_state->hash_table) {
451                 ret = iotcon_state_create(&cloned_state);
452                 if (IOTCON_ERROR_NONE != ret) {
453                         ERR("iotcon_state_create() Fail");
454                         iotcon_representation_destroy(cloned_repr);
455                         return ret;
456                 }
457                 g_hash_table_foreach(ori_state->hash_table, (GHFunc)icl_state_clone_foreach,
458                                 cloned_state);
459                 ret = iotcon_representation_set_state(cloned_repr, cloned_state);
460                 if (IOTCON_ERROR_NONE != ret) {
461                         ERR("iotcon_representation_set_state() Fail");
462                         iotcon_state_destroy(cloned_state);
463                         iotcon_representation_destroy(cloned_repr);
464                         return ret;
465                 }
466                 iotcon_state_destroy(cloned_state);
467         }
468
469         *dest = cloned_repr;
470
471         return IOTCON_ERROR_NONE;
472 }