From a74d4f0dc27a0dc115e25b650cc65fdead00f3a2 Mon Sep 17 00:00:00 2001 From: dkp116 Date: Fri, 3 Jul 2026 22:41:48 +0100 Subject: [PATCH 1/5] [C++] added get Span function for ArrayData --- cpp/src/arrow/array/data.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/cpp/src/arrow/array/data.h b/cpp/src/arrow/array/data.h index 92308e8a010f..573ded629124 100644 --- a/cpp/src/arrow/array/data.h +++ b/cpp/src/arrow/array/data.h @@ -256,6 +256,37 @@ struct ARROW_EXPORT ArrayData { return NULLPTR; } } +/// \brief Access a buffer's data as a span + /// + /// \param i The buffer index + /// \param length The required length (in number of typed values) of the requested span + /// \pre i > 0 + /// \pre length <= the length of the buffer (in number of values) that's expected for + /// this array type + /// \return A span of the requested length + template + std::span GetSpan(int i, int64_t length) const { + const int64_t buffer_length = buffers[i]->size() / static_cast(sizeof(T)); + assert(i > 0 && length + offset <= buffer_length); + ARROW_UNUSED(buffer_length); + return std::span(buffers[i]->data_as() + this->offset, length); + } + + /// \brief Access a buffer's data as a span + /// + /// \param i The buffer index + /// \param length The required length (in number of typed values) of the requested span + /// \pre i > 0 + /// \pre length <= the length of the buffer (in number of values) that's expected for + /// this array type + /// \return A span of the requested length + template + std::span GetMutableSpan(int i, int64_t length) { + const int64_t buffer_length = buffers[i]->size() / static_cast(sizeof(T)); + assert(i > 0 && length + offset <= buffer_length); + ARROW_UNUSED(buffer_length); + return std::span(buffers[i]->mutable_data_as() + this->offset, length); + } /// \brief Access a buffer's data as a typed C pointer /// From ac3467749c7ddbf7b7529920e9fb746bebbf5740 Mon Sep 17 00:00:00 2001 From: dkp116 Date: Sat, 4 Jul 2026 22:05:12 +0100 Subject: [PATCH 2/5] [C++] added unit test for ArrayData member function GetSpan --- cpp/src/arrow/array/array_test.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index dcfe1c76c301..51d81c7f2405 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -1137,6 +1137,18 @@ TEST_F(TestArray, TestBinaryViewAppendArraySlice) { AssertArraysEqual(*src, *dst); } +TEST_F(TestArray, GetSpanRespectsOffset) { + auto data_buffer = Buffer::FromString("123456789abcdef0"); + + auto data = ArrayData::Make(uint8(), 3, {nullptr, data_buffer}, 0, 1); + + auto span = data->GetSpan(1, 3); + + EXPECT_EQ(span.size(), 3); + EXPECT_EQ(span[0], '2'); + EXPECT_EQ(span[1], '3'); + EXPECT_EQ(span[2], '4'); +} TEST_F(TestArray, ValidateBuffersPrimitive) { auto empty_buffer = std::make_shared(""); From cef9fb15f76f23a05f7d0ad60113d9bc8b36b3d2 Mon Sep 17 00:00:00 2001 From: dkp116 Date: Sat, 4 Jul 2026 22:34:54 +0100 Subject: [PATCH 3/5] [C++] added test for ArrayData member function GetMutableSpan --- cpp/src/arrow/array/array_test.cc | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index 51d81c7f2405..f4c657b91c4b 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -1139,9 +1139,7 @@ TEST_F(TestArray, TestBinaryViewAppendArraySlice) { } TEST_F(TestArray, GetSpanRespectsOffset) { auto data_buffer = Buffer::FromString("123456789abcdef0"); - auto data = ArrayData::Make(uint8(), 3, {nullptr, data_buffer}, 0, 1); - auto span = data->GetSpan(1, 3); EXPECT_EQ(span.size(), 3); @@ -1149,7 +1147,29 @@ TEST_F(TestArray, GetSpanRespectsOffset) { EXPECT_EQ(span[1], '3'); EXPECT_EQ(span[2], '4'); } +TEST_F(TestArray, GetMutableSpanRespectsOffset) { + const int64_t nbytes = 16; + ASSERT_OK_AND_ASSIGN(auto uniq_buffer, AllocateResizableBuffer(nbytes, pool_)); + memset(uniq_buffer->mutable_data(), '0', nbytes); + std::shared_ptr buffer(std::move(uniq_buffer)); + std::vector> buffers = {nullptr, buffer}; + auto data = ArrayData::Make(uint8(), 3, buffers, 0, 1); + auto span = data->template GetMutableSpan(1, 3); + + EXPECT_EQ(span.size(), 3); + EXPECT_EQ(span[0], '0'); + EXPECT_EQ(span[1], '0'); + EXPECT_EQ(span[2], '0'); + + span[0] = 'X'; + span[1] = 'Y'; + span[2] = 'Z'; + auto raw = buffer->mutable_data(); + EXPECT_EQ(raw[1], 'X'); + EXPECT_EQ(raw[2], 'Y'); + EXPECT_EQ(raw[3], 'Z'); +} TEST_F(TestArray, ValidateBuffersPrimitive) { auto empty_buffer = std::make_shared(""); auto null_buffer = Buffer::FromString("\xff"); From d3c363461da3cc042b662e8658f593dd60acc2d8 Mon Sep 17 00:00:00 2001 From: dkp116 Date: Sat, 4 Jul 2026 22:35:21 +0100 Subject: [PATCH 4/5] [C++] applied linting to data.h --- cpp/src/arrow/array/data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/array/data.h b/cpp/src/arrow/array/data.h index 573ded629124..b10a94fc869c 100644 --- a/cpp/src/arrow/array/data.h +++ b/cpp/src/arrow/array/data.h @@ -256,7 +256,7 @@ struct ARROW_EXPORT ArrayData { return NULLPTR; } } -/// \brief Access a buffer's data as a span + /// \brief Access a buffer's data as a span /// /// \param i The buffer index /// \param length The required length (in number of typed values) of the requested span From 6ff23e3a19f8f53cce22a74bf263927bc9c79ea6 Mon Sep 17 00:00:00 2001 From: dkp116 Date: Mon, 6 Jul 2026 23:02:50 +0100 Subject: [PATCH 5/5] [C++] - changed ArrayData GetSpan tests to use non-byte sized data type --- cpp/src/arrow/array/array_test.cc | 57 ++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index f4c657b91c4b..381e550e18f6 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -1138,38 +1138,55 @@ TEST_F(TestArray, TestBinaryViewAppendArraySlice) { AssertArraysEqual(*src, *dst); } TEST_F(TestArray, GetSpanRespectsOffset) { - auto data_buffer = Buffer::FromString("123456789abcdef0"); - auto data = ArrayData::Make(uint8(), 3, {nullptr, data_buffer}, 0, 1); - auto span = data->GetSpan(1, 3); + std::vector values = {1, 2, 3, 4, 5}; + + auto data_buffer = Buffer::Wrap(values); + auto data = ArrayData::Make(uint16(), 3, {nullptr, data_buffer}, 0, 1); + auto span = data->GetSpan(1, 3); EXPECT_EQ(span.size(), 3); - EXPECT_EQ(span[0], '2'); - EXPECT_EQ(span[1], '3'); - EXPECT_EQ(span[2], '4'); + + EXPECT_EQ(span[0], 2); + + EXPECT_EQ(span[1], 3); + + EXPECT_EQ(span[2], 4); } + TEST_F(TestArray, GetMutableSpanRespectsOffset) { - const int64_t nbytes = 16; + std::vector values = {10, 20, 30, 40, 50}; + + const int64_t nbytes = values.size() * sizeof(uint16_t); ASSERT_OK_AND_ASSIGN(auto uniq_buffer, AllocateResizableBuffer(nbytes, pool_)); - memset(uniq_buffer->mutable_data(), '0', nbytes); + memcpy(uniq_buffer->mutable_data(), values.data(), nbytes); + std::shared_ptr buffer(std::move(uniq_buffer)); std::vector> buffers = {nullptr, buffer}; - auto data = ArrayData::Make(uint8(), 3, buffers, 0, 1); - auto span = data->template GetMutableSpan(1, 3); + + auto data = ArrayData::Make(uint16(), 3, buffers, 0, 1); + auto span = data->GetMutableSpan(1, 3); EXPECT_EQ(span.size(), 3); - EXPECT_EQ(span[0], '0'); - EXPECT_EQ(span[1], '0'); - EXPECT_EQ(span[2], '0'); - span[0] = 'X'; - span[1] = 'Y'; - span[2] = 'Z'; + EXPECT_EQ(span[0], 20); + + EXPECT_EQ(span[1], 30); + + EXPECT_EQ(span[2], 40); + + span[0] = 200; + span[1] = 300; + span[2] = 400; - auto raw = buffer->mutable_data(); - EXPECT_EQ(raw[1], 'X'); - EXPECT_EQ(raw[2], 'Y'); - EXPECT_EQ(raw[3], 'Z'); + auto raw = reinterpret_cast(buffer->mutable_data()); + + EXPECT_EQ(raw[1], 200); + + EXPECT_EQ(raw[2], 300); + + EXPECT_EQ(raw[3], 400); } + TEST_F(TestArray, ValidateBuffersPrimitive) { auto empty_buffer = std::make_shared(""); auto null_buffer = Buffer::FromString("\xff");