File: buffer_source.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (160 lines) | stat: -rw-r--r-- 5,989 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/390223051): Remove C-library calls to fix the errors.
#pragma allow_unsafe_libc_calls
#endif

#ifndef COMPONENTS_ZUCCHINI_BUFFER_SOURCE_H_
#define COMPONENTS_ZUCCHINI_BUFFER_SOURCE_H_

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#include <initializer_list>
#include <type_traits>

#include "base/check_op.h"
#include "components/zucchini/buffer_view.h"

namespace zucchini {

// BufferSource acts like an input stream with convenience methods to parse data
// from a contiguous sequence of raw data. The underlying ConstBufferView
// emulates a cursor to track current read position, and guards against buffer
// overrun. Where applicable, BufferSource should be passed by pointer to
// maintain cursor progress across reads.
class BufferSource : public ConstBufferView {
 public:
  // LEB128 info: http://dwarfstd.org/doc/dwarf-2.0.0.pdf , Section 7.6.
  enum : size_t { kMaxLeb128Size = 5 };

  static BufferSource FromRange(const_iterator first, const_iterator last) {
    return BufferSource(ConstBufferView::FromRange(first, last));
  }

  using ConstBufferView::ConstBufferView;
  BufferSource() = default;
  explicit BufferSource(const ConstBufferView& buffer);

  // Constructs view into |buffer| starting at |offset| (truncated if size
  // exceeded).
  BufferSource(const ConstBufferView& buffer, size_type offset);

  BufferSource(const BufferSource&) = default;
  BufferSource& operator=(BufferSource&&) = default;

  // Advances the cursor by |n| bytes and returns true if there are enough bytes
  // remaining. Otherwise moves cursor to end and returns false.
  bool Skip(size_type n);

  // Returns true if |value| matches data starting at the cursor when
  // reinterpreted as the integral type |T|.
  template <class T>
  bool CheckNextValue(const T& value) const {
    static_assert(std::is_integral<T>::value,
                  "Value type must be an integral type");
    DCHECK_NE(begin(), nullptr);
    if (Remaining() < sizeof(T)) {
      return false;
    }
    T next_value = {};
    ::memcpy(&next_value, begin(), sizeof(T));
    return value == next_value;
  }

  // Returns true if the next bytes.size() bytes at the cursor match those in
  // |bytes|.
  bool CheckNextBytes(std::initializer_list<uint8_t> bytes) const;

  // Same as CheckNextBytes(), but moves the cursor by bytes.size() if read is
  // successfull.
  bool ConsumeBytes(std::initializer_list<uint8_t> bytes);

  // Tries to reinterpret data as type |T|, starting at the cursor and to write
  // the result into |value|, while moving the cursor forward by sizeof(T).
  // Returns true if sufficient data is available, and false otherwise.
  template <class T>
  bool GetValue(T* value) {
    static_assert(std::is_standard_layout<T>::value,
                  "Value type must be a standard layout type");

    DCHECK_NE(begin(), nullptr);
    if (Remaining() < sizeof(T)) {
      return false;
    }
    ::memcpy(value, begin(), sizeof(T));
    remove_prefix(sizeof(T));
    return true;
  }

  // Tries to reinterpret data as type |T| at the cursor and to return a
  // reinterpreted pointer of type |T| pointing into the underlying data, while
  // moving the cursor forward by sizeof(T). Returns nullptr if insufficient
  // data is available.
  template <class T>
  const T* GetPointer() {
    static_assert(std::is_standard_layout<T>::value,
                  "Value type must be a standard layout type");
    // Ensures unaligned data access is allowed.
    static_assert(alignof(T) == 1, "Value type requires byte alignment");

    DCHECK_NE(begin(), nullptr);
    if (Remaining() < sizeof(T)) {
      return nullptr;
    }
    const T* ptr = reinterpret_cast<const T*>(begin());
    remove_prefix(sizeof(T));
    return ptr;
  }

  // Tries to reinterpret data as an array of type |T| with |count| elements,
  // starting at the cursor, and to return a reinterpreted pointer of type |T|
  // pointing into the underlying data, while advancing the cursor beyond the
  // array. Returns nullptr if insufficient data is available.
  template <class T>
  const T* GetArray(size_t count) {
    static_assert(std::is_standard_layout<T>::value,
                  "Value type must be a standard layout type");
    // Ensures unaligned data access is allowed. Currently this is not used
    // with POD types. If the need arises, then more work will be needed (e.g.,
    // create a POD wrapper template to force unaligned data access).
    static_assert(alignof(T) == 1, "Value type requires byte alignment");

    if (Remaining() / sizeof(T) < count) {
      return nullptr;
    }
    const T* array = reinterpret_cast<const T*>(begin());
    remove_prefix(count * sizeof(T));
    return array;
  }

  // If sufficient data is available, assigns |buffer| to point to a region of
  // |size| bytes starting at the cursor, while advancing the cursor beyond the
  // region, and returns true. Otherwise returns false.
  bool GetRegion(size_type size, ConstBufferView* buffer);

  // Reads an Unsigned Little Endian Base 128 (uleb128) int at |first_|. If
  // successful, writes the result to |value|, advances |first_|, and returns
  // true. Otherwise returns false.
  bool GetUleb128(uint32_t* value);

  // Reads a Signed Little Endian Base 128 (sleb128) int at |first_|. If
  // successful, writes the result to |value|, advances |first_|, and returns
  // true. Otherwise returns false.
  bool GetSleb128(int32_t* value);

  // Reads uleb128 / sleb128 at |first_| but discards the result. If successful,
  // advances |first_| and returns true. Otherwise returns false.
  bool SkipLeb128();

  // Returns the number of bytes remaining from cursor until end.
  size_type Remaining() const { return size(); }
};

}  // namespace zucchini

#endif  // COMPONENTS_ZUCCHINI_BUFFER_SOURCE_H_