Bug 1943761 - Add class alignment to the mozsearch analysis file. r=asuth
[gecko.git] / js / xpconnect / loader / IOBuffers.h
blobe26b0c3bca8289dc3f3fac7d96960c96c2f159c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef IOBuffers_h
7 #define IOBuffers_h
9 #include "mozilla/Assertions.h"
10 #include "mozilla/CheckedInt.h"
11 #include "mozilla/EndianUtils.h"
12 #include "mozilla/EnumSet.h"
13 #include "mozilla/Range.h"
14 #include "mozilla/Span.h"
15 #include "nsString.h"
16 #include "nsTArray.h"
18 namespace mozilla {
19 namespace loader {
21 class OutputBuffer {
22 public:
23 OutputBuffer() {}
25 uint8_t* write(size_t size) {
26 auto buf = data.AppendElements(size);
27 cursor_ += size;
28 return buf;
31 void codeUint8(const uint8_t& val) { *write(sizeof val) = val; }
33 template <typename T>
34 void codeUint8(const EnumSet<T>& val) {
35 // EnumSets are always represented as uint32_t values, so we need to
36 // assert that the value actually fits in a uint8 before writing it.
37 uint32_t value = val.serialize();
38 codeUint8(CheckedUint8(value).value());
41 void codeUint16(const uint16_t& val) {
42 LittleEndian::writeUint16(write(sizeof val), val);
45 void codeUint32(const uint32_t& val) {
46 LittleEndian::writeUint32(write(sizeof val), val);
49 void codeString(const nsCString& str) {
50 auto len = CheckedUint16(str.Length()).value();
52 codeUint16(len);
53 memcpy(write(len), str.BeginReading(), len);
56 size_t cursor() const { return cursor_; }
58 uint8_t* Get() { return data.Elements(); }
60 const uint8_t* Get() const { return data.Elements(); }
62 private:
63 nsTArray<uint8_t> data;
64 size_t cursor_ = 0;
67 class InputBuffer {
68 public:
69 explicit InputBuffer(const Range<uint8_t>& buffer) : data(buffer) {}
71 const uint8_t* read(size_t size) {
72 MOZ_ASSERT(checkCapacity(size));
74 auto buf = &data[cursor_];
75 cursor_ += size;
76 return buf;
79 bool codeUint8(uint8_t& val) {
80 if (checkCapacity(sizeof val)) {
81 val = *read(sizeof val);
83 return !error_;
86 template <typename T>
87 bool codeUint8(EnumSet<T>& val) {
88 uint8_t value;
89 if (codeUint8(value)) {
90 val.deserialize(value);
92 return !error_;
95 bool codeUint16(uint16_t& val) {
96 if (checkCapacity(sizeof val)) {
97 val = LittleEndian::readUint16(read(sizeof val));
99 return !error_;
102 bool codeUint32(uint32_t& val) {
103 if (checkCapacity(sizeof val)) {
104 val = LittleEndian::readUint32(read(sizeof val));
106 return !error_;
109 bool codeString(nsCString& str) {
110 uint16_t len;
111 if (codeUint16(len)) {
112 if (checkCapacity(len)) {
113 str.SetLength(len);
114 memcpy(str.BeginWriting(), read(len), len);
117 return !error_;
120 bool error() { return error_; }
122 bool finished() { return error_ || !remainingCapacity(); }
124 size_t remainingCapacity() { return data.length() - cursor_; }
126 size_t cursor() const { return cursor_; }
128 const uint8_t* Get() const { return data.begin().get(); }
130 private:
131 bool checkCapacity(size_t size) {
132 if (size > remainingCapacity()) {
133 error_ = true;
135 return !error_;
138 bool error_ = false;
140 public:
141 const Range<uint8_t>& data;
142 size_t cursor_ = 0;
145 } // namespace loader
146 } // namespace mozilla
148 #endif // IOBuffers_h