tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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