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 ERR("calloc() Fail");
109 __ctsvc_result_destroy((contacts_record_h)out_data, true);
110 return CONTACTS_ERROR_OUT_OF_MEMORY;
113 dest->property_id = src->property_id;
114 dest->type = src->type;
116 case CTSVC_VIEW_DATA_TYPE_BOOL:
117 dest->value.b = src->value.b;
119 case CTSVC_VIEW_DATA_TYPE_INT:
120 dest->value.i = src->value.i;
122 case CTSVC_VIEW_DATA_TYPE_LLI:
123 dest->value.l = src->value.l;
125 case CTSVC_VIEW_DATA_TYPE_STR:
126 dest->value.s = SAFE_STRDUP(src->value.s);
128 case CTSVC_VIEW_DATA_TYPE_DOUBLE:
129 dest->value.d = src->value.d;
134 out_data->values = g_slist_append(out_data->values, (void*)dest);
137 int ret = ctsvc_record_copy_base(&(out_data->base), &(src_data->base));
138 if (CONTACTS_ERROR_NONE != ret) {
139 ERR("ctsvc_record_copy_base() Fail");
140 __ctsvc_result_destroy((contacts_record_h)out_data, true);
144 *out_record = (contacts_record_h)out_data;
146 return CONTACTS_ERROR_NONE;
149 static int __ctsvc_result_get_str_real(contacts_record_h record, unsigned int property_id,
150 char **out_str, bool copy)
152 ctsvc_result_s *result = (ctsvc_result_s*)record;
156 if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
157 ERR("property_id is not str type.");
158 return CONTACTS_ERROR_INVALID_PARAMETER;
161 for (cursor = result->values; cursor; cursor = cursor->next) {
162 ctsvc_result_value_s *data = cursor->data;
163 if (data->property_id == property_id) {
164 *out_str = GET_STR(copy, data->value.s);
165 return CONTACTS_ERROR_NONE;
169 return CONTACTS_ERROR_NO_DATA;
172 static int __ctsvc_result_get_str_p(contacts_record_h record, unsigned int property_id, char **out_str)
174 return __ctsvc_result_get_str_real(record, property_id, out_str, false);
177 static int __ctsvc_result_get_str(contacts_record_h record, unsigned int property_id, char **out_str)
179 return __ctsvc_result_get_str_real(record, property_id, out_str, true);
182 static int __ctsvc_result_get_int(contacts_record_h record, unsigned int property_id, int *out_value)
184 ctsvc_result_s *result = (ctsvc_result_s*)record;
188 if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
189 ERR("property_id is not int type.");
190 return CONTACTS_ERROR_INVALID_PARAMETER;
193 for (cursor = result->values; cursor; cursor = cursor->next) {
194 ctsvc_result_value_s *data = cursor->data;
195 if (data->property_id == property_id) {
196 *out_value = data->value.i;
197 return CONTACTS_ERROR_NONE;
201 return CONTACTS_ERROR_NO_DATA;
204 static int __ctsvc_result_set_int(contacts_record_h record, unsigned int property_id, int value, bool *is_dirty)
206 ctsvc_result_s *result = (ctsvc_result_s*)record;
208 ctsvc_result_value_s *data;
210 if (CTSVC_VIEW_DATA_TYPE_INT != (CTSVC_VIEW_DATA_TYPE_INT & property_id)) {
211 ERR("property_id is not int type.");
212 return CONTACTS_ERROR_INVALID_PARAMETER;
215 for (cursor = result->values; cursor; cursor = cursor->next) {
217 if (data->property_id == property_id) {
218 #ifdef _CONTACTS_IPC_SERVER
219 if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
220 || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
221 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
222 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
224 #endif /* _CONTACTS_IPC_SERVER */
226 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
227 data->value.i = value;
229 return CONTACTS_ERROR_NONE;
233 data = calloc(1, sizeof(ctsvc_result_value_s));
235 ERR("calloc() Fail");
236 return CONTACTS_ERROR_OUT_OF_MEMORY;
238 data->property_id = property_id;
239 data->type = CTSVC_VIEW_DATA_TYPE_INT;
240 #ifdef _CONTACTS_IPC_SERVER
241 if (CTSVC_PROPERTY_PHONELOG_SIM_SLOT_NO == property_id
242 || CTSVC_PROPERTY_PHONELOG_STAT_SIM_SLOT_NO == property_id) {
243 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
244 data->value.i = ctsvc_server_sim_get_sim_slot_no_by_info_id(value);
246 #endif /* _CONTACTS_IPC_SERVER */
248 CHECK_DIRTY_VAL(data->value.i, value, is_dirty);
249 data->value.i = value;
251 result->values = g_slist_append(result->values, (void*)data);
252 return CONTACTS_ERROR_NONE;
255 static int __ctsvc_result_set_bool(contacts_record_h record, unsigned int property_id, bool value, bool *is_dirty)
257 ctsvc_result_s *result = (ctsvc_result_s*)record;
259 ctsvc_result_value_s *data;
261 /* TODO: check the value type of property_id is int */
262 for (cursor = result->values; cursor; cursor = cursor->next) {
264 if (data->property_id == property_id) {
265 if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
266 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
267 data->value.b = value;
268 return CONTACTS_ERROR_NONE;
270 ERR("use another get_type API, (type : %d)", data->type);
271 return CONTACTS_ERROR_INVALID_PARAMETER;
276 data = calloc(1, sizeof(ctsvc_result_value_s));
278 ERR("calloc() Fail");
279 return CONTACTS_ERROR_OUT_OF_MEMORY;
281 data->property_id = property_id;
282 data->type = CTSVC_VIEW_DATA_TYPE_BOOL;
283 CHECK_DIRTY_VAL(data->value.b, value, is_dirty);
284 data->value.b = value;
285 result->values = g_slist_append(result->values, (void*)data);
286 return CONTACTS_ERROR_NONE;
289 static int __ctsvc_result_set_str(contacts_record_h record, unsigned int property_id, const char *str, bool *is_dirty)
291 ctsvc_result_s *result = (ctsvc_result_s*)record;
293 ctsvc_result_value_s *data;
294 char *full_path = NULL;
297 if (CTSVC_VIEW_DATA_TYPE_STR != (CTSVC_VIEW_DATA_TYPE_STR & property_id)) {
298 ERR("property_id is not str type.");
299 return CONTACTS_ERROR_INVALID_PARAMETER;
302 for (cursor = result->values; cursor; cursor = cursor->next) {
304 if (data->property_id == property_id) {
305 switch (property_id) {
306 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
307 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
309 str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
310 full_path = calloc(1, str_len);
311 if (NULL == full_path) {
312 ERR("calloc() Fail");
313 return CONTACTS_ERROR_OUT_OF_MEMORY;
315 snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
317 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
319 data->value.s = full_path;
320 return CONTACTS_ERROR_NONE;
322 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
323 FREEandSTRDUP(data->value.s, str);
324 return CONTACTS_ERROR_NONE;
329 data = calloc(1, sizeof(ctsvc_result_value_s));
331 ERR("calloc() Fail");
332 return CONTACTS_ERROR_OUT_OF_MEMORY;
334 data->property_id = property_id;
335 data->type = CTSVC_VIEW_DATA_TYPE_STR;
336 switch (property_id) {
337 case CTSVC_PROPERTY_PERSON_IMAGE_THUMBNAIL:
338 case CTSVC_PROPERTY_CONTACT_IMAGE_THUMBNAIL:
340 str_len = strlen(CTSVC_CONTACT_IMG_FULL_LOCATION) + strlen(str) + 2;
341 full_path = calloc(1, str_len);
342 if (NULL == full_path) {
343 ERR("calloc() Fail");
345 return CONTACTS_ERROR_OUT_OF_MEMORY;
347 snprintf(full_path, str_len, "%s/%s", CTSVC_CONTACT_IMG_FULL_LOCATION, str);
349 CHECK_DIRTY_STR(data->value.s, full_path, is_dirty);
351 data->value.s = full_path;
354 CHECK_DIRTY_STR(data->value.s, str, is_dirty);
355 data->value.s = SAFE_STRDUP(str);
359 result->values = g_slist_append(result->values, (void*)data);
360 return CONTACTS_ERROR_NONE;
363 static int __ctsvc_result_get_bool(contacts_record_h record, unsigned int property_id, bool *out_value)
365 ctsvc_result_s *result = (ctsvc_result_s*)record;
367 for (cursor = result->values; cursor; cursor = cursor->next) {
368 ctsvc_result_value_s *data = cursor->data;
369 if (data->property_id == property_id) {
370 if (data->type == CTSVC_VIEW_DATA_TYPE_BOOL) {
371 *out_value = data->value.b;
372 return CONTACTS_ERROR_NONE;
374 ERR("use another get_type API, (type : %d)", data->type);
375 return CONTACTS_ERROR_INVALID_PARAMETER;
380 return CONTACTS_ERROR_NO_DATA;