Skip to content

Commit 58e4875

Browse files
committed
Add Slice, Copy methods to Buffer
Change-Id: Ia6f232bf020a0249c19453a2c39eea51b52f86cf
1 parent 73d35e7 commit 58e4875

File tree

3 files changed

+85
-5
lines changed

3 files changed

+85
-5
lines changed

cpp/src/arrow/util/buffer-test.cc

+41
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ namespace arrow {
3131

3232
class TestBuffer : public ::testing::Test {};
3333

34+
TEST_F(TestBuffer, IsMutableFlag) {
35+
Buffer buf(nullptr, 0);
36+
37+
ASSERT_FALSE(buf.is_mutable());
38+
39+
MutableBuffer mbuf(nullptr, 0);
40+
ASSERT_TRUE(mbuf.is_mutable());
41+
42+
PoolBuffer pbuf;
43+
ASSERT_TRUE(pbuf.is_mutable());
44+
}
45+
3446
TEST_F(TestBuffer, Resize) {
3547
PoolBuffer buf;
3648

@@ -96,4 +108,33 @@ TEST_F(TestBuffer, EqualsWithSameBuffer) {
96108
pool->Free(rawBuffer, bufferSize);
97109
}
98110

111+
TEST_F(TestBuffer, Copy) {
112+
std::string data_str = "some data to copy";
113+
114+
auto data = reinterpret_cast<const uint8_t*>(data_str.c_str());
115+
116+
Buffer buf(data, data_str.size());
117+
118+
std::shared_ptr<Buffer> out;
119+
120+
ASSERT_OK(buf.Copy(5, 4, &out));
121+
122+
Buffer expected(data + 5, 4);
123+
ASSERT_TRUE(out->Equals(expected));
124+
}
125+
126+
TEST_F(TestBuffer, SliceBuffer) {
127+
std::string data_str = "some data to slice";
128+
129+
auto data = reinterpret_cast<const uint8_t*>(data_str.c_str());
130+
131+
auto buf = std::make_shared<Buffer>(data, data_str.size());
132+
133+
std::shared_ptr<Buffer> out = SliceBuffer(buf, 5, 4);
134+
Buffer expected(data + 5, 4);
135+
ASSERT_TRUE(out->Equals(expected));
136+
137+
ASSERT_EQ(2, buf.use_count());
138+
}
139+
99140
} // namespace arrow

cpp/src/arrow/util/buffer.cc

+26
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,32 @@ Buffer::Buffer(const std::shared_ptr<Buffer>& parent, int64_t offset, int64_t si
3636

3737
Buffer::~Buffer() {}
3838

39+
Status Buffer::Copy(
40+
int64_t start, int64_t nbytes, MemoryPool* pool, std::shared_ptr<Buffer>* out) const {
41+
// Sanity checks
42+
DCHECK_LT(start, size_);
43+
DCHECK_LE(nbytes, size_ - start);
44+
45+
auto new_buffer = std::make_shared<PoolBuffer>(pool);
46+
RETURN_NOT_OK(new_buffer->Resize(nbytes));
47+
48+
std::memcpy(new_buffer->mutable_data(), data() + start, nbytes);
49+
50+
*out = new_buffer;
51+
return Status::OK();
52+
}
53+
54+
Status Buffer::Copy(int64_t start, int64_t nbytes, std::shared_ptr<Buffer>* out) const {
55+
return Copy(start, nbytes, default_memory_pool(), out);
56+
}
57+
58+
std::shared_ptr<Buffer> SliceBuffer(
59+
const std::shared_ptr<Buffer>& buffer, int64_t offset, int64_t length) {
60+
DCHECK_LT(offset, buffer->size());
61+
DCHECK_LE(length, buffer->size() - offset);
62+
return std::make_shared<Buffer>(buffer, offset, length);
63+
}
64+
3965
std::shared_ptr<Buffer> MutableBuffer::GetImmutableView() {
4066
return std::make_shared<Buffer>(this->get_shared_ptr(), 0, size());
4167
}

cpp/src/arrow/util/buffer.h

+18-5
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class Status;
4343
// The following invariant is always true: Size < Capacity
4444
class ARROW_EXPORT Buffer : public std::enable_shared_from_this<Buffer> {
4545
public:
46-
Buffer(const uint8_t* data, int64_t size) : data_(data), size_(size), capacity_(size) {}
46+
Buffer(const uint8_t* data, int64_t size)
47+
: is_mutable_(false), data_(data), size_(size), capacity_(size) {}
4748
virtual ~Buffer();
4849

4950
// An offset into data that is owned by another buffer, but we want to be
@@ -57,6 +58,8 @@ class ARROW_EXPORT Buffer : public std::enable_shared_from_this<Buffer> {
5758

5859
std::shared_ptr<Buffer> get_shared_ptr() { return shared_from_this(); }
5960

61+
bool is_mutable() const { return is_mutable_; }
62+
6063
// Return true if both buffers are the same size and contain the same bytes
6164
// up to the number of compared bytes
6265
bool Equals(const Buffer& other, int64_t nbytes) const {
@@ -71,18 +74,22 @@ class ARROW_EXPORT Buffer : public std::enable_shared_from_this<Buffer> {
7174
(data_ == other.data_ || !memcmp(data_, other.data_, size_)));
7275
}
7376

77+
// Copy section of buffer into a new Buffer
78+
Status Copy(int64_t start, int64_t nbytes, MemoryPool* pool,
79+
std::shared_ptr<Buffer>* out) const;
80+
81+
// Default memory pool
82+
Status Copy(int64_t start, int64_t nbytes, std::shared_ptr<Buffer>* out) const;
83+
7484
int64_t capacity() const { return capacity_; }
7585
const uint8_t* data() const { return data_; }
7686

7787
int64_t size() const { return size_; }
7888

79-
// Returns true if this Buffer is referencing memory (possibly) owned by some
80-
// other buffer
81-
bool is_shared() const { return static_cast<bool>(parent_); }
82-
8389
const std::shared_ptr<Buffer> parent() const { return parent_; }
8490

8591
protected:
92+
bool is_mutable_;
8693
const uint8_t* data_;
8794
int64_t size_;
8895
int64_t capacity_;
@@ -94,10 +101,16 @@ class ARROW_EXPORT Buffer : public std::enable_shared_from_this<Buffer> {
94101
DISALLOW_COPY_AND_ASSIGN(Buffer);
95102
};
96103

104+
// Construct a view on passed buffer at the indicated offset and length. This
105+
// function cannot fail and does not error checking (except in debug builds)
106+
std::shared_ptr<Buffer> SliceBuffer(
107+
const std::shared_ptr<Buffer>& buffer, int64_t offset, int64_t length);
108+
97109
// A Buffer whose contents can be mutated. May or may not own its data.
98110
class ARROW_EXPORT MutableBuffer : public Buffer {
99111
public:
100112
MutableBuffer(uint8_t* data, int64_t size) : Buffer(data, size) {
113+
is_mutable_ = true;
101114
mutable_data_ = data;
102115
}
103116

0 commit comments

Comments
 (0)