Home | History | Annotate | Download | only in base
      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 
     21 namespace rtc {
     22 
     23 static const int DEFAULT_SIZE = 4096;
     24 
     25 ByteBuffer::ByteBuffer() {
     26   Construct(NULL, DEFAULT_SIZE, ORDER_NETWORK);
     27 }
     28 
     29 ByteBuffer::ByteBuffer(ByteOrder byte_order) {
     30   Construct(NULL, DEFAULT_SIZE, byte_order);
     31 }
     32 
     33 ByteBuffer::ByteBuffer(const char* bytes, size_t len) {
     34   Construct(bytes, len, ORDER_NETWORK);
     35 }
     36 
     37 ByteBuffer::ByteBuffer(const char* bytes, size_t len, ByteOrder byte_order) {
     38   Construct(bytes, len, byte_order);
     39 }
     40 
     41 ByteBuffer::ByteBuffer(const char* bytes) {
     42   Construct(bytes, strlen(bytes), ORDER_NETWORK);
     43 }
     44 
     45 void 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 
     61 ByteBuffer::~ByteBuffer() {
     62   delete[] bytes_;
     63 }
     64 
     65 bool ByteBuffer::ReadUInt8(uint8* val) {
     66   if (!val) return false;
     67 
     68   return ReadBytes(reinterpret_cast<char*>(val), 1);
     69 }
     70 
     71 bool 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 
     83 bool 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 
    100 bool 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 
    112 bool 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 
    124 bool 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 
    136 bool 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 
    146 void ByteBuffer::WriteUInt8(uint8 val) {
    147   WriteBytes(reinterpret_cast<const char*>(&val), 1);
    148 }
    149 
    150 void ByteBuffer::WriteUInt16(uint16 val) {
    151   uint16 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork16(val) : val;
    152   WriteBytes(reinterpret_cast<const char*>(&v), 2);
    153 }
    154 
    155 void 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 
    164 void ByteBuffer::WriteUInt32(uint32 val) {
    165   uint32 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork32(val) : val;
    166   WriteBytes(reinterpret_cast<const char*>(&v), 4);
    167 }
    168 
    169 void ByteBuffer::WriteUInt64(uint64 val) {
    170   uint64 v = (byte_order_ == ORDER_NETWORK) ? HostToNetwork64(val) : val;
    171   WriteBytes(reinterpret_cast<const char*>(&v), 8);
    172 }
    173 
    174 void ByteBuffer::WriteString(const std::string& val) {
    175   WriteBytes(val.c_str(), val.size());
    176 }
    177 
    178 void ByteBuffer::WriteBytes(const char* val, size_t len) {
    179   memcpy(ReserveWriteBuffer(len), val, len);
    180 }
    181 
    182 char* 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 
    191 void 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 
    209 bool ByteBuffer::Consume(size_t size) {
    210   if (size > Length())
    211     return false;
    212   start_ += size;
    213   return true;
    214 }
    215 
    216 ByteBuffer::ReadPosition ByteBuffer::GetReadPosition() const {
    217   return ReadPosition(start_, version_);
    218 }
    219 
    220 bool ByteBuffer::SetReadPosition(const ReadPosition &position) {
    221   if (position.version_ != version_) {
    222     return false;
    223   }
    224   start_ = position.start_;
    225   return true;
    226 }
    227 
    228 void ByteBuffer::Clear() {
    229   memset(bytes_, 0, size_);
    230   start_ = end_ = 0;
    231   ++version_;
    232 }
    233 
    234 }  // namespace rtc
    235