buffer_source.h 5.2 KB

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