adb: add stroll equivalent for string_view.
Test: $ANDROID_HOST_OUT/nativetest64/adb_test/adb_test Test: adb shell /data/nativetest64/adbd_test/adbd_test Change-Id: I1d89913474fcd1aa4a856b5e4583a3c1f076ddd4
This commit is contained in:
parent
d19b77ac12
commit
3add0c4d42
2 changed files with 78 additions and 0 deletions
|
@ -19,6 +19,8 @@
|
|||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
|
@ -107,3 +109,34 @@ inline std::string_view StripTrailingNulls(std::string_view str) {
|
|||
str.remove_suffix(n);
|
||||
return str;
|
||||
}
|
||||
|
||||
// Base-10 stroll on a string_view.
|
||||
template <typename T>
|
||||
inline bool ParseUint(T* result, std::string_view str, std::string_view* remaining) {
|
||||
if (str.empty() || !isdigit(str[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
T value = 0;
|
||||
std::string_view::iterator it;
|
||||
constexpr T max = std::numeric_limits<T>::max();
|
||||
for (it = str.begin(); it != str.end() && isdigit(*it); ++it) {
|
||||
if (value > max / 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value *= 10;
|
||||
|
||||
T digit = *it - '0';
|
||||
if (value > max - digit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value += digit;
|
||||
}
|
||||
*result = value;
|
||||
if (remaining) {
|
||||
*remaining = str.substr(it - str.begin());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -181,3 +181,48 @@ TEST(adb_utils, test_forward_targets_are_valid) {
|
|||
EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:a", &error));
|
||||
EXPECT_FALSE(forward_targets_are_valid("tcp:8000", "tcp:22x", &error));
|
||||
}
|
||||
|
||||
void TestParseUint(std::string_view string, bool expected_success, uint32_t expected_value = 0) {
|
||||
// Standalone.
|
||||
{
|
||||
uint32_t value;
|
||||
std::string_view remaining;
|
||||
bool success = ParseUint(&value, string, &remaining);
|
||||
EXPECT_EQ(success, expected_success);
|
||||
if (expected_success) {
|
||||
EXPECT_EQ(value, expected_value);
|
||||
}
|
||||
EXPECT_TRUE(remaining.empty());
|
||||
}
|
||||
|
||||
// With trailing text.
|
||||
{
|
||||
std::string text = std::string(string) + "foo";
|
||||
uint32_t value;
|
||||
std::string_view remaining;
|
||||
bool success = ParseUint(&value, text, &remaining);
|
||||
EXPECT_EQ(success, expected_success);
|
||||
if (expected_success) {
|
||||
EXPECT_EQ(value, expected_value);
|
||||
EXPECT_EQ(remaining, "foo");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(adb_utils, ParseUint) {
|
||||
TestParseUint("", false);
|
||||
TestParseUint("foo", false);
|
||||
TestParseUint("foo123", false);
|
||||
TestParseUint("-1", false);
|
||||
|
||||
TestParseUint("123", true, 123);
|
||||
TestParseUint("9999999999999999999999999", false);
|
||||
TestParseUint(std::to_string(UINT32_MAX), true, UINT32_MAX);
|
||||
TestParseUint("0" + std::to_string(UINT32_MAX), true, UINT32_MAX);
|
||||
TestParseUint(std::to_string(static_cast<uint64_t>(UINT32_MAX) + 1), false);
|
||||
TestParseUint("0" + std::to_string(static_cast<uint64_t>(UINT32_MAX) + 1), false);
|
||||
|
||||
std::string x = std::to_string(UINT32_MAX) + "123";
|
||||
std::string_view substr = std::string_view(x).substr(0, std::to_string(UINT32_MAX).size());
|
||||
TestParseUint(substr, true, UINT32_MAX);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue