Coverage Report

Created: 2023-01-07 15:25

/src/arrow/cpp/src/arrow/buffer.cc
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "arrow/buffer.h"
19
20
#include <algorithm>
21
#include <cstdint>
22
#include <utility>
23
24
#include "arrow/result.h"
25
#include "arrow/status.h"
26
#include "arrow/util/bit_util.h"
27
#include "arrow/util/logging.h"
28
#include "arrow/util/slice_util_internal.h"
29
#include "arrow/util/string.h"
30
31
namespace arrow {
32
33
Result<std::shared_ptr<Buffer>> Buffer::CopySlice(const int64_t start,
34
                                                  const int64_t nbytes,
35
1
                                                  MemoryPool* pool) const {
36
  // Sanity checks
37
1
  ARROW_CHECK_LE(start, size_);
38
1
  ARROW_CHECK_LE(nbytes, size_ - start);
39
1
  DCHECK_GE(nbytes, 0);
40
41
1
  ARROW_ASSIGN_OR_RAISE(auto new_buffer, AllocateResizableBuffer(nbytes, pool));
42
1
  std::memcpy(new_buffer->mutable_data(), data() + start, static_cast<size_t>(nbytes));
43
1
  return std::move(new_buffer);
44
1
}
45
46
namespace {
47
48
0
Status CheckBufferSlice(const Buffer& buffer, int64_t offset, int64_t length) {
49
0
  return internal::CheckSliceParams(buffer.size(), offset, length, "buffer");
50
0
}
51
52
0
Status CheckBufferSlice(const Buffer& buffer, int64_t offset) {
53
0
  if (ARROW_PREDICT_FALSE(offset < 0)) {
54
    // Avoid UBSAN in subtraction below
55
0
    return Status::IndexError("Negative buffer slice offset");
56
0
  }
57
0
  return CheckBufferSlice(buffer, offset, buffer.size() - offset);
58
0
}
59
60
}  // namespace
61
62
Result<std::shared_ptr<Buffer>> SliceBufferSafe(const std::shared_ptr<Buffer>& buffer,
63
0
                                                int64_t offset) {
64
0
  RETURN_NOT_OK(CheckBufferSlice(*buffer, offset));
65
0
  return SliceBuffer(buffer, offset);
66
0
}
67
68
Result<std::shared_ptr<Buffer>> SliceBufferSafe(const std::shared_ptr<Buffer>& buffer,
69
0
                                                int64_t offset, int64_t length) {
70
0
  RETURN_NOT_OK(CheckBufferSlice(*buffer, offset, length));
71
0
  return SliceBuffer(buffer, offset, length);
72
0
}
73
74
Result<std::shared_ptr<Buffer>> SliceMutableBufferSafe(
75
0
    const std::shared_ptr<Buffer>& buffer, int64_t offset) {
76
0
  RETURN_NOT_OK(CheckBufferSlice(*buffer, offset));
77
0
  return SliceMutableBuffer(buffer, offset);
78
0
}
79
80
Result<std::shared_ptr<Buffer>> SliceMutableBufferSafe(
81
0
    const std::shared_ptr<Buffer>& buffer, int64_t offset, int64_t length) {
82
0
  RETURN_NOT_OK(CheckBufferSlice(*buffer, offset, length));
83
0
  return SliceMutableBuffer(buffer, offset, length);
84
0
}
85
86
0
std::string Buffer::ToHexString() {
87
0
  return HexEncode(data(), static_cast<size_t>(size()));
88
0
}
89
90
0
bool Buffer::Equals(const Buffer& other, const int64_t nbytes) const {
91
0
  return this == &other || (size_ >= nbytes && other.size_ >= nbytes &&
92
0
                            (data_ == other.data_ ||
93
0
                             !memcmp(data_, other.data_, static_cast<size_t>(nbytes))));
94
0
}
95
96
0
bool Buffer::Equals(const Buffer& other) const {
97
0
  return this == &other || (size_ == other.size_ &&
98
0
                            (data_ == other.data_ ||
99
0
                             !memcmp(data_, other.data_, static_cast<size_t>(size_))));
100
0
}
101
102
0
std::string Buffer::ToString() const {
103
0
  return std::string(reinterpret_cast<const char*>(data_), static_cast<size_t>(size_));
104
0
}
105
106
0
void Buffer::CheckMutable() const { DCHECK(is_mutable()) << "buffer not mutable"; }
107
108
0
void Buffer::CheckCPU() const {
109
0
  DCHECK(is_cpu()) << "not a CPU buffer (device: " << device()->ToString() << ")";
110
0
}
111
112
Result<std::shared_ptr<io::RandomAccessFile>> Buffer::GetReader(
113
0
    std::shared_ptr<Buffer> buf) {
114
0
  return buf->memory_manager_->GetBufferReader(buf);
115
0
}
116
117
0
Result<std::shared_ptr<io::OutputStream>> Buffer::GetWriter(std::shared_ptr<Buffer> buf) {
118
0
  if (!buf->is_mutable()) {
119
0
    return Status::Invalid("Expected mutable buffer");
120
0
  }
121
0
  return buf->memory_manager_->GetBufferWriter(buf);
122
0
}
123
124
Result<std::shared_ptr<Buffer>> Buffer::Copy(std::shared_ptr<Buffer> source,
125
0
                                             const std::shared_ptr<MemoryManager>& to) {
126
0
  return MemoryManager::CopyBuffer(source, to);
127
0
}
128
129
Result<std::unique_ptr<Buffer>> Buffer::CopyNonOwned(
130
0
    const Buffer& source, const std::shared_ptr<MemoryManager>& to) {
131
0
  return MemoryManager::CopyNonOwned(source, to);
132
0
}
133
134
Result<std::shared_ptr<Buffer>> Buffer::View(std::shared_ptr<Buffer> source,
135
0
                                             const std::shared_ptr<MemoryManager>& to) {
136
0
  return MemoryManager::ViewBuffer(source, to);
137
0
}
138
139
Result<std::shared_ptr<Buffer>> Buffer::ViewOrCopy(
140
0
    std::shared_ptr<Buffer> source, const std::shared_ptr<MemoryManager>& to) {
141
0
  auto maybe_buffer = MemoryManager::ViewBuffer(source, to);
142
0
  if (maybe_buffer.ok()) {
143
0
    return maybe_buffer;
144
0
  }
145
0
  return MemoryManager::CopyBuffer(source, to);
146
0
}
147
148
class StlStringBuffer : public Buffer {
149
 public:
150
  explicit StlStringBuffer(std::string data)
151
0
      : Buffer(nullptr, 0), input_(std::move(data)) {
152
0
    data_ = reinterpret_cast<const uint8_t*>(input_.c_str());
153
0
    size_ = static_cast<int64_t>(input_.size());
154
0
    capacity_ = size_;
155
0
  }
156
157
 private:
158
  std::string input_;
159
};
160
161
0
std::shared_ptr<Buffer> Buffer::FromString(std::string data) {
162
0
  return std::make_shared<StlStringBuffer>(std::move(data));
163
0
}
164
165
std::shared_ptr<Buffer> SliceMutableBuffer(const std::shared_ptr<Buffer>& buffer,
166
0
                                           const int64_t offset, const int64_t length) {
167
0
  return std::make_shared<MutableBuffer>(buffer, offset, length);
168
0
}
169
170
MutableBuffer::MutableBuffer(const std::shared_ptr<Buffer>& parent, const int64_t offset,
171
                             const int64_t size)
172
    : MutableBuffer(reinterpret_cast<uint8_t*>(parent->mutable_address()) + offset,
173
0
                    size) {
174
0
  DCHECK(parent->is_mutable()) << "Must pass mutable buffer";
175
0
  parent_ = parent;
176
0
}
177
178
0
Result<std::shared_ptr<Buffer>> AllocateBitmap(int64_t length, MemoryPool* pool) {
179
0
  ARROW_ASSIGN_OR_RAISE(auto buf, AllocateBuffer(bit_util::BytesForBits(length), pool));
180
  // Zero out any trailing bits
181
0
  if (buf->size() > 0) {
182
0
    buf->mutable_data()[buf->size() - 1] = 0;
183
0
  }
184
0
  return std::move(buf);
185
0
}
186
187
0
Result<std::shared_ptr<Buffer>> AllocateEmptyBitmap(int64_t length, MemoryPool* pool) {
188
0
  return AllocateEmptyBitmap(length, kDefaultBufferAlignment, pool);
189
0
}
190
191
Result<std::shared_ptr<Buffer>> AllocateEmptyBitmap(int64_t length, int64_t alignment,
192
0
                                                    MemoryPool* pool) {
193
0
  ARROW_ASSIGN_OR_RAISE(auto buf,
194
0
                        AllocateBuffer(bit_util::BytesForBits(length), alignment, pool));
195
0
  memset(buf->mutable_data(), 0, static_cast<size_t>(buf->size()));
196
0
  return std::move(buf);
197
0
}
198
199
0
Status AllocateEmptyBitmap(int64_t length, std::shared_ptr<Buffer>* out) {
200
0
  return AllocateEmptyBitmap(length).Value(out);
201
0
}
202
203
Result<std::shared_ptr<Buffer>> ConcatenateBuffers(
204
0
    const std::vector<std::shared_ptr<Buffer>>& buffers, MemoryPool* pool) {
205
0
  int64_t out_length = 0;
206
0
  for (const auto& buffer : buffers) {
207
0
    out_length += buffer->size();
208
0
  }
209
0
  ARROW_ASSIGN_OR_RAISE(auto out, AllocateBuffer(out_length, pool));
210
0
  auto out_data = out->mutable_data();
211
0
  for (const auto& buffer : buffers) {
212
0
    std::memcpy(out_data, buffer->data(), buffer->size());
213
0
    out_data += buffer->size();
214
0
  }
215
0
  return std::move(out);
216
0
}
217
218
}  // namespace arrow