Coverage Report

Created: 2024-05-20 06:23

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