tor-browser

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

databuffer.cc (3581B)


      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 #include "databuffer.h"
      8 #include <algorithm>
      9 #include <cassert>
     10 #include <cstring>
     11 #include <iomanip>
     12 #include <iostream>
     13 #if defined(WIN32) || defined(WIN64)
     14 #include <winsock2.h>
     15 #else
     16 #include <arpa/inet.h>
     17 #endif
     18 
     19 namespace nss_test {
     20 
     21 void DataBuffer::Assign(const uint8_t* d, size_t l) {
     22  if (d) {
     23    Allocate(l);
     24    memcpy(static_cast<void*>(data_), static_cast<const void*>(d), l);
     25  } else {
     26    assert(l == 0);
     27    data_ = nullptr;
     28    len_ = 0;
     29  }
     30 }
     31 
     32 // Write will do a new allocation and expand the size of the buffer if needed.
     33 // Returns the offset of the end of the write.
     34 size_t DataBuffer::Write(size_t index, const uint8_t* val, size_t count) {
     35  assert(val);
     36  if (index + count > len_) {
     37    size_t newlen = index + count;
     38    uint8_t* tmp = new uint8_t[newlen];  // Always > 0.
     39    if (data_) {
     40      memcpy(static_cast<void*>(tmp), static_cast<const void*>(data_), len_);
     41    }
     42    if (index > len_) {
     43      memset(static_cast<void*>(tmp + len_), 0, index - len_);
     44    }
     45    delete[] data_;
     46    data_ = tmp;
     47    len_ = newlen;
     48  }
     49  if (data_) {
     50    memcpy(static_cast<void*>(data_ + index), static_cast<const void*>(val),
     51           count);
     52  }
     53  return index + count;
     54 }
     55 
     56 // Write an integer, also performing host-to-network order conversion.
     57 // Returns the offset of the end of the write.
     58 size_t DataBuffer::Write(size_t index, uint32_t val, size_t count) {
     59  assert(count <= sizeof(uint32_t));
     60  uint32_t nvalue = htonl(val);
     61  auto* addr = reinterpret_cast<const uint8_t*>(&nvalue);
     62  return Write(index, addr + sizeof(uint32_t) - count, count);
     63 }
     64 
     65 void DataBuffer::Splice(const uint8_t* ins, size_t ins_len, size_t index,
     66                        size_t remove) {
     67  assert(ins);
     68  uint8_t* old_value = data_;
     69  size_t old_len = len_;
     70 
     71  // The amount of stuff remaining from the tail of the old.
     72  size_t tail_len = old_len - (std::min)(old_len, index + remove);
     73  // The new length: the head of the old, the new, and the tail of the old.
     74  len_ = index + ins_len + tail_len;
     75  data_ = new uint8_t[len_ ? len_ : 1];
     76 
     77  // The head of the old.
     78  if (old_value) {
     79    Write(0, old_value, (std::min)(old_len, index));
     80  }
     81  // Maybe a gap.
     82  if (old_value && index > old_len) {
     83    memset(old_value + index, 0, index - old_len);
     84  }
     85  // The new.
     86  Write(index, ins, ins_len);
     87  // The tail of the old.
     88  if (tail_len > 0) {
     89    Write(index + ins_len, old_value + index + remove, tail_len);
     90  }
     91 
     92  delete[] old_value;
     93 }
     94 
     95 // This can't use the same trick as Write(), since we might be reading from a
     96 // smaller data source.
     97 bool DataBuffer::Read(size_t index, size_t count, uint64_t* val) const {
     98  assert(count <= sizeof(uint64_t));
     99  assert(val);
    100  if ((index > len()) || (count > (len() - index))) {
    101    return false;
    102  }
    103  *val = 0;
    104  for (size_t i = 0; i < count; ++i) {
    105    *val = (*val << 8) | data()[index + i];
    106  }
    107  return true;
    108 }
    109 
    110 bool DataBuffer::Read(size_t index, size_t count, uint32_t* val) const {
    111  assert(count <= sizeof(uint32_t));
    112  uint64_t tmp;
    113 
    114  if (!Read(index, count, &tmp)) {
    115    return false;
    116  }
    117  *val = tmp & 0xffffffff;
    118  return true;
    119 }
    120 
    121 size_t DataBuffer::logging_limit = 32;
    122 
    123 /* static */ void DataBuffer::SetLogLimit(size_t limit) {
    124  DataBuffer::logging_limit = limit;
    125 }
    126 
    127 }  // namespace nss_test