Browse Source

AK: Add a way to disable the trimming of whitespace in to_*int

This behavior might not always be desirable, and so this patch adds a
way to disable it.
sin-ack 4 years ago
parent
commit
3abcfcc178
6 changed files with 74 additions and 61 deletions
  1. 12 12
      AK/FlyString.cpp
  2. 3 2
      AK/FlyString.h
  3. 12 12
      AK/String.cpp
  4. 2 2
      AK/String.h
  5. 36 30
      AK/StringUtils.cpp
  6. 9 3
      AK/StringUtils.h

+ 12 - 12
AK/FlyString.cpp

@@ -74,26 +74,26 @@ FlyString::FlyString(StringView const& string)
 }
 
 template<typename T>
-Optional<T> FlyString::to_int() const
+Optional<T> FlyString::to_int(TrimWhitespace trim_whitespace) const
 {
-    return StringUtils::convert_to_int<T>(view());
+    return StringUtils::convert_to_int<T>(view(), trim_whitespace);
 }
 
-template Optional<i8> FlyString::to_int() const;
-template Optional<i16> FlyString::to_int() const;
-template Optional<i32> FlyString::to_int() const;
-template Optional<i64> FlyString::to_int() const;
+template Optional<i8> FlyString::to_int(TrimWhitespace) const;
+template Optional<i16> FlyString::to_int(TrimWhitespace) const;
+template Optional<i32> FlyString::to_int(TrimWhitespace) const;
+template Optional<i64> FlyString::to_int(TrimWhitespace) const;
 
 template<typename T>
-Optional<T> FlyString::to_uint() const
+Optional<T> FlyString::to_uint(TrimWhitespace trim_whitespace) const
 {
-    return StringUtils::convert_to_uint<T>(view());
+    return StringUtils::convert_to_uint<T>(view(), trim_whitespace);
 }
 
