Exemple #1
0
StringData* StringData::reserve(size_t cap) {
    assert(!isImmutable() && !hasMultipleRefs());
    assert(isFlat());

    if (cap <= capacity()) return this;

    cap = std::min(cap + cap / 4, size_t(MaxSize));
    auto const sd = allocFlatForLenSmall(cap);

    // Request-allocated StringData are always aligned at 16 bytes, thus it is
    // safe to copy in 16-byte groups.
#ifdef NO_M_DATA
    // layout: [m_lenAndHash][header][...data]
    sd->m_lenAndHash = m_lenAndHash;
    // This copies the characters (m_len bytes), and the trailing zero (1 byte)
    memcpy16_inline(sd+1, this+1, (m_len + 1 + 15) & ~0xF);
    assertx(reinterpret_cast<uintptr_t>(this+1) % 16 == 0);
#else
    // layout: [m_data][header][m_lenAndHash][...data]
    // This copies m_lenAndHash (8 bytes), the characters (m_len bytes),
    // and the trailing zero (1 byte).
    memcpy16_inline(&sd->m_lenAndHash, &m_lenAndHash,
                    (m_len + 8 + 1 + 15) & ~0xF);
    assertx(reinterpret_cast<uintptr_t>(&m_lenAndHash) + 8 ==
            reinterpret_cast<uintptr_t>(m_data));
    assertx(reinterpret_cast<uintptr_t>(&m_lenAndHash) % 16 == 0);
#endif

    assert(sd->hasExactlyOneRef());
    assert(sd->isFlat());
    assert(sd->checkSane());
    return sd;
}
Exemple #2
0
StringData* StringData::Make(size_t reserveLen) {
  auto const sd = allocFlatForLenSmall(reserveLen);
  sd->setSize(0);

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #3
0
StringData* StringData::Make(const StringData* s, CopyStringMode) {
  auto const sd = allocFlatForLenSmall(s->m_len);
  sd->m_lenAndHash = s->m_lenAndHash;
  auto const data = static_cast<void*>(sd + 1);
  *memcpy8(data, s->data(), s->m_len) = 0;

  assert(sd->same(s));
  return sd;
}
Exemple #4
0
// State transition from Mode::Shared to Mode::Flat.
StringData* StringData::escalate(size_t cap) {
  assert(isShared() && !isStatic() && cap >= m_len);

  auto const sd = allocFlatForLenSmall(cap);
  sd->m_lenAndHash = m_lenAndHash;
  auto const data = reinterpret_cast<char*>(sd + 1);
  *memcpy8(data, m_data, m_len) = 0;

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #5
0
StringData* StringData::shrinkImpl(size_t len) {
  assert(!isImmutable() && !hasMultipleRefs());
  assert(isFlat());
  assert(len <= capacity());

  auto const sd = allocFlatForLenSmall(len);
  sd->m_lenAndHash = len;
  auto const src = static_cast<void*>(this + 1);
  auto const dst = static_cast<void*>(sd + 1);
  *memcpy8(dst, src, len) = 0;

  assert(sd->checkSane());
  return sd;
}
Exemple #6
0
StringData* StringData::Make(StringSlice r1, StringSlice r2) {
  auto const len = r1.len + r2.len;
  auto const sd = allocFlatForLenSmall(len);
  sd->m_lenAndHash = len; // hash=0

  auto const data = reinterpret_cast<char*>(sd + 1);
  memcpy(data, r1.ptr, r1.len);
  memcpy(data + r1.len, r2.ptr, r2.len);
  data[len] = 0;

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #7
0
StringData* StringData::Make(folly::StringPiece r1, folly::StringPiece r2) {
  auto const len = r1.size() + r2.size();
  auto const sd = allocFlatForLenSmall(len);
  sd->m_lenAndHash = len; // hash=0

  auto const data = reinterpret_cast<char*>(sd + 1);
  memcpy(data,             r1.data(), r1.size());
  memcpy(data + r1.size(), r2.data(), r2.size());
  data[len] = 0;

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #8
0
StringData* StringData::Make(const StringData* s1, const StringData* s2) {
  auto const len = s1->m_len + s2->m_len;
  // `memcpy8()' could overrun the buffer by at most 7 bytes, so we allocate 6
  // more bytes here, which (together with the trailing 0) makes it safe.
  auto const sd = allocFlatForLenSmall(len + 6);
  sd->m_lenAndHash = len; // hash=0

  auto const data = reinterpret_cast<char*>(sd + 1);
  auto const next = memcpy8(data, s1->m_data, s1->m_len);
  *memcpy8(next, s2->m_data, s2->m_len) = 0;

  assert(sd->getCount() == 1);
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #9
0
StringData* StringData::Make(StringSlice r1, StringSlice r2,
                             StringSlice r3) {
  auto const len = r1.len + r2.len + r3.len;
  auto const sd = allocFlatForLenSmall(len);
  sd->m_lenAndHash  = len; // hash=0

  char* p = reinterpret_cast<char*>(sd + 1);
  p = static_cast<char*>(memcpy(p, r1.ptr, r1.len));
  p = static_cast<char*>(memcpy(p + r1.len, r2.ptr, r2.len));
  p = static_cast<char*>(memcpy(p + r2.len, r3.ptr, r3.len));
  p[r3.len] = 0;

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #10
0
StringData* StringData::Make(folly::StringPiece r1, folly::StringPiece r2,
                             folly::StringPiece r3) {
  auto const len = r1.size() + r2.size() + r3.size();
  auto const sd = allocFlatForLenSmall(len);
  sd->m_lenAndHash  = len; // hash=0

  auto p = reinterpret_cast<char*>(sd + 1);
  p = static_cast<char*>(memcpy(p,             r1.data(), r1.size()));
  p = static_cast<char*>(memcpy(p + r1.size(), r2.data(), r2.size()));
  p = static_cast<char*>(memcpy(p + r2.size(), r3.data(), r3.size()));
  p[r3.size()] = 0;

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Exemple #11
0
StringData* StringData::Make(StringSlice sl, CopyStringMode) {
  auto const sd = allocFlatForLenSmall(sl.len);
  sd->m_lenAndHash = sl.len; // hash=0
  auto const data = reinterpret_cast<char*>(sd + 1);

  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 == sd);
  assert(ret->m_len == sl.len);
  assert(ret->hasExactlyOneRef());
  assert(ret->m_hash == 0);
  assert(ret->isFlat());
  assert(ret->checkSane());
  return ret;
}