PageRenderTime 31ms CodeModel.GetById 12ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/mordor/streams/duplex.h

http://github.com/mozy/mordor
C Header | 94 lines | 79 code | 10 blank | 5 comment | 15 complexity | f1450de792242278192a9e52f5e1bf2a MD5 | raw file
 1#ifndef __MORDOR_DUPLEX_STREAM_H__
 2#define __MORDOR_DUPLEX_STREAM_H__
 3// Copyright (c) 2009 - Mozy, Inc.
 4
 5#include "stream.h"
 6
 7namespace Mordor {
 8
 9// A DuplexStream combines a read and a write stream to form a stream that can
10// be read and written to.  It *disables* seek(), size(), and truncate(),
11// because the parent streams are disparate, and those concepts are supposed
12// to be shared
13class DuplexStream : public Stream
14{
15public:
16    DuplexStream(Stream::ptr readParent, Stream::ptr writeParent,
17        bool own = true)
18        : m_readParent(readParent),
19          m_writeParent(writeParent),
20          m_own(own)
21    {
22        MORDOR_ASSERT(readParent);
23        MORDOR_ASSERT(writeParent);
24        MORDOR_ASSERT(readParent->supportsRead());
25        MORDOR_ASSERT(writeParent->supportsWrite());
26    }
27
28    Stream::ptr readParent() { return m_readParent; }
29    Stream::ptr writeParent() { return m_writeParent; }
30    bool ownsParents() { return m_own; }
31
32    bool supportsHalfClose() { return true; }
33    bool supportsRead() { return true; }
34    bool supportsWrite() { return true; }
35    bool supportsFind() { return m_readParent && m_readParent->supportsFind(); }
36    bool supportsUnread() { return m_readParent && m_readParent->supportsUnread(); }
37
38    void close(CloseType type = BOTH)
39    {
40        if (m_own) {
41            if ((type & READ) && m_readParent)
42                m_readParent->close(m_readParent->supportsHalfClose() ? READ : BOTH);
43            if ((type & WRITE) && m_writeParent)
44                m_writeParent->close(m_writeParent->supportsHalfClose() ? WRITE : BOTH);
45        }
46        if (type & READ)
47            m_readParent.reset();
48        if (type & WRITE)
49            m_writeParent.reset();
50    }
51    using Stream::read;
52    size_t read(Buffer &b, size_t len)
53    {
54        if (!m_readParent) MORDOR_THROW_EXCEPTION(BrokenPipeException());
55        return m_readParent->read(b, len);
56    }
57    using Stream::write;
58    size_t write(const Buffer &b, size_t len)
59    {
60        if (!m_writeParent) MORDOR_THROW_EXCEPTION(BrokenPipeException());
61        return m_writeParent->write(b, len);
62    }
63    void flush(bool flushParent = true)
64    {
65        if (!m_writeParent) MORDOR_THROW_EXCEPTION(BrokenPipeException());
66        m_writeParent->flush();
67    }
68    using Stream::find;
69    ptrdiff_t find(char delim)
70    {
71        if (!m_readParent) MORDOR_THROW_EXCEPTION(BrokenPipeException());
72        return m_readParent->find(delim);
73    }
74    ptrdiff_t find(const std::string &str, size_t sanitySize = ~0, bool throwOnNotFound = true)
75    {
76        if (!m_readParent) MORDOR_THROW_EXCEPTION(BrokenPipeException());
77        return m_readParent->find(str, sanitySize, throwOnNotFound);
78    }
79    void unread(const Buffer &b, size_t len) {
80        if (!m_readParent) MORDOR_THROW_EXCEPTION(BrokenPipeException());
81        return m_readParent->unread(b, len);
82    }
83
84protected:
85    void ownsParents(bool own) { m_own = own; }
86
87private:
88    Stream::ptr m_readParent, m_writeParent;
89    bool m_own;
90};
91
92}
93
94#endif