| 2035 | protected: |
| 2036 | template <bool is_first_run> |
| 2037 | static void BuildBufferInternal(const int32_t* prefix_len_ptr, int i, ByteArray* buffer, |
| 2038 | std::string_view* prefix, uint8_t** data_ptr) { |
| 2039 | if (ARROW_PREDICT_FALSE(static_cast<size_t>(prefix_len_ptr[i]) > prefix->length())) { |
| 2040 | throw ParquetException("prefix length too large in DELTA_BYTE_ARRAY"); |
| 2041 | } |
| 2042 | // For now, `buffer` points to string suffixes, and the suffix decoder |
| 2043 | // ensures that the suffix data has sufficient lifetime. |
| 2044 | if (prefix_len_ptr[i] == 0) { |
| 2045 | // prefix is empty: buffer[i] already points to the suffix. |
| 2046 | *prefix = std::string_view{buffer[i]}; |
| 2047 | return; |
| 2048 | } |
| 2049 | DCHECK_EQ(is_first_run, i == 0); |
| 2050 | if constexpr (!is_first_run) { |
| 2051 | if (buffer[i].len == 0) { |
| 2052 | // suffix is empty: buffer[i] can simply point to the prefix. |
| 2053 | // This is not possible for the first run since the prefix |
| 2054 | // would point to the mutable `last_value_`. |
| 2055 | *prefix = prefix->substr(0, prefix_len_ptr[i]); |
| 2056 | buffer[i] = ByteArray(*prefix); |
| 2057 | return; |
| 2058 | } |
| 2059 | } |
| 2060 | // Both prefix and suffix are non-empty, so we need to decode the string |
| 2061 | // into `data_ptr`. |
| 2062 | // 1. Copy the prefix |
| 2063 | memcpy(*data_ptr, prefix->data(), prefix_len_ptr[i]); |
| 2064 | // 2. Copy the suffix. |
| 2065 | memcpy(*data_ptr + prefix_len_ptr[i], buffer[i].ptr, buffer[i].len); |
| 2066 | // 3. Point buffer[i] to the decoded string. |
| 2067 | buffer[i].ptr = *data_ptr; |
| 2068 | buffer[i].len += prefix_len_ptr[i]; |
| 2069 | *data_ptr += buffer[i].len; |
| 2070 | *prefix = std::string_view{buffer[i]}; |
| 2071 | } |
| 2072 | |
| 2073 | int GetInternal(ByteArray* buffer, int max_values) { |
| 2074 | // Decode up to `max_values` strings into an internal buffer |
nothing calls this directly
no test coverage detected