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)
86 g_slist_free(result->values);
87 result->base.plugin_cbs = NULL; /* help to find double destroy bug (refer to the contacts_record_destroy) */
88 free(result->base.properties_flags);
92 return CONTACTS_ERROR_NONE;
95 static int __ctsvc_result_clone(contacts_record_h record, contacts_record_h *out_record)
97 ctsvc_result_s *out_data = NULL;
98 ctsvc_result_s *src_data = NULL;
101 src_data = (ctsvc_result_s*)record;
102 out_data = calloc(1, sizeof(ctsvc_result_s));
103 RETVM_IF(NULL == out_data, CONTACTS_ERROR_OUT_OF_MEMORY,
104 "Out of memeory : calloc(ctsvc_result_s) Fail(%d)", CONTACTS_ERROR_OUT_OF_MEMORY);
106 for (cursor = src_data->values; cursor; cursor = cursor->next) {
107 ctsvc_result_value_s *src = cursor->data;
108 ctsvc_result_value_s *dest = calloc(1, sizeof(ctsvc_result_value_s));
110 /* LCOV_EXCL_START */
111 ERR("calloc() Fail");
112 __ctsvc_result_destroy((contacts_record_h)out_data, true);
113 return CONTACTS_ERROR_OUT_OF_MEMORY;
117 /* LCOV_EXCL_START */
118 dest->property_id = src->property_id;
119 dest->type = src->type;
121 case CTSVC_VIEW_DATA_TYPE_BOOL:
122 dest->value.b = src->value.b;
124 case CTSVC_VIEW_DATA_TYPE_INT:
125 dest->value.i = src->value.i;
127 case CTSVC_VIEW_DATA_TYPE_LLI:
128 dest->value.l = src->value.l;
130 case CTSVC_VIEW_DATA_TYPE_STR:
131 dest->value.s = SAFE_STRDUP(src->value.s);
133 case CTSVC_VIEW_DATA_TYPE_DOUBLE:
134 dest->value.d = src->value.d;
139 out_data->values = g_slist_append(out_data->values, (void*)dest);
143 int ret = ctsvc_record_copy_base(&(out_data->base), &(src_data->base));
144 if (CONTACTS_ERROR_NONE != ret) {
145 /* LCOV_EXCL_START */
146 ERR("ctsvc_record_copy_base() Fail");
147 __ctsvc_result_destroy((contacts_record_h)out_data, true);
152 *out_record = (contacts_record_h)out_data;
154 return CONTACTS_ERROR_NONE;
157 /* LCOV_EXCL_START */
158 static int __ctsvc_result_get_str_real(contacts_record_h record, unsigned int property_id,
159 char **out_str, bool copy)
161 ctsvc_result_s *result = (ctsvc_result_s*)record;
165 if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
166 ERR("property_id is not str type.");
167 return CONTACTS_ERROR_INVALID_PARAMETER;
170 for (cursor = result->values; cursor; cursor = cursor->next) {
171 ctsvc_result_value_s *data = cursor->data;
172 if (data->property_id == property_id) {
173 *out_str = GET_STR(copy, data->value.s);
174 return CONTACTS_ERROR_NONE;
178 return CONTACTS_ERROR_NO_DATA;
181 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
183 return __ctsvc_result_get_str_real(record, property_id, out_str, false);
186 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
188 return __ctsvc_result_get_str_real(record, property_id, out_str, true);
191 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
193 ctsvc_result_s *result = (ctsvc_result_s*)record;
197 if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
198 ERR("property_id is not int type.");
199 return CONTACTS_ERROR_INVALID_PARAMETER;
202 for (cursor = result->values; cursor; cursor = cursor->next) {
203 ctsvc_result_value_s *data = cursor->data;
204 if (data->property_id == property_id) {
205 *out_value = data->value.i;
206 return CONTACTS_ERROR_NONE;
210 return CONTACTS_ERROR_NO_DATA;
214 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty)
216 ctsvc_result_s *result = (ctsvc_result_s*)record;
218 ctsvc_result_value_s *data;
220 if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
221 /* LCOV_EXCL_START */
222 ERR("property_id is not int type.");
223 return CONTACTS_ERROR_INVALID_PARAMETER;
227 for (cursor = result->values; cursor; cursor = cursor->next) {
229 if (data->property_id == property_id) {
230 #ifdef _CONTACTS_IPC_SERVER
231 /* LCOV_EXCL_START */
232 if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
233 || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
234 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
235 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
237 #endif /* _CONTACTS_IPC_SERVER */
239 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
240 data->value.i = value;
242 return CONTACTS_ERROR_NONE;
247 data = calloc(1, sizeof(ctsvc_result_value_s));
249 /* LCOV_EXCL_START */
250 ERR("calloc() Fail");
251 return CONTACTS_ERROR_OUT_OF_MEMORY;
254 data->property_id = property_id;
255 data->type = CTSVC_VIEW_DATA_TYPE_INT;
256 #ifdef _CONTACTS_IPC_SERVER
257 if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
258 || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
259 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
260 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
262 #endif /* _CONTACTS_IPC_SERVER */
264 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
265 data->value.i = value;
267 result->values = g_slist_append(result->values, (void*)data);
268 return CONTACTS_ERROR_NONE;
271 /* LCOV_EXCL_START */
272 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty)
274 ctsvc_result_s *result = (ctsvc_result_s*)record;
276 ctsvc_result_value_s *data;
278 /* TODO: check the value type of property_id is int */
279 for (cursor = result->values; cursor; cursor = cursor->next) {
281 if (data->property_id == property_id) {
282 if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
283 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
284 data->value.b = value;
285 return CONTACTS_ERROR_NONE;
287 ERR("use another get_type API, (type : %d)", data->type);
288 return CONTACTS_ERROR_INVALID_PARAMETER;
293 data = calloc(1, sizeof(ctsvc_result_value_s));
295 ERR("calloc() Fail");
296 return CONTACTS_ERROR_OUT_OF_MEMORY;
298 data->property_id = property_id;
299 data->type = CTSVC_VIEW_DATA_TYPE_BOOL;
300 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
301 data->value.b = value;
302 result->values = g_slist_append(result->values, (void*)data);
303 return CONTACTS_ERROR_NONE;
306 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty)
308 ctsvc_result_s *result = (ctsvc_result_s*)record;
310 ctsvc_result_value_s *data;
311 char *full_path = NULL;
314 if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
315 ERR("property_id is not str type.");
316 return CONTACTS_ERROR_INVALID_PARAMETER;
319 for (cursor = result->values; cursor; cursor = cursor->next) {
321 if (data->property_id == property_id) {
322 switch (property_id) {
323 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
324 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
326 str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
327 full_path = calloc(1, str_len);
328 if (NULL == full_path) {
329 ERR("calloc() Fail");
330 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 ERR("calloc() Fail");
349 return CONTACTS_ERROR_OUT_OF_MEMORY;
351 data->property_id = property_id;
352 data->type = CTSVC_VIEW_DATA_TYPE_STR;
353 switch (property_id) {
354 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
355 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
357 str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
358 full_path = calloc(1, str_len);
359 if (NULL == full_path) {
360 ERR("calloc() Fail");
362 return CONTACTS_ERROR_OUT_OF_MEMORY;
364 snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
366 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
368 data->value.s = full_path;
371 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
372 data->value.s = SAFE_STRDUP(str);
376 result->values = g_slist_append(result->values, (void*)data);
377 return CONTACTS_ERROR_NONE;
380 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value)
382 ctsvc_result_s *result = (ctsvc_result_s*)record;
384 for (cursor = result->values; cursor; cursor = cursor->next) {
385 ctsvc_result_value_s *data = cursor->data;
386 if (data->property_id == property_id) {
387 if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
388 *out_value = data->value.b;
389 return CONTACTS_ERROR_NONE;
391 ERR("use another get_type API, (type : %d)", data->type);
392 return CONTACTS_ERROR_INVALID_PARAMETER;
397 return CONTACTS_ERROR_NO_DATA;