Beispiel #1
0
int Buffer::pushBytes(const uint8_t* bytes, int cnt)
{
    if (writeAvailable() < cnt)
        cnt = writeAvailable();

    memcpy(_tail, bytes, cnt);
    _tail += cnt;
    return cnt;
}
Beispiel #2
0
std::vector<iovec>
Buffer::writeBuffers(size_t length)
{
    if (length == (size_t)~0)
        length = writeAvailable();
    reserve(length);
    std::vector<iovec> result;
    result.reserve(m_segments.size());
    size_t remaining = length;
    std::list<Segment>::iterator it = m_writeIt;
    while (remaining > 0) {
        Segment& segment = *it;
        size_t toProduce = (std::min)(segment.writeAvailable(), remaining);
        SegmentData data = segment.writeBuffer().slice(0, toProduce);
#ifdef WINDOWS
        while (data.length() > 0) {
            iovec wsabuf;
            wsabuf.iov_base = (void *)data.start();
            wsabuf.iov_len = iovLength(data.length());
            result.push_back(wsabuf);
            data = data.slice(wsabuf.iov_len);
        }
#else
        iovec iov;
        iov.iov_base = (void *)data.start();
        iov.iov_len = data.length();
        result.push_back(iov);
#endif
        remaining -= toProduce;
        ++it;
    }
    MORDOR_ASSERT(remaining == 0);
    invariant();
    return result;
}
Beispiel #3
0
void
Buffer::Segment::produce(size_t length)
{
    MORDOR_ASSERT(length <= writeAvailable());
    m_writeIndex += length;
    invariant();
}
Beispiel #4
0
int Buffer::pushBytesFromStream(std::basic_istream<char>& istr, int cnt)
{
    if (writeAvailable() < cnt)
        cnt = writeAvailable();

    istr.read((char*)_tail, cnt);
    if (istr.eof())
    {
        cnt = istr.gcount();
    }
    else if (istr.fail())
    {
        return -1;
    }
    _tail += cnt;
    return cnt;
}
Beispiel #5
0
iovec
Buffer::writeBuffer(size_t length, bool coalesce)
{
    iovec result;
    result.iov_base = NULL;
    result.iov_len = 0;
    if (length == 0u)
        return result;
    // Must allocate just the write segment
    if (writeAvailable() == 0) {
        reserve(length);
        MORDOR_ASSERT(m_writeIt != m_segments.end());
        MORDOR_ASSERT(m_writeIt->writeAvailable() >= length);
        SegmentData data = m_writeIt->writeBuffer().slice(0, length);
        result.iov_base = data.start();
        result.iov_len = iovLength(data.length());
        return result;
    }
    // Can use an existing write segment
    if (writeAvailable() > 0 && m_writeIt->writeAvailable() >= length) {
        SegmentData data = m_writeIt->writeBuffer().slice(0, length);
        result.iov_base = data.start();
        result.iov_len = iovLength(data.length());
        return result;
    }
    // If they don't want us to coalesce, just return as much as we can from
    // the first segment
    if (!coalesce) {
        SegmentData data = m_writeIt->writeBuffer();
        result.iov_base = data.start();
        result.iov_len = iovLength(data.length());
        return result;
    }
    // Existing bufs are insufficient... remove them and reserve anew
    compact();
    reserve(length);
    MORDOR_ASSERT(m_writeIt != m_segments.end());
    MORDOR_ASSERT(m_writeIt->writeAvailable() >= length);
    SegmentData data = m_writeIt->writeBuffer().slice(0, length);
    result.iov_base = data.start();
    result.iov_len = iovLength(data.length());
    return result;
}
Beispiel #6
0
void
Buffer::reserve(size_t length)
{
    if (writeAvailable() < length) {
        // over-reserve to avoid fragmentation
        Segment newSegment(length * 2 - writeAvailable());
        if (readAvailable() == 0) {
            // put the new buffer at the front if possible to avoid
            // fragmentation
            m_segments.push_front(newSegment);
            m_writeIt = m_segments.begin();
        } else {
            m_segments.push_back(newSegment);
            if (m_writeAvailable == 0) {
                m_writeIt = m_segments.end();
                --m_writeIt;
            }
        }
        m_writeAvailable += newSegment.length();
        invariant();
    }
}
Beispiel #7
0
void
Buffer::compact()
{
    invariant();
    if (m_writeIt != m_segments.end()) {
        if (m_writeIt->readAvailable() > 0) {
            Segment newSegment = Segment(m_writeIt->readBuffer());
            m_segments.insert(m_writeIt, newSegment);
        }
        m_writeIt = m_segments.erase(m_writeIt, m_segments.end());
        m_writeAvailable = 0;
    }
    MORDOR_ASSERT(writeAvailable() == 0);
}
Beispiel #8
0
void
Buffer::produce(size_t length)
{
    MORDOR_ASSERT(length <= writeAvailable());
    m_readAvailable += length;
    m_writeAvailable -= length;
    while (length > 0) {
        Segment &segment = *m_writeIt;
        size_t toProduce = (std::min)(segment.writeAvailable(), length);
        segment.produce(toProduce);
        length -= toProduce;
        if (segment.writeAvailable() == 0)
            ++m_writeIt;
    }
    MORDOR_ASSERT(length == 0);
    invariant();
}