diff --git a/Jupiter/String.h b/Jupiter/String.h new file mode 100644 index 0000000..10d900e --- /dev/null +++ b/Jupiter/String.h @@ -0,0 +1,417 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _STRING_H_HEADER +#define _STRING_H_HEADER + +/** + * @file String.h + * @brief Defines the base String_Base, as well as a series of String types. + * Note: Functions which take "case" or "wildcards" into consideration will only function + * for types char and wchar_t; inputs with other types will simply return false. + */ + +#include "Shift_String.h" + +namespace Jupiter +{ + + /** + * @brief Provides a minimal String implementation (i.e: no extra variables). + * + * @param T Element type which the String will store. Defaults to char. + */ + template class String_Strict : public Shift_String_Type + { + public: + + /** + * @brief Returns a C-Style string representation of the String. + * + * @return C-Style string representation of the String. + */ + const T *c_str() const; + + /** + * @brief Sets the String'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 args Inputs to match the format specifiers. + * @return Number of characters written. + */ + size_t vformat(const T *format, va_list args); + + /** + * @brief Appends to a String'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 args Inputs to match the format specifiers. + * @return Number of characters written. + */ + size_t avformat(const T *format, va_list args); + + /** + * @brief Sets the String'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 String containing the new format. + */ + static String_Strict Format(const T *format, ...); + + /** + * @brief Creates a partial copy of the string. + * + * @param pos Position in the string to start copying from. + * @return String containing a partial copy of the original string. + */ + String_Strict substring(size_t pos) const; + + /** + * @brief Creates a partial copy of the string. + * + * @param pos Position in the string to start copying from. + * @param length Number of characters to copy. + * @return String containing a partial copy of the original string. + */ + String_Strict substring(size_t pos, size_t length) const; + + /** + * @brief Creates a partial copy of the string. + * + * @param in String to get a partial copy of. + * @param pos Position in the string to start copying from. + * @return String containing a partial copy of the original string. + */ + static String_Strict substring(const Jupiter::String_Type &in, size_t pos); + static String_Strict substring(const T *in, size_t pos); + + /** + * @brief Creates a partial copy of the string. + * + * @param in String to get a partial copy of. + * @param pos Position in the string to start copying from. + * @param length Number of characters to copy. + * @return String containing a partial copy of the original string. + */ + static String_Strict substring(const Jupiter::String_Type &in, size_t pos, size_t length); + static String_Strict substring(const T *in, size_t pos, size_t length); + + /** + * @brief Creates a partial copy of the string, based on a set of tokens. + * + * @param pos Position of word in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + String_Strict getWord(size_t pos, const T *whitespace) const; + + /** + * @brief Creates a partial copy of an input string, based on a set of tokens. + * + * @param in String to get a partial copy of. + * @param pos Position of word in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + static String_Strict 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. + * + * @param in C-Style string to get a partial copy of. + * @param pos Position of word in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + static String_Strict getWord(const T *in, size_t pos, const T *whitespace); + + /** + * @brief Creates a partial copy of the string, based on a set of tokens. + * + * @param pos Position in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + String_Strict gotoWord(size_t pos, const T *whitespace) const; + + /** + * @brief Creates a partial copy of the string, based on a set of tokens. + * + * @param in String to get a partial copy of. + * @param pos Position in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + static String_Strict gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); + + /** Assignment Operators */ + inline String_Strict &operator=(const String_Strict &right) { this->set(right); return *this; }; + inline String_Strict &operator=(const String_Type &right) { this->set(right); return *this; }; + inline String_Strict &operator=(const std::basic_string &right) { this->set(right); return *this; }; + inline String_Strict &operator=(const T *right) { this->set(right); return *this; }; + inline String_Strict &operator=(const T right) { this->set(right); return *this; }; + + static const Jupiter::String_Strict empty; /** Empty instantation of String_Strict */ + + /** Default Constructor */ + String_Strict(); + + /** + * @brief Size hint constructor. + * Note: For the String_Strict base class, this is only truly useful internally. + * + * @param size Minimum number of elements the string must be able to hold. + */ + String_Strict(size_t size); + + /** Move Constructor */ + String_Strict(String_Strict &&source); + + /** Copy Constructors */ + String_Strict(const String_Strict &in) : String_Strict((String_Type &)in) {} + String_Strict(const String_Type &in); + String_Strict(const std::basic_string &in); + String_Strict(const T *in); + + protected: + + /** Dummy constructor to prevent string initialization */ + String_Strict(Jupiter::String_Constructor_Base &) {}; + }; + + /** + * @brief Provides a "loose" String implementation that's more optimized for repeated concatenations. + * Note: The underlying string will always have a size which is a power of 2, but no fewer than 8 elements. + * + * @param T Element type which the String will store. Defaults to char. + */ + template class String_Loose : public Shift_String_Type + { + public: + + /** + * @brief Returns a C-Style string representation of the String. + * + * @return C-Style string representation of the String. + */ + const T *c_str() const; + + /** + * @brief Sets the String'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 args Inputs to match the format specifiers. + * @return Number of characters written. + */ + size_t vformat(const T *format, va_list args); + + /** + * @brief Appends to a String'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 args Inputs to match the format specifiers. + * @return Number of characters written. + */ + size_t avformat(const T *format, va_list args); + + /** + * @brief Sets the String'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 String containing the new format. + */ + static String_Loose Format(const T *format, ...); + + /** + * @brief Creates a partial copy of the string. + * + * @param pos Position in the string to start copying from. + * @return String containing a partial copy of the original string. + */ + String_Loose substring(size_t pos) const; + + /** + * @brief Creates a partial copy of the string. + * + * @param pos Position in the string to start copying from. + * @param length Number of characters to copy. + * @return String containing a partial copy of the original string. + */ + String_Loose substring(size_t pos, size_t length) const; + + /** + * @brief Creates a partial copy of the string. + * + * @param in String to get a partial copy of. + * @param pos Position in the string to start copying from. + * @return String containing a partial copy of the original string. + */ + static String_Loose substring(const Jupiter::String_Type &in, size_t pos); + static String_Loose substring(const T *in, size_t pos); + + /** + * @brief Creates a partial copy of the string. + * + * @param in String to get a partial copy of. + * @param pos Position in the string to start copying from. + * @param length Number of characters to copy. + * @return String containing a partial copy of the original string. + */ + static String_Loose substring(const Jupiter::String_Type &in, size_t pos, size_t length); + static String_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. + * + * @param pos Position in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + String_Loose getWord(size_t pos, const T *whitespace) const; + + /** + * @brief Creates a partial copy of an input string, based on a set of tokens. + * Useful when the input string's type isn't known. + * + * @param in String to get a partial copy of. + * @param pos Position of word in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + static String_Loose 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. + * Useful when the input string's type isn't known. + * + * @param in C-Style string to get a partial copy of. + * @param pos Position of word in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + static String_Loose getWord(const T *in, size_t pos, const T *whitespace); + + /** + * @brief Creates a partial copy of the string, based on a set of tokens. + * + * @param pos Position in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + String_Loose gotoWord(size_t pos, const T *whitespace) const; + + /** + * @brief Creates a partial copy of the string, based on a set of tokens. + * + * @param in String to get a partial copy of. + * @param pos Position in the string to start copying from. + * @param whitespace A string of tokens used to deliminate words. + * @return String containing a partial copy of the original string. + */ + static String_Loose gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace); + + /** Default constructor */ + String_Loose(); + + /** + * @brief Size hint constructor. + * + * @param size Minimum number of elements the string must be able to hold. + */ + String_Loose(size_t size); + + /** Move Constructor */ + String_Loose(String_Loose &&source); + + /** Copy Constructors */ + String_Loose(const String_Loose &in); + String_Loose(const String_Type &in); + String_Loose(const std::basic_string &in); + String_Loose(const T *in); + + static const Jupiter::String_Loose empty; /** Empty instantation of String_Loose */ + static const size_t start_size = 8; /** Starting size for loose Strings. */ + + /** Assignment Operators */ + inline String_Loose &operator=(const String_Loose &right) { this->set(right); return *this; }; + inline String_Loose &operator=(const String_Type &right) { this->set(right); return *this; }; + inline String_Loose &operator=(const std::basic_string &right) { this->set(right); return *this; }; + inline String_Loose &operator=(const T *right) { this->set(right); return *this; }; + inline String_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 */ + String_Loose(Jupiter::String_Constructor_Base &) {}; + + size_t strSize; /** Size of underlying string buffer */ + }; + + /** Definition of a Loose String. */ + typedef String_Loose StringL; + + /** Definition of a Loose Wide String */ + typedef String_Loose WStringL; + + /** Definition of a Strict String. */ + typedef String_Strict StringS; + + /** Definition of a Strict Wide String */ + typedef String_Strict WStringS; + + /** Definition of a String. */ + typedef StringL String; + + /** Definition of a Wide String */ + typedef WStringL WString; + + /** Empty String constants */ + static const Jupiter::StringS &emptyStringS = Jupiter::StringS::empty; + static const Jupiter::StringL &emptyStringL = Jupiter::StringL::empty; + //static const Jupiter::StringType &emptyString = emptyStringS; +} + +/** Implementation for String_Strict and String_Loose. Very scary. */ +#include "String_Imp.h" + +#endif // _STRING_H_HEADER \ No newline at end of file diff --git a/Jupiter/String_Imp.h b/Jupiter/String_Imp.h new file mode 100644 index 0000000..23299d4 --- /dev/null +++ b/Jupiter/String_Imp.h @@ -0,0 +1,484 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _STRING_IMP_H_HEADER +#define _STRING_IMP_H_HEADER + +/** +* @file String_Imp.h +* @brief Provides the implementations for String_Strict and String_Loose. +* Note: Modification of this file is not supported in any way. +*/ + +#include "String.h" + +#if !defined va_copy + +#if defined __INTEL_COMPILER +#pragma message("Warning: va_copy not properly defined. Assuming common implementation.") +#define va_copy(dst, src) ((void)((dst) = (src))) +#else +#error "va_copy not defined." +#endif // __INTEL_COMPILER + +#endif // va_copy + +/** +* IMPLEMENTATION: +* String_Strict +*/ + +template Jupiter::String_Strict::String_Strict() : Jupiter::String_Strict::String_Strict(size_t(0)) +{ +} + +template Jupiter::String_Strict::String_Strict(size_t len) +{ + Jupiter::Shift_String_Type::base = new T[len]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + Jupiter::String_Type::length = 0; +} + +template Jupiter::String_Strict::String_Strict(Jupiter::String_Strict &&source) : Jupiter::Shift_String_Type(std::move(source)) +{ +} + +template Jupiter::String_Strict::String_Strict(const Jupiter::String_Type &in) : Jupiter::String_Strict::String_Strict(in.size()) +{ + while (Jupiter::String_Type::length < in.size()) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } +} + +template Jupiter::String_Strict::String_Strict(const std::basic_string &in) : Jupiter::String_Strict::String_Strict(in.size()) +{ + while (Jupiter::String_Type::length < in.size()) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } +} + +template Jupiter::String_Strict::String_Strict(const T *in) +{ + if (in == nullptr) Jupiter::String_Type::length = 0; + else Jupiter::String_Type::length = Jupiter::strlen(in); + + Jupiter::Shift_String_Type::base = new T[Jupiter::String_Type::length]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + for (size_t index = 0; *in != 0; index++, in++) Jupiter::String_Type::str[index] = *in; +} + +template const T *Jupiter::String_Strict::c_str() const +{ + static T *buff = new T[1]; + delete[] buff; + + buff = new T[Jupiter::String_Type::length + 1]; + size_t index; + for (index = 0; index < Jupiter::String_Type::length && Jupiter::String_Type::str[index] != 0; index++) buff[index] = Jupiter::String_Type::str[index]; + buff[index] = 0; + + return buff; +} + +// vformat() + +template<> size_t inline Jupiter::String_Strict::vformat(const char *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vsnprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + + this->setBufferSizeNoCopy(minLen + 1); // vsnprintf REQUIRES space for an additional null character. + minLen = vsnprintf(Jupiter::String_Type::str, Jupiter::String_Type::length + 1, format, args); + if (minLen < 0) return 0; + return Jupiter::String_Type::length = minLen; +} + +template<> size_t inline Jupiter::String_Strict::vformat(const wchar_t *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vswprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + + this->setBufferSizeNoCopy(minLen + 1); // vsnprintf REQUIRES space for an additional null character. + minLen = vswprintf(Jupiter::String_Type::str, Jupiter::String_Type::length + 1, format, args); + if (minLen < 0) return 0; + return Jupiter::String_Type::length = minLen; +} + +template size_t Jupiter::String_Strict::vformat(const T *format, va_list args) +{ + return 0; +} + +// avformat() + +template<> size_t inline Jupiter::String_Strict::avformat(const char *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vsnprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + + this->setBufferSize(Jupiter::String_Type::length + minLen + 1); // vsnprintf REQUIRES space for an additional null character. + minLen = vsnprintf(Jupiter::String_Type::str + Jupiter::String_Type::length + 1, minLen, format, args); + if (minLen <= 0) return 0; + Jupiter::String_Type::length += minLen; + return minLen; +} + +template<> size_t inline Jupiter::String_Strict::avformat(const wchar_t *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vswprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + this->setBufferSize(minLen + Jupiter::String_Type::length + 1); // vsnprintf REQUIRES space for an additional null character. + + minLen = vswprintf(Jupiter::String_Type::str + Jupiter::String_Type::length + 1, minLen, format, args); + if (minLen <= 0) return 0; + Jupiter::String_Type::length += minLen; + return minLen; +} + +template size_t Jupiter::String_Strict::avformat(const T *format, va_list args) +{ + return 0; +} + +template Jupiter::String_Strict Jupiter::String_Strict::Format(const T *format, ...) +{ + String_Strict r; + va_list args; + va_start(args, format); + r.vformat(format, args); + va_end(args); + return r; +} + +template Jupiter::String_Strict Jupiter::String_Strict::substring(size_t pos) const +{ + return Jupiter::String_Strict::substring(*this, pos); +} + +template Jupiter::String_Strict Jupiter::String_Strict::substring(size_t pos, size_t len) const +{ + return Jupiter::String_Strict::substring(*this, pos, len); +} + +template Jupiter::String_Strict Jupiter::String_Strict::substring(const Jupiter::String_Type &in, size_t pos) +{ + return Jupiter::String_Type::substring(in, pos); +} + +template Jupiter::String_Strict Jupiter::String_Strict::substring(const T *in, size_t pos) +{ + return Jupiter::String_Type::substring(in, pos); +} + +template Jupiter::String_Strict Jupiter::String_Strict::substring(const Jupiter::String_Type &in, size_t pos, size_t len) +{ + return Jupiter::String_Type::substring(in, pos, len); +} + +template Jupiter::String_Strict Jupiter::String_Strict::substring(const T *in, size_t pos, size_t len) +{ + return Jupiter::String_Type::substring(in, pos, len); +} + +template Jupiter::String_Strict Jupiter::String_Strict::getWord(size_t pos, const T *whitespace) const +{ + return Jupiter::String_Strict::getWord(*this, pos, whitespace); +} + +template Jupiter::String_Strict Jupiter::String_Strict::getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::getWord(in, pos, whitespace); +} + +template Jupiter::String_Strict Jupiter::String_Strict::getWord(const T *in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::getWord(in, pos, whitespace); +} + +template Jupiter::String_Strict Jupiter::String_Strict::gotoWord(size_t pos, const T *whitespace) const +{ + return Jupiter::String_Strict::gotoWord(*this, pos, whitespace); +} + +template Jupiter::String_Strict Jupiter::String_Strict::gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::gotoWord(in, pos, whitespace); +} + +template const Jupiter::String_Strict Jupiter::String_Strict::empty = Jupiter::String_Strict(); + +/** +* IMPLEMENTATION: +* String_Loose +*/ + +template Jupiter::String_Loose::String_Loose() : Jupiter::String_Loose::String_Loose(Jupiter::String_Loose::start_size) +{ +} + +template Jupiter::String_Loose::String_Loose(Jupiter::String_Loose &&source) : Jupiter::Shift_String_Type(std::move(source)) +{ + Jupiter::String_Loose::strSize = source.strSize; + source.strSize = 0; +} + +template Jupiter::String_Loose::String_Loose(size_t len) +{ + if (len > Jupiter::String_Loose::start_size) Jupiter::String_Loose::strSize = len; + else Jupiter::String_Loose::strSize = Jupiter::String_Loose::start_size; + + Jupiter::Shift_String_Type::base = new T[Jupiter::String_Loose::strSize]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + Jupiter::String_Type::length = 0; +} + +template Jupiter::String_Loose::String_Loose(const Jupiter::String_Loose &in) +{ + Jupiter::String_Loose::strSize = in.strSize; + Jupiter::Shift_String_Type::base = new T[Jupiter::String_Loose::strSize]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length != in.length; Jupiter::String_Type::length++) + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); +} + +template Jupiter::String_Loose::String_Loose(const Jupiter::String_Type &in) : Jupiter::String_Loose::String_Loose(in.size()) +{ + while (Jupiter::String_Type::length < in.size()) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } +} + +template Jupiter::String_Loose::String_Loose(const std::basic_string &in) : Jupiter::String_Loose::String_Loose(in.size()) +{ + while (Jupiter::String_Type::length < in.size()) + { + Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); + Jupiter::String_Type::length++; + } +} + +template Jupiter::String_Loose::String_Loose(const T *in) +{ + if (in == nullptr) + { + Jupiter::String_Loose::strSize = Jupiter::String_Loose::start_size; + Jupiter::Shift_String_Type::base = new T[Jupiter::String_Loose::strSize]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + Jupiter::String_Type::length = 0; + } + else + { + Jupiter::String_Type::length = Jupiter::strlen(in); + + Jupiter::String_Loose::strSize = getPowerTwo32(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]; + Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; + for (Jupiter::String_Type::length = 0; *in != 0; Jupiter::String_Type::length++, in++) Jupiter::String_Type::str[Jupiter::String_Type::length] = *in; + } +} + +template bool Jupiter::String_Loose::setBufferSize(size_t len) +{ + return Jupiter::Shift_String_Type::setBufferSize(Jupiter::String_Loose::strSize = getPowerTwo32(len)); +} + +template bool Jupiter::String_Loose::setBufferSizeNoCopy(size_t len) +{ + return Jupiter::Shift_String_Type::setBufferSizeNoCopy(Jupiter::String_Loose::strSize = getPowerTwo32(len)); +} + +template const T *Jupiter::String_Loose::c_str() const +{ + static T *buff = new T[1]; + delete[] buff; + + buff = new T[Jupiter::String_Type::length + 1]; + size_t index; + for (index = 0; index < Jupiter::String_Type::length && Jupiter::String_Type::str[index] != 0; index++) buff[index] = Jupiter::String_Type::str[index]; + buff[index] = 0; + + return buff; +} + +// vformat() + +template<> size_t inline Jupiter::String_Loose::vformat(const char *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vsnprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + + this->setBufferSizeNoCopy(minLen + 1); // vsnprintf REQUIRES space for an additional null character. + minLen = vsnprintf(Jupiter::String_Type::str, Jupiter::String_Type::length + 1, format, args); + if (minLen < 0) return 0; + return Jupiter::String_Type::length = minLen; +} + +template<> size_t inline Jupiter::String_Loose::vformat(const wchar_t *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vswprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + + this->setBufferSizeNoCopy(minLen + 1); // vsnprintf REQUIRES space for an additional null character. + minLen = vswprintf(Jupiter::String_Type::str, Jupiter::String_Type::length + 1, format, args); + if (minLen < 0) return 0; + return Jupiter::String_Type::length = minLen; +} + +template size_t Jupiter::String_Loose::vformat(const T *format, va_list args) +{ + return 0; +} + +// avformat() + +template<> size_t inline Jupiter::String_Loose::avformat(const char *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vsnprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + + this->setBufferSize(Jupiter::String_Type::length + minLen + 1); // vsnprintf REQUIRES space for an additional null character. + minLen = vsnprintf(Jupiter::String_Type::str + Jupiter::String_Type::length + 1, minLen, format, args); + if (minLen <= 0) return 0; + Jupiter::String_Type::length += minLen; + return minLen; +} + +template<> size_t inline Jupiter::String_Loose::avformat(const wchar_t *format, va_list args) +{ + int minLen; + va_list sargs; + va_copy(sargs, args); + minLen = vswprintf(nullptr, 0, format, sargs); + va_end(sargs); + if (minLen < 0) return 0; // We simply can not work with this. + this->setBufferSize(minLen + Jupiter::String_Type::length + 1); // vsnprintf REQUIRES space for an additional null character. + + minLen = vswprintf(Jupiter::String_Type::str + Jupiter::String_Type::length + 1, minLen, format, args); + if (minLen <= 0) return 0; + Jupiter::String_Type::length += minLen; + return minLen; +} + +template size_t Jupiter::String_Loose::avformat(const T *format, va_list args) +{ + return 0; +} + +template Jupiter::String_Loose Jupiter::String_Loose::Format(const T *format, ...) +{ + String_Loose r; + va_list args; + va_start(args, format); + r.vformat(format, args); + va_end(args); + return r; +} + +template Jupiter::String_Loose Jupiter::String_Loose::substring(size_t pos) const +{ + return Jupiter::String_Loose::substring(*this, pos); +} + +template Jupiter::String_Loose Jupiter::String_Loose::substring(size_t pos, size_t length) const +{ + return Jupiter::String_Loose::substring(*this, pos, length); +} + +template Jupiter::String_Loose Jupiter::String_Loose::substring(const Jupiter::String_Type &in, size_t pos) +{ + return Jupiter::String_Type::substring(in, pos); +} + +template Jupiter::String_Loose Jupiter::String_Loose::substring(const T *in, size_t pos) +{ + return Jupiter::String_Type::substring(in, pos); +} + +template Jupiter::String_Loose Jupiter::String_Loose::substring(const Jupiter::String_Type &in, size_t pos, size_t len) +{ + return Jupiter::String_Type::substring(in, pos, len); +} + +template Jupiter::String_Loose Jupiter::String_Loose::substring(const T *in, size_t pos, size_t len) +{ + return Jupiter::String_Type::substring(in, pos, len); +} + +template Jupiter::String_Loose Jupiter::String_Loose::getWord(size_t pos, const T *whitespace) const +{ + return Jupiter::String_Loose::getWord(*this, pos, whitespace); +} + +template Jupiter::String_Loose Jupiter::String_Loose::getWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::getWord(in, pos, whitespace); +} + +template Jupiter::String_Loose Jupiter::String_Loose::getWord(const T *in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::getWord(in, pos, whitespace); +} + +template Jupiter::String_Loose Jupiter::String_Loose::gotoWord(size_t pos, const T *whitespace) const +{ + return Jupiter::String_Loose::gotoWord(*this, pos, whitespace); +} + +template Jupiter::String_Loose Jupiter::String_Loose::gotoWord(const Jupiter::String_Type &in, size_t pos, const T *whitespace) +{ + return Jupiter::String_Type::gotoWord(in, pos, whitespace); +} + +template const Jupiter::String_Loose Jupiter::String_Loose::empty = Jupiter::String_Loose(); + +#endif // _STRING_IMP_H_HEADER \ No newline at end of file diff --git a/Release/Jupiter.lib b/Release/Jupiter.lib index 00b54d5..f92f4c1 100644 Binary files a/Release/Jupiter.lib and b/Release/Jupiter.lib differ