Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: compiled/String.h

Issue 29714586: Noissue - implement a couple of common lexical_cast cases. (Closed) Base URL: github.com:adblockplus/adblockpluscore
Patch Set: address comment Created March 6, 2018, 10:35 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/compiled/String.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: compiled/String.h
diff --git a/compiled/String.h b/compiled/String.h
index 3ea7a6782322147a84e5f0da8752910017285167..85f3e244604a064423f488ca9bfb2e1d2120043f 100644
--- a/compiled/String.h
+++ b/compiled/String.h
@@ -26,6 +26,7 @@
#include <codecvt>
#endif
#include <utility>
+#include <limits>
#include "base.h"
#include "debug.h"
@@ -457,6 +458,78 @@ inline std::ostream& operator<<(std::ostream& os, const OwnedString& str)
}
#endif
+template<typename T>
+struct LexicalCastImpl;
+
+/// Performs common conversions of a text represented value.
+template<typename T>
+inline T lexical_cast(const String& value)
+{
+ return LexicalCastImpl<T>::Convert(value);
+}
+
+template<>
+struct LexicalCastImpl<bool>
+{
+ static bool Convert(const String& value)
+ {
+ return value == u"true"_str;
+ }
+};
+
+template<typename T>
+struct LexicalCastImpl
+{
+ static_assert(std::is_integral<T>::value, "T should be a number");
+ static T Convert(const String& value)
+ {
+ String::size_type len = value.length();
+ if (len == 0)
+ return 0;
+ String::size_type pos = 0;
+ bool negative = std::numeric_limits<T>::is_signed && value[0] == u'-';
+ if (negative)
+ {
+ ++pos;
+ }
+ T result = 0;
+ for (; pos < len; ++pos)
+ {
+ auto c = value[pos];
+ if (c < u'0' || c > u'9')
+ return 0;
+ // isDangerous is the optimization because there is no need for some checks
+ // when the values are far from edge cases.
+ // It targets the normal values, when a value is prefixed with several
+ // zeros additional checks start to work earlier than the actual value of
+ // result reaches an edge case, but it does not affect the result.
+ bool isDangerous = pos >= std::numeric_limits<T>::digits10;
hub 2018/03/06 14:45:53 this check on the number of digits could also be d
sergei 2018/03/06 15:41:32 This condition is satisfied but from a different p
hub 2018/03/06 15:56:45 Acknowledged.
+ // It also invalidates the parsing of too big numbers in comparison with
+ // stopping when it encounters a non numerical character.
+ // cast<uint8_t>(u"1230"_str) -> 0
+ // cast<uint8_t>(u"123E"_str) -> 123
+ if (isDangerous && std::numeric_limits<T>::max() / 10 < result)
+ {
+ return 0;
+ }
+ result *= 10;
+ uint8_t digit = c - u'0';
+ if (isDangerous && (std::numeric_limits<T>::max() - digit < result - (negative ? 1 : 0)))
+ {
+ return 0;
+ }
+ result += digit;
+ }
+ return negative ? -result : result;
+ }
+};
+
+template<>
+inline OwnedString lexical_cast<OwnedString>(const String& value)
+{
+ return OwnedString{value};
+}
+
DependentString TrimSpaces(const String& value);
// Splits the `value` string into two `DependentString`s excluding the character staying at `separatorPos`.
« no previous file with comments | « no previous file | test/compiled/String.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld