summaryrefslogtreecommitdiff
path: root/win32/common/mystring.h
diff options
context:
space:
mode:
Diffstat (limited to 'win32/common/mystring.h')
-rw-r--r--win32/common/mystring.h536
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_)