blob: 32fc4d053be20a2749642a676d0cc15158d9df72 [file] [log] [blame]
David Valleau46c3f412018-11-14 10:25:47 -08001// Copyright 2018 The Chromium OS 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
Fletcher Woodruff6cdda0a2020-04-22 11:14:07 -06005#ifndef SMART_BUFFER_H__
6#define SMART_BUFFER_H__
David Valleau46c3f412018-11-14 10:25:47 -08007
8#include <memory>
9#include <string>
10#include <vector>
11
12#include <base/logging.h>
13
14// Wrapper class used for packing bytes to be transferred on a network socket.
15class SmartBuffer {
16 public:
17 SmartBuffer() = default;
18
19 // Initialize the buffer with an initial size of |size|.
20 explicit SmartBuffer(size_t size);
21
22 // Initialize the buffer with the same contents as |v|.
23 explicit SmartBuffer(const std::vector<uint8_t>& v);
24
25 // Convert |data| into uint8_t* and add |data_size| bytes to the internal
26 // buffer.
27 template <typename T>
28 void Add(const T* data, size_t data_size);
29
30 // Add the underlying byte representation of |data| to the buffer.
31 template <typename T>
32 void Add(const T& data);
33
34 // Specialized Add method for std::vector so that we can call |v.data()| and
35 // |v.size()| to extract the underlying pointer and size of the data.
36 template <typename T>
37 void Add(const std::vector<T>& v);
38
39 // Specialized Add method for std::string so that we can call |s.c_str()| and
40 // |s.size()| to extract the underlying pointer and size of the data.
41 void Add(const std::string& s);
42
Fletcher Woodruff86deb602020-05-06 16:43:56 -060043 // Specialized Add method for char* that uses strlen.
44 void Add(const char* s);
45
David Valleau46c3f412018-11-14 10:25:47 -080046 // Adds the contents from |buf|.
47 void Add(const SmartBuffer& buf);
48
49 // Add the contents from |buf|, starting from |start|.
50 void Add(const SmartBuffer& buf, size_t start);
51
52 // Add the subsequence of |buf| starting at |start| and of length |len|.
53 void Add(const SmartBuffer& buf, size_t start, size_t len);
54
55 // Erases the element at |index|.
56 void Erase(size_t index);
57
58 // Erases the subsequence of length |len| starting at |start| from |buffer|.
59 void Erase(size_t start, size_t len);
60
61 // Shrink the underlying vector to |size|.
62 void Shrink(size_t size);
63
Fletcher Woodruffe1bf8392020-04-27 15:15:15 -060064 // Find first occurrence of |target| in the buffer and return the index to
65 // where it begins. If |target| does not appear in |message| then returns -1.
66 ssize_t FindFirstOccurrence(const std::string& target,
67 size_t start = 0) const;
68
David Valleau46c3f412018-11-14 10:25:47 -080069 size_t size() const { return buffer_.size(); }
70 const std::vector<uint8_t>& contents() const { return buffer_; }
71 const uint8_t* data() const { return buffer_.data(); }
72
73 private:
74 std::vector<uint8_t> buffer_;
75};
76
77template <typename T>
78void SmartBuffer::Add(const T* data, size_t data_size) {
79 const uint8_t* packed_data = reinterpret_cast<const uint8_t*>(data);
80 buffer_.insert(buffer_.end(), packed_data, packed_data + data_size);
81}
82
83template <typename T>
84void SmartBuffer::Add(const T& data) {
Fletcher Woodruff86deb602020-05-06 16:43:56 -060085 static_assert(!std::is_pointer<T>::value,
86 "cannot use Add(const T&) for pointer types. If you want to "
87 "Add a pointer type, use Add(const T* data, size)");
David Valleau46c3f412018-11-14 10:25:47 -080088 Add(&data, sizeof(data));
89}
90
91template <typename T>
92void SmartBuffer::Add(const std::vector<T>& v) {
93 CHECK(std::is_fundamental<T>::value)
94 << "Given vector does not contain fundamental elements";
95 size_t byte_size = sizeof(T) * v.size();
96 Add(v.data(), byte_size);
97}
98
Fletcher Woodruff6cdda0a2020-04-22 11:14:07 -060099#endif // SMART_BUFFER_H__