// These are String methods which are best inlined in heap allocator void String0::LSet(const String0& s) { w[2] = s.w[2]; w[3] = s.w[3]; if(s.IsRef()) { ptr = s.ptr; if(ptr != (char *)(voidptr + 1)) AtomicInc(s.Ref()->refcount); } else { ptr = (char *)MemoryAlloc32_i(); memcpy(qptr, s.qptr, 32); // optimizes to movups } } void String0::LFree() { if(IsRef()) { if(ptr != (char *)(voidptr + 1)) { Rc *rc = Ref(); ASSERT(rc->refcount > 0); if(AtomicDec(rc->refcount) == 0) MemoryFree(rc); } } else MemoryFree32_i(ptr); } force_inline char *String0::Alloc_(int count, char& kind) { if(count < 32) { kind = MEDIUM; return (char *)MemoryAlloc32_i(); } size_t sz = sizeof(Rc) + count + 1; Rc *rc = (Rc *)MemoryAllocSz(sz); rc->alloc = count == INT_MAX ? INT_MAX : (int)sz - sizeof(Rc) - 1; rc->refcount = 1; kind = min(rc->alloc, 255); return rc->GetPtr(); } char *String0::Alloc(int count, char& kind) { return Alloc_(count, kind); } void String0::SetL(const char *s, int len) { ptr = Alloc_(len, chr[KIND]); memcpy8(ptr, s, len); ptr[len] = 0; LLen() = len; SLen() = 15; } void String0::LCat(int c) { if(IsSmall()) { qword *x = (qword *)MemoryAlloc32_i(); x[0] = q[0]; x[1] = q[1]; LLen() = SLen(); SLen() = 15; chr[KIND] = MEDIUM; qptr = x; } int l = LLen(); if(IsRef() ? !IsShared() && l < (int)Ref()->alloc : l < 31) { ptr[l] = c; ptr[LLen() = l + 1] = 0; } else { char *s = Insert(l, 1, NULL); s[0] = c; s[1] = 0; } } char *StringBuffer::Alloc(int count, int& alloc) { if(count <= 31) { char *s = (char *)MemoryAlloc32_i(); alloc = 31; return s; } else { size_t sz = sizeof(Rc) + count + 1; Rc *rc = (Rc *)MemoryAlloc(sz); alloc = rc->alloc = (int)min((size_t)INT_MAX, sz - sizeof(Rc) - 1); rc->refcount = 1; return (char *)(rc + 1); } } void StringBuffer::Set(String& s) { s.UnShare(); int l = s.GetLength(); if(s.GetAlloc() == 14) { pbegin = (char *)MemoryAlloc32_i(); limit = pbegin + 31; memcpy8(pbegin, s.Begin(), l); pend = pbegin + l; } else { pbegin = s.ptr; pend = pbegin + l; limit = pbegin + s.GetAlloc(); } s.Zero(); } void StringBuffer::Free() { if(pbegin == buffer) return; int all = (int)(limit - pbegin); if(all == 31) MemoryFree32_i(pbegin); if(all > 31) MemoryFree((Rc *)pbegin - 1); }