mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
309 lines
5.8 KiB
C++
309 lines
5.8 KiB
C++
#include "Core.h"
|
|
|
|
#include "HeapImp.h"
|
|
|
|
static inline void *MAlloc_WS()
|
|
{
|
|
MCache& m = mcache[2];
|
|
FreeLink *l = m.list;
|
|
if(l) {
|
|
m.list = l->next;
|
|
m.count--;
|
|
return l;
|
|
}
|
|
else {
|
|
void *ptr = MAlloc_Get(m, 2);
|
|
return ptr;
|
|
}
|
|
}
|
|
|
|
static inline void MFree_WS(void *ptr)
|
|
{
|
|
MCache& m = mcache[2];
|
|
((FreeLink *)ptr)->next = m.list;
|
|
m.list = (FreeLink *)ptr;
|
|
if(++m.count > CACHEMAX)
|
|
MFree_Reduce(m, 2);
|
|
}
|
|
|
|
/*
|
|
void *MAlloc_WS() { void *ptr = new byte[24 * sizeof(wchar)]; LOG("Alloc " << ptr); return ptr; }
|
|
void MFree_WS(void *ptr) { LOG("Free " << ptr); delete[] (byte *)ptr; }
|
|
*/
|
|
|
|
wchar *WString0::Alloc(int& count)
|
|
{
|
|
if(count <= SMALL) {
|
|
count = SMALL;
|
|
wchar *p = (wchar *)MAlloc_WS();
|
|
return p;
|
|
}
|
|
size_t sz = sizeof(Atomic) + (count + 1) * sizeof(wchar);
|
|
Atomic *rc = (Atomic *)MAlloc(sz);
|
|
count = ((sz - sizeof(Atomic)) >> 1) - 1;
|
|
*rc = 1;
|
|
return (wchar *)(rc + 1);
|
|
}
|
|
|
|
void WString0::Free()
|
|
{
|
|
if(alloc > 0)
|
|
if(IsRc()) {
|
|
Atomic& rc = Rc();
|
|
if(AtomicDec(rc) == 0)
|
|
MFree(&rc);
|
|
}
|
|
else
|
|
MFree_WS(ptr);
|
|
}
|
|
|
|
wchar *WString0::Insert(int pos, int count, const wchar *s)
|
|
{
|
|
ASSERT(pos >= 0 && count >= 0 && pos <= GetCount());
|
|
int newlen = length + count;
|
|
if(newlen < alloc && !IsShared()/* && !(s >= ptr && s <= ptr + length)*/) { //Optimize!
|
|
if(s >= ptr + pos && s <= ptr + length)
|
|
s += count;
|
|
if(pos < length)
|
|
memmove(ptr + pos + count, ptr + pos, (length - pos) * sizeof(wchar));
|
|
length = newlen;
|
|
ptr[newlen] = 0;
|
|
if(s)
|
|
memcpy(ptr + pos, s, count * sizeof(wchar));
|
|
return ptr + pos;
|
|
}
|
|
int all = max(2 * length, newlen);
|
|
wchar *p = Alloc(all);
|
|
if(pos > 0)
|
|
memcpy(p, ptr, pos * sizeof(wchar));
|
|
if(pos < length)
|
|
memcpy(p + pos + count, ptr + pos, (length - pos) * sizeof(wchar));
|
|
if(s)
|
|
memcpy(p + pos, s, count * sizeof(wchar));
|
|
ASSERT(pos + count <= all);
|
|
p[newlen] = 0;
|
|
Free();
|
|
ptr = p;
|
|
length = newlen;
|
|
alloc = all;
|
|
return ptr + pos;
|
|
}
|
|
|
|
void WString0::Set(const WString0& src)
|
|
{
|
|
if(src.alloc <= 0) {
|
|
static wchar h[2];
|
|
ptr = h;
|
|
length = 0;
|
|
alloc = src.alloc;
|
|
return;
|
|
}
|
|
if(src.length == 0) {
|
|
Zero();
|
|
return;
|
|
}
|
|
length = src.length;
|
|
alloc = src.alloc;
|
|
if(src.IsRc()) {
|
|
ptr = src.ptr;
|
|
AtomicInc(Rc());
|
|
}
|
|
else {
|
|
ptr = (wchar *)MAlloc_WS();
|
|
qword *t = (qword *)ptr;
|
|
qword *s = (qword *)src.ptr;
|
|
t[0] = s[0];
|
|
t[1] = s[1];
|
|
t[2] = s[2];
|
|
t[3] = s[3];
|
|
t[4] = s[4];
|
|
t[5] = s[5];
|
|
}
|
|
}
|
|
|
|
void WString0::Cat(const wchar *s, int l)
|
|
{
|
|
if(length + l >= alloc || IsShared())
|
|
Insert(length, l, s);
|
|
else {
|
|
memcpy(ptr + length, s, l * sizeof(wchar));
|
|
ptr[length += l] = 0;
|
|
}
|
|
}
|
|
|
|
void WString0::LCat(int c)
|
|
{
|
|
*Insert(length, 1, NULL) = c;
|
|
}
|
|
|
|
void WString0::Set(const wchar *s, int l)
|
|
{
|
|
alloc = length = l;
|
|
memcpy(ptr = Alloc(alloc), s, l * sizeof(wchar));
|
|
ptr[l] = 0;
|
|
}
|
|
|
|
void WString0::UnShare()
|
|
{
|
|
if(!IsShared()) return;
|
|
int al = length;
|
|
wchar *p = Alloc(al);
|
|
memcpy(p, ptr, (length + 1) * sizeof(wchar));
|
|
Free();
|
|
ptr = p;
|
|
alloc = al;
|
|
}
|
|
|
|
void WString0::Set(int pos, int ch)
|
|
{
|
|
ASSERT(pos >= 0 && pos < GetCount());
|
|
UnShare();
|
|
ptr[pos] = ch;
|
|
}
|
|
|
|
void WString0::Trim(int pos)
|
|
{
|
|
ASSERT(pos >= 0 && pos <= GetCount());
|
|
UnShare();
|
|
length = pos;
|
|
ptr[pos] = 0;
|
|
}
|
|
|
|
void WString0::Remove(int pos, int count)
|
|
{
|
|
ASSERT(pos >= 0 && count >= 0 && pos + count <= GetCount());
|
|
UnShare();
|
|
memmove(ptr + pos, ptr + pos + count, (GetCount() - pos - count + 1) * sizeof(wchar));
|
|
length -= count;
|
|
}
|
|
|
|
void WString0::Insert(int pos, const wchar *s, int count)
|
|
{
|
|
Insert(pos, count, s);
|
|
}
|
|
|
|
WString::WString(WStringBuffer& b)
|
|
{
|
|
length = b.GetLength();
|
|
ptr = b.begin;
|
|
ptr[length] = 0;
|
|
alloc = b.GetAlloc();
|
|
b.Zero();
|
|
}
|
|
|
|
//ToDo
|
|
/*
|
|
WString::WString(const char *s) : B(ToUnicode(s, s ? strlen(s) : 0, CHARSET_DEFAULT)) {}
|
|
WString::WString(const char *s, int n) : B(ToUnicode(s, n, CHARSET_DEFAULT)) {}
|
|
WString::WString(const char *s, const char *lim) : B(ToUnicode(s, s ? lim - s : 0, CHARSET_DEFAULT)) {}
|
|
*/
|
|
|
|
#ifdef _DEBUG
|
|
|
|
WString::WString(const char *s)
|
|
{
|
|
while(*s)
|
|
Cat(*s++);
|
|
}
|
|
|
|
WString::WString(const char *s, int n)
|
|
{
|
|
while(n--)
|
|
Cat(*s++);
|
|
}
|
|
|
|
WString::WString(const char *s, const char *lim)
|
|
{
|
|
while(s < lim)
|
|
Cat(*s++);
|
|
}
|
|
|
|
#endif
|
|
|
|
Atomic WString0::voidptr[2] = { 0, 0 };
|
|
|
|
WString WString::GetVoid()
|
|
{
|
|
WString b;
|
|
b.alloc = -1;
|
|
return b;
|
|
}
|
|
|
|
void WStringBuffer::Zero()
|
|
{
|
|
static wchar h[2];
|
|
begin = end = limit = h;
|
|
}
|
|
|
|
wchar *WStringBuffer::Alloc(int count, int& alloc)
|
|
{
|
|
if(count <= 23) {
|
|
wchar *s = (wchar *)MAlloc_WS();
|
|
alloc = WString0::SMALL;
|
|
return s;
|
|
}
|
|
else {
|
|
size_t sz = sizeof(Atomic) + (count + 1) * sizeof(wchar);
|
|
Atomic *rc = (Atomic *)MAlloc(sz);
|
|
alloc = ((sz - sizeof(Atomic)) >> 1) - 1;
|
|
*rc = 1;
|
|
return (wchar *)(rc + 1);
|
|
}
|
|
}
|
|
|
|
void WStringBuffer::Free()
|
|
{
|
|
int all = limit - begin;
|
|
if(all == WString0::SMALL)
|
|
MFree_WS(begin);
|
|
if(all > WString0::SMALL)
|
|
MFree((Atomic *)begin - 1);
|
|
}
|
|
|
|
void WStringBuffer::Expand(int n, const wchar *cat, int l)
|
|
{
|
|
int al;
|
|
int ep = end - begin;
|
|
wchar *p = Alloc(n, al);
|
|
memcpy(p, begin, GetLength() * sizeof(wchar));
|
|
if(cat) {
|
|
memcpy(p + ep, cat, l * sizeof(wchar));
|
|
ep += l;
|
|
}
|
|
Free();
|
|
begin = p;
|
|
end = begin + ep;
|
|
limit = begin + al;
|
|
}
|
|
|
|
void WStringBuffer::Expand()
|
|
{
|
|
Expand(GetLength() * 2);
|
|
}
|
|
|
|
void WStringBuffer::SetLength(int l)
|
|
{
|
|
if(l > (limit - begin))
|
|
Expand(l);
|
|
end = begin + l;
|
|
}
|
|
|
|
void WStringBuffer::Cat(const wchar *s, int l)
|
|
{
|
|
if(end + l > limit)
|
|
Expand(max(GetLength(), l) + GetLength(), s, l);
|
|
else {
|
|
memcpy(end, s, l * sizeof(wchar));
|
|
end += l;
|
|
}
|
|
}
|
|
|
|
void WStringBuffer::Set(WString& s)
|
|
{
|
|
s.UnShare();
|
|
int l = s.GetLength();
|
|
begin = s.ptr;
|
|
end = begin + l;
|
|
limit = begin + s.GetAlloc();
|
|
s.Zero();
|
|
}
|