1 : // Copyright 2014 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 buffers.
16 :
17 : #ifndef SYZYGY_COMMON_BUFFER_PARSER_H_
18 : #define SYZYGY_COMMON_BUFFER_PARSER_H_
19 :
20 : #include "base/basictypes.h"
21 :
22 : namespace common {
23 :
24 : // A binary buffer parser
25 : class BinaryBufferParser {
26 : public:
27 : BinaryBufferParser(const void* data, size_t data_len);
28 :
29 : // Accessors.
30 E : const void* data() const { return data_; }
31 E : size_t data_len() const { return data_len_; }
32 :
33 : // Check whether the buffer contains the range of data from @p pos to
34 : // @p pos + @p data_len.
35 : // @param pos the byte position of the start of the data range.
36 : // @param data_len the byte length of the data range.
37 : // @returns true iff the range of bytes from @p pos to @p pos + @p data_len.
38 : bool Contains(size_t pos, size_t data_len);
39 :
40 : // Retrieve a pointer into the buffer if the requested data is contained
41 : // in our buffer.
42 : // @param pos the position to get a pointer to.
43 : // @param data_len the amount of data expected behind @p pos.
44 : // @param data_ptr on success will contain a pointer to @p pos in data.
45 : // @returns true iff Contains(pos, data_len).
46 : bool GetAt(size_t pos, size_t data_len, const void** data_ptr);
47 :
48 : // Retrieve a typed pointer into the buffer if the requested data
49 : // is contained in our buffer.
50 : // @note Does not check @p pos for appropriate alignment.
51 : template <class DataType>
52 E : bool GetAt(size_t pos, size_t data_len, const DataType** data_ptr) {
53 E : return GetAt(pos, data_len, reinterpret_cast<const void**>(data_ptr));
54 E : }
55 :
56 : // Retrieve a typed pointer into the buffer if the requested structure
57 : // fits into our buffer at position @pos.
58 : // @note Does not check @p pos for appropriate alignment.
59 : template <class DataType>
60 E : bool GetAt(size_t pos, const DataType** data_ptr) {
61 E : return GetAt(pos, sizeof(**data_ptr), data_ptr);
62 E : }
63 :
64 : // Get a zero terminated string starting at the byte offset @p pos.
65 : // @param pos the byte offset where the string starts.
66 : // @param ptr on success returns the string pointer.
67 : // @param len on success returns the string character length.
68 : // @returns true on success, e.g. there's a zero termiator in the buffer
69 : // after @p pos, or false on failure, when @p pos is outside the buffer
70 : // or there is no zero terminator in the buffer after @p pos.
71 : // @note this function does not check @pos for appropriate alignment.
72 : bool GetStringAt(size_t pos, const char** ptr, size_t* len);
73 : bool GetStringAt(size_t pos, const wchar_t** ptr, size_t* len);
74 :
75 : protected:
76 : const int8* data_;
77 : size_t data_len_;
78 : };
79 :
80 : // A binary buffer reader allows reading sequentially from a binary buffer,
81 : // as well as peeking at the current position without moving it.
82 : class BinaryBufferReader {
83 : public:
84 : BinaryBufferReader(const void* data, size_t data_len);
85 :
86 : // Accessors.
87 E : size_t pos() const { return pos_; }
88 E : void set_pos(size_t pos) { pos_ = pos; }
89 :
90 : // Calculate the number of bytes remaining in the buffer.
91 : // @returns the number of bytes remaining in the buffer.
92 : size_t RemainingBytes() const;
93 : // Advance the read position by @p bytes.
94 : // @param bytes the number of bytes to advance the read position.
95 : // @returns true iff the new position is in our buffer.
96 : bool Consume(size_t bytes);
97 :
98 : // Align the read position to the next even multiple of @p bytes.
99 : // @param bytes the byte alignment, must be a power of two.
100 : // @returns true iff the new position is in our buffer.
101 : bool Align(size_t bytes);
102 :
103 : // Check whether the read position is aligned to bytes.
104 : // @param bytes the byte alignment to check, must be a power of two.
105 : // @returns true iff the current position is an integer multiple of @p bytes.
106 : bool IsAligned(size_t bytes);
107 :
108 : // Retrieve a pointer into our buffer, without moving the read position.
109 : bool Peek(size_t data_len, const void** data);
110 : template <class DataType>
111 : bool Peek(size_t data_len, const DataType** data_ptr) {
112 : return Peek(data_len, reinterpret_cast<const void**>(data_ptr));
113 : }
114 : template <class DataType>
115 : bool Peek(const DataType** data_ptr) {
116 : return Peek(sizeof(**data_ptr), data_ptr);
117 : }
118 :
119 : // Retrieve a pointer into our buffer and advance the read position.
120 : bool Read(size_t data_len, const void** data);
121 : template <class DataType>
122 E : bool Read(size_t data_len, const DataType** data_ptr) {
123 E : return Read(data_len, reinterpret_cast<const void**>(data_ptr));
124 E : }
125 : template <class DataType>
126 E : bool Read(const DataType** data_ptr) {
127 E : return Read(sizeof(**data_ptr), data_ptr);
128 E : }
129 :
130 : // Retrieve a zero-terminated string from our buffer without
131 : // advancing the read position.
132 : bool PeekString(const char** str, size_t* str_len);
133 : bool PeekString(const wchar_t** str, size_t* str_len);
134 :
135 : // Retrieve a zero-terminated string from our buffer and
136 : // advance the read position.
137 : bool ReadString(const char** str, size_t* str_len);
138 : bool ReadString(const wchar_t** str, size_t* str_len);
139 :
140 : private:
141 : // The buffer we read from.
142 : BinaryBufferParser parser_;
143 : // Current position.
144 : size_t pos_;
145 : };
146 :
147 : } // namespace common
148 :
149 : #endif // SYZYGY_COMMON_BUFFER_PARSER_H_
|