1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #ifndef SYZYGY_MSF_MSF_STREAM_H_
16 : #define SYZYGY_MSF_MSF_STREAM_H_
17 :
18 : #include "base/logging.h"
19 : #include "base/memory/ref_counted.h"
20 : #include "syzygy/common/buffer_writer.h"
21 : #include "syzygy/msf/msf_decl.h"
22 :
23 : namespace msf {
24 : namespace detail {
25 :
26 : // Forward declaration.
27 : template <MsfFileType T>
28 : class WritableMsfStreamImpl;
29 :
30 : // This class represents an MSF stream. It has a stream-like interface that
31 : // allows invoking successive reads through the stream and seeking.
32 : template <MsfFileType T>
33 : class MsfStreamImpl : public base::RefCounted<MsfStreamImpl<T>> {
34 : public:
35 : explicit MsfStreamImpl(size_t length);
36 :
37 : // Reads @p count bytes of data starting at @p pos into the destination
38 : // buffer. The caller is responsible for ensuring that the destination
39 : // buffer has enough space to receive the data.
40 : //
41 : // @param pos the position in the stream of the first byte to read.
42 : // @param dest the buffer to receive the data. May be modified on failure.
43 : // @param count the number of bytes to read.
44 : // @returns true if all @p count bytes are read, false otherwise.
45 : virtual bool ReadBytesAt(size_t pos, size_t count, void* dest) = 0;
46 :
47 : // Returns a pointer to a WritableMsfStreamImpl if the underlying object
48 : // supports this interface. If this returns non-NULL, it is up to the user to
49 : // ensure thread safety; each writer should be used exclusively of any other
50 : // writer, and no reader should be used while a writer is in use. Each of the
51 : // reader and writer maintains its own cursor, but their view of the data (and
52 : // its length) will remain in sync.
53 : //
54 : // NOTE: This function should act as a factory, with each call returning a
55 : // heap allocated reference counted writer. However, since each
56 : // WritableMsfStreamImpl is currently implemented using a BufferWriter,
57 : // and the BufferWriter maintains its own state internally rather than a
58 : // shared state, its possible that one writer causing a resize could
59 : // invalidate the internal data pointer held by another writer. As a
60 : // workaround, there is only a single writer allowed to be allocated
61 : // right now.
62 : //
63 : // TODO(chrisha): Clean this up to return an interface, which can be wrapped
64 : // in some common stream-writer functionality, reusing BufferWriter.
65 : //
66 : // @returns a pointer to a WritableMsfStreamImpl.
67 E : virtual scoped_refptr<WritableMsfStreamImpl<T>> GetWritableStream() {
68 E : return scoped_refptr<WritableMsfStreamImpl<T>>();
69 E : }
70 :
71 : // Gets the stream's length.
72 : // @returns the total number of bytes in the stream.
73 E : size_t length() const { return length_; }
74 :
75 : protected:
76 : friend base::RefCounted<MsfStreamImpl>;
77 :
78 : // Protected to enforce use of ref-counted pointers at compile time.
79 : virtual ~MsfStreamImpl();
80 :
81 : // Sets the stream's length.
82 E : void set_length(size_t length) { length_ = length; }
83 :
84 : private:
85 : // The length of the stream.
86 : size_t length_;
87 :
88 : DISALLOW_COPY_AND_ASSIGN(MsfStreamImpl);
89 : };
90 :
91 : // Represents a writable MSF stream.
92 : // TODO(chrisha): For now, this inherits from common::BufferWriter, but a far
93 : // cleaner approach would be to hoist a basic WritableStreamInterface, and
94 : // make BufferWriter accept a pointer to said interface. The same thing
95 : // could be done to the common::BufferParser/BufferReader and MsfStreamImpl
96 : // hierarchy.
97 : template <MsfFileType T>
98 : class WritableMsfStreamImpl : public base::RefCounted<WritableMsfStreamImpl<T>>,
99 : public common::BufferWriter {
100 : public:
101 : // Constructor.
102 E : WritableMsfStreamImpl() : common::BufferWriter(NULL, 0) {}
103 :
104 : protected:
105 : friend base::RefCounted<WritableMsfStreamImpl>;
106 :
107 : // Destructor. Protected to enforce use of ref-counted pointers at compile
108 : // time.
109 E : virtual ~WritableMsfStreamImpl() {}
110 :
111 : // Forwarded from common::BufferWriter.
112 : virtual uint8_t* GrowBuffer(size_t size) = 0;
113 : };
114 :
115 : } // namespace detail
116 :
117 : using WritableMsfStream = detail::WritableMsfStreamImpl<kGenericMsfFileType>;
118 : using MsfStream = detail::MsfStreamImpl<kGenericMsfFileType>;
119 :
120 : } // namespace msf
121 :
122 : #include "syzygy/msf/msf_stream_impl.h"
123 :
124 : #endif // SYZYGY_MSF_MSF_STREAM_H_
|