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 <assert.h> 31 #include <string.h> 32 33 #include <algorithm> 34 35 #include "talk/base/basictypes.h" 36 #include "talk/base/byteorder.h" 37 38 namespace talk_base { 39 40 static const int DEFAULT_SIZE = 4096; 41 42 ByteBuffer::ByteBuffer() { 43 Construct(NULL, DEFAULT_SIZE, ORDER_NETWORK); 44 } 45 46 ByteBuffer::ByteBuffer(ByteOrder byte_order) { 47 Construct(NULL, DEFAULT_SIZE, byte_order); 48 } 49 50 ByteBuffer::ByteBuffer(const char* bytes, size_t len) { 51 Construct(bytes, len, ORDER_NETWORK); 52 } 53 54 ByteBuffer::ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order) { 55 Construct(bytes, len, byte_order); 56 } 57 58 ByteBuffer::ByteBuffer(const char* bytes) { 59 Construct(bytes, strlen(bytes), ORDER_NETWORK); 60 } 61 62 void ByteBuffer::Construct(const char* bytes, size_t len, 63 ByteOrder byte_order) { 64 version_ = 0; 65 start_ = 0; 66 size_ = len; 67 byte_order_ = byte_order; 68 bytes_ = new char[size_]; 69 70 if (bytes) { 71 end_ = len; 72 memcpy(bytes_, bytes, end_); 73 } else { 74 end_ = 0; 75 } 76 } 77 78 ByteBuffer::~ByteBuffer() { 79 delete[] bytes_; 80 } 81 82 bool ByteBuffer::ReadUInt8(uint8* val) { 83 if (!val) return false; 84 85 return ReadBytes(reinterpret_cast<char*>(val), 1); 86 } 87 88 bool ByteBuffer::ReadUInt16(uint16* val) { 89 if (!val) return false; 90 91 uint16 v; 92 if (!ReadBytes(reinterpret_cast<char*>(&v), 2)) { 93 return false; 94 } else { 95 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost16(v) : v; 96 return true; 97 } 98 } 99 100 bool ByteBuffer::ReadUInt24(uint32* val) { 101 if (!val) return false; 102 103 uint32 v = 0; 104 char* read_into = reinterpret_cast<char*>(&v); 105 if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) { 106 ++read_into; 107 } 108 109 if (!ReadBytes(read_into, 3)) { 110 return false; 111 } else { 112 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v; 113 return true; 114 } 115 } 116 117 bool ByteBuffer::ReadUInt32(uint32* val) { 118 if (!val) return false; 119 120 uint32 v; 121 if (!ReadBytes(reinterpret_cast<char*>(&v), 4)) { 122 return false; 123 } else { 124 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost32(v) : v; 125 return true; 126 } 127 } 128 129 bool ByteBuffer::ReadUInt64(uint64* val) { 130 if (!val) return false; 131 132 uint64 v; 133 if (!ReadBytes(reinterpret_cast<char*>(&v), 8)) { 134 return false; 135 } else { 136 *val = (byte_order_ == ORDER_NETWORK) ? NetworkToHost64(v) : v; 137 return true; 138 } 139 } 140 141 bool ByteBuffer::ReadString(std::string* val, size_t len) { 142 if (!val) return false; 143 144 if (len > Length()) { 145 return false; 146 } else { 147 val->append(bytes_ + start_, len); 148 start_ += len; 149 return true; 150 } 151 } 152 153 bool ByteBuffer::ReadBytes(char* val, size_t len) { 154 if (len > Length()) { 155 return false; 156 } else { 157 memcpy(val, bytes_ + start_, len); 158 start_ += len; 159 return true; 160 } 161 } 162 163 void ByteBuffer::WriteUInt8(uint8 val) { 164 WriteBytes(reinterpret_cast<const char*>(&val), 1); 165 } 166 167 void ByteBuffer::WriteUInt16(uint16 val) { 168 uint16 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork16(val) : val; 169 WriteBytes(reinterpret_cast<const char*>(&v), 2); 170 } 171 172 void ByteBuffer::WriteUInt24(uint32 val) { 173 uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val; 174 char* start = reinterpret_cast<char*>(&v); 175 if (byte_order_ == ORDER_NETWORK || IsHostBigEndian()) { 176 ++start; 177 } 178 WriteBytes(start, 3); 179 } 180 181 void ByteBuffer::WriteUInt32(uint32 val) { 182 uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val; 183 WriteBytes(reinterpret_cast<const char*>(&v), 4); 184 } 185 186 void ByteBuffer::WriteUInt64(uint64 val) { 187 uint64 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork64(val) : val; 188 WriteBytes(reinterpret_cast<const char*>(&v), 8); 189 } 190 191 void ByteBuffer::WriteString(const std::string& val) { 192 WriteBytes(val.c_str(), val.size()); 193 } 194 195 void ByteBuffer::WriteBytes(const char* val, size_t len) { 196 memcpy(ReserveWriteBuffer(len), val, len); 197 } 198 199 char* ByteBuffer::ReserveWriteBuffer(size_t len) { 200 if (Length() + len > Capacity()) 201 Resize(Length() + len); 202 203 char* start = bytes_ + end_; 204 end_ += len; 205 return start; 206 } 207 208 void ByteBuffer::Resize(size_t size) { 209 size_t len = _min(end_ - start_, size); 210 if (size <= size_) { 211 // Don't reallocate, just move data backwards 212 memmove(bytes_, bytes_ + start_, len); 213 } else { 214 // Reallocate a larger buffer. 215 size_ = _max(size, 3 * size_ / 2); 216 char* new_bytes = new char[size_]; 217 memcpy(new_bytes, bytes_ + start_, len); 218 delete [] bytes_; 219 bytes_ = new_bytes; 220 } 221 start_ = 0; 222 end_ = len; 223 ++version_; 224 } 225 226 bool ByteBuffer::Consume(size_t size) { 227 if (size > Length()) 228 return false; 229 start_ += size; 230 return true; 231 } 232 233 ByteBuffer::ReadPosition ByteBuffer::GetReadPosition() const { 234 return ReadPosition(start_, version_); 235 } 236 237 bool ByteBuffer::SetReadPosition(const ReadPosition &position) { 238 if (position.version_ != version_) { 239 return false; 240 } 241 start_ = position.start_; 242 return true; 243 } 244 245 void ByteBuffer::Clear() { 246 memset(bytes_, 0, size_); 247 start_ = end_ = 0; 248 ++version_; 249 } 250 251 } // namespace talk_base 252