4 * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 #include "ctsvc_internal.h"
22 #include "ctsvc_record.h"
23 #include "ctsvc_view.h"
24 #include "ctsvc_notify.h"
26 #ifdef _CONTACTS_IPC_SERVER
27 #include "ctsvc_server_sim.h"
28 #endif /* _CONTACTS_IPC_SERVER */
30 static int __ctsvc_result_create(contacts_record_h *out_record);
31 static int __ctsvc_result_destroy(contacts_record_h record, bool delete_child);
32 static int __ctsvc_result_clone(contacts_record_h record, contacts_record_h *out_record);
33 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str);
34 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str);
35 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value);
36 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value);
37 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty);
38 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty);
39 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty);
41 ctsvc_record_plugin_cb_s result_plugin_cbs = {
42 .create = __ctsvc_result_create,
43 .destroy = __ctsvc_result_destroy,
44 .clone = __ctsvc_result_clone,
45 .get_str = __ctsvc_result_get_str,
46 .get_str_p = __ctsvc_result_get_str_p,
47 .get_int = __ctsvc_result_get_int,
48 .get_bool = __ctsvc_result_get_bool,
51 .set_str = __ctsvc_result_set_str,
52 .set_int = __ctsvc_result_set_int,
53 .set_bool = __ctsvc_result_set_bool,
56 .add_child_record = NULL,
57 .remove_child_record = NULL,
58 .get_child_record_count = NULL,
59 .get_child_record_at_p = NULL,
60 .clone_child_record_list = NULL,
63 static int __ctsvc_result_create(contacts_record_h *out_record)
65 ctsvc_result_s *result;
66 result = calloc(1, sizeof(ctsvc_result_s));
67 RETVM_IF(NULL == result, CONTACTS_ERROR_OUT_OF_MEMORY, "calloc() Fail");
69 *out_record = (contacts_record_h)result;
70 return CONTACTS_ERROR_NONE;
73 static int __ctsvc_result_destroy(contacts_record_h record, bool delete_child)
76 ctsvc_result_s *result = (ctsvc_result_s*)record;
78 for (cursor = result->values; cursor; cursor = cursor->next) {
79 ctsvc_result_value_s *data = cursor->data;
80 if (data->type == CTSVC_VIEW_DATA_TYPE_STR)
84 g_slist_free(result->values);
85 result->base.plugin_cbs = NULL; /* help to find double destroy bug (refer to the contacts_record_destroy) */
86 free(result->base.properties_flags);
90 return CONTACTS_ERROR_NONE;
93 static int __ctsvc_result_clone(contacts_record_h record, contacts_record_h *out_record)
95 ctsvc_result_s *out_data = NULL;
96 ctsvc_result_s *src_data = NULL;
99 src_data = (ctsvc_result_s*)record;
100 out_data = calloc(1, sizeof(ctsvc_result_s));
101 RETVM_IF(NULL == out_data, CONTACTS_ERROR_OUT_OF_MEMORY,
102 "Out of memeory : calloc(ctsvc_result_s) Fail(%d)", CONTACTS_ERROR_OUT_OF_MEMORY);
104 for (cursor = src_data->values; cursor; cursor = cursor->next) {
105 ctsvc_result_value_s *src = cursor->data;
106 ctsvc_result_value_s *dest = calloc(1, sizeof(ctsvc_result_value_s));
108 /* LCOV_EXCL_START */
109 ERR("calloc() Fail");
110 __ctsvc_result_destroy((contacts_record_h)out_data, true);
111 return CONTACTS_ERROR_OUT_OF_MEMORY;
115 /* LCOV_EXCL_START */
116 dest->property_id = src->property_id;
117 dest->type = src->type;
119 case CTSVC_VIEW_DATA_TYPE_BOOL:
120 dest->value.b = src->value.b;
122 case CTSVC_VIEW_DATA_TYPE_INT:
123 dest->value.i = src->value.i;
125 case CTSVC_VIEW_DATA_TYPE_LLI:
126 dest->value.l = src->value.l;
128 case CTSVC_VIEW_DATA_TYPE_STR:
129 dest->value.s = SAFE_STRDUP(src->value.s);
131 case CTSVC_VIEW_DATA_TYPE_DOUBLE:
132 dest->value.d = src->value.d;
137 out_data->values = g_slist_append(out_data->values, (void*)dest);
141 int ret = ctsvc_record_copy_base(&(out_data->base), &(src_data->base));
142 if (CONTACTS_ERROR_NONE != ret) {
143 /* LCOV_EXCL_START */
144 ERR("ctsvc_record_copy_base() Fail");
145 __ctsvc_result_destroy((contacts_record_h)out_data, true);
150 *out_record = (contacts_record_h)out_data;
152 return CONTACTS_ERROR_NONE;
155 /* LCOV_EXCL_START */
156 static int __ctsvc_result_get_str_real(contacts_record_h record, unsigned int property_id,
157 char **out_str, bool copy)
159 ctsvc_result_s *result = (ctsvc_result_s*)record;
163 if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
164 ERR("property_id is not str type.");
165 return CONTACTS_ERROR_INVALID_PARAMETER;
168 for (cursor = result->values; cursor; cursor = cursor->next) {
169 ctsvc_result_value_s *data = cursor->data;
170 if (data->property_id == property_id) {
171 *out_str = GET_STR(copy, data->value.s);
172 return CONTACTS_ERROR_NONE;
176 return CONTACTS_ERROR_NO_DATA;
179 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
181 return __ctsvc_result_get_str_real(record, property_id, out_str, false);
184 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
186 return __ctsvc_result_get_str_real(record, property_id, out_str, true);
189 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
191 ctsvc_result_s *result = (ctsvc_result_s*)record;
195 if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
196 ERR("property_id is not int type.");
197 return CONTACTS_ERROR_INVALID_PARAMETER;
200 for (cursor = result->values; cursor; cursor = cursor->next) {
201 ctsvc_result_value_s *data = cursor->data;
202 if (data->property_id == property_id) {
203 *out_value = data->value.i;
204 return CONTACTS_ERROR_NONE;
208 return CONTACTS_ERROR_NO_DATA;
212 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty)
214 ctsvc_result_s *result = (ctsvc_result_s*)record;
216 ctsvc_result_value_s *data;
218 if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
219 ERR("property_id is not int type.");
220 return CONTACTS_ERROR_INVALID_PARAMETER;
223 for (cursor = result->values; cursor; cursor = cursor->next) {
225 if (data->property_id == property_id) {
226 #ifdef _CONTACTS_IPC_SERVER
227 if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
228 || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
229 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
230 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
232 #endif /* _CONTACTS_IPC_SERVER */
234 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
235 data->value.i = value;
237 return CONTACTS_ERROR_NONE;
241 data = calloc(1, sizeof(ctsvc_result_value_s));
243 /* LCOV_EXCL_START */
244 ERR("calloc() Fail");
245 return CONTACTS_ERROR_OUT_OF_MEMORY;
248 data->property_id = property_id;
249 data->type = CTSVC_VIEW_DATA_TYPE_INT;
250 #ifdef _CONTACTS_IPC_SERVER
251 if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
252 || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
253 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
254 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
256 #endif /* _CONTACTS_IPC_SERVER */
258 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
259 data->value.i = value;
261 result->values = g_slist_append(result->values, (void*)data);
262 return CONTACTS_ERROR_NONE;
265 /* LCOV_EXCL_START */
266 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty)
268 ctsvc_result_s *result = (ctsvc_result_s*)record;
270 ctsvc_result_value_s *data;
272 /* TODO: check the value type of property_id is int */
273 for (cursor = result->values; cursor; cursor = cursor->next) {
275 if (data->property_id == property_id) {
276 if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
277 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
278 data->value.b = value;
279 return CONTACTS_ERROR_NONE;
281 /* LCOV_EXCL_START */
282 ERR("use another get_type API, (type : %d)", data->type);
283 return CONTACTS_ERROR_INVALID_PARAMETER;
289 data = calloc(1, sizeof(ctsvc_result_value_s));
291 /* LCOV_EXCL_START */
292 ERR("calloc() Fail");
293 return CONTACTS_ERROR_OUT_OF_MEMORY;
296 data->property_id = property_id;
297 data->type = CTSVC_VIEW_DATA_TYPE_BOOL;
298 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
299 data->value.b = value;
300 result->values = g_slist_append(result->values, (void*)data);
301 return CONTACTS_ERROR_NONE;
304 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty)
306 ctsvc_result_s *result = (ctsvc_result_s*)record;
308 ctsvc_result_value_s *data;
309 char *full_path = NULL;
312 if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
313 ERR("property_id is not str type.");
314 return CONTACTS_ERROR_INVALID_PARAMETER;
317 for (cursor = result->values; cursor; cursor = cursor->next) {
319 if (data->property_id == property_id) {
320 switch (property_id) {
321 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
322 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
324 str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
325 full_path = calloc(1, str_len);
326 if (NULL == full_path) {
327 /* LCOV_EXCL_START */
328 ERR("calloc() Fail");
329 return CONTACTS_ERROR_OUT_OF_MEMORY;
332 snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
334 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
336 data->value.s = full_path;
337 return CONTACTS_ERROR_NONE;
339 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
340 FREEandSTRDUP(data->value.s, str);
341 return CONTACTS_ERROR_NONE;
346 data = calloc(1, sizeof(ctsvc_result_value_s));
348 /* LCOV_EXCL_START */
349 ERR("calloc() Fail");
350 return CONTACTS_ERROR_OUT_OF_MEMORY;
353 data->property_id = property_id;
354 data->type = CTSVC_VIEW_DATA_TYPE_STR;
355 switch (property_id) {
356 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
357 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
359 str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
360 full_path = calloc(1, str_len);
361 if (NULL == full_path) {
362 /* LCOV_EXCL_START */
363 ERR("calloc() Fail");
365 return CONTACTS_ERROR_OUT_OF_MEMORY;
368 snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
370 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
372 data->value.s = full_path;
375 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
376 data->value.s = SAFE_STRDUP(str);
380 result->values = g_slist_append(result->values, (void*)data);
381 return CONTACTS_ERROR_NONE;
384 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value)
386 ctsvc_result_s *result = (ctsvc_result_s*)record;
388 for (cursor = result->values; cursor; cursor = cursor->next) {
389 ctsvc_result_value_s *data = cursor->data;
390 if (data->property_id == property_id) {
391 if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
392 *out_value = data->value.b;
393 return CONTACTS_ERROR_NONE;
395 /* LCOV_EXCL_START */
396 ERR("use another get_type API, (type : %d)", data->type);
397 return CONTACTS_ERROR_INVALID_PARAMETER;
403 return CONTACTS_ERROR_NO_DATA;