Change C APIs to a unified string implementation (#6299)

Currently in the entire C API of WPILib we have ~8 different ways of handling strings. The C API actually isn't built for pure C callers (We don't actually have any of those). Instead, they're built for interop between languages like LabVIEW and C# which can talk to C API's directly.

For output parameters, the choice was fairly obvious. An output struct containing a const string pointer and a length makes the most sense. Its easy to use these from most other languages, and doesn't require special null termination handling. Freeing these is also easy, as if you ever receive one of these string structures, theres just a single function call to free it.

Input parameters are a bit more complex. To be used from pure C, and from LabVIEW, a null terminated string is the best in most cases. However, null terminated strings in general have a lot of downsides. Additionally, from LabVIEW there are other considerations around encoding that having a wrapper struct helps make a bit easier. From a language like C#, a wrapper struct is by far the easiest, as custom marshalling can make it trivial to marshal both UTF8 and UTF16 strings down.

The final consideration is its nice to have an identical concept for both input and output. It makes the rules fairly easy to understand.

WPILib will not have any APIs that manipulate a string allocated externally. This means WPI_String can be const, as across the boundary it is always const.
If a WPILib API takes a const WPI_String*, WPILib will not manipulate or attempt to free that string, and that string is treated as an input. It is up to the caller to handle that memory, WPILib will never hold onto that memory longer than the call.
If a WPILib API takes a WPI_String*, that string is an output. WPILib will allocate that API with WPI_AllocateString(), fill in the string, and return to the caller. When the caller is done with the string, they must free it with WPI_FreeString().
If an output struct contains a WPI_String member, that member is considered read only, and should not be explicitly freed. The caller should call the free function for that struct.
If an array of WPI_Strings are returned, each individual string is considered read only, and should not be explicitly freed. The free function for that array should be called by the caller.
If an input struct containing a WPI_String, or an input array of WPI_Strings is passed to WPILib, the individual strings will not be manipulated or freed by WPILib, and the caller owns and should free that memory.
Callbacks also follow these rules. The most common is a callback either getting passed a const WPI_String* or a struct containing a WPI_String. In both of these cases, the callback target should consider these strings read only, and not attempt to free them or manipulate them.
This commit is contained in:
Thad House
2024-05-13 05:35:14 -07:00
committed by GitHub
parent 178fe99f12
commit 4ce8f3f935
60 changed files with 990 additions and 914 deletions

View File

