diff --git a/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp b/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp index 9f09eff0502..e7e8721d9f4 100644 --- a/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp +++ b/cscore/src/main/native/cpp/ConfigurableSourceImpl.cpp @@ -197,9 +197,9 @@ void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property, } // namespace cs extern "C" { -void CS_NotifySourceError(CS_Source source, const char* msg, +void CS_NotifySourceError(CS_Source source, const struct WPI_String* msg, CS_Status* status) { - return cs::NotifySourceError(source, msg, status); + return cs::NotifySourceError(source, wpi::to_string_view(msg), status); } void CS_SetSourceConnected(CS_Source source, CS_Bool connected, @@ -207,17 +207,21 @@ void CS_SetSourceConnected(CS_Source source, CS_Bool connected, return cs::SetSourceConnected(source, connected, status); } -void CS_SetSourceDescription(CS_Source source, const char* description, +void CS_SetSourceDescription(CS_Source source, + const struct WPI_String* description, CS_Status* status) { - return cs::SetSourceDescription(source, description, status); + return cs::SetSourceDescription(source, wpi::to_string_view(description), + status); } -CS_Property CS_CreateSourceProperty(CS_Source source, const char* name, +CS_Property CS_CreateSourceProperty(CS_Source source, + const struct WPI_String* name, enum CS_PropertyKind kind, int minimum, int maximum, int step, int defaultValue, int value, CS_Status* status) { - return cs::CreateSourceProperty(source, name, kind, minimum, maximum, step, - defaultValue, value, status); + return cs::CreateSourceProperty(source, wpi::to_string_view(name), kind, + minimum, maximum, step, defaultValue, value, + status); } CS_Property CS_CreateSourcePropertyCallback( @@ -230,12 +234,12 @@ CS_Property CS_CreateSourcePropertyCallback( } void CS_SetSourceEnumPropertyChoices(CS_Source source, CS_Property property, - const char** choices, int count, - CS_Status* status) { + const struct WPI_String* choices, + int count, CS_Status* status) { wpi::SmallVector vec; vec.reserve(count); for (int i = 0; i < count; ++i) { - vec.push_back(choices[i]); + vec.emplace_back(wpi::to_string_view(&choices[i])); } return cs::SetSourceEnumPropertyChoices(source, property, vec, status); } diff --git a/cscore/src/main/native/cpp/HttpCameraImpl.cpp b/cscore/src/main/native/cpp/HttpCameraImpl.cpp index da60d77f291..05a5c90cafe 100644 --- a/cscore/src/main/native/cpp/HttpCameraImpl.cpp +++ b/cscore/src/main/native/cpp/HttpCameraImpl.cpp @@ -634,55 +634,47 @@ std::vector GetHttpCameraUrls(CS_Source source, extern "C" { -CS_Source CS_CreateHttpCamera(const char* name, const char* url, +CS_Source CS_CreateHttpCamera(const struct WPI_String* name, + const struct WPI_String* url, CS_HttpCameraKind kind, CS_Status* status) { - return cs::CreateHttpCamera(name, url, kind, status); + return cs::CreateHttpCamera(wpi::to_string_view(name), + wpi::to_string_view(url), kind, status); } -CS_Source CS_CreateHttpCameraMulti(const char* name, const char** urls, - int count, CS_HttpCameraKind kind, - CS_Status* status) { +CS_Source CS_CreateHttpCameraMulti(const struct WPI_String* name, + const struct WPI_String* urls, int count, + CS_HttpCameraKind kind, CS_Status* status) { wpi::SmallVector vec; vec.reserve(count); for (int i = 0; i < count; ++i) { - vec.push_back(urls[i]); + vec.emplace_back(wpi::to_string_view(&urls[i])); } - return cs::CreateHttpCamera(name, vec, kind, status); + return cs::CreateHttpCamera(wpi::to_string_view(name), vec, kind, status); } CS_HttpCameraKind CS_GetHttpCameraKind(CS_Source source, CS_Status* status) { return cs::GetHttpCameraKind(source, status); } -void CS_SetHttpCameraUrls(CS_Source source, const char** urls, int count, - CS_Status* status) { +void CS_SetHttpCameraUrls(CS_Source source, const struct WPI_String* urls, + int count, CS_Status* status) { wpi::SmallVector vec; vec.reserve(count); for (int i = 0; i < count; ++i) { - vec.push_back(urls[i]); + vec.emplace_back(wpi::to_string_view(&urls[i])); } cs::SetHttpCameraUrls(source, vec, status); } -char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status) { +WPI_String* CS_GetHttpCameraUrls(CS_Source source, int* count, + CS_Status* status) { auto urls = cs::GetHttpCameraUrls(source, status); - char** out = - static_cast(wpi::safe_malloc(urls.size() * sizeof(char*))); + WPI_String* out = WPI_AllocateStringArray(urls.size()); *count = urls.size(); for (size_t i = 0; i < urls.size(); ++i) { - out[i] = cs::ConvertToC(urls[i]); + cs::ConvertToC(&out[i], urls[i]); } return out; } -void CS_FreeHttpCameraUrls(char** urls, int count) { - if (!urls) { - return; - } - for (int i = 0; i < count; ++i) { - std::free(urls[i]); - } - std::free(urls); -} - } // extern "C" diff --git a/cscore/src/main/native/cpp/MjpegServerImpl.cpp b/cscore/src/main/native/cpp/MjpegServerImpl.cpp index 6dd09847ec0..f6f63d6673d 100644 --- a/cscore/src/main/native/cpp/MjpegServerImpl.cpp +++ b/cscore/src/main/native/cpp/MjpegServerImpl.cpp @@ -1047,13 +1047,17 @@ int GetMjpegServerPort(CS_Sink sink, CS_Status* status) { extern "C" { -CS_Sink CS_CreateMjpegServer(const char* name, const char* listenAddress, - int port, CS_Status* status) { - return cs::CreateMjpegServer(name, listenAddress, port, status); +CS_Sink CS_CreateMjpegServer(const struct WPI_String* name, + const struct WPI_String* listenAddress, int port, + CS_Status* status) { + return cs::CreateMjpegServer(wpi::to_string_view(name), + wpi::to_string_view(listenAddress), port, + status); } -char* CS_GetMjpegServerListenAddress(CS_Sink sink, CS_Status* status) { - return ConvertToC(cs::GetMjpegServerListenAddress(sink, status)); +void CS_GetMjpegServerListenAddress(CS_Sink sink, WPI_String* listenAddress, + CS_Status* status) { + cs::ConvertToC(listenAddress, cs::GetMjpegServerListenAddress(sink, status)); } int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status) { diff --git a/cscore/src/main/native/cpp/RawSinkImpl.cpp b/cscore/src/main/native/cpp/RawSinkImpl.cpp index 74e73590931..bdbf2c1a9a6 100644 --- a/cscore/src/main/native/cpp/RawSinkImpl.cpp +++ b/cscore/src/main/native/cpp/RawSinkImpl.cpp @@ -184,16 +184,17 @@ uint64_t GrabSinkFrameTimeout(CS_Sink sink, WPI_RawFrame& image, double timeout, } // namespace cs extern "C" { -CS_Sink CS_CreateRawSink(const char* name, CS_Bool isCv, CS_Status* status) { - return cs::CreateRawSink(name, isCv, status); +CS_Sink CS_CreateRawSink(const struct WPI_String* name, CS_Bool isCv, + CS_Status* status) { + return cs::CreateRawSink(wpi::to_string_view(name), isCv, status); } -CS_Sink CS_CreateRawSinkCallback(const char* name, CS_Bool isCv, void* data, - void (*processFrame)(void* data, - uint64_t time), - CS_Status* status) { +CS_Sink CS_CreateRawSinkCallback( + const struct WPI_String* name, CS_Bool isCv, void* data, + void (*processFrame)(void* data, uint64_t time), CS_Status* status) { return cs::CreateRawSinkCallback( - name, isCv, [=](uint64_t time) { processFrame(data, time); }, status); + wpi::to_string_view(name), isCv, + [=](uint64_t time) { processFrame(data, time); }, status); } uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct WPI_RawFrame* image, diff --git a/cscore/src/main/native/cpp/RawSourceImpl.cpp b/cscore/src/main/native/cpp/RawSourceImpl.cpp index 94da6d06aa3..aad27b240ef 100644 --- a/cscore/src/main/native/cpp/RawSourceImpl.cpp +++ b/cscore/src/main/native/cpp/RawSourceImpl.cpp @@ -53,9 +53,9 @@ void PutSourceFrame(CS_Source source, const WPI_RawFrame& image, } // namespace cs extern "C" { -CS_Source CS_CreateRawSource(const char* name, CS_Bool isCv, +CS_Source CS_CreateRawSource(const struct WPI_String* name, CS_Bool isCv, const CS_VideoMode* mode, CS_Status* status) { - return cs::CreateRawSource(name, isCv, + return cs::CreateRawSource(wpi::to_string_view(name), isCv, static_cast(*mode), status); } diff --git a/cscore/src/main/native/cpp/SinkImpl.cpp b/cscore/src/main/native/cpp/SinkImpl.cpp index 3d4e70cf9a8..0897bb8d6a5 100644 --- a/cscore/src/main/native/cpp/SinkImpl.cpp +++ b/cscore/src/main/native/cpp/SinkImpl.cpp @@ -242,18 +242,15 @@ void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status) { } // namespace cs extern "C" { -void CS_SetSinkDescription(CS_Sink sink, const char* description, +void CS_SetSinkDescription(CS_Sink sink, const struct WPI_String* description, CS_Status* status) { - return cs::SetSinkDescription(sink, description, status); + return cs::SetSinkDescription(sink, wpi::to_string_view(description), status); } -char* CS_GetSinkError(CS_Sink sink, CS_Status* status) { +void CS_GetSinkError(CS_Sink sink, struct WPI_String* error, + CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetSinkError(sink, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(error, cs::GetSinkError(sink, buf, status)); } void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status) { diff --git a/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp b/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp index 5731f1f1b6b..81afcc10563 100644 --- a/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp +++ b/cscore/src/main/native/cpp/UsbCameraImplCommon.cpp @@ -4,6 +4,8 @@ #include "cscore_c.h" // NOLINT(build/include_order) +#include + #include "c_util.h" #include "cscore_cpp.h" @@ -11,56 +13,53 @@ using namespace cs; static void ConvertToC(CS_UsbCameraInfo* out, const UsbCameraInfo& in) { out->dev = in.dev; - out->path = ConvertToC(in.path); - out->name = ConvertToC(in.name); - out->otherPaths = static_cast( - wpi::safe_malloc(in.otherPaths.size() * sizeof(char*))); + cs::ConvertToC(&out->path, in.path); + cs::ConvertToC(&out->name, in.name); + out->otherPaths = WPI_AllocateStringArray(in.otherPaths.size()); out->otherPathsCount = in.otherPaths.size(); for (size_t i = 0; i < in.otherPaths.size(); ++i) { - out->otherPaths[i] = cs::ConvertToC(in.otherPaths[i]); + cs::ConvertToC(&out->otherPaths[i], in.otherPaths[i]); } out->vendorId = in.vendorId; out->productId = in.productId; } static void FreeUsbCameraInfo(CS_UsbCameraInfo* info) { - std::free(info->path); - std::free(info->name); + WPI_FreeString(&info->path); + WPI_FreeString(&info->name); for (int i = 0; i < info->otherPathsCount; ++i) { - std::free(info->otherPaths[i]); + WPI_FreeString(&info->otherPaths[i]); } - std::free(info->otherPaths); } extern "C" { -CS_Source CS_CreateUsbCameraDev(const char* name, int dev, CS_Status* status) { - return cs::CreateUsbCameraDev(name, dev, status); +CS_Source CS_CreateUsbCameraDev(const struct WPI_String* name, int dev, + CS_Status* status) { + return cs::CreateUsbCameraDev(wpi::to_string_view(name), dev, status); } -CS_Source CS_CreateUsbCameraPath(const char* name, const char* path, +CS_Source CS_CreateUsbCameraPath(const struct WPI_String* name, + const struct WPI_String* path, CS_Status* status) { - return cs::CreateUsbCameraPath(name, path, status); + return cs::CreateUsbCameraPath(wpi::to_string_view(name), + wpi::to_string_view(path), status); } -void CS_SetUsbCameraPath(CS_Source source, const char* path, +void CS_SetUsbCameraPath(CS_Source source, const struct WPI_String* path, CS_Status* status) { - cs::SetUsbCameraPath(source, path, status); + cs::SetUsbCameraPath(source, wpi::to_string_view(path), status); } -char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status) { - return ConvertToC(cs::GetUsbCameraPath(source, status)); +void CS_GetUsbCameraPath(CS_Source source, WPI_String* path, + CS_Status* status) { + ConvertToC(path, cs::GetUsbCameraPath(source, status)); } -CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) { - auto info = cs::GetUsbCameraInfo(source, status); - if (*status != CS_OK) { - return nullptr; - } - CS_UsbCameraInfo* out = static_cast( - wpi::safe_malloc(sizeof(CS_UsbCameraInfo))); - ConvertToC(out, info); - return out; +void CS_GetUsbCameraInfo(CS_Source source, CS_UsbCameraInfo* info, + CS_Status* status) { + auto info_cpp = cs::GetUsbCameraInfo(source, status); + ConvertToC(info, info_cpp); } CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) { @@ -89,7 +88,6 @@ void CS_FreeUsbCameraInfo(CS_UsbCameraInfo* info) { return; } FreeUsbCameraInfo(info); - std::free(info); } } // extern "C" diff --git a/cscore/src/main/native/cpp/c_util.h b/cscore/src/main/native/cpp/c_util.h index 904d049ef6f..a81f4287168 100644 --- a/cscore/src/main/native/cpp/c_util.h +++ b/cscore/src/main/native/cpp/c_util.h @@ -5,19 +5,16 @@ #ifndef CSCORE_C_UTIL_H_ #define CSCORE_C_UTIL_H_ -#include #include #include -#include +#include namespace cs { -inline char* ConvertToC(std::string_view in) { - char* out = static_cast(wpi::safe_malloc(in.size() + 1)); - std::memmove(out, in.data(), in.size()); - out[in.size()] = '\0'; - return out; +inline void ConvertToC(struct WPI_String* output, std::string_view str) { + char* write = WPI_AllocateString(output, str.size()); + std::memcpy(write, str.data(), str.size()); } } // namespace cs diff --git a/cscore/src/main/native/cpp/cscore_c.cpp b/cscore/src/main/native/cpp/cscore_c.cpp index 4670dd4c8eb..521a1ffa501 100644 --- a/cscore/src/main/native/cpp/cscore_c.cpp +++ b/cscore/src/main/native/cpp/cscore_c.cpp @@ -19,12 +19,12 @@ static CS_Event ConvertToC(const cs::RawEvent& rawEvent) { event.kind = static_cast(static_cast(rawEvent.kind)); event.source = rawEvent.sourceHandle; event.sink = rawEvent.sinkHandle; - event.name = rawEvent.name.c_str(); + cs::ConvertToC(&event.name, rawEvent.name); event.mode = rawEvent.mode; event.property = rawEvent.propertyHandle; event.propertyKind = rawEvent.propertyKind; event.value = rawEvent.value; - event.valueStr = rawEvent.valueStr.c_str(); + cs::ConvertToC(&event.name, rawEvent.valueStr); event.listener = rawEvent.listener; return event; } @@ -53,13 +53,10 @@ CS_PropertyKind CS_GetPropertyKind(CS_Property property, CS_Status* status) { return cs::GetPropertyKind(property, status); } -char* CS_GetPropertyName(CS_Property property, CS_Status* status) { +void CS_GetPropertyName(CS_Property property, WPI_String* name, + CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetPropertyName(property, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(name, cs::GetPropertyName(property, buf, status)); } int CS_GetProperty(CS_Property property, CS_Status* status) { @@ -86,28 +83,24 @@ int CS_GetPropertyDefault(CS_Property property, CS_Status* status) { return cs::GetPropertyDefault(property, status); } -char* CS_GetStringProperty(CS_Property property, CS_Status* status) { +void CS_GetStringProperty(CS_Property property, WPI_String* value, + CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetStringProperty(property, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(value, cs::GetStringProperty(property, buf, status)); } -void CS_SetStringProperty(CS_Property property, const char* value, +void CS_SetStringProperty(CS_Property property, const struct WPI_String* value, CS_Status* status) { - return cs::SetStringProperty(property, value, status); + return cs::SetStringProperty(property, wpi::to_string_view(value), status); } -char** CS_GetEnumPropertyChoices(CS_Property property, int* count, - CS_Status* status) { +WPI_String* CS_GetEnumPropertyChoices(CS_Property property, int* count, + CS_Status* status) { auto choices = cs::GetEnumPropertyChoices(property, status); - char** out = - static_cast(wpi::safe_malloc(choices.size() * sizeof(char*))); + WPI_String* out = WPI_AllocateStringArray(choices.size()); *count = choices.size(); for (size_t i = 0; i < choices.size(); ++i) { - out[i] = cs::ConvertToC(choices[i]); + cs::ConvertToC(&out[i], choices[i]); } return out; } @@ -116,22 +109,15 @@ CS_SourceKind CS_GetSourceKind(CS_Source source, CS_Status* status) { return cs::GetSourceKind(source, status); } -char* CS_GetSourceName(CS_Source source, CS_Status* status) { +void CS_GetSourceName(CS_Source source, WPI_String* name, CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetSourceName(source, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(name, cs::GetSourceName(source, buf, status)); } -char* CS_GetSourceDescription(CS_Source source, CS_Status* status) { +void CS_GetSourceDescription(CS_Source source, WPI_String* description, + CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetSourceDescription(source, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(description, cs::GetSourceDescription(source, buf, status)); } uint64_t CS_GetSourceLastFrameTime(CS_Source source, CS_Status* status) { @@ -152,9 +138,10 @@ CS_Bool CS_IsSourceEnabled(CS_Source source, CS_Status* status) { return cs::IsSourceEnabled(source, status); } -CS_Property CS_GetSourceProperty(CS_Source source, const char* name, +CS_Property CS_GetSourceProperty(CS_Source source, + const struct WPI_String* name, CS_Status* status) { - return cs::GetSourceProperty(source, name, status); + return cs::GetSourceProperty(source, wpi::to_string_view(name), status); } CS_Property* CS_EnumerateSourceProperties(CS_Source source, int* count, @@ -209,13 +196,15 @@ CS_Bool CS_SetSourceFPS(CS_Source source, int fps, CS_Status* status) { return cs::SetSourceFPS(source, fps, status); } -CS_Bool CS_SetSourceConfigJson(CS_Source source, const char* config, +CS_Bool CS_SetSourceConfigJson(CS_Source source, + const struct WPI_String* config, CS_Status* status) { - return cs::SetSourceConfigJson(source, config, status); + return cs::SetSourceConfigJson(source, wpi::to_string_view(config), status); } -char* CS_GetSourceConfigJson(CS_Source source, CS_Status* status) { - return cs::ConvertToC(cs::GetSourceConfigJson(source, status)); +void CS_GetSourceConfigJson(CS_Source source, WPI_String* config, + CS_Status* status) { + cs::ConvertToC(config, cs::GetSourceConfigJson(source, status)); } CS_VideoMode* CS_EnumerateSourceVideoModes(CS_Source source, int* count, @@ -286,27 +275,20 @@ CS_SinkKind CS_GetSinkKind(CS_Sink sink, CS_Status* status) { return cs::GetSinkKind(sink, status); } -char* CS_GetSinkName(CS_Sink sink, CS_Status* status) { +void CS_GetSinkName(CS_Sink sink, WPI_String* name, CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetSinkName(sink, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(name, cs::GetSinkName(sink, buf, status)); } -char* CS_GetSinkDescription(CS_Sink sink, CS_Status* status) { +void CS_GetSinkDescription(CS_Sink sink, WPI_String* description, + CS_Status* status) { wpi::SmallString<128> buf; - auto str = cs::GetSinkDescription(sink, buf, status); - if (*status != 0) { - return nullptr; - } - return cs::ConvertToC(str); + cs::ConvertToC(description, cs::GetSinkDescription(sink, buf, status)); } -CS_Property CS_GetSinkProperty(CS_Sink sink, const char* name, +CS_Property CS_GetSinkProperty(CS_Sink sink, const struct WPI_String* name, CS_Status* status) { - return cs::GetSinkProperty(sink, name, status); + return cs::GetSinkProperty(sink, wpi::to_string_view(name), status); } CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count, @@ -320,13 +302,13 @@ CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count, return out; } -CS_Bool CS_SetSinkConfigJson(CS_Sink sink, const char* config, +CS_Bool CS_SetSinkConfigJson(CS_Sink sink, const struct WPI_String* config, CS_Status* status) { - return cs::SetSinkConfigJson(sink, config, status); + return cs::SetSinkConfigJson(sink, wpi::to_string_view(config), status); } -char* CS_GetSinkConfigJson(CS_Sink sink, CS_Status* status) { - return cs::ConvertToC(cs::GetSinkConfigJson(sink, status)); +void CS_GetSinkConfigJson(CS_Sink sink, WPI_String* config, CS_Status* status) { + cs::ConvertToC(config, cs::GetSinkConfigJson(sink, status)); } void CS_SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status) { @@ -337,9 +319,10 @@ CS_Source CS_GetSinkSource(CS_Sink sink, CS_Status* status) { return cs::GetSinkSource(sink, status); } -CS_Property CS_GetSinkSourceProperty(CS_Sink sink, const char* name, +CS_Property CS_GetSinkSourceProperty(CS_Sink sink, + const struct WPI_String* name, CS_Status* status) { - return cs::GetSinkSourceProperty(sink, name, status); + return cs::GetSinkSourceProperty(sink, wpi::to_string_view(name), status); } CS_Sink CS_CopySink(CS_Sink sink, CS_Status* status) { @@ -360,7 +343,7 @@ void CS_SetListenerOnExit(void (*onExit)(void* data), void* data) { CS_Listener CS_AddListener(void* data, void (*callback)(void* data, const CS_Event* event), - int eventMask, int immediateNotify, + int eventMask, CS_Bool immediateNotify, CS_Status* status) { return cs::AddListener( [=](const cs::RawEvent& rawEvent) { @@ -435,8 +418,15 @@ double CS_GetTelemetryAverageValue(CS_Handle handle, CS_TelemetryKind kind, return cs::GetTelemetryAverageValue(handle, kind, status); } -void CS_SetLogger(CS_LogFunc func, unsigned int min_level) { - cs::SetLogger(func, min_level); +void CS_SetLogger(CS_LogFunc func, void* data, unsigned int min_level) { + cs::SetLogger( + [=](unsigned int level, const char* file, unsigned int line, + const char* msg) { + auto fileStr = wpi::make_string(file); + auto msgStr = wpi::make_string(msg); + func(data, level, &fileStr, line, &msgStr); + }, + min_level); } void CS_SetDefaultLogger(unsigned int min_level) { @@ -493,20 +483,6 @@ void CS_ReleaseEnumeratedSinks(CS_Sink* sinks, int count) { std::free(sinks); } -void CS_FreeString(char* str) { - std::free(str); -} - -void CS_FreeEnumPropertyChoices(char** choices, int count) { - if (!choices) { - return; - } - for (int i = 0; i < count; ++i) { - std::free(choices[i]); - } - std::free(choices); -} - void CS_FreeEnumeratedProperties(CS_Property* properties, int count) { std::free(properties); } @@ -515,29 +491,18 @@ void CS_FreeEnumeratedVideoModes(CS_VideoMode* modes, int count) { std::free(modes); } -char* CS_GetHostname(void) { - return cs::ConvertToC(cs::GetHostname()); +void CS_GetHostname(struct WPI_String* hostname) { + cs::ConvertToC(hostname, cs::GetHostname()); } -char** CS_GetNetworkInterfaces(int* count) { +WPI_String* CS_GetNetworkInterfaces(int* count) { auto interfaces = cs::GetNetworkInterfaces(); - char** out = - static_cast(wpi::safe_malloc(interfaces.size() * sizeof(char*))); + WPI_String* out = WPI_AllocateStringArray(interfaces.size()); *count = interfaces.size(); for (size_t i = 0; i < interfaces.size(); ++i) { - out[i] = cs::ConvertToC(interfaces[i]); + cs::ConvertToC(&out[i], interfaces[i]); } return out; } -void CS_FreeNetworkInterfaces(char** interfaces, int count) { - if (!interfaces) { - return; - } - for (int i = 0; i < count; ++i) { - std::free(interfaces[i]); - } - std::free(interfaces); -} - } // extern "C" diff --git a/cscore/src/main/native/include/cscore_c.h b/cscore/src/main/native/include/cscore_c.h index 45a334269af..60e66bf209c 100644 --- a/cscore/src/main/native/include/cscore_c.h +++ b/cscore/src/main/native/include/cscore_c.h @@ -8,6 +8,7 @@ #include #include +#include #ifdef __cplusplus #include @@ -204,7 +205,7 @@ struct CS_Event { CS_Sink sink; // Source/sink/property name - const char* name; + struct WPI_String name; // Fields for CS_SOURCE_VIDEOMODE_CHANGED event CS_VideoMode mode; @@ -213,7 +214,7 @@ struct CS_Event { CS_Property property; enum CS_PropertyKind propertyKind; int value; - const char* valueStr; + struct WPI_String valueStr; // Listener that was triggered CS_Listener listener; @@ -224,10 +225,10 @@ struct CS_Event { */ typedef struct CS_UsbCameraInfo { int dev; - char* path; - char* name; + struct WPI_String path; + struct WPI_String name; int otherPathsCount; - char** otherPaths; + struct WPI_String* otherPaths; int vendorId; int productId; } CS_UsbCameraInfo; @@ -238,34 +239,40 @@ typedef struct CS_UsbCameraInfo { */ enum CS_PropertyKind CS_GetPropertyKind(CS_Property property, CS_Status* status); -char* CS_GetPropertyName(CS_Property property, CS_Status* status); +void CS_GetPropertyName(CS_Property property, struct WPI_String* name, + CS_Status* status); int CS_GetProperty(CS_Property property, CS_Status* status); void CS_SetProperty(CS_Property property, int value, CS_Status* status); int CS_GetPropertyMin(CS_Property property, CS_Status* status); int CS_GetPropertyMax(CS_Property property, CS_Status* status); int CS_GetPropertyStep(CS_Property property, CS_Status* status); int CS_GetPropertyDefault(CS_Property property, CS_Status* status); -char* CS_GetStringProperty(CS_Property property, CS_Status* status); -void CS_SetStringProperty(CS_Property property, const char* value, +void CS_GetStringProperty(CS_Property property, struct WPI_String* value, CS_Status* status); -char** CS_GetEnumPropertyChoices(CS_Property property, int* count, - CS_Status* status); +void CS_SetStringProperty(CS_Property property, const struct WPI_String* value, + CS_Status* status); +struct WPI_String* CS_GetEnumPropertyChoices(CS_Property property, int* count, + CS_Status* status); /** @} */ /** * @defgroup cscore_source_create_cfunc Source Creation Functions * @{ */ -CS_Source CS_CreateUsbCameraDev(const char* name, int dev, CS_Status* status); -CS_Source CS_CreateUsbCameraPath(const char* name, const char* path, +CS_Source CS_CreateUsbCameraDev(const struct WPI_String* name, int dev, + CS_Status* status); +CS_Source CS_CreateUsbCameraPath(const struct WPI_String* name, + const struct WPI_String* path, CS_Status* status); -CS_Source CS_CreateHttpCamera(const char* name, const char* url, +CS_Source CS_CreateHttpCamera(const struct WPI_String* name, + const struct WPI_String* url, enum CS_HttpCameraKind kind, CS_Status* status); -CS_Source CS_CreateHttpCameraMulti(const char* name, const char** urls, - int count, enum CS_HttpCameraKind kind, +CS_Source CS_CreateHttpCameraMulti(const struct WPI_String* name, + const struct WPI_String* urls, int count, + enum CS_HttpCameraKind kind, CS_Status* status); -CS_Source CS_CreateCvSource(const char* name, const CS_VideoMode* mode, - CS_Status* status); +CS_Source CS_CreateCvSource(const struct WPI_String* name, + const CS_VideoMode* mode, CS_Status* status); /** @} */ /** @@ -273,15 +280,18 @@ CS_Source CS_CreateCvSource(const char* name, const CS_VideoMode* mode, * @{ */ enum CS_SourceKind CS_GetSourceKind(CS_Source source, CS_Status* status); -char* CS_GetSourceName(CS_Source source, CS_Status* status); -char* CS_GetSourceDescription(CS_Source source, CS_Status* status); +void CS_GetSourceName(CS_Source source, struct WPI_String* name, + CS_Status* status); +void CS_GetSourceDescription(CS_Source source, struct WPI_String* description, + CS_Status* status); uint64_t CS_GetSourceLastFrameTime(CS_Source source, CS_Status* status); void CS_SetSourceConnectionStrategy(CS_Source source, enum CS_ConnectionStrategy strategy, CS_Status* status); CS_Bool CS_IsSourceConnected(CS_Source source, CS_Status* status); CS_Bool CS_IsSourceEnabled(CS_Source source, CS_Status* status); -CS_Property CS_GetSourceProperty(CS_Source source, const char* name, +CS_Property CS_GetSourceProperty(CS_Source source, + const struct WPI_String* name, CS_Status* status); CS_Property* CS_EnumerateSourceProperties(CS_Source source, int* count, CS_Status* status); @@ -299,9 +309,11 @@ CS_Bool CS_SetSourcePixelFormat(CS_Source source, CS_Bool CS_SetSourceResolution(CS_Source source, int width, int height, CS_Status* status); CS_Bool CS_SetSourceFPS(CS_Source source, int fps, CS_Status* status); -CS_Bool CS_SetSourceConfigJson(CS_Source source, const char* config, +CS_Bool CS_SetSourceConfigJson(CS_Source source, + const struct WPI_String* config, CS_Status* status); -char* CS_GetSourceConfigJson(CS_Source source, CS_Status* status); +void CS_GetSourceConfigJson(CS_Source source, struct WPI_String* config, + CS_Status* status); CS_VideoMode* CS_EnumerateSourceVideoModes(CS_Source source, int* count, CS_Status* status); CS_Sink* CS_EnumerateSourceSinks(CS_Source source, int* count, @@ -330,9 +342,12 @@ void CS_SetCameraExposureManual(CS_Source source, int value, CS_Status* status); * @defgroup cscore_usbcamera_cfunc UsbCamera Source Functions * @{ */ -void CS_SetUsbCameraPath(CS_Source source, const char* path, CS_Status* status); -char* CS_GetUsbCameraPath(CS_Source source, CS_Status* status); -CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status); +void CS_SetUsbCameraPath(CS_Source source, const struct WPI_String* path, + CS_Status* status); +void CS_GetUsbCameraPath(CS_Source source, struct WPI_String* path, + CS_Status* status); +void CS_GetUsbCameraInfo(CS_Source source, CS_UsbCameraInfo* info, + CS_Status* status); /** @} */ /** @@ -341,38 +356,43 @@ CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status); */ enum CS_HttpCameraKind CS_GetHttpCameraKind(CS_Source source, CS_Status* status); -void CS_SetHttpCameraUrls(CS_Source source, const char** urls, int count, - CS_Status* status); -char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status); +void CS_SetHttpCameraUrls(CS_Source source, const struct WPI_String* urls, + int count, CS_Status* status); +struct WPI_String* CS_GetHttpCameraUrls(CS_Source source, int* count, + CS_Status* status); /** @} */ /** * @defgroup cscore_frame_source_cfunc Frame Source Functions * @{ */ -void CS_NotifySourceError(CS_Source source, const char* msg, CS_Status* status); +void CS_NotifySourceError(CS_Source source, const struct WPI_String* msg, + CS_Status* status); void CS_SetSourceConnected(CS_Source source, CS_Bool connected, CS_Status* status); -void CS_SetSourceDescription(CS_Source source, const char* description, +void CS_SetSourceDescription(CS_Source source, + const struct WPI_String* description, CS_Status* status); -CS_Property CS_CreateSourceProperty(CS_Source source, const char* name, +CS_Property CS_CreateSourceProperty(CS_Source source, + const struct WPI_String* name, enum CS_PropertyKind kind, int minimum, int maximum, int step, int defaultValue, int value, CS_Status* status); void CS_SetSourceEnumPropertyChoices(CS_Source source, CS_Property property, - const char** choices, int count, - CS_Status* status); + const struct WPI_String* choices, + int count, CS_Status* status); /** @} */ /** * @defgroup cscore_sink_create_cfunc Sink Creation Functions * @{ */ -CS_Sink CS_CreateMjpegServer(const char* name, const char* listenAddress, - int port, CS_Status* status); -CS_Sink CS_CreateCvSink(const char* name, enum WPI_PixelFormat pixelFormat, - CS_Status* status); -CS_Sink CS_CreateCvSinkCallback(const char* name, +CS_Sink CS_CreateMjpegServer(const struct WPI_String* name, + const struct WPI_String* listenAddress, int port, + CS_Status* status); +CS_Sink CS_CreateCvSink(const struct WPI_String* name, + enum WPI_PixelFormat pixelFormat, CS_Status* status); +CS_Sink CS_CreateCvSinkCallback(const struct WPI_String* name, enum WPI_PixelFormat pixelFormat, void* data, void (*processFrame)(void* data, uint64_t time), CS_Status* status); @@ -383,18 +403,21 @@ CS_Sink CS_CreateCvSinkCallback(const char* name, * @{ */ enum CS_SinkKind CS_GetSinkKind(CS_Sink sink, CS_Status* status); -char* CS_GetSinkName(CS_Sink sink, CS_Status* status); -char* CS_GetSinkDescription(CS_Sink sink, CS_Status* status); -CS_Property CS_GetSinkProperty(CS_Sink sink, const char* name, +void CS_GetSinkName(CS_Sink sink, struct WPI_String* name, CS_Status* status); +void CS_GetSinkDescription(CS_Sink sink, struct WPI_String* description, + CS_Status* status); +CS_Property CS_GetSinkProperty(CS_Sink sink, const struct WPI_String* name, CS_Status* status); CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count, CS_Status* status); void CS_SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status); -CS_Property CS_GetSinkSourceProperty(CS_Sink sink, const char* name, +CS_Property CS_GetSinkSourceProperty(CS_Sink sink, + const struct WPI_String* name, CS_Status* status); -CS_Bool CS_SetSinkConfigJson(CS_Sink sink, const char* config, +CS_Bool CS_SetSinkConfigJson(CS_Sink sink, const struct WPI_String* config, CS_Status* status); -char* CS_GetSinkConfigJson(CS_Sink sink, CS_Status* status); +void CS_GetSinkConfigJson(CS_Sink sink, struct WPI_String* config, + CS_Status* status); CS_Source CS_GetSinkSource(CS_Sink sink, CS_Status* status); CS_Sink CS_CopySink(CS_Sink sink, CS_Status* status); void CS_ReleaseSink(CS_Sink sink, CS_Status* status); @@ -404,7 +427,9 @@ void CS_ReleaseSink(CS_Sink sink, CS_Status* status); * @defgroup cscore_mjpegserver_cfunc MjpegServer Sink Functions * @{ */ -char* CS_GetMjpegServerListenAddress(CS_Sink sink, CS_Status* status); +void CS_GetMjpegServerListenAddress(CS_Sink sink, + struct WPI_String* listenAddress, + CS_Status* status); int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status); /** @} */ @@ -412,9 +437,9 @@ int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status); * @defgroup cscore_frame_sink_cfunc Frame Sink Functions * @{ */ -void CS_SetSinkDescription(CS_Sink sink, const char* description, +void CS_SetSinkDescription(CS_Sink sink, const struct WPI_String* description, CS_Status* status); -char* CS_GetSinkError(CS_Sink sink, CS_Status* status); +void CS_GetSinkError(CS_Sink sink, struct WPI_String* error, CS_Status* status); void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status); /** @} */ @@ -459,9 +484,10 @@ double CS_GetTelemetryAverageValue(CS_Handle handle, enum CS_TelemetryKind kind, * @defgroup cscore_logging_cfunc Logging Functions * @{ */ -typedef void (*CS_LogFunc)(unsigned int level, const char* file, - unsigned int line, const char* msg); -void CS_SetLogger(CS_LogFunc func, unsigned int min_level); +typedef void (*CS_LogFunc)(void* data, unsigned int level, + const struct WPI_String* file, unsigned int line, + const struct WPI_String* msg); +void CS_SetLogger(CS_LogFunc func, void* data, unsigned int min_level); void CS_SetDefaultLogger(unsigned int min_level); /** @} */ @@ -486,18 +512,14 @@ void CS_ReleaseEnumeratedSources(CS_Source* sources, int count); CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status); void CS_ReleaseEnumeratedSinks(CS_Sink* sinks, int count); -void CS_FreeString(char* str); -void CS_FreeEnumPropertyChoices(char** choices, int count); void CS_FreeUsbCameraInfo(CS_UsbCameraInfo* info); -void CS_FreeHttpCameraUrls(char** urls, int count); void CS_FreeEnumeratedProperties(CS_Property* properties, int count); void CS_FreeEnumeratedVideoModes(CS_VideoMode* modes, int count); -char* CS_GetHostname(void); +void CS_GetHostname(struct WPI_String* hostName); -char** CS_GetNetworkInterfaces(int* count); -void CS_FreeNetworkInterfaces(char** interfaces, int count); +struct WPI_String* CS_GetNetworkInterfaces(int* count); /** @} */ /** @} */ diff --git a/cscore/src/main/native/include/cscore_raw.h b/cscore/src/main/native/include/cscore_raw.h index 9367c26c6b5..e6106835633 100644 --- a/cscore/src/main/native/include/cscore_raw.h +++ b/cscore/src/main/native/include/cscore_raw.h @@ -28,17 +28,17 @@ uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct WPI_RawFrame* rawImage, uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct WPI_RawFrame* rawImage, double timeout, CS_Status* status); -CS_Sink CS_CreateRawSink(const char* name, CS_Bool isCv, CS_Status* status); +CS_Sink CS_CreateRawSink(const struct WPI_String* name, CS_Bool isCv, + CS_Status* status); -CS_Sink CS_CreateRawSinkCallback(const char* name, CS_Bool isCv, void* data, - void (*processFrame)(void* data, - uint64_t time), - CS_Status* status); +CS_Sink CS_CreateRawSinkCallback( + const struct WPI_String* name, CS_Bool isCv, void* data, + void (*processFrame)(void* data, uint64_t time), CS_Status* status); void CS_PutRawSourceFrame(CS_Source source, const struct WPI_RawFrame* image, CS_Status* status); -CS_Source CS_CreateRawSource(const char* name, CS_Bool isCv, +CS_Source CS_CreateRawSource(const struct WPI_String* name, CS_Bool isCv, const CS_VideoMode* mode, CS_Status* status); /** @} */ diff --git a/hal/src/main/native/athena/FRCDriverStation.cpp b/hal/src/main/native/athena/FRCDriverStation.cpp index b0aeb05acc2..1e2565b0096 100644 --- a/hal/src/main/native/athena/FRCDriverStation.cpp +++ b/hal/src/main/native/athena/FRCDriverStation.cpp @@ -424,22 +424,15 @@ int32_t HAL_GetJoystickType(int32_t joystickNum) { } } -char* HAL_GetJoystickName(int32_t joystickNum) { +void HAL_GetJoystickName(struct WPI_String* name, int32_t joystickNum) { HAL_JoystickDescriptor joystickDesc; + const char* cName = joystickDesc.name; if (HAL_GetJoystickDescriptor(joystickNum, &joystickDesc) < 0) { - char* name = static_cast(std::malloc(1)); - name[0] = '\0'; - return name; - } else { - const size_t len = std::strlen(joystickDesc.name) + 1; - char* name = static_cast(std::malloc(len)); - std::memcpy(name, joystickDesc.name, len); - return name; + cName = ""; } -} - -void HAL_FreeJoystickName(char* name) { - std::free(name); + auto len = std::strlen(cName); + auto write = WPI_AllocateString(name, len); + std::memcpy(write, cName, len); } int32_t HAL_GetJoystickAxisType(int32_t joystickNum, int32_t axis) { diff --git a/hal/src/main/native/athena/HAL.cpp b/hal/src/main/native/athena/HAL.cpp index 7be0e478a76..3ada7d8170b 100644 --- a/hal/src/main/native/athena/HAL.cpp +++ b/hal/src/main/native/athena/HAL.cpp @@ -286,18 +286,14 @@ int64_t HAL_GetFPGARevision(int32_t* status) { return global->readRevision(status); } -size_t HAL_GetSerialNumber(char* buffer, size_t size) { +void HAL_GetSerialNumber(struct WPI_String* serialNumber) { const char* serialNum = std::getenv("serialnum"); - if (serialNum) { - std::strncpy(buffer, serialNum, size); - buffer[size - 1] = '\0'; - return std::strlen(buffer); - } else { - if (size > 0) { - buffer[0] = '\0'; - } - return 0; + if (!serialNum) { + serialNum = ""; } + size_t len = std::strlen(serialNum); + auto write = WPI_AllocateString(serialNumber, len); + std::memcpy(write, serialNum, len); } void InitializeRoboRioComments(void) { @@ -341,21 +337,12 @@ void InitializeRoboRioComments(void) { } } -size_t HAL_GetComments(char* buffer, size_t size) { +void HAL_GetComments(struct WPI_String* comments) { if (!roboRioCommentsStringInitialized) { InitializeRoboRioComments(); } - size_t toCopy = size; - if (size > roboRioCommentsStringSize) { - toCopy = roboRioCommentsStringSize; - } - std::memcpy(buffer, roboRioCommentsString, toCopy); - if (toCopy < size) { - buffer[toCopy] = '\0'; - } else { - buffer[toCopy - 1] = '\0'; - } - return toCopy; + auto write = WPI_AllocateString(comments, roboRioCommentsStringSize); + std::memcpy(write, roboRioCommentsString, roboRioCommentsStringSize); } void InitializeTeamNumber(void) { diff --git a/hal/src/main/native/athena/mockdata/DriverStationData.cpp b/hal/src/main/native/athena/mockdata/DriverStationData.cpp index 76a8e8bf1e8..90fa34fc566 100644 --- a/hal/src/main/native/athena/mockdata/DriverStationData.cpp +++ b/hal/src/main/native/athena/mockdata/DriverStationData.cpp @@ -103,13 +103,13 @@ void HALSIM_SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox) {} void HALSIM_SetJoystickType(int32_t stick, int32_t type) {} -void HALSIM_SetJoystickName(int32_t stick, const char* name, size_t size) {} +void HALSIM_SetJoystickName(int32_t stick, const struct WPI_String* name) {} void HALSIM_SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type) {} -void HALSIM_SetGameSpecificMessage(const char* message, size_t size) {} +void HALSIM_SetGameSpecificMessage(const struct WPI_String* message) {} -void HALSIM_SetEventName(const char* name, size_t size) {} +void HALSIM_SetEventName(const struct WPI_String* name) {} void HALSIM_SetMatchType(HAL_MatchType type) {} diff --git a/hal/src/main/native/athena/mockdata/RoboRioData.cpp b/hal/src/main/native/athena/mockdata/RoboRioData.cpp index b57b706b8ab..b1ba26026da 100644 --- a/hal/src/main/native/athena/mockdata/RoboRioData.cpp +++ b/hal/src/main/native/athena/mockdata/RoboRioData.cpp @@ -37,26 +37,20 @@ int32_t HALSIM_RegisterRoboRioSerialNumberCallback( return 0; } void HALSIM_CancelRoboRioSerialNumberCallback(int32_t uid) {} -size_t HALSIM_GetRoboRioSerialNumber(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } - return 0; +void HALSIM_GetRoboRioSerialNumber(struct WPI_String* serialNumber) { + WPI_AllocateString(serialNumber, 0); } -void HALSIM_SetRoboRioSerialNumber(const char* buffer, size_t size) {} +void HALSIM_SetRoboRioSerialNumber(const struct WPI_String* serialNumber) {} int32_t HALSIM_RegisterRoboRioCommentsCallback( HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify) { return 0; } void HALSIM_CancelRoboRioCommentsCallback(int32_t uid) {} -size_t HALSIM_GetRoboRioComments(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } - return 0; +void HALSIM_GetRoboRioComments(struct WPI_String* comments) { + WPI_AllocateString(comments, 0); } -void HALSIM_SetRoboRioComments(const char* buffer, size_t size) {} +void HALSIM_SetRoboRioComments(const struct WPI_String* comments) {} void HALSIM_RegisterRoboRioAllCallbacks(HAL_NotifyCallback callback, void* param, HAL_Bool initialNotify) {} diff --git a/hal/src/main/native/cpp/jni/DriverStationJNI.cpp b/hal/src/main/native/cpp/jni/DriverStationJNI.cpp index 6b17cc01462..87c8b145058 100644 --- a/hal/src/main/native/cpp/jni/DriverStationJNI.cpp +++ b/hal/src/main/native/cpp/jni/DriverStationJNI.cpp @@ -336,9 +336,10 @@ JNIEXPORT jstring JNICALL Java_edu_wpi_first_hal_DriverStationJNI_getJoystickName (JNIEnv* env, jclass, jbyte port) { - char* joystickName = HAL_GetJoystickName(port); - jstring str = MakeJString(env, joystickName); - HAL_FreeJoystickName(joystickName); + WPI_String joystickName; + HAL_GetJoystickName(&joystickName, port); + jstring str = MakeJString(env, wpi::to_string_view(&joystickName)); + WPI_FreeString(&joystickName); return str; } diff --git a/hal/src/main/native/cpp/jni/HALUtil.cpp b/hal/src/main/native/cpp/jni/HALUtil.cpp index 1915108b34c..31b40efc57b 100644 --- a/hal/src/main/native/cpp/jni/HALUtil.cpp +++ b/hal/src/main/native/cpp/jni/HALUtil.cpp @@ -490,9 +490,11 @@ JNIEXPORT jstring JNICALL Java_edu_wpi_first_hal_HALUtil_getSerialNumber (JNIEnv* env, jclass) { - char serialNum[9]; - size_t len = HAL_GetSerialNumber(serialNum, sizeof(serialNum)); - return MakeJString(env, std::string_view(serialNum, len)); + WPI_String serialNum; + HAL_GetSerialNumber(&serialNum); + jstring ret = MakeJString(env, wpi::to_string_view(&serialNum)); + WPI_FreeString(&serialNum); + return ret; } /* @@ -504,9 +506,11 @@ JNIEXPORT jstring JNICALL Java_edu_wpi_first_hal_HALUtil_getComments (JNIEnv* env, jclass) { - char comments[65]; - size_t len = HAL_GetComments(comments, sizeof(comments)); - return MakeJString(env, std::string_view(comments, len)); + WPI_String comments; + HAL_GetComments(&comments); + jstring ret = MakeJString(env, wpi::to_string_view(&comments)); + WPI_FreeString(&comments); + return ret; } /* diff --git a/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp index 8b1ba4f68f5..63af783d41c 100644 --- a/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp +++ b/hal/src/main/native/cpp/jni/simulation/DriverStationDataJNI.cpp @@ -733,7 +733,8 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickName (JNIEnv* env, jclass, jint stick, jstring name) { JStringRef nameJString{env, name}; - HALSIM_SetJoystickName(stick, nameJString.c_str(), nameJString.size()); + auto str = wpi::make_string(nameJString); + HALSIM_SetJoystickName(stick, &str); } /* @@ -758,7 +759,8 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setGameSpecificMessage (JNIEnv* env, jclass, jstring message) { JStringRef messageJString{env, message}; - HALSIM_SetGameSpecificMessage(messageJString.c_str(), messageJString.size()); + auto str = wpi::make_string(messageJString); + HALSIM_SetGameSpecificMessage(&str); } /* @@ -771,7 +773,8 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setEventName (JNIEnv* env, jclass, jstring name) { JStringRef nameJString{env, name}; - HALSIM_SetEventName(nameJString.c_str(), nameJString.size()); + auto str = wpi::make_string(nameJString); + HALSIM_SetEventName(&str); } /* diff --git a/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp index c9a2acaa673..3c9d4422d4d 100644 --- a/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp +++ b/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp @@ -937,9 +937,11 @@ JNIEXPORT jstring JNICALL Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_getSerialNumber (JNIEnv* env, jclass) { - char serialNum[9]; - size_t len = HALSIM_GetRoboRioSerialNumber(serialNum, sizeof(serialNum)); - return MakeJString(env, std::string_view(serialNum, len)); + WPI_String str; + HALSIM_GetRoboRioSerialNumber(&str); + auto jstr = MakeJString(env, wpi::to_string_view(&str)); + WPI_FreeString(&str); + return jstr; } /* @@ -952,8 +954,8 @@ Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_setSerialNumber (JNIEnv* env, jclass, jstring serialNumber) { JStringRef serialNumberJString{env, serialNumber}; - HALSIM_SetRoboRioSerialNumber(serialNumberJString.c_str(), - serialNumberJString.size()); + auto str = wpi::make_string(serialNumberJString); + HALSIM_SetRoboRioSerialNumber(&str); } /* @@ -965,9 +967,11 @@ JNIEXPORT jstring JNICALL Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_getComments (JNIEnv* env, jclass) { - char comments[65]; - size_t len = HALSIM_GetRoboRioComments(comments, sizeof(comments)); - return MakeJString(env, std::string_view(comments, len)); + WPI_String str; + HALSIM_GetRoboRioComments(&str); + auto jstr = MakeJString(env, wpi::to_string_view(&str)); + WPI_FreeString(&str); + return jstr; } /* @@ -980,7 +984,8 @@ Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_setComments (JNIEnv* env, jclass, jstring comments) { JStringRef commentsJString{env, comments}; - HALSIM_SetRoboRioComments(commentsJString.c_str(), commentsJString.size()); + auto str = wpi::make_string(commentsJString); + HALSIM_SetRoboRioComments(&str); } /* diff --git a/hal/src/main/native/include/hal/DriverStation.h b/hal/src/main/native/include/hal/DriverStation.h index e0790742b02..8c5fea0c23f 100644 --- a/hal/src/main/native/include/hal/DriverStation.h +++ b/hal/src/main/native/include/hal/DriverStation.h @@ -9,6 +9,7 @@ #include //NOLINT #include +#include #include "hal/DriverStationTypes.h" #include "hal/Types.h" @@ -142,21 +143,12 @@ int32_t HAL_GetJoystickType(int32_t joystickNum); /** * Gets the name of a joystick. * - * The returned array must be freed with HAL_FreeJoystickName. - * - * Will be null terminated. + * The returned string must be freed with WPI_FreeString * + * @param name the joystick name string * @param joystickNum the joystick number - * @return the joystick name - */ -char* HAL_GetJoystickName(int32_t joystickNum); - -/** - * Frees a joystick name received with HAL_GetJoystickName - * - * @param name the name storage */ -void HAL_FreeJoystickName(char* name); +void HAL_GetJoystickName(struct WPI_String* name, int32_t joystickNum); /** * Gets the type of a specific joystick axis. diff --git a/hal/src/main/native/include/hal/HALBase.h b/hal/src/main/native/include/hal/HALBase.h index 3e9ddc67d1c..e59b26cbae1 100644 --- a/hal/src/main/native/include/hal/HALBase.h +++ b/hal/src/main/native/include/hal/HALBase.h @@ -14,6 +14,8 @@ #endif +#include + #include "hal/Types.h" /** @@ -79,20 +81,16 @@ int64_t HAL_GetFPGARevision(int32_t* status); /** * Returns the roboRIO serial number. * - * @param[out] buffer The roboRIO serial number. - * @param size The maximum characters to copy into buffer. - * @return Number of characters copied into buffer. + * @param[out] serialNumber The roboRIO serial number. Free with WPI_FreeString */ -size_t HAL_GetSerialNumber(char* buffer, size_t size); +void HAL_GetSerialNumber(struct WPI_String* serialNumber); /** * Returns the comments from the roboRIO web interface. * - * @param[out] buffer The comments string. - * @param size The maximum characters to copy into buffer. - * @return Number of characters copied into buffer. + * @param[out] comments The comments string. Free with WPI_FreeString */ -size_t HAL_GetComments(char* buffer, size_t size); +void HAL_GetComments(struct WPI_String* comments); /** * Returns the team number configured for the robot controller. diff --git a/hal/src/main/native/include/hal/simulation/DriverStationData.h b/hal/src/main/native/include/hal/simulation/DriverStationData.h index b10cf032622..b00fef8b515 100644 --- a/hal/src/main/native/include/hal/simulation/DriverStationData.h +++ b/hal/src/main/native/include/hal/simulation/DriverStationData.h @@ -6,6 +6,8 @@ #include +#include + #include "hal/DriverStationTypes.h" #include "hal/Types.h" #include "hal/simulation/NotifyListener.h" @@ -147,11 +149,11 @@ void HALSIM_GetJoystickCounts(int32_t stick, int32_t* axisCount, void HALSIM_SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox); void HALSIM_SetJoystickType(int32_t stick, int32_t type); -void HALSIM_SetJoystickName(int32_t stick, const char* name, size_t size); +void HALSIM_SetJoystickName(int32_t stick, const struct WPI_String* name); void HALSIM_SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type); -void HALSIM_SetGameSpecificMessage(const char* message, size_t size); -void HALSIM_SetEventName(const char* name, size_t size); +void HALSIM_SetGameSpecificMessage(const struct WPI_String* message); +void HALSIM_SetEventName(const struct WPI_String* name); void HALSIM_SetMatchType(HAL_MatchType type); void HALSIM_SetMatchNumber(int32_t matchNumber); void HALSIM_SetReplayNumber(int32_t replayNumber); diff --git a/hal/src/main/native/include/hal/simulation/RoboRioData.h b/hal/src/main/native/include/hal/simulation/RoboRioData.h index 83d68eadebe..0c87b07e5cb 100644 --- a/hal/src/main/native/include/hal/simulation/RoboRioData.h +++ b/hal/src/main/native/include/hal/simulation/RoboRioData.h @@ -6,6 +6,8 @@ #include +#include + #include "hal/LEDs.h" #include "hal/Types.h" #include "hal/simulation/NotifyListener.h" @@ -137,14 +139,14 @@ void HALSIM_SetRoboRioTeamNumber(int32_t teamNumber); int32_t HALSIM_RegisterRoboRioSerialNumberCallback( HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify); void HALSIM_CancelRoboRioSerialNumberCallback(int32_t uid); -size_t HALSIM_GetRoboRioSerialNumber(char* buffer, size_t size); -void HALSIM_SetRoboRioSerialNumber(const char* serialNumber, size_t size); +void HALSIM_GetRoboRioSerialNumber(struct WPI_String* serialNumber); +void HALSIM_SetRoboRioSerialNumber(const struct WPI_String* serialNumber); int32_t HALSIM_RegisterRoboRioCommentsCallback( HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify); void HALSIM_CancelRoboRioCommentsCallback(int32_t uid); -size_t HALSIM_GetRoboRioComments(char* buffer, size_t size); -void HALSIM_SetRoboRioComments(const char* comments, size_t size); +void HALSIM_GetRoboRioComments(struct WPI_String* comments); +void HALSIM_SetRoboRioComments(const struct WPI_String* comments); int32_t HALSIM_RegisterRoboRioCPUTempCallback(HAL_NotifyCallback callback, void* param, diff --git a/hal/src/main/native/sim/DriverStation.cpp b/hal/src/main/native/sim/DriverStation.cpp index 2ad13de861b..f50deaceb51 100644 --- a/hal/src/main/native/sim/DriverStation.cpp +++ b/hal/src/main/native/sim/DriverStation.cpp @@ -272,17 +272,12 @@ int32_t HAL_GetJoystickType(int32_t joystickNum) { return desc.type; } -char* HAL_GetJoystickName(int32_t joystickNum) { +void HAL_GetJoystickName(struct WPI_String* name, int32_t joystickNum) { HAL_JoystickDescriptor desc; SimDriverStationData->GetJoystickDescriptor(joystickNum, &desc); size_t len = std::strlen(desc.name); - char* name = static_cast(std::malloc(len + 1)); - std::memcpy(name, desc.name, len + 1); - return name; -} - -void HAL_FreeJoystickName(char* name) { - std::free(name); + auto write = WPI_AllocateString(name, len); + std::memcpy(write, desc.name, len); } int32_t HAL_GetJoystickAxisType(int32_t joystickNum, int32_t axis) { diff --git a/hal/src/main/native/sim/HAL.cpp b/hal/src/main/native/sim/HAL.cpp index c7b632c1b61..000ad8f80d1 100644 --- a/hal/src/main/native/sim/HAL.cpp +++ b/hal/src/main/native/sim/HAL.cpp @@ -5,6 +5,7 @@ #include "hal/HAL.h" #include +#include #include #include @@ -280,12 +281,12 @@ int64_t HAL_GetFPGARevision(int32_t* status) { return 0; // TODO: Find a better number to return; } -size_t HAL_GetSerialNumber(char* buffer, size_t size) { - return HALSIM_GetRoboRioSerialNumber(buffer, size); +void HAL_GetSerialNumber(struct WPI_String* serialNumber) { + HALSIM_GetRoboRioSerialNumber(serialNumber); } -size_t HAL_GetComments(char* buffer, size_t size) { - return HALSIM_GetRoboRioComments(buffer, size); +void HAL_GetComments(struct WPI_String* comments) { + HALSIM_GetRoboRioComments(comments); } int32_t HAL_GetTeamNumber(void) { diff --git a/hal/src/main/native/sim/mockdata/DriverStationData.cpp b/hal/src/main/native/sim/mockdata/DriverStationData.cpp index d124b213080..d7b8a087fa4 100644 --- a/hal/src/main/native/sim/mockdata/DriverStationData.cpp +++ b/hal/src/main/native/sim/mockdata/DriverStationData.cpp @@ -339,17 +339,14 @@ void DriverStationData::SetJoystickType(int32_t stick, int32_t type) { m_joystickDescriptorCallbacks(stick, &m_joystickData[stick].descriptor); } -void DriverStationData::SetJoystickName(int32_t stick, const char* name, - size_t size) { +void DriverStationData::SetJoystickName(int32_t stick, std::string_view name) { if (stick < 0 || stick >= kNumJoysticks) { return; } std::scoped_lock lock(m_joystickDataMutex); - if (size > sizeof(m_joystickData[stick].descriptor.name) - 1) { - size = sizeof(m_joystickData[stick].descriptor.name) - 1; - } - std::strncpy(m_joystickData[stick].descriptor.name, name, size); - m_joystickData[stick].descriptor.name[size] = '\0'; + auto copied = name.copy(m_joystickData[stick].descriptor.name, + sizeof(m_joystickData[stick].descriptor.name) - 1); + m_joystickData[stick].descriptor.name[copied] = '\0'; m_joystickDescriptorCallbacks(stick, &m_joystickData[stick].descriptor); } @@ -366,27 +363,20 @@ void DriverStationData::SetJoystickAxisType(int32_t stick, int32_t axis, m_joystickDescriptorCallbacks(stick, &m_joystickData[stick].descriptor); } -void DriverStationData::SetGameSpecificMessage(const char* message, - size_t size) { +void DriverStationData::SetGameSpecificMessage(std::string_view message) { std::scoped_lock lock(m_matchInfoMutex); - if (size > sizeof(m_matchInfo.gameSpecificMessage) - 1) { - size = sizeof(m_matchInfo.gameSpecificMessage) - 1; - } - std::strncpy(reinterpret_cast(m_matchInfo.gameSpecificMessage), - message, size); - m_matchInfo.gameSpecificMessage[size] = '\0'; - m_matchInfo.gameSpecificMessageSize = - std::strlen(reinterpret_cast(m_matchInfo.gameSpecificMessage)); + auto copied = + message.copy(reinterpret_cast(m_matchInfo.gameSpecificMessage), + sizeof(m_matchInfo.gameSpecificMessage)); + m_matchInfo.gameSpecificMessageSize = copied; m_matchInfoCallbacks(&m_matchInfo); } -void DriverStationData::SetEventName(const char* name, size_t size) { +void DriverStationData::SetEventName(std::string_view name) { std::scoped_lock lock(m_matchInfoMutex); - if (size > sizeof(m_matchInfo.eventName) - 1) { - size = sizeof(m_matchInfo.eventName) - 1; - } - std::strncpy(m_matchInfo.eventName, name, size); - m_matchInfo.eventName[size] = '\0'; + auto copied = + name.copy(m_matchInfo.eventName, sizeof(m_matchInfo.eventName) - 1); + m_matchInfo.eventName[copied] = '\0'; m_matchInfoCallbacks(&m_matchInfo); } @@ -551,20 +541,20 @@ void HALSIM_SetJoystickType(int32_t stick, int32_t type) { SimDriverStationData->SetJoystickType(stick, type); } -void HALSIM_SetJoystickName(int32_t stick, const char* name, size_t size) { - SimDriverStationData->SetJoystickName(stick, name, size); +void HALSIM_SetJoystickName(int32_t stick, const WPI_String* name) { + SimDriverStationData->SetJoystickName(stick, wpi::to_string_view(name)); } void HALSIM_SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type) { SimDriverStationData->SetJoystickAxisType(stick, axis, type); } -void HALSIM_SetGameSpecificMessage(const char* message, size_t size) { - SimDriverStationData->SetGameSpecificMessage(message, size); +void HALSIM_SetGameSpecificMessage(const WPI_String* message) { + SimDriverStationData->SetGameSpecificMessage(wpi::to_string_view(message)); } -void HALSIM_SetEventName(const char* name, size_t size) { - SimDriverStationData->SetEventName(name, size); +void HALSIM_SetEventName(const WPI_String* name) { + SimDriverStationData->SetEventName(wpi::to_string_view(name)); } void HALSIM_SetMatchType(HAL_MatchType type) { diff --git a/hal/src/main/native/sim/mockdata/DriverStationDataInternal.h b/hal/src/main/native/sim/mockdata/DriverStationDataInternal.h index 008329fde86..01de9cbdb18 100644 --- a/hal/src/main/native/sim/mockdata/DriverStationDataInternal.h +++ b/hal/src/main/native/sim/mockdata/DriverStationDataInternal.h @@ -107,11 +107,11 @@ class DriverStationData { void SetJoystickIsXbox(int32_t stick, HAL_Bool isXbox); void SetJoystickType(int32_t stick, int32_t type); - void SetJoystickName(int32_t stick, const char* name, size_t size); + void SetJoystickName(int32_t stick, std::string_view message); void SetJoystickAxisType(int32_t stick, int32_t axis, int32_t type); - void SetGameSpecificMessage(const char* message, size_t size); - void SetEventName(const char* name, size_t size); + void SetGameSpecificMessage(std::string_view message); + void SetEventName(std::string_view name); void SetMatchType(HAL_MatchType type); void SetMatchNumber(int32_t matchNumber); void SetReplayNumber(int32_t replayNumber); diff --git a/hal/src/main/native/sim/mockdata/RoboRioData.cpp b/hal/src/main/native/sim/mockdata/RoboRioData.cpp index 8ccc019edb7..94d61f8972b 100644 --- a/hal/src/main/native/sim/mockdata/RoboRioData.cpp +++ b/hal/src/main/native/sim/mockdata/RoboRioData.cpp @@ -53,25 +53,20 @@ void RoboRioData::CancelSerialNumberCallback(int32_t uid) { m_serialNumberCallbacks.Cancel(uid); } -size_t RoboRioData::GetSerialNumber(char* buffer, size_t size) { +void RoboRioData::GetSerialNumber(struct WPI_String* serialNumber) { std::scoped_lock lock(m_serialNumberMutex); - size_t copied = m_serialNumber.copy(buffer, size); - // Null terminate - if (copied == size) { - copied -= 1; - } - buffer[copied] = '\0'; - return copied; + auto write = WPI_AllocateString(serialNumber, m_serialNumber.size()); + m_serialNumber.copy(write, m_serialNumber.size()); } -void RoboRioData::SetSerialNumber(const char* serialNumber, size_t size) { +void RoboRioData::SetSerialNumber(std::string_view serialNumber) { // Limit serial number to 8 characters internally- serialnum environment // variable is always 8 characters - if (size > 8) { - size = 8; + if (serialNumber.size() > 8) { + serialNumber = serialNumber.substr(0, 8); } std::scoped_lock lock(m_serialNumberMutex); - m_serialNumber = std::string(serialNumber, size); + m_serialNumber = std::string(serialNumber); m_serialNumberCallbacks(m_serialNumber.c_str(), m_serialNumber.size()); } @@ -90,22 +85,18 @@ void RoboRioData::CancelCommentsCallback(int32_t uid) { m_commentsCallbacks.Cancel(uid); } -size_t RoboRioData::GetComments(char* buffer, size_t size) { +void RoboRioData::GetComments(struct WPI_String* comments) { std::scoped_lock lock(m_commentsMutex); - size_t copied = m_comments.copy(buffer, size); - // Null terminate if there is room - if (copied < size) { - buffer[copied] = '\0'; - } - return copied; + auto write = WPI_AllocateString(comments, m_comments.size()); + m_comments.copy(write, m_comments.size()); } -void RoboRioData::SetComments(const char* comments, size_t size) { - if (size > 64) { - size = 64; +void RoboRioData::SetComments(std::string_view comments) { + if (comments.size() > 64) { + comments = comments.substr(0, 64); } std::scoped_lock lock(m_commentsMutex); - m_comments = std::string(comments, size); + m_comments = std::string(comments); m_commentsCallbacks(m_comments.c_str(), m_comments.size()); } @@ -146,11 +137,11 @@ int32_t HALSIM_RegisterRoboRioSerialNumberCallback( void HALSIM_CancelRoboRioSerialNumberCallback(int32_t uid) { return SimRoboRioData->CancelSerialNumberCallback(uid); } -size_t HALSIM_GetRoboRioSerialNumber(char* buffer, size_t size) { - return SimRoboRioData->GetSerialNumber(buffer, size); +void HALSIM_GetRoboRioSerialNumber(struct WPI_String* serialNumber) { + SimRoboRioData->GetSerialNumber(serialNumber); } -void HALSIM_SetRoboRioSerialNumber(const char* serialNumber, size_t size) { - SimRoboRioData->SetSerialNumber(serialNumber, size); +void HALSIM_SetRoboRioSerialNumber(const struct WPI_String* serialNumber) { + SimRoboRioData->SetSerialNumber(wpi::to_string_view(serialNumber)); } int32_t HALSIM_RegisterRoboRioCommentsCallback( @@ -161,11 +152,11 @@ int32_t HALSIM_RegisterRoboRioCommentsCallback( void HALSIM_CancelRoboRioCommentsCallback(int32_t uid) { SimRoboRioData->CancelCommentsCallback(uid); } -size_t HALSIM_GetRoboRioComments(char* buffer, size_t size) { - return SimRoboRioData->GetComments(buffer, size); +void HALSIM_GetRoboRioComments(struct WPI_String* comments) { + SimRoboRioData->GetComments(comments); } -void HALSIM_SetRoboRioComments(const char* comments, size_t size) { - SimRoboRioData->SetComments(comments, size); +void HALSIM_SetRoboRioComments(const struct WPI_String* comments) { + SimRoboRioData->SetComments(wpi::to_string_view(comments)); } void HALSIM_RegisterRoboRioAllCallbacks(HAL_NotifyCallback callback, diff --git a/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h b/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h index 413c38eb2d3..6ef523e1829 100644 --- a/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h +++ b/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h @@ -72,14 +72,14 @@ class RoboRioData { int32_t RegisterSerialNumberCallback(HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify); void CancelSerialNumberCallback(int32_t uid); - size_t GetSerialNumber(char* buffer, size_t size); - void SetSerialNumber(const char* serialNumber, size_t size); + void GetSerialNumber(struct WPI_String* serialNumber); + void SetSerialNumber(std::string_view serialNumber); int32_t RegisterCommentsCallback(HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify); void CancelCommentsCallback(int32_t uid); - size_t GetComments(char* buffer, size_t size); - void SetComments(const char* comments, size_t size); + void GetComments(struct WPI_String* comments); + void SetComments(std::string_view comments); virtual void ResetData(); diff --git a/ntcore/src/generate/main/native/cpp/ntcore_c_types.cpp.jinja b/ntcore/src/generate/main/native/cpp/ntcore_c_types.cpp.jinja index a22563464c9..ccfe1833ac2 100644 --- a/ntcore/src/generate/main/native/cpp/ntcore_c_types.cpp.jinja +++ b/ntcore/src/generate/main/native/cpp/ntcore_c_types.cpp.jinja @@ -16,11 +16,11 @@ static inline std::span ConvertFromC(const T* arr, size_t size) { return {arr, size}; } -static inline std::string_view ConvertFromC(const char* arr, size_t size) { - return {arr, size}; +static inline std::string_view ConvertFromC(const struct WPI_String* str) { + return wpi::to_string_view(str); } -static std::vector ConvertFromC(const NT_String* arr, size_t size) { +static std::vector ConvertFromC(const struct WPI_String* arr, size_t size) { std::vector v; v.reserve(size); for (size_t i = 0; i < size; ++i) { @@ -35,6 +35,8 @@ static void ConvertToC(const nt::Timestamped{{ t.TypeName }}& in, NT_Timestamped out->serverTime = in.serverTime; {%- if t.c.IsArray %} out->value = ConvertToC<{{ t.c.ValueType[:-1] }}>(in.value, &out->len); +{% elif t.c.ValueInline %} + ConvertToC(in.value, &out->value); {% else %} out->value = in.value; {% endif -%} @@ -46,6 +48,8 @@ extern "C" { NT_Bool NT_Set{{ t.TypeName }}(NT_Handle pubentry, int64_t time, {{ t.c.ParamType }} value{% if t.c.IsArray %}, size_t len{% endif %}) { {%- if t.c.IsArray %} return nt::Set{{ t.TypeName }}(pubentry, ConvertFromC(value, len), time); +{%- elif t.c.ValueInline %} + return nt::Set{{ t.TypeName }}(pubentry, ConvertFromC(value), time); {%- else %} return nt::Set{{ t.TypeName }}(pubentry, value, time); {%- endif %} @@ -54,11 +58,21 @@ NT_Bool NT_Set{{ t.TypeName }}(NT_Handle pubentry, int64_t time, {{ t.c.ParamTyp NT_Bool NT_SetDefault{{ t.TypeName }}(NT_Handle pubentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen{% endif %}) { {%- if t.c.IsArray %} return nt::SetDefault{{ t.TypeName }}(pubentry, ConvertFromC(defaultValue, defaultValueLen)); +{%- elif t.c.ValueInline %} + return nt::SetDefault{{ t.TypeName }}(pubentry, ConvertFromC(defaultValue)); {%- else %} return nt::SetDefault{{ t.TypeName }}(pubentry, defaultValue); {%- endif %} } +{%- if t.c.ValueInline %} + +void NT_Get{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue, {{ t.c.ValueType }} value) { + auto cppValue = nt::Get{{ t.TypeName }}(subentry, ConvertFromC(defaultValue)); + ConvertToC(cppValue, value); +} +{%- else %} + {{ t.c.ValueType }} NT_Get{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen, size_t* len{% endif %}) { {%- if t.c.IsArray %} auto cppValue = nt::Get{{ t.TypeName }}(subentry, ConvertFromC(defaultValue, defaultValueLen)); @@ -67,10 +81,13 @@ NT_Bool NT_SetDefault{{ t.TypeName }}(NT_Handle pubentry, {{ t.c.ParamType }} de return nt::Get{{ t.TypeName }}(subentry, defaultValue); {%- endif %} } +{%- endif %} void NT_GetAtomic{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen{% endif %}, struct NT_Timestamped{{ t.TypeName }}* value) { {%- if t.c.IsArray %} auto cppValue = nt::GetAtomic{{ t.TypeName }}(subentry, ConvertFromC(defaultValue, defaultValueLen)); +{%- elif t.c.ValueInline %} + auto cppValue = nt::GetAtomic{{ t.TypeName }}(subentry, ConvertFromC(defaultValue)); {%- else %} auto cppValue = nt::GetAtomic{{ t.TypeName }}(subentry, defaultValue); {%- endif %} @@ -79,7 +96,9 @@ void NT_GetAtomic{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaul void NT_DisposeTimestamped{{ t.TypeName }}(struct NT_Timestamped{{ t.TypeName }}* value) { {%- if t.TypeName == "StringArray" %} - NT_FreeStringArray(value->value, value->len); + WPI_FreeStringArray(value->value, value->len); +{%- elif t.TypeName == "String" %} + WPI_FreeString(&value->value); {%- elif t.c.IsArray %} std::free(value->value); {%- endif %} @@ -97,7 +116,7 @@ void NT_FreeQueue{{ t.TypeName }}(struct NT_Timestamped{{ t.TypeName }}* arr, si std::free(arr); } -{%- if not t.c.IsArray %} +{%- if not t.c.IsArray and not t.c.ValueInline %} {{ t.c.ValueType }}* NT_ReadQueueValues{{ t.TypeName }}(NT_Handle subentry, size_t* len) { auto arr = nt::ReadQueueValues{{ t.TypeName }}(subentry); return ConvertToC<{{ t.c.ValueType }}>(arr, len); diff --git a/ntcore/src/generate/main/native/include/ntcore_c_types.h.jinja b/ntcore/src/generate/main/native/include/ntcore_c_types.h.jinja index 22866fbe6e5..93359ffce52 100644 --- a/ntcore/src/generate/main/native/include/ntcore_c_types.h.jinja +++ b/ntcore/src/generate/main/native/include/ntcore_c_types.h.jinja @@ -33,7 +33,11 @@ struct NT_Timestamped{{ t.TypeName }} { /** * Value. */ +{%- if t.c.ValueInline %} + {{ t.c.ValueInline }} value; +{%- else %} {{ t.c.ValueType }} value; +{%- endif %} {%- if t.c.IsArray %} /** * Value length. @@ -79,13 +83,22 @@ NT_Bool NT_SetDefault{{ t.TypeName }}(NT_Handle pubentry, {{ t.c.ParamType }} de * * @param subentry subscriber or entry handle * @param defaultValue default value to return if no value has been published +{%- if t.c.ValueInline %} + * @param value returned value (output) +{% endif %} {%- if t.c.IsArray %} * @param defaultValueLen length of default value * @param len length of returned value (output) {% endif %} +{%- if not t.c.ValueInline %} * @return value +{%- endif %} */ +{%- if t.c.ValueInline %} +void NT_Get{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue, {{ t.c.ValueType }} value); +{%- else %} {{ t.c.ValueType }} NT_Get{{ t.TypeName }}(NT_Handle subentry, {{ t.c.ParamType }} defaultValue{% if t.c.IsArray %}, size_t defaultValueLen, size_t* len{% endif %}); +{%- endif %} /** * Get the last published value along with its timestamp. @@ -130,7 +143,7 @@ struct NT_Timestamped{{ t.TypeName }}* NT_ReadQueue{{ t.TypeName }}(NT_Handle su */ void NT_FreeQueue{{ t.TypeName }}(struct NT_Timestamped{{ t.TypeName }}* arr, size_t len); -{%- if not t.c.IsArray %} +{%- if not t.c.IsArray and not t.c.ValueInline %} /** * Get an array of all value changes since the last call to ReadQueue. * diff --git a/ntcore/src/generate/types.json b/ntcore/src/generate/types.json index 3f9f252d54c..1ce48d950db 100644 --- a/ntcore/src/generate/types.json +++ b/ntcore/src/generate/types.json @@ -133,9 +133,9 @@ "TypeName": "String", "TypeString": "\"string\"", "c": { - "ValueType": "char*", - "ParamType": "const char*", - "IsArray": true + "ValueType": "struct WPI_String*", + "ParamType": "const struct WPI_String*", + "ValueInline": "struct WPI_String" }, "cpp": { "ValueType": "std::string", @@ -345,8 +345,8 @@ "TypeName": "StringArray", "TypeString": "\"string[]\"", "c": { - "ValueType": "struct NT_String*", - "ParamType": "const struct NT_String*", + "ValueType": "struct WPI_String*", + "ParamType": "const struct WPI_String*", "IsArray": true }, "cpp": { diff --git a/ntcore/src/generated/main/native/cpp/ntcore_c_types.cpp b/ntcore/src/generated/main/native/cpp/ntcore_c_types.cpp index ca14c7d6cdd..dcf1a946cbe 100644 --- a/ntcore/src/generated/main/native/cpp/ntcore_c_types.cpp +++ b/ntcore/src/generated/main/native/cpp/ntcore_c_types.cpp @@ -16,11 +16,11 @@ static inline std::span ConvertFromC(const T* arr, size_t size) { return {arr, size}; } -static inline std::string_view ConvertFromC(const char* arr, size_t size) { - return {arr, size}; +static inline std::string_view ConvertFromC(const struct WPI_String* str) { + return wpi::to_string_view(str); } -static std::vector ConvertFromC(const NT_String* arr, size_t size) { +static std::vector ConvertFromC(const struct WPI_String* arr, size_t size) { std::vector v; v.reserve(size); for (size_t i = 0; i < size; ++i) { @@ -57,7 +57,7 @@ static void ConvertToC(const nt::TimestampedDouble& in, NT_TimestampedDouble* ou static void ConvertToC(const nt::TimestampedString& in, NT_TimestampedString* out) { out->time = in.time; out->serverTime = in.serverTime; - out->value = ConvertToC(in.value, &out->len); + ConvertToC(in.value, &out->value); } static void ConvertToC(const nt::TimestampedRaw& in, NT_TimestampedRaw* out) { @@ -93,7 +93,7 @@ static void ConvertToC(const nt::TimestampedDoubleArray& in, NT_TimestampedDoubl static void ConvertToC(const nt::TimestampedStringArray& in, NT_TimestampedStringArray* out) { out->time = in.time; out->serverTime = in.serverTime; - out->value = ConvertToC(in.value, &out->len); + out->value = ConvertToC(in.value, &out->len); } @@ -247,26 +247,26 @@ double* NT_ReadQueueValuesDouble(NT_Handle subentry, size_t* len) { } -NT_Bool NT_SetString(NT_Handle pubentry, int64_t time, const char* value, size_t len) { - return nt::SetString(pubentry, ConvertFromC(value, len), time); +NT_Bool NT_SetString(NT_Handle pubentry, int64_t time, const struct WPI_String* value) { + return nt::SetString(pubentry, ConvertFromC(value), time); } -NT_Bool NT_SetDefaultString(NT_Handle pubentry, const char* defaultValue, size_t defaultValueLen) { - return nt::SetDefaultString(pubentry, ConvertFromC(defaultValue, defaultValueLen)); +NT_Bool NT_SetDefaultString(NT_Handle pubentry, const struct WPI_String* defaultValue) { + return nt::SetDefaultString(pubentry, ConvertFromC(defaultValue)); } -char* NT_GetString(NT_Handle subentry, const char* defaultValue, size_t defaultValueLen, size_t* len) { - auto cppValue = nt::GetString(subentry, ConvertFromC(defaultValue, defaultValueLen)); - return ConvertToC(cppValue, len); +void NT_GetString(NT_Handle subentry, const struct WPI_String* defaultValue, struct WPI_String* value) { + auto cppValue = nt::GetString(subentry, ConvertFromC(defaultValue)); + ConvertToC(cppValue, value); } -void NT_GetAtomicString(NT_Handle subentry, const char* defaultValue, size_t defaultValueLen, struct NT_TimestampedString* value) { - auto cppValue = nt::GetAtomicString(subentry, ConvertFromC(defaultValue, defaultValueLen)); +void NT_GetAtomicString(NT_Handle subentry, const struct WPI_String* defaultValue, struct NT_TimestampedString* value) { + auto cppValue = nt::GetAtomicString(subentry, ConvertFromC(defaultValue)); ConvertToC(cppValue, value); } void NT_DisposeTimestampedString(struct NT_TimestampedString* value) { - std::free(value->value); + WPI_FreeString(&value->value); } struct NT_TimestampedString* NT_ReadQueueString(NT_Handle subentry, size_t* len) { @@ -457,26 +457,26 @@ void NT_FreeQueueDoubleArray(struct NT_TimestampedDoubleArray* arr, size_t len) } -NT_Bool NT_SetStringArray(NT_Handle pubentry, int64_t time, const struct NT_String* value, size_t len) { +NT_Bool NT_SetStringArray(NT_Handle pubentry, int64_t time, const struct WPI_String* value, size_t len) { return nt::SetStringArray(pubentry, ConvertFromC(value, len), time); } -NT_Bool NT_SetDefaultStringArray(NT_Handle pubentry, const struct NT_String* defaultValue, size_t defaultValueLen) { +NT_Bool NT_SetDefaultStringArray(NT_Handle pubentry, const struct WPI_String* defaultValue, size_t defaultValueLen) { return nt::SetDefaultStringArray(pubentry, ConvertFromC(defaultValue, defaultValueLen)); } -struct NT_String* NT_GetStringArray(NT_Handle subentry, const struct NT_String* defaultValue, size_t defaultValueLen, size_t* len) { +struct WPI_String* NT_GetStringArray(NT_Handle subentry, const struct WPI_String* defaultValue, size_t defaultValueLen, size_t* len) { auto cppValue = nt::GetStringArray(subentry, ConvertFromC(defaultValue, defaultValueLen)); - return ConvertToC(cppValue, len); + return ConvertToC(cppValue, len); } -void NT_GetAtomicStringArray(NT_Handle subentry, const struct NT_String* defaultValue, size_t defaultValueLen, struct NT_TimestampedStringArray* value) { +void NT_GetAtomicStringArray(NT_Handle subentry, const struct WPI_String* defaultValue, size_t defaultValueLen, struct NT_TimestampedStringArray* value) { auto cppValue = nt::GetAtomicStringArray(subentry, ConvertFromC(defaultValue, defaultValueLen)); ConvertToC(cppValue, value); } void NT_DisposeTimestampedStringArray(struct NT_TimestampedStringArray* value) { - NT_FreeStringArray(value->value, value->len); + WPI_FreeStringArray(value->value, value->len); } struct NT_TimestampedStringArray* NT_ReadQueueStringArray(NT_Handle subentry, size_t* len) { diff --git a/ntcore/src/generated/main/native/include/ntcore_c_types.h b/ntcore/src/generated/main/native/include/ntcore_c_types.h index 3b95a09b6f8..a9a57117c1a 100644 --- a/ntcore/src/generated/main/native/include/ntcore_c_types.h +++ b/ntcore/src/generated/main/native/include/ntcore_c_types.h @@ -473,12 +473,7 @@ struct NT_TimestampedString { /** * Value. */ - char* value; - /** - * Value length. - */ - size_t len; - + struct WPI_String value; }; /** @@ -493,10 +488,8 @@ struct NT_TimestampedString { * @param pubentry publisher or entry handle * @param time timestamp; 0 indicates current NT time should be used * @param value value to publish - * @param len length of value - */ -NT_Bool NT_SetString(NT_Handle pubentry, int64_t time, const char* value, size_t len); +NT_Bool NT_SetString(NT_Handle pubentry, int64_t time, const struct WPI_String* value); /** * Publish a default value. @@ -505,10 +498,8 @@ NT_Bool NT_SetString(NT_Handle pubentry, int64_t time, const char* value, size_t * * @param pubentry publisher or entry handle * @param defaultValue default value - * @param defaultValueLen length of default value - */ -NT_Bool NT_SetDefaultString(NT_Handle pubentry, const char* defaultValue, size_t defaultValueLen); +NT_Bool NT_SetDefaultString(NT_Handle pubentry, const struct WPI_String* defaultValue); /** * Get the last published value. @@ -516,12 +507,10 @@ NT_Bool NT_SetDefaultString(NT_Handle pubentry, const char* defaultValue, size_t * * @param subentry subscriber or entry handle * @param defaultValue default value to return if no value has been published - * @param defaultValueLen length of default value - * @param len length of returned value (output) + * @param value returned value (output) - * @return value */ -char* NT_GetString(NT_Handle subentry, const char* defaultValue, size_t defaultValueLen, size_t* len); +void NT_GetString(NT_Handle subentry, const struct WPI_String* defaultValue, struct WPI_String* value); /** * Get the last published value along with its timestamp. @@ -530,11 +519,9 @@ char* NT_GetString(NT_Handle subentry, const char* defaultValue, size_t defaultV * * @param subentry subscriber or entry handle * @param defaultValue default value to return if no value has been published - * @param defaultValueLen length of default value - * @param value timestamped value (output) */ -void NT_GetAtomicString(NT_Handle subentry, const char* defaultValue, size_t defaultValueLen, struct NT_TimestampedString* value); +void NT_GetAtomicString(NT_Handle subentry, const struct WPI_String* defaultValue, struct NT_TimestampedString* value); /** * Disposes a timestamped value (as returned by NT_GetAtomicString). @@ -1145,7 +1132,7 @@ struct NT_TimestampedStringArray { /** * Value. */ - struct NT_String* value; + struct WPI_String* value; /** * Value length. */ @@ -1168,7 +1155,7 @@ struct NT_TimestampedStringArray { * @param len length of value */ -NT_Bool NT_SetStringArray(NT_Handle pubentry, int64_t time, const struct NT_String* value, size_t len); +NT_Bool NT_SetStringArray(NT_Handle pubentry, int64_t time, const struct WPI_String* value, size_t len); /** * Publish a default value. @@ -1180,7 +1167,7 @@ NT_Bool NT_SetStringArray(NT_Handle pubentry, int64_t time, const struct NT_Stri * @param defaultValueLen length of default value */ -NT_Bool NT_SetDefaultStringArray(NT_Handle pubentry, const struct NT_String* defaultValue, size_t defaultValueLen); +NT_Bool NT_SetDefaultStringArray(NT_Handle pubentry, const struct WPI_String* defaultValue, size_t defaultValueLen); /** * Get the last published value. @@ -1193,7 +1180,7 @@ NT_Bool NT_SetDefaultStringArray(NT_Handle pubentry, const struct NT_String* def * @return value */ -struct NT_String* NT_GetStringArray(NT_Handle subentry, const struct NT_String* defaultValue, size_t defaultValueLen, size_t* len); +struct WPI_String* NT_GetStringArray(NT_Handle subentry, const struct WPI_String* defaultValue, size_t defaultValueLen, size_t* len); /** * Get the last published value along with its timestamp. @@ -1206,7 +1193,7 @@ struct NT_String* NT_GetStringArray(NT_Handle subentry, const struct NT_String* * @param value timestamped value (output) */ -void NT_GetAtomicStringArray(NT_Handle subentry, const struct NT_String* defaultValue, size_t defaultValueLen, struct NT_TimestampedStringArray* value); +void NT_GetAtomicStringArray(NT_Handle subentry, const struct WPI_String* defaultValue, size_t defaultValueLen, struct NT_TimestampedStringArray* value); /** * Disposes a timestamped value (as returned by NT_GetAtomicStringArray). diff --git a/ntcore/src/main/native/cpp/Value.cpp b/ntcore/src/main/native/cpp/Value.cpp index 09ba775b899..28765487ae2 100644 --- a/ntcore/src/main/native/cpp/Value.cpp +++ b/ntcore/src/main/native/cpp/Value.cpp @@ -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 strings; - std::vector ntStrings; + std::vector ntStrings; }; template @@ -58,11 +58,11 @@ inline std::shared_ptr 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(str.c_str()), str.size()}); + WPI_String{const_cast(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( - 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(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(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) { diff --git a/ntcore/src/main/native/cpp/Value_internal.h b/ntcore/src/main/native/cpp/Value_internal.h index 8f2c8fb1382..fd633f13005 100644 --- a/ntcore/src/main/native/cpp/Value_internal.h +++ b/ntcore/src/main/native/cpp/Value_internal.h @@ -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}; } diff --git a/ntcore/src/main/native/cpp/ntcore_c.cpp b/ntcore/src/main/native/cpp/ntcore_c.cpp index cac7a3391eb..ee8b45eeb1e 100644 --- a/ntcore/src/main/native/cpp/ntcore_c.cpp +++ b/ntcore/src/main/native/cpp/ntcore_c.cpp @@ -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::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(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 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(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(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 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(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 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 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> 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(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(log), name); +NT_ConnectionDataLogger NT_StartConnectionDataLog( + NT_Inst inst, struct WPI_DataLog* log, const struct WPI_String* name) { + return nt::StartConnectionDataLog(inst, + *reinterpret_cast(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(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( - 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(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; } diff --git a/ntcore/src/main/native/cpp/ntcore_cpp.cpp b/ntcore/src/main/native/cpp/ntcore_cpp.cpp index 33920ea48fe..75f20a6db5c 100644 --- a/ntcore/src/main/native/cpp/ntcore_cpp.cpp +++ b/ntcore/src/main/native/cpp/ntcore_cpp.cpp @@ -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}}}); } diff --git a/ntcore/src/main/native/cpp/ntcore_meta_c.cpp b/ntcore/src/main/native/cpp/ntcore_meta_c.cpp index 889254e1b70..6c6c026ecb1 100644 --- a/ntcore/src/main/native/cpp/ntcore_meta_c.cpp +++ b/ntcore/src/main/native/cpp/ntcore_meta_c.cpp @@ -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(in.topics, &out->topicsCount); + out->topics = ConvertToC(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); } diff --git a/ntcore/src/main/native/cpp/ntcore_test.cpp b/ntcore/src/main/native/cpp/ntcore_test.cpp index 2a07867e95d..43643706687 100644 --- a/ntcore/src/main/native/cpp/ntcore_test.cpp +++ b/ntcore/src/main/native/cpp/ntcore_test.cpp @@ -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(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::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(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(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; diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h index cf8f8e116de..60cf7841de8 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h +++ b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h @@ -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). diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc b/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc index e583e597021..20b5c0b58ae 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc +++ b/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc @@ -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); } diff --git a/ntcore/src/main/native/include/ntcore_c.h b/ntcore/src/main/native/include/ntcore_c.h index 67efd766110..e918aaafa05 100644 --- a/ntcore/src/main/native/include/ntcore_c.h +++ b/ntcore/src/main/native/include/ntcore_c.h @@ -6,6 +6,8 @@ #include +#include + #ifdef __cplusplus #include #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$`). */ 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$`). */ 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; }; diff --git a/ntcore/src/main/native/include/ntcore_cpp.h b/ntcore/src/main/native/include/ntcore_cpp.h index f241f638118..226669927c0 100644 --- a/ntcore/src/main/native/include/ntcore_cpp.h +++ b/ntcore/src/main/native/include/ntcore_cpp.h @@ -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). diff --git a/ntcore/src/main/native/include/ntcore_test.h b/ntcore/src/main/native/include/ntcore_test.h index 7e0244682a8..bc17b6d6aa7 100644 --- a/ntcore/src/main/native/include/ntcore_test.h +++ b/ntcore/src/main/native/include/ntcore_test.h @@ -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 diff --git a/ntcore/src/test/native/cpp/ValueTest.cpp b/ntcore/src/test/native/cpp/ValueTest.cpp index ba99782ff67..abb0dd5ece9 100644 --- a/ntcore/src/test/native/cpp/ValueTest.cpp +++ b/ntcore/src/test/native/cpp/ValueTest.cpp @@ -84,7 +84,7 @@ TEST_F(ValueTest, String) { NT_InitValue(&cv); ConvertToC(v, &cv); ASSERT_EQ(NT_STRING, cv.type); - ASSERT_EQ("hello"sv, cv.data.v_string.str); + ASSERT_EQ("hello"sv, wpi::to_string_view(&cv.data.v_string)); ASSERT_EQ(5u, cv.data.v_string.len); v = Value::MakeString("goodbye"); @@ -93,7 +93,7 @@ TEST_F(ValueTest, String) { NT_DisposeValue(&cv); ConvertToC(v, &cv); ASSERT_EQ(NT_STRING, cv.type); - ASSERT_EQ("goodbye"sv, cv.data.v_string.str); + ASSERT_EQ("goodbye"sv, wpi::to_string_view(&cv.data.v_string)); ASSERT_EQ(7u, cv.data.v_string.len); NT_DisposeValue(&cv); @@ -226,9 +226,9 @@ TEST_F(ValueTest, StringArray) { ConvertToC(v, &cv); ASSERT_EQ(NT_STRING_ARRAY, cv.type); ASSERT_EQ(3u, cv.data.arr_string.size); - ASSERT_EQ("hello"sv, cv.data.arr_string.arr[0].str); - ASSERT_EQ("goodbye"sv, cv.data.arr_string.arr[1].str); - ASSERT_EQ("string"sv, cv.data.arr_string.arr[2].str); + ASSERT_EQ("hello"sv, wpi::to_string_view(&cv.data.arr_string.arr[0])); + ASSERT_EQ("goodbye"sv, wpi::to_string_view(&cv.data.arr_string.arr[1])); + ASSERT_EQ("string"sv, wpi::to_string_view(&cv.data.arr_string.arr[2])); // assign with same size vec.clear(); @@ -245,9 +245,9 @@ TEST_F(ValueTest, StringArray) { ConvertToC(v, &cv); ASSERT_EQ(NT_STRING_ARRAY, cv.type); ASSERT_EQ(3u, cv.data.arr_string.size); - ASSERT_EQ("s1"sv, cv.data.arr_string.arr[0].str); - ASSERT_EQ("str2"sv, cv.data.arr_string.arr[1].str); - ASSERT_EQ("string3"sv, cv.data.arr_string.arr[2].str); + ASSERT_EQ("s1"sv, wpi::to_string_view(&cv.data.arr_string.arr[0])); + ASSERT_EQ("str2"sv, wpi::to_string_view(&cv.data.arr_string.arr[1])); + ASSERT_EQ("string3"sv, wpi::to_string_view(&cv.data.arr_string.arr[2])); // assign with different size vec.clear(); @@ -262,8 +262,8 @@ TEST_F(ValueTest, StringArray) { ConvertToC(v, &cv); ASSERT_EQ(NT_STRING_ARRAY, cv.type); ASSERT_EQ(2u, cv.data.arr_string.size); - ASSERT_EQ("short"sv, cv.data.arr_string.arr[0].str); - ASSERT_EQ("er"sv, cv.data.arr_string.arr[1].str); + ASSERT_EQ("short"sv, wpi::to_string_view(&cv.data.arr_string.arr[0])); + ASSERT_EQ("er"sv, wpi::to_string_view(&cv.data.arr_string.arr[1])); NT_DisposeValue(&cv); } diff --git a/ntcoreffi/src/main/native/symbols.txt b/ntcoreffi/src/main/native/symbols.txt index 2a095529409..aeacd0f849e 100644 --- a/ntcoreffi/src/main/native/symbols.txt +++ b/ntcoreffi/src/main/native/symbols.txt @@ -18,7 +18,6 @@ NT_AllocateCharArray NT_AllocateDoubleArray NT_AllocateFloatArray NT_AllocateIntegerArray -NT_AllocateStringArray NT_CreateInstance NT_CreateListenerPoller NT_DeleteTopicProperty @@ -27,7 +26,6 @@ NT_DestroyListenerPoller NT_DisposeConnectionInfoArray NT_DisposeEvent NT_DisposeEventArray -NT_DisposeString NT_DisposeTimestampedBoolean NT_DisposeTimestampedBooleanArray NT_DisposeTimestampedDouble @@ -62,7 +60,6 @@ NT_FreeQueueIntegerArray NT_FreeQueueRaw NT_FreeQueueString NT_FreeQueueStringArray -NT_FreeStringArray NT_FreeTopicInfoForTesting NT_GetAtomicBoolean NT_GetAtomicBooleanArray @@ -135,7 +132,12 @@ NT_GetValueStringArray NT_GetValueStringArrayForTesting NT_GetValueStringForTesting NT_GetValueType -NT_InitString +WPI_InitString +WPI_InitStringWithLength +WPI_AllocateString +WPI_FreeString +WPI_AllocateStringArray +WPI_FreeStringArray NT_InitValue NT_IsConnected NT_Meta_DecodeClientPublishers diff --git a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp index 42df53efea4..5639c147c27 100644 --- a/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp +++ b/simulation/halsim_gui/src/main/native/cpp/DriverStationGui.cpp @@ -1168,7 +1168,8 @@ void FMSSimModel::UpdateHAL() { HALSIM_SetDriverStationTest(m_test.GetValue()); HALSIM_SetDriverStationAutonomous(m_autonomous.GetValue()); HALSIM_SetDriverStationMatchTime(m_matchTime.GetValue()); - HALSIM_SetGameSpecificMessage(m_gameMessage.data(), m_gameMessage.size()); + auto str = wpi::make_string(m_gameMessage); + HALSIM_SetGameSpecificMessage(&str); HALSIM_SetDriverStationDsAttached(m_dsAttached.GetValue()); } diff --git a/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_DriverStation.cpp b/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_DriverStation.cpp index ee959b6be07..27495263b92 100644 --- a/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_DriverStation.cpp +++ b/simulation/halsim_ws_core/src/main/native/cpp/WSProvider_DriverStation.cpp @@ -170,7 +170,8 @@ void HALSimWSProviderDriverStation::OnNetValueChanged(const wpi::json& json) { } if ((it = json.find(">game_data")) != json.end()) { std::string message = it.value().get_ref(); - HALSIM_SetGameSpecificMessage(message.c_str(), message.length()); + auto str = wpi::make_string(message); + HALSIM_SetGameSpecificMessage(&str); } // Only notify usercode if we get the new data message diff --git a/wpilibc/src/main/native/cpp/RobotController.cpp b/wpilibc/src/main/native/cpp/RobotController.cpp index 2414ed7fbe3..48da72372af 100644 --- a/wpilibc/src/main/native/cpp/RobotController.cpp +++ b/wpilibc/src/main/native/cpp/RobotController.cpp @@ -30,16 +30,19 @@ int64_t RobotController::GetFPGARevision() { } std::string RobotController::GetSerialNumber() { - // Serial number is 8 characters - char serialNum[9]; - size_t len = HAL_GetSerialNumber(serialNum, sizeof(serialNum)); - return std::string(serialNum, len); + WPI_String serialNum; + HAL_GetSerialNumber(&serialNum); + std::string ret{wpi::to_string_view(&serialNum)}; + WPI_FreeString(&serialNum); + return ret; } std::string RobotController::GetComments() { - char comments[65]; - size_t len = HAL_GetComments(comments, sizeof(comments)); - return std::string(comments, len); + WPI_String comments; + HAL_GetComments(&comments); + std::string ret{wpi::to_string_view(&comments)}; + WPI_FreeString(&comments); + return ret; } int32_t RobotController::GetTeamNumber() { diff --git a/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp b/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp index 345204a82a4..bdefda9002a 100644 --- a/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp +++ b/wpilibc/src/main/native/cpp/simulation/DriverStationSim.cpp @@ -235,7 +235,8 @@ void DriverStationSim::SetJoystickType(int stick, int type) { } void DriverStationSim::SetJoystickName(int stick, std::string_view name) { - HALSIM_SetJoystickName(stick, name.data(), name.size()); + auto str = wpi::make_string(name); + HALSIM_SetJoystickName(stick, &str); } void DriverStationSim::SetJoystickAxisType(int stick, int axis, int type) { @@ -243,11 +244,13 @@ void DriverStationSim::SetJoystickAxisType(int stick, int axis, int type) { } void DriverStationSim::SetGameSpecificMessage(std::string_view message) { - HALSIM_SetGameSpecificMessage(message.data(), message.size()); + auto str = wpi::make_string(message); + HALSIM_SetGameSpecificMessage(&str); } void DriverStationSim::SetEventName(std::string_view name) { - HALSIM_SetEventName(name.data(), name.size()); + auto str = wpi::make_string(name); + HALSIM_SetEventName(&str); } void DriverStationSim::SetMatchType(DriverStation::MatchType type) { diff --git a/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp b/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp index 728d358bfb1..3717128d99e 100644 --- a/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp +++ b/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp @@ -319,23 +319,29 @@ void RoboRioSim::SetTeamNumber(int32_t teamNumber) { } std::string RoboRioSim::GetSerialNumber() { - char serialNum[9]; - size_t len = HALSIM_GetRoboRioSerialNumber(serialNum, sizeof(serialNum)); - return std::string(serialNum, len); + WPI_String serialNum; + HALSIM_GetRoboRioSerialNumber(&serialNum); + std::string serial{wpi::to_string_view(&serialNum)}; + WPI_FreeString(&serialNum); + return serial; } void RoboRioSim::SetSerialNumber(std::string_view serialNumber) { - HALSIM_SetRoboRioSerialNumber(serialNumber.data(), serialNumber.size()); + auto str = wpi::make_string(serialNumber); + HALSIM_SetRoboRioSerialNumber(&str); } std::string RoboRioSim::GetComments() { - char comments[65]; - size_t len = HALSIM_GetRoboRioComments(comments, sizeof(comments)); - return std::string(comments, len); + WPI_String comments; + HALSIM_GetRoboRioComments(&comments); + std::string serial{wpi::to_string_view(&comments)}; + WPI_FreeString(&comments); + return serial; } void RoboRioSim::SetComments(std::string_view comments) { - HALSIM_SetRoboRioComments(comments.data(), comments.size()); + auto str = wpi::make_string(comments); + HALSIM_SetRoboRioComments(&str); } std::unique_ptr RoboRioSim::RegisterRadioLEDStateCallback( diff --git a/wpiutil/src/main/native/cpp/DataLog.cpp b/wpiutil/src/main/native/cpp/DataLog.cpp index befcc7513a9..5234c8e7059 100644 --- a/wpiutil/src/main/native/cpp/DataLog.cpp +++ b/wpiutil/src/main/native/cpp/DataLog.cpp @@ -596,7 +596,7 @@ void DataLog::AppendStringArray(int entry, } void DataLog::AppendStringArray(int entry, - std::span arr, + std::span arr, int64_t timestamp) { if (entry <= 0) { return; @@ -640,11 +640,13 @@ void WPI_DataLog_Stop(struct WPI_DataLog* datalog) { reinterpret_cast(datalog)->Stop(); } -int WPI_DataLog_Start(struct WPI_DataLog* datalog, const char* name, - const char* type, const char* metadata, - int64_t timestamp) { - return reinterpret_cast(datalog)->Start(name, type, metadata, - timestamp); +int WPI_DataLog_Start(struct WPI_DataLog* datalog, + const struct WPI_String* name, + const struct WPI_String* type, + const struct WPI_String* metadata, int64_t timestamp) { + return reinterpret_cast(datalog)->Start( + wpi::to_string_view(name), wpi::to_string_view(type), + wpi::to_string_view(metadata), timestamp); } void WPI_DataLog_Finish(struct WPI_DataLog* datalog, int entry, @@ -653,8 +655,10 @@ void WPI_DataLog_Finish(struct WPI_DataLog* datalog, int entry, } void WPI_DataLog_SetMetadata(struct WPI_DataLog* datalog, int entry, - const char* metadata, int64_t timestamp) { - reinterpret_cast(datalog)->SetMetadata(entry, metadata, timestamp); + const struct WPI_String* metadata, + int64_t timestamp) { + reinterpret_cast(datalog)->SetMetadata( + entry, wpi::to_string_view(metadata), timestamp); } void WPI_DataLog_AppendRaw(struct WPI_DataLog* datalog, int entry, @@ -683,10 +687,10 @@ void WPI_DataLog_AppendDouble(struct WPI_DataLog* datalog, int entry, } void WPI_DataLog_AppendString(struct WPI_DataLog* datalog, int entry, - const char* value, size_t len, + const struct WPI_String* value, int64_t timestamp) { - reinterpret_cast(datalog)->AppendString(entry, {value, len}, - timestamp); + reinterpret_cast(datalog)->AppendString( + entry, {value->str, value->len}, timestamp); } void WPI_DataLog_AppendBooleanArray(struct WPI_DataLog* datalog, int entry, @@ -725,23 +729,29 @@ void WPI_DataLog_AppendDoubleArray(struct WPI_DataLog* datalog, int entry, } void WPI_DataLog_AppendStringArray(struct WPI_DataLog* datalog, int entry, - const WPI_DataLog_String* arr, size_t len, + const struct WPI_String* arr, size_t len, int64_t timestamp) { reinterpret_cast(datalog)->AppendStringArray(entry, {arr, len}, timestamp); } -void WPI_DataLog_AddSchemaString(struct WPI_DataLog* datalog, const char* name, - const char* type, const char* schema, +void WPI_DataLog_AddSchemaString(struct WPI_DataLog* datalog, + const struct WPI_String* name, + const struct WPI_String* type, + const struct WPI_String* schema, int64_t timestamp) { - reinterpret_cast(datalog)->AddSchema(name, type, schema, timestamp); + reinterpret_cast(datalog)->AddSchema( + wpi::to_string_view(name), wpi::to_string_view(type), + wpi::to_string_view(schema), timestamp); } -void WPI_DataLog_AddSchema(struct WPI_DataLog* datalog, const char* name, - const char* type, const uint8_t* schema, +void WPI_DataLog_AddSchema(struct WPI_DataLog* datalog, + const struct WPI_String* name, + const struct WPI_String* type, const uint8_t* schema, size_t schema_len, int64_t timestamp) { reinterpret_cast(datalog)->AddSchema( - name, type, std::span{schema, schema_len}, timestamp); + wpi::to_string_view(name), wpi::to_string_view(type), + std::span{schema, schema_len}, timestamp); } } // extern "C" diff --git a/wpiutil/src/main/native/cpp/DataLogBackgroundWriter.cpp b/wpiutil/src/main/native/cpp/DataLogBackgroundWriter.cpp index 4ef7ef7cf9e..2db52e3cf7e 100644 --- a/wpiutil/src/main/native/cpp/DataLogBackgroundWriter.cpp +++ b/wpiutil/src/main/native/cpp/DataLogBackgroundWriter.cpp @@ -461,23 +461,25 @@ void DataLogBackgroundWriter::WriterThreadMain( extern "C" { struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter( - const char* dir, const char* filename, double period, - const char* extraHeader) { - return reinterpret_cast( - new DataLogBackgroundWriter{dir, filename, period, extraHeader}); + const struct WPI_String* dir, const struct WPI_String* filename, + double period, const struct WPI_String* extraHeader) { + return reinterpret_cast(new DataLogBackgroundWriter{ + wpi::to_string_view(dir), wpi::to_string_view(filename), period, + wpi::to_string_view(extraHeader)}); } struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter_Func( void (*write)(void* ptr, const uint8_t* data, size_t len), void* ptr, - double period, const char* extraHeader) { + double period, const struct WPI_String* extraHeader) { return reinterpret_cast(new DataLogBackgroundWriter{ [=](auto data) { write(ptr, data.data(), data.size()); }, period, - extraHeader}); + wpi::to_string_view(extraHeader)}); } -void WPI_DataLog_SetBackgroundWriterFilename(struct WPI_DataLog* datalog, - const char* filename) { - reinterpret_cast(datalog)->SetFilename(filename); +void WPI_DataLog_SetBackgroundWriterFilename( + struct WPI_DataLog* datalog, const struct WPI_String* filename) { + reinterpret_cast(datalog)->SetFilename( + wpi::to_string_view(filename)); } } // extern "C" diff --git a/wpiutil/src/main/native/cpp/DataLogWriter.cpp b/wpiutil/src/main/native/cpp/DataLogWriter.cpp index ca4645187f3..c4e4a501d4b 100644 --- a/wpiutil/src/main/native/cpp/DataLogWriter.cpp +++ b/wpiutil/src/main/native/cpp/DataLogWriter.cpp @@ -63,12 +63,12 @@ bool DataLogWriter::BufferFull() { extern "C" { -struct WPI_DataLog* WPI_DataLog_CreateWriter(const char* filename, - int* errorCode, - const char* extraHeader) { +struct WPI_DataLog* WPI_DataLog_CreateWriter( + const struct WPI_String* filename, int* errorCode, + const struct WPI_String* extraHeader) { std::error_code ec; - auto rv = reinterpret_cast( - new DataLogWriter{filename, ec, extraHeader}); + auto rv = reinterpret_cast(new DataLogWriter{ + wpi::to_string_view(filename), ec, wpi::to_string_view(extraHeader)}); *errorCode = ec.value(); return rv; } diff --git a/wpiutil/src/main/native/cpp/string.cpp b/wpiutil/src/main/native/cpp/string.cpp new file mode 100644 index 00000000000..e7a7ea3597b --- /dev/null +++ b/wpiutil/src/main/native/cpp/string.cpp @@ -0,0 +1,77 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#include "wpi/string.h" + +#include + +#include + +extern "C" { + +void WPI_InitString(struct WPI_String* wpiString, const char* utf8String) { + if (wpiString == nullptr) { + return; + } + if (utf8String == nullptr) { + wpiString->str = nullptr; + wpiString->len = 0; + } else { + wpiString->str = utf8String; + wpiString->len = std::char_traits::length(utf8String); + } +} + +void WPI_InitStringWithLength(struct WPI_String* wpiString, + const char* utf8String, size_t length) { + if (wpiString == nullptr) { + return; + } + wpiString->str = utf8String; + wpiString->len = length; +} + +// Returned from AllocateString if 0 length is requested. +// Returned instead of nullptr due to memcpy pointer validity rules +static char writeBuffer; + +char* WPI_AllocateString(struct WPI_String* wpiString, size_t length) { + if (wpiString == nullptr) { + return nullptr; + } + if (length == 0) { + wpiString->len = 0; + wpiString->str = nullptr; + return &writeBuffer; + } + char* str = static_cast(wpi::safe_malloc(length)); + wpiString->str = str; + wpiString->len = length; + return str; +} + +void WPI_FreeString(const struct WPI_String* wpiString) { + if (wpiString == nullptr) { + return; + } + std::free(const_cast(wpiString->str)); +} + +struct WPI_String* WPI_AllocateStringArray(size_t length) { + return static_cast( + wpi::safe_malloc(length * sizeof(struct WPI_String))); +} + +void WPI_FreeStringArray(const struct WPI_String* wpiStringArray, + size_t length) { + if (wpiStringArray == nullptr) { + return; + } + for (size_t i = 0; i < length; ++i) { + WPI_FreeString(&wpiStringArray[i]); + } + std::free(const_cast(wpiStringArray)); +} + +} // extern "C" diff --git a/wpiutil/src/main/native/include/wpi/DataLog.h b/wpiutil/src/main/native/include/wpi/DataLog.h index c7665ff1dc2..9fa209b2447 100644 --- a/wpiutil/src/main/native/include/wpi/DataLog.h +++ b/wpiutil/src/main/native/include/wpi/DataLog.h @@ -23,6 +23,7 @@ #include "wpi/StringMap.h" #include "wpi/mutex.h" #include "wpi/protobuf/Protobuf.h" +#include "wpi/string.h" #include "wpi/struct/Struct.h" #include "wpi/timestamp.h" @@ -373,7 +374,7 @@ class DataLog { * @param arr String array to record * @param timestamp Time stamp (may be 0 to indicate now) */ - void AppendStringArray(int entry, std::span arr, + void AppendStringArray(int entry, std::span arr, int64_t timestamp); protected: diff --git a/wpiutil/src/main/native/include/wpi/DataLog_c.h b/wpiutil/src/main/native/include/wpi/DataLog_c.h index c4f48e3a38a..654181a843a 100644 --- a/wpiutil/src/main/native/include/wpi/DataLog_c.h +++ b/wpiutil/src/main/native/include/wpi/DataLog_c.h @@ -7,22 +7,12 @@ #include // NOLINT #include +#include #ifdef __cplusplus extern "C" { #endif -/** - * A datalog string (for use with string array). - */ -struct WPI_DataLog_String { - /** Contents. */ - const char* str; - - /** Length. */ - size_t len; -}; - /** C-compatible data log (opaque struct). */ struct WPI_DataLog; @@ -33,9 +23,9 @@ struct WPI_DataLog; * @param errorCode error if file failed to open (output) * @param extraHeader extra header data */ -struct WPI_DataLog* WPI_DataLog_CreateWriter(const char* filename, - int* errorCode, - const char* extraHeader); +struct WPI_DataLog* WPI_DataLog_CreateWriter( + const struct WPI_String* filename, int* errorCode, + const struct WPI_String* extraHeader); /** * Construct a new Data Log background writer. The log will be initially @@ -48,10 +38,9 @@ struct WPI_DataLog* WPI_DataLog_CreateWriter(const char* filename, * this is a time/storage tradeoff * @param extraHeader extra header data */ -struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter(const char* dir, - const char* filename, - double period, - const char* extraHeader); +struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter( + const struct WPI_String* dir, const struct WPI_String* filename, + double period, const struct WPI_String* extraHeader); /** * Construct a new Data Log background writer that passes its output to the @@ -67,7 +56,7 @@ struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter(const char* dir, */ struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter_Func( void (*write)(void* ptr, const uint8_t* data, size_t len), void* ptr, - double period, const char* extraHeader); + double period, const struct WPI_String* extraHeader); /** * Change log filename. Can only be used on background writer data logs. @@ -76,7 +65,7 @@ struct WPI_DataLog* WPI_DataLog_CreateBackgroundWriter_Func( * @param filename filename */ void WPI_DataLog_SetBackgroundWriterFilename(struct WPI_DataLog* datalog, - const char* filename); + const struct WPI_String* filename); /** * Releases a data log object. Closes the file and returns resources to the @@ -134,9 +123,10 @@ void WPI_DataLog_Stop(struct WPI_DataLog* datalog); * * @return Entry index */ -int WPI_DataLog_Start(struct WPI_DataLog* datalog, const char* name, - const char* type, const char* metadata, - int64_t timestamp); +int WPI_DataLog_Start(struct WPI_DataLog* datalog, + const struct WPI_String* name, + const struct WPI_String* type, + const struct WPI_String* metadata, int64_t timestamp); /** * Finish an entry. @@ -157,7 +147,8 @@ void WPI_DataLog_Finish(struct WPI_DataLog* datalog, int entry, * @param timestamp Time stamp (may be 0 to indicate now) */ void WPI_DataLog_SetMetadata(struct WPI_DataLog* datalog, int entry, - const char* metadata, int64_t timestamp); + const struct WPI_String* metadata, + int64_t timestamp); /** * Appends a raw record to the log. @@ -221,11 +212,11 @@ void WPI_DataLog_AppendDouble(struct WPI_DataLog* datalog, int entry, * @param datalog data log * @param entry Entry index, as returned by WPI_DataLog_Start() * @param value String value to record - * @param len Length of string * @param timestamp Time stamp (may be 0 to indicate now) */ void WPI_DataLog_AppendString(struct WPI_DataLog* datalog, int entry, - const char* value, size_t len, int64_t timestamp); + const struct WPI_String* value, + int64_t timestamp); /** * Appends a boolean array record to the log. @@ -302,15 +293,18 @@ void WPI_DataLog_AppendDoubleArray(struct WPI_DataLog* datalog, int entry, * @param timestamp Time stamp (may be 0 to indicate now) */ void WPI_DataLog_AppendStringArray(struct WPI_DataLog* datalog, int entry, - const WPI_DataLog_String* arr, size_t len, + const struct WPI_String* arr, size_t len, int64_t timestamp); -void WPI_DataLog_AddSchemaString(struct WPI_DataLog* datalog, const char* name, - const char* type, const char* schema, +void WPI_DataLog_AddSchemaString(struct WPI_DataLog* datalog, + const struct WPI_String* name, + const struct WPI_String* type, + const struct WPI_String* schema, int64_t timestamp); -void WPI_DataLog_AddSchema(struct WPI_DataLog* datalog, const char* name, - const char* type, const uint8_t* schema, +void WPI_DataLog_AddSchema(struct WPI_DataLog* datalog, + const struct WPI_String* name, + const struct WPI_String* type, const uint8_t* schema, size_t schema_len, int64_t timestamp); #ifdef __cplusplus diff --git a/wpiutil/src/main/native/include/wpi/jni_util.h b/wpiutil/src/main/native/include/wpi/jni_util.h index 089e6efd2f1..f3418423911 100644 --- a/wpiutil/src/main/native/include/wpi/jni_util.h +++ b/wpiutil/src/main/native/include/wpi/jni_util.h @@ -23,6 +23,7 @@ #include "wpi/mutex.h" #include "wpi/print.h" #include "wpi/raw_ostream.h" +#include "wpi/string.h" /** Java Native Interface (JNI) utility functions */ namespace wpi::java { @@ -171,6 +172,7 @@ class JStringRef { std::string_view str() const { return m_str.str(); } const char* c_str() const { return m_str.data(); } size_t size() const { return m_str.size(); } + WPI_String wpi_str() const { return wpi::make_string(str()); } private: SmallString<128> m_str; diff --git a/wpiutil/src/main/native/include/wpi/string.h b/wpiutil/src/main/native/include/wpi/string.h new file mode 100644 index 00000000000..a001b7be179 --- /dev/null +++ b/wpiutil/src/main/native/include/wpi/string.h @@ -0,0 +1,108 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +#pragma once + +#ifdef __cplusplus +#include +#endif + +/** + * A const UTF8 string. + */ +struct WPI_String { + /** Contents. */ + const char* str; + /** Length */ + size_t len; +}; + +#ifdef __cplusplus +namespace wpi { +/** Converts a WPI_String to a string_view */ +constexpr std::string_view to_string_view(const struct WPI_String* str) { + if (str) { + return {str->str, str->len}; + } else { + return ""; + } +} + +/** Converts a string_view to a WPI_String */ +constexpr WPI_String make_string(std::string_view view) { + return WPI_String{view.data(), view.size()}; +} +} // namespace wpi +#endif // __cplusplus + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Initializes a WPI_String from a null terminated UTF-8 string. + * If input string is null, initializes output to 0 length. + * The output length does not include the null terminator. + * + * The lifetime of the output string is the lifetime of the input string. + * Do not call WPI_FreeString() with the output of this call. + * + * @param wpiString output string + * @param utf8String input string (null terminated) + */ +void WPI_InitString(struct WPI_String* wpiString, const char* utf8String); + +/** + * Initializes a WPI_String from a UTF-8 string and length. + * If input string is null or 0 length, initilizes output to 0 length. + * The input string does not need to be null terminated. + * + * The lifetime of the output string is the lifetime of the input string. + * Do not call WPI_FreeString() with the output of this call. + * + * @param wpiString output string + * @param utf8String input string + * @param length input string length in chars + */ +void WPI_InitStringWithLength(struct WPI_String* wpiString, + const char* utf8String, size_t length); + +/** + * Allocates a WPI_String for the specified length. + * The resultant string must be freed with WPI_FreeString(). + * + * @param wpiString output string + * @param length string length in chars to allocate + * @return mutable pointer to allocated buffer + * + */ +char* WPI_AllocateString(struct WPI_String* wpiString, size_t length); + +/** + * Frees a WPI_String that was allocated with WPI_AllocateString() + * + * @param wpiString string to free + */ +void WPI_FreeString(const struct WPI_String* wpiString); + +/** + * Allocates an array of WPI_Strings. + * + * @param length array length + * @return string array + */ +struct WPI_String* WPI_AllocateStringArray(size_t length); + +/** + * Frees a WPI_String array returned by WPI_AllocateStringArray(). + * + * @param wpiStringArray string array to free + * @param length length of array + */ +void WPI_FreeStringArray(const struct WPI_String* wpiStringArray, + size_t length); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus