From 273bb80abfe378654d6f3f2b7a1eeaab2549faaf Mon Sep 17 00:00:00 2001 From: Jessica James Date: Thu, 2 Dec 2021 00:09:26 -0600 Subject: [PATCH] Removed shiftLeft/shiftRight; Fixed a bug in parsing IRC modes; refactored INI file parsing slightly --- src/common/Config.cpp | 46 ++++--------- src/common/INIConfig.cpp | 89 ++++++++++++-------------- src/common/IRC_Client.cpp | 9 +-- src/common/Socket.cpp | 4 ++ src/include/Jupiter/Config.h | 19 ------ src/include/Jupiter/Readable_String.h | 3 +- src/include/Jupiter/Shift_String.h | 16 ----- src/include/Jupiter/Shift_String_Imp.h | 27 ++------ src/include/Jupiter/Socket.h | 32 ++++----- 9 files changed, 82 insertions(+), 163 deletions(-) diff --git a/src/common/Config.cpp b/src/common/Config.cpp index 6248df5..c0a246d 100644 --- a/src/common/Config.cpp +++ b/src/common/Config.cpp @@ -29,8 +29,7 @@ Jupiter::Config& Jupiter::Config::operator=(const Config& in_config) { return *this; } -std::string_view Jupiter::Config::get(std::string_view in_key, std::string_view in_default_value) const -{ +std::string_view Jupiter::Config::get(std::string_view in_key, std::string_view in_default_value) const { auto value = m_table.find(JUPITER_WRAP_CONFIG_KEY(in_key)); if (value != m_table.end()) { return value->second; @@ -39,8 +38,7 @@ std::string_view Jupiter::Config::get(std::string_view in_key, std::string_view return in_default_value; } -Jupiter::Config *Jupiter::Config::getSection(std::string_view in_key) const -{ +Jupiter::Config *Jupiter::Config::getSection(std::string_view in_key) const { if (m_sections != nullptr) { auto section = m_sections->find(JUPITER_WRAP_CONFIG_KEY(in_key)); if (section != m_sections->end()) { @@ -51,8 +49,7 @@ Jupiter::Config *Jupiter::Config::getSection(std::string_view in_key) const return nullptr; } -Jupiter::Config &Jupiter::Config::getSectionReference(std::string_view in_key) -{ +Jupiter::Config &Jupiter::Config::getSectionReference(std::string_view in_key) { if (m_sections == nullptr) { m_sections = std::make_unique(); } @@ -117,35 +114,29 @@ bool Jupiter::Config::read(std::string_view in_filename) { return this->read_internal(m_name.c_str()); } -bool Jupiter::Config::write() -{ +bool Jupiter::Config::write() { return this->write(m_name.c_str()); } -bool Jupiter::Config::write(const char *in_filename) -{ +bool Jupiter::Config::write(const char *in_filename) { return this->write_internal(in_filename); } -bool Jupiter::Config::write(std::string_view in_filename) -{ +bool Jupiter::Config::write(std::string_view in_filename) { return this->write(static_cast(in_filename).c_str()); } -bool Jupiter::Config::reload() -{ +bool Jupiter::Config::reload() { this->erase(); return this->read_internal(m_name.c_str()); } -bool Jupiter::Config::reload(const char *in_filename) -{ +bool Jupiter::Config::reload(const char *in_filename) { this->erase(); return this->read(in_filename); } -bool Jupiter::Config::reload(std::string_view in_filename) -{ +bool Jupiter::Config::reload(std::string_view in_filename) { this->erase(); return this->read(in_filename); } @@ -159,29 +150,16 @@ const Jupiter::Config::SectionHashTable &Jupiter::Config::getSections() const { } /** Operators */ -Jupiter::Config &Jupiter::Config::operator[](std::string_view in_key) -{ +Jupiter::Config &Jupiter::Config::operator[](std::string_view in_key) { return this->getSectionReference(in_key); } /** Private functions */ -bool Jupiter::Config::read_internal(const char *) -{ +bool Jupiter::Config::read_internal(const char *) { return false; } -bool Jupiter::Config::write_internal(const char *) -{ +bool Jupiter::Config::write_internal(const char *) { return false; } - -void Jupiter::Config::Buffer::set_length(size_t in_length) -{ - this->length = in_length; -} - -char *Jupiter::Config::Buffer::get_str() const -{ - return this->str; -} diff --git a/src/common/INIConfig.cpp b/src/common/INIConfig.cpp index f0532f3..62a308e 100644 --- a/src/common/INIConfig.cpp +++ b/src/common/INIConfig.cpp @@ -82,13 +82,10 @@ bool Jupiter::INIConfig::write_internal(const char *in_filename) } bool Jupiter::INIConfig::read_internal(const char *in_filename) { - std::string_view line; std::stack section_stack; - section_stack.push(this); - auto process_line = [&line, §ion_stack]() - { + auto process_line = [§ion_stack](std::string_view line) { const char *itr = line.data(); const char *end = itr + line.size(); // guaranteed to be greater than itr @@ -189,9 +186,9 @@ bool Jupiter::INIConfig::read_internal(const char *in_filename) { constexpr size_t READ_CHUNK_SIZE = 1024; size_t read_count = READ_CHUNK_SIZE; - Buffer buffer; - char *itr; - char *end; + char* line_head; + char* read_head; + char* read_end; // Open file FILE *file = fopen(in_filename, "rb"); @@ -199,63 +196,57 @@ bool Jupiter::INIConfig::read_internal(const char *in_filename) { if (file == nullptr) return false; - buffer.setBufferSize(READ_CHUNK_SIZE * 2); - // Parse file contents - while (read_count == READ_CHUNK_SIZE) - { - // Ensure the buffer has at least READ_CHUNK_SIZE space remaining - buffer.setBufferSize(buffer.size() + READ_CHUNK_SIZE); - + char buffer[READ_CHUNK_SIZE]; + std::string line; + do { // Read data from file to end of buffer - itr = buffer.get_str(); - read_count = fread(itr + buffer.size(), sizeof(char), READ_CHUNK_SIZE, file); - buffer.set_length(buffer.size() + read_count); - end = itr + buffer.size(); - - // Reset line - line = std::string_view(buffer.data(), 0); + read_head = buffer; + read_count = fread(buffer, sizeof(char), READ_CHUNK_SIZE, file); + read_end = read_head + read_count; + line_head = nullptr; // Parse buffer for lines - while (itr != end) - { + while (read_head != read_end) { // Check if the line is over - if (*itr == '\n' || *itr == '\r') - { - // Process line - line = std::string_view(buffer.data(), itr - buffer.data()); - if (!line.empty()) - process_line(); + if (*read_head == '\n' || *read_head == '\r') { + if (line_head == nullptr) { + // There's not any pending data; process a view from the line_head to here + process_line({ buffer, static_cast(read_head - buffer) }); + } + else { + // There's pending data; join these together and process it + line.append(line_head, read_head); + process_line(line); + line.clear(); + } // Keep iterating until next non-newline character - while (true) - { - ++itr; - - if (itr == end) - { - // No data remains to be parsed in buffer; erase buffer and break - buffer.clear(); - break; - } - - if (*itr != '\n' && *itr != '\r') - { + for (++read_head; read_head != read_end; ++read_head) { + if (*read_head != '\n' && *read_head != '\r') { // Shift buffer and break - buffer.shiftRight(itr - buffer.data()); + line_head = read_head; break; } } } - else - ++itr; + else { + ++read_head; + } } - } + + // We've processed the read buffer; push any pending line data to the line buffer + if (line_head == nullptr) { + // No newlines in the entire buffer; should be rare + line_head = buffer; + } + line.append(line_head, read_head); + } while (read_count == READ_CHUNK_SIZE); // Process data remaining in buffer as a line - line = std::string_view(buffer.data(), buffer.size()); - if (!line.empty()) - process_line(); + if (!line.empty()) { + process_line(line); + } // File has been successfully read, or an error occurred. fclose(file); diff --git a/src/common/IRC_Client.cpp b/src/common/IRC_Client.cpp index fa47997..032ff08 100644 --- a/src/common/IRC_Client.cpp +++ b/src/common/IRC_Client.cpp @@ -789,7 +789,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) { else if (jessilib::equalsi(command_token, "NOTICE"sv)) { std::string_view channel_name = getLineToken(2); if (!channel_name.empty()) { - size_t pos = line.find('!', 0); + size_t pos = line.find('!'); auto message = jessilib::split_once_view(line, ':').second; if (pos < line.find(' ')) { auto nick = line.substr(1, pos); @@ -964,11 +964,8 @@ int Jupiter::IRC::Client::process_line(std::string_view line) { if (!channel_name.empty()) { if (m_chan_types.find(channel_name[0]) != std::string::npos) { auto nick = getSender(line); - if (!nick.empty()) { - std::string_view mode_line = line.substr(std::min(line.find(' ', 2), line.size())); - if (!mode_line.empty()) { - mode_line.remove_prefix(1); - } + if (!nick.empty() && line_split.size() >= 4) { + std::string_view mode_line = line.substr(line_split[3].data() - line.data()); auto split_mode_line = jessilib::word_split_once_view(mode_line, ' '); std::string_view modes = split_mode_line.first; diff --git a/src/common/Socket.cpp b/src/common/Socket.cpp index c85696d..f7b16b4 100644 --- a/src/common/Socket.cpp +++ b/src/common/Socket.cpp @@ -65,6 +65,10 @@ size_t Jupiter::Socket::Buffer::capacity() const { return m_buffer_capacity; } +size_t Jupiter::Socket::Buffer::size() const { + return m_buffer_size; +} + void Jupiter::Socket::Buffer::reserve(size_t new_capacity) { if (capacity() == new_capacity // Skip when already this size || new_capacity == 0 // Don't allow empty buffers, results in 0 from recv diff --git a/src/include/Jupiter/Config.h b/src/include/Jupiter/Config.h index 302bac8..252b93d 100644 --- a/src/include/Jupiter/Config.h +++ b/src/include/Jupiter/Config.h @@ -217,25 +217,6 @@ namespace Jupiter /** Subscript operator */ Config &operator[](std::string_view in_key); - /** Used for low-level string operations */ - class Buffer : public Jupiter::StringL - { - public: - /** - * @brief Sets the length of the string - * - * @param in_length Length of the string - */ - void set_length(size_t in_length); - - /** - * @brief Returns a pointer to the underlying string - * - * @return Pointer to an array of characters - */ - char *get_str() const; - }; - protected: virtual bool read_internal(const char *in_filename); virtual bool write_internal(const char *in_filename); diff --git a/src/include/Jupiter/Readable_String.h b/src/include/Jupiter/Readable_String.h index f6b7374..9b5b42a 100644 --- a/src/include/Jupiter/Readable_String.h +++ b/src/include/Jupiter/Readable_String.h @@ -163,10 +163,11 @@ namespace Jupiter { inline std::string vstring_printf(const char* format, va_list args) { std::string result; + // Calculate size needed for formatted string va_list args_copy; va_copy(args_copy, args); int min_length = std::vsnprintf(nullptr, 0, format, args_copy); - va_end(args_copy); + va_end(args_copy); if (min_length > 0) { result.resize(min_length); diff --git a/src/include/Jupiter/Shift_String.h b/src/include/Jupiter/Shift_String.h index 43e032b..51c0279 100644 --- a/src/include/Jupiter/Shift_String.h +++ b/src/include/Jupiter/Shift_String.h @@ -45,22 +45,6 @@ namespace Jupiter { public: - /** - * @brief Shifts the string pointer to the left. - * - * @param length Number of elements to shift - * @return Number of elements shifted to the left. - */ - size_t shiftLeft(size_t length); - - /** - * @brief Shifts the string pointer to the right. - * - * @param length Number of elements to shift - * @return Number of elements shifted. - */ - size_t shiftRight(size_t length); - /** * @brief Removes the first instance of an element from the string. * diff --git a/src/include/Jupiter/Shift_String_Imp.h b/src/include/Jupiter/Shift_String_Imp.h index 2d4dc49..34668dc 100644 --- a/src/include/Jupiter/Shift_String_Imp.h +++ b/src/include/Jupiter/Shift_String_Imp.h @@ -36,30 +36,16 @@ template Jupiter::Shift_String_Type::~Shift_String_Type() if (Jupiter::Shift_String_Type::base != nullptr) delete[] Jupiter::Shift_String_Type::base; } -template size_t Jupiter::Shift_String_Type::shiftLeft(size_t len) -{ - size_t offset = Jupiter::String_Type::str - Jupiter::Shift_String_Type::base; - if (len > offset) len = offset; - Jupiter::String_Type::str -= len; - Jupiter::String_Type::length += len; - return len; -} - -template size_t Jupiter::Shift_String_Type::shiftRight(size_t len) -{ - if (len > Jupiter::String_Type::length) len = Jupiter::String_Type::length; - Jupiter::String_Type::str += len; - Jupiter::String_Type::length -= len; - return len; -} - template bool Jupiter::Shift_String_Type::remove(const T &value) { if (Jupiter::String_Type::length == 0) return false; if (*Jupiter::String_Type::str == value) { if (Jupiter::String_Type::length == 1) this->truncate(1); - else this->shiftRight(1); + else { + ++Jupiter::String_Type::str; + --Jupiter::String_Type::length; + } return true; } return Jupiter::String_Type::remove(value); @@ -67,10 +53,7 @@ template bool Jupiter::Shift_String_Type::remove(const T &value) template void Jupiter::Shift_String_Type::remove(size_t index, size_t len) { - if (index == 0) - this->shiftRight(len); - else - Jupiter::String_Type::remove(index, len); + Jupiter::String_Type::remove(index, len); } template void Jupiter::Shift_String_Type::clear() diff --git a/src/include/Jupiter/Socket.h b/src/include/Jupiter/Socket.h index 98204cf..cb9541f 100644 --- a/src/include/Jupiter/Socket.h +++ b/src/include/Jupiter/Socket.h @@ -518,30 +518,21 @@ namespace Jupiter */ virtual ~Socket(); - /** Protected functions and members*/ - protected: - -#if defined _WIN32 - typedef uintptr_t SocketType; -#else - typedef int SocketType; -#endif - /** - * @brief An extended verison of the string class, which allows for low-level length and string modification. + * @brief An extremely basic data buffer */ - class Buffer - { + class Buffer { public: Buffer(); ~Buffer(); void set_length(size_t in_length); - size_t capacity() const; + [[nodiscard]] size_t capacity() const; + [[nodiscard]] size_t size() const; void reserve(size_t new_capacity); void clear(); - std::string_view view() const; - void* data() const; - char* chr_data() const; + [[nodiscard]] std::string_view view() const; + [[nodiscard]] void* data() const; + [[nodiscard]] char* chr_data() const; private: void* m_buffer; @@ -549,6 +540,15 @@ namespace Jupiter size_t m_buffer_size; }; + /** Protected functions and members*/ + protected: + +#if defined _WIN32 + typedef uintptr_t SocketType; +#else + typedef int SocketType; +#endif + /** * @brief Fetches the buffer where data is stored *