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_t* 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_t* 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 : // Read the MSF stream.
76 E : Init(stream, 0, stream->length());
77 :
78 E : return true;
79 E : }
80 :
81 : template <MsfFileType T>
82 : bool MsfByteStreamImpl<T>::Init(MsfStreamImpl* stream,
83 : size_t pos,
84 E : size_t length) {
85 E : DCHECK(stream != NULL);
86 :
87 : // Init data members.
88 E : set_length(length);
89 E : data_.resize(length);
90 :
91 E : if (data_.empty())
92 E : return true;
93 :
94 : // Read the MSF stream.
95 E : if (!stream->ReadBytesAt(pos, length, data())) {
96 i : LOG(ERROR) << "Failed to read MSF stream.";
97 i : return false;
98 : }
99 :
100 E : return true;
101 E : }
102 :
103 : template <MsfFileType T>
104 E : bool MsfByteStreamImpl<T>::ReadBytesAt(size_t pos, size_t count, void* dest) {
105 E : DCHECK(dest != NULL);
106 :
107 : // Don't read beyond the end of the known stream length.
108 E : if (count > length() - pos)
109 E : return false;
110 :
111 : // Read the stream.
112 E : ::memcpy(dest, data() + pos, count);
113 :
114 E : return true;
115 E : }
116 :
117 : template <MsfFileType T>
118 : scoped_refptr<WritableMsfStreamImpl<T>>
119 E : MsfByteStreamImpl<T>::GetWritableStream() {
120 : // This is very not thread-safe! If we want this to be thread-safe, we'll
121 : // need to be using thread-safe reference counting, and a little smarts here
122 : // to ensure we're not mid-destructor on some other thread.
123 E : if (writable_msf_stream_ == NULL)
124 E : writable_msf_stream_ = new WritableMsfByteStreamImpl<T>(this);
125 E : return scoped_refptr<WritableMsfStreamImpl<T>>(writable_msf_stream_);
126 E : }
127 :
128 : template <MsfFileType T>
129 : WritableMsfByteStreamImpl<T>::WritableMsfByteStreamImpl(
130 E : MsfByteStreamImpl<T>* msf_byte_stream) {
131 E : DCHECK(msf_byte_stream != NULL);
132 E : msf_byte_stream_ = msf_byte_stream;
133 :
134 : // If the stream contains data, initialize the BufferWriter.
135 E : if (msf_byte_stream_->length() > 0) {
136 E : SetBuffer(msf_byte_stream_->data(), msf_byte_stream_->length());
137 : }
138 E : }
139 :
140 : template <MsfFileType T>
141 E : WritableMsfByteStreamImpl<T>::~WritableMsfByteStreamImpl() {
142 : // Clear our parent's pointer to us.
143 E : msf_byte_stream_->writable_msf_stream_ = NULL;
144 E : }
145 :
146 : template <MsfFileType T>
147 E : uint8_t* WritableMsfByteStreamImpl<T>::GrowBuffer(size_t size) {
148 E : DCHECK_GT(size, msf_byte_stream_->data_.size());
149 : // Resize the vector underlying the MsfByteStreamImpl, and notify the parent
150 : // MsfStreamImpl object of the new length.
151 E : msf_byte_stream_->data_.resize(size);
152 E : msf_byte_stream_->set_length(size);
153 E : return msf_byte_stream_->data();
154 E : }
155 :
156 : } // namespace detail
157 : } // namespace msf
158 :
159 : #endif // SYZYGY_MSF_MSF_BYTE_STREAM_IMPL_H_
|