Skip to content

Commit 1397bd6

Browse files
authored
Misc cleanup from other branches added (#340)
1 parent 124471b commit 1397bd6

File tree

6 files changed

+162
-32
lines changed

6 files changed

+162
-32
lines changed

include/util/StringUtils.h

Lines changed: 119 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,133 @@
66
#include <limits>
77
#include <string>
88
#include <string_view>
9+
#include <utility>
910
#include <vector>
1011

1112
namespace OpenShock {
1213
bool FormatToString(std::string& out, const char* format, ...);
1314

14-
constexpr std::string_view StringTrimLeft(std::string_view view) {
15+
constexpr std::string_view StringTrimLeft(std::string_view view)
16+
{
1517
if (view.empty()) {
1618
return view;
1719
}
1820

1921
std::size_t pos = 0;
20-
while (pos < view.size() && isspace(view[pos])) {
22+
while (pos < view.size() && isspace(view[pos]) != 0) {
2123
++pos;
2224
}
2325

2426
return view.substr(pos);
2527
}
26-
constexpr std::string_view StringTrimRight(std::string_view view) {
28+
constexpr std::string_view StringTrimRight(std::string_view view)
29+
{
2730
if (view.empty()) {
2831
return view;
2932
}
3033

3134
std::size_t pos = view.size() - 1;
32-
while (pos > 0 && isspace(view[pos])) {
35+
while (pos > 0 && isspace(view[pos]) != 0) {
3336
--pos;
3437
}
3538

3639
return view.substr(0, pos + 1);
3740
}
38-
constexpr std::string_view StringTrim(std::string_view view) {
41+
constexpr std::string_view StringTrim(std::string_view view)
42+
{
3943
return StringTrimLeft(StringTrimRight(view));
4044
}
41-
constexpr bool StringStartsWith(std::string_view view, std::string_view prefix) {
45+
46+
constexpr bool StringHasPrefix(std::string_view view, char prefix)
47+
{
48+
return !view.empty() && view.front() == prefix;
49+
}
50+
constexpr bool StringHasPrefix(std::string_view view, std::string_view prefix)
51+
{
4252
return view.size() >= prefix.size() && view.substr(0, prefix.size()) == prefix;
4353
}
54+
constexpr bool StringHasSuffix(std::string_view view, char suffix)
55+
{
56+
return !view.empty() && view.back() == suffix;
57+
}
58+
constexpr bool StringHasSuffix(std::string_view view, std::string_view suffix)
59+
{
60+
return view.size() >= suffix.size() && view.substr(view.size() - suffix.size(), view.size()) == suffix;
61+
}
62+
63+
constexpr std::string_view StringRemovePrefix(std::string_view view, char prefix)
64+
{
65+
if (StringHasPrefix(view, prefix)) view.remove_prefix(1);
66+
return view;
67+
}
68+
constexpr std::string_view StringRemovePrefix(std::string_view view, std::string_view prefix)
69+
{
70+
if (StringHasPrefix(view, prefix)) view.remove_prefix(prefix.length());
71+
return view;
72+
}
73+
constexpr std::string_view StringRemoveSuffix(std::string_view view, char suffix)
74+
{
75+
if (StringHasSuffix(view, suffix)) view.remove_suffix(1);
76+
return view;
77+
}
78+
constexpr std::string_view StringRemoveSuffix(std::string_view view, std::string_view suffix)
79+
{
80+
if (StringHasSuffix(view, suffix)) view.remove_prefix(suffix.length());
81+
return view;
82+
}
83+
84+
constexpr std::string_view StringBeforeFirst(std::string_view view, char delimiter)
85+
{
86+
size_t pos = view.find(delimiter);
87+
if (pos == std::string_view::npos) return view;
88+
return view.substr(0, pos);
89+
}
90+
constexpr std::string_view StringBeforeFirst(std::string_view view, std::string_view delimiter)
91+
{
92+
size_t pos = view.find(delimiter);
93+
if (pos == std::string_view::npos) return view;
94+
return view.substr(0, pos);
95+
}
96+
constexpr std::string_view StringBeforeLast(std::string_view view, char delimiter)
97+
{
98+
size_t pos = view.find_last_of(delimiter);
99+
if (pos == std::string_view::npos) return view;
100+
return view.substr(0, pos);
101+
}
102+
constexpr std::string_view StringBeforeLast(std::string_view view, std::string_view delimiter)
103+
{
104+
size_t pos = view.find_last_of(delimiter);
105+
if (pos == std::string_view::npos) return view;
106+
return view.substr(0, pos);
107+
}
108+
constexpr std::string_view StringAfterFirst(std::string_view view, char delimiter)
109+
{
110+
size_t pos = view.find(delimiter);
111+
if (pos == std::string_view::npos) return view;
112+
return view.substr(pos + 1);
113+
}
114+
constexpr std::string_view StringAfterFirst(std::string_view view, std::string_view delimiter)
115+
{
116+
size_t pos = view.find(delimiter);
117+
if (pos == std::string_view::npos) return view;
118+
return view.substr(pos + delimiter.length());
119+
}
120+
constexpr std::string_view StringAfterLast(std::string_view view, char delimiter)
121+
{
122+
size_t pos = view.find_last_of(delimiter);
123+
if (pos == std::string_view::npos) return view;
124+
return view.substr(pos + 1);
125+
}
126+
constexpr std::string_view StringAfterLast(std::string_view view, std::string_view delimiter)
127+
{
128+
size_t pos = view.find_last_of(delimiter);
129+
if (pos == std::string_view::npos) return view;
130+
return view.substr(pos + delimiter.length());
131+
}
132+
44133
template<std::size_t N>
45-
constexpr bool TryStringSplit(std::string_view view, char delimiter, std::string_view (&out)[N]) {
134+
constexpr bool TryStringSplit(std::string_view view, char delimiter, std::string_view (&out)[N])
135+
{
46136
std::size_t pos = 0;
47137
std::size_t idx = 0;
48138
while (pos < view.size() && idx < N) {
@@ -62,8 +152,30 @@ namespace OpenShock {
62152
std::vector<std::string_view> StringSplit(std::string_view view, bool (*predicate)(char delimiter), std::size_t maxSplits = std::numeric_limits<std::size_t>::max());
63153
std::vector<std::string_view> StringSplitNewLines(std::string_view view, std::size_t maxSplits = std::numeric_limits<std::size_t>::max());
64154
std::vector<std::string_view> StringSplitWhiteSpace(std::string_view view, std::size_t maxSplits = std::numeric_limits<std::size_t>::max());
155+
constexpr std::pair<std::string_view, std::string_view> StringSplitByFirst(std::string_view view, char delimiter)
156+
{
157+
size_t pos = view.find(delimiter);
158+
return std::make_pair(view.substr(0, pos), pos == std::string_view::npos ? std::string_view() : view.substr(pos + 1));
159+
}
160+
constexpr std::pair<std::string_view, std::string_view> StringSplitByFirst(std::string_view view, std::string_view delimiter)
161+
{
162+
size_t pos = view.find(delimiter);
163+
return std::make_pair(view.substr(0, pos), pos == std::string_view::npos ? std::string_view() : view.substr(pos + delimiter.length()));
164+
}
165+
constexpr std::pair<std::string_view, std::string_view> StringSplitByLast(std::string_view view, char delimiter)
166+
{
167+
size_t pos = view.find_last_of(delimiter);
168+
return std::make_pair(view.substr(0, pos), pos == std::string_view::npos ? std::string_view() : view.substr(pos + 1));
169+
}
170+
constexpr std::pair<std::string_view, std::string_view> StringSplitByLast(std::string_view view, std::string_view delimiter)
171+
{
172+
size_t pos = view.find_last_of(delimiter);
173+
return std::make_pair(view.substr(0, pos), pos == std::string_view::npos ? std::string_view() : view.substr(pos + delimiter.length()));
174+
}
65175

66176
bool StringIEquals(std::string_view a, std::string_view b);
177+
bool StringIContains(std::string_view haystack, std::string_view needle);
178+
bool StringHasPrefixIC(std::string_view view, std::string_view prefix);
67179

68180
String StringToArduinoString(std::string_view view);
69181
} // namespace OpenShock

src/OtaUpdateManager.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -639,9 +639,7 @@ bool OtaUpdateManager::TryGetFirmwareRelease(const OpenShock::SemVer& version, F
639639
auto hash = OpenShock::StringTrim(parts[0]);
640640
auto file = OpenShock::StringTrim(parts[1]);
641641

642-
if (OpenShock::StringStartsWith(file, "./"sv)) {
643-
file = file.substr(2);
644-
}
642+
file = OpenShock::StringRemovePrefix(file, "./"sv);
645643

646644
if (hash.size() != 64) {
647645
OS_LOGE(TAG, "Invalid hash: %.*s", hash.size(), hash.data());

src/SemVer.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -331,17 +331,11 @@ bool OpenShock::TryParseSemVer(std::string_view semverStr, SemVer& semver)
331331

332332
std::string_view majorStr = parts[0], minorStr = parts[1], patchStr = parts[2];
333333

334-
auto dashIdx = patchStr.find('-');
335-
if (dashIdx != std::string_view::npos) {
336-
semver.prerelease = patchStr.substr(dashIdx + 1);
337-
patchStr = patchStr.substr(0, dashIdx);
338-
}
334+
size_t plusIdx = patchStr.find('+');
335+
size_t dashIdx = patchStr.find('-');
339336

340-
auto plusIdx = semver.prerelease.find('+');
341-
if (plusIdx != std::string_view::npos) {
342-
semver.build = semver.prerelease.substr(plusIdx + 1);
343-
semver.prerelease = semver.prerelease.substr(0, plusIdx);
344-
}
337+
std::string_view restStr = patchStr.substr(std::min(dashIdx, plusIdx));
338+
patchStr.remove_suffix(restStr.length());
345339

346340
if (!Convert::ToUint16(majorStr, semver.major)) {
347341
OS_LOGE(TAG, "Invalid major version: %.*s", majorStr.length(), majorStr.data());
@@ -358,14 +352,25 @@ bool OpenShock::TryParseSemVer(std::string_view semverStr, SemVer& semver)
358352
return false;
359353
}
360354

361-
if (!semver.prerelease.empty() && !_semverIsPrerelease(semver.prerelease)) {
362-
OS_LOGE(TAG, "Invalid prerelease: %s", semver.prerelease.c_str());
363-
return false;
364-
}
355+
if (!restStr.empty()) {
356+
if (plusIdx != std::string_view::npos) {
357+
semver.build = restStr.substr((plusIdx - patchStr.length()) + 1);
358+
patchStr.remove_suffix(semver.build.length() + 1);
365359

366-
if (!semver.build.empty() && !_semverIsBuild(semver.build)) {
367-
OS_LOGE(TAG, "Invalid build: %s", semver.build.c_str());
368-
return false;
360+
if (!semver.build.empty() && !_semverIsBuild(semver.build)) {
361+
OS_LOGE(TAG, "Invalid build: %s", semver.build.c_str());
362+
return false;
363+
}
364+
}
365+
366+
if (dashIdx != std::string_view::npos) {
367+
semver.prerelease = patchStr.substr(1);
368+
369+
if (!semver.prerelease.empty() && !_semverIsPrerelease(semver.prerelease)) {
370+
OS_LOGE(TAG, "Invalid prerelease: %s", semver.prerelease.c_str());
371+
return false;
372+
}
373+
}
369374
}
370375

371376
return true;

src/serial/SerialInputHandler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ void _echoHandleSerialInput(std::string_view buffer, bool hasData)
434434
}
435435

436436
// If the command starts with a $, it's a automated command, don't echo it
437-
if (!buffer.empty() && buffer[0] == '$') {
437+
if (OpenShock::StringHasPrefix(buffer, '$')) {
438438
return;
439439
}
440440

src/serial/command_handlers/lcgoverride.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
const char* TAG = "Serial::CommandHandlers::LcgOverride";
99

10-
void _handleLcgOverrideCommand(std::string_view arg, bool isAutomated) {
10+
void _handleLcgOverrideCommand(std::string_view arg, bool isAutomated)
11+
{
1112
if (arg.empty()) {
1213
std::string lcgOverride;
1314
if (!OpenShock::Config::GetBackendLCGOverride(lcgOverride)) {
@@ -20,7 +21,7 @@ void _handleLcgOverrideCommand(std::string_view arg, bool isAutomated) {
2021
return;
2122
}
2223

23-
if (OpenShock::StringStartsWith(arg, "clear"sv)) {
24+
if (OpenShock::StringHasPrefix(arg, "clear"sv)) {
2425
if (arg.size() != 5) {
2526
SERPR_ERROR("Invalid command (clear command should not have any arguments)");
2627
return;
@@ -35,7 +36,7 @@ void _handleLcgOverrideCommand(std::string_view arg, bool isAutomated) {
3536
return;
3637
}
3738

38-
if (OpenShock::StringStartsWith(arg, "set "sv)) {
39+
if (OpenShock::StringHasPrefix(arg, "set "sv)) {
3940
if (arg.size() <= 4) {
4041
SERPR_ERROR("Invalid command (set command should have an argument)");
4142
return;
@@ -90,7 +91,8 @@ void _handleLcgOverrideCommand(std::string_view arg, bool isAutomated) {
9091
SERPR_ERROR("Invalid subcommand");
9192
}
9293

93-
OpenShock::Serial::CommandGroup OpenShock::Serial::CommandHandlers::LcgOverrideHandler() {
94+
OpenShock::Serial::CommandGroup OpenShock::Serial::CommandHandlers::LcgOverrideHandler()
95+
{
9496
auto group = OpenShock::Serial::CommandGroup("lcgoverride"sv);
9597

9698
auto& getCommand = group.addCommand("Get the domain overridden for LCG endpoint (if any)."sv, _handleLcgOverrideCommand);

src/util/StringUtils.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const char* const TAG = "StringUtils";
44

55
#include "Logging.h"
66

7+
#include <algorithm>
78
#include <cstdarg>
89
#include <cstring>
910

@@ -128,6 +129,18 @@ bool OpenShock::StringIEquals(std::string_view a, std::string_view b)
128129
if (a.size() != b.size()) return false;
129130
return strncasecmp(a.data(), b.data(), a.size()) == 0;
130131
}
132+
bool OpenShock::StringIContains(std::string_view haystack, std::string_view needle)
133+
{
134+
if (haystack.size() < needle.size()) return false;
135+
if (haystack.size() == needle.size()) return StringIEquals(haystack, needle);
136+
137+
return std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char hc, char nc) { return tolower(hc) == tolower(nc); }) != haystack.end();
138+
}
139+
bool OpenShock::StringHasPrefixIC(std::string_view view, std::string_view prefix)
140+
{
141+
if (view.size() < prefix.size()) return false;
142+
return StringIEquals(view.substr(0, prefix.size()), prefix);
143+
}
131144

132145
String OpenShock::StringToArduinoString(std::string_view view) {
133146
return String(view.data(), view.size());

0 commit comments

Comments
 (0)