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