blob: dd3e063901bfcc2fc52bee7797f690abb7471238 [file] [log] [blame]
Josh Gaocd2a5292018-03-07 16:52:28 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <algorithm>
20#include <utility>
21
22#include <android-base/logging.h>
23
24#include "sysdeps/memory.h"
25
26// Essentially std::vector<char>, except without zero initialization or reallocation.
27struct Block {
28 using iterator = char*;
29
30 Block() {}
31
32 explicit Block(size_t size) { allocate(size); }
33
34 template <typename Iterator>
35 Block(Iterator begin, Iterator end) : Block(end - begin) {
36 std::copy(begin, end, data_);
37 }
38
39 Block(const Block& copy) = delete;
40 Block(Block&& move) {
41 std::swap(data_, move.data_);
42 std::swap(capacity_, move.capacity_);
43 std::swap(size_, move.size_);
44 }
45
46 Block& operator=(const Block& copy) = delete;
47 Block& operator=(Block&& move) {
48 clear();
49
50 std::swap(data_, move.data_);
51 std::swap(capacity_, move.capacity_);
52 std::swap(size_, move.size_);
53
54 return *this;
55 }
56
57 ~Block() { clear(); }
58
59 void resize(size_t new_size) {
60 if (!data_) {
61 allocate(new_size);
62 } else {
63 CHECK_GE(capacity_, new_size);
64 size_ = new_size;
65 }
66 }
67
68 template <typename InputIt>
69 void assign(InputIt begin, InputIt end) {
70 clear();
71 allocate(end - begin);
72 std::copy(begin, end, data_);
73 }
74
75 void clear() {
76 free(data_);
77 capacity_ = 0;
78 size_ = 0;
79 }
80
81 size_t capacity() const { return capacity_; }
82 size_t size() const { return size_; }
83 bool empty() const { return size() == 0; }
84
85 char* data() { return data_; }
86 const char* data() const { return data_; }
87
88 char* begin() { return data_; }
89 const char* begin() const { return data_; }
90
91 char* end() { return data() + size_; }
92 const char* end() const { return data() + size_; }
93
94 char& operator[](size_t idx) { return data()[idx]; }
95 const char& operator[](size_t idx) const { return data()[idx]; }
96
97 bool operator==(const Block& rhs) const {
98 return size() == rhs.size() && memcmp(data(), rhs.data(), size()) == 0;
99 }
100
101 private:
102 void allocate(size_t size) {
103 CHECK(data_ == nullptr);
104 CHECK_EQ(0ULL, capacity_);
105 CHECK_EQ(0ULL, size_);
106 if (size != 0) {
107 data_ = static_cast<char*>(malloc(size));
108 capacity_ = size;
109 size_ = size;
110 }
111 }
112
113 char* data_ = nullptr;
114 size_t capacity_ = 0;
115 size_t size_ = 0;
116};
117
118struct amessage {
119 uint32_t command; /* command identifier constant */
120 uint32_t arg0; /* first argument */
121 uint32_t arg1; /* second argument */
122 uint32_t data_length; /* length of payload (0 is allowed) */
123 uint32_t data_check; /* checksum of data payload */
124 uint32_t magic; /* command ^ 0xffffffff */
125};
126
127struct apacket {
128 using payload_type = Block;
129 amessage msg;
130 payload_type payload;
131};
132
133struct Range {
134 explicit Range(apacket::payload_type data) : data_(std::move(data)) {}
135
136 Range(const Range& copy) = delete;
137 Range& operator=(const Range& copy) = delete;
138
139 Range(Range&& move) = default;
140 Range& operator=(Range&& move) = default;
141
142 size_t size() const { return data_.size() - begin_offset_ - end_offset_; };
143 bool empty() const { return size() == 0; }
144
145 void drop_front(size_t n) {
146 CHECK_GE(size(), n);
147 begin_offset_ += n;
148 }
149
150 void drop_end(size_t n) {
151 CHECK_GE(size(), n);
152 end_offset_ += n;
153 }
154
155 char* data() { return &data_[0] + begin_offset_; }
156
157 apacket::payload_type::iterator begin() { return data_.begin() + begin_offset_; }
158 apacket::payload_type::iterator end() { return data_.end() - end_offset_; }
159
160 apacket::payload_type data_;
161 size_t begin_offset_ = 0;
162 size_t end_offset_ = 0;
163};