From 1a48e75d43566c23bfc6614d7c84e3ccb64061dd Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Mon, 22 Jun 2015 00:25:59 -0700 Subject: [PATCH] Implement SavePersistent. Change-Id: I0b635b3e17dcfb6f238f57f2bff5575538ab7743 --- include/ntcore.h | 5 +- src/nt_persistent.cpp | 136 +++++++++++++++++++++++++++++++++++++++++- src/nt_storage.h | 9 ++- 3 files changed, 145 insertions(+), 5 deletions(-) diff --git a/include/ntcore.h b/include/ntcore.h index 0050bb143d..8c1aba1139 100644 --- a/include/ntcore.h +++ b/include/ntcore.h @@ -279,8 +279,9 @@ struct NT_ConnectionInfo *NT_GetConnections(size_t *count); /* * Persistent Functions */ -void NT_SavePersistent(const char *filename); -void NT_LoadPersistent(const char *filename); +/* return error string, or NULL if successful */ +const char *NT_SavePersistent(const char *filename); +const char *NT_LoadPersistent(const char *filename); /* * Utility Functions diff --git a/src/nt_persistent.cpp b/src/nt_persistent.cpp index 04f29393e3..18b3d2e94c 100644 --- a/src/nt_persistent.cpp +++ b/src/nt_persistent.cpp @@ -9,14 +9,146 @@ #include +#include "llvm/StringExtras.h" +#include "nt_base64.h" #include "nt_storage.h" using namespace NtImpl; -void NT_SavePersistent(const char *filename) +static void +write_string(FILE *f, llvm::StringRef str) { + fputc('"', f); + for (unsigned int i = 0, e = str.size(); i != e; ++i) + { + unsigned char c = str[i]; + + switch (c) + { + case '\\': fputs("\\\\", f); break; + case '\t': fputs("\\t", f); break; + case '\n': fputs("\\n", f); break; + case '"': fputs("\\\"", f); break; + default: + if (std::isprint(c)) + { + fputc(c, f); + break; + } + + // Write out the escaped representation. + fputs("\\x", f); + fputc(llvm::hexdigit((c >> 4 & 0xF)), f); + fputc(llvm::hexdigit((c >> 0) & 0xF), f); + } + } + fputc('"', f); } -void NT_LoadPersistent(const char *filename) +const char * +NT_SavePersistent(const char *filename) { + FILE *f = fopen(filename, "wt"); + if (!f) + return "could not open file"; + + fputs("[NetworkTables Storage 3.0]\n", f); + + Storage &storage = Storage::GetInstance(); + for (Storage::EntriesMap::const_iterator i = storage.entries.begin(), + end = storage.entries.end(); i != end; ++i) + { + const StorageEntry &entry = i->getValue(); + // only write persistent-flagged values + if ((entry.flags & NT_PERSISTENT) == 0) + continue; + + // type + const NT_Value &v = entry.value; + switch (v.type) + { + case NT_BOOLEAN: fputs("boolean ", f); break; + case NT_DOUBLE: fputs("double ", f); break; + case NT_STRING: fputs("string ", f); break; + case NT_RAW: fputs("raw ", f); break; + case NT_BOOLEAN_ARRAY: fputs("array boolean ", f); break; + case NT_DOUBLE_ARRAY: fputs("array double ", f); break; + case NT_STRING_ARRAY: fputs("array string ", f); break; + default: + continue; + } + + // name + write_string(f, i->getKey()); + + // = + fputc('=', f); + + // value + switch (v.type) + { + case NT_BOOLEAN: + fputs(v.data.v_boolean ? "true" : "false", f); + break; + case NT_DOUBLE: + fprintf(f, "%g", v.data.v_double); + break; + case NT_STRING: + write_string(f, make_StringRef(v.data.v_string)); + break; + case NT_RAW: + { + char *buf = new char[base64encode_len(v.data.v_raw.len)]; + base64encode(buf, + reinterpret_cast(v.data.v_raw.str), + v.data.v_raw.len); + fputs(buf, f); + delete[] buf; + break; + } + case NT_BOOLEAN_ARRAY: + for (size_t i=0; i entries; + typedef llvm::StringMap EntriesMap; + EntriesMap entries; private: Storage();