| 2011 | protected: |
| 2012 | template <bool is_first_run> |
| 2013 | static void BuildBufferInternal(const int32_t* prefix_len_ptr, int i, ByteArray* buffer, |
| 2014 | std::string_view* prefix, uint8_t** data_ptr) { |
| 2015 | if (ARROW_PREDICT_FALSE(static_cast<size_t>(prefix_len_ptr[i]) > prefix->length())) { |
| 2016 | throw ParquetException("prefix length too large in DELTA_BYTE_ARRAY"); |
| 2017 | } |
| 2018 | // For now, `buffer` points to string suffixes, and the suffix decoder |
| 2019 | // ensures that the suffix data has sufficient lifetime. |
| 2020 | if (prefix_len_ptr[i] == 0) { |
| 2021 | // prefix is empty: buffer[i] already points to the suffix. |
| 2022 | *prefix = std::string_view{buffer[i]}; |
| 2023 | return; |
| 2024 | } |
| 2025 | DCHECK_EQ(is_first_run, i == 0); |
| 2026 | if constexpr (!is_first_run) { |
| 2027 | if (buffer[i].len == 0) { |
| 2028 | // suffix is empty: buffer[i] can simply point to the prefix. |
| 2029 | // This is not possible for the first run since the prefix |
| 2030 | // would point to the mutable `last_value_`. |
| 2031 | *prefix = prefix->substr(0, prefix_len_ptr[i]); |
| 2032 | buffer[i] = ByteArray(*prefix); |
| 2033 | return; |
| 2034 | } |
| 2035 | } |
| 2036 | // Both prefix and suffix are non-empty, so we need to decode the string |
| 2037 | // into `data_ptr`. |
| 2038 | // 1. Copy the prefix |
| 2039 | memcpy(*data_ptr, prefix->data(), prefix_len_ptr[i]); |
| 2040 | // 2. Copy the suffix. |
| 2041 | memcpy(*data_ptr + prefix_len_ptr[i], buffer[i].ptr, buffer[i].len); |
| 2042 | // 3. Point buffer[i] to the decoded string. |
| 2043 | buffer[i].ptr = *data_ptr; |
| 2044 | buffer[i].len += prefix_len_ptr[i]; |
| 2045 | *data_ptr += buffer[i].len; |
| 2046 | *prefix = std::string_view{buffer[i]}; |
| 2047 | } |
| 2048 | |
| 2049 | int GetInternal(ByteArray* buffer, int max_values) { |
| 2050 | // Decode up to `max_values` strings into an internal buffer |
nothing calls this directly
no test coverage detected