dict.c revision 31257b47d47510ceb093a6b218810a1a5b830c55
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen#include "array.h"
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "dict-sql.h"
993e6c2caaae971dd3c34913a42d854e3b623261Timo Sirainen#include "dict-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic ARRAY_DEFINE(dict_drivers, struct dict *);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic struct dict *dict_driver_lookup(const char *name)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct dict *const *dicts;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_foreach(&dict_drivers, dicts) {
7888a9d2008eab9985096c46e1da9ee985c22a2aTimo Sirainen struct dict *dict = *dicts;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9e0b187933b52db68c1aefb913970eeba47b986eAki Tuomi if (strcmp(dict->name, name) == 0)
9e0b187933b52db68c1aefb913970eeba47b986eAki Tuomi return dict;
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen }
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen return NULL;
213b139965e8bde6c8aff02ffd9fd39a74c887a9Timo Sirainen}
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainenvoid dict_driver_register(struct dict *driver)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!array_is_created(&dict_drivers))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_array_init(&dict_drivers, 8);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (dict_driver_lookup(driver->name) != NULL) {
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen i_fatal("dict_driver_register(%s): Already registered",
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen driver->name);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen }
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen array_append(&dict_drivers, &driver, 1);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen}
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainenvoid dict_driver_unregister(struct dict *driver)
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen{
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen struct dict *const *dicts;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen unsigned int idx = -1U;
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen array_foreach(&dict_drivers, dicts) {
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen if (*dicts == driver) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen idx = array_foreach_idx(&dict_drivers, dicts);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen }
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen i_assert(idx != -1U);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen array_delete(&dict_drivers, idx, 1);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen if (array_count(&dict_drivers) == 0)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen array_free(&dict_drivers);
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen}
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainenvoid dict_drivers_register_builtin(void)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen{
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen dict_driver_register(&dict_driver_client);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen dict_driver_register(&dict_driver_file);
a24f6b02ed8d0dde933a715be1c86f01977bf610Timo Sirainen dict_driver_register(&dict_driver_redis);
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen}
bbce20cb4e5739e9a06058cf8ee1f38a7f6884f6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid dict_drivers_unregister_builtin(void)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen dict_driver_unregister(&dict_driver_client);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen dict_driver_unregister(&dict_driver_file);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen dict_driver_unregister(&dict_driver_redis);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen}
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainenstruct dict *dict_init(const char *uri, enum dict_data_type value_type,
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen const char *username, const char *base_dir)
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen{
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen struct dict *dict;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen const char *p, *name;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen i_assert(username != NULL);
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen p = strchr(uri, ':');
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen if (p == NULL) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_error("Dictionary URI is missing ':': %s", uri);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return NULL;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen T_BEGIN {
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen name = t_strdup_until(uri, p);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen dict = dict_driver_lookup(name);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen if (dict == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Unknown dict module: %s", name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } T_END;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return dict == NULL ? NULL :
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen dict->v.init(dict, p+1, value_type, username, base_dir);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainenvoid dict_deinit(struct dict **_dict)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen{
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen struct dict *dict = *_dict;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen *_dict = NULL;
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen dict->v.deinit(dict);
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenint dict_wait(struct dict *dict)
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return dict->v.wait == NULL ? 1 : dict->v.wait(dict);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen}
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainenstatic bool dict_key_prefix_is_valid(const char *key)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return strncmp(key, DICT_PATH_SHARED, strlen(DICT_PATH_SHARED)) == 0 ||
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen strncmp(key, DICT_PATH_PRIVATE, strlen(DICT_PATH_PRIVATE)) == 0;
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen}
f2786c07cbd4a7a0a6a46c3e06dc4545aaf2f278Timo Sirainen
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainenint dict_lookup(struct dict *dict, pool_t pool, const char *key,
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen const char **value_r)
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen{
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen return dict->v.lookup(dict, pool, key, value_r);
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen}
0d658231054332c3f4c04aab0422af649de89a8cTimo Sirainen
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainenstruct dict_iterate_context *
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainendict_iterate_init(struct dict *dict, const char *path,
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen enum dict_iterate_flags flags)
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen{
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen const char *paths[2];
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen paths[0] = path;
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen paths[1] = NULL;
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen return dict_iterate_init_multiple(dict, paths, flags);
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen}
89334d8c6915db0fc8630470b7f3cd5ee9aa29aaTimo Sirainen
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainenstruct dict_iterate_context *
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainendict_iterate_init_multiple(struct dict *dict, const char *const *paths,
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen enum dict_iterate_flags flags)
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen{
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen unsigned int i;
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen i_assert(paths[0] != NULL);
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen for (i = 0; paths[i] != NULL; i++)
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen i_assert(dict_key_prefix_is_valid(paths[i]));
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen return dict->v.iterate_init(dict, paths, flags);
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen}
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainenbool dict_iterate(struct dict_iterate_context *ctx,
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen const char **key_r, const char **value_r)
23c502c6ef08d83e8ed68f90ed75138e14a3a246Timo Sirainen{
9df8c9225140d9d1df5ddf4c6c9da61662ae6c44Timo Sirainen return ctx->dict->v.iterate(ctx, key_r, value_r);
40ef82c46f6652412b068ebcdac7c3e74840a284Timo Sirainen}
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainenint dict_iterate_deinit(struct dict_iterate_context **_ctx)
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen{
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen struct dict_iterate_context *ctx = *_ctx;
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen *_ctx = NULL;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen return ctx->dict->v.iterate_deinit(ctx);
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen}
95a284736b8b11319a3f575ba249ba2eb7dbac1bTimo Sirainen
8eeafcb306872435f3171e6acf5a9937aec3a175Timo Sirainenstruct dict_transaction_context *dict_transaction_begin(struct dict *dict)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return dict->v.transaction_init(dict);
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen}
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainenint dict_transaction_commit(struct dict_transaction_context **_ctx)
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen{
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen struct dict_transaction_context *ctx = *_ctx;
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen *_ctx = NULL;
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen return ctx->dict->v.transaction_commit(ctx, FALSE, NULL, NULL);
faee566824fe3567c8beacf097f9dcfc0d3761b7Timo Sirainen}
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainen
f537e7efaec891d6b3320ca94331d09ca8c4a4dbTimo Sirainenvoid dict_transaction_commit_async(struct dict_transaction_context **_ctx,
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen dict_transaction_commit_callback_t *callback,
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen void *context)
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen{
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen struct dict_transaction_context *ctx = *_ctx;
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen *_ctx = NULL;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen ctx->dict->v.transaction_commit(ctx, TRUE, callback, context);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen}
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainenvoid dict_transaction_rollback(struct dict_transaction_context **_ctx)
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen{
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen struct dict_transaction_context *ctx = *_ctx;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen *_ctx = NULL;
fc7b17677ac1a5fa3f7fe13d5ef7dcfea8d9b4a1Timo Sirainen ctx->dict->v.transaction_rollback(ctx);
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenvoid dict_set(struct dict_transaction_context *ctx,
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen const char *key, const char *value)
ccb77e2f63626ec46e5745ef4f38baa8e8e504fcTimo Sirainen{
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen ctx->dict->v.set(ctx, key, value);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ctx->changed = TRUE;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenvoid dict_unset(struct dict_transaction_context *ctx,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen const char *key)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen ctx->dict->v.unset(ctx, key);
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen ctx->changed = TRUE;
6a4bfb2b0bb9f53fb1d4e705bf3948ef4d1ecccbTimo Sirainen}
6321d9d33937c7fc13a8ff04c220a9e377efeeb8Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenvoid dict_atomic_inc(struct dict_transaction_context *ctx,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen const char *key, long long diff)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen i_assert(dict_key_prefix_is_valid(key));
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen if (diff != 0) {
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ctx->dict->v.atomic_inc(ctx, key, diff);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ctx->changed = TRUE;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenconst char *dict_escape_string(const char *str)
e86d0d34fe365da4c7ca4312d575bfcbf3a01c0eTimo Sirainen{
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen const char *p;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen string_t *ret;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* see if we need to escape it */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen for (p = str; *p != '\0'; p++) {
e376e08040b5f21ff79a15ae728d2532a34207f6Timo Sirainen if (*p == '/' || *p == '\\')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen }
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainen if (*p == '\0')
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen return str;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* escape */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ret = t_str_new((size_t) (p - str) + 128);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen str_append_n(ret, str, (size_t) (p - str));
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen for (; *p != '\0'; p++) {
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen switch (*p) {
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen case '/':
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen str_append_c(ret, '\\');
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen str_append_c(ret, '|');
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen break;
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen case '\\':
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen str_append_c(ret, '\\');
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen str_append_c(ret, '\\');
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen break;
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen default:
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen str_append_c(ret, *p);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen break;
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen }
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen }
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen return str_c(ret);
1f4f81ba81bb9fa8abe2d94f344373c230066d67Timo Sirainen}
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainen
dcf4c70f8358db12859c3ab5b81b3abaac4109a3Timo Sirainenconst char *dict_unescape_string(const char *str)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen{
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen const char *p;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen string_t *ret;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen /* see if we need to unescape it */
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen for (p = str; *p != '\0'; p++) {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen if (*p == '\\')
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen break;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen }
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen if (*p == '\0')
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen return str;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen /* unescape */
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen ret = t_str_new((size_t) (p - str) + strlen(p) + 1);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen str_append_n(ret, str, (size_t) (p - str));
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen for (; *p != '\0'; p++) {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen if (*p != '\\')
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen str_append_c(ret, *p);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen else {
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen if (*++p == '|')
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen str_append_c(ret, '/');
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen else if (*p == '\0')
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen break;
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen else
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen str_append_c(ret, *p);
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen }
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen }
1cf72a848805fcf014b01c9d3665b6a157846a21Timo Sirainen return str_c(ret);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen