databuffer.h (3585B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef databuffer_h__ 8 #define databuffer_h__ 9 10 #include <algorithm> 11 #include <cstdint> 12 #include <cstring> 13 #include <iomanip> 14 #include <iostream> 15 16 namespace nss_test { 17 18 class DataBuffer { 19 public: 20 DataBuffer() : data_(nullptr), len_(0) {} 21 DataBuffer(const uint8_t* d, size_t l) : data_(nullptr), len_(0) { 22 Assign(d, l); 23 } 24 DataBuffer(const DataBuffer& other) : data_(nullptr), len_(0) { 25 Assign(other); 26 } 27 explicit DataBuffer(size_t l) : data_(nullptr), len_(0) { Allocate(l); } 28 ~DataBuffer() { delete[] data_; } 29 30 DataBuffer& operator=(const DataBuffer& other) { 31 if (&other != this) { 32 Assign(other); 33 } 34 return *this; 35 } 36 DataBuffer& operator=(DataBuffer&& other) { 37 if (this != &other) { 38 delete[] data_; 39 data_ = other.data_; 40 len_ = other.len_; 41 other.data_ = nullptr; 42 other.len_ = 0; 43 } 44 return *this; 45 } 46 47 void Allocate(size_t l) { 48 delete[] data_; 49 data_ = new uint8_t[l ? l : 1](); // Don't depend on new [0]. 50 len_ = l; 51 } 52 53 void Truncate(size_t l) { len_ = (std::min)(len_, l); } 54 55 void Assign(const DataBuffer& other) { Assign(other.data(), other.len()); } 56 57 void Assign(const uint8_t* d, size_t l); 58 59 // Write will do a new allocation and expand the size of the buffer if needed. 60 // Returns the offset of the end of the write. 61 size_t Write(size_t index, const uint8_t* val, size_t count); 62 size_t Write(size_t index, const DataBuffer& buf) { 63 return Write(index, buf.data(), buf.len()); 64 } 65 66 // Write an integer, also performing host-to-network order conversion. 67 // Returns the offset of the end of the write. 68 size_t Write(size_t index, uint32_t val, size_t count); 69 70 // Starting at |index|, remove |remove| bytes and replace them with the 71 // contents of |buf|. 72 void Splice(const DataBuffer& buf, size_t index, size_t remove = 0) { 73 Splice(buf.data(), buf.len(), index, remove); 74 } 75 76 void Splice(const uint8_t* ins, size_t ins_len, size_t index, 77 size_t remove = 0); 78 void Append(const DataBuffer& buf) { Splice(buf, len_); } 79 80 bool Read(size_t index, size_t count, uint64_t* val) const; 81 bool Read(size_t index, size_t count, uint32_t* val) const; 82 83 const uint8_t* data() const { return data_; } 84 uint8_t* data() { return data_; } 85 size_t len() const { return len_; } 86 bool empty() const { return len_ == 0; } 87 88 static void SetLogLimit(size_t limit); 89 friend std::ostream& operator<<(std::ostream& stream, const DataBuffer& buf); 90 91 private: 92 static size_t logging_limit; 93 uint8_t* data_; 94 size_t len_; 95 }; 96 97 inline std::ostream& operator<<(std::ostream& stream, const DataBuffer& buf) { 98 stream << "[" << buf.len() << "] "; 99 for (size_t i = 0; i < buf.len(); ++i) { 100 if (i >= DataBuffer::logging_limit) { 101 stream << "..."; 102 break; 103 } 104 stream << std::hex << std::setfill('0') << std::setw(2) 105 << static_cast<unsigned>(buf.data()[i]); 106 } 107 stream << std::dec; 108 return stream; 109 } 110 111 inline bool operator==(const DataBuffer& a, const DataBuffer& b) { 112 return (a.empty() && b.empty()) || 113 (a.len() == b.len() && 0 == memcmp(a.data(), b.data(), a.len())); 114 } 115 116 inline bool operator!=(const DataBuffer& a, const DataBuffer& b) { 117 return !(a == b); 118 } 119 120 } // namespace nss_test 121 122 #endif