Просмотр исходного кода

Introduce TryFromString returning TMaybe

Позволяем писать без неиницилизированных переменных по месту использования.

Вот такую красоту например:

```
if (auto a = TryFromString<T>(str)) {
    что-то делаем с \*a
}
```
evelkin 2 лет назад
Родитель
Сommit
dd2db1bb6a
2 измененных файлов с 59 добавлено и 2 удалено
  1. 31 0
      util/string/cast.h
  2. 28 2
      util/string/cast_ut.cpp

+ 31 - 0
util/string/cast.h

@@ -2,6 +2,7 @@
 
 #include <util/system/defaults.h>
 #include <util/stream/str.h>
+#include <util/generic/maybe.h>
 #include <util/generic/string.h>
 #include <util/generic/strbuf.h>
 #include <util/generic/typetraits.h>
@@ -270,6 +271,36 @@ inline bool TryFromString(const TUtf16String& s, T& result) {
     return TryFromString<T>(s.data(), s.size(), result);
 }
 
+template <class T, class TChar>
+inline TMaybe<T> TryFromString(TBasicStringBuf<TChar> s) {
+    TMaybe<T> result{NMaybe::TInPlace{}};
+    if (!TryFromString<T>(s, *result)) {
+        result.Clear();
+    }
+
+    return result;
+}
+
+template <class T, class TChar>
+inline TMaybe<T> TryFromString(const TChar* data) {
+    return TryFromString<T>(TBasicStringBuf<TChar>(data));
+}
+
+template <class T>
+inline TMaybe<T> TryFromString(const TString& s) {
+    return TryFromString<T>(TStringBuf(s));
+}
+
+template <class T>
+inline TMaybe<T> TryFromString(const std::string& s) {
+    return TryFromString<T>(TStringBuf(s));
+}
+
+template <class T>
+inline TMaybe<T> TryFromString(const TUtf16String& s) {
+    return TryFromString<T>(TWtringBuf(s));
+}
+
 template <class T, class TStringType>
 inline bool TryFromStringWithDefault(const TStringType& s, T& result, const T& def) {
     return TryFromString<T>(s.data(), s.size(), result, def);

+ 28 - 2
util/string/cast_ut.cpp

@@ -300,8 +300,8 @@ Y_UNIT_TEST_SUITE(TCastTest) {
         BadFloatTester<float>("a10E-5");
         BadFloatTester<float>("10 ");
         BadFloatTester<float>("10\t");
-        //BadFloatTester<float>("10E");
-        //BadFloatTester<float>("10.E");
+        // BadFloatTester<float>("10E");
+        // BadFloatTester<float>("10.E");
         BadFloatTester<float>("..0");
         BadFloatTester<float>(""); // IGNIETFERRO-300
         BadFloatTester<double>("1.00.01");
@@ -437,6 +437,32 @@ Y_UNIT_TEST_SUITE(TCastTest) {
         UNIT_ASSERT_VALUES_EQUAL(FromStringWithDefault<size_t>(s4), size_t());
     }
 
+    Y_UNIT_TEST(TestMaybe) {
+        TMaybe<int> res;
+
+        TString s1("100500");
+        UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s1), yexception);
+        UNIT_ASSERT_VALUES_EQUAL(res, 100500);
+
+        UNIT_ASSERT_VALUES_EQUAL(TryFromString<int>("100500"), 100500);
+
+        TString s2("100q500");
+        UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s2), yexception);
+        UNIT_ASSERT(res.Empty());
+
+        TUtf16String s3 = u"-100500";
+        UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<size_t>(s3), yexception);
+        UNIT_ASSERT(res.Empty());
+
+        TUtf16String s4 = u"-f100500";
+        UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s4), yexception);
+        UNIT_ASSERT(res.Empty());
+
+        std::string s5 = "100500";
+        UNIT_CHECK_GENERATED_NO_EXCEPTION(res = TryFromString<int>(s5), yexception);
+        UNIT_ASSERT_VALUES_EQUAL(res, 100500);
+    }
+
     Y_UNIT_TEST(TestBool) {
         // True cases
         UNIT_ASSERT_VALUES_EQUAL(FromString<bool>("yes"), true);