revise packaging
[platform/core/pim/contacts-service.git] / common / ctsvc_list.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19 #include <glib.h>
20
21 #include "contacts.h"
22 #include "ctsvc_internal.h"
23 #include "ctsvc_list.h"
24 #include "ctsvc_record.h"
25
26 EXPORT_API int contacts_list_create(contacts_list_h *out_list)
27 {
28         ctsvc_list_s *list_s;
29
30         RETV_IF(NULL == out_list, CONTACTS_ERROR_INVALID_PARAMETER);
31         *out_list = NULL;
32
33         list_s = calloc(1, sizeof(ctsvc_list_s));
34         RETVM_IF(NULL == list_s, CONTACTS_ERROR_OUT_OF_MEMORY, "calloc() Fail");
35
36         list_s->l_type = -1;
37         *out_list = (contacts_list_h)list_s;
38         return CONTACTS_ERROR_NONE;
39 }
40
41 EXPORT_API int contacts_list_get_count(contacts_list_h list, int *count)
42 {
43         ctsvc_list_s *list_s;
44
45         RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
46         *count = 0;
47
48         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
49         list_s = (ctsvc_list_s*)list;
50
51         *count = list_s->count;
52         return CONTACTS_ERROR_NONE;
53 }
54
55 int ctsvc_list_add_child(contacts_list_h list, contacts_record_h child_record)
56 {
57         ctsvc_list_s *s_list;
58         ctsvc_record_s *s_record;
59
60         RETV_IF(NULL == list || NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
61         s_list = (ctsvc_list_s*)list;
62         s_record = (ctsvc_record_s*)child_record;
63
64         if (-1 == s_list->l_type)
65                 s_list->l_type = s_record->r_type;
66         else if (s_list->l_type != s_record->r_type)
67                 return CONTACTS_ERROR_INVALID_PARAMETER;
68
69         s_list->records = g_list_append(s_list->records, child_record);
70
71         if (s_list->count == 0)
72                 s_list->cursor = s_list->records;
73
74         s_list->count++;
75         return CONTACTS_ERROR_NONE;
76 }
77
78 EXPORT_API int contacts_list_add(contacts_list_h list, contacts_record_h child_record)
79 {
80         ctsvc_list_s *s_list;
81         ctsvc_record_s *s_record;
82
83         RETV_IF(NULL == list || NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
84         s_list = (ctsvc_list_s*)list;
85         s_record = (ctsvc_record_s*)child_record;
86
87         if (-1 == s_list->l_type)
88                 s_list->l_type = s_record->r_type;
89         else if (s_list->l_type != s_record->r_type)
90                 return CONTACTS_ERROR_INVALID_PARAMETER;
91
92         s_list->records = g_list_append(s_list->records, child_record);
93
94         if (s_list->count == 0)
95                 s_list->cursor = s_list->records;
96
97         s_list->count++;
98         return CONTACTS_ERROR_NONE;
99 }
100
101 int ctsvc_list_prepend(contacts_list_h list, contacts_record_h child_record)
102 {
103         ctsvc_list_s *s_list;
104         ctsvc_record_s *s_record;
105
106         RETV_IF(NULL == list || NULL == child_record, CONTACTS_ERROR_INVALID_PARAMETER);
107         s_list = (ctsvc_list_s*)list;
108         s_record = (ctsvc_record_s*)child_record;
109
110         if (-1 == s_list->l_type)
111                 s_list->l_type = s_record->r_type;
112         else if (s_list->l_type != s_record->r_type)
113                 return CONTACTS_ERROR_INVALID_PARAMETER;
114
115         s_list->records = g_list_prepend(s_list->records, child_record);
116
117         if (s_list->count == 0)
118                 s_list->cursor = s_list->records;
119
120         s_list->count++;
121         return CONTACTS_ERROR_NONE;
122 }
123
124 int ctsvc_list_reverse(contacts_list_h list)
125 {
126         ctsvc_list_s *s_list;
127
128         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
129         s_list = (ctsvc_list_s*)list;
130
131         if (s_list->count != 0)
132                 s_list->records =  g_list_reverse(s_list->records);
133
134         return CONTACTS_ERROR_NONE;
135 }
136
137 int ctsvc_list_remove_child(contacts_list_h list, contacts_record_h record,
138                 bool insert_delete_list)
139 {
140         GList *cursor = NULL;
141         ctsvc_list_s *s_list;
142         ctsvc_record_s *s_record;
143         contacts_record_h delete_record;
144         contacts_error_e err = CONTACTS_ERROR_NONE;
145
146         RETV_IF(NULL == list || NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
147         s_list = (ctsvc_list_s*)list;
148         s_record = (ctsvc_record_s*)record;
149
150         if (s_list->l_type != s_record->r_type)
151                 return CONTACTS_ERROR_INVALID_PARAMETER;
152
153         for (cursor = s_list->records; cursor; cursor = cursor->next) {
154                 ctsvc_record_s *data = cursor->data;
155                 if (data == s_record) {
156                         s_list->count--;
157                         if (s_list->cursor == cursor)
158                                 s_list->cursor = cursor->next;
159
160                         s_list->records = g_list_remove(s_list->records, s_record);
161                         if (insert_delete_list) {
162                                 err = contacts_record_clone(record, &delete_record);
163                                 if (CONTACTS_ERROR_NONE != err) {
164                                         /* LCOV_EXCL_START */
165                                         ERR("contacts_record_clone() Fail(%d)", err);
166                                         return err;
167                                         /* LCOV_EXCL_STOP */
168                                 }
169
170                                 s_list->deleted_records = g_list_append(s_list->deleted_records, delete_record);
171                         }
172                         return CONTACTS_ERROR_NONE;
173                 }
174         }
175
176         return CONTACTS_ERROR_NO_DATA;
177 }
178
179 EXPORT_API int contacts_list_remove(contacts_list_h list, contacts_record_h record)
180 {
181         GList *cursor = NULL;
182         ctsvc_list_s *s_list;
183         ctsvc_record_s *s_record;
184
185         RETV_IF(NULL == list || NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
186         s_list = (ctsvc_list_s*)list;
187         s_record = (ctsvc_record_s*)record;
188
189         if (s_list->l_type != s_record->r_type)
190                 return CONTACTS_ERROR_INVALID_PARAMETER;
191
192         for (cursor = s_list->records; cursor; cursor = cursor->next) {
193                 ctsvc_record_s *data = cursor->data;
194                 if (data == s_record) {
195                         s_list->count--;
196                         if (s_list->cursor == cursor)
197                                 s_list->cursor = cursor->next;
198                         s_list->records = g_list_remove(s_list->records, s_record);
199                         return CONTACTS_ERROR_NONE;
200                 }
201         }
202
203         return CONTACTS_ERROR_NO_DATA;
204 }
205
206 EXPORT_API int contacts_list_get_current_record_p(contacts_list_h list, contacts_record_h *record)
207 {
208         ctsvc_list_s *list_s;
209
210         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
211         *record = NULL;
212
213         RETV_IF(NULL == list || NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
214         list_s = (ctsvc_list_s*)list;
215
216         if (NULL == list_s->cursor) {
217                 *record = NULL;
218                 return CONTACTS_ERROR_NO_DATA;
219         }
220
221         *record = list_s->cursor->data;
222
223         return CONTACTS_ERROR_NONE;
224 }
225
226 int ctsvc_list_get_nth_record_p(contacts_list_h list, int index, contacts_record_h *record)
227 {
228         GList *cursor = NULL;
229         ctsvc_list_s *list_s;
230         int i, j;
231
232         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
233         *record = NULL;
234
235         RETV_IF(NULL == list || NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
236         list_s = (ctsvc_list_s*)list;
237
238         for (i = 0, j = 0, cursor = list_s->records; cursor; cursor = cursor->next, i++) {
239                 if (j == index) {
240                         *record = cursor->data;
241                         return CONTACTS_ERROR_NONE;
242                 }
243                 j++;
244         }
245         *record = NULL;
246         return CONTACTS_ERROR_NO_DATA;
247 }
248
249 static int __ctsvc_list_move_cursor(contacts_list_h list, bool next)
250 {
251         ctsvc_list_s *list_s;
252
253         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
254         list_s = (ctsvc_list_s*)list;
255
256         if (NULL == list_s->cursor)
257                 return CONTACTS_ERROR_NO_DATA;
258
259         list_s->cursor = next ? list_s->cursor->next : list_s->cursor->prev ;
260
261         if (NULL == list_s->cursor)
262                 return CONTACTS_ERROR_NO_DATA;
263
264         return CONTACTS_ERROR_NONE;
265 }
266
267 EXPORT_API int contacts_list_prev(contacts_list_h list)
268 {
269         return __ctsvc_list_move_cursor(list, false);
270 }
271
272 EXPORT_API int contacts_list_next(contacts_list_h list)
273 {
274         return __ctsvc_list_move_cursor(list, true);
275 }
276
277
278
279 EXPORT_API int contacts_list_first(contacts_list_h list)
280 {
281         ctsvc_list_s *list_s;
282
283         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
284         list_s = (ctsvc_list_s*)list;
285
286         list_s->cursor = list_s->records;
287         if (NULL == list_s->cursor)
288                 return CONTACTS_ERROR_NO_DATA;
289
290         return CONTACTS_ERROR_NONE;
291 }
292
293 EXPORT_API int contacts_list_last(contacts_list_h list)
294 {
295         ctsvc_list_s *list_s;
296
297         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
298         list_s = (ctsvc_list_s*)list;
299
300         list_s->cursor = g_list_last(list_s->records);
301         if (NULL == list_s->cursor)
302                 return CONTACTS_ERROR_NO_DATA;
303
304         return CONTACTS_ERROR_NONE;
305 }
306
307 EXPORT_API int contacts_list_destroy(contacts_list_h list, bool delete_child)
308 {
309         ctsvc_list_s *s_list;
310         GList *cursor = NULL;
311
312         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
313
314         s_list = (ctsvc_list_s*)list;
315
316         if (delete_child) {
317                 for (cursor = s_list->records; cursor; cursor = cursor->next)
318                         contacts_record_destroy((contacts_record_h)(cursor->data), true);
319         }
320         g_list_free(s_list->records);
321
322         for (cursor = s_list->deleted_records; cursor; cursor = cursor->next)
323                 contacts_record_destroy((contacts_record_h)(cursor->data), true);
324         g_list_free(s_list->deleted_records);
325
326         free(s_list);
327         return CONTACTS_ERROR_NONE;
328 }
329
330 int ctsvc_list_clone(contacts_list_h list, contacts_list_h *out_list)
331 {
332         ctsvc_list_s *list_s;
333         contacts_record_h new_record;
334         contacts_list_h new_list;
335         GList *cursor = NULL;
336         contacts_error_e err = CONTACTS_ERROR_NONE;
337
338         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
339
340         list_s = (ctsvc_list_s*)list;
341
342         contacts_list_create(&new_list);
343         for (cursor = list_s->records; cursor; cursor = cursor->next) {
344                 err = contacts_record_clone(cursor->data, &new_record);
345                 if (CONTACTS_ERROR_NONE != err) {
346                         /* LCOV_EXCL_START */
347                         ERR("contacts_record_clone() Fail(%d)", err);
348                         contacts_list_destroy(new_list, true);
349                         return err;
350                         /* LCOV_EXCL_STOP */
351                 }
352                 ctsvc_list_prepend(new_list, new_record);
353         }
354         ctsvc_list_reverse(new_list);
355
356         for (cursor = list_s->deleted_records; cursor; cursor = cursor->next) {
357                 err = contacts_record_clone(cursor->data, &new_record);
358                 if (CONTACTS_ERROR_NONE != err) {
359                         /* LCOV_EXCL_START */
360                         ERR("contacts_record_clone() Fail(%d)", err);
361                         contacts_list_destroy(new_list, true);
362                         return err;
363                         /* LCOV_EXCL_STOP */
364                 }
365                 ((ctsvc_list_s*)new_list)->deleted_records
366                         = g_list_prepend(((ctsvc_list_s*)new_list)->deleted_records, new_record);
367         }
368         if (((ctsvc_list_s*)new_list)->deleted_records) {
369                 ((ctsvc_list_s*)new_list)->deleted_records
370                         = g_list_reverse(((ctsvc_list_s*)new_list)->deleted_records);
371         }
372
373         *out_list = new_list;
374
375         return CONTACTS_ERROR_NONE;
376 }
377
378
379 int ctsvc_list_get_deleted_count(contacts_list_h list, unsigned int *count)
380 {
381         ctsvc_list_s *list_s;
382
383         RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
384         *count = 0;
385
386         RETV_IF(NULL == list, CONTACTS_ERROR_INVALID_PARAMETER);
387         list_s = (ctsvc_list_s*)list;
388
389         if (NULL == list_s->deleted_records)
390                 return CONTACTS_ERROR_NONE;
391
392         *count = g_list_length(list_s->deleted_records);
393
394         return CONTACTS_ERROR_NONE;
395 }
396
397 int ctsvc_list_get_deleted_nth_record_p(contacts_list_h list, int index,
398                 contacts_record_h *record)
399 {
400         ctsvc_list_s *list_s;
401
402         RETV_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
403         *record = NULL;
404
405         RETV_IF(NULL == list || NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
406         list_s = (ctsvc_list_s*)list;
407
408         RETV_IF(NULL == list_s->deleted_records, CONTACTS_ERROR_NO_DATA);
409
410         *record = (contacts_record_h)g_list_nth_data(list_s->deleted_records, index);
411
412         return CONTACTS_ERROR_NONE;
413 }
414
415 int ctsvc_list_append_deleted_record(contacts_list_h list, contacts_record_h record)
416 {
417         ctsvc_list_s *list_s;
418
419         RETV_IF(NULL == list || NULL == record, CONTACTS_ERROR_INVALID_PARAMETER);
420
421         list_s = (ctsvc_list_s*)list;
422
423         list_s->deleted_records = g_list_append(list_s->deleted_records, record);
424
425         return CONTACTS_ERROR_NONE;
426 }