1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved. 2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be 3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file. 4*a03ca8b9SKrzysztof Kosiński 5*a03ca8b9SKrzysztof Kosiński #ifndef COMPONENTS_ZUCCHINI_BUFFER_SOURCE_H_ 6*a03ca8b9SKrzysztof Kosiński #define COMPONENTS_ZUCCHINI_BUFFER_SOURCE_H_ 7*a03ca8b9SKrzysztof Kosiński 8*a03ca8b9SKrzysztof Kosiński #include <stddef.h> 9*a03ca8b9SKrzysztof Kosiński #include <stdint.h> 10*a03ca8b9SKrzysztof Kosiński 11*a03ca8b9SKrzysztof Kosiński #include <initializer_list> 12*a03ca8b9SKrzysztof Kosiński #include <type_traits> 13*a03ca8b9SKrzysztof Kosiński 14*a03ca8b9SKrzysztof Kosiński #include "base/check_op.h" 15*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/buffer_view.h" 16*a03ca8b9SKrzysztof Kosiński 17*a03ca8b9SKrzysztof Kosiński namespace zucchini { 18*a03ca8b9SKrzysztof Kosiński 19*a03ca8b9SKrzysztof Kosiński // BufferSource acts like an input stream with convenience methods to parse data 20*a03ca8b9SKrzysztof Kosiński // from a contiguous sequence of raw data. The underlying ConstBufferView 21*a03ca8b9SKrzysztof Kosiński // emulates a cursor to track current read position, and guards against buffer 22*a03ca8b9SKrzysztof Kosiński // overrun. Where applicable, BufferSource should be passed by pointer to 23*a03ca8b9SKrzysztof Kosiński // maintain cursor progress across reads. 24*a03ca8b9SKrzysztof Kosiński class BufferSource : public ConstBufferView { 25*a03ca8b9SKrzysztof Kosiński public: 26*a03ca8b9SKrzysztof Kosiński // LEB128 info: http://dwarfstd.org/doc/dwarf-2.0.0.pdf , Section 7.6. 27*a03ca8b9SKrzysztof Kosiński enum : size_t { kMaxLeb128Size = 5 }; 28*a03ca8b9SKrzysztof Kosiński FromRange(const_iterator first,const_iterator last)29*a03ca8b9SKrzysztof Kosiński static BufferSource FromRange(const_iterator first, const_iterator last) { 30*a03ca8b9SKrzysztof Kosiński return BufferSource(ConstBufferView::FromRange(first, last)); 31*a03ca8b9SKrzysztof Kosiński } 32*a03ca8b9SKrzysztof Kosiński 33*a03ca8b9SKrzysztof Kosiński using ConstBufferView::ConstBufferView; 34*a03ca8b9SKrzysztof Kosiński BufferSource() = default; 35*a03ca8b9SKrzysztof Kosiński explicit BufferSource(ConstBufferView buffer); 36*a03ca8b9SKrzysztof Kosiński BufferSource(const BufferSource&) = default; 37*a03ca8b9SKrzysztof Kosiński BufferSource& operator=(BufferSource&&) = default; 38*a03ca8b9SKrzysztof Kosiński 39*a03ca8b9SKrzysztof Kosiński // Moves the cursor forward by |n| bytes, or to the end if data is exhausted. 40*a03ca8b9SKrzysztof Kosiński // Returns a reference to *this, to allow chaining, e.g.: 41*a03ca8b9SKrzysztof Kosiński // if (!buffer_source.Skip(1024).GetValue<uint32_t>(&value)) { 42*a03ca8b9SKrzysztof Kosiński // ... // Handle error. 43*a03ca8b9SKrzysztof Kosiński // } 44*a03ca8b9SKrzysztof Kosiński // Notice that Skip() defers error handling to GetValue(). 45*a03ca8b9SKrzysztof Kosiński BufferSource& Skip(size_type n); 46*a03ca8b9SKrzysztof Kosiński 47*a03ca8b9SKrzysztof Kosiński // Returns true if |value| matches data starting at the cursor when 48*a03ca8b9SKrzysztof Kosiński // reinterpreted as the integral type |T|. 49*a03ca8b9SKrzysztof Kosiński template <class T> CheckNextValue(const T & value)50*a03ca8b9SKrzysztof Kosiński bool CheckNextValue(const T& value) const { 51*a03ca8b9SKrzysztof Kosiński static_assert(std::is_integral<T>::value, 52*a03ca8b9SKrzysztof Kosiński "Value type must be an integral type"); 53*a03ca8b9SKrzysztof Kosiński DCHECK_NE(begin(), nullptr); 54*a03ca8b9SKrzysztof Kosiński if (Remaining() < sizeof(T)) 55*a03ca8b9SKrzysztof Kosiński return false; 56*a03ca8b9SKrzysztof Kosiński return value == *reinterpret_cast<const T*>(begin()); 57*a03ca8b9SKrzysztof Kosiński } 58*a03ca8b9SKrzysztof Kosiński 59*a03ca8b9SKrzysztof Kosiński // Returns true if the next bytes.size() bytes at the cursor match those in 60*a03ca8b9SKrzysztof Kosiński // |bytes|. 61*a03ca8b9SKrzysztof Kosiński bool CheckNextBytes(std::initializer_list<uint8_t> bytes) const; 62*a03ca8b9SKrzysztof Kosiński 63*a03ca8b9SKrzysztof Kosiński // Same as CheckNextBytes(), but moves the cursor by bytes.size() if read is 64*a03ca8b9SKrzysztof Kosiński // successfull. 65*a03ca8b9SKrzysztof Kosiński bool ConsumeBytes(std::initializer_list<uint8_t> bytes); 66*a03ca8b9SKrzysztof Kosiński 67*a03ca8b9SKrzysztof Kosiński // Tries to reinterpret data as type |T|, starting at the cursor and to write 68*a03ca8b9SKrzysztof Kosiński // the result into |value|, while moving the cursor forward by sizeof(T). 69*a03ca8b9SKrzysztof Kosiński // Returns true if sufficient data is available, and false otherwise. 70*a03ca8b9SKrzysztof Kosiński template <class T> GetValue(T * value)71*a03ca8b9SKrzysztof Kosiński bool GetValue(T* value) { 72*a03ca8b9SKrzysztof Kosiński static_assert(std::is_standard_layout<T>::value, 73*a03ca8b9SKrzysztof Kosiński "Value type must be a standard layout type"); 74*a03ca8b9SKrzysztof Kosiński 75*a03ca8b9SKrzysztof Kosiński DCHECK_NE(begin(), nullptr); 76*a03ca8b9SKrzysztof Kosiński if (Remaining() < sizeof(T)) 77*a03ca8b9SKrzysztof Kosiński return false; 78*a03ca8b9SKrzysztof Kosiński *value = *reinterpret_cast<const T*>(begin()); 79*a03ca8b9SKrzysztof Kosiński remove_prefix(sizeof(T)); 80*a03ca8b9SKrzysztof Kosiński return true; 81*a03ca8b9SKrzysztof Kosiński } 82*a03ca8b9SKrzysztof Kosiński 83*a03ca8b9SKrzysztof Kosiński // Tries to reinterpret data as type |T| at the cursor and to return a 84*a03ca8b9SKrzysztof Kosiński // reinterpreted pointer of type |T| pointing into the underlying data, while 85*a03ca8b9SKrzysztof Kosiński // moving the cursor forward by sizeof(T). Returns nullptr if insufficient 86*a03ca8b9SKrzysztof Kosiński // data is available. 87*a03ca8b9SKrzysztof Kosiński template <class T> GetPointer()88*a03ca8b9SKrzysztof Kosiński const T* GetPointer() { 89*a03ca8b9SKrzysztof Kosiński static_assert(std::is_standard_layout<T>::value, 90*a03ca8b9SKrzysztof Kosiński "Value type must be a standard layout type"); 91*a03ca8b9SKrzysztof Kosiński 92*a03ca8b9SKrzysztof Kosiński DCHECK_NE(begin(), nullptr); 93*a03ca8b9SKrzysztof Kosiński if (Remaining() < sizeof(T)) 94*a03ca8b9SKrzysztof Kosiński return nullptr; 95*a03ca8b9SKrzysztof Kosiński const T* ptr = reinterpret_cast<const T*>(begin()); 96*a03ca8b9SKrzysztof Kosiński remove_prefix(sizeof(T)); 97*a03ca8b9SKrzysztof Kosiński return ptr; 98*a03ca8b9SKrzysztof Kosiński } 99*a03ca8b9SKrzysztof Kosiński 100*a03ca8b9SKrzysztof Kosiński // Tries to reinterpret data as an array of type |T| with |count| elements, 101*a03ca8b9SKrzysztof Kosiński // starting at the cursor, and to return a reinterpreted pointer of type |T| 102*a03ca8b9SKrzysztof Kosiński // pointing into the underlying data, while advancing the cursor beyond the 103*a03ca8b9SKrzysztof Kosiński // array. Returns nullptr if insufficient data is available. 104*a03ca8b9SKrzysztof Kosiński template <class T> GetArray(size_t count)105*a03ca8b9SKrzysztof Kosiński const T* GetArray(size_t count) { 106*a03ca8b9SKrzysztof Kosiński static_assert(std::is_standard_layout<T>::value, 107*a03ca8b9SKrzysztof Kosiński "Value type must be a standard layout type"); 108*a03ca8b9SKrzysztof Kosiński 109*a03ca8b9SKrzysztof Kosiński if (Remaining() / sizeof(T) < count) 110*a03ca8b9SKrzysztof Kosiński return nullptr; 111*a03ca8b9SKrzysztof Kosiński const T* array = reinterpret_cast<const T*>(begin()); 112*a03ca8b9SKrzysztof Kosiński remove_prefix(count * sizeof(T)); 113*a03ca8b9SKrzysztof Kosiński return array; 114*a03ca8b9SKrzysztof Kosiński } 115*a03ca8b9SKrzysztof Kosiński 116*a03ca8b9SKrzysztof Kosiński // If sufficient data is available, assigns |buffer| to point to a region of 117*a03ca8b9SKrzysztof Kosiński // |size| bytes starting at the cursor, while advancing the cursor beyond the 118*a03ca8b9SKrzysztof Kosiński // region, and returns true. Otherwise returns false. 119*a03ca8b9SKrzysztof Kosiński bool GetRegion(size_type size, ConstBufferView* buffer); 120*a03ca8b9SKrzysztof Kosiński 121*a03ca8b9SKrzysztof Kosiński // Reads an Unsigned Little Endian Base 128 (uleb128) int at |first_|. If 122*a03ca8b9SKrzysztof Kosiński // successful, writes the result to |value|, advances |first_|, and returns 123*a03ca8b9SKrzysztof Kosiński // true. Otherwise returns false. 124*a03ca8b9SKrzysztof Kosiński bool GetUleb128(uint32_t* value); 125*a03ca8b9SKrzysztof Kosiński 126*a03ca8b9SKrzysztof Kosiński // Reads a Signed Little Endian Base 128 (sleb128) int at |first_|. If 127*a03ca8b9SKrzysztof Kosiński // successful, writes the result to |value|, advances |first_|, and returns 128*a03ca8b9SKrzysztof Kosiński // true. Otherwise returns false. 129*a03ca8b9SKrzysztof Kosiński bool GetSleb128(int32_t* value); 130*a03ca8b9SKrzysztof Kosiński 131*a03ca8b9SKrzysztof Kosiński // Reads uleb128 / sleb128 at |first_| but discards the result. If successful, 132*a03ca8b9SKrzysztof Kosiński // advances |first_| and returns true. Otherwise returns false. 133*a03ca8b9SKrzysztof Kosiński bool SkipLeb128(); 134*a03ca8b9SKrzysztof Kosiński 135*a03ca8b9SKrzysztof Kosiński // Returns the number of bytes remaining from cursor until end. Remaining()136*a03ca8b9SKrzysztof Kosiński size_type Remaining() const { return size(); } 137*a03ca8b9SKrzysztof Kosiński }; 138*a03ca8b9SKrzysztof Kosiński 139*a03ca8b9SKrzysztof Kosiński } // namespace zucchini 140*a03ca8b9SKrzysztof Kosiński 141*a03ca8b9SKrzysztof Kosiński #endif // COMPONENTS_ZUCCHINI_BUFFER_SOURCE_H_ 142