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