| 2071 | } |
| 2072 | |
| 2073 | int GetInternal(ByteArray* buffer, int max_values) { |
| 2074 | // Decode up to `max_values` strings into an internal buffer |
| 2075 | // and reference them into `buffer`. |
| 2076 | max_values = std::min(max_values, num_valid_values_); |
| 2077 | if (max_values == 0) { |
| 2078 | return max_values; |
| 2079 | } |
| 2080 | |
| 2081 | int suffix_read = suffix_decoder_.Decode(buffer, max_values); |
| 2082 | if (ARROW_PREDICT_FALSE(suffix_read != max_values)) { |
| 2083 | ParquetException::EofException("Read " + std::to_string(suffix_read) + |
| 2084 | ", expecting " + std::to_string(max_values) + |
| 2085 | " from suffix decoder"); |
| 2086 | } |
| 2087 | |
| 2088 | int64_t data_size = 0; |
| 2089 | const int32_t* prefix_len_ptr = |
| 2090 | buffered_prefix_length_->data_as<int32_t>() + prefix_len_offset_; |
| 2091 | for (int i = 0; i < max_values; ++i) { |
| 2092 | if (prefix_len_ptr[i] == 0) { |
| 2093 | // We don't need to copy the suffix if the prefix length is 0. |
| 2094 | continue; |
| 2095 | } |
| 2096 | if (ARROW_PREDICT_FALSE(prefix_len_ptr[i] < 0)) { |
| 2097 | throw ParquetException("negative prefix length in DELTA_BYTE_ARRAY"); |
| 2098 | } |
| 2099 | if (buffer[i].len == 0 && i != 0) { |
| 2100 | // We don't need to copy the prefix if the suffix length is 0 |
| 2101 | // and this is not the first run (that is, the prefix doesn't point |
| 2102 | // to the mutable `last_value_`). |
| 2103 | continue; |
| 2104 | } |
| 2105 | if (ARROW_PREDICT_FALSE(AddWithOverflow(data_size, prefix_len_ptr[i], &data_size) || |
| 2106 | AddWithOverflow(data_size, buffer[i].len, &data_size))) { |
| 2107 | throw ParquetException("excess expansion in DELTA_BYTE_ARRAY"); |
| 2108 | } |
| 2109 | } |
| 2110 | PARQUET_THROW_NOT_OK(buffered_data_->Resize(data_size)); |
| 2111 | |
| 2112 | std::string_view prefix{last_value_}; |
| 2113 | uint8_t* data_ptr = buffered_data_->mutable_data(); |
| 2114 | if (max_values > 0) { |
| 2115 | BuildBufferInternal</*is_first_run=*/true>(prefix_len_ptr, 0, buffer, &prefix, |
| 2116 | &data_ptr); |
| 2117 | } |
| 2118 | for (int i = 1; i < max_values; ++i) { |
| 2119 | BuildBufferInternal</*is_first_run=*/false>(prefix_len_ptr, i, buffer, &prefix, |
| 2120 | &data_ptr); |
| 2121 | } |
| 2122 | DCHECK_EQ(data_ptr - buffered_data_->mutable_data(), data_size); |
| 2123 | prefix_len_offset_ += max_values; |
| 2124 | this->num_values_ -= max_values; |
| 2125 | num_valid_values_ -= max_values; |
| 2126 | last_value_ = std::string{prefix}; |
| 2127 | |
| 2128 | if (num_valid_values_ == 0) { |
| 2129 | last_value_in_previous_page_ = last_value_; |
| 2130 | } |
nothing calls this directly
no test coverage detected