/** * Copyright (C) 2013-2014 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any * component of this program must not be commercial, unless explicit * permission is granted from the original author. The use of this * program for non-profit purposes is permitted. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * In the event that this license restricts you from making desired use of this program, contact the original author. * Written by Justin James */ #if !defined _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" #if !defined va_copy #if defined __INTEL_COMPILER #pragma message("Warning: va_copy not properly defined. Assuming common implementation.") #define va_copy(dst, src) ((void)((dst) = (src))) #else #error "va_copy not defined." #endif // __INTEL_COMPILER #endif // va_copy /** * IMPLEMENTATION: * CString_Type */ template Jupiter::CString_Type::CString_Type() : Jupiter::CString_Type::CString_Type(size_t(0)) { } template Jupiter::CString_Type::CString_Type(size_t len) { Jupiter::Shift_String_Type::base = new T[len + 1]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; Jupiter::String_Type::length = 0; } template Jupiter::CString_Type::CString_Type(Jupiter::CString_Type &&source) : Jupiter::Shift_String_Type(std::move(source)) { } template Jupiter::CString_Type::CString_Type(const Jupiter::Readable_String &in) : Jupiter::CString_Type::CString_Type(in.ptr(), in.size()) { } template Jupiter::CString_Type::CString_Type(const std::basic_string &in) : Jupiter::CString_Type::CString_Type(in.data(), in.size()) { } template Jupiter::CString_Type::CString_Type(const T *in, size_t len) : Jupiter::CString_Type::CString_Type(len) { while (Jupiter::String_Type::length != len) { if ((Jupiter::String_Type::str[Jupiter::String_Type::length] = *in) == 0) return; Jupiter::String_Type::length++; in++; } Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; } template Jupiter::CString_Type::CString_Type(const T *in) { if (in == nullptr) { Jupiter::String_Type::length = 0; Jupiter::Shift_String_Type::base = new T[1]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; } else { Jupiter::String_Type::length = Jupiter::strlen(in); Jupiter::Shift_String_Type::base = new T[Jupiter::String_Type::length + 1]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; Jupiter::strcpy(Jupiter::String_Type::str, in); } } template bool Jupiter::CString_Type::setBufferSize(size_t len) { if (Jupiter::Shift_String_Type::setBufferSize(len + 1)) { Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return true; } return false; } template bool Jupiter::CString_Type::setBufferSizeNoCopy(size_t len) { bool r = Jupiter::Shift_String_Type::setBufferSizeNoCopy(len + 1); *Jupiter::String_Type::str = 0; return r; } template const T *Jupiter::CString_Type::c_str() const { return Jupiter::String_Type::str; } template size_t Jupiter::CString_Type::truncate(size_t n) { Jupiter::String_Type::str[Jupiter::String_Type::truncate(n)] = 0; return Jupiter::String_Type::length; } template bool Jupiter::CString_Type::remove(const T &value) { if (Jupiter::Shift_String_Type::remove(value)) { Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return true; } return false; } // vformat() template<> size_t inline Jupiter::CString_Type::vformat(const char *format, va_list args) { int minLen; va_list sargs; va_copy(sargs, args); minLen = vsnprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. this->setBufferSizeNoCopy(minLen); Jupiter::String_Type::length = minLen; vsnprintf(Jupiter::String_Type::str, Jupiter::String_Type::length, format, args); Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } template<> size_t inline Jupiter::CString_Type::vformat(const wchar_t *format, va_list args) { int minLen; va_list sargs; va_copy(sargs, args); minLen = vswprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. this->setBufferSizeNoCopy(minLen); Jupiter::String_Type::length = minLen; vswprintf(Jupiter::String_Type::str, Jupiter::String_Type::length, format, args); Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } template size_t Jupiter::CString_Type::vformat(const T *format, va_list args) { return 0; } // avformat() template<> size_t inline Jupiter::CString_Type::avformat(const char *format, va_list args) { int minLen; va_list sargs; va_copy(sargs, args); minLen = vsnprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. this->setBufferSize(Jupiter::String_Type::length + minLen); minLen = vsnprintf(Jupiter::String_Type::str + Jupiter::String_Type::length, minLen, format, args); if (minLen <= 0) return 0; Jupiter::String_Type::length += minLen; Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return minLen; } template<> size_t inline Jupiter::CString_Type::avformat(const wchar_t *format, va_list args) { int minLen; va_list sargs; va_copy(sargs, args); minLen = vswprintf(nullptr, 0, format, sargs); va_end(sargs); if (minLen < 0) return 0; // We simply can not work with this. this->setBufferSize(minLen + Jupiter::String_Type::length); minLen = vswprintf(Jupiter::String_Type::str + Jupiter::String_Type::length, minLen, format, args); if (minLen <= 0) return 0; Jupiter::String_Type::length += minLen; Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return minLen; } template size_t Jupiter::CString_Type::avformat(const T *format, va_list args) { return 0; } template Jupiter::CString_Type Jupiter::CString_Type::Format(const T *format, ...) { CString_Type r; va_list args; va_start(args, format); r.vformat(format, args); va_end(args); return r; } template Jupiter::CString_Type Jupiter::CString_Type::substring(size_t pos) const { return Jupiter::CString_Type::substring(*this, pos); } template Jupiter::CString_Type Jupiter::CString_Type::substring(size_t pos, size_t len) const { return Jupiter::CString_Type::substring(*this, pos, len); } template Jupiter::CString_Type Jupiter::CString_Type::substring(const Jupiter::Readable_String &in, size_t pos) { if (pos >= in.size()) return Jupiter::CString_Type(); Jupiter::CString_Type r = Jupiter::CString_Type(in.size() - pos); for (r.length = 0; pos + r.length != in.size() && in.get(pos + r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length); r.str[r.length] = 0; return r; } template Jupiter::CString_Type Jupiter::CString_Type::substring(const T *in, size_t pos) { Jupiter::CString_Type r = Jupiter::String_Type::substring(in, pos); r.str[r.length] = 0; return r; } template Jupiter::CString_Type Jupiter::CString_Type::substring(const Jupiter::Readable_String &in, size_t pos, size_t len) { if (pos + len >= in.size()) return Jupiter::CString_Type::substring(in, pos); Jupiter::CString_Type r = Jupiter::CString_Type(len); for (r.length = 0; r.length != len && in.get(pos + r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length); r.str[r.length] = 0; return r; } template Jupiter::CString_Type Jupiter::CString_Type::substring(const T *in, size_t pos, size_t len) { Jupiter::CString_Type r = Jupiter::String_Type::substring(in, pos, len); r.str[r.length] = 0; return r; } template Jupiter::CString_Type Jupiter::CString_Type::getWord(size_t pos, const T *whitespace) const { return Jupiter::CString_Type::getWord(*this, pos, whitespace); } template Jupiter::CString_Type Jupiter::CString_Type::getWord(const Jupiter::Readable_String &in, size_t pos, const T *whitespace) { return Jupiter::Readable_String::getWord(in, pos, whitespace); } template Jupiter::CString_Type Jupiter::CString_Type::getWord(const T *in, size_t pos, const T *whitespace) { return Jupiter::Readable_String::getWord(in, pos, whitespace); } template Jupiter::CString_Type Jupiter::CString_Type::gotoWord(size_t pos, const T *whitespace) const { return Jupiter::CString_Type::gotoWord(*this, pos, whitespace); } template Jupiter::CString_Type Jupiter::CString_Type::gotoWord(const Jupiter::Readable_String &in, size_t pos, const T *whitespace) { return Jupiter::Readable_String::gotoWord(in, pos, whitespace); } template size_t Jupiter::CString_Type::set(const Jupiter::Readable_String &in) { this->setBufferSizeNoCopy(in.size()); for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length < in.size() && in.get(Jupiter::String_Type::length) != 0; Jupiter::String_Type::length++) Jupiter::String_Type::str[Jupiter::String_Type::length] = in.get(Jupiter::String_Type::length); return Jupiter::String_Type::length; } template size_t Jupiter::CString_Type::set(const std::basic_string &in) { this->setBufferSizeNoCopy(in.size()); for (Jupiter::String_Type::length = 0; Jupiter::String_Type::length < in.size() && in.at(Jupiter::String_Type::length) != 0; Jupiter::String_Type::length++) Jupiter::String_Type::str[Jupiter::String_Type::length] = in.at(Jupiter::String_Type::length); return Jupiter::String_Type::length; } template size_t Jupiter::CString_Type::set(const T *in) { Jupiter::String_Type::str[Jupiter::String_Type::set(in)] = 0; return Jupiter::String_Type::length; } template size_t Jupiter::CString_Type::set(const T in) { if (in == 0) { Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; return Jupiter::String_Type::length = 0; } this->setBufferSizeNoCopy(1); *Jupiter::String_Type::str = in; Jupiter::String_Type::str[1] = 0; return Jupiter::String_Type::length = 1; } template size_t Jupiter::CString_Type::concat(const Jupiter::Readable_String &in) { size_t nSize = Jupiter::String_Type::length + in.size(); const T *inData = in.ptr(); this->setBufferSize(nSize); while (Jupiter::String_Type::length != nSize && *inData != 0) { Jupiter::String_Type::str[Jupiter::String_Type::length] = *inData; Jupiter::String_Type::length++; inData++; } Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } template size_t Jupiter::CString_Type::concat(const std::basic_string &in) { size_t nSize = Jupiter::String_Type::length + in.size(); const T *inData = in.data(); this->setBufferSize(nSize); while (Jupiter::String_Type::length != nSize && *inData != 0) { Jupiter::String_Type::str[Jupiter::String_Type::length] = *inData; Jupiter::String_Type::length++; inData++; } Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } template size_t Jupiter::CString_Type::concat(const T *in) { size_t nSize = Jupiter::String_Type::length + Jupiter::strlen(in); this->setBufferSize(nSize); Jupiter::strcpy(Jupiter::String_Type::str + Jupiter::String_Type::length, in); return Jupiter::String_Type::length = nSize; } template size_t Jupiter::CString_Type::concat(const T c) { this->setBufferSize(Jupiter::String_Type::length + 1); Jupiter::String_Type::str[Jupiter::String_Type::length] = c; Jupiter::String_Type::str[++Jupiter::String_Type::length] = 0; return Jupiter::String_Type::length; } template const Jupiter::CString_Type Jupiter::CString_Type::empty = Jupiter::CString_Type(); /** * IMPLEMENTATION: * CString_Loose */ template Jupiter::CString_Loose::CString_Loose() : Jupiter::CString_Loose::CString_Loose(Jupiter::CString_Loose::start_size) { } template Jupiter::CString_Loose::CString_Loose(Jupiter::CString_Loose &&source) : Jupiter::CString_Type(std::move(source)) { Jupiter::CString_Loose::strSize = source.strSize; source.strSize = 0; } template Jupiter::CString_Loose::CString_Loose(size_t len) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { if (len < Jupiter::CString_Loose::start_size) Jupiter::CString_Loose::strSize = Jupiter::CString_Loose::start_size; else Jupiter::CString_Loose::strSize = getPowerTwo32(len + 1); Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; Jupiter::String_Type::length = 0; } template Jupiter::CString_Loose::CString_Loose(const Jupiter::CString_Loose &in) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { Jupiter::CString_Loose::strSize = in.strSize; Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; Jupiter::strcpy(Jupiter::String_Type::str, in.str); Jupiter::String_Type::length = in.length; } template Jupiter::CString_Loose::CString_Loose(const Jupiter::Readable_String &in) : Jupiter::CString_Loose::CString_Loose(in.ptr(), in.size()) { } template Jupiter::CString_Loose::CString_Loose(const std::basic_string &in) : Jupiter::CString_Loose::CString_Loose(in.data(), in.size()) { } template Jupiter::CString_Loose::CString_Loose(const T *in, size_t len) : Jupiter::CString_Loose::CString_Loose(len) { while (Jupiter::String_Type::length != len) { if ((Jupiter::String_Type::str[Jupiter::String_Type::length] = *in) == 0) return; Jupiter::String_Type::length++; } Jupiter::String_Type::str[Jupiter::String_Type::length] = 0; } template Jupiter::CString_Loose::CString_Loose(const T *in) : Jupiter::CString_Type::CString_Type(Jupiter::stringConstructorBase) { if (in == nullptr) { Jupiter::CString_Loose::strSize = Jupiter::CString_Loose::start_size; Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; Jupiter::String_Type::length = 0; } else { Jupiter::String_Type::length = Jupiter::strlen(in); Jupiter::CString_Loose::strSize = getPowerTwo32(Jupiter::String_Type::length + 1); if (Jupiter::CString_Loose::strSize < Jupiter::CString_Loose::start_size) Jupiter::CString_Loose::strSize = Jupiter::CString_Loose::start_size; Jupiter::Shift_String_Type::base = new T[Jupiter::CString_Loose::strSize]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; Jupiter::strcpy(Jupiter::String_Type::str, in); } } template bool Jupiter::CString_Loose::setBufferSize(size_t len) { len = getPowerTwo32(len + 1); if (len > Jupiter::CString_Loose::strSize) { T *ptr = new T[len]; for (unsigned int i = 0; i < Jupiter::String_Type::length; i++) ptr[i] = Jupiter::Shift_String_Type::str[i]; ptr[Jupiter::String_Type::length] = 0; delete[] Jupiter::Shift_String_Type::base; Jupiter::Shift_String_Type::base = ptr; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; return true; } return false; } template bool Jupiter::CString_Loose::setBufferSizeNoCopy(size_t len) { len = getPowerTwo32(len + 1); if (len > Jupiter::CString_Loose::strSize) { Jupiter::String_Type::length = 0; delete[] Jupiter::Shift_String_Type::base; Jupiter::Shift_String_Type::base = new T[len]; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; return true; } Jupiter::String_Type::length = 0; Jupiter::String_Type::str = Jupiter::Shift_String_Type::base; *Jupiter::String_Type::str = 0; return false; } template Jupiter::CString_Loose Jupiter::CString_Loose::Format(const T *format, ...) { CString_Loose r; va_list args; va_start(args, format); r.vformat(format, args); va_end(args); return r; } template Jupiter::CString_Loose Jupiter::CString_Loose::substring(size_t pos) const { return Jupiter::CString_Loose::substring(*this, pos); } template Jupiter::CString_Loose Jupiter::CString_Loose::substring(size_t pos, size_t length) const { return Jupiter::CString_Loose::substring(*this, pos, length); } template Jupiter::CString_Loose Jupiter::CString_Loose::substring(const Jupiter::Readable_String &in, size_t pos) { if (pos > in.size()) return Jupiter::CString_Loose(); Jupiter::CString_Loose r = Jupiter::CString_Loose(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 Jupiter::CString_Loose Jupiter::CString_Loose::substring(const T *in, size_t pos) { Jupiter::CString_Loose r = Jupiter::String_Type::substring(in, pos); r.str[r.length] = 0; return r; } template Jupiter::CString_Loose Jupiter::CString_Loose::substring(const Jupiter::Readable_String &in, size_t pos, size_t len) { if (pos + len >= in.size()) return Jupiter::CString_Loose::substring(in, pos); Jupiter::CString_Loose r = Jupiter::CString_Loose(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 Jupiter::CString_Loose Jupiter::CString_Loose::substring(const T *in, size_t pos, size_t len) { Jupiter::CString_Loose r = Jupiter::String_Type::substring(in, pos, len); r.str[r.length] = 0; return r; } template Jupiter::CString_Loose Jupiter::CString_Loose::getWord(size_t pos, const T *whitespace) const { return Jupiter::CString_Loose::getWord(*this, pos, whitespace); } template Jupiter::CString_Loose Jupiter::CString_Loose::getWord(const Jupiter::Readable_String &in, size_t pos, const T *whitespace) { return Jupiter::Readable_String::getWord(in, pos, whitespace); } template Jupiter::CString_Loose Jupiter::CString_Loose::getWord(const T *in, size_t pos, const T *whitespace) { return Jupiter::Readable_String::getWord(in, pos, whitespace); } template Jupiter::CString_Loose Jupiter::CString_Loose::gotoWord(size_t pos, const T *whitespace) const { return Jupiter::CString_Loose::gotoWord(*this, pos, whitespace); } template Jupiter::CString_Loose Jupiter::CString_Loose::gotoWord(const Jupiter::Readable_String &in, size_t pos, const T *whitespace) { return Jupiter::Readable_String::gotoWord(in, pos, whitespace); } template const Jupiter::CString_Loose Jupiter::CString_Loose::empty = Jupiter::CString_Loose(); #endif // _CSTRING_IMP_H_HEADER