1 /* 2 * libjingle 3 * Copyright 2004-2010, 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 #ifndef TALK_BASE_BUFFER_H_ 29 #define TALK_BASE_BUFFER_H_ 30 31 #include <cstring> 32 33 #include "talk/base/scoped_ptr.h" 34 35 namespace talk_base { 36 37 // Basic buffer class, can be grown and shrunk dynamically. 38 // Unlike std::string/vector, does not initialize data when expanding capacity. 39 class Buffer { 40 public: 41 Buffer() { 42 Construct(NULL, 0, 0); 43 } 44 Buffer(const void* data, size_t length) { 45 Construct(data, length, length); 46 } 47 Buffer(const void* data, size_t length, size_t capacity) { 48 Construct(data, length, capacity); 49 } 50 Buffer(const Buffer& buf) { 51 Construct(buf.data(), buf.length(), buf.length()); 52 } 53 54 const char* data() const { return data_.get(); } 55 char* data() { return data_.get(); } 56 // TODO: should this be size(), like STL? 57 size_t length() const { return length_; } 58 size_t capacity() const { return capacity_; } 59 60 Buffer& operator=(const Buffer& buf) { 61 if (&buf != this) { 62 Construct(buf.data(), buf.length(), buf.length()); 63 } 64 return *this; 65 } 66 bool operator==(const Buffer& buf) const { 67 return (length_ == buf.length() && 68 memcmp(data_.get(), buf.data(), length_) == 0); 69 } 70 bool operator!=(const Buffer& buf) const { 71 return !operator==(buf); 72 } 73 74 void SetData(const void* data, size_t length) { 75 ASSERT(data != NULL || length == 0); 76 SetLength(length); 77 memcpy(data_.get(), data, length); 78 } 79 void AppendData(const void* data, size_t length) { 80 ASSERT(data != NULL || length == 0); 81 size_t old_length = length_; 82 SetLength(length_ + length); 83 memcpy(data_.get() + old_length, data, length); 84 } 85 void SetLength(size_t length) { 86 SetCapacity(length); 87 length_ = length; 88 } 89 void SetCapacity(size_t capacity) { 90 if (capacity > capacity_) { 91 talk_base::scoped_ptr<char[]> data(new char[capacity]); 92 memcpy(data.get(), data_.get(), length_); 93 data_.swap(data); 94 capacity_ = capacity; 95 } 96 } 97 98 void TransferTo(Buffer* buf) { 99 ASSERT(buf != NULL); 100 buf->data_.reset(data_.release()); 101 buf->length_ = length_; 102 buf->capacity_ = capacity_; 103 Construct(NULL, 0, 0); 104 } 105 106 protected: 107 void Construct(const void* data, size_t length, size_t capacity) { 108 data_.reset(new char[capacity_ = capacity]); 109 SetData(data, length); 110 } 111 112 scoped_ptr<char[]> data_; 113 size_t length_; 114 size_t capacity_; 115 }; 116 117 } // namespace talk_base 118 119 #endif // TALK_BASE_BUFFER_H_ 120