summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorElliott Hughes2018-04-19 21:48:25 -0500
committerElliott Hughes2018-04-19 21:49:16 -0500
commit955b6a47929678a0b9dae703061dcd7f2974b32b (patch)
tree5ff57344de6db184a9dbe36c26cdf07485a418ef /base
parent01ce44b734d8eeb6f29d6038857bcefe4854b7cd (diff)
downloadplatform-system-core-955b6a47929678a0b9dae703061dcd7f2974b32b.tar.gz
platform-system-core-955b6a47929678a0b9dae703061dcd7f2974b32b.tar.xz
platform-system-core-955b6a47929678a0b9dae703061dcd7f2974b32b.zip
Add android::base::ParseByteCount.
Bug: N/A Test: ran tests Change-Id: Ib2adcf0a5b9494fcf8259b29974303e8516a9ad9
Diffstat (limited to 'base')
-rw-r--r--base/include/android-base/parseint.h32
-rw-r--r--base/parseint_test.cpp41
2 files changed, 66 insertions, 7 deletions
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 2c8570ead..1b7cc5fa6 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -19,6 +19,7 @@
19 19
20#include <errno.h> 20#include <errno.h>
21#include <stdlib.h> 21#include <stdlib.h>
22#include <string.h>
22 23
23#include <limits> 24#include <limits>
24#include <string> 25#include <string>
@@ -31,14 +32,20 @@ namespace base {
31// otherwise valid values will be rejected. Returns boolean success; 'out' 32// otherwise valid values will be rejected. Returns boolean success; 'out'
32// is untouched if parsing fails. 33// is untouched if parsing fails.
33template <typename T> 34template <typename T>
34bool ParseUint(const char* s, T* out, 35bool ParseUint(const char* s, T* out, T max = std::numeric_limits<T>::max(),
35 T max = std::numeric_limits<T>::max()) { 36 bool allow_suffixes = false) {
36 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10; 37 int base = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10;
37 errno = 0; 38 errno = 0;
38 char* end; 39 char* end;
39 unsigned long long int result = strtoull(s, &end, base); 40 unsigned long long int result = strtoull(s, &end, base);
40 if (errno != 0 || s == end || *end != '\0') { 41 if (errno != 0 || end == s) return false;
41 return false; 42 if (*end != '\0') {
43 const char* suffixes = "bkmgtpe";
44 const char* suffix;
45 if (!allow_suffixes || (suffix = strchr(suffixes, tolower(*end))) == nullptr) return false;
46#if __clang__ // TODO: win32 still builds with GCC :-(
47 if (__builtin_mul_overflow(result, 1ULL << (10 * (suffix - suffixes)), &result)) return false;
48#endif
42 } 49 }
43 if (max < result) { 50 if (max < result) {
44 return false; 51 return false;
@@ -49,9 +56,20 @@ bool ParseUint(const char* s, T* out,
49 56
50// TODO: string_view 57// TODO: string_view
51template <typename T> 58template <typename T>
52bool ParseUint(const std::string& s, T* out, 59bool ParseUint(const std::string& s, T* out, T max = std::numeric_limits<T>::max(),
53 T max = std::numeric_limits<T>::max()) { 60 bool allow_suffixes = false) {
54 return ParseUint(s.c_str(), out, max); 61 return ParseUint(s.c_str(), out, max, allow_suffixes);
62}
63
64template <typename T>
65bool ParseByteCount(const char* s, T* out, T max = std::numeric_limits<T>::max()) {
66 return ParseUint(s, out, max, true);
67}
68
69// TODO: string_view
70template <typename T>
71bool ParseByteCount(const std::string& s, T* out, T max = std::numeric_limits<T>::max()) {
72 return ParseByteCount(s.c_str(), out, max);
55} 73}
56 74
57// Parses the signed decimal integer in the string 's' and sets 'out' to 75// Parses the signed decimal integer in the string 's' and sets 'out' to
diff --git a/base/parseint_test.cpp b/base/parseint_test.cpp
index 483b1d3be..fb1c33993 100644
--- a/base/parseint_test.cpp
+++ b/base/parseint_test.cpp
@@ -96,3 +96,44 @@ TEST(parseint, untouched_on_failure) {
96 ASSERT_FALSE(android::base::ParseInt("456x", &u)); 96 ASSERT_FALSE(android::base::ParseInt("456x", &u));
97 ASSERT_EQ(123u, u); 97 ASSERT_EQ(123u, u);
98} 98}
99
100TEST(parseint, ParseByteCount) {
101 uint64_t i = 0;
102 ASSERT_TRUE(android::base::ParseByteCount("123b", &i));
103 ASSERT_EQ(123ULL, i);
104
105 ASSERT_TRUE(android::base::ParseByteCount("8k", &i));
106 ASSERT_EQ(8ULL * 1024, i);
107
108 ASSERT_TRUE(android::base::ParseByteCount("8M", &i));
109 ASSERT_EQ(8ULL * 1024 * 1024, i);
110
111 ASSERT_TRUE(android::base::ParseByteCount("6g", &i));
112 ASSERT_EQ(6ULL * 1024 * 1024 * 1024, i);
113
114 ASSERT_TRUE(android::base::ParseByteCount("1T", &i));
115 ASSERT_EQ(1ULL * 1024 * 1024 * 1024 * 1024, i);
116
117 ASSERT_TRUE(android::base::ParseByteCount("2p", &i));
118 ASSERT_EQ(2ULL * 1024 * 1024 * 1024 * 1024 * 1024, i);
119
120 ASSERT_TRUE(android::base::ParseByteCount("4e", &i));
121 ASSERT_EQ(4ULL * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, i);
122}
123
124TEST(parseint, ParseByteCount_invalid_suffix) {
125 unsigned u;
126 ASSERT_FALSE(android::base::ParseByteCount("1x", &u));
127}
128
129TEST(parseint, ParseByteCount_overflow) {
130 uint64_t u64;
131 ASSERT_FALSE(android::base::ParseByteCount("4294967295E", &u64));
132
133 uint16_t u16;
134 ASSERT_TRUE(android::base::ParseByteCount("63k", &u16));
135 ASSERT_EQ(63U * 1024, u16);
136 ASSERT_TRUE(android::base::ParseByteCount("65535b", &u16));
137 ASSERT_EQ(65535U, u16);
138 ASSERT_FALSE(android::base::ParseByteCount("65k", &u16));
139}