StringData* StringData::append(StringSlice range) { assert(!hasMultipleRefs()); auto s = range.ptr; auto const len = range.len; if (len == 0) return this; auto const newLen = size_t(m_len) + size_t(len); if (UNLIKELY(newLen > MaxSize)) { throw_string_too_large(newLen); } /* * We may have an aliasing append. We don't allow appending with an * interior pointer, although we may be asked to append less than * the whole string in an aliasing situation. */ ALIASING_APPEND_ASSERT(s, len); auto const requestLen = static_cast<uint32_t>(newLen); auto const target = UNLIKELY(isShared()) ? escalate(requestLen) : reserve(requestLen); memcpy(target->mutableData() + m_len, s, len); target->setSize(newLen); assert(target->checkSane()); return target; }
void StringData::setChar(int offset, char ch) { ASSERT(offset >= 0 && offset < size()); if (isImmutable()) { escalate(); } ((char*)m_data)[offset] = ch; }
ArrayData *SharedMap::lvalNew(Variant *&ret, bool copy) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->lvalNew(ret, false); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::setRef(StringData* k, CVarRef v, bool copy) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->setRef(k, v, false); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::remove(const StringData* k, bool copy) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->remove(k, false); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::append(const ArrayData *elems, ArrayOp op, bool copy) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->append(elems, op, false); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::prepend(CVarRef v, bool copy) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->prepend(v, false); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::remove(CVarRef k, bool copy, int64 prehash /* = -1 */) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->remove(k, false, prehash); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::set(CVarRef k, CVarRef v, bool copy, int64 prehash) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->set(k, v, false, prehash); if (ee) { escalated->release(); return ee; } return escalated; }
ArrayData *SharedMap::lval(StringData* k, Variant *&ret, bool copy, bool checkExist /* = false */) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->lval(k, ret, false); if (ee) { escalated->release(); return ee; } return escalated; }
StringData* StringData::increment() { assert(!isStatic()); assert(!empty()); auto const sd = UNLIKELY(isShared()) ? escalate(m_len + 1) : reserve(m_len + 1); sd->incrementHelper(); return sd; }
ArrayData *SharedMap::lval(CVarRef k, Variant *&ret, bool copy, int64 prehash /* = -1 */, bool checkExist /* = false */) { ArrayData *escalated = escalate(); ArrayData *ee = escalated->lval(k, ret, false, prehash); if (ee) { escalated->release(); return ee; } return escalated; }
inline ALWAYS_INLINE CVarRef Array::setRefImpl(const T &key, CVarRef v) { if (!m_px) { ArrayData *data = ArrayData::CreateRef(key, v); ArrayBase::operator=(data); } else { escalate(); ArrayData *escalated = m_px->setRef(key, v, (m_px->getCount() > 1)); if (escalated != m_px) ArrayBase::operator=(escalated); } return v; }
void StringData::inc() { if (empty()) { m_len = (IsLiteral | 1); m_data = "1"; return; } if (isImmutable()) { escalate(); } char *overflowed = increment_string((char *)m_data, size()); if (overflowed) { assign(overflowed, AttachString); } }
void StringData::inc() { ASSERT(!isStatic()); ASSERT(!empty()); if (isImmutable()) { escalate(); } StringSlice s = slice(); // if increment_string overflows, it returns a new ptr and updates s.len ASSERT(int(s.len) >= 0 && s.len <= MaxSize); // safe int/uint casting int len = s.len; char *overflowed = increment_string((char *)s.ptr, len); if (overflowed) attach(overflowed, len); m_hash = 0; }
StringData* StringData::append(StringSlice r1, StringSlice r2, StringSlice r3) { assert(!hasMultipleRefs()); auto const len = r1.len + r2.len + r3.len; if (len == 0) return this; if (UNLIKELY(uint32_t(len) > MaxSize)) { throw_string_too_large(len); } if (UNLIKELY(size_t(m_len) + size_t(len) > MaxSize)) { throw_string_too_large(size_t(len) + size_t(m_len)); } auto const newLen = m_len + len; /* * We may have an aliasing append. We don't allow appending with an * interior pointer, although we may be asked to append less than * the whole string in an aliasing situation. */ ALIASING_APPEND_ASSERT(r1.ptr, r1.len); ALIASING_APPEND_ASSERT(r2.ptr, r2.len); ALIASING_APPEND_ASSERT(r3.ptr, r3.len); auto const target = UNLIKELY(isShared()) ? escalate(newLen) : reserve(newLen); auto const mslice = target->bufferSlice(); /* * memcpy is safe even if it's a self append---the regions will be * disjoint, since rN.ptr can't point past the start of our source * pointer, and rN.len is smaller than the old length. */ void* p = mslice.ptr; p = memcpy((char*)p + m_len, r1.ptr, r1.len); p = memcpy((char*)p + r1.len, r2.ptr, r2.len); memcpy((char*)p + r2.len, r3.ptr, r3.len); target->setSize(newLen); assert(target->checkSane()); return target; }
void StringData::append(const char* s, int len) { assert(!isStatic() && getCount() <= 1); if (len == 0) return; if (UNLIKELY(uint32_t(len) > MaxSize)) { throw InvalidArgumentException("len > 2^31-2", len); } if (UNLIKELY(size_t(m_len) + size_t(len) > MaxSize)) { throw FatalErrorException(0, "String length exceeded 2^31-2: %zu", size_t(len) + size_t(m_len)); } const uint32_t newLen = m_len + len; /* * In case we're being to asked to append our own string, we need to * load the old pointer value (it might change when we reserve * below). * * We don't allow appending with an interior pointers here, although * we may be asked to append less than the whole string. */ auto const oldDataPtr = rawdata(); assert(uintptr_t(s) <= uintptr_t(rawdata()) || uintptr_t(s) >= uintptr_t(rawdata() + capacity())); assert(s != rawdata() || len <= m_len); auto const mslice = UNLIKELY(isShared()) ? escalate(newLen) : reserve(newLen); if (UNLIKELY(s == oldDataPtr)) s = mslice.ptr; /* * memcpy is safe even if it's a self append---the regions will be * disjoint, since s can't point past our oldDataPtr, and len is * smaller than the old length. */ memcpy(mslice.ptr + m_len, s, len); setSize(newLen); assert(checkSane()); }
// mutations void StringData::setChar(int offset, CStrRef substring) { assert(!isStatic()); if (offset >= 0) { StringSlice s = slice(); if (s.len == 0) { // PHP will treat data as an array and we don't want to follow that. throw OffsetOutOfRangeException(); } char c = substring.empty() ? 0 : substring.data()[0]; if (uint32_t(offset) < s.len) { ((char*)s.ptr)[offset] = c; } else if (offset <= RuntimeOption::StringOffsetLimit) { uint32_t newlen = offset + 1; MutableSlice buf = isImmutable() ? escalate(newlen) : reserve(newlen); memset(buf.ptr + s.len, ' ', newlen - s.len); buf.ptr[offset] = c; setSize(newlen); } else { throw OffsetOutOfRangeException(); } m_hash = 0; // since we modified the string. } }
StringData* StringData::append(folly::StringPiece r1, folly::StringPiece r2) { assert(!hasMultipleRefs()); auto const len = r1.size() + r2.size(); if (len == 0) return this; if (UNLIKELY(size_t(m_len) + size_t(len) > MaxSize)) { throw_string_too_large(size_t(len) + size_t(m_len)); } auto const newLen = m_len + len; /* * We may have an aliasing append. We don't allow appending with an * interior pointer, although we may be asked to append less than * the whole string in an aliasing situation. */ ALIASING_APPEND_ASSERT(r1.data(), r1.size()); ALIASING_APPEND_ASSERT(r2.data(), r2.size()); auto const target = UNLIKELY(isProxy()) ? escalate(newLen) : reserve(newLen); /* * memcpy is safe even if it's a self append---the regions will be * disjoint, since rN.data() can't point past the start of our source * pointer, and rN.size() is smaller than the old length. */ void* p = target->mutableData(); p = memcpy((char*)p + m_len, r1.data(), r1.size()); memcpy((char*)p + r1.size(), r2.data(), r2.size()); target->setSize(newLen); assert(target->checkSane()); return target; }
MapVariant *SharedMap::escalateToMapVariant() const { ASSERT(!RuntimeOption::UseZendArray); return (MapVariant *)escalate(); }
ArrayData *SharedMap::copy() const { return escalate(); }
void StringData::inc() { assert(!isStatic()); assert(!empty()); if (isImmutable()) { escalate(m_len + 1); } else { reserve(m_len + 1); } m_hash = 0; enum class CharKind { UNKNOWN, LOWER_CASE, UPPER_CASE, NUMERIC }; auto const len = m_len; auto const s = m_data; int carry = 0; int pos = len - 1; auto last = CharKind::UNKNOWN; // Shut up the compiler warning int ch; while (pos >= 0) { ch = s[pos]; if (ch >= 'a' && ch <= 'z') { if (ch == 'z') { s[pos] = 'a'; carry=1; } else { s[pos]++; carry=0; } last = CharKind::LOWER_CASE; } else if (ch >= 'A' && ch <= 'Z') { if (ch == 'Z') { s[pos] = 'A'; carry=1; } else { s[pos]++; carry=0; } last = CharKind::UPPER_CASE; } else if (ch >= '0' && ch <= '9') { if (ch == '9') { s[pos] = '0'; carry=1; } else { s[pos]++; carry=0; } last = CharKind::NUMERIC; } else { carry=0; break; } if (carry == 0) { break; } pos--; } if (carry) { if (UNLIKELY(len + 1 > MaxSize)) { throw InvalidArgumentException("len > 2^31-2", len); } assert(len + 2 <= capacity()); memmove(s + 1, s, len); s[len + 1] = '\0'; m_len = len + 1; switch (last) { case CharKind::NUMERIC: s[0] = '1'; break; case CharKind::UPPER_CASE: s[0] = 'A'; break; case CharKind::LOWER_CASE: s[0] = 'a'; break; default: break; } } }
void StringData::setChar(int offset, char ch) { ASSERT(offset >= 0 && offset < size() && !isStatic()); if (isImmutable()) escalate(); ((char*)rawdata())[offset] = ch; m_hash = 0; }
int cmd_umount(int argc, char* argv[]) { char *boot_loop; char *root_loop; struct piimg_img simg; FSTR_DECLARE_WRAPPER(mnt_root, argv[0]); FSTR_DECLARE_NULL (mnt_boot); FSTR_DECLARE_NULL (mnt_dev); FSTR_DECLARE_NULL (mnt_proc); FSTR_DECLARE_NULL (mnt_sys); const FSTR_DECLARE_WRAPPER(dir_boot, "/boot"); const FSTR_DECLARE_WRAPPER(dir_dev, "/dev"); const FSTR_DECLARE_WRAPPER(dir_proc, "/proc"); const FSTR_DECLARE_WRAPPER(dir_sys, "/sys"); memset(&simg, 0, sizeof(struct piimg_img)); if(fstrcat(&mnt_boot, &mnt_root, &dir_boot) || fstrcat(&mnt_dev, &mnt_root, &dir_dev) || fstrcat(&mnt_proc, &mnt_root, &dir_proc) || fstrcat(&mnt_sys, &mnt_root, &dir_sys)) { fprintf(stderr, "Failed to construct mount points.\n"); goto error; } printf("Mount Points\n"); printf("============\n"); printf("/ : %s\n", mnt_root.c_str); printf("/boot: %s\n", mnt_boot.c_str); printf("/dev : %s\n", mnt_dev.c_str); printf("/proc: %s\n", mnt_proc.c_str); printf("/sys : %s\n", mnt_sys.c_str); if(escalate()) goto error; if(ui_umount(mnt_sys.c_str) || ui_umount(mnt_proc.c_str) || ui_umount(mnt_boot.c_str) || ui_umount(mnt_dev.c_str) || ui_umount(mnt_root.c_str)) { goto error; } if(drop()) goto error; fstrfree(&mnt_boot); fstrfree(&mnt_dev); fstrfree(&mnt_proc); fstrfree(&mnt_sys); return 0; error: fstrfree(&mnt_boot); fstrfree(&mnt_dev); fstrfree(&mnt_proc); fstrfree(&mnt_sys); /* TODO: Should clean up allocated loop devices too. */ return 1; }