From 342c948b494e958c482d92328290251af9003de8 Mon Sep 17 00:00:00 2001 From: JustinAJ Date: Sun, 1 Jun 2014 14:19:11 -0400 Subject: [PATCH] Moved String Implementations around, moved repeated code (i.e: getWord) to templates, updated other code to be compatible to chagnes. CString_Strict is now typedef'd to CString_Type. --- Jupiter/CString.h | 217 ++++---- Jupiter/CString_Imp.h | 868 ++++++++------------------------ Jupiter/File.cpp | 2 +- Jupiter/IRC_Client.cpp | 2 +- Jupiter/Jupiter.vcxproj | 7 + Jupiter/Jupiter.vcxproj.filters | 21 +- Jupiter/Shift_String.h | 34 ++ Jupiter/Shift_String_Imp.h | 40 ++ Jupiter/String_Type.h | 101 +++- Jupiter/String_Type_Imp.h | 438 +++++++++++++++- Release/Jupiter.lib | Bin 184464 -> 193990 bytes Tester/Tester.vcxproj | 1 + 12 files changed, 926 insertions(+), 805 deletions(-) diff --git a/Jupiter/CString.h b/Jupiter/CString.h index 149e6b9..fe224e1 100644 --- a/Jupiter/CString.h +++ b/Jupiter/CString.h @@ -30,8 +30,7 @@ namespace Jupiter { /** - * @brief Provides the basis for CString classes by providing the implementations for many abstract methods in String_Type. - * Note: This is an abstract type. + * @brief Provides the basis for CString classes by providing a minimalist implementation (i.e: no extra variables). * * @param T Element type which the CString will store. Defaults to char. */ @@ -62,24 +61,6 @@ namespace Jupiter */ bool remove(const T &value); - /** Assignment Operators */ - inline CString_Type &operator=(const CString_Type &right) { this->set(right); return *this; }; - inline CString_Type &operator=(const String_Type &right) { this->set(right); return *this; }; - inline CString_Type &operator=(const std::basic_string &right) { this->set(right); return *this; }; - inline CString_Type &operator=(const T *right) { this->set(right); return *this; }; - inline CString_Type &operator=(const T right) { this->set(right); return *this; }; - }; - - /** - * @brief Provides a "strict" CString implementation that's more optimized for minimal memory usage. - * Note: This recreates the underlying C-style string with every concatenation. - * - * @param T Element type which the CString will store. Defaults to char. - */ - template class CString_Strict : public CString_Type - { - public: - /** * @brief Sets the CString's contents based on the format string and input variables. * Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t. @@ -108,7 +89,7 @@ namespace Jupiter * @param ... Inputs to match the format specifiers. * @return String containing the new format. */ - static CString_Strict Format(const T *format, ...); + static CString_Type Format(const T *format, ...); /** * @brief Creates a partial copy of the string. @@ -116,7 +97,7 @@ namespace Jupiter * @param pos Position in the string to start copying from. * @return String containing a partial copy of the original string. */ - CString_Strict substring(size_t pos) const; + CString_Type substring(size_t pos) const; /** * @brief Creates a partial copy of the string. @@ -125,7 +106,7 @@ namespace Jupiter * @param length Number of characters to copy. * @return String containing a partial copy of the original string. */ - CString_Strict substring(size_t pos, size_t length) const; + CString_Type substring(size_t pos, size_t length) const; /** * @brief Creates a partial copy of the string. @@ -134,7 +115,8 @@ namespace Jupiter * @param pos Position in the string to start copying from. * @return String containing a partial copy of the original string. */ - static CString_Strict substring(const Jupiter::String_Type &in, size_t pos); + static CString_Type substring(const Jupiter::String_Type &in, size_t pos); + static CString_Type substring(const T *in, size_t pos); /** * @brief Creates a partial copy of the string. @@ -144,7 +126,8 @@ namespace Jupiter * @param length Number of characters to copy. * @return String containing a partial copy of the original string. */ - static CString_Strict substring(const Jupiter::String_Type &in, size_t pos, size_t length); + static CString_Type substring(const Jupiter::String_Type &in, size_t pos, size_t length); + static CString_Type substring(const T *in, size_t pos, size_t length); /** * @brief Creates a partial copy of the string, based on a set of tokens. @@ -153,7 +136,7 @@ namespace Jupiter * @param whitespace A string of tokens used to deliminate words. * @return String containing a partial copy of the original string. */ - CString_Strict getWord(size_t pos, const T *whitespace) const; + CString_Type getWord(size_t pos, const T *whitespace) const; /** * @brief Creates a partial copy of an input string, based on a set of tokens. @@ -163,7 +146,7 @@ namespace Jupiter * @param whitespace A string of tokens used to deliminate words. * @return String containing a partial copy of the original string. */ - static CString_Strict getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); + static CString_Type getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); /** * @brief Creates a partial copy of an input string, based on a set of tokens. @@ -173,7 +156,7 @@ namespace Jupiter * @param whitespace A string of tokens used to deliminate words. * @return String containing a partial copy of the original string. */ - static CString_Strict getWord(const T *in, size_t pos, const T *whitespace); + static CString_Type getWord(const T *in, size_t pos, const T *whitespace); /** * @brief Creates a partial copy of the string, based on a set of tokens. @@ -182,7 +165,7 @@ namespace Jupiter * @param whitespace A string of tokens used to deliminate words. * @return String containing a partial copy of the original string. */ - CString_Strict gotoWord(size_t pos, const T *whitespace) const; + CString_Type gotoWord(size_t pos, const T *whitespace) const; /** * @brief Creates a partial copy of the string, based on a set of tokens. @@ -192,7 +175,7 @@ namespace Jupiter * @param whitespace A string of tokens used to deliminate words. * @return String containing a partial copy of the original string. */ - static CString_Strict gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); + static CString_Type gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); /** * @brief Copies the data from the input string to the CString. @@ -205,26 +188,6 @@ namespace Jupiter size_t set(const T *in); size_t set(const T in); - /** - * @brief Sets the string buffer. - * Note: This class will free the buffer for you when it's done. - * - * @param in New buffer to be used. - * @return The length of the string. - */ - size_t setString(T *in); - - /** - * @brief Sets the string buffer. - * Note: This class will free the buffer for you when it's done. DO NOT DELETE THE INPUT BUFFER. - * Note: This method is unique to the CString_Strict template class, and does not appear in CString_Loose. - * - * @param in New buffer to be used. - * @param size At least the number of characters in the buffer, not including the null-terminator. - * @return The length of the string. - */ - size_t setString(T *in, size_t size); - /** * @brief Copies the data from the input string and concatenates it to the end of CString. * @@ -236,26 +199,58 @@ namespace Jupiter size_t concat(const T *in); size_t concat(const T in); + /** Assignment Operators */ + inline CString_Type &operator=(const CString_Type &right) { this->set(right); return *this; }; + inline CString_Type &operator=(const String_Type &right) { this->set(right); return *this; }; + inline CString_Type &operator=(const std::basic_string &right) { this->set(right); return *this; }; + inline CString_Type &operator=(const T *right) { this->set(right); return *this; }; + inline CString_Type &operator=(const T right) { this->set(right); return *this; }; + + static const Jupiter::CString_Type empty; /** Empty instantation of CString_Type */ + /** Default Constructor */ - CString_Strict(); + CString_Type(); + + /** + * @brief Size hint constructor. + * Note: For the CString_Type base class, this is only truly useful internally. + * + * @param size Minimum number of elements the string must be able to hold. + */ + CString_Type(size_t size); + + /** Move Constructor */ + CString_Type(CString_Type &&source); /** Copy Constructors */ - CString_Strict(const String_Type &in); - CString_Strict(const std::basic_string &in); - CString_Strict(const T *in); - CString_Strict(size_t size); + CString_Type(const String_Type &in); + CString_Type(const std::basic_string &in); + CString_Type(const T *in); - /** Destructor */ - virtual ~CString_Strict(); + protected: - /** Assignment Operators */ - inline CString_Strict &operator=(const CString_Strict &right) { this->set(right); return *this; }; - inline CString_Strict &operator=(const CString_Type &right) { this->set(right); return *this; }; - inline CString_Strict &operator=(const String_Type &right) { this->set(right); return *this; }; - inline CString_Strict &operator=(const std::basic_string &right) { this->set(right); return *this; }; - inline CString_Strict &operator=(const T *right) { this->set(right); return *this; }; - inline CString_Strict &operator=(const T right) { this->set(right); return *this; }; + /** + * @brief Sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSize(size_t len); + + /** + * @brief Empties the string, and sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSizeNoCopy(size_t len); + + /** Dummy constructor to prevent string initialization */ + CString_Type(Jupiter::String_Constructor_Base &) {}; }; + template using CString_Strict = CString_Type; /** * @brief Provides a "loose" CString implementation that's more optimized for repeated concatenations. @@ -267,26 +262,6 @@ namespace Jupiter { public: - /** - * @brief Sets the CString's contents based on the format string and input variables. - * Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t. - * - * @param format Format that the string is compared against. - * @param ... Inputs to match the format specifiers. - * @return Number of characters written. - */ - size_t vformat(const T *format, va_list args); - - /** - * @brief Appends to a CString's contents based on the format string and input variables. - * Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t. - * - * @param format Format that the string is compared against. - * @param ... Inputs to match the format specifiers. - * @return Number of characters written. - */ - size_t avformat(const T *format, va_list args); - /** * @brief Sets the CString's contents based on the format string and input variables. * Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t. @@ -322,6 +297,7 @@ namespace Jupiter * @return String containing a partial copy of the original string. */ static CString_Loose substring(const Jupiter::String_Type &in, size_t pos); + static CString_Loose substring(const T *in, size_t pos); /** * @brief Creates a partial copy of the string. @@ -332,6 +308,7 @@ namespace Jupiter * @return String containing a partial copy of the original string. */ static CString_Loose substring(const Jupiter::String_Type &in, size_t pos, size_t length); + static CString_Loose substring(const T *in, size_t pos, size_t length); /** * @brief Creates a partial copy of the string, based on a set of tokens. @@ -383,48 +360,26 @@ namespace Jupiter */ static CString_Loose gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); - /** - * @brief Copies the data from the input string to the CString. - * - * @param in String containing the data to be copied. - * @return New size of the CString. - */ - size_t set(const CString_Loose &in); - size_t set(const String_Type &in); - size_t set(const std::basic_string &in); - size_t set(const T *in); - size_t set(const T in); - - /** - * @brief Copies the data from the input string and concatenats it to the end of CString. - * - * @param in String containing the data to be concatenated. - * @return New size of the CString. - */ - size_t concat(const String_Type &in); - size_t concat(const std::basic_string &in); - size_t concat(const T *in); - size_t concat(const T in); - /** Default constructor */ CString_Loose(); /** * @brief Size hint constructor. * - * @param size Minimum size of new string's buffer. + * @param size Minimum number of elements the string must be able to hold. */ CString_Loose(size_t size); + /** Move Constructor */ + CString_Loose(CString_Loose &&source); + /** Copy Constructors */ CString_Loose(const CString_Loose &in); CString_Loose(const String_Type &in); CString_Loose(const std::basic_string &in); CString_Loose(const T *in); - - /** Destructor */ - virtual ~CString_Loose(); + static const Jupiter::CString_Loose empty; /** Empty instantation of CString_Loose */ static const size_t start_size = 8; /** Starting size for loose CStrings. */ /** Assignment Operators */ @@ -436,6 +391,28 @@ namespace Jupiter inline CString_Loose &operator=(const T right) { this->set(right); return *this; }; protected: + + /** + * @brief Sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSize(size_t len); + + /** + * @brief Empties the string, and sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSizeNoCopy(size_t len); + + /** Dummy constructor to prevent string initialization */ + CString_Loose(Jupiter::String_Constructor_Base &) {}; + size_t strSize; /** Size of underlying C-string buffer */ }; @@ -445,12 +422,6 @@ namespace Jupiter /** Definition of a Loose Wide CString */ typedef CString_Loose WCStringL; - /** Definition of a Strict CString. */ - typedef CString_Strict CStringS; - - /** Definition of a Strict Wide CString */ - typedef CString_Strict WCStringS; - /** Definition of a CString. */ typedef CStringL CString; @@ -463,14 +434,20 @@ namespace Jupiter /** Generic Wide CString Type */ typedef CString_Type WCStringType; + /** Definition of a Strict CString. */ + typedef CStringType CStringS; + + /** Definition of a Strict Wide CString */ + typedef WCStringType WCStringS; + /** Empty String constants */ - static const Jupiter::CStringS emptyCStringS; - static const Jupiter::CStringL emptyCStringL; + static const Jupiter::CStringS &emptyCStringS = Jupiter::CStringS::empty; + static const Jupiter::CStringL &emptyCStringL = Jupiter::CStringL::empty; static const Jupiter::CStringType &emptyCString = emptyCStringS; static const Jupiter::StringType &emptyString = emptyCString; } -/** Implementation for CString_Type, CString_Strict, and CString_Loose. Very scary. */ +/** Implementation for CString_Type and CString_Loose. Very scary. */ #include "CString_Imp.h" #endif // _CSTRING_H_HEADER \ No newline at end of file diff --git a/Jupiter/CString_Imp.h b/Jupiter/CString_Imp.h index bd9d83e..c588e94 100644 --- a/Jupiter/CString_Imp.h +++ b/Jupiter/CString_Imp.h @@ -43,65 +43,43 @@ * CString_Type */ -template const T *Jupiter::CString_Type::c_str() const -{ - return Jupiter::String_Type::str; -} - -template size_t Jupiter::CString_Type::truncate(size_t n) -{ - Jupiter::String_Type::str[Jupiter::String_Type::truncate(n)] = 0; - return Jupiter::String_Type::length; -} - -template bool Jupiter::CString_Type::remove(const T &value) -{ - if (Jupiter::Shift_String_Type::remove(value)) - { - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return true; - } - return false; -} - -/** -* IMPLEMENTATION: -* CString_Strict -*/ - -template Jupiter::CString_Strict::CString_Strict() : Jupiter::CString_Strict::CString_Strict(size_t(0)) +template Jupiter::CString_Type::CString_Type() : Jupiter::CString_Type::CString_Type(size_t(0)) { } -template Jupiter::CString_Strict::CString_Strict(size_t size) +template Jupiter::CString_Type::CString_Type(size_t len) { - // We need a size variable to actually make any real use of this. - Jupiter::Shift_String_Type::base = new T[size+1]; + Jupiter::Shift_String_Type::base = new T[len + 1]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; Jupiter::String_Type::length = 0; } -template Jupiter::CString_Strict::CString_Strict(const Jupiter::String_Type &in) +template Jupiter::CString_Type::CString_Type(Jupiter::CString_Type &&source) : Jupiter::Shift_String_Type(std::move(source)) { - Jupiter::String_Type::length = in.size(); - Jupiter::Shift_String_Type::base = new T[Jupiter::String_Type::length + 1]; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - size_t index; - for (index = 0; index < Jupiter::String_Type::length && in.get(index) != 0; index++) Jupiter::String_Type::str[index] = in.get(index); - Jupiter::String_Type::length = index; +} + +template Jupiter::CString_Type::CString_Type(const Jupiter::String_Type &in) : Jupiter::CString_Type::CString_Type(in.size()) +{ + while (Jupiter::String_Type::length < in.size() && in.get(Jupiter::String_Type::length) != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; } -template Jupiter::CString_Strict::CString_Strict(const std::basic_string &in) +template Jupiter::CString_Type::CString_Type(const std::basic_string &in) : Jupiter::CString_Type::CString_Type(in.size()) { - Jupiter::String_Type::length = in.size(); - Jupiter::Shift_String_Type::base = new T[Jupiter::String_Type::length + 1]; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::strcpy(Jupiter::String_Type::str, in.c_str()); + while (Jupiter::String_Type::length < in.size() && in.at(Jupiter::String_Type::length) != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } + Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; } -template Jupiter::CString_Strict::CString_Strict(const T *in) +template Jupiter::CString_Type::CString_Type(const T *in) { if (in == nullptr) { @@ -119,14 +97,47 @@ template Jupiter::CString_Strict::CString_Strict(const T *in) } } -template Jupiter::CString_Strict::~CString_Strict() +template bool Jupiter::CString_Type::setBufferSize(size_t len) { - delete[] Jupiter::Shift_String_Type::base; + if (Jupiter::Shift_String_Type::setBufferSize(len + 1)) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; + return true; + } + return false; +} + +template bool Jupiter::CString_Type::setBufferSizeNoCopy(size_t len) +{ + bool r = Jupiter::Shift_String_Type::setBufferSizeNoCopy(len + 1); + *Jupiter::String_Type::str = 0; + return r; +} + +template const T *Jupiter::CString_Type::c_str() const +{ + return Jupiter::String_Type::str; +} + +template size_t Jupiter::CString_Type::truncate(size_t n) +{ + Jupiter::String_Type::str[Jupiter::String_Type::truncate(n)] = 0; + return Jupiter::String_Type::length; +} + +template bool Jupiter::CString_Type::remove(const T &value) +{ + if (Jupiter::Shift_String_Type::remove(value)) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; + return true; + } + return false; } // vformat() -template<> size_t inline Jupiter::CString_Strict::vformat(const char *format, va_list args) +template<> size_t inline Jupiter::CString_Type::vformat(const char *format, va_list args) { int minLen; va_list sargs; @@ -134,19 +145,14 @@ template<> size_t inline Jupiter::CString_Strict::vformat(const char *form minLen = vsnprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. - if ((unsigned)minLen > Jupiter::String_Type::length) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = new char[minLen + 1]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + this->setBufferSizeNoCopy(minLen); Jupiter::String_Type::length = minLen; vsnprintf(Jupiter::String_Type::str, Jupiter::String_Type::length, format, args); Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } -template<> size_t inline Jupiter::CString_Strict::vformat(const wchar_t *format, va_list args) +template<> size_t inline Jupiter::CString_Type::vformat(const wchar_t *format, va_list args) { int minLen; va_list sargs; @@ -154,26 +160,21 @@ template<> size_t inline Jupiter::CString_Strict::vformat(const wchar_t minLen = vswprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. - if ((unsigned)minLen > Jupiter::String_Type::length) - { - delete[] Jupiter::CString_Type::base; - Jupiter::CString_Type::base = new wchar_t[minLen + 1]; - } - Jupiter::String_Type::str = Jupiter::CString_Type::base; + this->setBufferSizeNoCopy(minLen); Jupiter::String_Type::length = minLen; vswprintf(Jupiter::String_Type::str, Jupiter::String_Type::length, format, args); Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } -template size_t Jupiter::CString_Strict::vformat(const T *format, va_list args) +template size_t Jupiter::CString_Type::vformat(const T *format, va_list args) { return 0; } // avformat() -template<> size_t inline Jupiter::CString_Strict::avformat(const char *format, va_list args) +template<> size_t inline Jupiter::CString_Type::avformat(const char *format, va_list args) { int minLen; va_list sargs; @@ -181,12 +182,7 @@ template<> size_t inline Jupiter::CString_Strict::avformat(const char *for minLen = vsnprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. - - char *t = new char[minLen + Jupiter::String_Type::length + 1]; - Jupiter::strcpy(t, Jupiter::String_Type::str); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = t; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + this->setBufferSize(Jupiter::String_Type::length + minLen); minLen = vsnprintf(Jupiter::String_Type::str + Jupiter::String_Type::length, minLen, format, args); if (minLen <= 0) return 0; @@ -195,7 +191,7 @@ template<> size_t inline Jupiter::CString_Strict::avformat(const char *for return minLen; } -template<> size_t inline Jupiter::CString_Strict::avformat(const wchar_t *format, va_list args) +template<> size_t inline Jupiter::CString_Type::avformat(const wchar_t *format, va_list args) { int minLen; va_list sargs; @@ -203,12 +199,7 @@ template<> size_t inline Jupiter::CString_Strict::avformat(const wchar_ minLen = vswprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. - - wchar_t *t = new wchar_t[minLen + Jupiter::String_Type::length + 1]; - Jupiter::strcpy(t, Jupiter::String_Type::str); - delete[] Jupiter::CString_Type::base; - Jupiter::CString_Type::base = t; - Jupiter::String_Type::str = Jupiter::CString_Type::base; + this->setBufferSize(minLen + Jupiter::String_Type::length); minLen = vswprintf(Jupiter::String_Type::str + Jupiter::String_Type::length, minLen, format, args); if (minLen <= 0) return 0; @@ -217,14 +208,14 @@ template<> size_t inline Jupiter::CString_Strict::avformat(const wchar_ return minLen; } -template size_t Jupiter::CString_Strict::avformat(const T *format, va_list args) +template size_t Jupiter::CString_Type::avformat(const T *format, va_list args) { return 0; } -template Jupiter::CString_Strict Jupiter::CString_Strict::Format(const T *format, ...) +template Jupiter::CString_Type Jupiter::CString_Type::Format(const T *format, ...) { - CString_Strict r; + CString_Type r; va_list args; va_start(args, format); r.vformat(format, args); @@ -232,182 +223,96 @@ template Jupiter::CString_Strict Jupiter::CString_Strict::Form return r; } -template Jupiter::CString_Strict Jupiter::CString_Strict::substring(size_t pos) const +template Jupiter::CString_Type Jupiter::CString_Type::substring(size_t pos) const { - return Jupiter::CString_Strict::substring(*this, pos, Jupiter::String_Type::length - pos); + return Jupiter::CString_Type::substring(*this, pos); } -template Jupiter::CString_Strict Jupiter::CString_Strict::substring(size_t pos, size_t len) const +template Jupiter::CString_Type Jupiter::CString_Type::substring(size_t pos, size_t len) const { - return Jupiter::CString_Strict::substring(*this, pos, len); + return Jupiter::CString_Type::substring(*this, pos, len); } -template Jupiter::CString_Strict Jupiter::CString_Strict::substring(const Jupiter::String_Type &in, size_t pos) +template Jupiter::CString_Type Jupiter::CString_Type::substring(const Jupiter::String_Type &in, size_t pos) { - if (pos > in.size()) return Jupiter::CString_Strict(); - Jupiter::CString_Strict r = Jupiter::CString_Strict(in.size() - pos); - size_t index; - for (index = pos; index != in.size() && in.get(index) != 0; index++) r.str[index - pos] = in.get(index); - r.str[index - pos] = 0; - r.length = index; + if (pos >= in.size()) return Jupiter::CString_Type(); + Jupiter::CString_Type r = Jupiter::CString_Type(in.size() - pos); + for (r.length = 0; pos + r.length != in.size() && in.get(pos + r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length); + r.str[r.length] = 0; return r; } -template Jupiter::CString_Strict Jupiter::CString_Strict::substring(const Jupiter::String_Type &in, size_t pos, size_t len) +template Jupiter::CString_Type Jupiter::CString_Type::substring(const T *in, size_t pos) { - if (pos > in.size()) return Jupiter::CString_Strict(); - if (len > in.size() - pos) len = in.size() - pos; - Jupiter::CString_Strict r = Jupiter::CString_Strict(len); - size_t index; - for (index = 0; index != len && in.get(index + pos) != 0; index++) r.str[index] = in.get(index + pos); - r.str[index] = 0; - r.length = index; + Jupiter::CString_Type r = Jupiter::String_Type::substring(in, pos); + r.str[r.length] = 0; return r; } -template Jupiter::CString_Strict Jupiter::CString_Strict::getWord(size_t pos, const T *whitespace) const +template Jupiter::CString_Type Jupiter::CString_Type::substring(const Jupiter::String_Type &in, size_t pos, size_t len) { - return Jupiter::CString_Strict::getWord(*this, pos, whitespace); + if (pos + len >= in.size()) return Jupiter::CString_Type::substring(in, pos); + Jupiter::CString_Type r = Jupiter::CString_Type(len); + for (r.length = 0; r.length != len && in.get(pos + r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length); + r.str[r.length] = 0; + return r; } -template Jupiter::CString_Strict Jupiter::CString_Strict::getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +template Jupiter::CString_Type Jupiter::CString_Type::substring(const T *in, size_t pos, size_t len) { - unsigned int x = 0; - unsigned int y = 1; - for (unsigned int i = 0; i < pos || y == 1; x++) - { - if (in.get(x) == 0) return Jupiter::CString_Strict(); - if (Jupiter::strpbrk(whitespace, in.get(x)) != nullptr) - { - if (y != 1) - { - y = 1; - i++; - } - } - else - { - if (i >= pos) break; - y = 0; - } - } - for (y = x; Jupiter::strpbrk(whitespace, in.get(y)) == nullptr && in.get(y) != 0; y++); - return Jupiter::CString_Strict::substring(in, x, y - x); + Jupiter::CString_Type r = Jupiter::String_Type::substring(in, pos, len); + r.str[r.length] = 0; + return r; } -template Jupiter::CString_Strict Jupiter::CString_Strict::getWord(const T *in, size_t pos, const T *whitespace) +template Jupiter::CString_Type Jupiter::CString_Type::getWord(size_t pos, const T *whitespace) const { - Jupiter::CString_Strict r; - unsigned int x = 0; - unsigned int y = 1; - unsigned int i; - for (i = 0; i < pos || y == 1; x++) - { - if (in[x] == 0) return r; - if (Jupiter::strpbrk(whitespace, in[x]) != nullptr) - { - if (y != 1) - { - y = 1; - i++; - } - } - else - { - if (i >= pos) break; - y = 0; - } - } + return Jupiter::CString_Type::getWord(*this, pos, whitespace); +} - for (y = x; Jupiter::strpbrk(whitespace, in[y]) == nullptr && in[y] != 0; y++); - r.length = y - x; - delete[] r.base; - r.base = new T[r.length + 1]; - r.str = r.base; - for (i = 0; x < y; i++) - { - r.str[i] = in[x]; - x++; - } - r.str[r.length] = 0; - return r; +template Jupiter::CString_Type Jupiter::CString_Type::getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::getWord(in, pos, whitespace); } -template Jupiter::CString_Strict Jupiter::CString_Strict::gotoWord(size_t pos, const T *whitespace) const +template Jupiter::CString_Type Jupiter::CString_Type::getWord(const T *in, size_t pos, const T *whitespace) { - return Jupiter::CString_Strict::gotoWord(*this, pos, whitespace); + return Jupiter::String_Type::getWord(in, pos, whitespace); } -template Jupiter::CString_Strict Jupiter::CString_Strict::gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +template Jupiter::CString_Type Jupiter::CString_Type::gotoWord(size_t pos, const T *whitespace) const { - unsigned int x = 0; - bool y = true; - for (unsigned int i = 0; i < pos || y == true; x++) - { - if (in.get(x) == 0) return Jupiter::CString_Strict(); - if (Jupiter::strpbrk(whitespace, in.get(x)) != nullptr) - { - if (y != 1) - { - y = true; - i++; - } - } - else - { - if (i >= pos) break; - y = false; - } - } - return Jupiter::CString_Strict::substring(in, x); + return Jupiter::CString_Type::gotoWord(*this, pos, whitespace); } -template size_t Jupiter::CString_Strict::set(const String_Type &in) +template Jupiter::CString_Type Jupiter::CString_Type::gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) { - size_t sSize = in.size(); - if (Jupiter::String_Type::length < sSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = new T[sSize + 1]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = sSize; - size_t index; - for (index = 0; index < Jupiter::String_Type::length && in.get(index) != 0; index++) Jupiter::String_Type::str[index] = in.get(index); - Jupiter::String_Type::length = index; - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; + return Jupiter::String_Type::gotoWord(in, pos, whitespace); +} + +template size_t Jupiter::CString_Type::set(const String_Type &in) +{ + this->setBufferSizeNoCopy(in.size()); + for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length < in.size() && in.get(Jupiter::String_Type::length) != 0; Jupiter::String_Type::length++) + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); return Jupiter::String_Type::length; } -template size_t Jupiter::CString_Strict::set(const std::basic_string &in) +template size_t Jupiter::CString_Type::set(const std::basic_string &in) { - size_t sSize = in.size(); - if (Jupiter::String_Type::length < sSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = new T[sSize + 1]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = sSize; - Jupiter::strcpy(Jupiter::String_Type::str, in.c_str()); - return sSize; + this->setBufferSizeNoCopy(in.size()); + for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length < in.size() && in.at(Jupiter::String_Type::length) != 0; Jupiter::String_Type::length++) + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); + return Jupiter::String_Type::length; } -template size_t Jupiter::CString_Strict::set(const T *in) +template size_t Jupiter::CString_Type::set(const T *in) { - size_t sSize = Jupiter::strlen(in); - if (Jupiter::String_Type::length < sSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = new T[sSize + 1]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = sSize; - Jupiter::strcpy(Jupiter::String_Type::str, in); - return sSize; + Jupiter::String_Type::str[Jupiter::String_Type::set(in)] = 0; + return Jupiter::String_Type::length; } -template size_t Jupiter::CString_Strict::set(const T in) +template size_t Jupiter::CString_Type::set(const T in) { if (in == 0) { @@ -415,85 +320,60 @@ template size_t Jupiter::CString_Strict::set(const T in) *Jupiter::String_Type::str = 0; return Jupiter::String_Type::length = 0; } - if (Jupiter::String_Type::length < 1) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = new T[2]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + this->setBufferSizeNoCopy(1); *Jupiter::String_Type::str = in; Jupiter::String_Type::str[1] = 0; return Jupiter::String_Type::length = 1; } -template size_t Jupiter::CString_Strict::setString(T *in) -{ - return Jupiter::CString_Strict::setString(in, Jupiter::strlen(in)); -} - -template size_t Jupiter::CString_Strict::setString(T *in, size_t size) -{ - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = in; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - return Jupiter::String_Type::length = size; -} - -template size_t Jupiter::CString_Strict::concat(const String_Type &in) +template size_t Jupiter::CString_Type::concat(const String_Type &in) { size_t nSize = Jupiter::String_Type::length + in.size(); - T *tmp = new T[nSize + 1]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); // str guaranteed to be null-terminated. - size_t index; - for (index = Jupiter::String_Type::length; index < nSize && in.get(index - Jupiter::String_Type::length); index++) Jupiter::String_Type::str[index] = in.get(index - Jupiter::String_Type::length); - Jupiter::String_Type::str[index] = 0; - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = index; + const T *inData = in.ptr(); + this->setBufferSize(nSize); + while (Jupiter::String_Type::length != nSize && *inData != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = *inData; + Jupiter::String_Type::length++; + inData++; + } + Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } -template size_t Jupiter::CString_Strict::concat(const std::basic_string &in) +template size_t Jupiter::CString_Type::concat(const std::basic_string &in) { size_t nSize = Jupiter::String_Type::length + in.size(); - T *tmp = new T[nSize + 1]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - Jupiter::strcpy(tmp + Jupiter::String_Type::length, in.c_str()); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = nSize; - return nSize; + const T *inData = in.data(); + this->setBufferSize(nSize); + while (Jupiter::String_Type::length != nSize && *inData != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = *inData; + Jupiter::String_Type::length++; + inData++; + } + Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; + return Jupiter::String_Type::length; } -template size_t Jupiter::CString_Strict::concat(const T *in) +template size_t Jupiter::CString_Type::concat(const T *in) { size_t nSize = Jupiter::String_Type::length + Jupiter::strlen(in); - T *tmp = new T[nSize + 1]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - Jupiter::strcpy(tmp + Jupiter::String_Type::length, in); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = nSize; - return nSize; + this->setBufferSize(nSize); + Jupiter::strcpy(Jupiter::String_Type::str + Jupiter::String_Type::length, in); + return Jupiter::String_Type::length = nSize; } -template size_t Jupiter::CString_Strict::concat(const T c) +template size_t Jupiter::CString_Type::concat(const T c) { - size_t nSize = Jupiter::String_Type::length + 1; - T *tmp = new T[nSize + 1]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - tmp[nSize - 1] = c; - tmp[nSize] = 0; - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = nSize; - return nSize; + this->setBufferSize(Jupiter::String_Type::length + 1); + Jupiter::String_Type::str[Jupiter::String_Type::length] = c; + Jupiter::String_Type::str[++Jupiter::String_Type::length] = 0; + return Jupiter::String_Type::length; } +template const Jupiter::CString_Type Jupiter::CString_Type::empty = Jupiter::CString_Type(); + /** * IMPLEMENTATION: * CString_Loose @@ -503,17 +383,23 @@ template Jupiter::CString_Loose::CString_Loose() : Jupiter::CStri { } -template Jupiter::CString_Loose::CString_Loose(size_t size) +template Jupiter::CString_Loose::CString_Loose(Jupiter::CString_Loose &&source) : Jupiter::CString_Type(std::move(source)) +{ + Jupiter::CString_Loose::strSize = source.strSize; + source.strSize = 0; +} + +template Jupiter::CString_Loose::CString_Loose(size_t len) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { - if (size < Jupiter::CString_Loose::start_size) size = Jupiter::CString_Loose::start_size; - Jupiter::CString_Loose::strSize = size; + if (len < Jupiter::CString_Loose::start_size) Jupiter::CString_Loose::strSize = Jupiter::CString_Loose::start_size; + else Jupiter::CString_Loose::strSize = getPowerTwo32(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; Jupiter::String_Type::length = 0; } -template Jupiter::CString_Loose::CString_Loose(const Jupiter::CString_Loose &in) +template Jupiter::CString_Loose::CString_Loose(const Jupiter::CString_Loose &in) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { Jupiter::CString_Loose::strSize = in.strSize; Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; @@ -522,30 +408,27 @@ template Jupiter::CString_Loose::CString_Loose(const Jupiter::CSt Jupiter::String_Type::length = in.length; } -template Jupiter::CString_Loose::CString_Loose(const Jupiter::String_Type &in) +template Jupiter::CString_Loose::CString_Loose(const Jupiter::String_Type &in) : Jupiter::CString_Loose::CString_Loose(in.size()) { - Jupiter::String_Type::length = in.size(); - Jupiter::CString_Loose::strSize = getPowerTwo32(Jupiter::String_Type::length + 1); - if (Jupiter::CString_Loose::strSize < 8) Jupiter::CString_Loose::strSize = 8; - Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - size_t index; - for (index = 0; index < Jupiter::String_Type::length && in.get(index) != 0; index++) Jupiter::String_Type::str[index] = in.get(index); - Jupiter::String_Type::length = index; + while (Jupiter::String_Type::length < in.size() && in.get(Jupiter::String_Type::length) != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; } -template Jupiter::CString_Loose::CString_Loose(const std::basic_string &in) +template Jupiter::CString_Loose::CString_Loose(const std::basic_string &in) : Jupiter::CString_Loose::CString_Loose(in.size()) { - Jupiter::String_Type::length = in.size(); - Jupiter::CString_Loose::strSize = getPowerTwo32(Jupiter::String_Type::length + 1); - if (Jupiter::CString_Loose::strSize < 8) Jupiter::CString_Loose::strSize = 8; - Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::strcpy(Jupiter::String_Type::str, in.c_str()); + while (Jupiter::String_Type::length < in.size() && in.at(Jupiter::String_Type::length) != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } + Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; } -template Jupiter::CString_Loose::CString_Loose(const T *in) +template Jupiter::CString_Loose::CString_Loose(const T *in) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { if (in == nullptr) { @@ -566,121 +449,38 @@ template Jupiter::CString_Loose::CString_Loose(const T *in) } } -template Jupiter::CString_Loose::~CString_Loose() -{ - delete[] Jupiter::Shift_String_Type::base; -} - -template<> size_t inline Jupiter::CString_Loose::vformat(const char *format, va_list args) -{ - int minLen; - va_list sargs; - va_copy(sargs, args); - minLen = vsnprintf(nullptr, 0, format, sargs); // Portable as of C++11. - va_end(sargs); - if (minLen < 0) return 0; // We simply can not work with this. - if ((unsigned)minLen > Jupiter::CString_Loose::strSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::CString_Loose::strSize = getPowerTwo32(minLen + 1); - Jupiter::Shift_String_Type::base = new char[Jupiter::CString_Loose::strSize]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = minLen; - vsnprintf(Jupiter::String_Type::str, Jupiter::CString_Loose::strSize, format, args); - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return Jupiter::String_Type::length; -} - -template<> size_t inline Jupiter::CString_Loose::vformat(const wchar_t *format, va_list args) -{ - int minLen; - va_list sargs; - va_copy(sargs, args); - minLen = vswprintf(nullptr, 0, format, sargs); // Portable as of C++11. - va_end(sargs); - if (minLen < 0) return 0; // We simply can not work with this. - if ((unsigned)minLen > Jupiter::CString_Loose::strSize) - { - delete[] Jupiter::CString_Type::base; - Jupiter::CString_Loose::strSize = getPowerTwo32(minLen + 1); - Jupiter::CString_Type::base = new wchar_t[Jupiter::CString_Loose::strSize]; - } - Jupiter::String_Type::str = Jupiter::CString_Type::base; - Jupiter::String_Type::length = minLen; - vswprintf(Jupiter::String_Type::str, Jupiter::CString_Loose::strSize, format, args); - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::vformat(const T *format, va_list args) -{ - return 0; -} - -template<> size_t inline Jupiter::CString_Loose::avformat(const char *format, va_list args) +template bool Jupiter::CString_Loose::setBufferSize(size_t len) { - int minLen; - va_list sargs; - va_copy(sargs, args); - minLen = vsnprintf(nullptr, 0, format, sargs); // Portable as of C++11. - va_end(sargs); - if (minLen < 0) return 0; // We simply can not work with this. - minLen += Jupiter::String_Type::length; - if ((unsigned)minLen + 1 > Jupiter::CString_Loose::strSize) - { - Jupiter::CString_Loose::strSize = getPowerTwo32(minLen + 1); - char *tmpStr = new char[Jupiter::CString_Loose::strSize]; - Jupiter::strcpy(tmpStr, Jupiter::String_Type::str); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmpStr; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - else if ((unsigned)minLen + 1 + (Jupiter::String_Type::str - Jupiter::Shift_String_Type::base) > Jupiter::CString_Loose::strSize) + len = getPowerTwo32(len + 1); + if (len > Jupiter::CString_Loose::strSize) { - Jupiter::strcpy(Jupiter::Shift_String_Type::base, Jupiter::String_Type::str); - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + 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; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + return true; } - minLen = vsnprintf(Jupiter::String_Type::str + Jupiter::String_Type::length, Jupiter::CString_Loose::strSize - Jupiter::String_Type::length, format, args); - if (minLen <= 0) return 0; - Jupiter::String_Type::length += minLen; - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return minLen; + return false; } -template<> size_t inline Jupiter::CString_Loose::avformat(const wchar_t *format, va_list args) +template bool Jupiter::CString_Loose::setBufferSizeNoCopy(size_t len) { - int minLen; - va_list sargs; - va_copy(sargs, args); - minLen = vswprintf(nullptr, 0, format, sargs); // Portable as of C++11. - va_end(sargs); - if (minLen < 0) return 0; // We simply can not work with this. - minLen += Jupiter::String_Type::length; - if ((unsigned)minLen + 1 > Jupiter::CString_Loose::strSize) + len = getPowerTwo32(len + 1); + if (len > Jupiter::CString_Loose::strSize) { - Jupiter::CString_Loose::strSize = getPowerTwo32(minLen + 1); - wchar_t *tmpStr = new wchar_t[Jupiter::CString_Loose::strSize]; - Jupiter::strcpy(tmpStr, Jupiter::String_Type::str); - delete[] Jupiter::CString_Type::base; - Jupiter::CString_Type::base = tmpStr; - Jupiter::String_Type::str = Jupiter::CString_Type::base; - } - else if ((unsigned)minLen + 1 + (Jupiter::String_Type::str - Jupiter::CString_Type::base) > Jupiter::CString_Loose::strSize) - { - Jupiter::strcpy(Jupiter::CString_Type::base, Jupiter::String_Type::str); - Jupiter::String_Type::str = Jupiter::CString_Type::base; + 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; + *Jupiter::String_Type::str = 0; + return true; } - minLen = vswprintf(Jupiter::String_Type::str + Jupiter::String_Type::length, Jupiter::CString_Loose::strSize - Jupiter::String_Type::length, format, args); - if (minLen <= 0) return 0; - Jupiter::String_Type::length += minLen; - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return minLen; -} - -template size_t Jupiter::CString_Loose::avformat(const T *format, va_list args) -{ - return 0; + Jupiter::String_Type::length = 0; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + *Jupiter::String_Type::str = 0; + return false; } template Jupiter::CString_Loose Jupiter::CString_Loose::Format(const T *format, ...) @@ -708,21 +508,32 @@ template Jupiter::CString_Loose Jupiter::CString_Loose::substr if (pos > in.size()) return Jupiter::CString_Loose(); Jupiter::CString_Loose r = Jupiter::CString_Loose(in.size() - pos); size_t index; - for (index = pos; index != in.size() && in.get(index) != 0; index++) r.str[index - pos] = in.get(index); + for (index = pos; pos + index != in.size() && in.get(index) != 0; index++) r.str[index - pos] = in.get(index); r.str[index - pos] = 0; r.length = index; return r; } +template Jupiter::CString_Loose Jupiter::CString_Loose::substring(const T *in, size_t pos) +{ + Jupiter::CString_Loose r = Jupiter::String_Type::substring(in, pos); + r.str[r.length] = 0; + return r; +} + template Jupiter::CString_Loose Jupiter::CString_Loose::substring(const Jupiter::String_Type &in, size_t pos, size_t len) { - if (pos > in.size()) return Jupiter::CString_Loose(); - if (len > in.size() - pos) len = in.size() - pos; + if (pos + len >= in.size()) return Jupiter::CString_Loose::substring(in, pos); Jupiter::CString_Loose r = Jupiter::CString_Loose(len); - size_t index; - for (index = 0; index != len && in.get(index + pos) != 0; index++) r.str[index] = in.get(index + pos); - r.str[index] = 0; - r.length = index; + for (r.length = 0; r.length != len && in.get(r.length + pos) != 0; r.length++) r.str[r.length] = in.get(r.length + pos); + r.str[r.length] = 0; + return r; +} + +template Jupiter::CString_Loose Jupiter::CString_Loose::substring(const T *in, size_t pos, size_t len) +{ + Jupiter::CString_Loose r = Jupiter::String_Type::substring(in, pos, len); + r.str[r.length] = 0; return r; } @@ -733,65 +544,12 @@ template Jupiter::CString_Loose Jupiter::CString_Loose::getWor template Jupiter::CString_Loose Jupiter::CString_Loose::getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) { - unsigned int x = 0; - unsigned int y = 1; - for (unsigned int i = 0; i < pos || y == 1; x++) - { - if (in.get(x) == 0) return Jupiter::CString_Loose(); - if (Jupiter::strpbrk(whitespace, in.get(x)) != nullptr) - { - if (y != 1) - { - y = 1; - i++; - } - } - else - { - if (i >= pos) break; - y = 0; - } - } - for (y = x; Jupiter::strpbrk(whitespace, in.get(y)) == nullptr && in.get(y) != 0; y++); - return Jupiter::CString_Loose::substring(in, x, y - x); + return Jupiter::String_Type::getWord(in, pos, whitespace); } template Jupiter::CString_Loose Jupiter::CString_Loose::getWord(const T *in, size_t pos, const T *whitespace) { - Jupiter::CString_Loose r; - unsigned int x = 0; - unsigned int y = 1; - unsigned int i; - for (i = 0; i < pos || y == 1; x++) - { - if (in[x] == 0) return r; - if (Jupiter::strpbrk(whitespace, in[x]) != nullptr) - { - if (y != 1) - { - y = 1; - i++; - } - } - else - { - if (i >= pos) break; - y = 0; - } - } - for (y = x; Jupiter::strpbrk(whitespace, in[y]) == nullptr && in[y] != 0; y++); - r.length = y - x; - r.strSize = getPowerTwo32(r.length + 1); - delete[] r.base; - r.base = new T[r.strSize]; - r.str = r.base; - for (i = 0; x < y; i++) - { - r.str[i] = in[x]; - x++; - } - r.str[i] = 0; - return r; + return Jupiter::String_Type::getWord(in, pos, whitespace); } template Jupiter::CString_Loose Jupiter::CString_Loose::gotoWord(size_t pos, const T *whitespace) const @@ -801,193 +559,9 @@ template Jupiter::CString_Loose Jupiter::CString_Loose::gotoWo template Jupiter::CString_Loose Jupiter::CString_Loose::gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) { - unsigned int x = 0; - bool y = true; - for (unsigned int i = 0; i < pos || y == true; x++) - { - if (in.get(x) == 0) return Jupiter::CString_Loose(); - if (Jupiter::strpbrk(whitespace, in.get(x)) != nullptr) - { - if (y == false) - { - y = true; - i++; - } - } - else - { - if (i >= pos) break; - y = false; - } - } - return Jupiter::CString_Loose::substring(in, x); -} - -template size_t Jupiter::CString_Loose::set(const CString_Loose &in) -{ - if (Jupiter::CString_Loose::strSize <= in.length) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::CString_Loose::strSize = in.strSize; - Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = in.length; - Jupiter::strcpy(Jupiter::String_Type::str, in.str); - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::set(const String_Type &in) -{ - size_t sSize = in.size() + 1; - if (Jupiter::CString_Loose::strSize < sSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::CString_Loose::strSize = getPowerTwo32(sSize); - Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = sSize - 1; - size_t index; - for (index = 0; index != Jupiter::String_Type::length && in.get(index) != 0; index++) Jupiter::String_Type::str[index] = in.get(index); - Jupiter::String_Type::length = index; - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::set(const std::basic_string &in) -{ - size_t sSize = in.size() + 1; - if (Jupiter::CString_Loose::strSize < sSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::CString_Loose::strSize = getPowerTwo32(sSize); - Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = sSize - 1; - Jupiter::strcpy(Jupiter::String_Type::str, in.c_str()); - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::set(const T *in) -{ - size_t sSize = Jupiter::strlen(in) + 1; - if (Jupiter::CString_Loose::strSize < sSize) - { - delete[] Jupiter::Shift_String_Type::base; - Jupiter::CString_Loose::strSize = getPowerTwo32(sSize); - Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; - } - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - Jupiter::String_Type::length = sSize - 1; - Jupiter::strcpy(Jupiter::String_Type::str, in); - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::set(const T in) -{ - if (in == 0) - { - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - *Jupiter::String_Type::str = 0; - return Jupiter::String_Type::length = 0; - } - Jupiter::String_Type::length = 1; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - *Jupiter::String_Type::str = in; - Jupiter::String_Type::str[1] = 0; - return 1; + return Jupiter::String_Type::gotoWord(in, pos, whitespace); } -template size_t Jupiter::CString_Loose::concat(const String_Type &in) -{ - size_t nLen = Jupiter::String_Type::length + in.size(); - if (nLen + 1 > Jupiter::CString_Loose::strSize) - { - Jupiter::CString_Loose::strSize = getPowerTwo32(nLen + 1); - T *tmp = new T[Jupiter::CString_Loose::strSize]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - else if (nLen + 1 + (Jupiter::String_Type::str - Jupiter::Shift_String_Type::base) > Jupiter::CString_Loose::strSize) - { - Jupiter::strcpy(Jupiter::Shift_String_Type::base, Jupiter::String_Type::str); - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - size_t index; - for (index = Jupiter::String_Type::length; index < nLen && in.get(index - Jupiter::String_Type::length); index++) Jupiter::String_Type::str[index] = in.get(index - Jupiter::String_Type::length); - Jupiter::String_Type::length = index; - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::concat(const std::basic_string &in) -{ - size_t nLen = Jupiter::String_Type::length + in.size(); - if (nLen + 1 > Jupiter::CString_Loose::strSize) - { - Jupiter::CString_Loose::strSize = getPowerTwo32(nLen + 1); - T *tmp = new T[Jupiter::CString_Loose::strSize]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - else if (nLen + 1 + (Jupiter::String_Type::str - Jupiter::Shift_String_Type::base) > Jupiter::CString_Loose::strSize) - { - Jupiter::strcpy(Jupiter::Shift_String_Type::base, Jupiter::String_Type::str); - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - Jupiter::strcpy(Jupiter::String_Type::str + Jupiter::String_Type::length, in.c_str()); - Jupiter::String_Type::length = nLen; - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::concat(const T *in) -{ - size_t nLen = Jupiter::String_Type::length + Jupiter::strlen(in); - if (nLen + 1 > Jupiter::CString_Loose::strSize) - { - Jupiter::CString_Loose::strSize = getPowerTwo32(nLen + 1); - T *tmp = new T[Jupiter::CString_Loose::strSize]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - else if (nLen + 1 + (Jupiter::String_Type::str - Jupiter::Shift_String_Type::base) > Jupiter::CString_Loose::strSize) - { - Jupiter::strcpy(Jupiter::Shift_String_Type::base, Jupiter::String_Type::str); - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - Jupiter::strcpy(Jupiter::String_Type::str + Jupiter::String_Type::length, in); - Jupiter::String_Type::length = nLen; - return Jupiter::String_Type::length; -} - -template size_t Jupiter::CString_Loose::concat(const T in) -{ - if (Jupiter::String_Type::length + 1 == Jupiter::CString_Loose::strSize) - { - Jupiter::CString_Loose::strSize = getPowerTwo32(Jupiter::CString_Loose::strSize + 1); - T *tmp = new T[Jupiter::CString_Loose::strSize]; - Jupiter::strcpy(tmp, Jupiter::String_Type::str); - delete[] Jupiter::Shift_String_Type::base; - Jupiter::Shift_String_Type::base = tmp; - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - else if (Jupiter::String_Type::length + 1 + (Jupiter::String_Type::str - Jupiter::Shift_String_Type::base) >= Jupiter::CString_Loose::strSize) - { - Jupiter::strcpy(Jupiter::Shift_String_Type::base, Jupiter::String_Type::str); - Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; - } - Jupiter::String_Type::str[Jupiter::String_Type::length] = in; - Jupiter::String_Type::length++; - Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; - return Jupiter::String_Type::length; -} +template const Jupiter::CString_Loose Jupiter::CString_Loose::empty = Jupiter::CString_Loose(); #endif // _CSTRING_IMP_H_HEADER \ No newline at end of file diff --git a/Jupiter/File.cpp b/Jupiter/File.cpp index fdbe8c7..4934b79 100644 --- a/Jupiter/File.cpp +++ b/Jupiter/File.cpp @@ -28,7 +28,7 @@ int64_t getFileSize(const char *file) const size_t defaultBufferSize = 8192; -template class JUPITER_API Jupiter::CString_Strict; +template class JUPITER_API Jupiter::CString_Type; struct JUPITER_API Jupiter::File::Data { diff --git a/Jupiter/IRC_Client.cpp b/Jupiter/IRC_Client.cpp index e234053..78fc326 100644 --- a/Jupiter/IRC_Client.cpp +++ b/Jupiter/IRC_Client.cpp @@ -30,7 +30,7 @@ Jupiter::INIFile _Config; Jupiter::INIFile *Jupiter::IRC::Client::Config = &_Config; -template class JUPITER_API Jupiter::CString_Strict; +template class JUPITER_API Jupiter::CString_Type; template class JUPITER_API Jupiter::ArrayList; template class JUPITER_API Jupiter::ArrayList; diff --git a/Jupiter/Jupiter.vcxproj b/Jupiter/Jupiter.vcxproj index 62616cf..adacc60 100644 --- a/Jupiter/Jupiter.vcxproj +++ b/Jupiter/Jupiter.vcxproj @@ -74,6 +74,8 @@ %(AdditionalIncludeDirectories) Async Speed + 4505 + true Console @@ -133,8 +135,13 @@ + + + + + diff --git a/Jupiter/Jupiter.vcxproj.filters b/Jupiter/Jupiter.vcxproj.filters index 1e27077..2ca4bfb 100644 --- a/Jupiter/Jupiter.vcxproj.filters +++ b/Jupiter/Jupiter.vcxproj.filters @@ -57,9 +57,6 @@ Source Files\IRC - - Source Files\IRC - Source Files\IRC @@ -102,6 +99,9 @@ Source Files + + Source Files\IRC + @@ -188,6 +188,21 @@ Header Files + + Header Files\Strings + + + Header Files\Strings + + + Header Files\Strings + + + Header Files\Strings + + + Header Files\Strings + diff --git a/Jupiter/Shift_String.h b/Jupiter/Shift_String.h index 2314936..c030286 100644 --- a/Jupiter/Shift_String.h +++ b/Jupiter/Shift_String.h @@ -62,7 +62,41 @@ namespace Jupiter */ virtual bool remove(const T &value); + /** + * @brief Default constructor for the Shift_String_Type class. + */ + Shift_String_Type() {} + + /** + * @brief Move constructor for the Shift_String_Type class. + */ + Shift_String_Type(Jupiter::Shift_String_Type &&source); + + /** + * @brief Destructor for the Shift_String_Type class. + */ + virtual ~Shift_String_Type(); + protected: + + /** + * @brief Sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSize(size_t len); + + /** + * @brief Empties the string, and sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This still empties the string if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSizeNoCopy(size_t len); + T *base; /** Base pointer for the underlying String's memory allocation */ }; } diff --git a/Jupiter/Shift_String_Imp.h b/Jupiter/Shift_String_Imp.h index e80fda3..d807d5c 100644 --- a/Jupiter/Shift_String_Imp.h +++ b/Jupiter/Shift_String_Imp.h @@ -24,6 +24,17 @@ * Note: Modification of this file is not supported in any way. */ +template Jupiter::Shift_String_Type::Shift_String_Type(Jupiter::Shift_String_Type &&source) : Jupiter::String_Type(std::move(source)) +{ + Jupiter::Shift_String_Type::base = source.base; + source.base = nullptr; +} + +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; @@ -53,4 +64,33 @@ template bool Jupiter::Shift_String_Type::remove(const T &value) return Jupiter::String_Type::remove(value); } +template bool Jupiter::Shift_String_Type::setBufferSize(size_t len) +{ + if (len > Jupiter::String_Type::length) + { + T *ptr = new T[len]; + for (unsigned int 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; + } + return false; +} + +template bool Jupiter::Shift_String_Type::setBufferSizeNoCopy(size_t len) +{ + if (len > Jupiter::String_Type::length) + { + 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; +} + #endif // _SHIFT_STRING_IMP_H_HEADER \ No newline at end of file diff --git a/Jupiter/String_Type.h b/Jupiter/String_Type.h index a7de4d4..358ee13 100644 --- a/Jupiter/String_Type.h +++ b/Jupiter/String_Type.h @@ -232,10 +232,10 @@ namespace Jupiter * @param in String containing the data to be copied. * @return New size of the String. */ - virtual size_t set(const String_Type &in) = 0; - virtual size_t set(const std::basic_string &in) = 0; - virtual size_t set(const T *in) = 0; - virtual size_t set(const T in) = 0; + virtual size_t set(const String_Type &in); + virtual size_t set(const std::basic_string &in); + virtual size_t set(const T *in); + virtual size_t set(const T in); /** * @brief Copies the data from the input string and concatenates it to the end of String. @@ -243,16 +243,66 @@ namespace Jupiter * @param in String containing the data to be concatenated. * @return New size of the CString. */ - virtual size_t concat(const String_Type &in) = 0; - virtual size_t concat(const std::basic_string &in) = 0; - virtual size_t concat(const T *in) = 0; - virtual size_t concat(const T in) = 0; + virtual size_t concat(const String_Type &in); + virtual size_t concat(const std::basic_string &in); + virtual size_t concat(const T *in); + virtual size_t concat(const T in); + + /** + * @brief Copies a part of an input string and returns it in an output type. + * + * @param R Type to return. Must be a subclass of String_Type. + * + * @param in String to get a partial copy of. + * @param pos Position to start copying from. + * @return Partial copy of the input string. + */ + template class R> static R substring(const Jupiter::String_Type &in, size_t pos); + template class R> static R substring(const T *in, size_t pos); + + /** + * @brief Copies a part of an input string and returns it in an output type. + * + * @param R Type to return. Must be a subclass of String_Type. + * + * @param in String to get a partial copy of. + * @param pos Position to start copying from. + * @param len Number of elements to copy. + * @return Partial copy of the input string. + */ + template class R> static R substring(const Jupiter::String_Type &in, size_t pos, size_t len); + template class R> static R substring(const T *in, size_t pos, size_t len); + + /** + * @brief Copies a "word" from an input string and returns it in an output type. + * + * @param R Type to return. Must be a subclass of String_Type. + * + * @param in String to get a partial copy of. + * @param pos Index of the word to copy. + * @param whitespace String of characters that are to be considered whitespace. + * @return Copy of the word at the specified index on success, an empty string otherwise. + */ + template class R> static R getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); + template class R> static R getWord(const T *in, size_t pos, const T *whitespace); + + /** + * @brief Copies a part of an input string starting at a specified "word" and returns it in an output type. + * + * @param R Type to return. Must be a subclass of String_Type. + * + * @param in String to get a partial copy of. + * @param pos Index of the word to start copying from. + * @param whitespace String of characters that are to be considered whitespace. + * @return Copy of the string starting at the specified word on success, an empty string otherwise. + */ + template class R> static R gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); + template class R> static R gotoWord(const T *in, size_t pos, const T *whitespace); /** Access operator */ inline T &operator[](size_t index) { return Jupiter::String_Type::get(index); }; - // Mutative operators. - // Note: All extending classes must overload operator= for its own type. + /** Mutative operators */ inline String_Type &operator+=(const String_Type &right) { this->concat(right); return *this; }; inline String_Type &operator+=(const std::basic_string &right) { this->concat(right); return *this; }; inline String_Type &operator+=(const T *right) { this->concat(right); return *this; }; @@ -263,7 +313,7 @@ namespace Jupiter inline String_Type &operator=(const T *right) { this->set(right); return *this; }; inline String_Type &operator=(const T right) { this->set(right); return *this; }; - // Comparative operators. + /** Comparative operators */ inline bool operator==(const String_Type &right)const{ return this->equals(right); } inline bool operator==(const std::basic_string &right)const{ return this->equals(right); } inline bool operator==(const T *right)const{ return this->equals(right); } @@ -289,6 +339,16 @@ namespace Jupiter inline bool operator>=(const T *right)const{ return !operator<(right); } inline bool operator>=(const T right)const{ return !operator<(right); } + /** + * @brief Default constructor for the String_Type class. + */ + String_Type() {} + + /** + * @brief Move constructor for the String_Type class. + */ + String_Type(Jupiter::String_Type &&source); + /** * The following constructors should exist: * A default constructor @@ -299,6 +359,25 @@ namespace Jupiter */ protected: + + /** + * @brief Sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSize(size_t len) = 0; + + /** + * @brief Empties the string, and sets the internal buffer to be at least large enough to old a specified number of elements. + * Note: This does nothing if len is less than the string's current length. + * + * @param len Minimum number of elements the string buffer must be able to hold. + * @return True if a new buffer was allocated, false otherwise. + */ + virtual bool setBufferSizeNoCopy(size_t len) = 0; + T *str; /** Pointer for the underlying string of elements */ size_t length; /** Number of representable elements in the string */ }; diff --git a/Jupiter/String_Type_Imp.h b/Jupiter/String_Type_Imp.h index 09abe8d..7bdc687 100644 --- a/Jupiter/String_Type_Imp.h +++ b/Jupiter/String_Type_Imp.h @@ -32,6 +32,12 @@ * String_Type */ +template Jupiter::String_Type::String_Type(Jupiter::String_Type &&source) +{ + Jupiter::String_Type::str = source.str; + source.str = nullptr; +} + template T &Jupiter::String_Type::get(size_t index) const { return Jupiter::String_Type::str[index]; @@ -74,7 +80,19 @@ template int Jupiter::String_Type::compare(const Jupiter::String_ template int Jupiter::String_Type::compare(const std::basic_string &in) const { - return Jupiter::String_Type::compare(in.c_str()); + // rewrite to compare multiple bytes at a time. + size_t index = 0; + while (Jupiter::String_Type::str[index] == in.at(index)) + { + index++; + if (index == in.size()) + { + if (index == Jupiter::String_Type::length) return 0; + return 1; + } + if (index == Jupiter::String_Type::length) return 0 - in.at(index); + } + return Jupiter::String_Type::str[index] - in.at(index); } template int Jupiter::String_Type::compare(const T *s2) const @@ -126,7 +144,14 @@ template bool Jupiter::String_Type::equals(const Jupiter::String_ template bool Jupiter::String_Type::equals(const std::basic_string &in) const { if (Jupiter::String_Type::length != in.size()) return false; - return Jupiter::String_Type::equals(in.c_str()); + // rewrite to compare multiple bytes at a time. + size_t index = 0; + while (index != Jupiter::String_Type::length) + { + if (Jupiter::String_Type::str[index] != in.at(index)) return false; + index++; + } + return true; } template bool Jupiter::String_Type::equals(const T *in) const @@ -152,35 +177,54 @@ template bool Jupiter::String_Type::equals(std::nullptr_t) const // equalsi() +template<> bool inline Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const +{ + if (Jupiter::String_Type::length != in.size()) return false; + for (size_t index = 0; index != Jupiter::String_Type::length; index++) + { + if (toupper(Jupiter::String_Type::str[index]) != toupper(in.str[index])) return false; + } + return true; +} + +template<> bool inline Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const +{ + if (Jupiter::String_Type::length != in.size()) return false; + for (size_t index = 0; index != Jupiter::String_Type::length; index++) + { + if (towupper(Jupiter::String_Type::str[index]) != towupper(in.str[index])) return false; + } + return true; +} + template bool Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const { - return false; // Concept of "case" not supported for type. + return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type. } -template<> bool inline Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const +template<> bool inline Jupiter::String_Type::equalsi(const std::basic_string &in) const { if (Jupiter::String_Type::length != in.size()) return false; for (size_t index = 0; index != Jupiter::String_Type::length; index++) { - if (toupper(Jupiter::String_Type::str[index]) != toupper(in.str[index])) return false; + if (toupper(Jupiter::String_Type::str[index]) != toupper(in.at(index))) return false; } return true; } -template<> bool inline Jupiter::String_Type::equalsi(const Jupiter::String_Type &in) const +template<> bool inline Jupiter::String_Type::equalsi(const std::basic_string &in) const { if (Jupiter::String_Type::length != in.size()) return false; for (size_t index = 0; index != Jupiter::String_Type::length; index++) { - if (toupper(Jupiter::String_Type::str[index]) != toupper(in.str[index])) return false; + if (towupper(Jupiter::String_Type::str[index]) != towupper(in.at(index))) return false; } return true; } template bool Jupiter::String_Type::equalsi(const std::basic_string &in) const { - if (Jupiter::String_Type::length != in.size()) return false; - return Jupiter::String_Type::equalsi(in.c_str()); + return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type. } template<> bool inline Jupiter::String_Type::equalsi(const char *in) const @@ -207,7 +251,7 @@ template<> bool inline Jupiter::String_Type::equalsi(const wchar_t *in) template bool Jupiter::String_Type::equalsi(const T *in) const { - return false; // Concept of "case" not supported for type. + return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type. } template<> bool inline Jupiter::String_Type::equalsi(const char &in) const @@ -222,7 +266,7 @@ template<> bool inline Jupiter::String_Type::equalsi(const wchar_t &in) template bool Jupiter::String_Type::equalsi(const T &in) const { - return false; // Concept of "case" not supported for type. + return Jupiter::String_Type::equals(in); // Concept of "case" not supported for type. } template bool Jupiter::String_Type::equalsi(const std::nullptr_t) const @@ -232,11 +276,6 @@ template bool Jupiter::String_Type::equalsi(const std::nullptr_t) // match() -template bool Jupiter::String_Type::match(const Jupiter::String_Type &format) const -{ - return false; // Wildcard matching not supported for type. -} - template<> bool inline Jupiter::String_Type::match(const Jupiter::String_Type &format) const { size_t index = 0; @@ -297,9 +336,74 @@ template<> bool inline Jupiter::String_Type::match(const Jupiter::Strin return index == Jupiter::String_Type::length; } +template bool Jupiter::String_Type::match(const Jupiter::String_Type &format) const +{ + return false; // Wildcard matching not supported for type. +} + +template<> bool inline Jupiter::String_Type::match(const std::basic_string &format) const +{ + size_t index = 0; + size_t formatIndex = 0; + while (formatIndex != format.size()) + { + if (format.at(formatIndex) == '*') + { + formatIndex++; + while (format.at(formatIndex) == '?') + { + if (Jupiter::String_Type::str[index] == 0) return false; + formatIndex++; + index++; + } + if (format.at(formatIndex) == 0) return true; + if (format.at(formatIndex) == '*') continue; + while (format.at(formatIndex) != Jupiter::String_Type::str[index]) + { + if (Jupiter::String_Type::str[index] == 0) return false; + index++; + } + } + else if (format.at(formatIndex) != '?' && format.at(formatIndex) != Jupiter::String_Type::str[index]) return false; + formatIndex++; + index++; + } + return index == Jupiter::String_Type::length; +} + +template<> bool inline Jupiter::String_Type::match(const std::basic_string &format) const +{ + size_t index = 0; + size_t formatIndex = 0; + while (formatIndex != format.size()) + { + if (format.at(formatIndex) == '*') + { + formatIndex++; + while (format.at(formatIndex) == '?') + { + if (Jupiter::String_Type::str[index] == 0) return false; + formatIndex++; + index++; + } + if (format.at(formatIndex) == 0) return true; + if (format.at(formatIndex) == '*') continue; + while (format.at(formatIndex) != Jupiter::String_Type::str[index]) + { + if (Jupiter::String_Type::str[index] == 0) return false; + index++; + } + } + else if (format.at(formatIndex) != '?' && format.at(formatIndex) != Jupiter::String_Type::str[index]) return false; + formatIndex++; + index++; + } + return index == Jupiter::String_Type::length; +} + template bool Jupiter::String_Type::match(const std::basic_string &format) const { - return Jupiter::String_Type::match(format.c_str()); + return false; // Wildcard matching not supported for type. } template<> inline bool Jupiter::String_Type::match(const char *format) const @@ -362,7 +466,7 @@ template<> inline bool Jupiter::String_Type::match(const wchar_t *forma template bool Jupiter::String_Type::match(const T *format) const { - return false; // Type is not comparable to wildcards. + return false; // Wildcard matching not supported for type. } // matchi() @@ -433,12 +537,76 @@ template<> bool inline Jupiter::String_Type::matchi(const Jupiter::Stri template bool Jupiter::String_Type::matchi(const Jupiter::String_Type &format) const { - return false; + return false; // Wildcard matching not supported for type. Concept of "case" not supported for type. +} + +template<> bool inline Jupiter::String_Type::matchi(const std::basic_string &format) const +{ + int fUpper; + size_t index = 0; + size_t formatIndex = 0; + while (formatIndex != format.size()) + { + if (format.at(formatIndex) == L'*') + { + formatIndex++; + while (format.at(formatIndex) == L'?') + { + if (Jupiter::String_Type::str[index] == 0) return false; + formatIndex++; + index++; + } + if (format.at(formatIndex) == 0) return true; + if (format.at(formatIndex) == '*') continue; + fUpper = toupper(format.at(formatIndex)); + while (fUpper != toupper(Jupiter::String_Type::str[index])) + { + if (Jupiter::String_Type::str[index] == 0) return false; + index++; + } + } + else if (format.at(formatIndex) != L'?' && toupper(format.at(formatIndex)) != toupper(Jupiter::String_Type::str[index])) return false; + formatIndex++; + index++; + } + return index == Jupiter::String_Type::length; +} + +template<> bool inline Jupiter::String_Type::matchi(const std::basic_string &format) const +{ + wint_t fUpper; + size_t index = 0; + size_t formatIndex = 0; + while (formatIndex != format.size()) + { + if (format.at(formatIndex) == L'*') + { + formatIndex++; + while (format.at(formatIndex) == L'?') + { + if (Jupiter::String_Type::str[index] == 0) return false; + formatIndex++; + index++; + } + if (format.at(formatIndex) == 0) return true; + if (format.at(formatIndex) == '*') continue; + fUpper = towupper(format.at(formatIndex)); + while (fUpper != towupper(Jupiter::String_Type::str[index])) + { + if (Jupiter::String_Type::str[index] == 0) return false; + index++; + } + } + else if (format.at(formatIndex) != L'?' && towupper(format.at(formatIndex)) != towupper(Jupiter::String_Type::str[index])) return false; + formatIndex++; + index++; + } + return index == Jupiter::String_Type::length; } template bool Jupiter::String_Type::matchi(const std::basic_string &format) const { - return Jupiter::String_Type::matchi(format.c_str()); + return false; // Wildcard matching not supported for type. Concept of "case" not supported for type. } template<> bool inline Jupiter::String_Type::matchi(const char *format) const @@ -505,7 +673,7 @@ template<> bool inline Jupiter::String_Type::matchi(const wchar_t *form template bool Jupiter::String_Type::matchi(const T *format) const { - return false; // Type is not comparable to wildcards. Concept of "case" not supported for type. + return false; // Wildcard matching not supported for type. Concept of "case" not supported for type. } // wordCount() @@ -582,7 +750,6 @@ template size_t Jupiter::String_Type::println(FILE *out) const { size_t r = Jupiter::String_Type::print(out); if (r != Jupiter::String_Type::length) return r; - // This may change to simply '\n' at a later date. if (fputs("\r\n", out) != EOF) r += 2; return r; } @@ -692,4 +859,231 @@ template bool Jupiter::String_Type::remove(const T &value) return false; } +template size_t Jupiter::String_Type::set(const String_Type &in) +{ + this->setBufferSizeNoCopy(in.size()); + for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length < in.size() != 0; Jupiter::String_Type::length++) + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::set(const std::basic_string &in) +{ + this->setBufferSizeNoCopy(in.size()); + for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length < in.size(); Jupiter::String_Type::length++) + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::set(const T *in) +{ + size_t nLen = Jupiter::strlen(in); + this->setBufferSizeNoCopy(nLen); + for (Jupiter::String_Type::length = 0; *in != 0; Jupiter::String_Type::length++, in++) Jupiter::String_Type::str[Jupiter::String_Type::length] = *in; + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::set(const T in) +{ + this->setBufferSizeNoCopy(1); + *Jupiter::String_Type::str = in; + return Jupiter::String_Type::length = 1; +} + +template size_t Jupiter::String_Type::concat(const String_Type &in) +{ + size_t nSize = Jupiter::String_Type::length + in.size(); + const T *inData = in.ptr(); + this->setBufferSize(nSize); + while (Jupiter::String_Type::length != nSize) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = *inData; + Jupiter::String_Type::length++; + inData++; + } + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::concat(const std::basic_string &in) +{ + size_t nSize = Jupiter::String_Type::length + in.size(); + const T *inData = in.data(); + this->setBufferSize(nSize); + while (Jupiter::String_Type::length != nSize) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = *inData; + Jupiter::String_Type::length++; + inData++; + } + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::concat(const T *in) +{ + size_t nSize = Jupiter::String_Type::length + Jupiter::strlen(in); + this->setBufferSize(nSize); + while (*in != 0) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = *in; + Jupiter::String_Type::length++; + in++; + } + return Jupiter::String_Type::length; +} + +template size_t Jupiter::String_Type::concat(const T c) +{ + this->setBufferSize(Jupiter::String_Type::length + 1); + Jupiter::String_Type::str[Jupiter::String_Type::length] = c; + return ++Jupiter::String_Type::length; +} + +/** +* IMPLEMENTATION: +* String helper templates +*/ + +// substring + +template template class R> R Jupiter::String_Type::substring(const Jupiter::String_Type &in, size_t pos) +{ + if (pos >= in.size()) return R(); + R r = R(in.size() - pos); + for (r.length = 0; pos + r.length != in.size(); r.length++) r.str[r.length] = in.get(pos + r.length); + return r; +} + +template template class R> R Jupiter::String_Type::substring(const Jupiter::String_Type &in, size_t pos, size_t len) +{ + if (pos + len >= in.size()) return R::substring(in, pos); + R r = R(len); + for (r.length = 0; r.length != len; r.length++) r.str[r.length] = in.get(pos + r.length); + return r; +} + +template template class R> R Jupiter::String_Type::substring(const T *in, size_t pos) +{ + size_t strLen = Jupiter::strlen(in); + if (pos >= strLen) return R(); + R r = R(strLen - pos); + in += pos; + for (r.length = 0; *in != 0; r.length++, in++) r.str[r.length] = *in; + return r; +} + +template template class R> R Jupiter::String_Type::substring(const T *in, size_t pos, size_t len) +{ + R r = R(len); + in += pos; + for (r.length = 0; r.length != len; r.length++, in++) r.str[r.length] = *in; + return r; +} + +// getWord + +template template class R> R Jupiter::String_Type::getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + unsigned int x = 0; + unsigned int y = 1; + for (unsigned int i = 0; i < pos || y == 1; x++) + { + if (x == in.size()) return R(); + if (Jupiter::strpbrk(whitespace, in.get(x)) != nullptr) + { + if (y != 1) + { + y = 1; + i++; + } + } + else + { + if (i >= pos) break; + y = 0; + } + } + for (y = x; y != in.size() && Jupiter::strpbrk(whitespace, in.get(y)) == nullptr; y++); + return R::substring(in, x, y - x); +} + +template template class R> R Jupiter::String_Type::getWord(const T *in, size_t pos, const T *whitespace) +{ + unsigned int x = 0; + unsigned int y = 1; + for (unsigned int i = 0; i < pos || y == 1; x++) + { + if (in[x] == 0) return R(); + if (Jupiter::strpbrk(whitespace, in[x]) != nullptr) + { + if (y != 1) + { + y = 1; + i++; + } + } + else + { + if (i >= pos) break; + y = 0; + } + } + for (y = x; in[y] != 0 && Jupiter::strpbrk(whitespace, in[y]) == nullptr; y++); + return R::substring(in, x, y - x); +} + +// gotoWord + +template template class R> R Jupiter::String_Type::gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + unsigned int x = 0; + bool y = true; + for (unsigned int i = 0; i < pos || y == true; x++) + { + if (x == in.size()) return R(); + if (Jupiter::strpbrk(whitespace, in.get(x)) != nullptr) + { + if (y != true) + { + y = true; + i++; + } + } + else + { + if (i >= pos) break; + y = false; + } + } + return R::substring(in, x); +} + +template template class R> R Jupiter::String_Type::gotoWord(const T *in, size_t pos, const T *whitespace) +{ + unsigned int x = 0; + bool y = true; + for (unsigned int i = 0; i < pos || y == true; x++) + { + if (in[x] == 0) return R(); + if (Jupiter::strpbrk(whitespace, in[x]) != nullptr) + { + if (y != true) + { + y = true; + i++; + } + } + else + { + if (i >= pos) break; + y = false; + } + } + return R::substring(in, x); +} + +namespace Jupiter +{ + static struct String_Constructor_Base {} stringConstructorBase; +} + #endif // _STRING_TYPE_IMP_H_HEADER \ No newline at end of file diff --git a/Release/Jupiter.lib b/Release/Jupiter.lib index a6b98c13d95f62961462884fb92e6f16adaa912b..62187fc0a67baa2bfa64dff108e9a1ad327baace 100644 GIT binary patch literal 193990 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 DZzrUr diff --git a/Tester/Tester.vcxproj b/Tester/Tester.vcxproj index e055047..b825fc1 100644 --- a/Tester/Tester.vcxproj +++ b/Tester/Tester.vcxproj @@ -73,6 +73,7 @@ true true true + MachineX86