1 : // Copyright 2016 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 : // A utility class for safe and easy parsing of binary data streams.
16 :
17 : #ifndef SYZYGY_COMMON_BINARY_STREAM_H_
18 : #define SYZYGY_COMMON_BINARY_STREAM_H_
19 :
20 : #include <stdint.h>
21 : #include <string>
22 : #include <vector>
23 :
24 : #include "base/macros.h"
25 : #include "base/strings/string_piece.h"
26 :
27 : namespace common {
28 :
29 : // A binary stream reader yields a stream of bytes. The underlying
30 : // implementation may be seekable, but this interface is forward-only.
31 : // This is different from BinaryBufferParser et al, in that those classes
32 : // yield pointers into an in-memory buffer, whereas this class always copies
33 : // data to a caller-supplied buffer.
34 : class BinaryStreamReader {
35 : public:
36 : // Read @p len bytes forward and return the read bytes in @p out.
37 : // @param len the number of bytes to read.
38 : // @param out a buffer for the read bytes, must be at least @p len bytes in
39 : // size. On failure the contents of @p out are undefined.
40 : // @returns true iff @p len bytes were read, false otherwise.
41 : virtual bool Read(size_t len, void* out) = 0;
42 :
43 : // Get the current position of the stream.
44 : // @returns the current position of the stream.
45 : virtual size_t Position() const = 0;
46 :
47 : // Tests whether the stream is at end.
48 : // @returns true iff the stream is at the end.
49 : virtual bool AtEnd() const = 0;
50 : };
51 :
52 : // This class implements a binary stream reader on an in-memory buffer.
53 : class BinaryBufferStreamReader : public BinaryStreamReader {
54 : public:
55 : // Construct a binary stream reader on @p data of @p len bytes.
56 : // @param data the buffer to read.
57 : // @param len byte length of @p data.
58 : // @note the caller must ensure @p data outlives this instance.
59 : BinaryBufferStreamReader(const void* data, size_t len);
60 :
61 : // Construct a binary stream reader on @p data.
62 : // @param data the buffer to read.
63 : // @note the caller must ensure @p data outlives this instance.
64 : explicit BinaryBufferStreamReader(const base::StringPiece& data);
65 :
66 : // @name BinaryStreamReader implementation.
67 : // @{
68 : bool Read(size_t len, void* out) override;
69 : size_t Position() const override;
70 : bool AtEnd() const override;
71 : // @}
72 :
73 : private:
74 : bool IsValid();
75 E : size_t bytes_remaining() const { return len_ - pos_; }
76 :
77 : // Not owned.
78 : const uint8_t* data_;
79 : size_t pos_;
80 : size_t len_;
81 :
82 : DISALLOW_COPY_AND_ASSIGN(BinaryBufferStreamReader);
83 : };
84 :
85 : // This class implements a binary stream reader on a byte vector.
86 : class BinaryVectorStreamReader : public BinaryStreamReader {
87 : public:
88 : explicit BinaryVectorStreamReader(std::vector<uint8_t>* data);
89 :
90 : // @name BinaryStreamReader implementation.
91 : // @{
92 : bool Read(size_t len, void* out) override;
93 : size_t Position() const override;
94 : bool AtEnd() const override;
95 : // @}
96 :
97 : private:
98 : size_t position_;
99 : std::vector<uint8_t>* data_;
100 : };
101 :
102 : // A binary stream reader allows parsing a binary stream forwards.
103 : class BinaryStreamParser {
104 : public:
105 : // Constructs a parser on @p stream_reader.
106 : // @param stream_reader the reader to parse.
107 : // @note the caller must ensuer @p stream_reader outlives this instance.
108 : explicit BinaryStreamParser(BinaryStreamReader* stream_reader);
109 :
110 : // Read @p len bytes to @p out.
111 : // @param len the number of bytes to read.
112 : // @param out the buffer where @p len bytes will be written.
113 : // @returns true iff @p len bytes can be read, false otherwise.
114 : bool ReadBytes(size_t len, void* out) const;
115 :
116 : // Read sizeof(@p DataType) bytes into @p data.
117 : // @param data the read data on success, otherwise contains partial data.
118 : // @returns true iff @p data was successfully read.
119 : template <typename DataType>
120 : bool Read(DataType* data) const;
121 :
122 : // Read @p elements of sizeof(@p DataType) bytes into the @p data vector.
123 : // @param elements the number of elements to read.
124 : // @param data the read data on success, otherwise contains partial data.
125 : // @returns true iff @p elements element were successfully read into
126 : // @p data.
127 : template <typename DataType>
128 : bool ReadMultiple(size_t elements, std::vector<DataType>* data) const;
129 :
130 : // Read a zero-terminated string and advance the read position.
131 : // @param str returns the characters read, less the zero terminator.
132 : // @returns true if a zero terminating character is encountered.
133 : bool ReadString(std::string* str) const;
134 : bool ReadString(std::wstring* str) const;
135 :
136 : // Consumes and discards a minimal number of bytes such that the position
137 : // of the underlying stream satisifies @p alignment.
138 : // @param alignment the required alignment.
139 : // @returns true iff @p alignment is achieved.
140 : bool AlignTo(size_t alignment) const;
141 :
142 : // Accessor to underlying stream.
143 : // @returns the underlying stream for the parser.
144 E : BinaryStreamReader* stream_reader() const { return stream_reader_; }
145 :
146 : private:
147 : // Not owned.
148 : BinaryStreamReader* stream_reader_;
149 :
150 : DISALLOW_COPY_AND_ASSIGN(BinaryStreamParser);
151 : };
152 :
153 : template <typename DataType>
154 E : bool BinaryStreamParser::Read(DataType* data) const {
155 E : return ReadBytes(sizeof(*data), data);
156 E : }
157 :
158 : template <typename DataType>
159 : bool BinaryStreamParser::ReadMultiple(size_t elements,
160 E : std::vector<DataType>* data) const {
161 E : DCHECK(data != nullptr);
162 : // Reserve for the new data to save on reallocs.
163 E : data->reserve(data->size() + elements);
164 E : for (size_t read = 0; read < elements; ++read) {
165 E : DataType tmp = {};
166 E : if (!Read(&tmp))
167 E : return false;
168 :
169 E : data->push_back(tmp);
170 E : }
171 :
172 E : return true;
173 E : }
174 :
175 : } // namespace common
176 :
177 : #endif // SYZYGY_COMMON_BINARY_STREAM_H_
|