Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
void StringData::setChar(int offset, char ch) {
  ASSERT(offset >= 0 && offset < size());
  if (isImmutable()) {
    escalate();
  }
  ((char*)m_data)[offset] = ch;
}
Ejemplo n.º 3
0
ArrayData *SharedMap::lvalNew(Variant *&ret, bool copy) {
    ArrayData *escalated = escalate();
    ArrayData *ee = escalated->lvalNew(ret, false);
    if (ee) {
        escalated->release();
        return ee;
    }
    return escalated;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
ArrayData *SharedMap::prepend(CVarRef v, bool copy) {
    ArrayData *escalated = escalate();
    ArrayData *ee = escalated->prepend(v, false);
    if (ee) {
        escalated->release();
        return ee;
    }
    return escalated;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
StringData* StringData::increment() {
  assert(!isStatic());
  assert(!empty());

  auto const sd = UNLIKELY(isShared())
    ? escalate(m_len + 1)
    : reserve(m_len + 1);
  sd->incrementHelper();
  return sd;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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);
  }
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
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;
}
Ejemplo n.º 17
0
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());
}
Ejemplo n.º 18
0
// 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.
  }
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
MapVariant *SharedMap::escalateToMapVariant() const {
  ASSERT(!RuntimeOption::UseZendArray);
  return (MapVariant *)escalate();
}
Ejemplo n.º 21
0
ArrayData *SharedMap::copy() const {
    return escalate();
}
Ejemplo n.º 22
0
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;
    }
  }
}
Ejemplo n.º 23
0
void StringData::setChar(int offset, char ch) {
  ASSERT(offset >= 0 && offset < size() && !isStatic());
  if (isImmutable()) escalate();
  ((char*)rawdata())[offset] = ch;
  m_hash = 0;
}
Ejemplo n.º 24
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;
}