diff --git a/src/misc/base64.h b/src/misc/base64.h index 9697b31..fa60d02 100644 --- a/src/misc/base64.h +++ b/src/misc/base64.h @@ -17,7 +17,8 @@ namespace base64 { * @param input The input string to Base64-encode * @return A Base64-encoded version of the encoded string */ - inline std::string encode(const std::string& input) { return encode(input.c_str(), (unsigned long) input.size()); } + inline std::string encode(const std::string& input) { return encode(input.data(), (unsigned long) input.size()); } + inline std::string encode(const std::string_view& input) { return encode(input.data(), input.size()); } /** @@ -32,7 +33,8 @@ namespace base64 { * @param input The input string to decode * @return A string (binary) that represents the Base64-decoded data of the input */ - inline std::string decode(const std::string& input) { return decode(input.c_str(), input.size()); } + inline std::string decode(const std::string& input) { return decode(input.data(), input.size()); } + inline std::string decode(const std::string_view& input) { return decode(input.data(), input.size()); } //A–Z, a–z, 0–9, + und / inline bool validate(const std::string& input) { diff --git a/src/misc/digest.h b/src/misc/digest.h index 919f715..c5a90aa 100644 --- a/src/misc/digest.h +++ b/src/misc/digest.h @@ -39,18 +39,22 @@ #include #define DECLARE_DIGEST(name, method, digestLength) \ - inline std::string name(const std::string& input) { \ + inline std::string name(const std::string_view& input) { \ u_char buffer[digestLength]; \ method((u_char*) input.data(), input.length(), buffer); \ - return std::string((const char*) buffer, (size_t) digestLength); \ + return std::string{(const char*) buffer, (size_t) digestLength}; \ + } \ + \ + inline std::string name(const std::string& input) { \ + return name(std::string_view{input}); \ } \ \ inline std::string name(const char* input, ssize_t length = -1) { \ if(length == -1) length = strlen(input); \ - return name(std::string(input, (size_t) length)); \ + return name(std::string_view{input, (size_t) length}); \ } \ - \ - inline void name(const char* input, size_t length, uint8_t* result) { \ + \ + inline void name(const char* input, size_t length, uint8_t* result) { \ method((u_char*) input, length, result); \ } #endif diff --git a/src/protocol/PacketLossCalculator.cpp b/src/protocol/PacketLossCalculator.cpp index 6a1907a..545523f 100644 --- a/src/protocol/PacketLossCalculator.cpp +++ b/src/protocol/PacketLossCalculator.cpp @@ -80,7 +80,7 @@ void UnorderedPacketLossCalculator::reset_offsets() { void CommandPacketLossCalculator::packet_send(uint32_t packet_id) { if(packet_id > this->packet_history_offset) { - assert(packet_id - 1 == this->packet_history_offset); /* the method will only be called with an incrementing packet id */ + assert(packet_id - 1 == this->packet_history_offset || this->packet_history_offset == 0); /* the method will only be called with an incrementing packet id */ /* newly send packet */ auto lost = std::exchange(this->packet_ack_counts[packet_id % CommandPacketLossCalculator::packet_ack_counts_length], 1); this->lost_packets_ += lost; diff --git a/src/query/command3.cpp b/src/query/command3.cpp index e249b15..055be17 100644 --- a/src/query/command3.cpp +++ b/src/query/command3.cpp @@ -7,17 +7,14 @@ using namespace ts; -command_bulk command_parser::empty_bulk{std::string::npos, 0, ""}; - bool command_parser::parse(bool command) { - this->data = this->_command_memory; - this->index = std::string::npos; + this->bulk_index = std::string::npos; size_t index{0}, findex; if(command) { - index = this->_command_memory.find(' ', index); + index = this->data.find(' ', index); if(index == std::string::npos) { - this->command_type = this->_command_memory; + this->command_type = this->data; return true; } else { this->command_type = this->data.substr(0, index); @@ -26,11 +23,10 @@ bool command_parser::parse(bool command) { index++; } - this->_bulks.reserve(4); - while(index < this->_command_memory.size()) { - findex = this->_command_memory.find('|', index); + while(index < this->data.size()) { + findex = this->data.find('|', index); if(findex == std::string::npos) - findex = this->_command_memory.size(); + findex = this->data.size(); this->_bulks.emplace_back(this->_bulks.size() - 1, index, this->data.substr(index, findex - index)); index = findex + 1; @@ -38,6 +34,14 @@ bool command_parser::parse(bool command) { return true; } +std::string_view command_parser::payload_view(size_t bulk_index) const noexcept { + if(bulk_index >= this->bulk_count()) + return {}; + + auto bulk = this->bulk(bulk_index); + return this->data.substr(bulk.command_character_index()); +} + std::optional command_parser::next_bulk_containing(const std::string_view &key, size_t start) const { if(start >= this->bulk_count()) return std::nullopt; diff --git a/src/query/command3.h b/src/query/command3.h index 60dc6da..ce96e75 100644 --- a/src/query/command3.h +++ b/src/query/command3.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ namespace ts { [[nodiscard]] inline std::string_view value_raw(const std::string_view& key) const { bool tmp; auto result = this->value_raw(key, tmp); - if(!tmp) throw command_value_missing_exception{index, std::string{key}}; + if(!tmp) throw command_value_missing_exception{this->bulk_index, std::string{key}}; return result; } @@ -88,7 +89,12 @@ namespace ts { static_assert(converter::supported, "Target type isn't supported!"); static_assert(!converter::supported || converter::from_string_view, "Target type dosn't support parsing"); - return converter::from_string_view(this->value(key)); + auto value = this->value(key); + try { + return converter::from_string_view(value); + } catch (std::exception& ex) { + throw command_value_cast_failed{this->key_command_character_index(key), std::string{key}, value, typeid(T)}; + } } [[nodiscard]] inline size_t command_character_index() const { return this->abs_index; } @@ -98,10 +104,10 @@ namespace ts { return this->abs_index + begin; } protected: - command_string_parser(size_t index, size_t abs_index, std::string_view data) : index{index}, abs_index{abs_index}, data{data} {} + command_string_parser(size_t bulk_index, size_t abs_index, std::string_view data) : bulk_index{bulk_index}, abs_index{abs_index}, data{data} {} size_t abs_index{}; - size_t index{}; + size_t bulk_index{}; std::string_view data{}; }; } @@ -148,8 +154,10 @@ namespace ts { [[nodiscard]] inline const std::string_view& identifier() const noexcept { return this->command_type; } [[nodiscard]] inline size_t bulk_count() const noexcept { return this->_bulks.size(); } - [[nodiscard]] inline const command_bulk& bulk(size_t index) const noexcept { - if(this->_bulks.size() <= index) return empty_bulk; + [[nodiscard]] inline const command_bulk& bulk(size_t index) const { + if(this->_bulks.size() <= index) + throw command_bulk_index_out_of_bounds_exception{index}; + return this->_bulks[index]; } @@ -184,15 +192,14 @@ namespace ts { } while(true); } - [[nodiscard]] const std::vector& bulks() const { return this->_bulks; } + [[nodiscard]] const std::deque& bulks() const { return this->_bulks; } + [[nodiscard]] std::string_view payload_view(size_t bulk_index) const noexcept; [[nodiscard]] std::optional next_bulk_containing(const std::string_view& /* key */, size_t /* bulk offset */) const; private: - static command_bulk empty_bulk; - const std::string _command_memory{}; std::string_view command_type{}; - std::vector _bulks{}; + std::deque _bulks{}; }; class command_builder_bulk { diff --git a/src/query/command_exception.h b/src/query/command_exception.h index 6aa8434..f29a1a4 100644 --- a/src/query/command_exception.h +++ b/src/query/command_exception.h @@ -1,26 +1,51 @@ #pragma once +#include + namespace ts { class command_exception : public std::exception {}; - class command_casted_exception : public command_exception { }; - class command_cannot_uncast_exception : public command_exception { }; - class command_bulk_exceed_index_exception : public command_exception { }; + class command_bulk_index_out_of_bounds_exception : public command_exception { + public: + explicit command_bulk_index_out_of_bounds_exception(size_t index) : _index(index) { } + + [[nodiscard]] inline size_t index() const { return this->_index; } + private: + size_t _index; + }; + class command_value_missing_exception : public command_exception { public: command_value_missing_exception(size_t index, std::string key) : _index(index), _key(move(key)) { } - inline size_t index() const { return this->_index; } - inline std::string key() const { return this->_key; } + [[nodiscard]] inline size_t bulk_index() const { return this->_index; } + [[nodiscard]] inline std::string key() const { return this->_key; } private: size_t _index; std::string _key; }; + class command_malformed_exception : public command_exception { public: - command_malformed_exception(size_t index) : _index(index) {} - inline size_t index() const { return this->_index; } + explicit command_malformed_exception(size_t index) : _index(index) {} + [[nodiscard]] inline size_t index() const { return this->_index; } private: size_t _index; }; + + class command_value_cast_failed : public command_exception { + public: + command_value_cast_failed(size_t index, std::string key, std::string value, const std::type_info& target_type) + : index_{index}, key_{std::move(key)}, value_{std::move(value)}, target_type_{target_type} {} + + [[nodiscard]] inline size_t index() const { return this->index_; } + [[nodiscard]] inline const std::string& key() const { return this->key_; } + [[nodiscard]] inline const std::string& value() const { return this->value_; } + [[nodiscard]] inline const std::type_info& target_type() const { return this->target_type_; } + private: + size_t index_; + std::string key_; + std::string value_; + const std::type_info& target_type_; + }; } \ No newline at end of file diff --git a/src/sql/insert.h b/src/sql/insert.h index b154d2a..714d3c4 100644 --- a/src/sql/insert.h +++ b/src/sql/insert.h @@ -49,6 +49,7 @@ namespace sql { else result += "OR IGNORE "; } + result += "INTO "; result += this->table_name + " ("; //"INSERT INTO " + this->table_name + " ("