File indexing completed on 2025-08-27 08:47:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #pragma once
0019
0020 #include <cstdint>
0021 #include <cstring>
0022 #include <memory>
0023 #include <optional>
0024 #include <string>
0025 #include <string_view>
0026 #include <utility>
0027 #include <vector>
0028
0029 #include "arrow/device.h"
0030 #include "arrow/status.h"
0031 #include "arrow/type_fwd.h"
0032 #include "arrow/util/macros.h"
0033 #include "arrow/util/span.h"
0034 #include "arrow/util/visibility.h"
0035
0036 namespace arrow {
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 class ARROW_EXPORT Buffer {
0053 public:
0054 ARROW_DISALLOW_COPY_AND_ASSIGN(Buffer);
0055
0056
0057
0058
0059
0060
0061
0062 Buffer(const uint8_t* data, int64_t size)
0063 : is_mutable_(false),
0064 is_cpu_(true),
0065 data_(data),
0066 size_(size),
0067 capacity_(size),
0068 device_type_(DeviceAllocationType::kCPU) {
0069 SetMemoryManager(default_cpu_memory_manager());
0070 }
0071
0072 Buffer(const uint8_t* data, int64_t size, std::shared_ptr<MemoryManager> mm,
0073 std::shared_ptr<Buffer> parent = NULLPTR,
0074 std::optional<DeviceAllocationType> device_type_override = std::nullopt)
0075 : is_mutable_(false),
0076 data_(data),
0077 size_(size),
0078 capacity_(size),
0079 parent_(std::move(parent)) {
0080
0081 SetMemoryManager(std::move(mm));
0082
0083
0084
0085 if (device_type_override != std::nullopt) {
0086 device_type_ = *device_type_override;
0087 }
0088 }
0089
0090 Buffer(uintptr_t address, int64_t size, std::shared_ptr<MemoryManager> mm,
0091 std::shared_ptr<Buffer> parent = NULLPTR)
0092 : Buffer(reinterpret_cast<const uint8_t*>(address), size, std::move(mm),
0093 std::move(parent)) {}
0094
0095
0096
0097
0098
0099
0100
0101 explicit Buffer(std::string_view data)
0102 : Buffer(reinterpret_cast<const uint8_t*>(data.data()),
0103 static_cast<int64_t>(data.size())) {}
0104
0105 virtual ~Buffer() = default;
0106
0107
0108
0109
0110
0111
0112
0113
0114 Buffer(const std::shared_ptr<Buffer>& parent, const int64_t offset, const int64_t size)
0115 : Buffer(parent->data_ + offset, size) {
0116 parent_ = parent;
0117 SetMemoryManager(parent->memory_manager_);
0118 }
0119
0120 uint8_t operator[](std::size_t i) const { return data_[i]; }
0121
0122
0123
0124 std::string ToHexString();
0125
0126
0127
0128 bool Equals(const Buffer& other, int64_t nbytes) const;
0129
0130
0131 bool Equals(const Buffer& other) const;
0132
0133
0134 Result<std::shared_ptr<Buffer>> CopySlice(
0135 const int64_t start, const int64_t nbytes,
0136 MemoryPool* pool = default_memory_pool()) const;
0137
0138
0139 void ZeroPadding() {
0140 #ifndef NDEBUG
0141 CheckMutable();
0142 #endif
0143
0144 if (capacity_ != 0) {
0145 memset(mutable_data() + size_, 0, static_cast<size_t>(capacity_ - size_));
0146 }
0147 }
0148
0149
0150
0151
0152
0153
0154 static std::shared_ptr<Buffer> FromString(std::string data);
0155
0156
0157
0158
0159
0160
0161
0162 template <typename T>
0163 static std::shared_ptr<Buffer> FromVector(std::vector<T> vec) {
0164 static_assert(std::is_trivial_v<T>,
0165 "Buffer::FromVector can only wrap vectors of trivial objects");
0166
0167 if (vec.empty()) {
0168 return std::shared_ptr<Buffer>{new Buffer()};
0169 }
0170
0171 auto* data = reinterpret_cast<uint8_t*>(vec.data());
0172 auto size_in_bytes = static_cast<int64_t>(vec.size() * sizeof(T));
0173 return std::shared_ptr<Buffer>{
0174 new Buffer{data, size_in_bytes},
0175
0176
0177
0178
0179 [vec = std::move(vec)](Buffer* buffer) { delete buffer; }};
0180 }
0181
0182
0183
0184
0185
0186
0187 template <typename T, typename SizeType = int64_t>
0188 static std::shared_ptr<Buffer> Wrap(const T* data, SizeType length) {
0189 return std::make_shared<Buffer>(reinterpret_cast<const uint8_t*>(data),
0190 static_cast<int64_t>(sizeof(T) * length));
0191 }
0192
0193
0194
0195
0196
0197
0198 template <typename T>
0199 static std::shared_ptr<Buffer> Wrap(const std::vector<T>& data) {
0200 return std::make_shared<Buffer>(reinterpret_cast<const uint8_t*>(data.data()),
0201 static_cast<int64_t>(sizeof(T) * data.size()));
0202 }
0203
0204
0205
0206
0207 std::string ToString() const;
0208
0209
0210
0211 explicit operator std::string_view() const {
0212 return {reinterpret_cast<const char*>(data_), static_cast<size_t>(size_)};
0213 }
0214
0215
0216
0217
0218
0219
0220
0221 const uint8_t* data() const {
0222 #ifndef NDEBUG
0223 CheckCPU();
0224 #endif
0225 return ARROW_PREDICT_TRUE(is_cpu_) ? data_ : NULLPTR;
0226 }
0227
0228
0229
0230
0231
0232 template <typename T>
0233 const T* data_as() const {
0234 return reinterpret_cast<const T*>(data());
0235 }
0236
0237
0238 template <typename T>
0239 util::span<const T> span_as() const {
0240 return util::span(data_as<T>(), static_cast<size_t>(size() / sizeof(T)));
0241 }
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 uint8_t* mutable_data() {
0252 #ifndef NDEBUG
0253 CheckCPU();
0254 CheckMutable();
0255 #endif
0256 return ARROW_PREDICT_TRUE(is_cpu_ && is_mutable_) ? const_cast<uint8_t*>(data_)
0257 : NULLPTR;
0258 }
0259
0260
0261
0262
0263
0264
0265 template <typename T>
0266 T* mutable_data_as() {
0267 return reinterpret_cast<T*>(mutable_data());
0268 }
0269
0270
0271 template <typename T>
0272 util::span<T> mutable_span_as() {
0273 return util::span(mutable_data_as<T>(), static_cast<size_t>(size() / sizeof(T)));
0274 }
0275
0276
0277 uintptr_t address() const { return reinterpret_cast<uintptr_t>(data_); }
0278
0279
0280
0281
0282
0283 uintptr_t mutable_address() const {
0284 #ifndef NDEBUG
0285 CheckMutable();
0286 #endif
0287 return ARROW_PREDICT_TRUE(is_mutable_) ? reinterpret_cast<uintptr_t>(data_) : 0;
0288 }
0289
0290
0291 int64_t size() const { return size_; }
0292
0293
0294 int64_t capacity() const { return capacity_; }
0295
0296
0297
0298
0299
0300 bool is_cpu() const { return is_cpu_; }
0301
0302
0303
0304
0305
0306 bool is_mutable() const { return is_mutable_; }
0307
0308 const std::shared_ptr<Device>& device() const { return memory_manager_->device(); }
0309
0310 const std::shared_ptr<MemoryManager>& memory_manager() const { return memory_manager_; }
0311
0312 DeviceAllocationType device_type() const { return device_type_; }
0313
0314 std::shared_ptr<Buffer> parent() const { return parent_; }
0315
0316
0317
0318
0319 static Result<std::shared_ptr<io::RandomAccessFile>> GetReader(std::shared_ptr<Buffer>);
0320
0321
0322
0323
0324
0325 static Result<std::shared_ptr<io::OutputStream>> GetWriter(std::shared_ptr<Buffer>);
0326
0327
0328
0329
0330
0331 static Result<std::shared_ptr<Buffer>> Copy(std::shared_ptr<Buffer> source,
0332 const std::shared_ptr<MemoryManager>& to);
0333
0334
0335
0336
0337
0338 static Result<std::unique_ptr<Buffer>> CopyNonOwned(
0339 const Buffer& source, const std::shared_ptr<MemoryManager>& to);
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 static Result<std::shared_ptr<Buffer>> View(std::shared_ptr<Buffer> source,
0353 const std::shared_ptr<MemoryManager>& to);
0354
0355
0356
0357
0358
0359 static Result<std::shared_ptr<Buffer>> ViewOrCopy(
0360 std::shared_ptr<Buffer> source, const std::shared_ptr<MemoryManager>& to);
0361
0362 virtual std::shared_ptr<Device::SyncEvent> device_sync_event() const { return NULLPTR; }
0363
0364 protected:
0365 bool is_mutable_;
0366 bool is_cpu_;
0367 const uint8_t* data_;
0368 int64_t size_;
0369 int64_t capacity_;
0370 DeviceAllocationType device_type_;
0371
0372
0373 std::shared_ptr<Buffer> parent_;
0374
0375 private:
0376
0377 std::shared_ptr<MemoryManager> memory_manager_;
0378
0379 protected:
0380 Buffer();
0381
0382 void CheckMutable() const;
0383 void CheckCPU() const;
0384
0385 void SetMemoryManager(std::shared_ptr<MemoryManager> mm) {
0386 memory_manager_ = std::move(mm);
0387 is_cpu_ = memory_manager_->is_cpu();
0388 device_type_ = memory_manager_->device()->device_type();
0389 }
0390 };
0391
0392
0393
0394
0395
0396
0397
0398
0399 static inline std::shared_ptr<Buffer> SliceBuffer(const std::shared_ptr<Buffer>& buffer,
0400 const int64_t offset,
0401 const int64_t length) {
0402 return std::make_shared<Buffer>(buffer, offset, length);
0403 }
0404
0405
0406
0407
0408 static inline std::shared_ptr<Buffer> SliceBuffer(const std::shared_ptr<Buffer>& buffer,
0409 const int64_t offset) {
0410 int64_t length = buffer->size() - offset;
0411 return SliceBuffer(buffer, offset, length);
0412 }
0413
0414
0415
0416
0417 ARROW_EXPORT
0418 Result<std::shared_ptr<Buffer>> SliceBufferSafe(const std::shared_ptr<Buffer>& buffer,
0419 int64_t offset);
0420
0421
0422
0423
0424 ARROW_EXPORT
0425 Result<std::shared_ptr<Buffer>> SliceBufferSafe(const std::shared_ptr<Buffer>& buffer,
0426 int64_t offset, int64_t length);
0427
0428
0429
0430
0431
0432 ARROW_EXPORT
0433 std::shared_ptr<Buffer> SliceMutableBuffer(const std::shared_ptr<Buffer>& buffer,
0434 const int64_t offset, const int64_t length);
0435
0436
0437
0438
0439
0440 static inline std::shared_ptr<Buffer> SliceMutableBuffer(
0441 const std::shared_ptr<Buffer>& buffer, const int64_t offset) {
0442 int64_t length = buffer->size() - offset;
0443 return SliceMutableBuffer(buffer, offset, length);
0444 }
0445
0446
0447
0448
0449 ARROW_EXPORT
0450 Result<std::shared_ptr<Buffer>> SliceMutableBufferSafe(
0451 const std::shared_ptr<Buffer>& buffer, int64_t offset);
0452
0453
0454
0455
0456 ARROW_EXPORT
0457 Result<std::shared_ptr<Buffer>> SliceMutableBufferSafe(
0458 const std::shared_ptr<Buffer>& buffer, int64_t offset, int64_t length);
0459
0460
0461
0462
0463
0464 class ARROW_EXPORT MutableBuffer : public Buffer {
0465 public:
0466 MutableBuffer(uint8_t* data, const int64_t size) : Buffer(data, size) {
0467 is_mutable_ = true;
0468 }
0469
0470 MutableBuffer(uint8_t* data, const int64_t size, std::shared_ptr<MemoryManager> mm)
0471 : Buffer(data, size, std::move(mm)) {
0472 is_mutable_ = true;
0473 }
0474
0475 MutableBuffer(const std::shared_ptr<Buffer>& parent, const int64_t offset,
0476 const int64_t size);
0477
0478
0479
0480
0481
0482 template <typename T, typename SizeType = int64_t>
0483 static std::shared_ptr<Buffer> Wrap(T* data, SizeType length) {
0484 return std::make_shared<MutableBuffer>(reinterpret_cast<uint8_t*>(data),
0485 static_cast<int64_t>(sizeof(T) * length));
0486 }
0487
0488 protected:
0489 MutableBuffer() : Buffer(NULLPTR, 0) {}
0490 };
0491
0492
0493
0494 class ARROW_EXPORT ResizableBuffer : public MutableBuffer {
0495 public:
0496
0497
0498
0499
0500
0501
0502
0503
0504 virtual Status Resize(const int64_t new_size, bool shrink_to_fit) = 0;
0505 Status Resize(const int64_t new_size) {
0506 return Resize(new_size, true);
0507 }
0508
0509
0510
0511
0512 virtual Status Reserve(const int64_t new_capacity) = 0;
0513
0514 template <class T>
0515 Status TypedResize(const int64_t new_nb_elements, bool shrink_to_fit = true) {
0516 return Resize(sizeof(T) * new_nb_elements, shrink_to_fit);
0517 }
0518
0519 template <class T>
0520 Status TypedReserve(const int64_t new_nb_elements) {
0521 return Reserve(sizeof(T) * new_nb_elements);
0522 }
0523
0524 protected:
0525 ResizableBuffer(uint8_t* data, int64_t size) : MutableBuffer(data, size) {}
0526 ResizableBuffer(uint8_t* data, int64_t size, std::shared_ptr<MemoryManager> mm)
0527 : MutableBuffer(data, size, std::move(mm)) {}
0528 };
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538 ARROW_EXPORT
0539 Result<std::unique_ptr<Buffer>> AllocateBuffer(const int64_t size,
0540 MemoryPool* pool = NULLPTR);
0541 ARROW_EXPORT
0542 Result<std::unique_ptr<Buffer>> AllocateBuffer(const int64_t size, int64_t alignment,
0543 MemoryPool* pool = NULLPTR);
0544
0545
0546
0547
0548
0549 ARROW_EXPORT
0550 Result<std::unique_ptr<ResizableBuffer>> AllocateResizableBuffer(
0551 const int64_t size, MemoryPool* pool = NULLPTR);
0552 ARROW_EXPORT
0553 Result<std::unique_ptr<ResizableBuffer>> AllocateResizableBuffer(
0554 const int64_t size, const int64_t alignment, MemoryPool* pool = NULLPTR);
0555
0556
0557
0558
0559
0560
0561 ARROW_EXPORT
0562 Result<std::shared_ptr<Buffer>> AllocateBitmap(int64_t length,
0563 MemoryPool* pool = NULLPTR);
0564
0565
0566
0567
0568
0569 ARROW_EXPORT
0570 Result<std::shared_ptr<Buffer>> AllocateEmptyBitmap(int64_t length,
0571 MemoryPool* pool = NULLPTR);
0572
0573 ARROW_EXPORT
0574 Result<std::shared_ptr<Buffer>> AllocateEmptyBitmap(int64_t length, int64_t alignment,
0575 MemoryPool* pool = NULLPTR);
0576
0577
0578
0579
0580
0581 ARROW_EXPORT
0582 Result<std::shared_ptr<Buffer>> ConcatenateBuffers(const BufferVector& buffers,
0583 MemoryPool* pool = NULLPTR);
0584
0585
0586
0587 }