diff --git a/common/estring.cpp b/common/estring.cpp index 6822f891..f16fc12e 100644 --- a/common/estring.cpp +++ b/common/estring.cpp @@ -55,12 +55,14 @@ size_t estring_view::find_last_not_of(const charset& set) const bool estring_view::to_uint64_check(uint64_t* v) const { - v ? (*v = 0) : 0; + uint64_t val = 0; for (unsigned char c : *this) { - if (c > '9' || c < '0') + c -= '0'; + if (c > 9) return false; - v ? (*v = *v * 10 + (c - '0')) : 0; + val = val * 10 + c; } + if (v) *v = val; return true; } @@ -68,14 +70,19 @@ uint64_t estring_view::hex_to_uint64() const { uint64_t ret = 0; for (unsigned char c : *this) { - if (c >= '0' && c <= '9') { - ret = ret * 16 + (c - '0'); - } else if (c >= 'A' && c <= 'F') { - ret = ret * 16 + (c - 'A' + 10); - } else if (c >= 'a' && c <= 'f') { - ret = ret * 16 + (c - 'a' + 10); + unsigned char cc = c - '0'; + if (c < 10) { + ret = ret * 16 + cc; } else { - return ret; + const unsigned char mask = 'a' - 'A'; + static_assert(mask == 32, "..."); // single digit + c |= mask; // unified to 'a'..'f' + cc = c - 'a'; + if (cc < 6) { + ret = ret * 16 + cc + 10; + } else { + break; // invalid char + } } } return ret; diff --git a/common/estring.h b/common/estring.h index 9e57214f..a51bb5f1 100644 --- a/common/estring.h +++ b/common/estring.h @@ -18,6 +18,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -289,8 +290,33 @@ class estring_view : public std::string_view uint64_t to_uint64(uint64_t default_val = 0) const { uint64_t val; - to_uint64_check(&val); - return val; + return to_uint64_check(&val) ? val : default_val; + } + bool to_int64_check(int64_t* v = nullptr) const + { + if (this->empty()) return false; + if (this->front() != '-') return to_uint64_check((uint64_t*)v); + bool ret = this->substr(1).to_uint64_check((uint64_t*)v); + if (ret) *v = -*v; + return ret; + } + int64_t to_int64(int64_t default_val = 0) const + { + int64_t val; + return to_int64_check(&val) ? val : default_val; + } + bool to_double_check(double* v = nullptr) + { + char buf[32]; + auto len = std::max(this->size(), sizeof(buf) - 1 ); + memcpy(buf, data(), len); + buf[len] = '0'; + return sscanf("%f", buf, v) == 1; + } + double to_double(double default_val = NAN) + { + double val; + return to_double_check(&val) ? val : default_val; } // do not support 0x/0X prefix uint64_t hex_to_uint64() const; @@ -312,8 +338,8 @@ class rstring_view // relative string_view, that stores values relative protected: static_assert(std::is_integral::value, "..."); static_assert(std::is_integral::value, "..."); - OffsetType _offset; - LengthType _length; + OffsetType _offset = 0; + LengthType _length = 0; estring_view to_abs(const char* s) const { diff --git a/net/http/message.cpp b/net/http/message.cpp index ab8e3179..82ffbd22 100644 --- a/net/http/message.cpp +++ b/net/http/message.cpp @@ -331,7 +331,7 @@ int Request::redirect(Verb v, estring_view location, bool enable_proxy) { } StoredURL u(location); auto new_request_line_size = verbstr[v].size() + sizeof(" HTTP/1.1\r\n") + - enable_proxy ? full_url_size(u) : u.target().size(); + (enable_proxy ? full_url_size(u) : u.target().size()); auto delta = new_request_line_size - m_buf_size; LOG_DEBUG(VALUE(delta));