String &String::operator+=(const String& str) { if (!str.empty()) { if (empty()) { StringBase::operator=(str.m_px); } else if (m_px->getCount() == 1) { auto tmp = m_px->append(str.slice()); if (UNLIKELY(tmp != m_px)) StringBase::operator=(tmp); } else { StringData* px = StringData::Make(m_px, str.slice()); decRefStr(m_px); px->setRefCount(1); m_px = px; } } return *this; }
String &String::operator+=(litstr s) { if (s && *s) { if (empty()) { m_px = NEW(StringData)(s, AttachLiteral); m_px->setRefCount(1); } else if (m_px->getCount() == 1) { m_px->append(s, strlen(s)); } else { StringData* px = NEW(StringData)(m_px, s); px->setRefCount(1); decRefStr(m_px); m_px = px; } } return *this; }
String &String::operator+=(litstr s) { if (s && *s) { if (empty()) { m_px = StringData::Make(s, CopyString); m_px->setRefCount(1); } else if (m_px->getCount() == 1) { auto const tmp = m_px->append(StringSlice(s, strlen(s))); if (UNLIKELY(tmp != m_px)) StringBase::operator=(tmp); } else { StringData* px = StringData::Make(m_px, s); px->setRefCount(1); decRefStr(m_px); m_px = px; } } return *this; }
void Variant::setEvalScalar() { switch (m_type) { case KindOfUninit: case KindOfNull: case KindOfBoolean: case KindOfInt64: case KindOfDouble: case KindOfStaticString: return; case KindOfString: { StringData *pstr = m_data.pstr; if (!pstr->isStatic()) { StringData *sd = makeStaticString(pstr); decRefStr(pstr); m_data.pstr = sd; assert(m_data.pstr->isStatic()); m_type = KindOfStaticString; } return; } case KindOfPersistentArray: case KindOfArray: { auto parr = m_data.parr; if (!parr->isStatic()) { auto ad = ArrayData::GetScalarArray(parr); assert(ad->isStatic()); m_data.parr = ad; m_type = KindOfPersistentArray; decRefArr(parr); } return; } case KindOfObject: case KindOfResource: case KindOfRef: case KindOfClass: break; } not_reached(); }
/** * postSort() runs after the sort has been performed. For MixedArray, postSort() * handles rebuilding the hash. Also, if resetKeys is true, postSort() will * renumber the keys 0 thru n-1. */ void MixedArray::postSort(bool resetKeys) { // nothrow guarantee assert(m_size > 0); auto const ht = hashTab(); initHash(ht, m_scale); if (resetKeys) { for (uint32_t pos = 0; pos < m_used; ++pos) { auto& e = data()[pos]; if (e.hasStrKey()) decRefStr(e.skey); e.setIntKey(pos); ht[pos] = pos; } m_nextKI = m_size; } else { auto mask = this->mask(); auto data = this->data(); for (uint32_t pos = 0; pos < m_used; ++pos) { auto& e = data[pos]; *findForNewInsert(ht, mask, e.probe()) = pos; } } }
String &String::operator^=(CStrRef v) { const char *s1 = data(); const char *s2 = v.data(); int len1 = size(); int len2 = v.size(); int len; char *copy = NULL; if (len2 < len1) { len = len2; copy = string_duplicate(s2, len2); for (int i = 0; i < len2; i++) copy[i] ^= s1[i]; } else { len = len1; copy = string_duplicate(s1, len1); for (int i = 0; i < len1; i++) copy[i] ^= s2[i]; } if (m_px) decRefStr(m_px); m_px = NEW(StringData)(copy, len, AttachString); m_px->setRefCount(1); return *this; }
int64_t switchStringHelper(StringData* s, int64_t base, int64_t nTargets) { int64_t ival; double dval; switch (s->isNumericWithVal(ival, dval, 1)) { case KindOfNull: ival = switchBoundsCheck(0, base, nTargets); break; case KindOfDouble: ival = switchBoundsCheck(dval, base, nTargets); break; case KindOfInt64: ival = switchBoundsCheck(ival, base, nTargets); break; default: not_reached(); } decRefStr(s); return ival; }
/** * postSort() runs after the sort has been performed. For HphpArray, postSort() * handles rebuilding the hash. Also, if resetKeys is true, postSort() will * renumber the keys 0 thru n-1. */ void HphpArray::postSort(bool resetKeys) { assert(m_size > 0); size_t tableSize = computeTableSize(m_tableMask); initHash(m_hash, tableSize); m_hLoad = 0; if (resetKeys) { for (uint32_t pos = 0; pos < m_used; ++pos) { Elm* e = &m_data[pos]; if (e->hasStrKey()) decRefStr(e->key); e->setIntKey(pos); m_hash[pos] = pos; } m_nextKI = m_size; } else { for (uint32_t pos = 0; pos < m_used; ++pos) { Elm* e = &m_data[pos]; ElmInd* ei = findForNewInsert(e->hasIntKey() ? e->ikey : e->hash()); *ei = pos; } } m_hLoad = m_size; }
/** * postSort() runs after the sort has been performed. For MixedArray, postSort() * handles rebuilding the hash. Also, if resetKeys is true, postSort() will * renumber the keys 0 thru n-1. */ void MixedArray::postSort(bool resetKeys) { assert(m_size > 0); auto const ht = hashTab(); initHash(ht, hashSize()); if (resetKeys) { for (uint32_t pos = 0; pos < m_used; ++pos) { auto& e = data()[pos]; if (e.hasStrKey()) decRefStr(e.skey); e.setIntKey(pos); ht[pos] = pos; } m_nextKI = m_size; } else { auto mask = m_tableMask; auto data = this->data(); for (uint32_t pos = 0; pos < m_used; ++pos) { auto& e = data[pos]; auto ei = findForNewInsert(ht, mask, e.hasIntKey() ? e.ikey : e.hash()); *ei = pos; } } }
void Variant::setEvalScalar() { switch (m_type) { DT_UNCOUNTED_CASE: return; case KindOfString: { StringData *pstr = m_data.pstr; if (!pstr->isStatic()) { StringData *sd = makeStaticString(pstr); decRefStr(pstr); m_data.pstr = sd; assert(m_data.pstr->isStatic()); m_type = KindOfStaticString; } return; } case KindOfArray: { ArrayData *parr = m_data.parr; if (!parr->isStatic()) { ArrayData *ad = ArrayData::GetScalarArray(parr); decRefArr(parr); m_data.parr = ad; assert(m_data.parr->isStatic()); } return; } case KindOfObject: case KindOfResource: case KindOfRef: case KindOfClass: break; } not_reached(); }
void String::unserialize(VariableUnserializer *uns, char delimiter0 /* = '"' */, char delimiter1 /* = '"' */) { int64 size = uns->readInt(); if (size >= RuntimeOption::MaxSerializedStringSize) { throw Exception("Size of serialized string (%d) exceeds max", int(size)); } if (size < 0) { throw Exception("Size of serialized string (%d) must not be negative", int(size)); } char ch = uns->readChar(); if (ch != ':') { throw Exception("Expected ':' but got '%c'", ch); } ch = uns->readChar(); if (ch != delimiter0) { throw Exception("Expected '%c' but got '%c'", delimiter0, ch); } StringData *px = NEW(StringData)(int(size)); MutableSlice buf = px->mutableSlice(); assert(size <= buf.len); uns->read(buf.ptr, size); px->setSize(size); if (m_px) decRefStr(m_px); m_px = px; px->setRefCount(1); ch = uns->readChar(); if (ch != delimiter1) { throw Exception("Expected '%c' but got '%c'", delimiter1, ch); } checkStatic(); }
String &String::operator=(const std::string & s) { if (m_px) decRefStr(m_px); m_px = NEW(StringData)(s.c_str(), s.size(), CopyString); m_px->setRefCount(1); return *this; }
void Variant::setEvalScalar() { assertx(cellIsPlausible(*this)); auto const do_array = [this]{ auto parr = m_data.parr; if (!parr->isStatic()) { auto ad = ArrayData::GetScalarArray(parr); assert(ad->isStatic()); m_data.parr = ad; decRefArr(parr); } }; switch (m_type) { case KindOfUninit: case KindOfNull: case KindOfBoolean: case KindOfInt64: case KindOfDouble: return; case KindOfString: m_type = KindOfPersistentString; case KindOfPersistentString: { auto pstr = m_data.pstr; if (!pstr->isStatic()) { StringData *sd = makeStaticString(pstr); decRefStr(pstr); m_data.pstr = sd; assert(m_data.pstr->isStatic()); } return; } case KindOfVec: m_type = KindOfPersistentVec; case KindOfPersistentVec: do_array(); return; case KindOfDict: m_type = KindOfPersistentDict; case KindOfPersistentDict: do_array(); return; case KindOfKeyset: m_type = KindOfPersistentKeyset; case KindOfPersistentKeyset: do_array(); return; case KindOfArray: m_type = KindOfPersistentArray; case KindOfPersistentArray: do_array(); return; case KindOfObject: case KindOfResource: case KindOfRef: case KindOfClass: break; } not_reached(); }
/** * print_string will decRef the string */ void print_string(StringData* s) { g_context->write(s->data(), s->size()); TRACE(1, "t-x64 output(str): (%p) %43s\n", s->data(), escapeStringForCPP(s->data(), s->size()).data()); decRefStr(s); }
HOT_FUNC_VM TypedValue* ldGblAddrDefHelper(StringData* name) { TypedValue* r = g_vmContext->m_globalVarEnv->lookupAdd(name); decRefStr(name); return r; }
void tvCastToKeysetInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); ArrayData* a; do { switch (tv->m_type) { case KindOfUninit: case KindOfNull: raise_warning("Null to keyset conversion"); a = staticEmptyKeysetArray(); continue; case KindOfBoolean: raise_warning("Bool to keyset conversion"); a = staticEmptyKeysetArray(); continue; case KindOfInt64: raise_warning("Int to keyset conversion"); a = staticEmptyKeysetArray(); continue; case KindOfDouble: raise_warning("Double to keyset conversion"); a = staticEmptyKeysetArray(); continue; case KindOfPersistentString: case KindOfString: raise_warning("String to keyset conversion"); a = staticEmptyKeysetArray(); decRefStr(tv->m_data.pstr); continue; case KindOfResource: raise_warning("Resource to keyset conversion"); a = staticEmptyKeysetArray(); decRefRes(tv->m_data.pres); continue; case KindOfPersistentVec: case KindOfVec: { auto* adIn = tv->m_data.parr; assert(adIn->isVecArray()); a = PackedArray::ToKeysetVec(adIn, adIn->cowCheck()); assert(a != adIn); decRefArr(adIn); continue; } case KindOfPersistentDict: case KindOfDict: { auto* adIn = tv->m_data.parr; assert(adIn->isDict()); a = MixedArray::ToKeysetDict(adIn, adIn->cowCheck()); if (a != adIn) decRefArr(adIn); continue; } case KindOfPersistentArray: case KindOfArray: { auto* adIn = tv->m_data.parr; assert(adIn->isPHPArray()); a = adIn->toKeyset(adIn->cowCheck()); if (a != adIn) decRefArr(adIn); continue; } case KindOfPersistentKeyset: case KindOfKeyset: assert(tv->m_data.parr->isKeyset()); return; case KindOfObject: { auto* obj = tv->m_data.pobj; if (!obj->isCollection()) { raise_warning("Non-collection object conversion to keyset"); a = staticEmptyKeysetArray(); } else { auto keyset = collections::toArray(obj).toKeyset(); decRefObj(obj); a = keyset.detach(); } continue; } case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); assert(!a->isRefCounted() || a->hasExactlyOneRef()); tv->m_data.parr = a; tv->m_type = KindOfKeyset; assert(cellIsPlausible(*tv)); }
void String::checkStaticHelper() { if (StringData* t = StringData::FindStaticString(m_px)) { decRefStr(m_px); m_px = t; } }
String &String::operator=(const StaticString& str) { if (m_px) decRefStr(m_px); m_px = str.m_px; return *this; }