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/basictypes.h"
19 : #include "base/logging.h"
20 : #include "base/memory/ref_counted.h"
21 : #include "syzygy/common/buffer_writer.h"
22 : #include "syzygy/msf/msf_decl.h"
23 :
24 : namespace msf {
25 : namespace detail {
26 :
27 : // Forward declaration.
28 : template <MsfFileType T>
29 : class WritableMsfStreamImpl;
30 :
31 : // This class represents an MSF stream. It has a stream-like interface that
32 : // allows invoking successive reads through the stream and seeking.
33 : template <MsfFileType T>
34 : class MsfStreamImpl : public base::RefCounted<MsfStreamImpl<T>> {
35 : public:
36 : explicit MsfStreamImpl(size_t length);
37 :
38 : // Reads @p count chunks of size sizeof(ItemType) into the destination buffer.
39 : // The caller is responsible for ensuring that the destination buffer has
40 : // enough space to receive the data. Returns the number of items successfully
41 : // read via @p items_read.
42 : //
43 : // @tparam ItemType the type of item to coerce the data to.
44 : // @param dest the destination array.
45 : // @param count the number of elements to read.
46 : // @param items_read pointer to receive the number of items successfully read.
47 : // @returns true if all @p count items are read, false otherwise.
48 : template <typename ItemType>
49 : bool Read(ItemType* dest, size_t count, size_t* items_read);
50 :
51 : // Reads @p count chunks of size sizeof(ItemType) into the destination buffer.
52 : // The caller is responsible for ensuring that the destination buffer has
53 : // enough space to receive the data.
54 : //
55 : // @tparam ItemType the type of item to coerce the data to.
56 : // @param dest the destination array.
57 : // @param count the number of elements to read.
58 : // @returns true on success.
59 : template <typename ItemType>
60 : bool Read(ItemType* dest, size_t count);
61 :
62 : // Reads @p count elements of size sizeof(ItemType) into the provided
63 : // vector of elements. Resizes @p dest to the number of elements that were
64 : // successfully read.
65 : //
66 : // @tparam ItemType the type of item to coerce the data to.
67 : // @param dest the destination vector.
68 : // @param count the number of elements to read.
69 : // @returns true if @p dest was populated with @p count elements, false
70 : // otherwise. The number of elements actually read is indicated by the
71 : // length of @p dest.
72 : template <typename ItemType>
73 : bool Read(std::vector<ItemType>* dest, size_t count);
74 :
75 : // Fills the provided vector with elements read from this stream. The bytes
76 : // remaining in the stream must be an even multiple of sizeof(ItemType).
77 : // Resizes @p dest to the number of elements read.
78 : //
79 : // @tparam ItemType the type of item to coerce the data to.
80 : // @param dest the destination vector.
81 : // @returns true if the remaining bytes in the stream were read into the
82 : // provided vector, false otherwise. The number of elements actually read
83 : // is indicated by the length of @p dest.
84 : template <typename ItemType>
85 : bool Read(std::vector<ItemType>* dest);
86 :
87 : // Reads @p count bytes of data into the destination buffer. The caller is
88 : // responsible for ensuring that the destination buffer has enough space to
89 : // receive the data. @p bytes_read will hold the number of bytes read. If
90 : // there was insufficient data but some bytes were read, returns false and
91 : // returns the number of bytes read via @p bytes_read.
92 : //
93 : // @param dest the buffer to receive the data.
94 : // @param count the number of bytes to read.
95 : // @param bytes_read pointer that will receive the number of bytes read.
96 : // @returns true if all @p count bytes are read, false otherwise.
97 : virtual bool ReadBytes(void* dest, size_t count, size_t* bytes_read) = 0;
98 :
99 : // Returns a pointer to a WritableMsfStreamImpl if the underlying object
100 : // supports this interface. If this returns non-NULL, it is up to the user to
101 : // ensure thread safety; each writer should be used exclusively of any other
102 : // writer, and no reader should be used while a writer is in use. Each of the
103 : // reader and writer maintains its own cursor, but their view of the data (and
104 : // its length) will remain in sync.
105 : //
106 : // NOTE: This function should act as a factory, with each call returning a
107 : // heap allocated reference counted writer. However, since each
108 : // WritableMsfStreamImpl is currently implemented using a BufferWriter,
109 : // and the BufferWriter maintains its own state internally rather than a
110 : // shared state, its possible that one writer causing a resize could
111 : // invalidate the internal data pointer held by another writer. As a
112 : // workaround, there is only a single writer allowed to be allocated
113 : // right now.
114 : //
115 : // TODO(chrisha): Clean this up to return an interface, which can be wrapped
116 : // in some common stream-writer functionality, reusing BufferWriter.
117 : //
118 : // @returns a pointer to a WritableMsfStreamImpl.
119 E : virtual scoped_refptr<WritableMsfStreamImpl<T>> GetWritableStream() {
120 E : return scoped_refptr<WritableMsfStreamImpl<T>>();
121 E : }
122 :
123 : // Sets the current read position.
124 : bool Seek(size_t pos);
125 :
126 : // Gets the stream's length.
127 : // @returns the total number of bytes in the stream.
128 E : size_t length() const { return length_; }
129 :
130 : // Gets the stream's read position.
131 : // @returns the number of bytes already read.
132 E : size_t pos() const { return pos_; }
133 :
134 : // Gets the number of bytes left to read in the stream.
135 : // @returns the number of bytes left.
136 E : size_t bytes_left() const { return length_ - pos_; }
137 :
138 : protected:
139 : friend base::RefCounted<MsfStreamImpl>;
140 :
141 : // Protected to enforce use of ref-counted pointers at compile time.
142 : virtual ~MsfStreamImpl();
143 :
144 : // Sets the stream's length.
145 E : void set_length(size_t length) { length_ = length; }
146 :
147 : private:
148 : // The length of the stream.
149 : size_t length_;
150 :
151 : // The read position within the stream.
152 : size_t pos_;
153 :
154 : DISALLOW_COPY_AND_ASSIGN(MsfStreamImpl);
155 : };
156 :
157 : // Represents a writable MSF stream.
158 : // TODO(chrisha): For now, this inherits from common::BufferWriter, but a far
159 : // cleaner approach would be to hoist a basic WritableStreamInterface, and
160 : // make BufferWriter accept a pointer to said interface. The same thing
161 : // could be done to the common::BufferParser/BufferReader and MsfStreamImpl
162 : // hierarchy.
163 : template <MsfFileType T>
164 : class WritableMsfStreamImpl : public base::RefCounted<WritableMsfStreamImpl<T>>,
165 : public common::BufferWriter {
166 : public:
167 : // Constructor.
168 E : WritableMsfStreamImpl() : common::BufferWriter(NULL, 0) {}
169 :
170 : protected:
171 : friend base::RefCounted<WritableMsfStreamImpl>;
172 :
173 : // Destructor. Protected to enforce use of ref-counted pointers at compile
174 : // time.
175 E : virtual ~WritableMsfStreamImpl() {}
176 :
177 : // Forwarded from common::BufferWriter.
178 : virtual uint8* GrowBuffer(size_t size) = 0;
179 : };
180 :
181 : } // namespace detail
182 :
183 : using WritableMsfStream = detail::WritableMsfStreamImpl<kGenericMsfFileType>;
184 : using MsfStream = detail::MsfStreamImpl<kGenericMsfFileType>;
185 :
186 : } // namespace msf
187 :
188 : #include "syzygy/msf/msf_stream_impl.h"
189 :
190 : #endif // SYZYGY_MSF_MSF_STREAM_H_
|