1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/bytebuffer.h" 29 30 #include <algorithm> 31 #include <cassert> 32 #include <cstring> 33 34 #include "talk/base/basictypes.h" 35 #include "talk/base/byteorder.h" 36 37 namespace talk_base { 38 39 static const int DEFAULT_SIZE = 4096; 40 41 ByteBuffer::ByteBuffer() { 42 Construct(NULL, DEFAULT_SIZE, ORDER_NETWORK); 43 } 44 45 ByteBuffer::ByteBuffer(ByteOrder byte_order) { 46 Construct(NULL, DEFAULT_SIZE, byte_order); 47 } 48 49 ByteBuffer::ByteBuffer(const char* bytes, size_t len) { 50 Construct(bytes, len, ORDER_NETWORK); 51 } 52 53 ByteBuffer::ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order) { 54 Construct(bytes, len, byte_order); 55 } 56 57 ByteBuffer::ByteBuffer(const char* bytes) { 58 Construct(bytes, strlen(bytes), ORDER_NETWORK); 59 } 60 61 void ByteBuffer::Construct(const char* bytes, size_t len, 62 ByteOrder byte_order) { 63 version_ = 0; 64 start_ = 0; 65 size_ = len; 66 byte_order_ = byte_order; 67 bytes_ = new char[size_]; 68 69 if (bytes) { 70 end_ = len; 71 memcpy(bytes_, bytes, end_); 72 } else { 73 end_ = 0; 74 } 75 } 76 77 ByteBuffer::~ByteBuffer() { 78 delete[] bytes_; 79 } 80 81 bool ByteBuffer::ReadUInt8(uint8* val) { 82 if (!val) return false; 83 84 return ReadBytes(reinterpret_cast<char*>(val), 1); 85 } 86 87 bool ByteBuffer::ReadUInt16(uint16* val) { 88 if (!val) return false; 89 90 uint16 v; 91 if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) { 92 return false; 93 } else { 94 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost16(v) : v; 95 return true; 96 } 97 } 98 99 bool ByteBuffer::ReadUInt24(uint32* val) { 100 if (!val) return false; 101 102 uint32 v = 0; 103 char* read_into = reinterpret_cast<char*>(&v); 104 if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) { 105 ++read_into; 106 } 107 108 if (!ReadBytes(read_into, 3)) { 109 return false; 110 } else { 111 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v; 112 return true; 113 } 114 } 115 116 bool ByteBuffer::ReadUInt32(uint32* val) { 117 if (!val) return false; 118 119 uint32 v; 120 if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) { 121 return false; 122 } else { 123 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v; 124 return true; 125 } 126 } 127 128 bool ByteBuffer::ReadUInt64(uint64* val) { 129 if (!val) return false; 130 131 uint64 v; 132 if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) { 133 return false; 134 } else { 135 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost64(v) : v; 136 return true; 137 } 138 } 139 140 bool ByteBuffer::ReadString(std::string* val, size_t len) { 141 if (!val) return false; 142 143 if (len > Length()) { 144 return false; 145 } else { 146 val->append(bytes_ + start_, len); 147 start_ += len; 148 return true; 149 } 150 } 151 152 bool ByteBuffer::ReadBytes(char* val, size_t len) { 153 if (len > Length()) { 154 return false; 155 } else { 156 memcpy(val, bytes_ + start_, len); 157 start_ += len; 158 return true; 159 } 160 } 161 162 void ByteBuffer::WriteUInt8(uint8 val) { 163 WriteBytes(reinterpret_cast<const char*>(&val), 1); 164 } 165 166 void ByteBuffer::WriteUInt16(uint16 val) { 167 uint16 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork16(val) : val; 168 WriteBytes(reinterpret_cast<const char*>(&v), 2); 169 } 170 171 void ByteBuffer::WriteUInt24(uint32 val) { 172 uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val; 173 char* start = reinterpret_cast<char*>(&v); 174 if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) { 175 ++start; 176 } 177 WriteBytes(start, 3); 178 } 179 180 void ByteBuffer::WriteUInt32(uint32 val) { 181 uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val; 182 WriteBytes(reinterpret_cast<const char*>(&v), 4); 183 } 184 185 void ByteBuffer::WriteUInt64(uint64 val) { 186 uint64 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork64(val) : val; 187 WriteBytes(reinterpret_cast<const char*>(&v), 8); 188 } 189 190 void ByteBuffer::WriteString(const std::string& val) { 191 WriteBytes(val.c_str(), val.size()); 192 } 193 194 void ByteBuffer::WriteBytes(const char* val, size_t len) { 195 memcpy(ReserveWriteBuffer(len), val, len); 196 } 197 198 char* ByteBuffer::ReserveWriteBuffer(size_t len) { 199 if (Length() + len > Capacity()) 200 Resize(Length() + len); 201 202 char* start = bytes_ + end_; 203 end_ += len; 204 return start; 205 } 206 207 void ByteBuffer::Resize(size_t size) { 208 size_t len = _min(end_ - start_, size); 209 if (size <= size_) { 210 // Don't reallocate, just move data backwards 211 memmove(bytes_, bytes_ + start_, len); 212 } else { 213 // Reallocate a larger buffer. 214 size_ = _max(size, 3 * size_ / 2); 215 char* new_bytes = new char[size_]; 216 memcpy(new_bytes, bytes_ + start_, len); 217 delete [] bytes_; 218 bytes_ = new_bytes; 219 } 220 start_ = 0; 221 end_ = len; 222 ++version_; 223 } 224 225 bool ByteBuffer::Consume(size_t size) { 226 if (size > Length()) 227 return false; 228 start_ += size; 229 return true; 230 } 231 232 ByteBuffer::ReadPosition ByteBuffer::GetReadPosition() const { 233 return ReadPosition(start_, version_); 234 } 235 236 bool ByteBuffer::SetReadPosition(const ReadPosition &position) { 237 if (position.version_ != version_) { 238 return false; 239 } 240 start_ = position.start_; 241 return true; 242 } 243 244 void ByteBuffer::Clear() { 245 memset(bytes_, 0, size_); 246 start_ = end_ = 0; 247 ++version_; 248 } 249 250 } // namespace talk_base 251