#include "wobject/xstring.hpp" #include "platform/nstring.hpp" #include "platform/nmemory.hpp" #include "system/itemalloc.hpp" #include "win32/win.hpp" #include //#include template class KStringBlock { private: static const unsigned int kShouldFree = 0x1; static const unsigned int kShouldSysFree = 0x2; static const unsigned int kUTF16 = 0x4; static const unsigned int kUTF8 = 0x8; static const unsigned int kACP = 0x10; private: union { T* m_val; T m_buff[16]; }; int m_len; int m_ref; unsigned int flag; public: void AddRef() { m_ref++; } void Release() { m_ref--; if (m_ref == 0) { if (flag & kShouldSysFree) ::SysFreeString((BSTR)m_val); else if (flag & kShouldFree) { if(m_len>=16)free(m_val,m_len); } this->~KStringBlock(); MyAllocer().free(this); } } public: const T* str() { return (m_len<16 && (flag & kShouldSysFree)==0)? (const T*)m_buff : (const T*)m_val; } private: KStringBlock() :m_val(nullptr), m_len(0), m_ref(1), flag(0) {} KStringBlock(wchar_t* val, bool shouldfree, bool shouldsysfree) :m_val(val), m_len(val ? (int)nstring::length(val) : 0), m_ref(1), flag(kUTF16 | (shouldfree ? kShouldFree : 0) | (shouldsysfree ? kShouldSysFree : 0)) { } KStringBlock(char* val, bool shouldfree, bool shouldsysfree) :m_val(val), m_len(val ? (int)nstring::length(val) : 0), m_ref(1), flag(kACP | (shouldfree ? kShouldFree : 0) | (shouldsysfree ? kShouldSysFree : 0)) { } ~KStringBlock() { } void initial() { m_val =nullptr; m_len = 0; m_ref=1; flag = kShouldFree | kUTF16; } public: static ItemAlloc* stringBlock32; static ItemAlloc* stringBlock64; static ItemAlloc* stringBlock128; static ItemAlloc* stringBlock256; static ItemAlloc, 4096>* stringBlockMgr; public: static ItemAlloc, 4096>& MyAllocer() { //static ItemAlloc, 4096> stringBlockMgr; //ItemAlloc, 4096>* stringBlockMgr=new (ItemAlloc, 4096>); if(!stringBlockMgr)stringBlockMgr=new ItemAlloc, 4096>(); return *stringBlockMgr; } static KStringBlock* make() { KStringBlock * p = MyAllocer().alloc(); p->initial(); return p; } static KStringBlock* make(char* value, bool shouldSysFree) { if(!value)return nullptr; int len = nstring::length(value); KStringBlock * p = MyAllocer().alloc(); //p = new (p) KStringBlock(); p->initial(); p->flag = kACP | kShouldFree; p->m_len = len; if(shouldSysFree) { m_val = value; if(shouldSysFree) p->flag |= kShouldSysFree; }else { if(len<16) nstring::cpy(m_buff,value); else { m_val = p->alloc(m_len+1); nstring::cpy(m_val,value); } } return p; } static KStringBlock* make(wchar_t* value, bool shouldSysFree) { if(!value)return nullptr; int len = nstring::length(value); KStringBlock * p = MyAllocer().alloc(); //p = new (p) KStringBlock(); p->initial(); p->flag = kUTF16 | kShouldFree; p->m_len =len; if(shouldSysFree) { p->m_val = value; if(shouldSysFree) p->flag |= kShouldSysFree; }else { if(len<16) nstring::cpy(p->m_buff,value); else { p->m_val = p->alloc(p->m_len+1); nstring::cpy(p->m_val,value); } } return p; } static KStringBlock* make(int value) { int len = 15; KStringBlock * p = MyAllocer().alloc(); //p = new (p) KStringBlock(); p->initial(); p->flag = kUTF16 | kShouldFree; p->m_len = len; nstring::toWStr(value,p->alloc(p->m_len+1),p->m_len+1); return p; } static KStringBlock* make(double value) { int len = 31; KStringBlock * p = MyAllocer().alloc(); //p = new (p) KStringBlock(); p->initial(); p->flag = kUTF16 | kShouldFree; p->m_len = len; nstring::toWStr(value,p->alloc(p->m_len+1),p->m_len+1); return p; } static KStringBlock* make(LPARAM value) { int len = 31; KStringBlock * p = MyAllocer().alloc(); //p = new (p) KStringBlock(); p->initial(); p->flag = kUTF16 | kShouldFree; p->m_len = len; nstring::toWStr(value,p->alloc(p->m_len+1),p->m_len+1); return p; } public: int length() { return this->m_len; } T* sure(int size) { if(size <=0) return nullptr; m_len = size - 1; if(size < 16) return m_buff; m_val = this->alloc(size); return m_val; } private: T* alloc(int size) { if(size <= 16) return m_buff; if(size <=32) { if(!stringBlock32)stringBlock32 = new ItemAlloc; return (T*)stringBlock32->alloc(); } if(size <=64) { if(!stringBlock64)stringBlock64 = new ItemAlloc; return (T*)stringBlock64->alloc(); } if(size <=128) { if(!stringBlock128)stringBlock128 = new ItemAlloc; return (T*)stringBlock128->alloc(); } if(size <=256) { if(!stringBlock256)stringBlock256 = new ItemAlloc; return (T*)stringBlock256->alloc(); } return new T[size]; } void free(T* p, int size) { if(!p) return; if(p==m_buff) return; if(size <32)return stringBlock32->free(p); if(size <64)return stringBlock64->free(p); if(size <128)return stringBlock128->free(p); if(size <256)return stringBlock256->free(p); return delete p; } }; template<> ItemAlloc* KStringBlock::stringBlock32 = 0; template<> ItemAlloc* KStringBlock::stringBlock64 = 0; template<> ItemAlloc* KStringBlock::stringBlock128 = 0; template<> ItemAlloc* KStringBlock::stringBlock256 = 0; template<> ItemAlloc, 4096>* KStringBlock::stringBlockMgr = 0; xstring::xstring() :data(nullptr) { } xstring::xstring(const xstring& rhs):data(rhs.data) { if(rhs.data)((KStringBlock*)rhs.data)->AddRef(); } xstring::xstring(wchar_t* val, bool shouldSysFree) :data(KStringBlock::make(val,shouldSysFree)) { } xstring::xstring(const wchar_t* val, bool shouldSysFree):data(KStringBlock::make((wchar_t*)val,shouldSysFree)) { } xstring::xstring(int val):data((KStringBlock::make(val))) { } xstring::xstring(double val):data((KStringBlock::make(val))) { } xstring::xstring(LPARAM val):data((KStringBlock::make(val))) { } xstring::~xstring() { if(data) ((KStringBlock*)data)->Release(); } xstring& xstring::operator =(const xstring& rhs) { if (data)((KStringBlock*)data)->Release(); if (rhs.data) { ((KStringBlock*)rhs.data)->AddRef(); data = rhs.data; } else data = nullptr; return *this; } xstring& xstring::operator =(const wchar_t* rhs) { if (data)((KStringBlock*)data)->Release(); data = KStringBlock::make((wchar_t*)rhs,false); return *this; } bool xstring::isEmpty() { if(!data) return true; const wchar_t* str = ((KStringBlock*)data)->str(); if(!str)return true; if(str[0]==0)return true; return false; } bool xstring::operator ==(const wchar_t* rhs) { bool rhsEmpty = !rhs || rhs[0]==0; if(rhsEmpty && isEmpty()) return true; if(rhsEmpty != isEmpty()) return false; return nstring::cmp(c_str(),rhs)==0; } bool xstring::operator >=(const wchar_t* rhs) { bool rhsEmpty = !rhs || rhs[0]==0; if(rhsEmpty) return true; if(isEmpty()) return false; return nstring::cmp(c_str(),rhs)>=0; } bool xstring::operator >(const wchar_t* rhs) { bool rhsEmpty = !rhs || rhs[0]==0; if(rhsEmpty) return isEmpty()?false:true; if(isEmpty())return false; return nstring::cmp(c_str(),rhs)>0; } bool xstring::operator <=(const wchar_t* rhs) { return !this->operator >(rhs); } bool xstring::operator <(const wchar_t* rhs) { return !this->operator >=(rhs); } bool xstring::operator !=(const wchar_t* rhs) { return !operator ==(rhs); } bool xstring::operator ==(const xstring& rhs) { return operator==(rhs.c_str()); } bool xstring::operator >=(const xstring& rhs) { return operator>=(rhs.c_str()); } bool xstring::operator >(const xstring& rhs) { return operator>(rhs.c_str()); } bool xstring::operator <=(const xstring& rhs) { return operator<=(rhs.c_str()); } bool xstring::operator <(const xstring& rhs) { return operator<(rhs.c_str()); } bool xstring::operator !=(const xstring& rhs) { return operator!=(rhs.c_str()); } xstring::operator bool() { return this->isEmpty(); } const wchar_t* xstring::c_str(bool bclone) const{ if(!data) return nullptr; const wchar_t* val = ((KStringBlock*)data)->str(); return bclone ? nstring::clone(val) : val; } int xstring::length() { if(!data) return 0; if (c_str())return nstring::length(c_str()); return 0; //return ((KStringBlock*)data)->length(); } wchar_t xstring::at(int index) { if(index < 0) return 0; if(isEmpty()) return 0; if(index >= length()) return 0; return c_str()[index]; } xstring xstring::concat(xstring && rhs) { return concat(rhs.c_str()); } xstring xstring::concat(const wchar_t* rhs) { if(!rhs) return *this; xstring xs; KStringBlock* pdata = KStringBlock::make(); xs.data = pdata; int len = length()+nstring::length(rhs); wchar_t* buffer = pdata->sure(len+1); if(length())nstring::cpy(buffer,c_str()); if(rhs)nstring::cpy(buffer +length(), rhs); return xs; } xstring xstring::operator +(const wchar_t* rhs) { return concat(rhs); } xstring xstring::operator +(xstring rhs) { return concat(rhs.c_str()); } int xstring::find(const xstring & str) { return find(str.c_str()); } int xstring::find(const wchar_t* str) { if (!str)return -1; if (!data)return -1; const wchar_t* p = nstring::str(c_str(), str); if(!p) return -1; return p - c_str(); } int xstring::find(const wchar_t* str,int pos) { if (!str)return -1; if (!data)return -1; if(pos >= nstring::length(c_str()))return -1; const wchar_t* p = nstring::str(c_str()+pos, str); if(!p) return -1; return p - c_str(); } wchar_t* xstring::sure(int len) { KStringBlock* pdata = KStringBlock::make(); this->data = pdata; return pdata->sure(len); } xstring xstring::mid(int start, int len) { if (!data) return xstring(); if (nstring::length(c_str()) < start) return xstring(); len = start + len > nstring::length(c_str()) ? nstring::length(c_str()) - start : len; xstring xs; wchar_t* buffer = xs.sure(len+1); nstring::ncpy(buffer, c_str() + start, len); buffer[len] = 0; return xs; } xstring xstring::left(int len) { if(!data) return xstring(); if(len<1) return xstring(); if(len > nstring::length(c_str())) len = nstring::length(c_str()); xstring xs; wchar_t* buffer = xs.sure(len+1); nstring::ncpy(buffer,c_str(),len); buffer[len] = 0; return xs; } xstring xstring::right(int len) { if (!data) return xstring(); if (len < 1) return xstring(); if (len > nstring::length(c_str())) len = nstring::length(c_str()); xstring xs; wchar_t* buffer = xs.sure(len + 1); nstring::ncpy(buffer, c_str() + (nstring::length(c_str()) - len), len); buffer[len] = 0; return xs; } int xstring::toInt() { if (!data)return 0; return nstring::toInt((wchar_t*)c_str()); } __int64 xstring::toInt64() { if (!data)return 0; return nstring::toInt64((wchar_t*)c_str()); } double xstring::toDouble() { return nstring::toDouble((wchar_t*)c_str()); } xstring xstring::toUpper() { return nstring::toUpper((wchar_t*)c_str()); } xstring xstring::toLower() { return nstring::toLower((wchar_t*)c_str()); } xstring& xstring::operator +=(const wchar_t* rhs) { xstring xs = *this; *this = xs + rhs; return *this; } xstring& xstring::operator +=(xstring rhs) { return operator +=(rhs.c_str()); } xstring xstring::trim() { xstring xs(c_str()); return xstring(nstring::trim_((wchar_t*)c_str(), (wchar_t*)xs.c_str())); } xstring xstring::rtrim() { xstring xs(c_str()); return xstring(nstring::rtrim_((wchar_t*)c_str(), (wchar_t*)xs.c_str())); } xstring xstring::ltrim() { xstring xs(c_str()); return xstring(nstring::ltrim_((wchar_t*)c_str(), (wchar_t*)xs.c_str())); } bool xstring::isNumber() { const wchar_t* val = c_str(); int len = length(); int i = 0; int cnt = 0; int e = 0; bool hasNumber = false; for (i = 0; i < len; i++) { wchar_t ch = val[i] & 0xff; if (ch >= L'0' && ch <= L'9') { hasNumber = true; continue; } else if (ch == L'e' || ch == L'E') { if (e == 0 && hasNumber) { e = 1; hasNumber = false; continue; } else return false; } else if (ch == L'-') { if (hasNumber) return false; hasNumber = true; continue; } else if (ch == L'.') { if (cnt == 1) return false; if (e) return false; cnt = 1; continue; } else if (ch == ' ')continue; break; } if (i == len) return true; return false; } xstring xstring::replace(const wchar_t* from, const wchar_t* to) { return replace(from, to, 0); } xstring xstring::replace(const wchar_t* from, const wchar_t* to, int pos) { const wchar_t* pstr = c_str(); if (!pstr) return 0; if (!from[0]) return pstr; if (pos < 1) pos = 0; int len = (int)nstring::length(from); if (len < 0) return pstr; std::vector arpos; const wchar_t* ptext = pstr; ptext = wcsstr(ptext + pos, from); if (!ptext) return pstr; while (ptext) { arpos.push_back((int)(ptext - pstr)); ptext = wcsstr(ptext + len, from); } int tolen = (int)wcslen(to); int inc = ((int)arpos.size()) * (tolen - len); int nlen = (int)wcslen(pstr) + inc + 1; int start = 0; int end = 0; wchar_t* p = new wchar_t[nlen]; memset(p, 0, nlen * 2); wchar_t* np = p; arpos.push_back((int)wcslen(pstr)); for (int i = 0; i < (int)arpos.size(); i++) { end = arpos[i]; if (end - start > 0) { wcsncpy_s(np, end - start + 1, pstr + start, end - start); np += end - start; } if (i != (int)arpos.size() - 1) { if (tolen) { wcsncpy_s(np, tolen + 1, to, tolen); np += tolen; } } start = end + len; } return p; } xstring operator +(const wchar_t* lhs, const xstring& rhs) { return xstring(lhs).concat(rhs.c_str()); }