Skip to content

Commit

Permalink
[wpiutil] Change StringExtras split() to template
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterJohnson committed Jan 4, 2025
1 parent 0f66935 commit 121d403
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 150 deletions.
3 changes: 2 additions & 1 deletion datalogtool/src/main/native/cpp/Exporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ static void RebuildEntryTree() {
} else {
parts.emplace_back(prefix);
}
wpi::split(mainpart, parts, '/', -1, false);
wpi::split(mainpart, '/', -1, false,
[&](auto part) { parts.emplace_back(part); });

// ignore a raw "/" key
if (parts.empty()) {
Expand Down
3 changes: 2 additions & 1 deletion glass/src/libnt/native/cpp/NetworkTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,8 @@ void NetworkTablesModel::RebuildTreeImpl(std::vector<TreeNode>* tree,
continue;
}
parts.clear();
wpi::split(entry->info.name, parts, '/', -1, false);
wpi::split(entry->info.name, '/', -1, false,
[&](auto part) { parts.emplace_back(part); });

// ignore a raw "/" key
if (parts.empty()) {
Expand Down
3 changes: 2 additions & 1 deletion glass/src/libnt/native/cpp/NetworkTablesProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ void NetworkTablesProvider::DisplayMenu() {
wpi::SmallString<64> name;
for (auto&& entry : m_viewEntries) {
path.clear();
wpi::split(entry->name, path, '/', -1, false);
wpi::split(entry->name, '/', -1, false,
[&](auto name) { path.emplace_back(name); });

bool fullDepth = true;
int depth = 0;
Expand Down
7 changes: 2 additions & 5 deletions glass/src/libnt/native/cpp/NetworkTablesSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <imgui.h>
#include <imgui_stdlib.h>
#include <ntcore_cpp.h>
#include <wpi/SmallVector.h>
#include <wpi/StringExtras.h>

#include "glass/Context.h"
Expand Down Expand Up @@ -69,12 +68,10 @@ void NetworkTablesSettings::Thread::Main() {
(team = wpi::parse_integer<unsigned int>(serverTeam, 10))) {
nt::SetServerTeam(m_inst, team.value(), m_port);
} else {
wpi::SmallVector<std::string_view, 4> serverNames;
std::vector<std::pair<std::string_view, unsigned int>> servers;
wpi::split(serverTeam, serverNames, ',', -1, false);
for (auto&& serverName : serverNames) {
wpi::split(serverTeam, ',', -1, false, [&](auto serverName) {
servers.emplace_back(serverName, m_port);
}
});
nt::SetServer(m_inst, servers);
}

Expand Down
12 changes: 4 additions & 8 deletions hal/src/main/native/sim/Extensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <utility>
#include <vector>

#include <wpi/SmallVector.h>
#include <wpi/StringExtras.h>
#include <wpi/fs.h>
#include <wpi/print.h>
Expand Down Expand Up @@ -100,7 +99,6 @@ int HAL_LoadOneExtension(const char* library) {

int HAL_LoadExtensions(void) {
int rc = 1;
wpi::SmallVector<std::string_view, 2> libraries;
const char* e = std::getenv("HALSIM_EXTENSIONS");
if (!e) {
if (GetShowNotFoundMessage()) {
Expand All @@ -109,13 +107,11 @@ int HAL_LoadExtensions(void) {
}
return rc;
}
wpi::split(e, libraries, DELIM, -1, false);
for (auto& library : libraries) {
rc = HAL_LoadOneExtension(std::string(library).c_str());
if (rc < 0) {
break;
wpi::split(e, DELIM, -1, false, [&](auto library) {
if (rc >= 0) {
rc = HAL_LoadOneExtension(std::string(library).c_str());
}
}
});
return rc;
}

Expand Down
32 changes: 14 additions & 18 deletions ntcore/src/main/native/cpp/networktables/NetworkTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,10 @@ std::string_view NetworkTable::NormalizeKey(std::string_view key,
buf.push_back(PATH_SEPARATOR_CHAR);
}
// for each path element, add it with a slash following
wpi::SmallVector<std::string_view, 16> parts;
wpi::split(key, parts, PATH_SEPARATOR_CHAR, -1, false);
for (auto i = parts.begin(); i != parts.end(); ++i) {
buf.append(i->begin(), i->end());
wpi::split(key, PATH_SEPARATOR_CHAR, -1, false, [&](auto part) {
buf.append(part.begin(), part.end());
buf.push_back(PATH_SEPARATOR_CHAR);
}
});
// remove trailing slash if the input key didn't have one
if (!key.empty() && key.back() != PATH_SEPARATOR_CHAR) {
buf.pop_back();
Expand All @@ -72,19 +70,17 @@ std::vector<std::string> NetworkTable::GetHierarchy(std::string_view key) {
hierarchy.emplace_back(1, PATH_SEPARATOR_CHAR);
// for each path element, add it to the end of what we built previously
wpi::SmallString<128> path;
wpi::SmallVector<std::string_view, 16> parts;
wpi::split(key, parts, PATH_SEPARATOR_CHAR, -1, false);
if (!parts.empty()) {
for (auto i = parts.begin(); i != parts.end(); ++i) {
path += PATH_SEPARATOR_CHAR;
path += *i;
hierarchy.emplace_back(path.str());
}
// handle trailing slash
if (key.back() == PATH_SEPARATOR_CHAR) {
path += PATH_SEPARATOR_CHAR;
hierarchy.emplace_back(path.str());
}
bool any = false;
wpi::split(key, PATH_SEPARATOR_CHAR, -1, false, [&](auto part) {
any = true;
path += PATH_SEPARATOR_CHAR;
path += part;
hierarchy.emplace_back(path.str());
});
// handle trailing slash
if (any && key.back() == PATH_SEPARATOR_CHAR) {
path += PATH_SEPARATOR_CHAR;
hierarchy.emplace_back(path.str());
}
return hierarchy;
}
Expand Down
12 changes: 2 additions & 10 deletions simulation/halsim_ws_client/src/main/native/cpp/HALSimWS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <string>

#include <wpi/SmallString.h>
#include <wpi/SmallVector.h>
#include <wpi/StringExtras.h>
#include <wpi/print.h>
#include <wpinet/uv/util.h>
Expand Down Expand Up @@ -73,15 +72,8 @@ bool HALSimWS::Initialize() {
const char* msgFilters = std::getenv("HALSIMWS_FILTERS");
if (msgFilters != nullptr) {
m_useMsgFiltering = true;

std::string_view filters(msgFilters);
filters = wpi::trim(filters);
wpi::SmallVector<std::string_view, 16> filtersSplit;

wpi::split(filters, filtersSplit, ',', -1, false);
for (auto val : filtersSplit) {
m_msgFilters[wpi::trim(val)] = true;
}
wpi::split(wpi::trim(msgFilters), ',', -1, false,
[&](auto val) { m_msgFilters[wpi::trim(val)] = true; });
} else {
m_useMsgFiltering = false;
}
Expand Down
11 changes: 2 additions & 9 deletions simulation/halsim_ws_server/src/main/native/cpp/HALSimWeb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,8 @@ bool HALSimWeb::Initialize() {
const char* msgFilters = std::getenv("HALSIMWS_FILTERS");
if (msgFilters != nullptr) {
m_useMsgFiltering = true;

std::string_view filters(msgFilters);
filters = wpi::trim(filters);
wpi::SmallVector<std::string_view, 16> filtersSplit;

wpi::split(filters, filtersSplit, ',', -1, false);
for (auto val : filtersSplit) {
m_msgFilters[wpi::trim(val)] = true;
}
wpi::split(wpi::trim(msgFilters), ',', -1, false,
[&](auto val) { m_msgFilters[wpi::trim(val)] = true; });
} else {
m_useMsgFiltering = false;
}
Expand Down
3 changes: 2 additions & 1 deletion sysid/src/main/native/cpp/view/LogLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ void LogLoader::RebuildEntryTree() {
} else {
parts.emplace_back(prefix);
}
wpi::split(mainpart, parts, '/', -1, false);
wpi::split(mainpart, '/', -1, false,
[&](auto part) { parts.emplace_back(part); });

// ignore a raw "/" key
if (parts.empty()) {
Expand Down
12 changes: 4 additions & 8 deletions wpinet/src/main/native/cpp/HttpUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ std::string_view EscapeHTML(std::string_view str, SmallVectorImpl<char>& buf) {
}

HttpQueryMap::HttpQueryMap(std::string_view query) {
SmallVector<std::string_view, 16> queryElems;
split(query, queryElems, '&', 100, false);
for (auto elem : queryElems) {
split(query, '&', 100, false, [&](auto elem) {
auto [nameEsc, valueEsc] = split(elem, '=');
SmallString<64> nameBuf;
bool err = false;
Expand All @@ -109,7 +107,7 @@ HttpQueryMap::HttpQueryMap(std::string_view query) {
if (!err) {
m_elems.try_emplace(name, valueEsc);
}
}
});
}

std::optional<std::string_view> HttpQueryMap::Get(
Expand All @@ -132,9 +130,7 @@ HttpPath::HttpPath(std::string_view path) {
m_pathEnds.emplace_back(0);
return;
}
wpi::SmallVector<std::string_view, 16> pathElems;
split(path, pathElems, '/', 100, false);
for (auto elem : pathElems) {
split(path, '/', 100, false, [&](auto elem) {
SmallString<64> buf;
bool err = false;
auto val = wpi::UnescapeURI(elem, buf, &err);
Expand All @@ -144,7 +140,7 @@ HttpPath::HttpPath(std::string_view path) {
}
m_pathBuf += val;
m_pathEnds.emplace_back(m_pathBuf.size());
}
});
}

bool HttpPath::startswith(size_t start,
Expand Down
25 changes: 18 additions & 7 deletions wpinet/src/main/native/cpp/WebSocketServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@ WebSocketServerHelper::WebSocketServerHelper(HttpParser& req) {
m_version = value;
} else if (equals_lower(name, "sec-websocket-protocol")) {
// Protocols are comma delimited, repeated headers add to list
SmallVector<std::string_view, 2> protocols;
split(value, protocols, ",", -1, false);
for (auto protocol : protocols) {
split(value, ',', -1, false, [&](auto protocol) {
protocol = trim(protocol);
if (!protocol.empty()) {
m_protocols.emplace_back(protocol);
}
}
});
}
});
req.headersComplete.connect([&req, this](bool) {
Expand All @@ -63,6 +61,21 @@ std::pair<bool, std::string_view> WebSocketServerHelper::MatchProtocol(
return {false, {}};
}

std::pair<bool, std::string_view> WebSocketServerHelper::MatchProtocol(
std::span<const std::string> protocols) {
if (protocols.empty() && m_protocols.empty()) {
return {true, {}};
}
for (auto protocol : protocols) {
for (auto&& clientProto : m_protocols) {
if (protocol == clientProto) {
return {true, protocol};
}
}
}
return {false, {}};
}

WebSocketServer::WebSocketServer(uv::Stream& stream,
std::span<const std::string_view> protocols,
ServerOptions options, const private_init&)
Expand Down Expand Up @@ -101,9 +114,7 @@ WebSocketServer::WebSocketServer(uv::Stream& stream,
}

// Negotiate sub-protocol
SmallVector<std::string_view, 2> protocols{m_protocols.begin(),
m_protocols.end()};
std::string_view protocol = m_helper.MatchProtocol(protocols).second;
std::string_view protocol = m_helper.MatchProtocol(m_protocols).second;

// Disconnect our header reader
m_dataConn.disconnect();
Expand Down
12 changes: 12 additions & 0 deletions wpinet/src/main/native/include/wpinet/WebSocketServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ class WebSocketServerHelper {
std::pair<bool, std::string_view> MatchProtocol(
std::span<const std::string_view> protocols);

/**
* Try to find a match to the list of sub-protocols provided by the client.
* The list is priority ordered, so the first match wins.
* Only valid during and after the upgrade event.
* @param protocols Acceptable protocols
* @return Pair; first item is true if a match was made, false if not.
* Second item is the matched protocol if a match was made, otherwise
* is empty.
*/
std::pair<bool, std::string_view> MatchProtocol(
std::span<const std::string> protocols);

/**
* Try to find a match to the list of sub-protocols provided by the client.
* The list is priority ordered, so the first match wins.
Expand Down
60 changes: 0 additions & 60 deletions wpiutil/src/main/native/thirdparty/llvm/cpp/llvm/StringExtras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <string_view>

#include "wpi/SmallString.h"
#include "wpi/SmallVector.h"

// strncasecmp() is not available on non-POSIX systems, so define an
// alternative function here.
Expand Down Expand Up @@ -118,65 +117,6 @@ bool wpi::ends_with_lower(std::string_view str,
suffix.data(), suffix.size()) == 0;
}

void wpi::split(std::string_view str, SmallVectorImpl<std::string_view>& arr,
std::string_view separator, int maxSplit,
bool keepEmpty) noexcept {
std::string_view s = str;

// Count down from maxSplit. When maxSplit is -1, this will just split
// "forever". This doesn't support splitting more than 2^31 times
// intentionally; if we ever want that we can make maxSplit a 64-bit integer
// but that seems unlikely to be useful.
while (maxSplit-- != 0) {
auto idx = s.find(separator);
if (idx == std::string_view::npos) {
break;
}

// Push this split.
if (keepEmpty || idx > 0) {
arr.push_back(slice(s, 0, idx));
}

// Jump forward.
s = slice(s, idx + separator.size(), std::string_view::npos);
}

// Push the tail.
if (keepEmpty || !s.empty()) {
arr.push_back(s);
}
}

void wpi::split(std::string_view str, SmallVectorImpl<std::string_view>& arr,
char separator, int maxSplit, bool keepEmpty) noexcept {
std::string_view s = str;

// Count down from maxSplit. When maxSplit is -1, this will just split
// "forever". This doesn't support splitting more than 2^31 times
// intentionally; if we ever want that we can make maxSplit a 64-bit integer
// but that seems unlikely to be useful.
while (maxSplit-- != 0) {
size_t idx = s.find(separator);
if (idx == std::string_view::npos) {
break;
}

// Push this split.
if (keepEmpty || idx > 0) {
arr.push_back(slice(s, 0, idx));
}

// Jump forward.
s = slice(s, idx + 1, std::string_view::npos);
}

// Push the tail.
if (keepEmpty || !s.empty()) {
arr.push_back(s);
}
}

static unsigned GetAutoSenseRadix(std::string_view& str) noexcept {
if (str.empty()) {
return 10;
Expand Down
Loading

0 comments on commit 121d403

Please sign in to comment.