diff --git a/common/estring.cpp b/common/estring.cpp index 2498c14d..54166380 100644 --- a/common/estring.cpp +++ b/common/estring.cpp @@ -55,36 +55,39 @@ size_t estring_view::find_last_not_of(const charset& set) const bool estring_view::to_uint64_check(uint64_t* v) const { - uint64_t val = 0; - for (unsigned char c : *this) { + if (this->empty()) return false; + uint64_t val = (*this)[0] - '0'; + if (val > 9) return false; + for (unsigned char c : this->substr(1)) { c -= '0'; - if (c > 9) - return false; + if (c > 9) break; val = val * 10 + c; } if (v) *v = val; return true; } -uint64_t estring_view::hex_to_uint64() const { - uint64_t ret = 0; - for (unsigned char c : *this) { - unsigned char cc = c - '0'; - if (cc < 10) { - ret = ret * 16 + cc; - } else { - 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 - } - } +inline char hex_char_to_digit(char c) { + unsigned char cc = c - '0'; + if (cc < 10) return cc; + const unsigned char mask = 'a' - 'A'; + static_assert(mask == 32, "..."); // single digit + c |= mask; // unified to 'a'..'f' + cc = c - 'a'; + return (cc < 6) ? (cc + 10) : -1; +} + +bool estring_view::hex_to_uint64_check(uint64_t* v) const { + if (this->empty()) return false; + uint64_t val = hex_char_to_digit((*this)[0]); + if (val == -1ul) return false; + for (unsigned char c : this->substr(1)) { + auto d = hex_char_to_digit(c); + if (d == -1) break; + val = val * 16 + d; } - return ret; + if (v) *v = val; + return true; } estring& estring::append(uint64_t x) diff --git a/common/estring.h b/common/estring.h index 50d1024a..cdd90af7 100644 --- a/common/estring.h +++ b/common/estring.h @@ -318,8 +318,13 @@ class estring_view : public std::string_view double val; return to_double_check(&val) ? val : default_val; } - // do not support 0x/0X prefix - uint64_t hex_to_uint64() const; + // not including 0x/0X prefix + bool hex_to_uint64_check(uint64_t* v = nullptr) const; + uint64_t hex_to_uint64(uint64_t default_val = 0) const + { + uint64_t val; + return hex_to_uint64_check(&val) ? val : default_val; + } }; inline bool operator == (const std::string_view& sv, const std::string& s) diff --git a/net/http/message.cpp b/net/http/message.cpp index 82ffbd22..481c059f 100644 --- a/net/http/message.cpp +++ b/net/http/message.cpp @@ -368,7 +368,7 @@ int Response::parse_status_line(Parser &p) { p.skip_chars(' '); auto code = p.extract_integer(); if (code <= 0 || code >= 1000) - LOG_ERROR_RETURN(0, -1, "invalid status code"); + LOG_ERROR_RETURN(0, -1, "invalid status code ", code); m_status_code = (uint16_t)code; p.skip_chars(' '); m_status_message = p.extract_until_char('\r'); diff --git a/net/http/test/client_function_test.cpp b/net/http/test/client_function_test.cpp index 7af2d2df..062f34c0 100644 --- a/net/http/test/client_function_test.cpp +++ b/net/http/test/client_function_test.cpp @@ -413,9 +413,9 @@ TEST(http_client, debug) { server->setsockopt(SOL_SOCKET, SO_REUSEPORT, 1); server->set_handler({nullptr, &chunked_handler_debug}); auto ret = server->bind(ep.port, ep.addr); - if (ret < 0) LOG_ERROR(VALUE(errno)); + if (ret < 0) LOG_ERROR(ERRNO()); ret |= server->listen(100); - if (ret < 0) LOG_ERROR(VALUE(errno)); + if (ret < 0) LOG_ERROR(ERRNO()); EXPECT_EQ(0, ret); LOG_INFO("Ready to accept"); server->start_loop(); @@ -438,13 +438,13 @@ TEST(http_client, debug) { memset((void*)buf.data(), '0', std_data_size); ret = op_test->resp.read((void*)buf.data(), std_data_size); EXPECT_EQ(std_data_size, ret); - EXPECT_EQ(true, buf == std_data); + EXPECT_TRUE(buf == std_data); for (int i = 0; i < buf.size(); i++) { if (buf[i] != std_data[i]) { - std::cout << i << std::endl; + LOG_ERROR("first occurrence of difference at: ", i); + break; } } - std::cout << "new" << std::endl; } int sleep_handler(void*, ISocketStream* sock) { photon::thread_sleep(3); diff --git a/net/utils.cpp b/net/utils.cpp index e1de9661..82985ffb 100644 --- a/net/utils.cpp +++ b/net/utils.cpp @@ -101,22 +101,25 @@ int _gethostbyname(const char* name, Delegate append_op) { return idx; } -inline __attribute__((always_inline)) void base64_translate_3to4(const char *in, char *out) { - struct xlator { - unsigned char _; - unsigned char a : 6; - unsigned char b : 6; - unsigned char c : 6; - unsigned char d : 6; - } __attribute__((packed)); - static_assert(sizeof(xlator) == 4, "..."); +struct xlator { + unsigned char _; + unsigned char a : 6; + unsigned char b : 6; + unsigned char c : 6; + unsigned char d : 6; +} __attribute__((packed)); +static_assert(sizeof(xlator) == 4, "..."); + +inline __attribute__((always_inline)) +void base64_translate_3to4(const char *in, char *out) { static const unsigned char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; auto v = htonl(*(uint32_t *)in); - auto x = *(xlator *)(&v); - *(uint32_t *)out = ((tbl[x.a] << 24) + (tbl[x.b] << 16) + - (tbl[x.c] << 8) + (tbl[x.d] << 0)); + auto x = (xlator*) &v; + *(uint32_t *)out = ((tbl[x->a] << 24) + (tbl[x->b] << 16) + + (tbl[x->c] << 8) + (tbl[x->d] << 0)); } + void Base64Encode(std::string_view in, std::string &out) { auto main = in.size() / 3; auto remain = in.size() % 3; @@ -137,7 +140,6 @@ void Base64Encode(std::string_view in, std::string &out) { base64_translate_3to4(_in + 9, _out + 12); } - for (; _in < end; _in += 3, _out += 4) { base64_translate_3to4(_in, _out); } @@ -191,16 +193,8 @@ static unsigned char get_index_of(char val, bool &ok) { } #undef EI +inline bool base64_translate_4to3(const char *in, char *out) { - struct xlator { - unsigned char _; - unsigned char a : 6; - unsigned char b : 6; - unsigned char c : 6; - unsigned char d : 6; - } __attribute__((packed)); - static_assert(sizeof(xlator) == 4, "..."); - xlator v; bool f1, f2, f3, f4; v.a = get_index_of(*(in+3), f1); @@ -208,10 +202,10 @@ bool base64_translate_4to3(const char *in, char *out) { v.c = get_index_of(*(in+1), f3); v.d = get_index_of(*(in), f4); - *(uint32_t *)out = ntohl(*(uint32_t *)&v); return (f1 && f2 && f3 && f4); } + bool Base64Decode(std::string_view in, std::string &out) { #define GSIZE 4 //Size of each group auto in_size = in.size();