Ejemplo n.º 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) + 1);

  auto const allocRet = allocFlatForLen(cap);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  sd->m_data          = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  // request-allocated StringData are always aligned at 16 bytes, thus it is
  // safe to copy in 16-byte groups. This copies m_lenAndHash (8 bytes), the
  // characters (m_len bytes), add 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);

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Ejemplo n.º 2
0
StringData* StringData::Make(const StringData* s, CopyStringMode) {
  auto const allocRet = allocFlatForLen(s->m_len);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);
  sd->m_data          = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash    = s->m_lenAndHash;
  *memcpy8(data, s->m_data, s->m_len) = 0;

  assert(sd->same(s));
  return sd;
}
Ejemplo n.º 3
0
StringData* StringData::Make(size_t reserveLen) {
  auto const allocRet = allocFlatForLen(reserveLen);
  auto const sd       = allocRet.first;
  auto const capCode  = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  data[0] = 0;
  sd->m_data        = data;
  sd->m_capAndCount = HeaderKind::String << 24 | capCode; // count=0
  sd->m_lenAndHash  = 0; // len=hash=0

  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Ejemplo n.º 4
0
StringData* StringData::Make(size_t reserveLen) {
  auto const allocRet = allocFlatForLen(reserveLen);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  data[0] = 0;
  sd->m_data        = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash  = 0; // len=hash=0

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Ejemplo n.º 5
0
// State transition from Mode::Shared to Mode::Flat.
StringData* StringData::escalate(size_t cap) {
  assert(isShared() && !isStatic() && cap >= m_len);

  auto const allocRet = allocFlatForLen(cap);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  sd->m_data          = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash    = m_lenAndHash;
  *memcpy8(data, m_data, m_len) = 0;

  assert(sd->hasExactlyOneRef());
  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Ejemplo n.º 6
0
StringData* StringData::Make(StringSlice r1, StringSlice r2) {
  auto const len      = r1.len + r2.len;
  auto const allocRet = allocFlatForLen(len);
  auto const sd       = allocRet.first;
  auto const capCode  = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  sd->m_data        = data;
  sd->m_capAndCount = HeaderKind::String << 24 | capCode; // count=0
  sd->m_lenAndHash  = len; // hash=0

  memcpy(data, r1.ptr, r1.len);
  memcpy(data + r1.len, r2.ptr, r2.len);
  data[len] = 0;

  assert(sd->isFlat());
  assert(sd->checkSane());
  return sd;
}
Ejemplo n.º 7
0
StringData* StringData::Make(StringSlice r1, StringSlice r2) {
  auto const len      = r1.len + r2.len;
  auto const allocRet = allocFlatForLen(len);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  sd->m_data        = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash  = len; // hash=0

  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;
}
Ejemplo n.º 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 allocRet = allocFlatForLen(len + 6);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  sd->m_data          = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash    = len; // hash=0

  auto 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;
}
Ejemplo n.º 9
0
StringData* StringData::Make(StringSlice sl, CopyStringMode) {
  auto const allocRet = allocFlatForLen(sl.len);
  auto const sd       = allocRet.first;
  auto const cc       = allocRet.second;
  auto const data     = reinterpret_cast<char*>(sd + 1);

  sd->m_data         = data;
  sd->m_hdr.init(cc, HeaderKind::String, 1);
  sd->m_lenAndHash   = sl.len; // hash=0

  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;
}