| 58 | |
| 59 | template <typename IndexType> |
| 60 | inline TypedChunkLocation<IndexType> ResolveOneInline(uint32_t num_offsets, |
| 61 | const uint64_t* offsets, |
| 62 | IndexType typed_logical_index, |
| 63 | int32_t num_chunks, |
| 64 | int32_t chunk_hint) { |
| 65 | const auto index = static_cast<uint64_t>(typed_logical_index); |
| 66 | // use or update chunk_hint |
| 67 | if (index >= offsets[chunk_hint] && |
| 68 | (chunk_hint == num_chunks || index < offsets[chunk_hint + 1])) { |
| 69 | // hint is correct! |
| 70 | } else { |
| 71 | // lo < hi is guaranteed by `num_offsets = chunks.size() + 1` |
| 72 | auto chunk_index = |
| 73 | ChunkResolver::Bisect(index, offsets, /*lo=*/0, /*hi=*/num_offsets); |
| 74 | chunk_hint = static_cast<int32_t>(chunk_index); |
| 75 | } |
| 76 | // chunk_index is in [0, chunks.size()] no matter what the value |
| 77 | // of logical_index is, so it's always safe to dereference offsets |
| 78 | // as it contains chunks.size()+1 values. |
| 79 | auto loc = TypedChunkLocation<IndexType>( |
| 80 | /*chunk_index=*/chunk_hint, |
| 81 | /*index_in_chunk=*/typed_logical_index - |
| 82 | static_cast<IndexType>(offsets[chunk_hint])); |
| 83 | #if defined(ARROW_VALGRIND) || defined(ADDRESS_SANITIZER) |
| 84 | // Make it more likely that Valgrind/ASAN can catch an invalid memory |
| 85 | // access by poisoning the index-in-chunk value when the logical |
| 86 | // index is out-of-bounds. |
| 87 | if (static_cast<int32_t>(loc.chunk_index) == num_chunks) { |
| 88 | loc.index_in_chunk = std::numeric_limits<IndexType>::max(); |
| 89 | } |
| 90 | #endif |
| 91 | return loc; |
| 92 | } |
| 93 | |
| 94 | /// \pre all the pre-conditions of ChunkResolver::ResolveMany() |
| 95 | /// \pre num_offsets - 1 <= std::numeric_limits<IndexType>::max() |
no test coverage detected