xref: /aosp_15_r20/external/webrtc/rtc_base/byte_buffer.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #ifndef RTC_BASE_BYTE_BUFFER_H_
12*d9f75844SAndroid Build Coastguard Worker #define RTC_BASE_BYTE_BUFFER_H_
13*d9f75844SAndroid Build Coastguard Worker 
14*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
15*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/buffer.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/byte_order.h"
22*d9f75844SAndroid Build Coastguard Worker 
23*d9f75844SAndroid Build Coastguard Worker // Reads/Writes from/to buffer using network byte order (big endian)
24*d9f75844SAndroid Build Coastguard Worker namespace rtc {
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker template <class BufferClassT>
27*d9f75844SAndroid Build Coastguard Worker class ByteBufferWriterT {
28*d9f75844SAndroid Build Coastguard Worker  public:
ByteBufferWriterT()29*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriterT() { Construct(nullptr, kDefaultCapacity); }
ByteBufferWriterT(const char * bytes,size_t len)30*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriterT(const char* bytes, size_t len) { Construct(bytes, len); }
31*d9f75844SAndroid Build Coastguard Worker 
32*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriterT(const ByteBufferWriterT&) = delete;
33*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriterT& operator=(const ByteBufferWriterT&) = delete;
34*d9f75844SAndroid Build Coastguard Worker 
Data()35*d9f75844SAndroid Build Coastguard Worker   const char* Data() const { return buffer_.data(); }
Length()36*d9f75844SAndroid Build Coastguard Worker   size_t Length() const { return buffer_.size(); }
Capacity()37*d9f75844SAndroid Build Coastguard Worker   size_t Capacity() const { return buffer_.capacity(); }
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker   // Write value to the buffer. Resizes the buffer when it is
40*d9f75844SAndroid Build Coastguard Worker   // neccessary.
WriteUInt8(uint8_t val)41*d9f75844SAndroid Build Coastguard Worker   void WriteUInt8(uint8_t val) {
42*d9f75844SAndroid Build Coastguard Worker     WriteBytes(reinterpret_cast<const char*>(&val), 1);
43*d9f75844SAndroid Build Coastguard Worker   }
WriteUInt16(uint16_t val)44*d9f75844SAndroid Build Coastguard Worker   void WriteUInt16(uint16_t val) {
45*d9f75844SAndroid Build Coastguard Worker     uint16_t v = HostToNetwork16(val);
46*d9f75844SAndroid Build Coastguard Worker     WriteBytes(reinterpret_cast<const char*>(&v), 2);
47*d9f75844SAndroid Build Coastguard Worker   }
WriteUInt24(uint32_t val)48*d9f75844SAndroid Build Coastguard Worker   void WriteUInt24(uint32_t val) {
49*d9f75844SAndroid Build Coastguard Worker     uint32_t v = HostToNetwork32(val);
50*d9f75844SAndroid Build Coastguard Worker     char* start = reinterpret_cast<char*>(&v);
51*d9f75844SAndroid Build Coastguard Worker     ++start;
52*d9f75844SAndroid Build Coastguard Worker     WriteBytes(start, 3);
53*d9f75844SAndroid Build Coastguard Worker   }
WriteUInt32(uint32_t val)54*d9f75844SAndroid Build Coastguard Worker   void WriteUInt32(uint32_t val) {
55*d9f75844SAndroid Build Coastguard Worker     uint32_t v = HostToNetwork32(val);
56*d9f75844SAndroid Build Coastguard Worker     WriteBytes(reinterpret_cast<const char*>(&v), 4);
57*d9f75844SAndroid Build Coastguard Worker   }
WriteUInt64(uint64_t val)58*d9f75844SAndroid Build Coastguard Worker   void WriteUInt64(uint64_t val) {
59*d9f75844SAndroid Build Coastguard Worker     uint64_t v = HostToNetwork64(val);
60*d9f75844SAndroid Build Coastguard Worker     WriteBytes(reinterpret_cast<const char*>(&v), 8);
61*d9f75844SAndroid Build Coastguard Worker   }
62*d9f75844SAndroid Build Coastguard Worker   // Serializes an unsigned varint in the format described by
63*d9f75844SAndroid Build Coastguard Worker   // https://developers.google.com/protocol-buffers/docs/encoding#varints
64*d9f75844SAndroid Build Coastguard Worker   // with the caveat that integers are 64-bit, not 128-bit.
WriteUVarint(uint64_t val)65*d9f75844SAndroid Build Coastguard Worker   void WriteUVarint(uint64_t val) {
66*d9f75844SAndroid Build Coastguard Worker     while (val >= 0x80) {
67*d9f75844SAndroid Build Coastguard Worker       // Write 7 bits at a time, then set the msb to a continuation byte
68*d9f75844SAndroid Build Coastguard Worker       // (msb=1).
69*d9f75844SAndroid Build Coastguard Worker       char byte = static_cast<char>(val) | 0x80;
70*d9f75844SAndroid Build Coastguard Worker       WriteBytes(&byte, 1);
71*d9f75844SAndroid Build Coastguard Worker       val >>= 7;
72*d9f75844SAndroid Build Coastguard Worker     }
73*d9f75844SAndroid Build Coastguard Worker     char last_byte = static_cast<char>(val);
74*d9f75844SAndroid Build Coastguard Worker     WriteBytes(&last_byte, 1);
75*d9f75844SAndroid Build Coastguard Worker   }
WriteString(absl::string_view val)76*d9f75844SAndroid Build Coastguard Worker   void WriteString(absl::string_view val) {
77*d9f75844SAndroid Build Coastguard Worker     WriteBytes(val.data(), val.size());
78*d9f75844SAndroid Build Coastguard Worker   }
WriteBytes(const char * val,size_t len)79*d9f75844SAndroid Build Coastguard Worker   void WriteBytes(const char* val, size_t len) { buffer_.AppendData(val, len); }
80*d9f75844SAndroid Build Coastguard Worker 
81*d9f75844SAndroid Build Coastguard Worker   // Reserves the given number of bytes and returns a char* that can be written
82*d9f75844SAndroid Build Coastguard Worker   // into. Useful for functions that require a char* buffer and not a
83*d9f75844SAndroid Build Coastguard Worker   // ByteBufferWriter.
ReserveWriteBuffer(size_t len)84*d9f75844SAndroid Build Coastguard Worker   char* ReserveWriteBuffer(size_t len) {
85*d9f75844SAndroid Build Coastguard Worker     buffer_.SetSize(buffer_.size() + len);
86*d9f75844SAndroid Build Coastguard Worker     return buffer_.data();
87*d9f75844SAndroid Build Coastguard Worker   }
88*d9f75844SAndroid Build Coastguard Worker 
89*d9f75844SAndroid Build Coastguard Worker   // Resize the buffer to the specified `size`.
Resize(size_t size)90*d9f75844SAndroid Build Coastguard Worker   void Resize(size_t size) { buffer_.SetSize(size); }
91*d9f75844SAndroid Build Coastguard Worker 
92*d9f75844SAndroid Build Coastguard Worker   // Clears the contents of the buffer. After this, Length() will be 0.
Clear()93*d9f75844SAndroid Build Coastguard Worker   void Clear() { buffer_.Clear(); }
94*d9f75844SAndroid Build Coastguard Worker 
95*d9f75844SAndroid Build Coastguard Worker  private:
96*d9f75844SAndroid Build Coastguard Worker   static constexpr size_t kDefaultCapacity = 4096;
97*d9f75844SAndroid Build Coastguard Worker 
Construct(const char * bytes,size_t size)98*d9f75844SAndroid Build Coastguard Worker   void Construct(const char* bytes, size_t size) {
99*d9f75844SAndroid Build Coastguard Worker     if (bytes) {
100*d9f75844SAndroid Build Coastguard Worker       buffer_.AppendData(bytes, size);
101*d9f75844SAndroid Build Coastguard Worker     } else {
102*d9f75844SAndroid Build Coastguard Worker       buffer_.EnsureCapacity(size);
103*d9f75844SAndroid Build Coastguard Worker     }
104*d9f75844SAndroid Build Coastguard Worker   }
105*d9f75844SAndroid Build Coastguard Worker 
106*d9f75844SAndroid Build Coastguard Worker   BufferClassT buffer_;
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker   // There are sensible ways to define these, but they aren't needed in our code
109*d9f75844SAndroid Build Coastguard Worker   // base.
110*d9f75844SAndroid Build Coastguard Worker };
111*d9f75844SAndroid Build Coastguard Worker 
112*d9f75844SAndroid Build Coastguard Worker class ByteBufferWriter : public ByteBufferWriterT<BufferT<char>> {
113*d9f75844SAndroid Build Coastguard Worker  public:
114*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriter();
115*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriter(const char* bytes, size_t len);
116*d9f75844SAndroid Build Coastguard Worker 
117*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriter(const ByteBufferWriter&) = delete;
118*d9f75844SAndroid Build Coastguard Worker   ByteBufferWriter& operator=(const ByteBufferWriter&) = delete;
119*d9f75844SAndroid Build Coastguard Worker };
120*d9f75844SAndroid Build Coastguard Worker 
121*d9f75844SAndroid Build Coastguard Worker // The ByteBufferReader references the passed data, i.e. the pointer must be
122*d9f75844SAndroid Build Coastguard Worker // valid during the lifetime of the reader.
123*d9f75844SAndroid Build Coastguard Worker class ByteBufferReader {
124*d9f75844SAndroid Build Coastguard Worker  public:
125*d9f75844SAndroid Build Coastguard Worker   ByteBufferReader(const char* bytes, size_t len);
126*d9f75844SAndroid Build Coastguard Worker 
127*d9f75844SAndroid Build Coastguard Worker   // Initializes buffer from a zero-terminated string.
128*d9f75844SAndroid Build Coastguard Worker   explicit ByteBufferReader(const char* bytes);
129*d9f75844SAndroid Build Coastguard Worker 
130*d9f75844SAndroid Build Coastguard Worker   explicit ByteBufferReader(const Buffer& buf);
131*d9f75844SAndroid Build Coastguard Worker 
132*d9f75844SAndroid Build Coastguard Worker   explicit ByteBufferReader(const ByteBufferWriter& buf);
133*d9f75844SAndroid Build Coastguard Worker 
134*d9f75844SAndroid Build Coastguard Worker   ByteBufferReader(const ByteBufferReader&) = delete;
135*d9f75844SAndroid Build Coastguard Worker   ByteBufferReader& operator=(const ByteBufferReader&) = delete;
136*d9f75844SAndroid Build Coastguard Worker 
137*d9f75844SAndroid Build Coastguard Worker   // Returns start of unprocessed data.
Data()138*d9f75844SAndroid Build Coastguard Worker   const char* Data() const { return bytes_ + start_; }
139*d9f75844SAndroid Build Coastguard Worker   // Returns number of unprocessed bytes.
Length()140*d9f75844SAndroid Build Coastguard Worker   size_t Length() const { return end_ - start_; }
141*d9f75844SAndroid Build Coastguard Worker 
142*d9f75844SAndroid Build Coastguard Worker   // Read a next value from the buffer. Return false if there isn't
143*d9f75844SAndroid Build Coastguard Worker   // enough data left for the specified type.
144*d9f75844SAndroid Build Coastguard Worker   bool ReadUInt8(uint8_t* val);
145*d9f75844SAndroid Build Coastguard Worker   bool ReadUInt16(uint16_t* val);
146*d9f75844SAndroid Build Coastguard Worker   bool ReadUInt24(uint32_t* val);
147*d9f75844SAndroid Build Coastguard Worker   bool ReadUInt32(uint32_t* val);
148*d9f75844SAndroid Build Coastguard Worker   bool ReadUInt64(uint64_t* val);
149*d9f75844SAndroid Build Coastguard Worker   bool ReadUVarint(uint64_t* val);
150*d9f75844SAndroid Build Coastguard Worker   bool ReadBytes(char* val, size_t len);
151*d9f75844SAndroid Build Coastguard Worker 
152*d9f75844SAndroid Build Coastguard Worker   // Appends next `len` bytes from the buffer to `val`. Returns false
153*d9f75844SAndroid Build Coastguard Worker   // if there is less than `len` bytes left.
154*d9f75844SAndroid Build Coastguard Worker   bool ReadString(std::string* val, size_t len);
155*d9f75844SAndroid Build Coastguard Worker 
156*d9f75844SAndroid Build Coastguard Worker   // Moves current position `size` bytes forward. Returns false if
157*d9f75844SAndroid Build Coastguard Worker   // there is less than `size` bytes left in the buffer. Consume doesn't
158*d9f75844SAndroid Build Coastguard Worker   // permanently remove data, so remembered read positions are still valid
159*d9f75844SAndroid Build Coastguard Worker   // after this call.
160*d9f75844SAndroid Build Coastguard Worker   bool Consume(size_t size);
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker  protected:
163*d9f75844SAndroid Build Coastguard Worker   void Construct(const char* bytes, size_t size);
164*d9f75844SAndroid Build Coastguard Worker 
165*d9f75844SAndroid Build Coastguard Worker   const char* bytes_;
166*d9f75844SAndroid Build Coastguard Worker   size_t size_;
167*d9f75844SAndroid Build Coastguard Worker   size_t start_;
168*d9f75844SAndroid Build Coastguard Worker   size_t end_;
169*d9f75844SAndroid Build Coastguard Worker };
170*d9f75844SAndroid Build Coastguard Worker 
171*d9f75844SAndroid Build Coastguard Worker }  // namespace rtc
172*d9f75844SAndroid Build Coastguard Worker 
173*d9f75844SAndroid Build Coastguard Worker #endif  // RTC_BASE_BYTE_BUFFER_H_
174