CstrBuffer::CstrBuffer(const char *filename) : m_buffer(nullptr), m_len(0) { struct stat sb; if (stat(filename, &sb) == 0) { if (sb.st_size > kMaxCap - 1) { auto const str = folly::to<std::string>( "file ", filename, " is too large" ); throw StringBufferLimitException(kMaxCap, String(str.c_str())); } m_cap = sb.st_size; m_buffer = (char *)safe_malloc(m_cap + 1); int fd = ::open(filename, O_RDONLY); if (fd != -1) { while (m_len < m_cap) { int buffer_size = m_cap - m_len; int len = ::read(fd, m_buffer + m_len, buffer_size); if (len == -1 && errno == EINTR) continue; if (len <= 0) break; m_len += len; } ::close(fd); } } }
void StringBuffer::growBy(int spaceRequired) { /* * The default initial size is a power-of-two minus 1. * This doubling scheme keeps the total block size a * power of two, which should be good for memory allocators. * But note there is no guarantee either that the initial size * is power-of-two minus 1, or that it stays that way * (new_size < minSize below). */ auto new_size = m_cap * 2 + 1; auto const minSize = static_cast<unsigned>(m_cap) + spaceRequired; if (new_size < minSize) { new_size = minSize; } if (new_size > m_maxBytes) { if (minSize > m_maxBytes) { throw StringBufferLimitException(m_maxBytes, detach()); } else { new_size = m_maxBytes; } } m_buffer[m_len] = 0; m_str->setSize(m_len); auto const tmp = m_str->reserve(new_size); if (UNLIKELY(tmp != m_str)) { assert(m_str->hasExactlyOneRef()); m_str->release(); m_str = tmp; } auto const s = m_str->bufferSlice(); m_buffer = s.ptr; m_cap = s.len; }
void StringBuffer::growBy(int spaceRequired) { /* * The default initial size is a power-of-two minus 1. * This doubling scheme keeps the total block size a * power of two, which should be good for memory allocators. * But note there is no guarantee either that the initial size * is power-of-two minus 1, or that it stays that way * (new_size < minSize below). */ long new_size = m_cap * 2L + 1; long minSize = m_cap + (long)spaceRequired; if (new_size < minSize) { new_size = minSize; } if (m_maxBytes > 0 && new_size > m_maxBytes) { if (minSize > m_maxBytes) { throw StringBufferLimitException(m_maxBytes, detach()); } else { new_size = m_maxBytes; } } m_buffer[m_len] = 0; m_str->setSize(m_len); MutableSlice s = m_str->reserve(new_size); m_buffer = s.ptr; m_cap = s.len; }
CstrBuffer::CstrBuffer(const char *filename) : m_buffer(NULL), m_len(0) { struct stat sb; if (stat(filename, &sb) == 0) { if (sb.st_size > kMaxCap - 1) { std::ostringstream out; out << "file " << filename << " is too large"; throw StringBufferLimitException(kMaxCap, String(out.str().c_str())); } m_cap = sb.st_size; m_buffer = (char *)Util::safe_malloc(m_cap + 1); int fd = ::open(filename, O_RDONLY); if (fd != -1) { while (m_len < m_cap) { int buffer_size = m_cap - m_len; int len = ::read(fd, m_buffer + m_len, buffer_size); if (len == -1 && errno == EINTR) continue; if (len <= 0) break; m_len += len; } ::close(fd); } } TAINT_OBSERVER_REGISTER_MUTATED(m_taint_data, dataIgnoreTaint()); }
void CstrBuffer::append(const char* data, int len) { ASSERT(m_buffer && len >= 0); unsigned newlen = m_len + len; if (newlen + 1 > m_cap) { if (newlen + 1 > kMaxCap) { throw StringBufferLimitException(kMaxCap, detach()); } unsigned newcap = Util::nextPower2(newlen + 1); m_buffer = (char*)Util::safe_realloc(m_buffer, newcap); m_cap = newcap - 1; ASSERT(newlen + 1 <= m_cap); } memcpy(m_buffer + m_len, data, len); m_buffer[m_len = newlen] = 0; }
void StringBuffer::grow(int minSize) { int new_size = m_size; new_size <<= 1; if (new_size < minSize) { new_size = minSize; } if (m_maxBytes > 0 && new_size > m_maxBytes) { throw StringBufferLimitException(m_maxBytes, detach()); } char *new_buffer; new_buffer = (char *)Util::safe_realloc(m_buffer, new_size + 1); m_size = new_size; m_buffer = new_buffer; }
void CstrBuffer::append(StringSlice slice) { auto const data = slice.ptr; auto const len = slice.len; assert(m_buffer && len >= 0); unsigned newlen = m_len + len; if (newlen + 1 > m_cap) { if (newlen + 1 > kMaxCap) { throw StringBufferLimitException(kMaxCap, detach()); } unsigned newcap = Util::nextPower2(newlen + 1); m_buffer = (char*)Util::safe_realloc(m_buffer, newcap); m_cap = newcap - 1; assert(newlen + 1 <= m_cap); } memcpy(m_buffer + m_len, data, len); m_buffer[m_len = newlen] = 0; }
void CstrBuffer::append(StringSlice slice) { auto const data = slice.ptr; auto const len = slice.len; static_assert(std::is_unsigned<decltype(len)>::value, "len is supposed to be unsigned"); assert(m_buffer); unsigned newlen = m_len + len; if (newlen + 1 > m_cap) { if (newlen + 1 > kMaxCap) { throw StringBufferLimitException(kMaxCap, detach()); } unsigned newcap = folly::nextPowTwo(newlen + 1); m_buffer = (char*)safe_realloc(m_buffer, newcap); m_cap = newcap - 1; assert(newlen + 1 <= m_cap); } memcpy(m_buffer + m_len, data, len); m_buffer[m_len = newlen] = 0; }