APCHandle* APCString::MakeShared( DataType type, StringData* data, size_t& size) { auto const len = data->size(); auto const cap = roundUpPackedCap(static_cast<uint32_t>(len)); auto const apcStr = new (cap + 1) APCString(type); auto const capCode = packedCapToCode(cap); size = cap + 1 + sizeof(APCString); apcStr->m_data.m_data = reinterpret_cast<char*>(apcStr + 1); apcStr->m_data.m_capAndCount = capCode; // count=0 apcStr->m_data.m_len = len; // don't store hash apcStr->m_data.m_data[len] = 0; auto const mcret = memcpy(apcStr->m_data.m_data, data->data(), len); auto const ret = reinterpret_cast<APCString*>(mcret) - 1; // Recalculating ret from mcret avoids a spill. ret->m_data.preCompute(); assert(ret == apcStr); assert(apcStr->m_data.m_hash != 0); assert(ret->m_data.m_data[len] == 0); assert(ret->m_data.m_count == 0); assert(ret->m_data.isFlat()); assert(ret->m_data.checkSane()); return ret->getHandle(); }
APCHandle::Pair APCString::MakeSharedString(DataType type, StringData* data) { auto const len = data->size(); auto const cap = roundUpPackedCap(static_cast<uint32_t>(len)); auto const capCode = packedCapToCode(cap); auto apcStr = new (cap + 1) APCString(type); auto size = cap + 1 + sizeof(APCString); apcStr->m_str.m_data = reinterpret_cast<char*>(apcStr + 1); apcStr->m_str.m_capAndCount = HeaderKind::String << 24 | capCode; // count=0 apcStr->m_str.m_len = len; // don't store hash apcStr->m_str.m_data[len] = 0; assert(apcStr == reinterpret_cast<APCString*>(apcStr->m_str.m_data) - 1); auto const mcret = memcpy(apcStr->m_str.m_data, data->data(), len); apcStr = reinterpret_cast<APCString*>(mcret) - 1; // Recalculating apcStr from mcret avoids a spill. apcStr->m_str.preCompute(); assert(apcStr->m_str.m_hash != 0); assert(apcStr->m_str.m_data[len] == 0); assert(apcStr->m_str.m_count == 0); assert(apcStr->m_str.isFlat()); assert(apcStr->m_str.checkSane()); return {apcStr->getHandle(), size}; }
// create either a static or an uncounted string. // Diffrence between static and uncounted is in the lifetime // of the string. Static are alive for the lifetime of the process. // Uncounted are not ref counted but will be deleted at some point. StringData* StringData::MakeShared(StringSlice sl, bool trueStatic) { if (UNLIKELY(sl.len > StringData::MaxSize)) { throw_string_too_large(sl.len); } auto const encodable = roundUpPackedCap(sl.len); auto const need = encodable + kCapOverhead; auto const sd = static_cast<StringData*>( trueStatic ? low_malloc(need) : malloc(need) ); auto const data = reinterpret_cast<char*>(sd + 1); auto const capCode = packedCapToCode(encodable); sd->m_data = data; sd->m_capAndCount = HeaderKind::String << 24 | capCode; // count=0 sd->m_lenAndHash = sl.len; // hash=0 data[sl.len] = 0; auto const mcret = memcpy(data, sl.ptr, sl.len); auto const ret = reinterpret_cast<StringData*>(mcret) - 1; // Recalculating ret from mcret avoids a spill. assert(ret->m_hash == 0); assert(ret->m_count == 0); if (trueStatic) { ret->setStatic(); } else { ret->setUncounted(); } assert(ret == sd); assert(ret->isFlat()); assert(trueStatic ? ret->isStatic() : ret->isUncounted()); assert(ret->checkSane()); return ret; }