Create a decimal128 array with data at a specific alignment offset This simulates the real-world scenario where Arrow data from external sources (like JNI/Java) may not be 16-byte aligned.
| 49 | // This simulates the real-world scenario where Arrow data from external sources |
| 50 | // (like JNI/Java) may not be 16-byte aligned. |
| 51 | std::shared_ptr<arrow::Array> MakeMisalignedDecimalArray( |
| 52 | const std::shared_ptr<arrow::Decimal128Type>& type, |
| 53 | const std::vector<Decimal128>& values, int alignment_offset) { |
| 54 | // Allocate buffer with extra space for misalignment |
| 55 | int64_t data_size = values.size() * 16; // 16 bytes per Decimal128 |
| 56 | int64_t buffer_size = data_size + 16; // Extra space for offset |
| 57 | |
| 58 | std::shared_ptr<arrow::Buffer> buffer; |
| 59 | ARROW_EXPECT_OK(arrow::AllocateBuffer(buffer_size).Value(&buffer)); |
| 60 | |
| 61 | // Calculate the starting offset to achieve desired alignment |
| 62 | // We want the data to be 8-byte aligned but NOT 16-byte aligned |
| 63 | uint8_t* raw_data = buffer->mutable_data(); |
| 64 | uintptr_t addr = reinterpret_cast<uintptr_t>(raw_data); |
| 65 | |
| 66 | // Find offset to get to 8-byte aligned but not 16-byte aligned address |
| 67 | int offset_to_8 = (8 - (addr % 8)) % 8; |
| 68 | int current_16_alignment = (addr + offset_to_8) % 16; |
| 69 | |
| 70 | int final_offset; |
| 71 | if (alignment_offset == 8) { |
| 72 | // Want 8-byte aligned but NOT 16-byte aligned |
| 73 | if (current_16_alignment == 0) { |
| 74 | final_offset = offset_to_8 + 8; // Add 8 to break 16-byte alignment |
| 75 | } else { |
| 76 | final_offset = offset_to_8; |
| 77 | } |
| 78 | } else { |
| 79 | // Want 16-byte aligned |
| 80 | final_offset = (16 - (addr % 16)) % 16; |
| 81 | } |
| 82 | |
| 83 | // Copy decimal values to the offset location |
| 84 | uint8_t* data_start = raw_data + final_offset; |
| 85 | for (size_t i = 0; i < values.size(); i++) { |
| 86 | memcpy(data_start + i * 16, values[i].ToBytes().data(), 16); |
| 87 | } |
| 88 | |
| 89 | // Verify alignment |
| 90 | uintptr_t data_addr = reinterpret_cast<uintptr_t>(data_start); |
| 91 | EXPECT_EQ(data_addr % 8, 0) << "Data should be 8-byte aligned"; |
| 92 | if (alignment_offset == 8) { |
| 93 | EXPECT_NE(data_addr % 16, 0) << "Data should NOT be 16-byte aligned"; |
| 94 | } |
| 95 | |
| 96 | // Create a sliced buffer starting at our offset |
| 97 | auto sliced_buffer = arrow::SliceBuffer(buffer, final_offset, data_size); |
| 98 | |
| 99 | // Create validity buffer (all valid) |
| 100 | std::shared_ptr<arrow::Buffer> validity_buffer; |
| 101 | ARROW_EXPECT_OK(arrow::AllocateBuffer((values.size() + 7) / 8).Value(&validity_buffer)); |
| 102 | memset(validity_buffer->mutable_data(), 0xFF, validity_buffer->size()); |
| 103 | |
| 104 | // Create the array with our misaligned data buffer |
| 105 | auto array_data = arrow::ArrayData::Make(type, static_cast<int64_t>(values.size()), |
| 106 | {validity_buffer, sliced_buffer}); |
| 107 | |
| 108 | return std::make_shared<arrow::Decimal128Array>(array_data); |
no test coverage detected