@@ -32,7 +32,7 @@ struct StringArrayStorage {
size_t EstimateSize() const {
return sizeof(StringArrayStorage) +
strings.capacity() * sizeof(std::string) +
ntStrings.capacity() * sizeof(NT_String) +
ntStrings.capacity() * sizeof(WPI_String) +
std::accumulate(strings.begin(), strings.end(), 0,
[](const auto& sum, const auto& val) {
return sum + val.capacity();
@@ -40,7 +40,7 @@ struct StringArrayStorage {
}
std::vector<std::string> strings;
std::vector<NT_String> ntStrings;
std::vector<WPI_String> ntStrings;
};
template <typename T>
@@ -58,11 +58,11 @@ inline std::shared_ptr<T[]> AllocateArray(size_t nelem) {
} // namespace
void StringArrayStorage::InitNtStrings() {
// point NT_String's to the contents in the vector.
// point WPI_String's to the contents in the vector.
ntStrings.reserve(strings.size());
for (const auto& str : strings) {
ntStrings.emplace_back(
NT_String{const_cast<char*>(str.c_str()), str.size()});
WPI_String{const_cast<char*>(str.c_str()), str.size()});
}
}
@@ -250,8 +250,7 @@ void nt::ConvertToC(const Value& in, NT_Value* out) {
}
case NT_STRING_ARRAY: {
auto v = in.GetStringArray();
out->data.arr_string.arr = static_cast<NT_String*>(
wpi::safe_malloc(v.size() * sizeof(NT_String)));
out->data.arr_string.arr = WPI_AllocateStringArray(v.size());
for (size_t i = 0; i < v.size(); ++i) {
ConvertToC(std::string_view{v[i]}, &out->data.arr_string.arr[i]);
}
@@ -263,18 +262,14 @@ void nt::ConvertToC(const Value& in, NT_Value* out) {
}
}
size_t nt::ConvertToC(std::string_view in, char** out) {
*out = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
std::memmove(*out, in.data(), in.size()); // NOLINT
(*out)[in.size()] = '\0';
return in.size();
}
void nt::ConvertToC(std::string_view in, NT_String* out) {
out->len = in.size();
out->str = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
std::memcpy(out->str, in.data(), in.size());
out->str[in.size()] = '\0';
void nt::ConvertToC(std::string_view in, WPI_String* out) {
if (in.empty()) {
out->len = 0;
out->str = nullptr;
return;
}
auto write = WPI_AllocateString(out, in.size());
std::memcpy(write, in.data(), in.size());
}
Value nt::ConvertFromC(const NT_Value& value) {

View File

@@ -420,8 +420,8 @@ inline void ConvertToC(const T& in, T* out) {
void ConvertToC(const Value& in, NT_Value* out);
Value ConvertFromC(const NT_Value& value);
size_t ConvertToC(std::string_view in, char** out);
void ConvertToC(std::string_view in, NT_String* out);
inline std::string_view ConvertFromC(const NT_String& str) {
void ConvertToC(std::string_view in, WPI_String* out);
inline std::string_view ConvertFromC(const WPI_String& str) {
return {str.str, str.len};
}

View File

@@ -87,19 +87,19 @@ static void ConvertToC(const Event& in, NT_Event* out) {
}
static void DisposeConnectionInfo(NT_ConnectionInfo* info) {
std::free(info->remote_id.str);
std::free(info->remote_ip.str);
WPI_FreeString(&info->remote_id);
WPI_FreeString(&info->remote_ip);
}
static void DisposeTopicInfo(NT_TopicInfo* info) {
std::free(info->name.str);
std::free(info->type_str.str);
std::free(info->properties.str);
WPI_FreeString(&info->name);
WPI_FreeString(&info->type_str);
WPI_FreeString(&info->properties);
}
static void DisposeLogMessage(NT_LogMessage* msg) {
std::free(msg->filename);
std::free(msg->message);
WPI_FreeString(&msg->filename);
WPI_FreeString(&msg->message);
}
static void DisposeEvent(NT_Event* event) {
@@ -156,15 +156,12 @@ NT_Inst NT_GetInstanceFromHandle(NT_Handle handle) {
* Table Functions
*/
NT_Entry NT_GetEntry(NT_Inst inst, const char* name, size_t name_len) {
return nt::GetEntry(inst, {name, name_len});
NT_Entry NT_GetEntry(NT_Inst inst, const struct WPI_String* name) {
return nt::GetEntry(inst, wpi::to_string_view(name));
}
char* NT_GetEntryName(NT_Entry entry, size_t* name_len) {
struct NT_String v_name;
nt::ConvertToC(nt::GetEntryName(entry), &v_name);
*name_len = v_name.len;
return v_name.str;
void NT_GetEntryName(NT_Entry entry, struct WPI_String* name) {
nt::ConvertToC(nt::GetEntryName(entry), name);
}
enum NT_Type NT_GetEntryType(NT_Entry entry) {
@@ -218,41 +215,41 @@ struct NT_Value* NT_ReadQueueValueType(NT_Handle subentry, unsigned int types,
return ConvertToC<NT_Value>(nt::ReadQueueValue(subentry, types), count);
}
NT_Topic* NT_GetTopics(NT_Inst inst, const char* prefix, size_t prefix_len,
NT_Topic* NT_GetTopics(NT_Inst inst, const struct WPI_String* prefix,
unsigned int types, size_t* count) {
auto info_v = nt::GetTopics(inst, {prefix, prefix_len}, types);
auto info_v = nt::GetTopics(inst, wpi::to_string_view(prefix), types);
return ConvertToC<NT_Topic>(info_v, count);
}
NT_Topic* NT_GetTopicsStr(NT_Inst inst, const char* prefix, size_t prefix_len,
const char* const* types, size_t types_len,
NT_Topic* NT_GetTopicsStr(NT_Inst inst, const struct WPI_String* prefix,
const struct WPI_String* types, size_t types_len,
size_t* count) {
wpi::SmallVector<std::string_view, 4> typesCpp;
typesCpp.reserve(types_len);
for (size_t i = 0; i < types_len; ++i) {
typesCpp.emplace_back(types[i]);
typesCpp.emplace_back(wpi::to_string_view(&types[i]));
}
auto info_v = nt::GetTopics(inst, {prefix, prefix_len}, typesCpp);
auto info_v = nt::GetTopics(inst, wpi::to_string_view(prefix), typesCpp);
return ConvertToC<NT_Topic>(info_v, count);
}
struct NT_TopicInfo* NT_GetTopicInfos(NT_Inst inst, const char* prefix,
size_t prefix_len, unsigned int types,
size_t* count) {
auto info_v = nt::GetTopicInfo(inst, {prefix, prefix_len}, types);
struct NT_TopicInfo* NT_GetTopicInfos(NT_Inst inst,
const struct WPI_String* prefix,
unsigned int types, size_t* count) {
auto info_v = nt::GetTopicInfo(inst, wpi::to_string_view(prefix), types);
return ConvertToC<NT_TopicInfo>(info_v, count);
}
struct NT_TopicInfo* NT_GetTopicInfosStr(NT_Inst inst, const char* prefix,
size_t prefix_len,
const char* const* types,
struct NT_TopicInfo* NT_GetTopicInfosStr(NT_Inst inst,
const struct WPI_String* prefix,
const struct WPI_String* types,
size_t types_len, size_t* count) {
wpi::SmallVector<std::string_view, 4> typesCpp;
typesCpp.reserve(types_len);
for (size_t i = 0; i < types_len; ++i) {
typesCpp.emplace_back(types[i]);
typesCpp.emplace_back(wpi::to_string_view(&types[i]));
}
auto info_v = nt::GetTopicInfo(inst, {prefix, prefix_len}, typesCpp);
auto info_v = nt::GetTopicInfo(inst, wpi::to_string_view(prefix), typesCpp);
return ConvertToC<NT_TopicInfo>(info_v, count);
}
@@ -265,32 +262,20 @@ NT_Bool NT_GetTopicInfo(NT_Topic topic, struct NT_TopicInfo* info) {
return true;
}
NT_Topic NT_GetTopic(NT_Inst inst, const char* name, size_t name_len) {
return nt::GetTopic(inst, std::string_view{name, name_len});
NT_Topic NT_GetTopic(NT_Inst inst, const struct WPI_String* name) {
return nt::GetTopic(inst, wpi::to_string_view(name));
}
char* NT_GetTopicName(NT_Topic topic, size_t* name_len) {
auto name = nt::GetTopicName(topic);
if (name.empty()) {
*name_len = 0;
return nullptr;
}
struct NT_String v_name;
nt::ConvertToC(name, &v_name);
*name_len = v_name.len;
return v_name.str;
void NT_GetTopicName(NT_Topic topic, struct WPI_String* name) {
nt::ConvertToC(nt::GetTopicName(topic), name);
}
NT_Type NT_GetTopicType(NT_Topic topic) {
return nt::GetTopicType(topic);
}
char* NT_GetTopicTypeString(NT_Topic topic, size_t* type_len) {
auto type = nt::GetTopicTypeString(topic);
struct NT_String v_type;
nt::ConvertToC(type, &v_type);
*type_len = v_type.len;
return v_type.str;
void NT_GetTopicTypeString(NT_Topic topic, struct WPI_String* type) {
nt::ConvertToC(nt::GetTopicTypeString(topic), type);
}
void NT_SetTopicPersistent(NT_Topic topic, NT_Bool value) {
@@ -321,87 +306,91 @@ NT_Bool NT_GetTopicExists(NT_Handle handle) {
return nt::GetTopicExists(handle);
}
char* NT_GetTopicProperty(NT_Topic topic, const char* name, size_t* len) {
wpi::json j = nt::GetTopicProperty(topic, name);
struct NT_String v;
nt::ConvertToC(j.dump(), &v);
*len = v.len;
return v.str;
void NT_GetTopicProperty(NT_Topic topic, const struct WPI_String* name,
struct WPI_String* prop) {
wpi::json j = nt::GetTopicProperty(topic, wpi::to_string_view(name));
nt::ConvertToC(j.dump(), prop);
}
NT_Bool NT_SetTopicProperty(NT_Topic topic, const char* name,
const char* value) {
NT_Bool NT_SetTopicProperty(NT_Topic topic, const struct WPI_String* name,
const struct WPI_String* value) {
wpi::json j;
try {
j = wpi::json::parse(value);
j = wpi::json::parse(wpi::to_string_view(value));
} catch (wpi::json::parse_error&) {
return false;
}
nt::SetTopicProperty(topic, name, j);
nt::SetTopicProperty(topic, wpi::to_string_view(name), j);
return true;
}
void NT_DeleteTopicProperty(NT_Topic topic, const char* name) {
nt::DeleteTopicProperty(topic, name);
void NT_DeleteTopicProperty(NT_Topic topic, const struct WPI_String* name) {
nt::DeleteTopicProperty(topic, wpi::to_string_view(name));
}
char* NT_GetTopicProperties(NT_Topic topic, size_t* len) {
void NT_GetTopicProperties(NT_Topic topic, struct WPI_String* property) {
wpi::json j = nt::GetTopicProperties(topic);
struct NT_String v;
nt::ConvertToC(j.dump(), &v);
*len = v.len;
return v.str;
nt::ConvertToC(j.dump(), property);
}
NT_Bool NT_SetTopicProperties(NT_Topic topic, const char* properties) {
NT_Bool NT_SetTopicProperties(NT_Topic topic,
const struct WPI_String* properties) {
wpi::json j;
try {
j = wpi::json::parse(properties);
j = wpi::json::parse(wpi::to_string_view(properties));
} catch (wpi::json::parse_error&) {
return false;
}
return nt::SetTopicProperties(topic, j);
}
NT_Subscriber NT_Subscribe(NT_Topic topic, NT_Type type, const char* typeStr,
NT_Subscriber NT_Subscribe(NT_Topic topic, NT_Type type,
const struct WPI_String* typeStr,
const struct NT_PubSubOptions* options) {
return nt::Subscribe(topic, type, typeStr, ConvertToCpp(options));
return nt::Subscribe(topic, type, wpi::to_string_view(typeStr),
ConvertToCpp(options));
}
void NT_Unsubscribe(NT_Subscriber sub) {
return nt::Unsubscribe(sub);
}
NT_Publisher NT_Publish(NT_Topic topic, NT_Type type, const char* typeStr,
NT_Publisher NT_Publish(NT_Topic topic, NT_Type type,
const struct WPI_String* typeStr,
const struct NT_PubSubOptions* options) {
return nt::Publish(topic, type, typeStr, ConvertToCpp(options));
return nt::Publish(topic, type, wpi::to_string_view(typeStr),
ConvertToCpp(options));
}
NT_Publisher NT_PublishEx(NT_Topic topic, NT_Type type, const char* typeStr,
const char* properties,
NT_Publisher NT_PublishEx(NT_Topic topic, NT_Type type,
const struct WPI_String* typeStr,
const struct WPI_String* properties,
const struct NT_PubSubOptions* options) {
wpi::json j;
if (properties[0] == '\0') {
if (properties->len == 0) {
// gracefully handle empty string
j = wpi::json::object();
} else {
try {
j = wpi::json::parse(properties);
j = wpi::json::parse(wpi::to_string_view(properties));
} catch (wpi::json::parse_error&) {
return {};
}
}
return nt::PublishEx(topic, type, typeStr, j, ConvertToCpp(options));
return nt::PublishEx(topic, type, wpi::to_string_view(typeStr), j,
ConvertToCpp(options));
}
void NT_Unpublish(NT_Handle pubentry) {
return nt::Unpublish(pubentry);
}
NT_Entry NT_GetEntryEx(NT_Topic topic, NT_Type type, const char* typeStr,
NT_Entry NT_GetEntryEx(NT_Topic topic, NT_Type type,
const struct WPI_String* typeStr,
const struct NT_PubSubOptions* options) {
return nt::GetEntry(topic, type, typeStr, ConvertToCpp(options));
return nt::GetEntry(topic, type, wpi::to_string_view(typeStr),
ConvertToCpp(options));
}
void NT_ReleaseEntry(NT_Entry entry) {
@@ -441,10 +430,10 @@ NT_Bool NT_WaitForListenerQueue(NT_Handle handle, double timeout) {
return nt::WaitForListenerQueue(handle, timeout);
}
NT_Listener NT_AddListenerSingle(NT_Inst inst, const char* prefix,
size_t prefix_len, unsigned int mask,
void* data, NT_ListenerCallback callback) {
std::string_view p{prefix, prefix_len};
NT_Listener NT_AddListenerSingle(NT_Inst inst, const struct WPI_String* prefix,
unsigned int mask, void* data,
NT_ListenerCallback callback) {
std::string_view p = wpi::to_string_view(prefix);
return nt::AddListener(inst, {{p}}, mask, [=](auto& event) {
NT_Event event_c;
ConvertToC(event, &event_c);
@@ -453,7 +442,8 @@ NT_Listener NT_AddListenerSingle(NT_Inst inst, const char* prefix,
});
}
NT_Listener NT_AddListenerMultiple(NT_Inst inst, const NT_String* prefixes,
NT_Listener NT_AddListenerMultiple(NT_Inst inst,
const struct WPI_String* prefixes,
size_t prefixes_len, unsigned int mask,
void* data, NT_ListenerCallback callback) {
wpi::SmallVector<std::string_view, 8> p;
@@ -480,14 +470,14 @@ NT_Listener NT_AddListener(NT_Topic topic, unsigned int mask, void* data,
}
NT_Listener NT_AddPolledListenerSingle(NT_ListenerPoller poller,
const char* prefix, size_t prefix_len,
const struct WPI_String* prefix,
unsigned int mask) {
std::string_view p{prefix, prefix_len};
std::string_view p = wpi::to_string_view(prefix);
return nt::AddPolledListener(poller, {{p}}, mask);
}
NT_Listener NT_AddPolledListenerMultiple(NT_ListenerPoller poller,
const NT_String* prefixes,
const struct WPI_String* prefixes,
size_t prefixes_len,
unsigned int mask) {
wpi::SmallVector<std::string_view, 8> p;
@@ -519,38 +509,42 @@ void NT_StopLocal(NT_Inst inst) {
nt::StopLocal(inst);
}
void NT_StartServer(NT_Inst inst, const char* persist_filename,
const char* listen_address, unsigned int port3,
void NT_StartServer(NT_Inst inst, const struct WPI_String* persist_filename,
const struct WPI_String* listen_address, unsigned int port3,
unsigned int port4) {
nt::StartServer(inst, persist_filename, listen_address, port3, port4);
nt::StartServer(inst, wpi::to_string_view(persist_filename),
wpi::to_string_view(listen_address), port3, port4);
}
void NT_StopServer(NT_Inst inst) {
nt::StopServer(inst);
}
void NT_StartClient3(NT_Inst inst, const char* identity) {
nt::StartClient3(inst, identity);
void NT_StartClient3(NT_Inst inst, const struct WPI_String* identity) {
nt::StartClient3(inst, wpi::to_string_view(identity));
}
void NT_StartClient4(NT_Inst inst, const char* identity) {
nt::StartClient4(inst, identity);
void NT_StartClient4(NT_Inst inst, const struct WPI_String* identity) {
nt::StartClient4(inst, wpi::to_string_view(identity));
}
void NT_StopClient(NT_Inst inst) {
nt::StopClient(inst);
}
void NT_SetServer(NT_Inst inst, const char* server_name, unsigned int port) {
nt::SetServer(inst, server_name, port);
void NT_SetServer(NT_Inst inst, const struct WPI_String* server_name,
unsigned int port) {
nt::SetServer(inst, wpi::to_string_view(server_name), port);
}
void NT_SetServerMulti(NT_Inst inst, size_t count, const char** server_names,
void NT_SetServerMulti(NT_Inst inst, size_t count,
const struct WPI_String* server_names,
const unsigned int* ports) {
std::vector<std::pair<std::string_view, unsigned int>> servers;
servers.reserve(count);
for (size_t i = 0; i < count; ++i) {
servers.emplace_back(std::make_pair(server_names[i], ports[i]));
servers.emplace_back(
std::make_pair(wpi::to_string_view(&server_names[i]), ports[i]));
}
nt::SetServer(inst, servers);
}
@@ -611,20 +605,22 @@ void NT_SetNow(int64_t timestamp) {
}
NT_DataLogger NT_StartEntryDataLog(NT_Inst inst, struct WPI_DataLog* log,
const char* prefix, const char* logPrefix) {
const struct WPI_String* prefix,
const struct WPI_String* logPrefix) {
return nt::StartEntryDataLog(inst, *reinterpret_cast<wpi::log::DataLog*>(log),
prefix, logPrefix);
wpi::to_string_view(prefix),
wpi::to_string_view(logPrefix));
}
void NT_StopEntryDataLog(NT_DataLogger logger) {
nt::StopEntryDataLog(logger);
}
NT_ConnectionDataLogger NT_StartConnectionDataLog(NT_Inst inst,
struct WPI_DataLog* log,
const char* name) {
return nt::StartConnectionDataLog(
inst, *reinterpret_cast<wpi::log::DataLog*>(log), name);
NT_ConnectionDataLogger NT_StartConnectionDataLog(
NT_Inst inst, struct WPI_DataLog* log, const struct WPI_String* name) {
return nt::StartConnectionDataLog(inst,
*reinterpret_cast<wpi::log::DataLog*>(log),
wpi::to_string_view(name));
}
void NT_StopConnectionDataLog(NT_ConnectionDataLogger logger) {
@@ -647,13 +643,15 @@ NT_Listener NT_AddPolledLogger(NT_ListenerPoller poller, unsigned int min_level,
return nt::AddPolledLogger(poller, min_level, max_level);
}
NT_Bool NT_HasSchema(NT_Inst inst, const char* name) {
return nt::HasSchema(inst, name);
NT_Bool NT_HasSchema(NT_Inst inst, const struct WPI_String* name) {
return nt::HasSchema(inst, wpi::to_string_view(name));
}
void NT_AddSchema(NT_Inst inst, const char* name, const char* type,
const uint8_t* schema, size_t schemaSize) {
nt::AddSchema(inst, name, type, {schema, schemaSize});
void NT_AddSchema(NT_Inst inst, const struct WPI_String* name,
const struct WPI_String* type, const uint8_t* schema,
size_t schemaSize) {
nt::AddSchema(inst, wpi::to_string_view(name), wpi::to_string_view(type),
{schema, schemaSize});
}
void NT_DisposeValue(NT_Value* value) {
@@ -665,7 +663,7 @@ void NT_DisposeValue(NT_Value* value) {
case NT_DOUBLE:
break;
case NT_STRING:
std::free(value->data.v_string.str);
WPI_FreeString(&value->data.v_string);
break;
case NT_RAW:
std::free(value->data.v_raw.data);
@@ -684,7 +682,7 @@ void NT_DisposeValue(NT_Value* value) {
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);
WPI_FreeString(&value->data.arr_string.arr[i]);
}
std::free(value->data.arr_string.arr);
break;
@@ -703,17 +701,6 @@ void NT_InitValue(NT_Value* value) {
value->server_time = 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_DisposeValueArray(struct NT_Value* arr, size_t count) {
for (size_t i = 0; i < count; ++i) {
NT_DisposeValue(&arr[i]);
@@ -781,12 +768,6 @@ double* NT_AllocateDoubleArray(size_t size) {
return retVal;
}
struct NT_String* NT_AllocateStringArray(size_t size) {
NT_String* retVal =
static_cast<NT_String*>(wpi::safe_malloc(size * sizeof(NT_String)));
return retVal;
}
void NT_FreeCharArray(char* v_char) {
std::free(v_char);
}
@@ -802,12 +783,6 @@ void NT_FreeFloatArray(float* v_float) {
void NT_FreeDoubleArray(double* v_double) {
std::free(v_double);
}
void NT_FreeStringArray(struct NT_String* v_string, size_t arr_size) {
for (size_t i = 0; i < arr_size; ++i) {
std::free(v_string[i].str);
}
std::free(v_string);
}
enum NT_Type NT_GetValueType(const struct NT_Value* value) {
if (!value) {
@@ -938,20 +913,19 @@ double* NT_GetValueDoubleArray(const struct NT_Value* value,
return arr;
}
NT_String* NT_GetValueStringArray(const struct NT_Value* value,
uint64_t* last_change, size_t* arr_size) {
struct WPI_String* NT_GetValueStringArray(const struct NT_Value* value,
uint64_t* last_change,
size_t* arr_size) {
if (!value || value->type != NT_Type::NT_STRING_ARRAY) {
return nullptr;
}
*last_change = value->last_change;
*arr_size = value->data.arr_string.size;
NT_String* arr = static_cast<NT_String*>(
wpi::safe_malloc(value->data.arr_string.size * sizeof(NT_String)));
struct WPI_String* arr = WPI_AllocateStringArray(value->data.arr_string.size);
for (size_t i = 0; i < value->data.arr_string.size; ++i) {
size_t len = value->data.arr_string.arr[i].len;
arr[i].len = len;
arr[i].str = static_cast<char*>(wpi::safe_malloc(len + 1));
std::memcpy(arr[i].str, value->data.arr_string.arr[i].str, len + 1);
auto write = WPI_AllocateString(&arr[i], len);
std::memcpy(write, value->data.arr_string.arr[i].str, len);
}
return arr;
}

View File

@@ -630,7 +630,7 @@ void StopLocal(NT_Inst inst) {
}
void StartServer(NT_Inst inst, std::string_view persist_filename,
const char* listen_address, unsigned int port3,
std::string_view listen_address, unsigned int port3,
unsigned int port4) {
if (auto ii = InstanceImpl::GetTyped(inst, Handle::kInstance)) {
ii->StartServer(persist_filename, listen_address, port3, port4);
@@ -661,7 +661,7 @@ void StopClient(NT_Inst inst) {
}
}
void SetServer(NT_Inst inst, const char* server_name, unsigned int port) {
void SetServer(NT_Inst inst, std::string_view server_name, unsigned int port) {
SetServer(inst, {{{server_name, port}}});
}

View File

@@ -40,7 +40,7 @@ static void ConvertToC(const ClientPublisher& in,
static void ConvertToC(const ClientSubscriber& in,
NT_Meta_ClientSubscriber* out) {
out->uid = in.uid;
out->topics = ConvertToC<NT_String>(in.topics, &out->topicsCount);
out->topics = ConvertToC<WPI_String>(in.topics, &out->topicsCount);
ConvertToC(in.options, &out->options);
}
@@ -98,7 +98,7 @@ struct NT_Meta_Client* NT_Meta_DecodeClients(const uint8_t* data, size_t size,
void NT_Meta_FreeTopicPublishers(struct NT_Meta_TopicPublisher* arr,
size_t count) {
for (size_t i = 0; i < count; ++i) {
std::free(arr[i].client.str);
WPI_FreeString(&arr[i].client);
}
std::free(arr);
}
@@ -106,7 +106,7 @@ void NT_Meta_FreeTopicPublishers(struct NT_Meta_TopicPublisher* arr,
void NT_Meta_FreeTopicSubscribers(struct NT_Meta_TopicSubscriber* arr,
size_t count) {
for (size_t i = 0; i < count; ++i) {
std::free(arr[i].client.str);
WPI_FreeString(&arr[i].client);
}
std::free(arr);
}
@@ -114,7 +114,7 @@ void NT_Meta_FreeTopicSubscribers(struct NT_Meta_TopicSubscriber* arr,
void NT_Meta_FreeClientPublishers(struct NT_Meta_ClientPublisher* arr,
size_t count) {
for (size_t i = 0; i < count; ++i) {
std::free(arr[i].topic.str);
WPI_FreeString(&arr[i].topic);
}
std::free(arr);
}
@@ -122,15 +122,15 @@ void NT_Meta_FreeClientPublishers(struct NT_Meta_ClientPublisher* arr,
void NT_Meta_FreeClientSubscribers(struct NT_Meta_ClientSubscriber* arr,
size_t count) {
for (size_t i = 0; i < count; ++i) {
NT_FreeStringArray(arr[i].topics, arr[i].topicsCount);
WPI_FreeStringArray(arr[i].topics, arr[i].topicsCount);
}
std::free(arr);
}
void NT_Meta_FreeClients(struct NT_Meta_Client* arr, size_t count) {
for (size_t i = 0; i < count; ++i) {
std::free(arr[i].id.str);
std::free(arr[i].conn.str);
WPI_FreeString(&arr[i].id);
WPI_FreeString(&arr[i].conn);
}
std::free(arr);
}

View File

@@ -11,11 +11,11 @@
#include "Value_internal.h"
extern "C" {
struct NT_String* NT_GetStringForTesting(const char* str, int* struct_size) {
struct NT_String* strout =
static_cast<NT_String*>(wpi::safe_calloc(1, sizeof(NT_String)));
struct WPI_String* NT_GetStringForTesting(const char* str, int* struct_size) {
struct WPI_String* strout =
static_cast<WPI_String*>(wpi::safe_calloc(1, sizeof(WPI_String)));
nt::ConvertToC(str, strout);
*struct_size = sizeof(NT_String);
*struct_size = sizeof(WPI_String);
return strout;
}
@@ -33,8 +33,9 @@ struct NT_TopicInfo* NT_GetTopicInfoForTesting(const char* name,
}
void NT_FreeTopicInfoForTesting(struct NT_TopicInfo* info) {
std::free(info->name.str);
std::free(info->type_str.str);
WPI_FreeString(&info->name);
WPI_FreeString(&info->type_str);
WPI_FreeString(&info->properties);
std::free(info);
}
@@ -53,8 +54,8 @@ struct NT_ConnectionInfo* NT_GetConnectionInfoForTesting(
}
void NT_FreeConnectionInfoForTesting(struct NT_ConnectionInfo* info) {
std::free(info->remote_id.str);
std::free(info->remote_ip.str);
WPI_FreeString(&info->remote_id);
WPI_FreeString(&info->remote_ip);
std::free(info);
}
@@ -136,21 +137,19 @@ struct NT_Value* NT_GetValueDoubleArrayForTesting(uint64_t last_change,
}
struct NT_Value* NT_GetValueStringArrayForTesting(uint64_t last_change,
const struct NT_String* arr,
const struct WPI_String* arr,
size_t array_len,
int* struct_size) {
struct NT_Value* value =
static_cast<NT_Value*>(wpi::safe_calloc(1, sizeof(NT_Value)));
value->type = NT_BOOLEAN;
value->last_change = last_change;
value->data.arr_string.arr = NT_AllocateStringArray(array_len);
value->data.arr_string.arr = WPI_AllocateStringArray(array_len);
value->data.arr_string.size = array_len;
for (size_t i = 0; i < value->data.arr_string.size; ++i) {
size_t len = arr[i].len;
value->data.arr_string.arr[i].len = len;
value->data.arr_string.arr[i].str =
static_cast<char*>(wpi::safe_malloc(len + 1));
std::memcpy(value->data.arr_string.arr[i].str, arr[i].str, len + 1);
auto write = WPI_AllocateString(&value->data.arr_string.arr[i], len);
std::memcpy(write, arr[i].str, len);
}
*struct_size = sizeof(NT_Value);
return value;

View File

@@ -596,10 +596,10 @@ class NetworkTableInstance final {
/**
* Sets server address and port for client (without restarting client).
*
* @param server_name server name (UTF-8 string, null terminated)
* @param server_name server name (UTF-8 string)
* @param port port to communicate over (0 = default)
*/
void SetServer(const char* server_name, unsigned int port = 0);
void SetServer(std::string_view server_name, unsigned int port = 0);
/**
* Sets server addresses and ports for client (without restarting client).

View File

@@ -168,7 +168,7 @@ inline void NetworkTableInstance::StopClient() {
::nt::StopClient(m_handle);
}
inline void NetworkTableInstance::SetServer(const char* server_name,
inline void NetworkTableInstance::SetServer(std::string_view server_name,
unsigned int port) {
::nt::SetServer(m_handle, server_name, port);
}

View File

@@ -6,6 +6,8 @@
#include <stdint.h>
#include <wpi/string.h>
#ifdef __cplusplus
#include <cstddef>
#else
@@ -129,23 +131,6 @@ enum NT_EventFlags {
* Structures
*/
/** 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
* std::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;
};
/** NetworkTables Entry Value. Note this is a typed union. */
struct NT_Value {
enum NT_Type type;
@@ -156,7 +141,7 @@ struct NT_Value {
int64_t v_int;
float v_float;
double v_double;
struct NT_String v_string;
struct WPI_String v_string;
struct {
uint8_t* data;
size_t size;
@@ -178,7 +163,7 @@ struct NT_Value {
size_t size;
} arr_int;
struct {
struct NT_String* arr;
struct WPI_String* arr;
size_t size;
} arr_string;
} data;
@@ -190,16 +175,16 @@ struct NT_TopicInfo {
NT_Topic topic;
/** Topic name */
struct NT_String name;
struct WPI_String name;
/** Topic type */
enum NT_Type type;
/** Topic type string */
struct NT_String type_str;
struct WPI_String type_str;
/** Topic properties JSON string */
struct NT_String properties;
struct WPI_String properties;
};
/** NetworkTables Connection Information */
@@ -207,10 +192,10 @@ struct NT_ConnectionInfo {
/**
* The remote identifier (as set on the remote node by NT_StartClient4().
*/
struct NT_String remote_id;
struct WPI_String remote_id;
/** The IP address of the remote node. */
struct NT_String remote_ip;
struct WPI_String remote_ip;
/** The port number of the remote node. */
unsigned int remote_port;
@@ -246,13 +231,13 @@ struct NT_LogMessage {
unsigned int level;
/** The filename of the source file that generated the message. */
char* filename;
struct WPI_String filename;
/** The line number in the source file that generated the message. */
unsigned int line;
/** The message. */
char* message;
struct WPI_String message;
};
/** NetworkTables time sync event data. */
@@ -425,20 +410,18 @@ NT_Inst NT_GetInstanceFromHandle(NT_Handle handle);
*
* @param inst instance handle
* @param name entry name (UTF-8 string)
* @param name_len length of name in bytes
* @return entry handle
*/
NT_Entry NT_GetEntry(NT_Inst inst, const char* name, size_t name_len);
NT_Entry NT_GetEntry(NT_Inst inst, const struct WPI_String* name);
/**
* Gets the name of the specified entry.
* Returns an empty string if the handle is invalid.
*
* @param entry entry handle
* @param name_len length of the returned string (output parameter)
* @return Entry name
* @param name entry name (output parameter)
*/
char* NT_GetEntryName(NT_Entry entry, size_t* name_len);
void NT_GetEntryName(NT_Entry entry, struct WPI_String* name);
/**
* Gets the type for the specified key, or unassigned if non existent.
@@ -576,13 +559,12 @@ struct NT_Value* NT_ReadQueueValueType(NT_Handle subentry, unsigned int types,
* @param inst instance handle
* @param prefix name required prefix; only topics whose name
* starts with this string are returned
* @param prefix_len length of prefix in bytes
* @param types bitmask of NT_Type values; 0 is treated specially
* as a "don't care"
* @param count output parameter; set to length of returned array
* @return Array of topic handles.
*/
NT_Topic* NT_GetTopics(NT_Inst inst, const char* prefix, size_t prefix_len,
NT_Topic* NT_GetTopics(NT_Inst inst, const struct WPI_String* prefix,
unsigned int types, size_t* count);
/**
@@ -595,14 +577,13 @@ NT_Topic* NT_GetTopics(NT_Inst inst, const char* prefix, size_t prefix_len,
* @param inst instance handle
* @param prefix name required prefix; only topics whose name
* starts with this string are returned
* @param prefix_len length of prefix in bytes
* @param types array of type strings
* @param types_len number of elements in types array
* @param count output parameter; set to length of returned array
* @return Array of topic handles.
*/
NT_Topic* NT_GetTopicsStr(NT_Inst inst, const char* prefix, size_t prefix_len,
const char* const* types, size_t types_len,
NT_Topic* NT_GetTopicsStr(NT_Inst inst, const struct WPI_String* prefix,
const struct WPI_String* types, size_t types_len,
size_t* count);
/**
@@ -615,15 +596,14 @@ NT_Topic* NT_GetTopicsStr(NT_Inst inst, const char* prefix, size_t prefix_len,
* @param inst instance handle
* @param prefix name required prefix; only topics whose name
* starts with this string are returned
* @param prefix_len length of prefix in bytes
* @param types bitmask of NT_Type values; 0 is treated specially
* as a "don't care"
* @param count output parameter; set to length of returned array
* @return Array of topic information.
*/
struct NT_TopicInfo* NT_GetTopicInfos(NT_Inst inst, const char* prefix,
size_t prefix_len, unsigned int types,
size_t* count);
struct NT_TopicInfo* NT_GetTopicInfos(NT_Inst inst,
const struct WPI_String* prefix,
unsigned int types, size_t* count);
/**
* Get Topics.
@@ -635,15 +615,14 @@ struct NT_TopicInfo* NT_GetTopicInfos(NT_Inst inst, const char* prefix,
* @param inst instance handle
* @param prefix name required prefix; only topics whose name
* starts with this string are returned
* @param prefix_len length of prefix in bytes
* @param types array of type strings
* @param types_len number of elements in types array
* @param count output parameter; set to length of returned array
* @return Array of topic information.
*/
struct NT_TopicInfo* NT_GetTopicInfosStr(NT_Inst inst, const char* prefix,
size_t prefix_len,
const char* const* types,
struct NT_TopicInfo* NT_GetTopicInfosStr(NT_Inst inst,
const struct WPI_String* prefix,
const struct WPI_String* types,
size_t types_len, size_t* count);
/**
@@ -664,19 +643,18 @@ NT_Bool NT_GetTopicInfo(NT_Topic topic, struct NT_TopicInfo* info);
*
* @param inst instance handle
* @param name topic name
* @param name_len length of topic name in bytes
* @return Topic handle.
*/
NT_Topic NT_GetTopic(NT_Inst inst, const char* name, size_t name_len);
NT_Topic NT_GetTopic(NT_Inst inst, const struct WPI_String* name);
/**
* Gets the name of the specified topic.
*
* @param topic topic handle
* @param name_len length of topic name (output)
* @return Topic name; returns NULL and name_len=0 if the handle is invalid.
* @param name topic name (output); return length of 0 and nullptr if
* handle is invalid.
*/
char* NT_GetTopicName(NT_Topic topic, size_t* name_len);
void NT_GetTopicName(NT_Topic topic, struct WPI_String* name);
/**
* Gets the type for the specified topic, or unassigned if non existent.
@@ -690,11 +668,10 @@ enum NT_Type NT_GetTopicType(NT_Topic topic);
* Gets the type string for the specified topic. This may have more information
* than the numeric type (especially for raw values).
*
* @param topic topic handle
* @param type_len length of type string (output)
* @return Topic type string; returns NULL if non-existent
* @param topic topic handle
* @param type topic type string (output)
*/
char* NT_GetTopicTypeString(NT_Topic topic, size_t* type_len);
void NT_GetTopicTypeString(NT_Topic topic, struct WPI_String* type);
/**
* Sets the persistent property of a topic. If true, the stored value is
@@ -761,10 +738,10 @@ NT_Bool NT_GetTopicExists(NT_Handle handle);
*
* @param topic topic handle
* @param name property name
* @param len length of returned string (output)
* @return JSON string; empty string if the property does not exist.
* @param property JSON string (output)
*/
char* NT_GetTopicProperty(NT_Topic topic, const char* name, size_t* len);
void NT_GetTopicProperty(NT_Topic topic, const struct WPI_String* name,
struct WPI_String* property);
/**
* Sets a property value.
@@ -773,8 +750,8 @@ char* NT_GetTopicProperty(NT_Topic topic, const char* name, size_t* len);
* @param name property name
* @param value property value (JSON string)
*/
NT_Bool NT_SetTopicProperty(NT_Topic topic, const char* name,
const char* value);
NT_Bool NT_SetTopicProperty(NT_Topic topic, const struct WPI_String* name,
const struct WPI_String* value);
/**
* Deletes a property. Has no effect if the property does not exist.
@@ -782,17 +759,16 @@ NT_Bool NT_SetTopicProperty(NT_Topic topic, const char* name,
* @param topic topic handle
* @param name property name
*/
void NT_DeleteTopicProperty(NT_Topic topic, const char* name);
void NT_DeleteTopicProperty(NT_Topic topic, const struct WPI_String* name);
/**
* Gets all topic properties as a JSON string. Each key in the object
* is the property name, and the corresponding value is the property value.
*
* @param topic topic handle
* @param len length of returned string (output)
* @return JSON string
* @param properties JSON string (output)
*/
char* NT_GetTopicProperties(NT_Topic topic, size_t* len);
void NT_GetTopicProperties(NT_Topic topic, struct WPI_String* properties);
/**
* Updates multiple topic properties. Each key in the passed-in JSON object is
@@ -804,7 +780,8 @@ char* NT_GetTopicProperties(NT_Topic topic, size_t* len);
* @param properties JSON object string with keys to add/update/delete
* @return False if properties are not a valid JSON object
*/
NT_Bool NT_SetTopicProperties(NT_Topic topic, const char* properties);
NT_Bool NT_SetTopicProperties(NT_Topic topic,
const struct WPI_String* properties);
/**
* Creates a new subscriber to value changes on a topic.
@@ -816,7 +793,7 @@ NT_Bool NT_SetTopicProperties(NT_Topic topic, const char* properties);
* @return Subscriber handle
*/
NT_Subscriber NT_Subscribe(NT_Topic topic, enum NT_Type type,
const char* typeStr,
const struct WPI_String* typeStr,
const struct NT_PubSubOptions* options);
/**
@@ -835,7 +812,8 @@ void NT_Unsubscribe(NT_Subscriber sub);
* @param options publish options
* @return Publisher handle
*/
NT_Publisher NT_Publish(NT_Topic topic, enum NT_Type type, const char* typeStr,
NT_Publisher NT_Publish(NT_Topic topic, enum NT_Type type,
const struct WPI_String* typeStr,
const struct NT_PubSubOptions* options);
/**
@@ -849,7 +827,8 @@ NT_Publisher NT_Publish(NT_Topic topic, enum NT_Type type, const char* typeStr,
* @return Publisher handle
*/
NT_Publisher NT_PublishEx(NT_Topic topic, enum NT_Type type,
const char* typeStr, const char* properties,
const struct WPI_String* typeStr,
const struct WPI_String* properties,
const struct NT_PubSubOptions* options);
/**
@@ -868,7 +847,8 @@ void NT_Unpublish(NT_Handle pubentry);
* @param options publish options
* @return Entry handle
*/
NT_Entry NT_GetEntryEx(NT_Topic topic, enum NT_Type type, const char* typeStr,
NT_Entry NT_GetEntryEx(NT_Topic topic, enum NT_Type type,
const struct WPI_String* typeStr,
const struct NT_PubSubOptions* options);
/**
@@ -912,7 +892,7 @@ NT_Topic NT_GetTopicFromHandle(NT_Handle pubsubentry);
* @return subscriber handle
*/
NT_MultiSubscriber NT_SubscribeMultiple(NT_Inst inst,
const struct NT_String* prefixes,
const struct WPI_String* prefixes,
size_t prefixes_len,
const struct NT_PubSubOptions* options);
@@ -996,16 +976,15 @@ NT_Bool NT_WaitForListenerQueue(NT_Handle handle, double timeout);
*
* @param inst Instance handle
* @param prefix Topic name string prefix
* @param prefix_len Length of topic name string prefix
* @param mask Bitmask of NT_EventFlags values (only topic and value events will
* be generated)
* @param data Data passed to callback function
* @param callback Listener function
* @return Listener handle
*/
NT_Listener NT_AddListenerSingle(NT_Inst inst, const char* prefix,
size_t prefix_len, unsigned int mask,
void* data, NT_ListenerCallback callback);
NT_Listener NT_AddListenerSingle(NT_Inst inst, const struct WPI_String* prefix,
unsigned int mask, void* data,
NT_ListenerCallback callback);
/**
* Create a listener for changes to topics with names that start with any of
@@ -1022,7 +1001,7 @@ NT_Listener NT_AddListenerSingle(NT_Inst inst, const char* prefix,
* @return Listener handle
*/
NT_Listener NT_AddListenerMultiple(NT_Inst inst,
const struct NT_String* prefixes,
const struct WPI_String* prefixes,
size_t prefixes_len, unsigned int mask,
void* data, NT_ListenerCallback callback);
@@ -1056,13 +1035,12 @@ NT_Listener NT_AddListener(NT_Handle handle, unsigned int mask, void* data,
*
* @param poller poller handle
* @param prefix UTF-8 string prefix
* @param prefix_len Length of UTF-8 string prefix
* @param mask NT_EventFlags bitmask (only topic and value events
* will be generated)
* @return Listener handle
*/
NT_Listener NT_AddPolledListenerSingle(NT_ListenerPoller poller,
const char* prefix, size_t prefix_len,
const struct WPI_String* prefix,
unsigned int mask);
/**
@@ -1078,7 +1056,7 @@ NT_Listener NT_AddPolledListenerSingle(NT_ListenerPoller poller,
* @return Listener handle
*/
NT_Listener NT_AddPolledListenerMultiple(NT_ListenerPoller poller,
const struct NT_String* prefixes,
const struct WPI_String* prefixes,
size_t prefixes_len,
unsigned int mask);
@@ -1144,8 +1122,8 @@ void NT_StopLocal(NT_Inst inst);
* @param port3 port to communicate over (NT3)
* @param port4 port to communicate over (NT4)
*/
void NT_StartServer(NT_Inst inst, const char* persist_filename,
const char* listen_address, unsigned int port3,
void NT_StartServer(NT_Inst inst, const struct WPI_String* persist_filename,
const struct WPI_String* listen_address, unsigned int port3,
unsigned int port4);
/**
@@ -1162,7 +1140,7 @@ void NT_StopServer(NT_Inst inst);
* @param inst instance handle
* @param identity network identity to advertise (cannot be empty string)
*/
void NT_StartClient3(NT_Inst inst, const char* identity);
void NT_StartClient3(NT_Inst inst, const struct WPI_String* identity);
/**
* Starts a NT4 client. Use NT_SetServer or NT_SetServerTeam to set the server
@@ -1171,7 +1149,7 @@ void NT_StartClient3(NT_Inst inst, const char* identity);
* @param inst instance handle
* @param identity network identity to advertise (cannot be empty string)
*/
void NT_StartClient4(NT_Inst inst, const char* identity);
void NT_StartClient4(NT_Inst inst, const struct WPI_String* identity);
/**
* Stops the client if it is running.
@@ -1187,7 +1165,8 @@ void NT_StopClient(NT_Inst inst);
* @param server_name server name (UTF-8 string, null terminated)
* @param port port to communicate over
*/
void NT_SetServer(NT_Inst inst, const char* server_name, unsigned int port);
void NT_SetServer(NT_Inst inst, const struct WPI_String* server_name,
unsigned int port);
/**
* Sets server addresses for client (without restarting client).
@@ -1199,7 +1178,8 @@ void NT_SetServer(NT_Inst inst, const char* server_name, unsigned int port);
* terminated)
* @param ports array of ports to communicate over (one for each server)
*/
void NT_SetServerMulti(NT_Inst inst, size_t count, const char** server_names,
void NT_SetServerMulti(NT_Inst inst, size_t count,
const struct WPI_String* server_names,
const unsigned int* ports);
/**
@@ -1323,21 +1303,6 @@ void NT_DisposeValue(struct NT_Value* value);
*/
void NT_InitValue(struct NT_Value* value);
/**
* Frees string memory.
*
* @param str string to free
*/
void NT_DisposeString(struct NT_String* str);
/**
* Initializes a NT_String.
* Sets length to zero and pointer to null.
*
* @param str string to initialize
*/
void NT_InitString(struct NT_String* str);
/**
* Frees an array of NT_Values.
*
@@ -1429,7 +1394,8 @@ void NT_SetNow(int64_t timestamp);
* @return Data logger handle
*/
NT_DataLogger NT_StartEntryDataLog(NT_Inst inst, struct WPI_DataLog* log,
const char* prefix, const char* logPrefix);
const struct WPI_String* prefix,
const struct WPI_String* logPrefix);
/**
* Stops logging entry changes to a DataLog.
@@ -1447,9 +1413,8 @@ void NT_StopEntryDataLog(NT_DataLogger logger);
* @param name data log entry name
* @return Data logger handle
*/
NT_ConnectionDataLogger NT_StartConnectionDataLog(NT_Inst inst,
struct WPI_DataLog* log,
const char* name);
NT_ConnectionDataLogger NT_StartConnectionDataLog(
NT_Inst inst, struct WPI_DataLog* log, const struct WPI_String* name);
/**
* Stops logging connection changes to a DataLog.
@@ -1513,7 +1478,7 @@ NT_Listener NT_AddPolledLogger(NT_ListenerPoller poller, unsigned int min_level,
* schema)
* @return True if schema already registered
*/
NT_Bool NT_HasSchema(NT_Inst inst, const char* name);
NT_Bool NT_HasSchema(NT_Inst inst, const struct WPI_String* name);
/**
* Registers a data schema. Data schemas provide information for how a
@@ -1531,8 +1496,9 @@ NT_Bool NT_HasSchema(NT_Inst inst, const char* name);
* @param schema Schema data
* @param schemaSize Size of schema data
*/
void NT_AddSchema(NT_Inst inst, const char* name, const char* type,
const uint8_t* schema, size_t schemaSize);
void NT_AddSchema(NT_Inst inst, const struct WPI_String* name,
const struct WPI_String* type, const uint8_t* schema,
size_t schemaSize);
/** @} */
@@ -1611,19 +1577,6 @@ float* NT_AllocateFloatArray(size_t size);
*/
double* NT_AllocateDoubleArray(size_t size);
/**
* Allocates an array of NT_Strings.
* Note that the size is the number of elements, and not the
* specific number of bytes to allocate. That is calculated internally.
*
* @param size the number of elements the array will contain
* @return the allocated NT_String array
*
* After use, the array should be freed using the NT_FreeStringArray()
* function.
*/
struct NT_String* NT_AllocateStringArray(size_t size);
/**
* Frees an array of chars.
*
@@ -1659,18 +1612,6 @@ void NT_FreeFloatArray(float* v_float);
*/
void NT_FreeDoubleArray(double* v_double);
/**
* Frees an array of NT_Strings.
*
* @param v_string pointer to the string array to free
* @param arr_size size of the string array to free
*
* Note that the individual NT_Strings in the array should NOT be
* freed before calling this. This function will free all the strings
* individually.
*/
void NT_FreeStringArray(struct NT_String* v_string, size_t arr_size);
/** @} */
/**
@@ -1838,24 +1779,24 @@ double* NT_GetValueDoubleArray(const struct NT_Value* value,
uint64_t* last_change, size_t* arr_size);
/**
* Returns a copy of the NT_String array from the NT_Value.
* Returns a copy of the struct WPI_String array from the NT_Value.
* If the NT_Value is null, or is assigned to a different type, returns null.
*
* @param value NT_Value struct to get the NT_String array from
* @param value NT_Value struct to get the struct WPI_String array from
* @param last_change returns time in ms since the last change in the value
* @param arr_size returns the number of elements in the array
* @return pointer to the NT_String array, or null if error
* @return pointer to the struct WPI_String array, or null if error
*
* It is the caller's responsibility to free the array once its no longer
* needed. The NT_FreeStringArray() function is useful for this purpose.
* needed. The WPI_FreeStringArray() function is useful for this purpose.
* The returned array is a copy of the array in the value, and must be
* freed separately. Note that the individual NT_Strings should not be freed,
* but the entire array should be freed at once. The NT_FreeStringArray()
* function will free all the NT_Strings.
* freed separately. Note that the individual struct WPI_Strings should not be
* freed, but the entire array should be freed at once. The
* WPI_FreeStringArray() function will free all the struct WPI_Strings.
*/
struct NT_String* NT_GetValueStringArray(const struct NT_Value* value,
uint64_t* last_change,
size_t* arr_size);
struct WPI_String* NT_GetValueStringArray(const struct NT_Value* value,
uint64_t* last_change,
size_t* arr_size);
/** @} */
/** @} */
@@ -1884,7 +1825,7 @@ struct NT_Meta_SubscriberOptions {
* Topic publisher (as published via `$pub$<topic>`).
*/
struct NT_Meta_TopicPublisher {
struct NT_String client;
struct WPI_String client;
uint64_t pubuid;
};
@@ -1892,7 +1833,7 @@ struct NT_Meta_TopicPublisher {
* Topic subscriber (as published via `$sub$<topic>`).
*/
struct NT_Meta_TopicSubscriber {
struct NT_String client;
struct WPI_String client;
uint64_t subuid;
struct NT_Meta_SubscriberOptions options;
};
@@ -1902,7 +1843,7 @@ struct NT_Meta_TopicSubscriber {
*/
struct NT_Meta_ClientPublisher {
int64_t uid;
struct NT_String topic;
struct WPI_String topic;
};
/**
@@ -1911,7 +1852,7 @@ struct NT_Meta_ClientPublisher {
struct NT_Meta_ClientSubscriber {
int64_t uid;
size_t topicsCount;
struct NT_String* topics;
struct WPI_String* topics;
struct NT_Meta_SubscriberOptions options;
};
@@ -1919,8 +1860,8 @@ struct NT_Meta_ClientSubscriber {
* Client (as published via `$clients`).
*/
struct NT_Meta_Client {
struct NT_String id;
struct NT_String conn;
struct WPI_String id;
struct WPI_String conn;
uint16_t version;
};

View File

@@ -1056,12 +1056,12 @@ void StopLocal(NT_Inst inst);
* @param persist_filename the name of the persist file to use (UTF-8 string,
* null terminated)
* @param listen_address the address to listen on, or null to listen on any
* address. (UTF-8 string, null terminated)
* address. (UTF-8 string)
* @param port3 port to communicate over (NT3)
* @param port4 port to communicate over (NT4)
*/
void StartServer(NT_Inst inst, std::string_view persist_filename,
const char* listen_address, unsigned int port3,
std::string_view listen_address, unsigned int port3,
unsigned int port4);
/**
@@ -1103,7 +1103,7 @@ void StopClient(NT_Inst inst);
* @param server_name server name (UTF-8 string, null terminated)
* @param port port to communicate over
*/
void SetServer(NT_Inst inst, const char* server_name, unsigned int port);
void SetServer(NT_Inst inst, std::string_view server_name, unsigned int port);
/**
* Sets server addresses for client (without restarting client).

View File

@@ -14,7 +14,7 @@
extern "C" {
#endif
struct NT_String* NT_GetStringForTesting(const char* str, int* struct_size);
struct WPI_String* NT_GetStringForTesting(const char* str, int* struct_size);
// No need for free as one already exists in main library
struct NT_EntryInfo* NT_GetEntryInfoForTesting(const char* name,
@@ -54,7 +54,7 @@ struct NT_Value* NT_GetValueDoubleArrayForTesting(uint64_t last_change,
int* struct_size);
struct NT_Value* NT_GetValueStringArrayForTesting(uint64_t last_change,
const struct NT_String* arr,
const struct WPI_String* arr,
size_t array_len,
int* struct_size);
// No need for free as one already exists in the main library