mirror of https://github.com/JAJames/Jupiter.git
Jessica James
5 years ago
24 changed files with 262 additions and 2528 deletions
@ -1,570 +0,0 @@ |
|||
/**
|
|||
* Copyright (C) 2013-2017 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _CSTRING_H_HEADER |
|||
#define _CSTRING_H_HEADER |
|||
|
|||
/**
|
|||
* @file CString.h |
|||
* @brief Defines the base CString_Type, as well as a series of CString 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" |
|||
|
|||
/** Disable warning 4458 */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(push) |
|||
#pragma warning(disable: 4458) // declaration of 'length' hides class member
|
|||
#endif |
|||
|
|||
namespace Jupiter |
|||
{ |
|||
/**
|
|||
* @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. |
|||
*/ |
|||
template<typename T = char> class CString_Type : public Shift_String_Type<T> |
|||
{ |
|||
public: |
|||
|
|||
/**
|
|||
* @brief Returns the C-Style string behind the CString. |
|||
* |
|||
* @return C-Style string that the CString represents. |
|||
*/ |
|||
const T *c_str() const; |
|||
|
|||
/**
|
|||
* @brief Truncates the string by a specified number of elements. |
|||
* |
|||
* @param n Number of elements to remove from the tail. |
|||
* @return New size of the CString. |
|||
*/ |
|||
size_t truncate(size_t n); |
|||
|
|||
/**
|
|||
* @brief Removes the first instance of an element from the string. |
|||
* |
|||
* @param value Value of the element to remove. |
|||
* @return True if an element was removed, false otherwise. |
|||
*/ |
|||
bool remove(const T &value); |
|||
|
|||
/**
|
|||
* @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 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 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 args 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. |
|||
* |
|||
* @param format Format that the string is compared against. |
|||
* @param ... Inputs to match the format specifiers. |
|||
* @return String containing the new format. |
|||
*/ |
|||
static CString_Type 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. |
|||
*/ |
|||
CString_Type<T> 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. |
|||
*/ |
|||
CString_Type<T> 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 CString_Type<T> substring(const Jupiter::Readable_String<T> &in, size_t pos); |
|||
static CString_Type<T> 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 CString_Type<T> substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t length); |
|||
static CString_Type<T> 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. |
|||
*/ |
|||
CString_Type<T> 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 CString_Type<T> getWord(const Jupiter::Readable_String<T> &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 CString_Type<T> 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. |
|||
*/ |
|||
CString_Type<T> 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 CString_Type<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace); |
|||
|
|||
/**
|
|||
* @brief Tokenizes a string, based on an input token separator |
|||
* |
|||
* @param separator Separator to split tokens by |
|||
* @return TokenizeResult containing the results of the tokenization process. |
|||
*/ |
|||
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const T &separator) const; |
|||
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &separator) const; |
|||
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const T *separator, size_t separator_size) const; |
|||
|
|||
/**
|
|||
* @brief Tokenizes a string, based on an input token separator |
|||
* |
|||
* @param in String to split into tokens |
|||
* @param separator Separator to split tokens by |
|||
* @return TokenizeResult containing the results of the tokenization process. |
|||
*/ |
|||
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &in, const T &separator); |
|||
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator); |
|||
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size); |
|||
|
|||
/**
|
|||
* @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 T *in, size_t inSize) override; |
|||
size_t set(const Jupiter::Readable_String<T> &in) override; |
|||
size_t set(const std::basic_string<T> &in) override; |
|||
size_t set(const T *in) override; |
|||
size_t set(const T &in) override; |
|||
|
|||
/**
|
|||
* @brief Copies the data from the input string and concatenates 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 T *in, size_t inSize) override; |
|||
size_t concat(const Readable_String<T> &in) override; |
|||
size_t concat(const std::basic_string<T> &in) override; |
|||
size_t concat(const T *in) override; |
|||
size_t concat(const T &in) override; |
|||
|
|||
/**
|
|||
* @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) override; |
|||
|
|||
/**
|
|||
* @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) override; |
|||
|
|||
/** Default Constructor */ |
|||
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<T> &&source); |
|||
|
|||
/** Copy Constructors */ |
|||
CString_Type(const CString_Type<T> &in) : CString_Type((Readable_String<T> &)in) {} |
|||
CString_Type(const Readable_String<T> &in); |
|||
CString_Type(const std::basic_string<T> &in); |
|||
CString_Type(const T *in, size_t len); |
|||
CString_Type(const T *in); |
|||
|
|||
/** Concatenation Constructors */ |
|||
CString_Type(const Readable_String<T> &lhs, const T &rhs); |
|||
CString_Type(const Readable_String<T> &lhs, const Readable_String<T> &rhs); |
|||
CString_Type(const Readable_String<T> &lhs, const std::basic_string<T> &rhs); |
|||
CString_Type(const Readable_String<T> &lhs, const T *rhs); |
|||
CString_Type(const Readable_String<T> &lhs, const T *rhs, size_t rhs_size); |
|||
|
|||
/** Addition Operators */ |
|||
inline CString_Type<T> operator+(const T &rhs) const; |
|||
inline CString_Type<T> operator+(const CString_Type<T> &rhs) const; |
|||
inline CString_Type<T> operator+(const Readable_String<T> &rhs) const; |
|||
inline CString_Type<T> operator+(const std::basic_string<T> &rhs) const; |
|||
inline CString_Type<T> operator+(const T *rhs) const; |
|||
|
|||
/** Assignment Operators */ |
|||
inline CString_Type<T> &operator=(const CString_Type<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Type<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Type<T> &operator=(const std::basic_string<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Type<T> &operator=(const T *right) { this->set(right); return *this; }; |
|||
inline CString_Type<T> &operator=(const T right) { this->set(right); return *this; }; |
|||
|
|||
static const Jupiter::CString_Type<T> empty; /** Empty instantiation of CString_Type */ |
|||
|
|||
protected: |
|||
/** Dummy constructor to prevent string initialization */ |
|||
CString_Type(Jupiter::String_Constructor_Base &) {}; |
|||
}; |
|||
template<typename T = char> using CString_Strict = CString_Type<T>; |
|||
|
|||
#if defined JUPITER_CSTRING_TYPE_OPERATOR_PLUS |
|||
/** String_Loose<T> Addition Operator */ |
|||
template<typename T> static inline Jupiter::CString_Type<T> operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs); |
|||
#endif // JUPITER_CSTRING_TYPE_OPERATOR_PLUS
|
|||
|
|||
/**
|
|||
* @brief Provides a "loose" CString implementation that's more optimized for repeated concatenations. |
|||
* Note: The underlying C-style string will always have a size which is a power of 2, but no fewer than 8 elements. |
|||
* |
|||
* @param T Element type which the CString will store. Defaults to char. |
|||
*/ |
|||
template<typename T = char> class CString_Loose : public CString_Type<T> |
|||
{ |
|||
public: |
|||
|
|||
/**
|
|||
* @brief Returns the maximum number of elements the String can contain, |
|||
* without expanding the socket buffer. This is generally the size of the |
|||
* underlying memory buffer. |
|||
* |
|||
* @return Number of elements the string can contain without reallocation. |
|||
*/ |
|||
virtual size_t capacity() const; |
|||
|
|||
/**
|
|||
* @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 String containing the new format. |
|||
*/ |
|||
static CString_Loose<T> 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. |
|||
*/ |
|||
CString_Loose<T> 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. |
|||
*/ |
|||
CString_Loose<T> 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 CString_Loose<T> substring(const Jupiter::Readable_String<T> &in, size_t pos); |
|||
static CString_Loose<T> 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 CString_Loose<T> substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t length); |
|||
static CString_Loose<T> 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. |
|||
*/ |
|||
CString_Loose<T> 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 CString_Loose<T> getWord(const Jupiter::Readable_String<T> &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 CString_Loose<T> 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. |
|||
*/ |
|||
CString_Loose<T> 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 CString_Loose<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace); |
|||
|
|||
/**
|
|||
* @brief Tokenizes a string, based on an input token separator |
|||
* |
|||
* @param separator Separator to split tokens by |
|||
* @return TokenizeResult containing the results of the tokenization process. |
|||
*/ |
|||
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const T &separator); |
|||
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &separator); |
|||
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const T *separator, size_t separator_size); |
|||
|
|||
/**
|
|||
* @brief Tokenizes a string, based on an input token separator |
|||
* |
|||
* @param in String to split into tokens |
|||
* @param separator Separator to split tokens by |
|||
* @return TokenizeResult containing the results of the tokenization process. |
|||
*/ |
|||
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &in, const T &separator); |
|||
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator); |
|||
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size); |
|||
|
|||
/**
|
|||
* @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) override; |
|||
|
|||
/**
|
|||
* @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) override; |
|||
|
|||
/** Default constructor */ |
|||
CString_Loose(); |
|||
|
|||
/**
|
|||
* @brief Size hint constructor. |
|||
* |
|||
* @param size Minimum number of elements the string must be able to hold. |
|||
*/ |
|||
CString_Loose(size_t size); |
|||
|
|||
/** Move Constructor */ |
|||
CString_Loose(CString_Loose<T> &&source); |
|||
|
|||
/** Copy Constructors */ |
|||
CString_Loose(const CString_Loose<T> &in); |
|||
CString_Loose(const Readable_String<T> &in); |
|||
CString_Loose(const std::basic_string<T> &in); |
|||
CString_Loose(const T *in, size_t len); |
|||
CString_Loose(const T *in); |
|||
|
|||
/** Concatenation Constructors */ |
|||
CString_Loose(const Readable_String<T> &lhs, const T &rhs); |
|||
CString_Loose(const Readable_String<T> &lhs, const Readable_String<T> &rhs); |
|||
CString_Loose(const Readable_String<T> &lhs, const std::basic_string<T> &rhs); |
|||
CString_Loose(const Readable_String<T> &lhs, const T *rhs); |
|||
CString_Loose(const Readable_String<T> &lhs, const T *rhs, size_t rhs_size); |
|||
|
|||
/** Addition Operators */ |
|||
inline CString_Loose<T> operator+(const T &rhs) const; |
|||
inline CString_Loose<T> operator+(const CString_Loose<T> &rhs) const; |
|||
inline CString_Loose<T> operator+(const Readable_String<T> &rhs) const; |
|||
inline CString_Loose<T> operator+(const std::basic_string<T> &rhs) const; |
|||
inline CString_Loose<T> operator+(const T *rhs) const; |
|||
|
|||
/** Assignment Operators */ |
|||
inline CString_Loose<T> &operator=(const CString_Loose<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Loose<T> &operator=(const CString_Type<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Loose<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Loose<T> &operator=(const std::basic_string<T> &right) { this->set(right); return *this; }; |
|||
inline CString_Loose<T> &operator=(const T *right) { this->set(right); return *this; }; |
|||
inline CString_Loose<T> &operator=(const T right) { this->set(right); return *this; }; |
|||
|
|||
static const Jupiter::CString_Loose<T> empty; /** Empty instantiation of CString_Loose */ |
|||
static const size_t start_size = 8; /** Starting size for loose CStrings. */ |
|||
|
|||
protected: |
|||
/** Dummy constructor to prevent string initialization */ |
|||
CString_Loose(Jupiter::String_Constructor_Base &) {}; |
|||
|
|||
size_t strSize; /** Size of underlying C-string buffer */ |
|||
}; |
|||
|
|||
#if defined JUPITER_CSTRING_LOOSE_OPERATOR_PLUS |
|||
/** String_Loose<T> Addition Operator */ |
|||
template<typename T> static inline Jupiter::CString_LOOSE<T> operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs); |
|||
#endif // JUPITER_CSTRING_LOOSE_OPERATOR_PLUS
|
|||
|
|||
/** Definition of a Loose CString. */ |
|||
typedef CString_Loose<char> CStringL; |
|||
|
|||
/** Definition of a Loose Wide CString */ |
|||
typedef CString_Loose<wchar_t> WCStringL; |
|||
|
|||
/** Definition of a CString. */ |
|||
typedef CStringL CString; |
|||
|
|||
/** Definition of a Wide CString */ |
|||
typedef WCStringL WCString; |
|||
|
|||
/** Generic CString Type */ |
|||
typedef CString_Type<char> CStringType; |
|||
|
|||
/** Generic Wide CString Type */ |
|||
typedef CString_Type<wchar_t> WCStringType; |
|||
|
|||
/** Definition of a Strict CString. */ |
|||
typedef CStringType CStringS; |
|||
|
|||
/** Definition of a Strict Wide CString */ |
|||
typedef WCStringType WCStringS; |
|||
|
|||
namespace literals |
|||
{ |
|||
/** CString_Strict literals */ |
|||
inline Jupiter::CStringType operator"" _jcst(const char *str, size_t len) { return Jupiter::CStringType(str, len); } |
|||
inline Jupiter::WCStringType operator"" _jwcst(const wchar_t *str, size_t len) { return Jupiter::WCStringType(str, len); } |
|||
|
|||
/** CString_Strict literals */ |
|||
inline Jupiter::CStringS operator"" _jcss(const char *str, size_t len) { return Jupiter::CStringS(str, len); } |
|||
inline Jupiter::WCStringS operator"" _jwcss(const wchar_t *str, size_t len) { return Jupiter::WCStringS(str, len); } |
|||
|
|||
/** CString_Loose literals */ |
|||
inline Jupiter::CStringL operator"" _jcsl(const char *str, size_t len) { return Jupiter::CStringL(str, len); } |
|||
inline Jupiter::WCStringL operator"" _jwcsl(const wchar_t *str, size_t len) { return Jupiter::WCStringL(str, len); } |
|||
|
|||
/** CString literals */ |
|||
inline Jupiter::CStringS operator"" _jcs(const char *str, size_t len) { return Jupiter::CString(str, len); } |
|||
inline Jupiter::WCStringS operator"" _jwcs(const wchar_t *str, size_t len) { return Jupiter::WCString(str, len); } |
|||
} |
|||
} |
|||
|
|||
/** Re-enable warning */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(pop) |
|||
#endif |
|||
|
|||
/** Implementation for CString_Type and CString_Loose. Very scary. */ |
|||
#include "CString_Imp.h" |
|||
|
|||
#endif // _CSTRING_H_HEADER
|
@ -1,932 +0,0 @@ |
|||
/**
|
|||
* Copyright (C) 2013-2017 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _CSTRING_IMP_H_HEADER |
|||
#define _CSTRING_IMP_H_HEADER |
|||
|
|||
/**
|
|||
* @file CString_Imp.h |
|||
* @brief Provides the implementations for CString_Type functions, as well as extending classes. |
|||
* Note: Modification of this file is not supported in any way. |
|||
*/ |
|||
|
|||
#include "Functions.h" |
|||
#include "CString.h" |
|||
#include "String.hpp" |
|||
|
|||
#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
|
|||
|
|||
#if !defined JUPITER_VSCPRINTF |
|||
|
|||
#if defined _WIN32 |
|||
#define JUPITER_VSCPRINTF(format, format_args) _vscprintf(format, format_args) |
|||
#define JUPITER_VSCWPRINTF(format, format_args) _vscwprintf(format, format_args) |
|||
#else // _WIN32
|
|||
#define JUPITER_VSCPRINTF(format, format_args) vsnprintf(nullptr, 0, format, format_args) |
|||
#define JUPITER_VSCWPRINTF(format, format_args) vswprintf(nullptr, 0, format, format_args) |
|||
#endif // _WIN32
|
|||
|
|||
#endif // JUPITER_VSCPRINTF
|
|||
|
|||
/**
|
|||
* IMPLEMENTATION: |
|||
* CString_Type |
|||
*/ |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type() : Jupiter::CString_Type<T>::CString_Type(size_t(0)) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(size_t len) |
|||
{ |
|||
Jupiter::Shift_String_Type<T>::base = new T[len + 1]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
Jupiter::String_Type<T>::length = 0; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(Jupiter::CString_Type<T> &&source) : Jupiter::Shift_String_Type<T>(std::move(source)) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &in) : Jupiter::CString_Type<T>::CString_Type(in.ptr(), in.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const std::basic_string<T> &in) : Jupiter::CString_Type<T>::CString_Type(in.data(), in.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const T *in, size_t len) : Jupiter::CString_Type<T>::CString_Type(len) |
|||
{ |
|||
while (Jupiter::String_Type<T>::length != len) |
|||
{ |
|||
if ((Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = *in) == 0) return; |
|||
Jupiter::String_Type<T>::length++; |
|||
in++; |
|||
} |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const T *in) |
|||
{ |
|||
if (in == nullptr) |
|||
{ |
|||
Jupiter::String_Type<T>::length = 0; |
|||
Jupiter::Shift_String_Type<T>::base = new T[1]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
} |
|||
else |
|||
{ |
|||
Jupiter::String_Type<T>::length = Jupiter::strlen<T>(in); |
|||
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::String_Type<T>::length + 1]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str, in); |
|||
} |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const T &rhs) : CString_Type<T>(lhs.size() + 1) |
|||
{ |
|||
const T *itr; |
|||
const T *end; |
|||
|
|||
if (lhs.isNotEmpty()) |
|||
{ |
|||
itr = lhs.ptr(); |
|||
end = itr + lhs.size(); |
|||
*Jupiter::String_Type<T>::str = *itr; |
|||
while (++itr != end) |
|||
*++Jupiter::String_Type<T>::str = *itr; |
|||
++Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
*Jupiter::String_Type<T>::str = rhs; |
|||
*++Jupiter::String_Type<T>::str = 0; |
|||
|
|||
Jupiter::String_Type<T>::length = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) : CString_Type<T>(lhs, rhs.ptr(), rhs.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) : CString_Type<T>(lhs, rhs.data(), rhs.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const T *rhs) : CString_Type<T>(lhs, rhs, Jupiter::strlen<T>(rhs)) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const T *rhs, size_t rhs_size) : CString_Type<T>(lhs.size() + rhs_size) |
|||
{ |
|||
const T *itr; |
|||
const T *end; |
|||
|
|||
if (lhs.isNotEmpty()) |
|||
{ |
|||
itr = lhs.ptr(); |
|||
end = itr + lhs.size(); |
|||
*Jupiter::String_Type<T>::str = *itr; |
|||
while (++itr != end) |
|||
*++Jupiter::String_Type<T>::str = *itr; |
|||
++Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
if (rhs_size != 0) |
|||
{ |
|||
itr = rhs; |
|||
end = itr + rhs_size; |
|||
*Jupiter::String_Type<T>::str = *itr; |
|||
while (++itr != end) |
|||
*++Jupiter::String_Type<T>::str = *itr; |
|||
++Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
*Jupiter::String_Type<T>::str = 0; |
|||
Jupiter::String_Type<T>::length = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
} |
|||
|
|||
template<typename T> bool Jupiter::CString_Type<T>::setBufferSize(size_t len) |
|||
{ |
|||
if (Jupiter::Shift_String_Type<T>::setBufferSize(len + 1)) |
|||
{ |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
template<typename T> bool Jupiter::CString_Type<T>::setBufferSizeNoCopy(size_t len) |
|||
{ |
|||
bool r = Jupiter::Shift_String_Type<T>::setBufferSizeNoCopy(len + 1); |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
return r; |
|||
} |
|||
|
|||
template<typename T> const T *Jupiter::CString_Type<T>::c_str() const |
|||
{ |
|||
return Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::truncate(size_t n) |
|||
{ |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::truncate(n)] = 0; |
|||
return Jupiter::String_Type<T>::length; |
|||
} |
|||
|
|||
template<typename T> bool Jupiter::CString_Type<T>::remove(const T &value) |
|||
{ |
|||
if (Jupiter::Shift_String_Type<T>::remove(value)) |
|||
{ |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
// vformat()
|
|||
|
|||
template<> size_t inline Jupiter::CString_Type<char>::vformat(const char *format, va_list args) |
|||
{ |
|||
int minLen; |
|||
va_list sargs; |
|||
va_copy(sargs, args); |
|||
minLen = JUPITER_VSCPRINTF(format, sargs); |
|||
va_end(sargs); |
|||
if (minLen < 0) return 0; // We simply can not work with this.
|
|||
this->setBufferSizeNoCopy(minLen); |
|||
Jupiter::String_Type<char>::length = minLen; |
|||
vsnprintf(Jupiter::String_Type<char>::str, Jupiter::String_Type<char>::length + 1, format, args); |
|||
Jupiter::String_Type<char>::str[Jupiter::String_Type<char>::length] = 0; |
|||
return Jupiter::String_Type<char>::length; |
|||
} |
|||
|
|||
template<> size_t inline Jupiter::CString_Type<wchar_t>::vformat(const wchar_t *format, va_list args) |
|||
{ |
|||
int minLen; |
|||
va_list sargs; |
|||
va_copy(sargs, args); |
|||
minLen = JUPITER_VSCWPRINTF(format, sargs); |
|||
va_end(sargs); |
|||
if (minLen < 0) return 0; // We simply can not work with this.
|
|||
this->setBufferSizeNoCopy(minLen); |
|||
Jupiter::String_Type<wchar_t>::length = minLen; |
|||
vswprintf(Jupiter::String_Type<wchar_t>::str, Jupiter::String_Type<wchar_t>::length, format, args); |
|||
Jupiter::String_Type<wchar_t>::str[Jupiter::String_Type<wchar_t>::length] = 0; |
|||
return Jupiter::String_Type<wchar_t>::length; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::vformat(const T *format, va_list args) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
// avformat()
|
|||
|
|||
template<> size_t inline Jupiter::CString_Type<char>::avformat(const char *format, va_list args) |
|||
{ |
|||
int minLen; |
|||
va_list sargs; |
|||
va_copy(sargs, args); |
|||
minLen = JUPITER_VSCPRINTF(format, sargs); |
|||
va_end(sargs); |
|||
if (minLen < 0) return 0; // We simply can not work with this.
|
|||
this->setBufferSize(Jupiter::String_Type<char>::length + minLen); |
|||
|
|||
minLen = vsnprintf(Jupiter::String_Type<char>::str + Jupiter::String_Type<char>::length, minLen + 1, format, args); |
|||
if (minLen <= 0) return 0; |
|||
Jupiter::String_Type<char>::length += minLen; |
|||
Jupiter::String_Type<char>::str[Jupiter::String_Type<char>::length] = 0; |
|||
return minLen; |
|||
} |
|||
|
|||
template<> size_t inline Jupiter::CString_Type<wchar_t>::avformat(const wchar_t *format, va_list args) |
|||
{ |
|||
int minLen; |
|||
va_list sargs; |
|||
va_copy(sargs, args); |
|||
minLen = JUPITER_VSCWPRINTF(format, sargs); |
|||
va_end(sargs); |
|||
if (minLen < 0) return 0; // We simply can not work with this.
|
|||
this->setBufferSize(minLen + Jupiter::String_Type<wchar_t>::length); |
|||
|
|||
minLen = vswprintf(Jupiter::String_Type<wchar_t>::str + Jupiter::String_Type<wchar_t>::length, minLen, format, args); |
|||
if (minLen <= 0) return 0; |
|||
Jupiter::String_Type<wchar_t>::length += minLen; |
|||
Jupiter::String_Type<wchar_t>::str[Jupiter::String_Type<wchar_t>::length] = 0; |
|||
return minLen; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::avformat(const T *format, va_list args) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::Format(const T *format, ...) |
|||
{ |
|||
CString_Type<T> r; |
|||
va_list args; |
|||
va_start(args, format); |
|||
r.vformat(format, args); |
|||
va_end(args); |
|||
return r; |
|||
} |
|||
|
|||
// substring
|
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(size_t pos) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::substring(*this, pos); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(size_t pos, size_t len) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::substring(*this, pos, len); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos) |
|||
{ |
|||
if (pos >= in.size()) return Jupiter::CString_Type<T>(); |
|||
Jupiter::CString_Type<T> r = Jupiter::CString_Type<T>(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<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const T *in, size_t pos) |
|||
{ |
|||
Jupiter::CString_Type<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Type>(in, pos); |
|||
r.str[r.length] = 0; |
|||
return r; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len) |
|||
{ |
|||
if (pos + len >= in.size()) return Jupiter::CString_Type<T>::substring(in, pos); |
|||
Jupiter::CString_Type<T> r = Jupiter::CString_Type<T>(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<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const T *in, size_t pos, size_t len) |
|||
{ |
|||
Jupiter::CString_Type<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Type>(in, pos, len); |
|||
r.str[r.length] = 0; |
|||
return r; |
|||
} |
|||
|
|||
// getWord
|
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::getWord(size_t pos, const T *whitespace) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::getWord(*this, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace) |
|||
{ |
|||
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Type>(in, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::getWord(const T *in, size_t pos, const T *whitespace) |
|||
{ |
|||
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Type>(in, pos, whitespace); |
|||
} |
|||
|
|||
// gotoWord
|
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::gotoWord(size_t pos, const T *whitespace) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::gotoWord(*this, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace) |
|||
{ |
|||
return Jupiter::Readable_String<T>::template gotoWord<Jupiter::CString_Type>(in, pos, whitespace); |
|||
} |
|||
|
|||
// tokenize
|
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const T &separator) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::tokenize(*this, separator); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &separator) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::tokenize(*this, separator); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const T *separator, size_t separator_size) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::tokenize(*this, separator, separator_size); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token) |
|||
{ |
|||
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Type<T>>(in, token); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator) |
|||
{ |
|||
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Type<T>>(in, separator); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size) |
|||
{ |
|||
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Type<T>>(in, separator, separator_size); |
|||
} |
|||
|
|||
// set
|
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::set(const T *in, size_t in_size) |
|||
{ |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::set(in, in_size)] = 0; |
|||
return Jupiter::String_Type<T>::length; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::set(const Jupiter::Readable_String<T> &in) |
|||
{ |
|||
return this->set(in.ptr(), in.size()); |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::set(const std::basic_string<T> &in) |
|||
{ |
|||
return this->set(in.data(), in.size()); |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::set(const T *in) |
|||
{ |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::set(in)] = 0; |
|||
return Jupiter::String_Type<T>::length; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::set(const T &in) |
|||
{ |
|||
if (in == 0) |
|||
{ |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
return Jupiter::String_Type<T>::length = 0; |
|||
} |
|||
this->setBufferSizeNoCopy(1); |
|||
*Jupiter::String_Type<T>::str = in; |
|||
Jupiter::String_Type<T>::str[1] = 0; |
|||
return Jupiter::String_Type<T>::length = 1; |
|||
} |
|||
|
|||
// concat
|
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::concat(const T *in, size_t in_size) |
|||
{ |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::concat(in, in_size)] = 0; |
|||
return Jupiter::String_Type<T>::length; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::concat(const Jupiter::Readable_String<T> &in) |
|||
{ |
|||
return this->concat(in.ptr(), in.size()); |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::concat(const std::basic_string<T> &in) |
|||
{ |
|||
return this->concat(in.data(), in.size()); |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::concat(const T *in) |
|||
{ |
|||
size_t nSize = Jupiter::String_Type<T>::length + Jupiter::strlen<T>(in); |
|||
this->setBufferSize(nSize); |
|||
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str + Jupiter::String_Type<T>::length, in); |
|||
return Jupiter::String_Type<T>::length = nSize; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Type<T>::concat(const T &in) |
|||
{ |
|||
this->setBufferSize(Jupiter::String_Type<T>::length + 1); |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = in; |
|||
Jupiter::String_Type<T>::str[++Jupiter::String_Type<T>::length] = 0; |
|||
return Jupiter::String_Type<T>::length; |
|||
} |
|||
|
|||
// Operators
|
|||
|
|||
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const T &rhs) const |
|||
{ |
|||
return Jupiter::template operator+<T>(*this, rhs); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const Jupiter::CString_Type<T> &rhs) const |
|||
{ |
|||
return Jupiter::CString_Type<T>::operator+(reinterpret_cast<const Jupiter::Readable_String<T> &>(rhs)); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const Jupiter::Readable_String<T> &rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const std::basic_string<T> &rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const T *rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
#if defined JUPITER_CSTRING_TYPE_OPERATOR_PLUS |
|||
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T &rhs) |
|||
{ |
|||
return Jupiter::CString_Type<T>(lhs, rhs); |
|||
} |
|||
|
|||
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) |
|||
{ |
|||
return Jupiter::CString_Type<T>(lhs, rhs); |
|||
} |
|||
|
|||
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) |
|||
{ |
|||
return Jupiter::CString_Type<T>(lhs, rhs); |
|||
} |
|||
|
|||
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T *rhs) |
|||
{ |
|||
return Jupiter::CString_Type<T>(lhs, rhs); |
|||
} |
|||
#endif // JUPITER_CSTRING_TYPE_OPERATOR_PLUS
|
|||
|
|||
template<typename T> const Jupiter::CString_Type<T> Jupiter::CString_Type<T>::empty = Jupiter::CString_Type<T>(); |
|||
|
|||
// Jupiter::DataBuffer specialization
|
|||
|
|||
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::CString_Type> |
|||
{ |
|||
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::CString_Type<Y> *data) |
|||
{ |
|||
_Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Readable_String>::push<Y>(buffer, data); |
|||
}; |
|||
|
|||
template<typename Y> static Jupiter::CString_Type<Y> interpret(uint8_t *&head) |
|||
{ |
|||
size_t size_ = *reinterpret_cast<size_t *>(head); |
|||
head += sizeof(size_t); |
|||
Jupiter::CString_Type<Y> r = Jupiter::CString_Type<Y>(reinterpret_cast<Y *>(head), size_); |
|||
head += size_; |
|||
return r; |
|||
} |
|||
}; |
|||
|
|||
/**
|
|||
* IMPLEMENTATION: |
|||
* CString_Loose |
|||
*/ |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose() : Jupiter::CString_Loose<T>::CString_Loose(Jupiter::CString_Loose<T>::start_size) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(Jupiter::CString_Loose<T> &&source) : Jupiter::CString_Type<T>(std::move(source)) |
|||
{ |
|||
Jupiter::CString_Loose<T>::strSize = source.strSize; |
|||
source.strSize = 0; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(size_t len) : Jupiter::CString_Type<T>::CString_Type(Jupiter::stringConstructorBase) |
|||
{ |
|||
if (len < Jupiter::CString_Loose<T>::start_size) Jupiter::CString_Loose<T>::strSize = Jupiter::CString_Loose<T>::start_size; |
|||
else Jupiter::CString_Loose<T>::strSize = getPowerTwo(len + 1); |
|||
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
Jupiter::String_Type<T>::length = 0; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::CString_Loose<T> &in) : Jupiter::CString_Type<T>::CString_Type(Jupiter::stringConstructorBase) |
|||
{ |
|||
Jupiter::CString_Loose<T>::strSize = in.strSize; |
|||
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str, in.str); |
|||
Jupiter::String_Type<T>::length = in.length; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &in) : Jupiter::CString_Loose<T>::CString_Loose(in.ptr(), in.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const std::basic_string<T> &in) : Jupiter::CString_Loose<T>::CString_Loose(in.data(), in.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const T *in, size_t len) : Jupiter::CString_Loose<T>::CString_Loose(len) |
|||
{ |
|||
while (Jupiter::String_Type<T>::length != len) |
|||
{ |
|||
if ((Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = *in) == 0) return; |
|||
Jupiter::String_Type<T>::length++; |
|||
} |
|||
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const T *in) : Jupiter::CString_Type<T>::CString_Type(Jupiter::stringConstructorBase) |
|||
{ |
|||
if (in == nullptr) |
|||
{ |
|||
Jupiter::CString_Loose<T>::strSize = Jupiter::CString_Loose<T>::start_size; |
|||
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
Jupiter::String_Type<T>::length = 0; |
|||
} |
|||
else |
|||
{ |
|||
Jupiter::String_Type<T>::length = Jupiter::strlen<T>(in); |
|||
Jupiter::CString_Loose<T>::strSize = getPowerTwo(Jupiter::String_Type<T>::length + 1); |
|||
if (Jupiter::CString_Loose<T>::strSize < Jupiter::CString_Loose<T>::start_size) Jupiter::CString_Loose<T>::strSize = Jupiter::CString_Loose<T>::start_size; |
|||
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str, in); |
|||
} |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const T &rhs) : CString_Loose<T>(lhs.size() + 1) |
|||
{ |
|||
const T *itr; |
|||
const T *end; |
|||
|
|||
if (lhs.isNotEmpty()) |
|||
{ |
|||
itr = lhs.ptr(); |
|||
end = itr + lhs.size(); |
|||
*Jupiter::String_Type<T>::str = *itr; |
|||
while (++itr != end) |
|||
*++Jupiter::String_Type<T>::str = *itr; |
|||
++Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
*Jupiter::String_Type<T>::str = rhs; |
|||
*++Jupiter::String_Type<T>::str = 0; |
|||
|
|||
Jupiter::String_Type<T>::length = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) : CString_Loose<T>(lhs, rhs.ptr(), rhs.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) : CString_Loose<T>(lhs, rhs.data(), rhs.size()) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const T *rhs) : CString_Loose<T>(lhs, rhs, Jupiter::strlen<T>(rhs)) |
|||
{ |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const T *rhs, size_t rhs_size) : CString_Loose<T>(lhs.size() + rhs_size) |
|||
{ |
|||
const T *itr; |
|||
const T *end; |
|||
|
|||
if (lhs.isNotEmpty()) |
|||
{ |
|||
itr = lhs.ptr(); |
|||
end = itr + lhs.size(); |
|||
*Jupiter::String_Type<T>::str = *itr; |
|||
while (++itr != end) |
|||
*++Jupiter::String_Type<T>::str = *itr; |
|||
++Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
if (rhs_size != 0) |
|||
{ |
|||
itr = rhs; |
|||
end = itr + rhs_size; |
|||
*Jupiter::String_Type<T>::str = *itr; |
|||
while (++itr != end) |
|||
*++Jupiter::String_Type<T>::str = *itr; |
|||
++Jupiter::String_Type<T>::str; |
|||
} |
|||
|
|||
*Jupiter::String_Type<T>::str = 0; |
|||
Jupiter::String_Type<T>::length = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
} |
|||
|
|||
template<typename T> bool Jupiter::CString_Loose<T>::setBufferSize(size_t len) |
|||
{ |
|||
size_t offset = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base; |
|||
|
|||
++len; // null term
|
|||
if (len + offset > Jupiter::CString_Loose<T>::strSize) |
|||
{ |
|||
if (len > Jupiter::CString_Loose<T>::strSize) |
|||
{ |
|||
// Buffer is not large enough; reallocate
|
|||
Jupiter::CString_Loose<T>::strSize = getPowerTwo(len); |
|||
|
|||
T *ptr = new T[Jupiter::CString_Loose<T>::strSize]; |
|||
for (size_t i = 0; i < Jupiter::String_Type<T>::length; i++) |
|||
ptr[i] = Jupiter::String_Type<T>::str[i]; |
|||
ptr[Jupiter::String_Type<T>::length] = 0; |
|||
|
|||
delete[] Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::Shift_String_Type<T>::base = ptr; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
// Buffer has enough space to accomodate; shift data to the left
|
|||
T *read_itr = Jupiter::String_Type<T>::str; |
|||
T *read_end = read_itr + Jupiter::String_Type<T>::length; |
|||
T *write_itr = Jupiter::Shift_String_Type<T>::base; |
|||
|
|||
while (read_itr != read_end) |
|||
{ |
|||
*write_itr = *read_itr; |
|||
|
|||
++read_itr; |
|||
++write_itr; |
|||
} |
|||
|
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template<typename T> bool Jupiter::CString_Loose<T>::setBufferSizeNoCopy(size_t len) |
|||
{ |
|||
len = getPowerTwo(len + 1); |
|||
if (len > Jupiter::CString_Loose<T>::strSize) |
|||
{ |
|||
Jupiter::String_Type<T>::length = 0; |
|||
delete[] Jupiter::Shift_String_Type<T>::base; |
|||
Jupiter::Shift_String_Type<T>::base = new T[len]; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
return true; |
|||
} |
|||
Jupiter::String_Type<T>::length = 0; |
|||
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base; |
|||
*Jupiter::String_Type<T>::str = 0; |
|||
return false; |
|||
} |
|||
|
|||
template<typename T> size_t Jupiter::CString_Loose<T>::capacity() const |
|||
{ |
|||
return Jupiter::CString_Loose<T>::strSize - 1; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::Format(const T *format, ...) |
|||
{ |
|||
CString_Loose<T> r; |
|||
va_list args; |
|||
va_start(args, format); |
|||
r.vformat(format, args); |
|||
va_end(args); |
|||
return r; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(size_t pos) const |
|||
{ |
|||
return Jupiter::CString_Loose<T>::substring(*this, pos); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(size_t pos, size_t length) const |
|||
{ |
|||
return Jupiter::CString_Loose<T>::substring(*this, pos, length); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos) |
|||
{ |
|||
if (pos > in.size()) return Jupiter::CString_Loose<T>(); |
|||
Jupiter::CString_Loose<T> r = Jupiter::CString_Loose<T>(in.size() - pos); |
|||
for (r.length = 0; pos + r.length != in.size() && in.get(r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length); |
|||
r.str[r.length] = 0; |
|||
return r; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const T *in, size_t pos) |
|||
{ |
|||
Jupiter::CString_Loose<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Loose>(in, pos); |
|||
r.str[r.length] = 0; |
|||
return r; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len) |
|||
{ |
|||
if (pos + len >= in.size()) return Jupiter::CString_Loose<T>::substring(in, pos); |
|||
Jupiter::CString_Loose<T> r = Jupiter::CString_Loose<T>(len); |
|||
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<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const T *in, size_t pos, size_t len) |
|||
{ |
|||
Jupiter::CString_Loose<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Loose>(in, pos, len); |
|||
r.str[r.length] = 0; |
|||
return r; |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::getWord(size_t pos, const T *whitespace) const |
|||
{ |
|||
return Jupiter::CString_Loose<T>::getWord(*this, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace) |
|||
{ |
|||
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Loose>(in, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::getWord(const T *in, size_t pos, const T *whitespace) |
|||
{ |
|||
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Loose>(in, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::gotoWord(size_t pos, const T *whitespace) const |
|||
{ |
|||
return Jupiter::CString_Loose<T>::gotoWord(*this, pos, whitespace); |
|||
} |
|||
|
|||
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace) |
|||
{ |
|||
return Jupiter::Readable_String<T>::template gotoWord<Jupiter::CString_Loose>(in, pos, whitespace); |
|||
} |
|||
|
|||
// tokenize
|
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const T &token) |
|||
{ |
|||
return Jupiter::CString_Loose<T>::tokenize(*this, token); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &separator) |
|||
{ |
|||
return Jupiter::CString_Loose<T>::tokenize(*this, separator); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const T *separator, size_t separator_size) |
|||
{ |
|||
return Jupiter::CString_Loose<T>::tokenize(*this, separator, separator_size); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token) |
|||
{ |
|||
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Loose<T>>(in, token); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator) |
|||
{ |
|||
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Loose<T>>(in, separator); |
|||
} |
|||
|
|||
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size) |
|||
{ |
|||
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Loose<T>>(in, separator, separator_size); |
|||
} |
|||
|
|||
// Operators
|
|||
|
|||
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const T &rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const Jupiter::CString_Loose<T> &rhs) const |
|||
{ |
|||
return Jupiter::CString_Loose<T>::operator+(reinterpret_cast<const Jupiter::Readable_String<T> &>(rhs)); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const Jupiter::Readable_String<T> &rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const std::basic_string<T> &rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const T *rhs) const |
|||
{ |
|||
return Jupiter::operator+(*this, rhs); |
|||
} |
|||
|
|||
#if defined JUPITER_CSTRING_LOOSE_OPERATOR_PLUS |
|||
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T &rhs) |
|||
{ |
|||
return Jupiter::CString_Loose<T>(lhs, rhs); |
|||
} |
|||
|
|||
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) |
|||
{ |
|||
return Jupiter::CString_Loose<T>(lhs, rhs); |
|||
} |
|||
|
|||
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) |
|||
{ |
|||
return Jupiter::CString_Loose<T>(lhs, rhs); |
|||
} |
|||
|
|||
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T *rhs) |
|||
{ |
|||
return Jupiter::CString_Loose<T>(lhs, rhs); |
|||
} |
|||
#endif // JUPITER_CSTRING_LOOSE_OPERATOR_PLUS
|
|||
|
|||
template<typename T> const Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::empty = Jupiter::CString_Loose<T>(); |
|||
|
|||
// Jupiter::DataBuffer specialization
|
|||
|
|||
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::CString_Loose> |
|||
{ |
|||
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::CString_Loose<Y> *data) |
|||
{ |
|||
_Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Readable_String>::push<Y>(buffer, data); |
|||
}; |
|||
|
|||
template<typename Y> static Jupiter::CString_Loose<Y> interpret(uint8_t *&head) |
|||
{ |
|||
size_t size_ = *reinterpret_cast<size_t *>(head); |
|||
head += sizeof(size_t); |
|||
Jupiter::CString_Loose<Y> r = Jupiter::CString_Loose<Y>(reinterpret_cast<Y *>(head), size_); |
|||
head += size_; |
|||
return r; |
|||
} |
|||
}; |
|||
|
|||
#endif // _CSTRING_IMP_H_HEADER
|
@ -1,285 +0,0 @@ |
|||
/**
|
|||
* Copyright (C) 2016-2017 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _HASH_TABLE_H_HEADER |
|||
#define _HASH_TABLE_H_HEADER |
|||
|
|||
/**
|
|||
* @file Hash_Table.h |
|||
* @brief Defines a generic hash table structure |
|||
*/ |
|||
|
|||
#include <forward_list> |
|||
#include "String.hpp" |
|||
|
|||
namespace Jupiter |
|||
{ |
|||
template<typename T> inline size_t default_hash_function(const T &in); |
|||
|
|||
/**
|
|||
* @brief Provides a generic hash table structure |
|||
* |
|||
* @param KeyT Type the table will use for keys; must implement following: operator==, move constructor |
|||
* @param ValueT Type the table will use for values |
|||
* @param InKeyT Type the table will accept for keys (Default: KeyT) |
|||
* @param InValueT Type the table will accept for values (Default: ValueT) |
|||
* @param HashF Function to be used for generating hashes (Default: Fowler-Noll-Vo 1a) |
|||
*/ |
|||
template<typename KeyT, typename ValueT, typename InKeyT = KeyT, typename InValueT = ValueT, size_t(*HashF)(const InKeyT &) = Jupiter::default_hash_function<InKeyT>> class Hash_Table |
|||
{ |
|||
public: |
|||
/** Initial number of buckets to allocate; m_buckets_size is never less than INIT_SIZE. */ |
|||
static constexpr const size_t INIT_SIZE = 8; |
|||
|
|||
/**
|
|||
* @brief Container for table entries |
|||
*/ |
|||
struct Bucket |
|||
{ |
|||
/**
|
|||
* @brief An individual entry within the table, including its normal key and value. |
|||
*/ |
|||
struct Entry |
|||
{ |
|||
KeyT key; |
|||
ValueT value; |
|||
|
|||
Entry(const InKeyT &in_key); |
|||
Entry(const InKeyT &in_key, const InValueT &in_value); |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Searches for an entry in the bucket and returns its value if it exists. |
|||
* |
|||
* @param in_key Key of the entry to search for |
|||
* @return Pointer to the value of the entry if it exists, nullptr otherwise |
|||
*/ |
|||
const ValueT *get(const InKeyT &in_key) const; |
|||
ValueT *get(const InKeyT &in_key); |
|||
const InValueT &get(const InKeyT &in_key, const InValueT &in_value) const; |
|||
template<typename CastT> CastT getCast(const InKeyT &in_key, const CastT &in_value) const; |
|||
|
|||
/**
|
|||
* @brief Sets the value for an entry in the bucket |
|||
* |
|||
* @param in_key Key of the entry to set |
|||
* @param in_value Value to set in the entry |
|||
* @return True if a new entry was added, false if an entry was overwritten |
|||
*/ |
|||
bool set(const InKeyT &in_key, const InValueT &in_value); |
|||
bool set(const InKeyT &in_key); |
|||
|
|||
/**
|
|||
* @brief Removes an entry from the table |
|||
* |
|||
* @param in_key Key of the entry to remove |
|||
* @return True if an entry was removed, false otherwise |
|||
*/ |
|||
bool remove(const InKeyT &in_key); |
|||
|
|||
/**
|
|||
* @brief Calls a function for each Entry in the table, passing each Entry as a parameter |
|||
* |
|||
* @param CallT Function type to call |
|||
* |
|||
* @param in_callback Function to callback |
|||
*/ |
|||
template<typename CallT> void callback(CallT &in_callback) const; |
|||
template<typename CallT> void callback(CallT &in_callback); |
|||
|
|||
/**
|
|||
* @brief Copy assignment operator |
|||
* |
|||
* @param in_bucket Bucket to copy entries from |
|||
* @return Reference to this bucket |
|||
*/ |
|||
Bucket &operator=(const Bucket &in_bucket); |
|||
|
|||
/**
|
|||
* @brief Move assignment operator |
|||
* |
|||
* @param in_bucket Bucket to move entries from |
|||
* @return Reference to this bucket |
|||
*/ |
|||
Bucket &operator=(Bucket &&in_bucket); |
|||
|
|||
/**
|
|||
* @brief Default constructor for the Bucket class |
|||
*/ |
|||
Bucket() = default; |
|||
|
|||
/**
|
|||
* @brief Copy constructor for the Bucket class |
|||
*/ |
|||
Bucket(const Bucket &in_bucket); |
|||
|
|||
/**
|
|||
* @brief Move constructor for the Bucket class |
|||
*/ |
|||
Bucket(Bucket &&in_bucket); |
|||
|
|||
/**
|
|||
* @brief Destructor for the Bucket class |
|||
*/ |
|||
~Bucket(); |
|||
|
|||
/** List of entries in the bucket */ |
|||
std::forward_list<Entry> m_entries; |
|||
}; |
|||
|
|||
/**
|
|||
* @brief Returns an iterator positioned at the beginning of the table |
|||
* |
|||
* @brief Iterator at beginning of m_buckets |
|||
*/ |
|||
Bucket *begin() const; |
|||
|
|||
/**
|
|||
* @brief Returns an iterator positioned at the end of the table |
|||
* |
|||
* @return Iterator at end of m_buckets |
|||
*/ |
|||
Bucket *end() const; |
|||
|
|||
/**
|
|||
* @brief Fetches the value of an entry based on its key |
|||
* |
|||
* @param in_key Key of the entry to search for |
|||
* @return Value of the entry if it exists, nullptr otherwise |
|||
*/ |
|||
ValueT *get(const InKeyT &in_key) const; |
|||
const InValueT &get(const InKeyT &in_key, const InValueT &in_value) const; |
|||
template<typename CastT> CastT getCast(const InKeyT &in_key, const CastT &in_value) const; |
|||
|
|||
/**
|
|||
* @brief Sets the value for an entry in the table |
|||
* |
|||
* @param in_key Key of the entry to set |
|||
* @param in_value Value of the entry to set |
|||
* @return True if a new entry was added, false if an entry was overwritten |
|||
*/ |
|||
bool set(const InKeyT &in_key, const InValueT &in_value); |
|||
bool set(const InKeyT &in_key); |
|||
|
|||
/**
|
|||
* @brief Removes an entry from the table |
|||
* |
|||
* @param in_key Key of the entry to remove |
|||
* @return True if an entry was removed, false otherwise |
|||
*/ |
|||
bool remove(const InKeyT &in_key); |
|||
|
|||
/**
|
|||
* @brief Calls a function for each Entry in the table, passing each Entry as a parameter |
|||
* |
|||
* @param CallT Function type to call |
|||
* |
|||
* @param in_callback Function to callback |
|||
*/ |
|||
template<typename CallT> void callback(CallT &in_callback) const; |
|||
template<typename CallT> void callback(CallT &in_callback); |
|||
|
|||
/**
|
|||
* @brief Returns the number of entries in the table |
|||
* |
|||
* @return Number of entries in the table |
|||
*/ |
|||
size_t size() const; |
|||
|
|||
/**
|
|||
* @brief Erases the table's contents |
|||
*/ |
|||
void erase(); |
|||
|
|||
/**
|
|||
* @brief Shrinks the table's internal bucket pool to the current number of entries, not to be less than INIT_SIZE. |
|||
*/ |
|||
void shrink(); |
|||
|
|||
/**
|
|||
* @brief Copy assignment operator |
|||
* |
|||
* @param in_table Table to copy entries from |
|||
* @return Reference to this table |
|||
*/ |
|||
Hash_Table &operator=(const Hash_Table &in_table); |
|||
|
|||
/**
|
|||
* @brief Move assignment operator |
|||
* |
|||
* @param in_table Table to move entries from |
|||
* @return Reference to this table |
|||
*/ |
|||
Hash_Table &operator=(Hash_Table &&in_table); |
|||
|
|||
/**
|
|||
* @brief Default constructor for the Hash_Table class |
|||
*/ |
|||
Hash_Table(); |
|||
|
|||
/**
|
|||
* @brief Allocation constructor for the Hash_Table class |
|||
* |
|||
* @param in_buckets_size Number of buckets to initialize to |
|||
*/ |
|||
Hash_Table(size_t in_buckets_size); |
|||
|
|||
/**
|
|||
* @brief Copy constructor for the Hash_Table class |
|||
* |
|||
* @param in_table Table to copy entries from |
|||
*/ |
|||
Hash_Table(const Hash_Table &in_table); |
|||
|
|||
/**
|
|||
* @brief Move constructor for the Hash_Table class |
|||
* |
|||
* @param in_table Table to move entries from |
|||
*/ |
|||
Hash_Table(Hash_Table &&in_table); |
|||
|
|||
/**
|
|||
* @brief Destructor for the Hash_Table class |
|||
*/ |
|||
~Hash_Table(); |
|||
|
|||
private: |
|||
/**
|
|||
* @brief Doubles the size of m_buckets |
|||
*/ |
|||
void expand(); |
|||
|
|||
/**
|
|||
* @brief Copies entries from m_buckets to in_buckets; used when expanding or shrinking m_buckets. |
|||
* |
|||
* @param in_buckets Array of buckets to copy entries into |
|||
* @param in_buckets_size Number of buckets in in_buckets |
|||
*/ |
|||
void copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) const; |
|||
|
|||
Bucket *m_buckets; /** Array of Buckets */ |
|||
size_t m_buckets_size; /** Number of buckets */ |
|||
size_t m_length = 0; /** Number of entries */ |
|||
}; |
|||
|
|||
typedef Hash_Table<Jupiter::StringS, Jupiter::StringS, Jupiter::ReadableString, Jupiter::ReadableString, Jupiter::default_hash_function<Jupiter::ReadableString>> HashTable; |
|||
} |
|||
|
|||
#include "Hash_Table_Imp.h" |
|||
|
|||
#endif // _HASH_TABLE_H_HEADER
|
@ -1,503 +0,0 @@ |
|||
/**
|
|||
* Copyright (C) 2016-2017 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _HASH_TABLE_IMP_H_HEADER |
|||
#define _HASH_TABLE_IMP_H_HEADER |
|||
|
|||
/**
|
|||
* @file Hash_Table_Imp.h |
|||
* @brief Provides the implementation for Hash_Table. |
|||
*/ |
|||
|
|||
#include "Hash_Table.h" |
|||
#include "Hash.h" |
|||
|
|||
/**
|
|||
* IMPLEMENTATION: |
|||
* Hash_Table |
|||
*/ |
|||
|
|||
/** Conditional is constant; can probably be removed when 'if constexpr' support is added to MSVC */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(push) |
|||
#pragma warning(disable: 4127) |
|||
#endif |
|||
|
|||
template<typename T> inline size_t Jupiter::default_hash_function(const T &in) |
|||
{ |
|||
if (sizeof(size_t) >= sizeof(uint64_t)) |
|||
return static_cast<size_t>(Jupiter::fnv1a(in)); |
|||
|
|||
return static_cast<size_t>(Jupiter::fnv1a_32(in)); |
|||
} |
|||
|
|||
/** Re-enable warnings */ |
|||
#if defined _MSC_VER |
|||
#pragma warning(pop) |
|||
#endif |
|||
|
|||
/** Hash_Table::Bucket::Entry */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key) |
|||
: key{ in_key } |
|||
{ |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key, const InValueT &in_value) |
|||
: key{ in_key }, value{ in_value } |
|||
{ |
|||
} |
|||
|
|||
/** Hash_Table::Bucket */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
const ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key) const |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
if (node->key == in_key) |
|||
return &node->value; |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key) |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
if (node->key == in_key) |
|||
return &node->value; |
|||
|
|||
return nullptr; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
const InValueT &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key, const InValueT &in_value) const |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
if (node->key == in_key) |
|||
return node->value; |
|||
|
|||
return in_value; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
template<typename CastT> |
|||
CastT Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::getCast(const InKeyT &in_key, const CastT &in_value) const |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
if (node->key == in_key) |
|||
return static_cast<CastT>(node->value); |
|||
|
|||
return in_value; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(const InKeyT &in_key, const InValueT &in_value) |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
if (node->key == in_key) |
|||
{ |
|||
node->value = in_value; |
|||
return false; |
|||
} |
|||
|
|||
m_entries.emplace_front(in_key, in_value); |
|||
return true; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(const InKeyT &in_key) |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
if (node->key == in_key) |
|||
return false; |
|||
|
|||
m_entries.emplace_front(in_key); |
|||
return true; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::remove(const InKeyT &in_key) |
|||
{ |
|||
auto node = m_entries.begin(); |
|||
auto end = m_entries.end(); |
|||
|
|||
// No nodes in the bucket
|
|||
if (node == end) |
|||
return false; |
|||
|
|||
// Check if the head is the desired node
|
|||
if (node->key == in_key) |
|||
{ |
|||
m_entries.pop_front(); |
|||
return true; |
|||
} |
|||
|
|||
auto next_node = node; |
|||
++next_node; |
|||
|
|||
// iterate through list
|
|||
while (next_node != end) |
|||
{ |
|||
if (next_node->key == in_key) |
|||
{ |
|||
// The next node is the desired node
|
|||
m_entries.erase_after(node); |
|||
return true; |
|||
} |
|||
|
|||
node = next_node; |
|||
++next_node; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
template<typename CallT> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::callback(CallT &in_callback) const |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
in_callback(*node); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
template<typename CallT> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::callback(CallT &in_callback) |
|||
{ |
|||
for (auto node = m_entries.begin(); node != m_entries.end(); ++node) |
|||
in_callback(*node); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(const Bucket &in_bucket) |
|||
{ |
|||
m_entries.clear(); |
|||
for (auto node = in_bucket.m_entries.begin(); node != m_entries.end(); ++node) |
|||
m_entries.emplace_front(node->key, node->value); |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(Bucket &&in_bucket) |
|||
{ |
|||
m_entries = std::move(in_bucket.m_entries); |
|||
return *this; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Bucket(const Bucket &in_bucket) |
|||
{ |
|||
for (auto node = in_bucket.m_entries.getHead(); node != in_bucket.m_entries.end(); ++node) |
|||
m_entries.emplace_front(node->key, node->value); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Bucket(Bucket &&in_bucket) |
|||
{ |
|||
m_entries = std::move(in_bucket.m_entries); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::~Bucket() |
|||
{ |
|||
m_entries.clear(); |
|||
} |
|||
|
|||
/** Hash_Table */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::begin() const |
|||
{ |
|||
return m_buckets; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::end() const |
|||
{ |
|||
return m_buckets + m_buckets_size; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::get(const InKeyT &in_key) const |
|||
{ |
|||
return m_buckets[HashF(in_key) % m_buckets_size].get(in_key); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
const InValueT &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::get(const InKeyT &in_key, const InValueT &in_value) const |
|||
{ |
|||
return m_buckets[HashF(in_key) % m_buckets_size].get(in_key, in_value); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
template<typename CastT> |
|||
CastT Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::getCast(const InKeyT &in_key, const CastT &in_value) const |
|||
{ |
|||
return m_buckets[HashF(in_key) % m_buckets_size].getCast(in_key, in_value); |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKeyT &in_key, const InValueT &in_value) |
|||
{ |
|||
if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key, in_value)) |
|||
{ |
|||
if (++m_length == m_buckets_size) |
|||
expand(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKeyT &in_key) |
|||
{ |
|||
if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key)) |
|||
{ |
|||
if (++m_length == m_buckets_size) |
|||
expand(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::remove(const InKeyT &in_key) |
|||
{ |
|||
if (m_buckets[HashF(in_key) % m_buckets_size].remove(in_key)) |
|||
{ |
|||
--m_length; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
template<typename CallT> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::callback(CallT &in_callback) const |
|||
{ |
|||
Bucket *itr = m_buckets; |
|||
Bucket *end = m_buckets + m_buckets_size; |
|||
|
|||
while (itr != end) |
|||
{ |
|||
itr->template callback<CallT>(in_callback); |
|||
++itr; |
|||
} |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
template<typename CallT> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::callback(CallT &in_callback) |
|||
{ |
|||
Bucket *itr = m_buckets; |
|||
Bucket *end = m_buckets + m_buckets_size; |
|||
|
|||
while (itr != end) |
|||
{ |
|||
itr->template callback<CallT>(in_callback); |
|||
++itr; |
|||
} |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
size_t Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::size() const |
|||
{ |
|||
return m_length; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::erase() |
|||
{ |
|||
m_length = 0; |
|||
delete[] m_buckets; |
|||
|
|||
m_buckets_size = INIT_SIZE; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::shrink() |
|||
{ |
|||
size_t buckets_size = m_length < INIT_SIZE ? INIT_SIZE : m_length; |
|||
Bucket *buckets = new Bucket[buckets_size]; |
|||
|
|||
copy_to_buckets(buckets, buckets_size); |
|||
|
|||
delete[] m_buckets; |
|||
m_buckets = buckets; |
|||
m_buckets_size = buckets_size; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(const Hash_Table &in_table) |
|||
{ |
|||
if (m_buckets_size >= in_table.m_buckets_size && m_buckets_size <= in_table.m_buckets_size * 2) |
|||
{ |
|||
// We're larger than what we're copying, but not drastically (2x) larger. Just erase our current data and copy their entries.
|
|||
|
|||
if (m_length == 0) // we don't need to erase any data
|
|||
in_table.copy_to_buckets(m_buckets, m_buckets_size); |
|||
else |
|||
{ |
|||
// we need to erase data; slightly modified version of copy_to_buckets()
|
|||
size_t index = 0; |
|||
while (index != in_table.m_buckets_size) |
|||
{ |
|||
in_table.m_buckets[index].m_entries.clear(); |
|||
|
|||
for (auto node = in_table.m_buckets[index].m_entries.begin(); node != in_table.m_buckets[index].m_entries.end(); ++node) |
|||
m_buckets[HashF(node->key) % m_buckets_size].set(node->key, node->value); |
|||
|
|||
++index; |
|||
} |
|||
|
|||
while (index != m_buckets_size) |
|||
{ |
|||
in_table.m_buckets[index].m_entries.clear(); |
|||
++index; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// m_buckets is either too small to copy the data, or it'd be too wasteful
|
|||
|
|||
delete[] m_buckets; |
|||
|
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
|
|||
for (size_t index = 0; index != m_buckets_size; ++index) |
|||
m_buckets[index] = in_table.m_buckets[index]; |
|||
} |
|||
|
|||
m_length = in_table.m_length; |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(Hash_Table &&in_table) |
|||
{ |
|||
if (m_length == 0) |
|||
{ |
|||
Bucket *old_buckets = m_buckets; |
|||
size_t old_buckets_size = m_buckets_size; |
|||
|
|||
m_buckets = in_table.m_buckets; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_length = in_table.m_length; |
|||
|
|||
in_table.m_buckets = old_buckets; |
|||
in_table.m_buckets_size = old_buckets_size; |
|||
} |
|||
else |
|||
{ |
|||
delete[] m_buckets; |
|||
|
|||
m_buckets = in_table.m_buckets; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_length = in_table.m_length; |
|||
|
|||
in_table.m_buckets = new Bucket[1]; |
|||
in_table.m_buckets_size = 1; |
|||
} |
|||
|
|||
in_table.m_length = 0; |
|||
|
|||
return *this; |
|||
} |
|||
|
|||
/** Constructors */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table() |
|||
{ |
|||
m_buckets_size = INIT_SIZE; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(size_t in_buckets_size) |
|||
{ |
|||
m_buckets_size = in_buckets_size; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(const Hash_Table &in_table) |
|||
{ |
|||
m_length = in_table.m_length; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_buckets = new Bucket[m_buckets_size]; |
|||
|
|||
for (size_t index = 0; index != m_buckets_size; ++index) |
|||
m_buckets[index] = in_table.m_buckets[index]; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(Hash_Table &&in_table) |
|||
{ |
|||
m_buckets = in_table.m_buckets; |
|||
m_buckets_size = in_table.m_buckets_size; |
|||
m_length = in_table.m_length; |
|||
|
|||
in_table.m_buckets = new Bucket[1]; |
|||
in_table.m_buckets_size = 1; |
|||
in_table.m_length = 0; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::~Hash_Table() |
|||
{ |
|||
delete[] m_buckets; |
|||
} |
|||
|
|||
/** Hash_Table/private */ |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::expand() |
|||
{ |
|||
size_t buckets_size = m_buckets_size * 2; |
|||
Bucket *buckets = new Bucket[buckets_size]; |
|||
|
|||
copy_to_buckets(buckets, buckets_size); |
|||
|
|||
delete[] m_buckets; |
|||
m_buckets = buckets; |
|||
m_buckets_size = buckets_size; |
|||
} |
|||
|
|||
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)> |
|||
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) const |
|||
{ |
|||
for (size_t index = 0; index != m_buckets_size; ++index) |
|||
for (auto node = m_buckets[index].m_entries.begin(); node != m_buckets[index].m_entries.end(); ++node) |
|||
in_buckets[HashF(node->key) % in_buckets_size].set(node->key, node->value); |
|||
} |
|||
|
|||
#endif // _HASH_TABLE_IMP_H_HEADER
|
Loading…
Reference in new issue