blob: 6133759e59a411e4763c346d0776cfce18d180d1 [file] [log] [blame]
henrike@webrtc.orgf7795df2014-05-13 18:00:26 +00001/*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/bytebuffer.h"
12
13#include <assert.h>
14#include <string.h>
15
16#include <algorithm>
17
18#include "webrtc/base/basictypes.h"
19#include "webrtc/base/byteorder.h"
20
21namespace rtc {
22
23static const int DEFAULT_SIZE = 4096;
24
25ByteBuffer::ByteBuffer() {
26 Construct(NULL, DEFAULT_SIZE, ORDER_NETWORK);
27}
28
29ByteBuffer::ByteBuffer(ByteOrder byte_order) {
30 Construct(NULL, DEFAULT_SIZE, byte_order);
31}
32
33ByteBuffer::ByteBuffer(const char* bytes, size_t len) {
34 Construct(bytes, len, ORDER_NETWORK);
35}
36
37ByteBuffer::ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order) {
38 Construct(bytes, len, byte_order);
39}
40
41ByteBuffer::ByteBuffer(const char* bytes) {
42 Construct(bytes, strlen(bytes), ORDER_NETWORK);
43}
44
45void ByteBuffer::Construct(const char* bytes, size_t len,
46 ByteOrder byte_order) {
47 version_ = 0;
48 start_ = 0;
49 size_ = len;
50 byte_order_ = byte_order;
51 bytes_ = new char[size_];
52
53 if (bytes) {
54 end_ = len;
55 memcpy(bytes_, bytes, end_);
56 } else {
57 end_ = 0;
58 }
59}
60
61ByteBuffer::~ByteBuffer() {
62 delete[] bytes_;
63}
64
65bool ByteBuffer::ReadUInt8(uint8* val) {
66 if (!val) return false;
67
68 return ReadBytes(reinterpret_cast<char*>(val), 1);
69}
70
71bool ByteBuffer::ReadUInt16(uint16* val) {
72 if (!val) return false;
73
74 uint16 v;
75 if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) {
76 return false;
77 } else {
78 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost16(v) : v;
79 return true;
80 }
81}
82
83bool ByteBuffer::ReadUInt24(uint32* val) {
84 if (!val) return false;
85
86 uint32 v = 0;
87 char* read_into = reinterpret_cast<char*>(&v);
88 if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) {
89 ++read_into;
90 }
91
92 if (!ReadBytes(read_into, 3)) {
93 return false;
94 } else {
95 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v;
96 return true;
97 }
98}
99
100bool ByteBuffer::ReadUInt32(uint32* val) {
101 if (!val) return false;
102
103 uint32 v;
104 if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) {
105 return false;
106 } else {
107 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v;
108 return true;
109 }
110}
111
112bool ByteBuffer::ReadUInt64(uint64* val) {
113 if (!val) return false;
114
115 uint64 v;
116 if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) {
117 return false;
118 } else {
119 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost64(v) : v;
120 return true;
121 }
122}
123
124bool ByteBuffer::ReadString(std::string* val, size_t len) {
125 if (!val) return false;
126
127 if (len > Length()) {
128 return false;
129 } else {
130 val->append(bytes_ + start_, len);
131 start_ += len;
132 return true;
133 }
134}
135
136bool ByteBuffer::ReadBytes(char* val, size_t len) {
137 if (len > Length()) {
138 return false;
139 } else {
140 memcpy(val, bytes_ + start_, len);
141 start_ += len;
142 return true;
143 }
144}
145
146void ByteBuffer::WriteUInt8(uint8 val) {
147 WriteBytes(reinterpret_cast<const char*>(&val), 1);
148}
149
150void ByteBuffer::WriteUInt16(uint16 val) {
151 uint16 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork16(val) : val;
152 WriteBytes(reinterpret_cast<const char*>(&v), 2);
153}
154
155void ByteBuffer::WriteUInt24(uint32 val) {
156 uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
157 char* start = reinterpret_cast<char*>(&v);
158 if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) {
159 ++start;
160 }
161 WriteBytes(start, 3);
162}
163
164void ByteBuffer::WriteUInt32(uint32 val) {
165 uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
166 WriteBytes(reinterpret_cast<const char*>(&v), 4);
167}
168
169void ByteBuffer::WriteUInt64(uint64 val) {
170 uint64 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork64(val) : val;
171 WriteBytes(reinterpret_cast<const char*>(&v), 8);
172}
173
174void ByteBuffer::WriteString(const std::string& val) {
175 WriteBytes(val.c_str(), val.size());
176}
177
178void ByteBuffer::WriteBytes(const char* val, size_t len) {
179 memcpy(ReserveWriteBuffer(len), val, len);
180}
181
182char* ByteBuffer::ReserveWriteBuffer(size_t len) {
183 if (Length() + len > Capacity())
184 Resize(Length() + len);
185
186 char* start = bytes_ + end_;
187 end_ += len;
188 return start;
189}
190
191void ByteBuffer::Resize(size_t size) {
192 size_t len = _min(end_ - start_, size);
193 if (size <= size_) {
194 // Don't reallocate, just move data backwards
195 memmove(bytes_, bytes_ + start_, len);
196 } else {
197 // Reallocate a larger buffer.
198 size_ = _max(size, 3 * size_ / 2);
199 char* new_bytes = new char[size_];
200 memcpy(new_bytes, bytes_ + start_, len);
201 delete [] bytes_;
202 bytes_ = new_bytes;
203 }
204 start_ = 0;
205 end_ = len;
206 ++version_;
207}
208
209bool ByteBuffer::Consume(size_t size) {
210 if (size > Length())
211 return false;
212 start_ += size;
213 return true;
214}
215
216ByteBuffer::ReadPosition ByteBuffer::GetReadPosition() const {
217 return ReadPosition(start_, version_);
218}
219
220bool ByteBuffer::SetReadPosition(const ReadPosition &position) {
221 if (position.version_ != version_) {
222 return false;
223 }
224 start_ = position.start_;
225 return true;
226}
227
228void ByteBuffer::Clear() {
229 memset(bytes_, 0, size_);
230 start_ = end_ = 0;
231 ++version_;
232}
233
234} // namespace rtc