1/*
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
235