From 6d9272201497e3f6e5f79676e2f228e36413fc84 Mon Sep 17 00:00:00 2001 From: Jessica James Date: Mon, 19 Dec 2016 13:19:38 -0500 Subject: [PATCH] String: * Added casts to fundamental types * Fixed some allocation issues Replaced all instances of getPowerTwo32 with slightly more generic 'getPowerTwo' template function Hash_Table::set now returns a bool General cleanup --- Jupiter/CString_Imp.h | 51 ++++++++++++++++++++++++++--------- Jupiter/Functions.h | 44 ++++++++++++++++++++++++++++++ Jupiter/HTTP_Server.cpp | 14 +++++----- Jupiter/Hash_Table.h | 5 ++-- Jupiter/Hash_Table_Imp.h | 19 ++++++++++++- Jupiter/Readable_String.h | 12 +++++++++ Jupiter/Socket.cpp | 12 ++++++--- Jupiter/String_Imp.h | 57 ++++++++++++++++++++++++++++++++++++--- 8 files changed, 185 insertions(+), 29 deletions(-) diff --git a/Jupiter/CString_Imp.h b/Jupiter/CString_Imp.h index 8f54edb..933586f 100644 --- a/Jupiter/CString_Imp.h +++ b/Jupiter/CString_Imp.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2013-2015 Jessica James. + * Copyright (C) 2013-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -564,7 +564,7 @@ template Jupiter::CString_Loose::CString_Loose(Jupiter::CString_L template Jupiter::CString_Loose::CString_Loose(size_t len) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { if (len < Jupiter::CString_Loose::start_size) Jupiter::CString_Loose::strSize = Jupiter::CString_Loose::start_size; - else Jupiter::CString_Loose::strSize = getPowerTwo32(len + 1); + else Jupiter::CString_Loose::strSize = getPowerTwo(len + 1); Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; @@ -611,7 +611,7 @@ template Jupiter::CString_Loose::CString_Loose(const T *in) : Jup else { Jupiter::String_Type::length = Jupiter::strlen(in); - Jupiter::CString_Loose::strSize = getPowerTwo32(Jupiter::String_Type::length + 1); + Jupiter::CString_Loose::strSize = getPowerTwo(Jupiter::String_Type::length + 1); if (Jupiter::CString_Loose::strSize < Jupiter::CString_Loose::start_size) Jupiter::CString_Loose::strSize = Jupiter::CString_Loose::start_size; Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; @@ -685,23 +685,50 @@ template Jupiter::CString_Loose::CString_Loose(const Jupiter::Rea template bool Jupiter::CString_Loose::setBufferSize(size_t len) { - len = getPowerTwo32(len + 1); - if (len > Jupiter::CString_Loose::strSize) + size_t offset = Jupiter::String_Type::str - Jupiter::Shift_String_Type::base; + + ++len; // null term + if (len + offset > Jupiter::CString_Loose::strSize) { - T *ptr = new T[len]; - for (unsigned int i = 0; i < Jupiter::String_Type::length; i++) ptr[i] = Jupiter::Shift_String_Type::str[i]; - ptr[Jupiter::String_Type::length] = 0; - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = ptr; + if (len > Jupiter::CString_Loose::strSize) + { + // Buffer is not large enough; reallocate + Jupiter::CString_Loose::strSize = getPowerTwo(len); + + T *ptr = new T[Jupiter::CString_Loose::strSize]; + for (size_t i = 0; i < Jupiter::String_Type::length; i++) + ptr[i] = Jupiter::String_Type::str[i]; + ptr[Jupiter::String_Type::length] = 0; + + delete[] Jupiter::Shift_String_Type::base; + Jupiter::Shift_String_Type::base = ptr; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + + return true; + } + + // Buffer has enough space to accomodate; shift data to the left + T *read_itr = Jupiter::String_Type::str; + T *read_end = read_itr + Jupiter::String_Type::length; + T *write_itr = Jupiter::Shift_String_Type::base; + + while (read_itr != read_end) + { + *write_itr = *read_itr; + + ++read_itr; + ++write_itr; + } + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - return true; } + return false; } template bool Jupiter::CString_Loose::setBufferSizeNoCopy(size_t len) { - len = getPowerTwo32(len + 1); + len = getPowerTwo(len + 1); if (len > Jupiter::CString_Loose::strSize) { Jupiter::String_Type::length = 0; diff --git a/Jupiter/Functions.h b/Jupiter/Functions.h index 160304a..3f2f9be 100644 --- a/Jupiter/Functions.h +++ b/Jupiter/Functions.h @@ -32,6 +32,7 @@ #include #include +#include namespace Jupiter { @@ -84,6 +85,14 @@ namespace Jupiter * @return True if the strings are equal, false otherwise. */ template bool streql(const T *str1, const T *str2); + + /** + * @brief Gets the first power of two from in_value + * + * @param in_value Integer to get power of two from + * @return First power of two at least as large as in_value + */ + template T getPowerTwo(T in_value); } extern "C" @@ -407,6 +416,41 @@ template inline bool Jupiter::streql(const T *str1, const T *str2) return (*str1 == *str2); } +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) /** Conditional is constant; can probably be removed when 'if constexpr' support is added to MSVC */ +#pragma warning(disable: 4293) /** shift count negative or too big, undefined behavior */ +#endif + +template T Jupiter::getPowerTwo(T in_value) +{ + static_assert(std::is_integral::value, "Integer type required"); + + --in_value; + in_value |= in_value >> 1; + in_value |= in_value >> 2; + in_value |= in_value >> 4; + + if (sizeof(T) >= 2) + in_value |= in_value >> 8; + + if (sizeof(T) >= 4) + in_value |= in_value >> 16; + + if (sizeof(T) >= 8) + in_value |= in_value >> 32; + + if (sizeof(T) >= 16) + in_value |= in_value >> 64; + + return ++in_value; +} + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + #endif // __cplusplus #endif // _FUNCTIONS_H_HEADER \ No newline at end of file diff --git a/Jupiter/HTTP_Server.cpp b/Jupiter/HTTP_Server.cpp index e0ad22f..af19075 100644 --- a/Jupiter/HTTP_Server.cpp +++ b/Jupiter/HTTP_Server.cpp @@ -92,7 +92,7 @@ void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_na if (index == Jupiter::INVALID_INDEX) dir_name = in_name_ref; else - dir_name = in_name_ref.substring(0U, index); + dir_name = in_name_ref.substring(size_t{ 0 }, index); in_name_ref.shiftRight(dir_name.size()); Jupiter::HTTP::Server::Directory *directory; @@ -120,7 +120,7 @@ void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_na index = in_name_ref.find('/'); if (index != Jupiter::INVALID_INDEX) { - directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref.substring(0U, index))); + directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref.substring(size_t{ 0 }, index))); directory = directory->directories.get(directories.size() - 1); in_name_ref.shiftRight(index + 1); goto directory_add_loop; @@ -165,7 +165,7 @@ bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &pat if (index == Jupiter::INVALID_INDEX) dir_name = in_name_ref; else - dir_name = in_name_ref.substring(0U, index); + dir_name = in_name_ref.substring(size_t{ 0 }, index); in_name_ref.shiftRight(dir_name.size()); Jupiter::HTTP::Server::Directory *directory; @@ -628,9 +628,9 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) else { if (session.host == nullptr) - content = Jupiter::HTTP::Server::Data::find(query_string.substring(0U, span)); + content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span)); else - content = session.host->find(query_string.substring(0U, span)); + content = session.host->find(query_string.substring(size_t{ 0 }, span)); query_string.shiftRight(span + 1); // decode query_string here } @@ -661,9 +661,9 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) else { if (session.host == nullptr) - content = Jupiter::HTTP::Server::Data::find(query_string.substring(0U, span)); + content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span)); else - content = session.host->find(query_string.substring(0U, span)); + content = session.host->find(query_string.substring(size_t{ 0 }, span)); query_string.shiftRight(span + 1); // decode query_string here } diff --git a/Jupiter/Hash_Table.h b/Jupiter/Hash_Table.h index 5eb97f5..c0d72f4 100644 --- a/Jupiter/Hash_Table.h +++ b/Jupiter/Hash_Table.h @@ -37,7 +37,7 @@ namespace Jupiter * @param KeyT Type the table will use for keys; must implement following: operator==, move constructor * @param ValueT Type the table will use for values * @param InKeyT Type the table will accept for keys (Default: KeyT) - * @param InValueT Type the table will accept for values (Default: KeyT) + * @param InValueT Type the table will accept for values (Default: ValueT) * @param HashF Function to be used for generating hashes (Default: Fowler-Noll-Vo 1a) */ template> class Hash_Table @@ -147,8 +147,9 @@ namespace Jupiter * * @param in_key Key of the entry to set * @param in_value Value of the entry to set + * @return True if a new entry was added, false if an entry was overwritten */ - void set(const InKeyT &in_key, const InValueT &in_value); + bool set(const InKeyT &in_key, const InValueT &in_value); /** * @brief Removes an entry from the table and returns its value diff --git a/Jupiter/Hash_Table_Imp.h b/Jupiter/Hash_Table_Imp.h index 51d426f..d76f286 100644 --- a/Jupiter/Hash_Table_Imp.h +++ b/Jupiter/Hash_Table_Imp.h @@ -32,6 +32,12 @@ * Hash_Table */ +/** Conditional is constant; can probably be removed when 'if constexpr' support is added to MSVC */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4127) +#endif + template inline size_t Jupiter::default_hash_function(const T &in) { if (sizeof(size_t) >= sizeof(uint64_t)) @@ -40,6 +46,11 @@ template inline size_t Jupiter::default_hash_function(const T &in) return static_cast(Jupiter::fnv1a_32(in)); } +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + /** Hash_Table::Bucket::Entry */ template @@ -168,11 +179,17 @@ ValueT *Jupiter::Hash_Table::get(const In } template -void Jupiter::Hash_Table::set(const InKeyT &in_key, const InValueT &in_value) +bool Jupiter::Hash_Table::set(const InKeyT &in_key, const InValueT &in_value) { if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key, in_value)) + { if (++m_length == m_buckets_size) expand(); + + return true; + } + + return false; } template diff --git a/Jupiter/Readable_String.h b/Jupiter/Readable_String.h index ab02046..7983892 100644 --- a/Jupiter/Readable_String.h +++ b/Jupiter/Readable_String.h @@ -430,6 +430,18 @@ namespace Jupiter inline bool operator>=(const T right)const{ return !operator<(right); } /** Conversion operators */ + explicit inline operator bool() { return this->asBool(); } + explicit inline operator short() { return static_cast(this->asInt()); } + explicit inline operator unsigned short() { return static_cast(this->asUnsignedInt()); } + explicit inline operator int() { return this->asInt(); } + explicit inline operator unsigned int() { return this->asUnsignedInt(); } + explicit inline operator long() { return static_cast(this->asLongLong()); } + explicit inline operator unsigned long() { return static_cast(this->asLongLong()); } + explicit inline operator long long() { return this->asLongLong(); } + explicit inline operator unsigned long long() { return this->asUnsignedLongLong(); } + explicit inline operator float() { return static_cast(this->asDouble()); } + explicit inline operator double() { return this->asDouble(); } + explicit inline operator long double() { return this->asDouble(); } // NEEDS TO NOT CAST FROM DOUBLE explicit inline operator std::basic_string() { return std::basic_string(this->ptr(), this->size()); } private: diff --git a/Jupiter/Socket.cpp b/Jupiter/Socket.cpp index fb5eac5..be3e0f8 100644 --- a/Jupiter/Socket.cpp +++ b/Jupiter/Socket.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2013-2015 Jessica James. + * Copyright (C) 2013-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -144,10 +144,16 @@ int Jupiter::Socket::getProtocol() const bool Jupiter::Socket::connect(addrinfo *info) { #if defined _WIN32 - if (!socketInit && !Jupiter::Socket::init()) return false; + if (!socketInit && !Jupiter::Socket::init()) + return false; #endif // _WIN32 + Jupiter::Socket::data_->rawSock = socket(info->ai_family, Jupiter::Socket::data_->sockType, Jupiter::Socket::data_->sockProto); - if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET || (Jupiter::Socket::data_->sockType != SOCK_RAW && Jupiter::Socket::data_->sockProto != IPPROTO_RAW && ::connect(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR)) return false; + + if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET + || (Jupiter::Socket::data_->sockType != SOCK_RAW && Jupiter::Socket::data_->sockProto != IPPROTO_RAW && ::connect(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR)) + return false; + return true; } diff --git a/Jupiter/String_Imp.h b/Jupiter/String_Imp.h index f1614d1..fdd9a4f 100644 --- a/Jupiter/String_Imp.h +++ b/Jupiter/String_Imp.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2013-2015 Jessica James. + * Copyright (C) 2013-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -514,7 +514,7 @@ template Jupiter::String_Loose::String_Loose(const T *in) { Jupiter::String_Type::length = Jupiter::strlen(in); - Jupiter::String_Loose::strSize = getPowerTwo32(Jupiter::String_Type::length); + Jupiter::String_Loose::strSize = getPowerTwo(Jupiter::String_Type::length); if (Jupiter::String_Loose::strSize < Jupiter::String_Loose::start_size) Jupiter::String_Loose::strSize = Jupiter::String_Loose::start_size; Jupiter::Shift_String_Type::base = new T[Jupiter::String_Loose::strSize]; @@ -591,12 +591,61 @@ template Jupiter::String_Loose::String_Loose(const Jupiter::Reada template bool Jupiter::String_Loose::setBufferSize(size_t len) { - return Jupiter::Shift_String_Type::setBufferSize(Jupiter::String_Loose::strSize = getPowerTwo32(len)); + size_t offset = Jupiter::String_Type::str - Jupiter::Shift_String_Type::base; + + if (len + offset > Jupiter::String_Loose::strSize) + { + if (len > Jupiter::String_Loose::strSize) + { + // Buffer is not large enough; reallocate + Jupiter::String_Loose::strSize = getPowerTwo(len); + + T *ptr = new T[Jupiter::String_Loose::strSize]; + for (size_t i = 0; i < Jupiter::String_Type::length; i++) + ptr[i] = Jupiter::String_Type::str[i]; + + delete[] Jupiter::Shift_String_Type::base; + Jupiter::Shift_String_Type::base = ptr; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + + return true; + } + + // Buffer has enough space to accomodate; shift data to the left + T *read_itr = Jupiter::String_Type::str; + T *read_end = read_itr + Jupiter::String_Type::length; + T *write_itr = Jupiter::Shift_String_Type::base; + + while (read_itr != read_end) + { + *write_itr = *read_itr; + + ++read_itr; + ++write_itr; + } + + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + } + + return false; } template bool Jupiter::String_Loose::setBufferSizeNoCopy(size_t len) { - return Jupiter::Shift_String_Type::setBufferSizeNoCopy(Jupiter::String_Loose::strSize = getPowerTwo32(len)); + len = getPowerTwo(len); + if (len > Jupiter::String_Loose::strSize) + { + Jupiter::String_Type::length = 0; + delete[] Jupiter::Shift_String_Type::base; + Jupiter::Shift_String_Type::base = new T[len]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + return true; + } + + Jupiter::String_Type::length = 0; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + + return false; } // vformat()