Fix invalid memory access
[platform/core/iot/iotcon.git] / lib / icl-resource-types.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 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <glib.h>
20
21 #include "iotcon-types.h"
22 #include "ic-utils.h"
23 #include "icl.h"
24 #include "icl-resource-types.h"
25
26 iotcon_resource_types_h icl_resource_types_ref(iotcon_resource_types_h types)
27 {
28         RETV_IF(NULL == types, NULL);
29         RETV_IF(types->ref_count <= 0, NULL);
30
31         types->ref_count++;
32
33         return types;
34 }
35
36
37 API int iotcon_resource_types_create(iotcon_resource_types_h *ret_types)
38 {
39         iotcon_resource_types_h types;
40
41         RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
42         RETV_IF(NULL == ret_types, IOTCON_ERROR_INVALID_PARAMETER);
43
44         types = calloc(1, sizeof(struct icl_resource_types));
45         if (NULL == types) {
46                 ERR("calloc() Fail(%d)", errno);
47                 return IOTCON_ERROR_OUT_OF_MEMORY;
48         }
49
50         types->ref_count = 1;
51
52         *ret_types = types;
53
54         return IOTCON_ERROR_NONE;
55 }
56
57
58 API void iotcon_resource_types_destroy(iotcon_resource_types_h types)
59 {
60         RET_IF(NULL == types);
61
62         types->ref_count--;
63
64         if (0 == types->ref_count) {
65                 g_list_free_full(types->type_list, free);
66                 free(types);
67         }
68 }
69
70
71 static int _icl_resource_types_strcmp(const void *a, const void *b)
72 {
73         return strcmp(a, b);
74 }
75
76
77 static bool _icl_resource_types_duplicate_check(iotcon_resource_types_h types,
78                 const char *type)
79 {
80         GList *found_node = NULL;
81
82         RETV_IF(NULL == types, false);
83         RETV_IF(NULL == type, false);
84
85         found_node = g_list_find_custom(types->type_list, type, _icl_resource_types_strcmp);
86         if (NULL == found_node)
87                 return false;
88
89         return true;
90 }
91
92
93 /* The length of resource type should be less than or equal to 61.
94  * Duplicate strings are not allowed. */
95 API int iotcon_resource_types_add(iotcon_resource_types_h types, const char *type)
96 {
97         char *resource_type;
98
99         RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
100         RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
101         RETV_IF(NULL == type, IOTCON_ERROR_INVALID_PARAMETER);
102         RETVM_IF(1 < types->ref_count, IOTCON_ERROR_INVALID_PARAMETER,
103                         "Don't modify it. It is already set.");
104
105         if (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(type)) {
106                 ERR("The length of type(%s) should be less than or equal to %d.", type,
107                                 ICL_RESOURCE_TYPE_LENGTH_MAX);
108                 return IOTCON_ERROR_INVALID_PARAMETER;
109         }
110
111         if (true == _icl_resource_types_duplicate_check(types, type)) {
112                 ERR("%s is already contained.", type);
113                 return IOTCON_ERROR_INVALID_PARAMETER;
114         }
115
116         resource_type = strdup(type);
117         if (NULL == resource_type) {
118                 ERR("strdup() Fail");
119                 return IOTCON_ERROR_INVALID_PARAMETER;
120         }
121
122         types->type_list = g_list_append(types->type_list, resource_type);
123
124         return IOTCON_ERROR_NONE;
125 }
126
127
128 API int iotcon_resource_types_remove(iotcon_resource_types_h types, const char *type)
129 {
130         GList *found_node;
131         char *node_data;
132
133         RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
134         RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
135         RETV_IF(NULL == type, IOTCON_ERROR_INVALID_PARAMETER);
136         RETVM_IF(1 < types->ref_count, IOTCON_ERROR_INVALID_PARAMETER,
137                         "Don't modify it. It is already set.");
138
139         found_node = g_list_find_custom(types->type_list, type, _icl_resource_types_strcmp);
140         if (NULL == found_node) {
141                 ERR("g_list_find_custom() Fail");
142                 return IOTCON_ERROR_NO_DATA;
143         }
144
145         node_data = found_node->data;
146         types->type_list = g_list_delete_link(types->type_list, found_node);
147         free(node_data);
148
149         return IOTCON_ERROR_NONE;
150 }
151
152
153 API int iotcon_resource_types_foreach(iotcon_resource_types_h types,
154                 iotcon_resource_types_foreach_cb cb, void *user_data)
155 {
156         GList *node;
157
158         RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
159         RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
160         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
161
162         for (node = types->type_list; node; node = node->next) {
163                 if (IOTCON_FUNC_STOP == cb((const char*)node->data, user_data))
164                         break;
165         }
166
167         return IOTCON_ERROR_NONE;
168 }
169
170
171 API int iotcon_resource_types_clone(iotcon_resource_types_h src,
172                 iotcon_resource_types_h *dest)
173 {
174         GList *node;
175         char *resource_type;
176         iotcon_resource_types_h resource_types;
177
178         RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
179         RETV_IF(NULL == src, IOTCON_ERROR_INVALID_PARAMETER);
180         RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
181
182         resource_types = calloc(1, sizeof(struct icl_resource_types));
183         if (NULL == resource_types) {
184                 ERR("calloc() Fail(%d)", errno);
185                 return IOTCON_ERROR_OUT_OF_MEMORY;
186         }
187
188         for (node = src->type_list; node; node = node->next) {
189                 resource_type = ic_utils_strdup(node->data);
190                 if (NULL == resource_type) {
191                         iotcon_resource_types_destroy(resource_types);
192                         ERR("ic_utils_strdup() Fail");
193                         return IOTCON_ERROR_OUT_OF_MEMORY;
194                 }
195                 resource_types->type_list = g_list_append(resource_types->type_list,
196                                 resource_type);
197         }
198
199         resource_types->ref_count = 1;
200
201         *dest = resource_types;
202
203         return IOTCON_ERROR_NONE;
204 }
205
206
207 /* counting from 0 */
208 const char* icl_resource_types_get_nth_data(iotcon_resource_types_h types, int index)
209 {
210         return g_list_nth_data(types->type_list, index);
211 }
212
213
214 unsigned int icl_resource_types_get_length(iotcon_resource_types_h types)
215 {
216         return g_list_length(types->type_list);
217 }