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; }
/** * concat_ss will decRef the values passed in as appropriate, and it will * incRef the output string */ StringData* concat_ss(StringData* v1, StringData* v2) { if (v1->getCount() > 1) { StringData* ret = NEW(StringData)(v1, v2); ret->setRefCount(1); decRefStr(v2); // Because v1->getCount() is greater than 1, we know we will never // have to release the string here v1->decRefCount(); return ret; } else { v1->append(v2->slice()); decRefStr(v2); return v1; } }
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 = 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; }
/** * concat_ss will will incRef the output string * and decref its first argument */ StringData* concat_ss(StringData* v1, StringData* v2) { if (v1->hasMultipleRefs()) { StringData* ret = StringData::Make(v1, v2); ret->setRefCount(1); // Because v1->getCount() is greater than 1, we know we will never // have to release the string here v1->decRefCount(); return ret; } auto const ret = v1->append(v2->slice()); if (UNLIKELY(ret != v1)) { assert(v1->hasExactlyOneRef()); v1->release(); ret->incRefCount(); } return ret; }
String& String::operator+=(const StringSlice& slice) { if (slice.size() == 0) { return *this; } if (m_px && m_px->getCount() == 1) { m_px->append(slice); return *this; } if (empty()) { if (m_px) decRefStr(m_px); m_px = NEW(StringData)(slice.begin(), slice.size(), CopyString); m_px->setRefCount(1); return *this; } StringData* px = NEW(StringData)(m_px, slice); px->setRefCount(1); decRefStr(m_px); m_px = px; return *this; }
/** * concat_ss will will incRef the output string * and decref its first argument */ StringData* concat_ss(StringData* v1, StringData* v2) { if (v1->getCount() > 1) { StringData* ret = StringData::Make(v1, v2); ret->setRefCount(1); // Because v1->getCount() is greater than 1, we know we will never // have to release the string here v1->decRefCount(); return ret; } auto const newV1 = v1->append(v2->slice()); if (UNLIKELY(newV1 != v1)) { assert(v1->getCount() == 1); v1->release(); newV1->incRefCount(); return newV1; } return v1; }
String& String::operator+=(const StringSlice& slice) { if (slice.size() == 0) { return *this; } if (m_px && m_px->getCount() == 1) { auto const tmp = m_px->append(slice); if (UNLIKELY(tmp != m_px)) StringBase::operator=(tmp); return *this; } if (empty()) { if (m_px) decRefStr(m_px); m_px = StringData::Make(slice.begin(), slice.size(), CopyString); m_px->setRefCount(1); return *this; } StringData* px = StringData::Make(m_px, slice); px->setRefCount(1); decRefStr(m_px); m_px = px; return *this; }
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 && m_px->decRefCount() == 0) { m_px->release(); } m_px = px; px->setRefCount(1); ch = uns->readChar(); if (ch != delimiter1) { throw Exception("Expected '%c' but got '%c'", delimiter1, ch); } checkStatic(); }