diff --git a/src/Storage.cpp b/src/Storage.cpp index 25ccc8e8eb..6642846cf0 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -7,6 +7,12 @@ #include "Storage.h" +#include +#include + +#include "llvm/StringExtras.h" +#include "base64.h" + using namespace ntimpl; Storage* Storage::m_instance = nullptr; @@ -14,3 +20,159 @@ Storage* Storage::m_instance = nullptr; Storage::Storage() {} Storage::~Storage() {} + +static void WriteString(std::ostream& os, llvm::StringRef str) { + os << '"'; + for (auto c : str) { + switch (c) { + case '\\': + os << "\\\\"; + break; + case '\t': + os << "\\t"; + break; + case '\n': + os << "\\n"; + break; + case '"': + os << "\\\""; + break; + default: + if (std::isprint(c)) { + os << c; + break; + } + + // Write out the escaped representation. + os << "\\x"; + os << llvm::hexdigit((c >> 4) & 0xF); + os << llvm::hexdigit((c >> 0) & 0xF); + } + } + os << '"'; +} + +void Storage::SavePersistent(std::ostream& os) const { + os << "[NetworkTables Storage 3.0]\n"; + + for (auto& i : m_entries) { + 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: + os << "boolean "; + break; + case NT_DOUBLE: + os << "double "; + break; + case NT_STRING: + os << "string "; + break; + case NT_RAW: + os << "raw "; + break; + case NT_BOOLEAN_ARRAY: + os << "array boolean "; + break; + case NT_DOUBLE_ARRAY: + os << "array double "; + break; + case NT_STRING_ARRAY: + os << "array string "; + break; + default: + continue; + } + + // name + WriteString(os, i.getKey()); + + // = + os << '='; + + // value + switch (v.type) { + case NT_BOOLEAN: + os << (v.data.v_boolean ? "true" : "false"); + break; + case NT_DOUBLE: + os << v.data.v_double; + break; + case NT_STRING: + WriteString(os, MakeStringRef(v.data.v_string)); + break; + case NT_RAW: { + char* buf = new char[Base64EncodeLen(v.data.v_raw.len)]; + Base64Encode(buf, + reinterpret_cast(v.data.v_raw.str), + v.data.v_raw.len); + os << buf; + delete[] buf; + break; + } + case NT_BOOLEAN_ARRAY: + for (size_t i = 0; i < v.data.arr_boolean.size; ++i) { + os << (v.data.arr_boolean.arr[i] ? "true" : "false"); + if (i != (v.data.arr_boolean.size - 1)) + os << ','; + } + break; + case NT_DOUBLE_ARRAY: + for (size_t i = 0; i < v.data.arr_double.size; ++i) { + os << v.data.arr_double.arr[i]; + if (i != (v.data.arr_double.size - 1)) + os << ','; + } + break; + case NT_STRING_ARRAY: + for (size_t i = 0; i < v.data.arr_double.size; ++i) { + WriteString(os, MakeStringRef(v.data.arr_string.arr[i])); + if (i != (v.data.arr_double.size - 1)) + os << ','; + } + break; + default: + break; + } + + // eol + os << '\n'; + } +} + +void Storage::LoadPersistent(std::istream& is, + void (*warn)(std::size_t line, const char* msg)) { + std::string line_str; + std::size_t line_num = 0; + while (std::getline(is, line_str)) { + llvm::StringRef line(line_str); + ++line_num; + + // type + llvm::StringRef type_str; + std::tie(type_str, line) = line.split(' '); + NT_Type type = NT_UNASSIGNED; + if (type_str == "boolean") type = NT_BOOLEAN; + else if (type_str == "double") type = NT_DOUBLE; + else if (type_str == "string") type = NT_STRING; + else if (type_str == "raw") type = NT_RAW; + else if (type_str == "array") { + llvm::StringRef array_str; + std::tie(array_str, line) = line.split(' '); + if (array_str == "boolean") type = NT_BOOLEAN_ARRAY; + else if (array_str == "double") type = NT_DOUBLE_ARRAY; + else if (array_str == "string") type = NT_STRING_ARRAY; + } + if (type == NT_UNASSIGNED) { + if (warn) warn(line_num, "unrecognized type"); + continue; + } + + // name + + } +} diff --git a/src/Storage.h b/src/Storage.h index 7aff6a0174..558baf5d7d 100644 --- a/src/Storage.h +++ b/src/Storage.h @@ -8,6 +8,9 @@ #ifndef NT_STORAGE_H_ #define NT_STORAGE_H_ +#include +#include + #include "ntcore.h" #include "llvm/StringMap.h" @@ -45,6 +48,10 @@ class Storage { EntriesMap& entries() { return m_entries; } const EntriesMap& entries() const { return m_entries; } + void SavePersistent(std::ostream& os) const; + void LoadPersistent(std::istream& is, + void (*warn)(std::size_t line, const char* msg)); + private: Storage(); ~Storage(); diff --git a/src/ntcore.cpp b/src/ntcore.cpp new file mode 100644 index 0000000000..eab63a5a8f --- /dev/null +++ b/src/ntcore.cpp @@ -0,0 +1,170 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2015. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ + +#include "ntcore.h" + +#include +#include +#include + +#include "Storage.h" + +using namespace ntimpl; + +/* + * Table Functions + */ + +void NT_GetEntryValue(const char *name, unsigned int name_len, + struct NT_Value *value) {} + +int NT_SetEntryValue(const char *name, unsigned int name_len, + const struct NT_Value *value) { + return 0; +} + +void NT_SetEntryTypeValue(const char *name, unsigned int name_len, + const struct NT_Value *value) {} + +void NT_SetEntryFlags(const char *name, size_t name_len, unsigned int flags) {} + +unsigned int NT_GetEntryFlags(const char *name, size_t name_len) { + return 0; +} + +void NT_DeleteEntry(const char *name, unsigned int name_len) {} + +void NT_DeleteAllEntries(void) {} + +struct NT_EntryInfo *NT_GetEntryInfo(const char *prefix, + unsigned int prefix_len, int types, + unsigned int *count) { + return nullptr; +} + +void NT_Flush(void) {} + +/* + * Callback Creation Functions + */ + +unsigned int NT_AddEntryListener(const char *prefix, size_t prefix_len, + void *data, + NT_EntryListenerCallback callback) { + return 0; +} +void NT_RemoveEntryListener(unsigned int entry_listener_uid) {} +unsigned int NT_AddConnectionListener(void *data, + NT_ConnectionListenerCallback callback) { + return 0; +} +void NT_RemoveConnectionListener(unsigned int conn_listener_uid) {} + +/* + * Remote Procedure Call Functions + */ + +unsigned int NT_CreateRpc(const char *name, size_t name_len, + const NT_RpcDefinition *def, void *data, + NT_RpcCallback callback); +void NT_DeleteRpc(unsigned int rpc_uid); +unsigned int NT_CallRpc(const char *name, size_t name_len, + const NT_Value *params, size_t params_len); +NT_Value *NT_GetRpcResult(unsigned int result_uid, size_t *results_len); + +/* + * Client/Server Functions + */ + +void NT_SetNetworkIdentity(const char *name, size_t name_len) {} +void NT_StartServer(const char *persist_filename, const char *listen_address, + unsigned int port) {} +void NT_StopServer(void) {} +void NT_StartClient(const char *server_name, unsigned int port) {} +void NT_StopClient(void) {} +void NT_SetUpdateRate(double interval) {} +struct NT_ConnectionInfo *NT_GetConnections(size_t *count) { + return nullptr; +} + +/* + * Persistent Functions + */ + +const char *NT_SavePersistent(const char *filename) { + const Storage& storage = Storage::GetInstance(); + std::ofstream os(filename); + if (!os) return "could not open file"; + storage.SavePersistent(os); + return nullptr; +} + +const char *NT_LoadPersistent(const char *filename, + void (*warn)(size_t line, const char *msg)) { + Storage& storage = Storage::GetInstance(); + std::ifstream is(filename); + if (!is) return "could not open file"; + storage.LoadPersistent(is, warn); + return nullptr; +} + +/* + * Utility Functions + */ + +void NT_DisposeValue(NT_Value *value) { + switch (value->type) { + case NT_UNASSIGNED: + case NT_BOOLEAN: + case NT_DOUBLE: + break; + case NT_STRING: + case NT_RAW: + case NT_RPC: + std::free(value->data.v_string.str); + break; + case NT_BOOLEAN_ARRAY: + std::free(value->data.arr_boolean.arr); + break; + case NT_DOUBLE_ARRAY: + std::free(value->data.arr_double.arr); + break; + case NT_STRING_ARRAY: { + for (size_t i = 0; i < value->data.arr_string.size; i++) + std::free(value->data.arr_string.arr[i].str); + std::free(value->data.arr_string.arr); + break; + } + default: + assert(0 && "unknown value type"); + } + value->type = NT_UNASSIGNED; + value->last_change = 0; +} + +void NT_InitValue(NT_Value *value) { + value->type = NT_UNASSIGNED; + value->last_change = 0; +} + +void NT_DisposeString(NT_String *str) { + std::free(str->str); + str->str = nullptr; + str->len = 0; +} + +void NT_InitString(NT_String *str) { + str->str = nullptr; + str->len = 0; +} + +void NT_DisposeConnectionInfoArray(NT_ConnectionInfo *arr, size_t count) { + unsigned int i; + for (i = 0; i < count; i++) + std::free(arr[i].remote_id.str); + std::free(arr); +} diff --git a/src/persistent.cpp b/src/persistent.cpp deleted file mode 100644 index 56fbe19e54..0000000000 --- a/src/persistent.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) FIRST 2015. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -#include "ntcore.h" - -#include -#include -#include - -#include "llvm/StringExtras.h" -#include "base64.h" -#include "Storage.h" - -using namespace ntimpl; - -static void WriteString(std::ostream& os, llvm::StringRef str) { - os << '"'; - for (auto c : str) { - switch (c) { - case '\\': - os << "\\\\"; - break; - case '\t': - os << "\\t"; - break; - case '\n': - os << "\\n"; - break; - case '"': - os << "\\\""; - break; - default: - if (std::isprint(c)) { - os << c; - break; - } - - // Write out the escaped representation. - os << "\\x"; - os << llvm::hexdigit((c >> 4) & 0xF); - os << llvm::hexdigit((c >> 0) & 0xF); - } - } - os << '"'; -} - -const char* NT_SavePersistent(const char* filename) { - std::ofstream os(filename); - if (!os) return "could not open file"; - - os << "[NetworkTables Storage 3.0]\n"; - - const Storage& storage = Storage::GetInstance(); - for (auto& i : storage.entries()) { - 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: - os << "boolean "; - break; - case NT_DOUBLE: - os << "double "; - break; - case NT_STRING: - os << "string "; - break; - case NT_RAW: - os << "raw "; - break; - case NT_BOOLEAN_ARRAY: - os << "array boolean "; - break; - case NT_DOUBLE_ARRAY: - os << "array double "; - break; - case NT_STRING_ARRAY: - os << "array string "; - break; - default: - continue; - } - - // name - WriteString(os, i.getKey()); - - // = - os << '='; - - // value - switch (v.type) { - case NT_BOOLEAN: - os << (v.data.v_boolean ? "true" : "false"); - break; - case NT_DOUBLE: - os << v.data.v_double; - break; - case NT_STRING: - WriteString(os, MakeStringRef(v.data.v_string)); - break; - case NT_RAW: { - char* buf = new char[Base64EncodeLen(v.data.v_raw.len)]; - Base64Encode(buf, - reinterpret_cast(v.data.v_raw.str), - v.data.v_raw.len); - os << buf; - delete[] buf; - break; - } - case NT_BOOLEAN_ARRAY: - for (size_t i = 0; i < v.data.arr_boolean.size; ++i) { - os << (v.data.arr_boolean.arr[i] ? "true" : "false"); - if (i != (v.data.arr_boolean.size - 1)) - os << ','; - } - break; - case NT_DOUBLE_ARRAY: - for (size_t i = 0; i < v.data.arr_double.size; ++i) { - os << v.data.arr_double.arr[i]; - if (i != (v.data.arr_double.size - 1)) - os << ','; - } - break; - case NT_STRING_ARRAY: - for (size_t i = 0; i < v.data.arr_double.size; ++i) { - WriteString(os, MakeStringRef(v.data.arr_string.arr[i])); - if (i != (v.data.arr_double.size - 1)) - os << ','; - } - break; - default: - break; - } - - // eol - os << '\n'; - } - - os.close(); - return 0; -} - -const char* NT_LoadPersistent(const char* filename, - void (*warn)(size_t line, const char* msg)) { - std::ifstream f(filename); - if (!f) return "could not open file"; - - std::string line_str; - std::size_t line_num = 0; - while (std::getline(f, line_str)) { - llvm::StringRef line(line_str); - ++line_num; - - // type - llvm::StringRef type_str; - std::tie(type_str, line) = line.split(' '); - NT_Type type = NT_UNASSIGNED; - if (type_str == "boolean") type = NT_BOOLEAN; - else if (type_str == "double") type = NT_DOUBLE; - else if (type_str == "string") type = NT_STRING; - else if (type_str == "raw") type = NT_RAW; - else if (type_str == "array") { - llvm::StringRef array_str; - std::tie(array_str, line) = line.split(' '); - if (array_str == "boolean") type = NT_BOOLEAN_ARRAY; - else if (array_str == "double") type = NT_DOUBLE_ARRAY; - else if (array_str == "string") type = NT_STRING_ARRAY; - } - if (type == NT_UNASSIGNED) { - if (warn) warn(line_num, "unrecognized type"); - continue; - } - - // name - - } - - f.close(); - return 0; -} diff --git a/src/utility.cpp b/src/utility.cpp deleted file mode 100644 index acb15ab239..0000000000 --- a/src/utility.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/*----------------------------------------------------------------------------*/ -/* Copyright (c) FIRST 2015. All Rights Reserved. */ -/* Open Source Software - may be modified and shared by FRC teams. The code */ -/* must be accompanied by the FIRST BSD license file in the root directory of */ -/* the project. */ -/*----------------------------------------------------------------------------*/ - -#include -#include - -#include "ntcore.h" - -void NT_DisposeValue(NT_Value *value) { - switch (value->type) { - case NT_UNASSIGNED: - case NT_BOOLEAN: - case NT_DOUBLE: - break; - case NT_STRING: - case NT_RAW: - case NT_RPC: - std::free(value->data.v_string.str); - break; - case NT_BOOLEAN_ARRAY: - std::free(value->data.arr_boolean.arr); - break; - case NT_DOUBLE_ARRAY: - std::free(value->data.arr_double.arr); - break; - case NT_STRING_ARRAY: { - for (size_t i = 0; i < value->data.arr_string.size; i++) - std::free(value->data.arr_string.arr[i].str); - std::free(value->data.arr_string.arr); - break; - } - default: - assert(0 && "unknown value type"); - } - value->type = NT_UNASSIGNED; - value->last_change = 0; -} - -void NT_InitValue(NT_Value *value) { - value->type = NT_UNASSIGNED; - value->last_change = 0; -} - -void NT_DisposeString(NT_String *str) { - std::free(str->str); - str->str = nullptr; - str->len = 0; -} - -void NT_InitString(NT_String *str) { - str->str = nullptr; - str->len = 0; -} - -void NT_DisposeConnectionInfoArray(NT_ConnectionInfo *arr, size_t count) { - unsigned int i; - for (i = 0; i < count; i++) - std::free(arr[i].remote_id.str); - std::free(arr); -}