-template Optional<u8> FlyString::to_uint() const;
-template Optional<u16> FlyString::to_uint() const;
-template Optional<u32> FlyString::to_uint() const;
-template Optional<u64> FlyString::to_uint() const;
+template Optional<u8> FlyString::to_uint(TrimWhitespace) const;
+template Optional<u16> FlyString::to_uint(TrimWhitespace) const;
+template Optional<u32> FlyString::to_uint(TrimWhitespace) const;
+template Optional<u64> FlyString::to_uint(TrimWhitespace) const;
 
 bool FlyString::equals_ignoring_case(const StringView& other) const
 {

+ 3 - 2
AK/FlyString.h

@@ -6,6 +6,7 @@
 
 #pragma once
 
+#include "AK/StringUtils.h"
 #include <AK/String.h>
 
 namespace AK {
@@ -73,9 +74,9 @@ public:
     FlyString to_lowercase() const;
 
     template<typename T = int>
-    Optional<T> to_int() const;
+    Optional<T> to_int(TrimWhitespace = TrimWhitespace::Yes) const;
     template<typename T = unsigned>
-    Optional<T> to_uint() const;
+    Optional<T> to_uint(TrimWhitespace = TrimWhitespace::Yes) const;
 
     bool equals_ignoring_case(const StringView&) const;
     bool starts_with(const StringView&, CaseSensitivity = CaseSensitivity::CaseSensitive) const;

+ 12 - 12
AK/String.cpp

@@ -180,26 +180,26 @@ ByteBuffer String::to_byte_buffer() const
 }
 
 template<typename T>
-Optional<T> String::to_int() const
+Optional<T> String::to_int(TrimWhitespace trim_whitespace) const
 {
-    return StringUtils::convert_to_int<T>(view());
+    return StringUtils::convert_to_int<T>(view(), trim_whitespace);
 }
 
-template Optional<i8> String::to_int() const;
-template Optional<i16> String::to_int() const;
-template Optional<i32> String::to_int() const;
-template Optional<i64> String::to_int() const;
+template Optional<i8> String::to_int(TrimWhitespace) const;
+template Optional<i16> String::to_int(TrimWhitespace) const;
+template Optional<i32> String::to_int(TrimWhitespace) const;
+template Optional<i64> String::to_int(TrimWhitespace) const;
 
 template<typename T>
-Optional<T> String::to_uint() const
+Optional<T> String::to_uint(TrimWhitespace trim_whitespace) const
 {
-    return StringUtils::convert_to_uint<T>(view());
+    return StringUtils::convert_to_uint<T>(view(), trim_whitespace);
 }
 
-template Optional<u8> String::to_uint() const;
-template Optional<u16> String::to_uint() const;
-template Optional<u32> String::to_uint() const;
-template Optional<u64> String::to_uint() const;
+template Optional<u8> String::to_uint(TrimWhitespace) const;
+template Optional<u16> String::to_uint(TrimWhitespace) const;
+template Optional<u32> String::to_uint(TrimWhitespace) const;
+template Optional<u64> String::to_uint(TrimWhitespace) const;
 
 bool String::starts_with(const StringView& str, CaseSensitivity case_sensitivity) const
 {

+ 2 - 2
AK/String.h

@@ -112,9 +112,9 @@ public:
     [[nodiscard]] bool matches(const StringView& mask, Vector<MaskSpan>&, CaseSensitivity = CaseSensitivity::CaseInsensitive) const;
 
     template<typename T = int>
-    [[nodiscard]] Optional<T> to_int() const;
+    [[nodiscard]] Optional<T> to_int(TrimWhitespace = TrimWhitespace::Yes) const;
     template<typename T = unsigned>
-    [[nodiscard]] Optional<T> to_uint() const;
+    [[nodiscard]] Optional<T> to_uint(TrimWhitespace = TrimWhitespace::Yes) const;
 
     [[nodiscard]] String to_lowercase() const;
     [[nodiscard]] String to_uppercase() const;

+ 36 - 30
AK/StringUtils.cpp

@@ -86,18 +86,20 @@ bool matches(const StringView& str, const StringView& mask, CaseSensitivity case
 }
 
 template<typename T>
-Optional<T> convert_to_int(const StringView& str)
+Optional<T> convert_to_int(const StringView& str, TrimWhitespace trim_whitespace)
 {
-    auto str_trimmed = str.trim_whitespace();
-    if (str_trimmed.is_empty())
+    auto string = trim_whitespace == TrimWhitespace::Yes
+        ? str.trim_whitespace()
+        : str;
+    if (string.is_empty())
         return {};
 
     T sign = 1;
     size_t i = 0;
-    const auto characters = str_trimmed.characters_without_null_termination();
+    const auto characters = string.characters_without_null_termination();
 
     if (characters[0] == '-' || characters[0] == '+') {
-        if (str_trimmed.length() == 1)
+        if (string.length() == 1)
             return {};
         i++;
         if (characters[0] == '-')
@@ -105,7 +107,7 @@ Optional<T> convert_to_int(const StringView& str)
     }
 
     T value = 0;
-    for (; i < str_trimmed.length(); i++) {
+    for (; i < string.length(); i++) {
         if (characters[i] < '0' || characters[i] > '9')
             return {};
 
@@ -118,22 +120,24 @@ Optional<T> convert_to_int(const StringView& str)
     return value;
 }
 
-template Optional<i8> convert_to_int(const StringView& str);
-template Optional<i16> convert_to_int(const StringView& str);
-template Optional<i32> convert_to_int(const StringView& str);
-template Optional<i64> convert_to_int(const StringView& str);
+template Optional<i8> convert_to_int(const StringView& str, TrimWhitespace);
+template Optional<i16> convert_to_int(const StringView& str, TrimWhitespace);
+template Optional<i32> convert_to_int(const StringView& str, TrimWhitespace);
+template Optional<i64> convert_to_int(const StringView& str, TrimWhitespace);
 
 template<typename T>
-Optional<T> convert_to_uint(const StringView& str)
+Optional<T> convert_to_uint(const StringView& str, TrimWhitespace trim_whitespace)
 {
-    auto str_trimmed = str.trim_whitespace();
-    if (str_trimmed.is_empty())
+    auto string = trim_whitespace == TrimWhitespace::Yes
+        ? str.trim_whitespace()
+        : str;
+    if (string.is_empty())
         return {};
 
     T value = 0;
-    const auto characters = str_trimmed.characters_without_null_termination();
+    const auto characters = string.characters_without_null_termination();
 
-    for (size_t i = 0; i < str_trimmed.length(); i++) {
+    for (size_t i = 0; i < string.length(); i++) {
         if (characters[i] < '0' || characters[i] > '9')
             return {};
 
@@ -146,26 +150,28 @@ Optional<T> convert_to_uint(const StringView& str)
     return value;
 }
 
-template Optional<u8> convert_to_uint(const StringView& str);
-template Optional<u16> convert_to_uint(const StringView& str);
-template Optional<u32> convert_to_uint(const StringView& str);
-template Optional<u64> convert_to_uint(const StringView& str);
-template Optional<long> convert_to_uint(const StringView& str);
-template Optional<long long> convert_to_uint(const StringView& str);
+template Optional<u8> convert_to_uint(const StringView& str, TrimWhitespace);
+template Optional<u16> convert_to_uint(const StringView& str, TrimWhitespace);
+template Optional<u32> convert_to_uint(const StringView& str, TrimWhitespace);
+template Optional<u64> convert_to_uint(const StringView& str, TrimWhitespace);
+template Optional<long> convert_to_uint(const StringView& str, TrimWhitespace);
+template Optional<long long> convert_to_uint(const StringView& str, TrimWhitespace);
 
 template<typename T>
-Optional<T> convert_to_uint_from_hex(const StringView& str)
+Optional<T> convert_to_uint_from_hex(const StringView& str, TrimWhitespace trim_whitespace)
 {
-    auto str_trimmed = str.trim_whitespace();
-    if (str_trimmed.is_empty())
+    auto string = trim_whitespace == TrimWhitespace::Yes
+        ? str.trim_whitespace()
+        : str;
+    if (string.is_empty())
         return {};
 
     T value = 0;
-    const auto count = str_trimmed.length();
+    const auto count = string.length();
     const T upper_bound = NumericLimits<T>::max();
 
     for (size_t i = 0; i < count; i++) {
-        char digit = str_trimmed[i];
+        char digit = string[i];
         u8 digit_val;
         if (value > (upper_bound >> 4))
             return {};
@@ -185,10 +191,10 @@ Optional<T> convert_to_uint_from_hex(const StringView& str)
     return value;
 }
 
-template Optional<u8> convert_to_uint_from_hex(const StringView& str);
-template Optional<u16> convert_to_uint_from_hex(const StringView& str);
-template Optional<u32> convert_to_uint_from_hex(const StringView& str);
-template Optional<u64> convert_to_uint_from_hex(const StringView& str);
+template Optional<u8> convert_to_uint_from_hex(const StringView& str, TrimWhitespace);
+template Optional<u16> convert_to_uint_from_hex(const StringView& str, TrimWhitespace);
+template Optional<u32> convert_to_uint_from_hex(const StringView& str, TrimWhitespace);
+template Optional<u64> convert_to_uint_from_hex(const StringView& str, TrimWhitespace);
 
 static inline char to_lowercase(char c)
 {

+ 9 - 3
AK/StringUtils.h

@@ -22,6 +22,11 @@ enum class TrimMode {
     Both
 };
 
+enum class TrimWhitespace {
+    Yes,
+    No,
+};
+
 struct MaskSpan {
     size_t start;
     size_t length;
@@ -40,11 +45,11 @@ namespace StringUtils {
 
 bool matches(const StringView& str, const StringView& mask, CaseSensitivity = CaseSensitivity::CaseInsensitive, Vector<MaskSpan>* match_spans = nullptr);
 template<typename T = int>
-Optional<T> convert_to_int(const StringView&);
+Optional<T> convert_to_int(const StringView&, TrimWhitespace = TrimWhitespace::Yes);
 template<typename T = unsigned>
-Optional<T> convert_to_uint(const StringView&);
+Optional<T> convert_to_uint(const StringView&, TrimWhitespace = TrimWhitespace::Yes);
 template<typename T = unsigned>
-Optional<T> convert_to_uint_from_hex(const StringView&);
+Optional<T> convert_to_uint_from_hex(const StringView&, TrimWhitespace = TrimWhitespace::Yes);
 bool equals_ignoring_case(const StringView&, const StringView&);
 bool ends_with(const StringView& a, const StringView& b, CaseSensitivity);
 bool starts_with(const StringView&, const StringView&, CaseSensitivity);
@@ -61,3 +66,4 @@ String to_snakecase(const StringView&);
 
 using AK::CaseSensitivity;
 using AK::TrimMode;
+using AK::TrimWhitespace;