mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-01 02:41:48 +00:00
Start implementing LoadPersistent.
Switch to using fstream instead of stdio. Change-Id: I600a8748a0b3dcf24740d63cc296df000abc388d
This commit is contained in:
166
include/ntcore.h
166
include/ntcore.h
@@ -19,20 +19,20 @@ extern "C" {
|
||||
|
||||
/** NetworkTables data types. */
|
||||
enum NT_Type {
|
||||
NT_UNASSIGNED = 0,
|
||||
NT_BOOLEAN = 0x01,
|
||||
NT_DOUBLE = 0x02,
|
||||
NT_STRING = 0x04,
|
||||
NT_RAW = 0x08,
|
||||
NT_BOOLEAN_ARRAY = 0x10,
|
||||
NT_DOUBLE_ARRAY = 0x20,
|
||||
NT_STRING_ARRAY = 0x40,
|
||||
NT_RPC = 0x80
|
||||
NT_UNASSIGNED = 0,
|
||||
NT_BOOLEAN = 0x01,
|
||||
NT_DOUBLE = 0x02,
|
||||
NT_STRING = 0x04,
|
||||
NT_RAW = 0x08,
|
||||
NT_BOOLEAN_ARRAY = 0x10,
|
||||
NT_DOUBLE_ARRAY = 0x20,
|
||||
NT_STRING_ARRAY = 0x40,
|
||||
NT_RPC = 0x80
|
||||
};
|
||||
|
||||
/** NetworkTables entry flags. */
|
||||
enum NT_EntryFlags {
|
||||
NT_PERSISTENT = 0x01
|
||||
NT_PERSISTENT = 0x01
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -41,87 +41,87 @@ enum NT_EntryFlags {
|
||||
|
||||
/** A NetworkTables string. */
|
||||
struct NT_String {
|
||||
/** String contents (UTF-8).
|
||||
* The string is NOT required to be zero-terminated.
|
||||
* When returned by the library, this is zero-terminated and allocated with
|
||||
* malloc().
|
||||
*/
|
||||
char *str;
|
||||
/** String contents (UTF-8).
|
||||
* The string is NOT required to be zero-terminated.
|
||||
* When returned by the library, this is zero-terminated and allocated with
|
||||
* malloc().
|
||||
*/
|
||||
char *str;
|
||||
|
||||
/** Length of the string in bytes. If the string happens to be zero
|
||||
* terminated, this does not include the zero-termination.
|
||||
*/
|
||||
size_t len;
|
||||
/** Length of the string in bytes. If the string happens to be zero
|
||||
* terminated, this does not include the zero-termination.
|
||||
*/
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** NetworkTables Entry Value. Note this is a typed union. */
|
||||
struct NT_Value {
|
||||
enum NT_Type type;
|
||||
unsigned long long last_change;
|
||||
union {
|
||||
int v_boolean;
|
||||
double v_double;
|
||||
struct NT_String v_string;
|
||||
struct NT_String v_raw;
|
||||
struct {
|
||||
int *arr;
|
||||
size_t size;
|
||||
} arr_boolean;
|
||||
struct {
|
||||
double *arr;
|
||||
size_t size;
|
||||
} arr_double;
|
||||
struct {
|
||||
struct NT_String *arr;
|
||||
size_t size;
|
||||
} arr_string;
|
||||
} data;
|
||||
enum NT_Type type;
|
||||
unsigned long long last_change;
|
||||
union {
|
||||
int v_boolean;
|
||||
double v_double;
|
||||
struct NT_String v_string;
|
||||
struct NT_String v_raw;
|
||||
struct {
|
||||
int *arr;
|
||||
size_t size;
|
||||
} arr_boolean;
|
||||
struct {
|
||||
double *arr;
|
||||
size_t size;
|
||||
} arr_double;
|
||||
struct {
|
||||
struct NT_String *arr;
|
||||
size_t size;
|
||||
} arr_string;
|
||||
} data;
|
||||
};
|
||||
|
||||
/** NetworkTables Entry Information */
|
||||
struct NT_EntryInfo {
|
||||
/** Entry name */
|
||||
struct NT_String name;
|
||||
/** Entry name */
|
||||
struct NT_String name;
|
||||
|
||||
/** Entry type */
|
||||
enum NT_Type type;
|
||||
/** Entry type */
|
||||
enum NT_Type type;
|
||||
|
||||
/** Entry flags */
|
||||
unsigned int flags;
|
||||
/** Entry flags */
|
||||
unsigned int flags;
|
||||
|
||||
/** Timestamp of last change to entry (type or value). */
|
||||
unsigned long long last_change;
|
||||
/** Timestamp of last change to entry (type or value). */
|
||||
unsigned long long last_change;
|
||||
};
|
||||
|
||||
/** NetworkTables Connection Information */
|
||||
struct NT_ConnectionInfo {
|
||||
struct NT_String remote_id;
|
||||
const char *remote_name;
|
||||
unsigned int remote_port;
|
||||
unsigned long long last_update;
|
||||
unsigned int protocol_version;
|
||||
struct NT_String remote_id;
|
||||
const char *remote_name;
|
||||
unsigned int remote_port;
|
||||
unsigned long long last_update;
|
||||
unsigned int protocol_version;
|
||||
};
|
||||
|
||||
/** NetworkTables RPC Parameter Definition */
|
||||
struct NT_RpcParamDef {
|
||||
struct NT_String name;
|
||||
struct NT_Value def_value;
|
||||
struct NT_String name;
|
||||
struct NT_Value def_value;
|
||||
};
|
||||
|
||||
/** NetworkTables RPC Result Definition */
|
||||
struct NT_RpcResultDef {
|
||||
struct NT_String name;
|
||||
enum NT_Type type;
|
||||
struct NT_String name;
|
||||
enum NT_Type type;
|
||||
};
|
||||
|
||||
/** NetworkTables RPC Definition */
|
||||
struct NT_RpcDefinition {
|
||||
unsigned int version;
|
||||
struct NT_String name;
|
||||
size_t num_params;
|
||||
NT_RpcParamDef *params;
|
||||
size_t num_results;
|
||||
NT_RpcResultDef *results;
|
||||
unsigned int version;
|
||||
struct NT_String name;
|
||||
size_t num_params;
|
||||
NT_RpcParamDef *params;
|
||||
size_t num_results;
|
||||
NT_RpcResultDef *results;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -141,7 +141,7 @@ struct NT_RpcDefinition {
|
||||
* purpose).
|
||||
*/
|
||||
void NT_GetEntryValue(const char *name, size_t name_len,
|
||||
struct NT_Value *value);
|
||||
struct NT_Value *value);
|
||||
|
||||
/** Set Entry Value.
|
||||
* Sets new entry value. If type of new value differs from the type of the
|
||||
@@ -153,7 +153,7 @@ void NT_GetEntryValue(const char *name, size_t name_len,
|
||||
* @return 0 on error (type mismatch), 1 on success
|
||||
*/
|
||||
int NT_SetEntryValue(const char *name, size_t name_len,
|
||||
const struct NT_Value *value);
|
||||
const struct NT_Value *value);
|
||||
|
||||
/** Set Entry Type and Value.
|
||||
* Sets new entry value. If type of new value differs from the type of the
|
||||
@@ -168,7 +168,7 @@ int NT_SetEntryValue(const char *name, size_t name_len,
|
||||
* @param value new entry value
|
||||
*/
|
||||
void NT_SetEntryTypeValue(const char *name, size_t name_len,
|
||||
const struct NT_Value *value);
|
||||
const struct NT_Value *value);
|
||||
|
||||
/** Set Entry Flags.
|
||||
*/
|
||||
@@ -218,7 +218,7 @@ void NT_DeleteAllEntries(void);
|
||||
* @return Array of entry information.
|
||||
*/
|
||||
struct NT_EntryInfo *NT_GetEntryInfo(const char *prefix, size_t prefix_len,
|
||||
unsigned int types, size_t *count);
|
||||
unsigned int types, size_t *count);
|
||||
|
||||
/** Flush Entries.
|
||||
* Forces an immediate flush of all local entry changes to network.
|
||||
@@ -235,33 +235,36 @@ void NT_Flush(void);
|
||||
* Callback Creation Functions
|
||||
*/
|
||||
|
||||
typedef void (*NT_EntryListenerCallback) (unsigned int uid, void *data,
|
||||
const char *name, size_t name_len, struct NT_Value *value);
|
||||
typedef void (*NT_EntryListenerCallback)(
|
||||
unsigned int uid, void *data, const char *name, size_t name_len,
|
||||
struct NT_Value *value);
|
||||
|
||||
typedef void (*NT_ConnectionListenerCallback) (unsigned int uid, void *data,
|
||||
int connected, const struct NT_ConnectionInfo *conn);
|
||||
typedef void (*NT_ConnectionListenerCallback)(
|
||||
unsigned int uid, void *data, int connected,
|
||||
const struct NT_ConnectionInfo *conn);
|
||||
|
||||
unsigned int NT_AddEntryListener(const char *prefix, size_t prefix_len,
|
||||
void *data, NT_EntryListenerCallback callback);
|
||||
void *data, NT_EntryListenerCallback callback);
|
||||
void NT_RemoveEntryListener(unsigned int entry_listener_uid);
|
||||
unsigned int NT_AddConnectionListener(void *data,
|
||||
NT_ConnectionListenerCallback callback);
|
||||
NT_ConnectionListenerCallback callback);
|
||||
void NT_RemoveConnectionListener(unsigned int conn_listener_uid);
|
||||
|
||||
/*
|
||||
* Remote Procedure Call Functions
|
||||
*/
|
||||
|
||||
typedef NT_Value * (*NT_RpcCallback) (unsigned int uid, void *data,
|
||||
const char *name, size_t name_len,
|
||||
NT_Value *params, size_t params_len,
|
||||
size_t *results_len);
|
||||
typedef NT_Value *(*NT_RpcCallback)(unsigned int uid, void *data,
|
||||
const char *name, size_t name_len,
|
||||
NT_Value *params, size_t params_len,
|
||||
size_t *results_len);
|
||||
|
||||
unsigned int NT_CreateRpc(const char *name, size_t name_len,
|
||||
const NT_RpcDefinition *def, void *data, NT_RpcCallback callback);
|
||||
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);
|
||||
const NT_Value *params, size_t params_len);
|
||||
NT_Value *NT_GetRpcResult(unsigned int result_uid, size_t *results_len);
|
||||
|
||||
/*
|
||||
@@ -269,7 +272,7 @@ NT_Value *NT_GetRpcResult(unsigned int result_uid, size_t *results_len);
|
||||
*/
|
||||
void NT_SetNetworkIdentity(const char *name, size_t name_len);
|
||||
void NT_StartServer(const char *persist_filename, const char *listen_address,
|
||||
unsigned int port);
|
||||
unsigned int port);
|
||||
void NT_StopServer(void);
|
||||
void NT_StartClient(const char *server_name, unsigned int port);
|
||||
void NT_StopClient(void);
|
||||
@@ -281,7 +284,8 @@ struct NT_ConnectionInfo *NT_GetConnections(size_t *count);
|
||||
*/
|
||||
/* return error string, or NULL if successful */
|
||||
const char *NT_SavePersistent(const char *filename);
|
||||
const char *NT_LoadPersistent(const char *filename);
|
||||
const char *NT_LoadPersistent(const char *filename,
|
||||
void (*warn)(size_t line, const char *msg));
|
||||
|
||||
/*
|
||||
* Utility Functions
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
|
||||
#include "ntcore.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
#include "llvm/StringExtras.h"
|
||||
#include "base64.h"
|
||||
@@ -15,48 +17,45 @@
|
||||
|
||||
using namespace ntimpl;
|
||||
|
||||
static void WriteString(FILE* f, llvm::StringRef str) {
|
||||
fputc('"', f);
|
||||
for (unsigned int i = 0, e = str.size(); i != e; ++i) {
|
||||
unsigned char c = str[i];
|
||||
|
||||
static void WriteString(std::ostream& os, llvm::StringRef str) {
|
||||
os << '"';
|
||||
for (auto c : str) {
|
||||
switch (c) {
|
||||
case '\\':
|
||||
fputs("\\\\", f);
|
||||
os << "\\\\";
|
||||
break;
|
||||
case '\t':
|
||||
fputs("\\t", f);
|
||||
os << "\\t";
|
||||
break;
|
||||
case '\n':
|
||||
fputs("\\n", f);
|
||||
os << "\\n";
|
||||
break;
|
||||
case '"':
|
||||
fputs("\\\"", f);
|
||||
os << "\\\"";
|
||||
break;
|
||||
default:
|
||||
if (std::isprint(c)) {
|
||||
fputc(c, f);
|
||||
os << c;
|
||||
break;
|
||||
}
|
||||
|
||||
// Write out the escaped representation.
|
||||
fputs("\\x", f);
|
||||
fputc(llvm::hexdigit((c >> 4 & 0xF)), f);
|
||||
fputc(llvm::hexdigit((c >> 0) & 0xF), f);
|
||||
os << "\\x";
|
||||
os << llvm::hexdigit((c >> 4) & 0xF);
|
||||
os << llvm::hexdigit((c >> 0) & 0xF);
|
||||
}
|
||||
}
|
||||
fputc('"', f);
|
||||
os << '"';
|
||||
}
|
||||
|
||||
const char* NT_SavePersistent(const char* filename) {
|
||||
FILE* f = fopen(filename, "wt");
|
||||
if (!f) return "could not open file";
|
||||
std::ofstream os(filename);
|
||||
if (!os) return "could not open file";
|
||||
|
||||
fputs("[NetworkTables Storage 3.0]\n", f);
|
||||
os << "[NetworkTables Storage 3.0]\n";
|
||||
|
||||
Storage& storage = Storage::GetInstance();
|
||||
for (Storage::EntriesMap::const_iterator i = storage.entries.begin(),
|
||||
end = storage.entries.end();
|
||||
const Storage& storage = Storage::GetInstance();
|
||||
for (auto i = storage.entries.begin(), end = storage.entries.end();
|
||||
i != end; ++i) {
|
||||
const StorageEntry& entry = i->getValue();
|
||||
// only write persistent-flagged values
|
||||
@@ -66,72 +65,75 @@ const char* NT_SavePersistent(const char* filename) {
|
||||
const NT_Value& v = entry.value;
|
||||
switch (v.type) {
|
||||
case NT_BOOLEAN:
|
||||
fputs("boolean ", f);
|
||||
os << "boolean ";
|
||||
break;
|
||||
case NT_DOUBLE:
|
||||
fputs("double ", f);
|
||||
os << "double ";
|
||||
break;
|
||||
case NT_STRING:
|
||||
fputs("string ", f);
|
||||
os << "string ";
|
||||
break;
|
||||
case NT_RAW:
|
||||
fputs("raw ", f);
|
||||
os << "raw ";
|
||||
break;
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
fputs("array boolean ", f);
|
||||
os << "array boolean ";
|
||||
break;
|
||||
case NT_DOUBLE_ARRAY:
|
||||
fputs("array double ", f);
|
||||
os << "array double ";
|
||||
break;
|
||||
case NT_STRING_ARRAY:
|
||||
fputs("array string ", f);
|
||||
os << "array string ";
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
// name
|
||||
WriteString(f, i->getKey());
|
||||
WriteString(os, i->getKey());
|
||||
|
||||
// =
|
||||
fputc('=', f);
|
||||
os << '=';
|
||||
|
||||
// value
|
||||
switch (v.type) {
|
||||
case NT_BOOLEAN:
|
||||
fputs(v.data.v_boolean ? "true" : "false", f);
|
||||
os << (v.data.v_boolean ? "true" : "false");
|
||||
break;
|
||||
case NT_DOUBLE:
|
||||
fprintf(f, "%g", v.data.v_double);
|
||||
os << v.data.v_double;
|
||||
break;
|
||||
case NT_STRING:
|
||||
WriteString(f, MakeStringRef(v.data.v_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<const unsigned char*>(v.data.v_raw.str),
|
||||
v.data.v_raw.len);
|
||||
fputs(buf, f);
|
||||
os << buf;
|
||||
delete[] buf;
|
||||
break;
|
||||
}
|
||||
case NT_BOOLEAN_ARRAY:
|
||||
for (size_t i = 0; i < v.data.arr_boolean.size; ++i) {
|
||||
fputs(v.data.arr_boolean.arr[i] ? "true" : "false", f);
|
||||
if (i != (v.data.arr_boolean.size - 1)) fputc(',', f);
|
||||
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) {
|
||||
fprintf(f, "%g", v.data.arr_double.arr[i]);
|
||||
if (i != (v.data.arr_double.size - 1)) fputc(',', f);
|
||||
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(f, MakeStringRef(v.data.arr_string.arr[i]));
|
||||
if (i != (v.data.arr_double.size - 1)) fputc(',', f);
|
||||
WriteString(os, MakeStringRef(v.data.arr_string.arr[i]));
|
||||
if (i != (v.data.arr_double.size - 1))
|
||||
os << ',';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -139,17 +141,48 @@ const char* NT_SavePersistent(const char* filename) {
|
||||
}
|
||||
|
||||
// eol
|
||||
fputc('\n', f);
|
||||
os << '\n';
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
os.close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* NT_LoadPersistent(const char* filename) {
|
||||
FILE* f = fopen(filename, "rt");
|
||||
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";
|
||||
|
||||
fclose(f);
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user