PageRenderTime 114ms CodeModel.GetById 50ms app.highlight 19ms RepoModel.GetById 41ms app.codeStats 0ms

/mordor/streams/stream.cpp

http://github.com/mozy/mordor
C++ | 168 lines | 142 code | 21 blank | 5 comment | 20 complexity | 0615eda27a1985271f8f151c29132bf0 MD5 | raw file
  1// Copyright (c) 2009 - Mozy, Inc.
  2
  3#include "stream.h"
  4
  5#include <boost/scoped_array.hpp>
  6
  7#include <string.h>
  8
  9#include "buffer.h"
 10#include "mordor/assert.h"
 11
 12namespace Mordor {
 13
 14size_t
 15Stream::read(void *buffer, size_t length)
 16{
 17    MORDOR_ASSERT(supportsRead());
 18    Buffer internalBuffer;
 19    internalBuffer.adopt(buffer, length);
 20    size_t result = read(internalBuffer, length);
 21    MORDOR_ASSERT(result <= length);
 22    MORDOR_ASSERT(internalBuffer.readAvailable() == result);
 23    if (result == 0u)
 24        return 0;
 25    std::vector<iovec> iovs = internalBuffer.readBuffers(result);
 26    MORDOR_ASSERT(!iovs.empty());
 27    // It wrote directly into our buffer
 28    if (iovs.front().iov_base == buffer && iovs.front().iov_len == result)
 29        return result;
 30    bool overlapping = false;
 31    for (std::vector<iovec>::iterator it = iovs.begin();
 32        it != iovs.end();
 33        ++it) {
 34        if (it->iov_base >= buffer || it->iov_base <=
 35            (unsigned char *)buffer + length) {
 36            overlapping = true;
 37            break;
 38        }
 39    }
 40    // It didn't touch our buffer at all; it's safe to just copyOut
 41    if (!overlapping) {
 42        internalBuffer.copyOut(buffer, result);
 43        return result;
 44    }
 45    // We have to allocate *another* buffer so we don't destroy any data while
 46    // copying to our buffer
 47    boost::scoped_array<unsigned char> extraBuffer(new unsigned char[result]);
 48    internalBuffer.copyOut(extraBuffer.get(), result);
 49    memcpy(buffer, extraBuffer.get(), result);
 50    return result;
 51}
 52
 53size_t
 54Stream::read(Buffer &buffer, size_t length)
 55{
 56    return read(buffer, length, false);
 57}
 58
 59size_t
 60Stream::read(Buffer &buffer, size_t length, bool coalesce)
 61{
 62    MORDOR_ASSERT(supportsRead());
 63    iovec iov = buffer.writeBuffer(length, coalesce);
 64    size_t result = read(iov.iov_base, iov.iov_len);
 65    buffer.produce(result);
 66    return result;
 67}
 68
 69size_t
 70Stream::write(const char *string)
 71{
 72    return write(string, strlen(string));
 73}
 74
 75size_t
 76Stream::write(const void *buffer, size_t length)
 77{
 78    MORDOR_ASSERT(supportsWrite());
 79    Buffer internalBuffer;
 80    internalBuffer.copyIn(buffer, length);
 81    return write(internalBuffer, length);
 82}
 83
 84size_t
 85Stream::write(const Buffer &buffer, size_t length)
 86{
 87    return write(buffer, length, false);
 88}
 89
 90size_t
 91Stream::write(const Buffer &buffer, size_t length, bool coalesce)
 92{
 93    MORDOR_ASSERT(supportsWrite());
 94    const iovec iov = buffer.readBuffer(length, coalesce);
 95    return write(iov.iov_base, iov.iov_len);
 96}
 97
 98long long
 99Stream::seek(long long offset, Anchor anchor)
100{
101    MORDOR_NOTREACHED();
102}
103
104long long
105Stream::size()
106{
107    MORDOR_NOTREACHED();
108}
109
110void
111Stream::truncate(long long size)
112{
113    MORDOR_NOTREACHED();
114}
115
116ptrdiff_t
117Stream::find(char delimiter, size_t sanitySize, bool throwIfNotFound)
118{
119    MORDOR_NOTREACHED();
120}
121
122ptrdiff_t
123Stream::find(const std::string &delimiter, size_t sanitySize,
124    bool throwIfNotFound)
125{
126    MORDOR_NOTREACHED();
127}
128
129std::string
130Stream::getDelimited(char delim, bool eofIsDelimiter, bool includeDelimiter)
131{
132    ptrdiff_t offset = find(delim, ~0, !eofIsDelimiter);
133    eofIsDelimiter = offset < 0;
134    if (offset < 0)
135        offset = -offset - 1;
136    std::string result;
137    result.resize(offset + (eofIsDelimiter ? 0 : 1));
138    MORDOR_VERIFY(read((char *)result.c_str(), result.size())
139        == result.size());
140    if (!eofIsDelimiter && !includeDelimiter)
141        result.resize(result.size() - 1);
142    return result;
143}
144
145std::string
146Stream::getDelimited(const std::string &delim, bool eofIsDelimiter,
147    bool includeDelimiter)
148{
149    ptrdiff_t offset = find(delim, ~0, !eofIsDelimiter);
150    eofIsDelimiter = offset < 0;
151    if (offset < 0)
152        offset = -offset - 1;
153    std::string result;
154    result.resize(offset + (eofIsDelimiter ? 0 : delim.size()));
155    MORDOR_VERIFY(read((char *)result.c_str(), result.size())
156        == result.size());
157    if (!eofIsDelimiter && !includeDelimiter)
158        result.resize(result.size() - delim.size());
159    return result;
160}
161
162void
163Stream::unread(const Buffer &buffer, size_t length)
164{
165    MORDOR_NOTREACHED();
166}
167
168}