2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <app_private.h>
26 #include <app_preference.h>
27 #include <app_preference_private.h>
35 #define LOG_TAG "CAPI_APPFW_APPLICATION_PREFERENCE"
38 static sqlite3 *pref_db = NULL;
39 static bool is_update_hook_registered = false;
40 static pref_changed_cb_node_t *head = NULL;
42 static void _finish(void *data)
46 sqlite3_close(pref_db);
51 static int _initialize(void)
53 char data_path[TIZEN_PATH_MAX] = {0, };
54 char db_path[TIZEN_PATH_MAX] = {0, };
58 if (app_get_data_directory(data_path, sizeof(data_path)) == NULL)
60 LOGE("IO_ERROR(0x%08x) : fail to get data directory", PREFERENCE_ERROR_IO_ERROR);
61 return PREFERENCE_ERROR_IO_ERROR;
63 snprintf(db_path, sizeof(db_path), "%s/%s", data_path, PREF_DB_NAME);
65 ret = sqlite3_open(db_path, &pref_db);
68 LOGE("IO_ERROR(0x%08x) : fail to open db(%s)", PREFERENCE_ERROR_IO_ERROR, sqlite3_errmsg(pref_db));
70 return PREFERENCE_ERROR_IO_ERROR;
73 ret = sqlite3_exec(pref_db, "CREATE TABLE IF NOT EXISTS pref ( pref_key TEXT PRIMARY KEY, pref_type TEXT, pref_data TEXT)",
77 LOGE("IO_ERROR(0x%08x) : fail to create db table(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
79 sqlite3_close(pref_db);
81 return PREFERENCE_ERROR_IO_ERROR;
84 app_finalizer_add(_finish, NULL);
86 return PREFERENCE_ERROR_NONE;
89 //static int _write_data(const char *key, preference_type_e type, const char *data)
90 static int _write_data(const char *key, const char *type, const char *data)
97 if (key == NULL || key[0] == '\0' || data == NULL)
99 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
100 return PREFERENCE_ERROR_INVALID_PARAMETER;
103 /* insert data or update data if data already exist */
104 ret = preference_is_existing(key, &exist);
105 if (ret != PREFERENCE_ERROR_NONE)
110 // to use sqlite3_update_hook, we have to use INSERT/UPDATE operation instead of REPLACE operation
113 buf = sqlite3_mprintf("UPDATE %s SET %s='%s', %s='%s' WHERE %s='%s';",
114 PREF_TBL_NAME, PREF_F_TYPE_NAME, type, PREF_F_DATA_NAME, data, PREF_F_KEY_NAME, key);
118 buf = sqlite3_mprintf("INSERT INTO %s (%s, %s, %s) values (%Q, %Q, %Q);",
119 PREF_TBL_NAME, PREF_F_KEY_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME, key, type, data);
124 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
125 return PREFERENCE_ERROR_IO_ERROR;
128 ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg);
130 if (ret != SQLITE_OK)
132 LOGE("IO_ERROR(0x%08x): fail to write data(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
133 sqlite3_free(errmsg);
134 return PREFERENCE_ERROR_IO_ERROR;
137 return PREFERENCE_ERROR_NONE;
140 //static int _read_data(const char *key, preference_type_e *type, char *data)
141 static int _read_data(const char *key, char *type, char *data)
150 if (key == NULL || key[0] == '\0' || data == NULL)
152 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
153 return PREFERENCE_ERROR_INVALID_PARAMETER;
158 if (_initialize() != PREFERENCE_ERROR_NONE)
160 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
161 return PREFERENCE_ERROR_IO_ERROR;
165 buf = sqlite3_mprintf("SELECT %s, %s, %s FROM %s WHERE %s=%Q;",
166 PREF_F_KEY_NAME, PREF_F_TYPE_NAME, PREF_F_DATA_NAME, PREF_TBL_NAME, PREF_F_KEY_NAME, key);
170 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
171 return PREFERENCE_ERROR_IO_ERROR;
174 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
176 if (ret != SQLITE_OK)
178 LOGE("IO_ERROR(0x%08x) : fail to read data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
179 sqlite3_free(errmsg);
180 return PREFERENCE_ERROR_IO_ERROR;
185 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
186 sqlite3_free_table(result);
187 return PREFERENCE_ERROR_NO_KEY;
190 snprintf(type, 2, "%s", result[4]); // get type value
191 snprintf(data, BUF_LEN, "%s", result[5]); // get data value
193 sqlite3_free_table(result);
195 return PREFERENCE_ERROR_NONE;
199 int preference_set_int(const char *key, int value)
203 snprintf(type, 2, "%d", PREFERENCE_TYPE_INT);
204 snprintf(data, BUF_LEN, "%d", value);
205 return _write_data(key, type, data);
208 int preference_get_int(const char *key, int *value)
214 ret = _read_data(key, type, data);
215 if (ret == PREFERENCE_ERROR_NONE)
217 if (atoi(type) == PREFERENCE_TYPE_INT)
223 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
224 return PREFERENCE_ERROR_INVALID_PARAMETER;
231 int preference_set_double(const char *key, double value)
235 snprintf(type, 2, "%d", PREFERENCE_TYPE_DOUBLE);
236 snprintf(data, BUF_LEN, "%f", value);
237 return _write_data(key, type, data);
240 int preference_get_double(const char *key, double *value)
247 ret = _read_data(key, type, data);
248 if (ret == PREFERENCE_ERROR_NONE)
250 if (atoi(type) == PREFERENCE_TYPE_DOUBLE)
256 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
257 return PREFERENCE_ERROR_INVALID_PARAMETER;
264 int preference_set_string(const char *key, const char *value)
268 snprintf(type, 2, "%d", PREFERENCE_TYPE_STRING);
269 if (strlen(value) > (BUF_LEN-1))
271 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
272 return PREFERENCE_ERROR_INVALID_PARAMETER;
274 return _write_data(key, type, value);
277 int preference_get_string(const char *key, char **value)
286 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
287 return PREFERENCE_ERROR_INVALID_PARAMETER;
290 ret = _read_data(key, type, data);
291 if (ret == PREFERENCE_ERROR_NONE)
293 if (atoi(type) == PREFERENCE_TYPE_STRING)
295 *value = strdup(data);
298 LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY);
299 return PREFERENCE_ERROR_OUT_OF_MEMORY;
304 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
305 return PREFERENCE_ERROR_INVALID_PARAMETER;
312 int preference_set_boolean(const char *key, bool value)
316 snprintf(type, 2, "%d", PREFERENCE_TYPE_BOOLEAN);
317 snprintf(data, BUF_LEN, "%d", value);
318 return _write_data(key, type, data);
321 int preference_get_boolean(const char *key, bool *value)
328 ret = _read_data(key, type, data);
329 if (ret == PREFERENCE_ERROR_NONE)
331 if (atoi(type) == PREFERENCE_TYPE_BOOLEAN)
333 *value = (bool)atoi(data);
337 LOGE("INVALID_PARAMETER(0x%08x) : param type(%d)", PREFERENCE_ERROR_INVALID_PARAMETER, atoi(type));
338 return PREFERENCE_ERROR_INVALID_PARAMETER;
346 // TODO: below operation is too heavy, let's find the light way to check.
347 int preference_is_existing(const char *key, bool *exist)
356 if (key == NULL || key[0] == '\0' || exist == NULL)
358 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
359 return PREFERENCE_ERROR_INVALID_PARAMETER;
364 if (_initialize() != PREFERENCE_ERROR_NONE)
366 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
367 return PREFERENCE_ERROR_IO_ERROR;
371 /* check data is exist */
372 buf = sqlite3_mprintf("SELECT %s FROM %s WHERE %s=%Q;", PREF_F_KEY_NAME, PREF_TBL_NAME, PREF_F_KEY_NAME, key);
376 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
377 return PREFERENCE_ERROR_IO_ERROR;
380 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
382 if (ret != SQLITE_OK)
384 LOGE("IO_ERROR(0x%08x) : fail to read data(%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
385 sqlite3_free(errmsg);
386 return PREFERENCE_ERROR_IO_ERROR;
398 sqlite3_free_table(result);
399 return PREFERENCE_ERROR_NONE;
402 static pref_changed_cb_node_t* _find_node(const char *key)
404 pref_changed_cb_node_t *tmp_node;
406 if (key == NULL || key[0] == '\0' )
415 if (strcmp(tmp_node->key, key) == 0)
419 tmp_node = tmp_node->next;
426 static int _add_node(const char *key, preference_changed_cb cb, void *user_data)
428 pref_changed_cb_node_t *tmp_node;
430 if (key == NULL || key[0] == '\0' || cb == NULL)
432 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
433 return PREFERENCE_ERROR_INVALID_PARAMETER;
436 tmp_node = _find_node(key);
438 if (tmp_node != NULL)
441 tmp_node->user_data = user_data;
445 tmp_node = (pref_changed_cb_node_t*)malloc(sizeof(pref_changed_cb_node_t));
446 if (tmp_node == NULL)
448 LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY);
449 return PREFERENCE_ERROR_OUT_OF_MEMORY;
452 tmp_node->key = strdup(key);
453 if (tmp_node->key == NULL)
456 LOGE("OUT_OF_MEMORY(0x%08x)", PREFERENCE_ERROR_OUT_OF_MEMORY);
457 return PREFERENCE_ERROR_OUT_OF_MEMORY;
460 tmp_node->user_data = user_data;
461 tmp_node->prev = NULL;
462 tmp_node->next = head;
466 return PREFERENCE_ERROR_NONE;
469 static int _remove_node(const char *key)
471 pref_changed_cb_node_t *tmp_node;
473 if (key == NULL || key[0] == '\0' )
475 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
476 return PREFERENCE_ERROR_INVALID_PARAMETER;
479 tmp_node = _find_node(key);
481 if (tmp_node == NULL)
483 return PREFERENCE_ERROR_NONE;
486 if (tmp_node->prev != NULL)
488 tmp_node->prev->next = tmp_node->next;
492 head = tmp_node->next;
495 if (tmp_node->next != NULL)
497 tmp_node->next->prev = tmp_node->prev;
507 return PREFERENCE_ERROR_NONE;
511 static void _remove_all_node(void)
513 pref_changed_cb_node_t *tmp_node;
518 head = tmp_node->next;
530 static void _update_cb(void *data, int action, char const *db_name, char const *table_name, sqlite_int64 rowid)
538 pref_changed_cb_node_t *tmp_node;
540 // skip INSERT/DELETE event
541 if (action != SQLITE_UPDATE)
546 if (strcmp(table_name, PREF_TBL_NAME) != 0)
548 SECURE_LOGE("given table name (%s) is not same", table_name);
552 buf = sqlite3_mprintf("SELECT %s FROM %s WHERE rowid='%lld';", PREF_F_KEY_NAME, PREF_TBL_NAME, rowid);
557 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
559 if (ret != SQLITE_OK)
561 LOGI("fail to read data(%s)", errmsg);
562 sqlite3_free(errmsg);
568 sqlite3_free_table(result);
572 tmp_node = _find_node(result[1]);
574 if (tmp_node != NULL && tmp_node->cb != NULL)
576 tmp_node->cb(result[1], tmp_node->user_data);
579 sqlite3_free_table(result);
583 int preference_remove(const char *key)
590 ret = preference_is_existing(key, &exist);
591 if (ret != PREFERENCE_ERROR_NONE)
598 return PREFERENCE_ERROR_NONE;
601 /* insert data or update data if data already exist */
602 buf = sqlite3_mprintf("DELETE FROM %s WHERE %s = '%s';",
603 PREF_TBL_NAME, PREF_F_KEY_NAME, key);
607 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
608 return PREFERENCE_ERROR_IO_ERROR;
611 ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg);
613 if (ret != SQLITE_OK)
615 LOGE("IO_ERROR(0x%08x) : fail to delete data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
616 sqlite3_free(errmsg);
617 return PREFERENCE_ERROR_IO_ERROR;
620 // if exist, remove changed cb
623 return PREFERENCE_ERROR_NONE;
627 int preference_remove_all(void)
635 if (_initialize() != PREFERENCE_ERROR_NONE)
637 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
638 return PREFERENCE_ERROR_IO_ERROR;
642 /* insert data or update data if data already exist */
643 buf = sqlite3_mprintf("DELETE FROM %s;", PREF_TBL_NAME);
646 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
647 return PREFERENCE_ERROR_IO_ERROR;
650 ret = sqlite3_exec(pref_db, buf, NULL, NULL, &errmsg);
652 if (ret != SQLITE_OK)
654 LOGE("IO_ERROR(0x%08x) : fail to delete data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
655 sqlite3_free(errmsg);
656 return PREFERENCE_ERROR_IO_ERROR;
659 // if exist, remove changed cb
662 return PREFERENCE_ERROR_NONE;
666 int preference_set_changed_cb(const char *key, preference_changed_cb callback, void *user_data)
671 ret = preference_is_existing(key, &exist);
672 if (ret != PREFERENCE_ERROR_NONE)
679 LOGE("NO_KEY(0x%08x) : fail to find given key(%s)", PREFERENCE_ERROR_NO_KEY, key);
680 return PREFERENCE_ERROR_NO_KEY;
683 if (!is_update_hook_registered)
685 sqlite3_update_hook(pref_db, _update_cb, NULL);
686 is_update_hook_registered = true;
689 return _add_node(key, callback, user_data);
692 int preference_unset_changed_cb(const char *key)
696 if (_initialize() != PREFERENCE_ERROR_NONE)
698 return PREFERENCE_ERROR_IO_ERROR;
702 return _remove_node(key);
705 int preference_foreach_item(preference_item_cb callback, void *user_data)
717 if (_initialize() != PREFERENCE_ERROR_NONE)
719 LOGE("IO_ERROR(0x%08x) : fail to initialize db", PREFERENCE_ERROR_IO_ERROR);
720 return PREFERENCE_ERROR_IO_ERROR;
724 if (callback == NULL)
726 LOGE("INVALID_PARAMETER(0x%08x)", PREFERENCE_ERROR_INVALID_PARAMETER);
727 return PREFERENCE_ERROR_INVALID_PARAMETER;
730 buf = sqlite3_mprintf("SELECT %s FROM %s;", PREF_F_KEY_NAME, PREF_TBL_NAME);
733 LOGE("IO_ERROR(0x%08x) : fail to create query string", PREFERENCE_ERROR_IO_ERROR);
734 return PREFERENCE_ERROR_IO_ERROR;
737 ret = sqlite3_get_table(pref_db, buf, &result, &rows, &columns, &errmsg);
739 if (ret != SQLITE_OK)
741 LOGE("IO_ERROR(0x%08x) : fail to read data (%s)", PREFERENCE_ERROR_IO_ERROR, errmsg);
742 sqlite3_free(errmsg);
743 return PREFERENCE_ERROR_IO_ERROR;
746 for (i = 1; i <= rows; i++)
748 if (callback(result[i], user_data) != true)
754 sqlite3_free_table(result);
756 return PREFERENCE_ERROR_NONE;