diff options
Diffstat (limited to 'win32/common/mystring.h')
-rw-r--r-- | win32/common/mystring.h | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/win32/common/mystring.h b/win32/common/mystring.h new file mode 100644 index 0000000..470ac3c --- /dev/null +++ b/win32/common/mystring.h @@ -0,0 +1,536 @@ +/* + * AUTHOR + * N. Nielsen + * + * LICENSE + * This software is in the public domain. + * + * The software is provided "as is", without warranty of any kind, + * express or implied, including but not limited to the warranties + * of merchantability, fitness for a particular purpose, and + * noninfringement. In no event shall the author(s) be liable for any + * claim, damages, or other liability, whether in an action of + * contract, tort, or otherwise, arising from, out of, or in connection + * with the software or the use or other dealings in the software. + * + * SUPPORT + * Send bug reports to: <nielsen@memberwebs.com> + */ + +#if !defined(_MYSTRING_H_) +#define _MYSTRING_H_ + +////////////////////////////////////////////////////////////////////////////// + +#include <tchar.h> + +#include <stdarg.h> + +#include <string> +#include <locale> + +#pragma warning(push) +#pragma warning(disable:4786) // Disable warning for names > 256 + +////////////////////////////////////////////////////////////////////////////// + +template<typename T> +class stringT : public std::basic_string<T> // T should be either char or wchar_t +{ +public: + // Constructors + stringT() + : std::basic_string<T>() + { } + + stringT(const stringT<T>& strInput) + : std::basic_string<T>(strInput) + { } + + + stringT(const std::basic_string<T>& strInput) + : std::basic_string<T>(strInput) + { } + + stringT(const std::basic_string<T>& strInput, size_type pos, size_type n) + : std::basic_string<T>(strInput, pos, n) + { } + + stringT(const std::basic_string<T>::const_iterator first, + const std::basic_string<T>::const_iterator last) + : std::basic_string<T>(first, last) + { } + + + stringT(const T* strInput) + : std::basic_string<T>(strInput) + { } + + + stringT(const T* strInput, size_type n) + : std::basic_string<T>(strInput, n) + { } + + +#ifdef _INC_COMDEF + stringT(_bstr_t bstr) + { + (*this) = (const T*)bstr; + } +#endif + + stringT(T ch, int nRepeat = 1) + : std::basic_string<T>(nRepeat, ch) + { } + + + // Other Conversions + stringT<T>& make_upper() + { + std::ctype<T> c; + T* p = get_buffer(); + c.toupper(p, p + size()); + release_buffer(); + return *this; + } + + stringT<T> upper() const + { + stringT<T> sTmp(*this); + sTmp.make_upper(); + return sTmp; + } + + stringT<T>& make_lower() + { + std::ctype<T> c; + T* p = get_buffer(); + c.tolower(p, p + size()); + release_buffer(); + return *this; + } + + stringT<T> lower() const + { + stringT<T> sTmp(*this); + sTmp.make_lower(); + return sTmp; + } + + void trim_left() + { + // TODO: Optimize + while(!empty() && _istspace(at(0))) + erase(0, 1); + } + + void trim_right() + { + // TODO: Optimize + while(!empty() && _istspace(at(length()-1))) + erase(length() - 1, 1); + } + + void trim() + { + trim_left(); + trim_right(); + } + + const stringT<T>& format(const T* pszFormat, ...) + { + va_list vl; + va_start(vl, pszFormat); + format_v(pszFormat, vl); + va_end(vl); + + return *this; + } + +#ifdef _WINDOWS_ + + const stringT<T>& format(HINSTANCE hInst, UINT nID, ... ) + { + stringT<T> sTemp; + sTemp.load_string(hInst, nID); + + va_list vl; + va_start(vl, nID); + format_v(sTemp, vl); + va_end(vl); + + return *this; + } + +#ifdef __ATLBASE_H__ + const stringT<T>& format(UINT nID, ... ) + { + stringT<T> sTemp; + sTemp.load_string(nID); + + va_list vl; + va_start(vl, nID); + format_v(sTemp, vl); + va_end(vl); + + return *this; + } +#endif // __ATLBASE_H__ + +#endif + + void format_v(const char* pszFormat, va_list vl) + { + // Copied Code.... + + // Doesn't have all the features of CString::Format() + T* pszTemp = NULL; + size_t nBufferSize = 32; + int nRetVal = -1; + + do + { + // Double the buffer size for next time around + nBufferSize += nBufferSize; + delete [] pszTemp; + pszTemp = new T [nBufferSize]; + nRetVal = _vsnprintf(pszTemp, nBufferSize, pszFormat, vl); + } while (nRetVal < 0); + + *this = pszTemp; + delete [] pszTemp; + + return; + } + + void format_v(const wchar_t* pszFormat, va_list vl) + { + // Copied Code.... + + // Doesn't have all the features of CString::Format() + T* pszTemp = NULL; + size_t nBufferSize = 32; + int nRetVal = -1; + + do + { + // Double the buffer size for next time around + nBufferSize += nBufferSize; + delete [] pszTemp; + pszTemp = new T [nBufferSize]; + nRetVal = _vsnwprintf(pszTemp, nBufferSize, pszFormat, vl); + } while (nRetVal < 0); + + *this = pszTemp; + delete [] pszTemp; + + return; + } + + int replace(const std::basic_string<T>& sFind, const std::basic_string<T>& sReplace, bool bMultiple = true, size_type nStart = 0) + { + stringT<T> sTemp = *this; + int nReplaced = 0; + + if((nStart = sTemp.find(sFind, nStart)) != npos) + { + sTemp.erase(nStart, sFind.length()); + sTemp.insert(nStart, sReplace); + nReplaced++; + } + + while(bMultiple && (nStart = sTemp.find(sFind, nStart + 1)) != npos) + { + sTemp.erase(nStart, sFind.length()); + sTemp.insert(nStart, sReplace); + nReplaced++; + } + + *this = sTemp; + return nReplaced; + } + + // Operators + + T operator[](int nIndex) const + { return at(nIndex); }; + +#ifdef _INC_COMDEF + operator _bstr_t() const + { return _bstr_t(c_str()); }; +#endif + + operator const T*() const + { return c_str(); }; + + + // Buffer Operations + // Derived code from MFC CString + T* get_buffer(size_t sz = npos) + { + if(sz == npos) + sz = size(); + + resize(sz + 1); + // Make sure we generate a write command + // so we have no extra references + // TODO: Does basic_string use reference counting? + // (much later) A: Yes it does! Reference is in the bytes before data + at(sz) = 0; + return const_cast<T*>(data()); + } + + void release_buffer() + { + if(!empty()) + { + // Make sure we generate a write command + // Find the null terminated end + for(string::size_type i = 0; i < capacity() && i < size(); i++) + if(at(i) == 0) + break; + + ASSERT(i != capacity()); + resize(i); + } + } + + void clear() + { resize(0); } + +#ifdef _WINDOWS_ + bool load_string(HINSTANCE hInst, unsigned int nID) + { + string::size_type nSize = 0x80; + do + { + release_buffer(); + nSize *= 2; + } + while(load_string(hInst, nID, get_buffer(nSize), nSize) == nSize); + + release_buffer(); + return nSize > 0; + } +#endif // WIN32 + +#ifdef __ATLBASE_H__ + bool load_string(unsigned int nID) + { + string::size_type nSize = 0x80; + do + { + release_buffer(); + nSize *= 2; + } + while(load_string(_Module.m_hInstResource, nID, get_buffer(nSize), nSize) == nSize); + + release_buffer(); + return nSize > 0; + } +#endif // __ATLBASE_H__ + + +protected: + +#ifdef _WINDOWS_ + + static int load_string(HINSTANCE hInst, UINT nID, char* pBuff, size_t nSize) + { + return ::LoadStringA(hInst, nID, pBuff, nSize); + } + + static int load_string(HINSTANCE hInst, UINT nID, wchar_t* pBuff, size_t nSize) + { +#ifdef _UNICODE + return ::LoadStringW(hInst, nID, pBuff, nSize); +#else + char* pABuff = new char[nSize]; + if(!pABuff) return 0; + + int nRet = load_string(hInst, nID, pABuff, nSize); + if(nRet) + { + pBuff[0] = L'\0'; + MultiByteToWideChar(GetACP(), 0, pABuff, -1, pBuff, nSize); + } + + return nRet; +#endif + } + + + +#endif + + +}; + + #ifndef _UNICODE + typedef stringT<char> string; + #else + typedef stringT<wchar_t> string; + #endif + + typedef stringT<char> astring; + typedef stringT<wchar_t> wstring; + + +template<typename T> +class cstringT +{ +public: + cstringT() + { clear(); }; + cstringT(const T* ptr, size_t len) + { set(ptr, len); }; + + operator stringT<T>() const + { + if(_Ptr) + return stringT<T>(_Ptr, _Len); + else + return stringT<T>(); + }; + + bool is_null() const + { return _Ptr ? false : true; } + // TODO: Maybe some validity checks + void set(const T* ptr, size_t len) + { _Ptr = ptr; _Len = len; } + void clear() + { _Ptr = 0; _Len = 0; } + +protected: + const T* _Ptr; + size_t _Len; +}; + + + #ifndef _UNICODE + typedef cstringT<char> cstring; + #else + typedef cstringT<wchar_t> cstring; + #endif + + typedef cstringT<char> castring; + typedef cstringT<wchar_t> cwstring; + + + +#include <vector> +#include <algorithm> + +template<typename S> +class string_arrayT : public std::vector<S> +{ +public: + string_arrayT(const std::vector<S> & x) + : std::vector<S>(x) {}; + string_arrayT(string_arrayT & x) + : std::vector<S>(x) {}; + string_arrayT(std::vector<S>::const_iterator first, std::vector<S>::const_iterator last, const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type()) + : std::vector<S>(first, last, al) {}; + explicit string_arrayT(const const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type()) + : std::vector<S>(al) {}; + explicit string_arrayT(std::vector<S>::size_type n, const std::vector<S>::value_type& v = std::vector<S>::value_type(), const std::vector<S>::allocator_type& al = std::vector<S>::allocator_type()) + : std::vector<S>(n, v, al) {}; + + std::vector<S>::size_type split(S sIn, S sDelim, bool bTrim = false) + { + S::size_type start = 0; + S::size_type ed = 0; + std::vector<S>::size_type cnt = 0; + S::size_type lenDelim = sDelim.size(); + S sTemp; + + if(lenDelim == 0) + { + if(bTrim) + sIn.trim(); + push_back(sIn); + return 1; + } + + while(ed != string::npos) + { + ed = sIn.find(sDelim, start); + if(ed == string::npos) + sTemp = sIn.substr(start); + else + sTemp = sIn.substr(start, ed - start); + + if(bTrim) + sTemp.trim(); + + push_back(sTemp); + + cnt++; + + start = ed + lenDelim; + } + + return cnt; + } + + S join(S sDelim) const + { + S sTemp; + const_iterator it = begin(); + const_iterator ed = end(); + + while(it != ed) + { + sTemp += *it; + it++; + } + + return sTemp; + } + + class no_case + { + public: + no_case(const S& s) : _str(s) + { _str.make_lower(); } + + bool operator()(const S& s) + { return s.lower() == _str; } + protected: + S _str; + }; + + bool has(S sVal, bool bCase = true) const + { return find(sVal, bCase) != end(); } + + const_iterator find(S sVal, bool bCase = true) const + { + if(bCase) + return std::find(begin(), end(), sVal); + else + { + no_case fndr(sVal); + return std::find_if(begin(), end(), fndr); + } + } + + iterator find(S sVal, bool bCase = true) + { + if(bCase) + return std::find(begin(), end(), sVal); + else + { + no_case fndr(sVal); + return std::find_if(begin(), end(), fndr); + } + } +}; + +typedef string_arrayT< string > string_array; +typedef string_arrayT< wstring > wstring_array; + +////////////////////////////////////////////////////////////////////////////// + +#pragma warning( pop ) + +#endif // !defined(_MYSTRING_H_) |