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 : // Internal implementation details for msf_byte_stream.h. Not meant to be
16 : // included directly.
17 :
18 : #ifndef SYZYGY_MSF_MSF_BYTE_STREAM_IMPL_H_
19 : #define SYZYGY_MSF_MSF_BYTE_STREAM_IMPL_H_
20 :
21 : #include <algorithm>
22 : #include <cstring>
23 :
24 : #include "base/logging.h"
25 : #include "base/memory/ref_counted.h"
26 :
27 : namespace msf {
28 : namespace detail {
29 :
30 : // The writable half of an in-memory MSF stream. This is not in an anonymous
31 : // namespace as it is forward declared in the header and is a friend of
32 : // MsfByteStreamImpl, allowing access to the underlying storage vector. Once we
33 : // hoist storage to another interface, this implementation can be entirely
34 : // hidden.
35 : template <MsfFileType T>
36 : class WritableMsfByteStreamImpl : public WritableMsfStreamImpl<T> {
37 : public:
38 : // Constructor.
39 : // @param msf_byte_stream a pointer to the MSF byte stream whose data we
40 : // wrap.
41 : explicit WritableMsfByteStreamImpl(MsfByteStreamImpl<T>* msf_byte_stream);
42 :
43 : protected:
44 : // This is protected to enforce use of reference counted pointers.
45 : virtual ~WritableMsfByteStreamImpl();
46 :
47 : // common::BufferWriter implementation.
48 : uint8* GrowBuffer(size_t size) override;
49 :
50 : // A reference counted pointer to the MsfByteStreamImpl we are wrapping.
51 : scoped_refptr<MsfByteStreamImpl<T>> msf_byte_stream_;
52 : };
53 :
54 : template <MsfFileType T>
55 : MsfByteStreamImpl<T>::MsfByteStreamImpl()
56 E : : MsfStreamImpl(0), writable_msf_stream_(NULL) {
57 E : }
58 :
59 : template <MsfFileType T>
60 E : MsfByteStreamImpl<T>::~MsfByteStreamImpl() {
61 E : }
62 :
63 : template <MsfFileType T>
64 E : bool MsfByteStreamImpl<T>::Init(const uint8* data, size_t length) {
65 E : set_length(length);
66 E : data_.resize(length);
67 E : memcpy(this->data(), data, length);
68 E : return true;
69 E : }
70 :
71 : template <MsfFileType T>
72 E : bool MsfByteStreamImpl<T>::Init(MsfStreamImpl* stream) {
73 E : DCHECK(stream != NULL);
74 :
75 : // Seek the beginning of the stream.
76 E : if (!stream->Seek(0)) {
77 i : LOG(ERROR) << "Failed to seek in MSF stream.";
78 i : return false;
79 : }
80 :
81 : // Read the MSF stream.
82 E : Init(stream, stream->length());
83 :
84 E : return true;
85 E : }
86 :
87 : template <MsfFileType T>
88 E : bool MsfByteStreamImpl<T>::Init(MsfStreamImpl* stream, size_t length) {
89 E : DCHECK(stream != NULL);
90 :
91 : // Init data members.
92 E : set_length(length);
93 E : data_.resize(length);
94 :
95 E : if (data_.empty())
96 E : return true;
97 :
98 : // Read the MSF stream.
99 E : if (!stream->Read(data(), length)) {
100 E : LOG(ERROR) << "Failed to read MSF stream.";
101 E : return false;
102 : }
103 :
104 E : return true;
105 E : }
106 :
107 : template <MsfFileType T>
108 : bool MsfByteStreamImpl<T>::ReadBytes(void* dest,
109 : size_t count,
110 E : size_t* bytes_read) {
111 E : DCHECK(dest != NULL);
112 E : DCHECK(bytes_read != NULL);
113 :
114 : // Return 0 once we've reached the end of the stream.
115 E : if (pos() == length()) {
116 E : *bytes_read = 0;
117 E : return true;
118 : }
119 :
120 : // Don't read beyond the end of the known stream length.
121 E : count = std::min(count, length() - pos());
122 :
123 : // Read the stream.
124 E : memcpy(dest, data() + pos(), count);
125 E : Seek(pos() + count);
126 E : *bytes_read = count;
127 :
128 E : return true;
129 E : }
130 :
131 : template <MsfFileType T>
132 : scoped_refptr<WritableMsfStreamImpl<T>>
133 E : MsfByteStreamImpl<T>::GetWritableStream() {
134 : // This is very not thread-safe! If we want this to be thread-safe, we'll
135 : // need to be using thread-safe reference counting, and a little smarts here
136 : // to ensure we're not mid-destructor on some other thread.
137 E : if (writable_msf_stream_ == NULL)
138 E : writable_msf_stream_ = new WritableMsfByteStreamImpl<T>(this);
139 E : return scoped_refptr<WritableMsfStreamImpl<T>>(writable_msf_stream_);
140 E : }
141 :
142 : template <MsfFileType T>
143 : WritableMsfByteStreamImpl<T>::WritableMsfByteStreamImpl(
144 E : MsfByteStreamImpl<T>* msf_byte_stream) {
145 E : DCHECK(msf_byte_stream != NULL);
146 E : msf_byte_stream_ = msf_byte_stream;
147 :
148 : // If the stream contains data, initialize the BufferWriter.
149 E : if (msf_byte_stream_->length() > 0) {
150 E : SetBuffer(msf_byte_stream_->data(), msf_byte_stream_->length());
151 : }
152 E : }
153 :
154 : template <MsfFileType T>
155 E : WritableMsfByteStreamImpl<T>::~WritableMsfByteStreamImpl() {
156 : // Clear our parent's pointer to us.
157 E : msf_byte_stream_->writable_msf_stream_ = NULL;
158 E : }
159 :
160 : template <MsfFileType T>
161 E : uint8* WritableMsfByteStreamImpl<T>::GrowBuffer(size_t size) {
162 E : DCHECK_GT(size, msf_byte_stream_->data_.size());
163 : // Resize the vector underlying the MsfByteStreamImpl, and notify the parent
164 : // MsfStreamImpl object of the new length.
165 E : msf_byte_stream_->data_.resize(size);
166 E : msf_byte_stream_->set_length(size);
167 E : return msf_byte_stream_->data();
168 E : }
169 :
170 : } // namespace detail
171 : } // namespace msf
172 :
173 : #endif // SYZYGY_MSF_MSF_BYTE_STREAM_IMPL_H_
|