| 2047 | } |
| 2048 | |
| 2049 | int GetInternal(ByteArray* buffer, int max_values) { |
| 2050 | // Decode up to `max_values` strings into an internal buffer |
| 2051 | // and reference them into `buffer`. |
| 2052 | max_values = std::min(max_values, num_valid_values_); |
| 2053 | if (max_values == 0) { |
| 2054 | return max_values; |
| 2055 | } |
| 2056 | |
| 2057 | int suffix_read = suffix_decoder_.Decode(buffer, max_values); |
| 2058 | if (ARROW_PREDICT_FALSE(suffix_read != max_values)) { |
| 2059 | ParquetException::EofException("Read " + std::to_string(suffix_read) + |
| 2060 | ", expecting " + std::to_string(max_values) + |
| 2061 | " from suffix decoder"); |
| 2062 | } |
| 2063 | |
| 2064 | int64_t data_size = 0; |
| 2065 | const int32_t* prefix_len_ptr = |
| 2066 | buffered_prefix_length_->data_as<int32_t>() + prefix_len_offset_; |
| 2067 | for (int i = 0; i < max_values; ++i) { |
| 2068 | if (prefix_len_ptr[i] == 0) { |
| 2069 | // We don't need to copy the suffix if the prefix length is 0. |
| 2070 | continue; |
| 2071 | } |
| 2072 | if (ARROW_PREDICT_FALSE(prefix_len_ptr[i] < 0)) { |
| 2073 | throw ParquetException("negative prefix length in DELTA_BYTE_ARRAY"); |
| 2074 | } |
| 2075 | if (buffer[i].len == 0 && i != 0) { |
| 2076 | // We don't need to copy the prefix if the suffix length is 0 |
| 2077 | // and this is not the first run (that is, the prefix doesn't point |
| 2078 | // to the mutable `last_value_`). |
| 2079 | continue; |
| 2080 | } |
| 2081 | if (ARROW_PREDICT_FALSE(AddWithOverflow(data_size, prefix_len_ptr[i], &data_size) || |
| 2082 | AddWithOverflow(data_size, buffer[i].len, &data_size))) { |
| 2083 | throw ParquetException("excess expansion in DELTA_BYTE_ARRAY"); |
| 2084 | } |
| 2085 | } |
| 2086 | PARQUET_THROW_NOT_OK(buffered_data_->Resize(data_size)); |
| 2087 | |
| 2088 | std::string_view prefix{last_value_}; |
| 2089 | uint8_t* data_ptr = buffered_data_->mutable_data(); |
| 2090 | if (max_values > 0) { |
| 2091 | BuildBufferInternal</*is_first_run=*/true>(prefix_len_ptr, 0, buffer, &prefix, |
| 2092 | &data_ptr); |
| 2093 | } |
| 2094 | for (int i = 1; i < max_values; ++i) { |
| 2095 | BuildBufferInternal</*is_first_run=*/false>(prefix_len_ptr, i, buffer, &prefix, |
| 2096 | &data_ptr); |
| 2097 | } |
| 2098 | DCHECK_EQ(data_ptr - buffered_data_->mutable_data(), data_size); |
| 2099 | prefix_len_offset_ += max_values; |
| 2100 | this->num_values_ -= max_values; |
| 2101 | num_valid_values_ -= max_values; |
| 2102 | last_value_ = std::string{prefix}; |
| 2103 | |
| 2104 | if (num_valid_values_ == 0) { |
| 2105 | last_value_in_previous_page_ = last_value_; |
| 2106 | } |
nothing calls this directly
no test coverage detected