From c28958446981bfed40eea582cb78d4052c730313 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 13 Mar 2024 02:39:54 +0300 Subject: [PATCH] Add JSON dump format --- src/kv_cli.cpp | 36 +++++++++++++++++++++++++++--------- src/str_util.cpp | 20 +++++++++++++------- src/str_util.h | 3 ++- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/kv_cli.cpp b/src/kv_cli.cpp index 92f9fc67..e93503b8 100644 --- a/src/kv_cli.cpp +++ b/src/kv_cli.cpp @@ -201,6 +201,15 @@ void kv_cli_t::next_cmd() } } +struct kv_cli_list_t +{ + kv_dbw_t *db = NULL; + void *handle = NULL; + int format = 0; + int n = 0; + std::function cb; +}; + void kv_cli_t::handle_cmd(const std::string & cmd, std::function cb) { if (cmd == "") @@ -327,9 +336,12 @@ void kv_cli_t::handle_cmd(const std::string & cmd, std::function cb) }); } } - else if (opname == "list" || opname == "dump") + else if (opname == "list" || opname == "dump" || opname == "dumpjson") { - bool dump = opname == "dump"; + kv_cli_list_t *lst = new kv_cli_list_t; + lst->db = db; + lst->format = opname == "dump" ? 1 : (opname == "dumpjson" ? 2 : 0); + lst->cb = std::move(cb); std::string start, end; if (pos != std::string::npos) { @@ -344,8 +356,8 @@ void kv_cli_t::handle_cmd(const std::string & cmd, std::function cb) start = trim(cmd.substr(pos+1)); } } - void *handle = db->list_start(start); - db->list_next(handle, [=](int res, const std::string & key, const std::string & value) + lst->handle = db->list_start(start); + db->list_next(lst->handle, [lst](int res, const std::string & key, const std::string & value) { if (res < 0) { @@ -353,16 +365,22 @@ void kv_cli_t::handle_cmd(const std::string & cmd, std::function cb) { fprintf(stderr, "Error: %s (code %d)\n", strerror(-res), res); } - db->list_close(handle); - cb(); + if (lst->format == 2) + printf("\n}\n"); + lst->db->list_close(lst->handle); + lst->cb(); + delete lst; } else { - if (dump) + if (lst->format == 2) + printf(lst->n ? ",\n %s: %s" : "{\n %s: %s", addslashes(key).c_str(), addslashes(value).c_str()); + else if (lst->format == 1) printf("set %s %s\n", auto_addslashes(key).c_str(), value.c_str()); else printf("%s = %s\n", key.c_str(), value.c_str()); - db->list_next(handle, NULL); + lst->n++; + lst->db->list_next(lst->handle, NULL); } }); } @@ -386,7 +404,7 @@ void kv_cli_t::handle_cmd(const std::string & cmd, std::function cb) "open [block_size]\n" "config \n" "get \nset \ndel \n" - "list [ [end]]\ndump [ [end]]\n" + "list [ [end]]\ndump [ [end]]\ndumpjson [ [end]]\n" "close\nquit\n", opname.c_str() ); cb(); diff --git a/src/str_util.cpp b/src/str_util.cpp index 1b78f1ad..8a5f00a3 100644 --- a/src/str_util.cpp +++ b/src/str_util.cpp @@ -412,19 +412,25 @@ std::string scan_escaped(const std::string & cmd, size_t & pos) return key; } -std::string auto_addslashes(const std::string & str) +std::string auto_addslashes(const std::string & str, const char *toescape) { - auto pos = str.find_first_of("\\\""); + auto pos = str.find_first_of(toescape); if (pos == std::string::npos) return str; - std::string res = "\""+str.substr(0, pos)+"\\"+str[pos]; - while (pos < str.size()-1) + return addslashes(str, toescape); +} + +std::string addslashes(const std::string & str, const char *toescape) +{ + std::string res = "\""; + auto pos = 0; + while (pos < str.size()) { - auto pos2 = str.find_first_of("\\\"", pos+1); + auto pos2 = str.find_first_of(toescape, pos); if (pos2 == std::string::npos) - return res + str.substr(pos+1) + "\""; + return res + str.substr(pos) + "\""; res += str.substr(pos, pos2-pos)+"\\"+str[pos2]; - pos = pos2; + pos = pos2+1; } return res+"\""; } diff --git a/src/str_util.h b/src/str_util.h index 3fb03be1..92a7f18b 100644 --- a/src/str_util.h +++ b/src/str_util.h @@ -24,5 +24,6 @@ size_t utf8_length(const std::string & s); size_t utf8_length(const char *s); std::vector explode(const std::string & sep, const std::string & value, bool trim); std::string scan_escaped(const std::string & cmd, size_t & pos); -std::string auto_addslashes(const std::string & str); +std::string auto_addslashes(const std::string & str, const char *toescape = "\\\""); +std::string addslashes(const std::string & str, const char *toescape = "\\\""); std::string realpath_str(std::string path, bool nofail = true);