| 172 | // --------------------------------------------------------------------------- |
| 173 | |
| 174 | FrameOfReferenceEncoded forEncode( |
| 175 | Span<const uint8_t> data, StorageKind kind, std::size_t count, int64_t min_val, int64_t max_val) { |
| 176 | FrameOfReferenceEncoded result; |
| 177 | result.reference = min_val; |
| 178 | result.count = count; |
| 179 | |
| 180 | const auto range = static_cast<uint64_t>(max_val - min_val); |
| 181 | result.offset_bytes = offsetBytesFor(range); |
| 182 | |
| 183 | const std::size_t esize = storageKindSize(kind); |
| 184 | result.offsets.reserve(count * result.offset_bytes); |
| 185 | |
| 186 | for (std::size_t i = 0; i < count; ++i) { |
| 187 | int64_t val{}; |
| 188 | if (kind == StorageKind::kInt32) { |
| 189 | int32_t tmp{}; |
| 190 | std::memcpy(&tmp, data.data() + i * esize, sizeof(tmp)); |
| 191 | val = tmp; // sign-extend |
| 192 | } else { |
| 193 | std::memcpy(&val, data.data() + i * esize, sizeof(val)); |
| 194 | } |
| 195 | const auto offset = static_cast<uint64_t>(val - min_val); |
| 196 | |
| 197 | switch (result.offset_bytes) { |
| 198 | case 1: { |
| 199 | auto v = static_cast<uint8_t>(offset); |
| 200 | result.offsets.append(&v, sizeof(v)); |
| 201 | break; |
| 202 | } |
| 203 | case 2: { |
| 204 | auto v = static_cast<uint16_t>(offset); |
| 205 | result.offsets.append(&v, sizeof(v)); |
| 206 | break; |
| 207 | } |
| 208 | default: { |
| 209 | auto v = static_cast<uint32_t>(offset); |
| 210 | result.offsets.append(&v, sizeof(v)); |
| 211 | break; |
| 212 | } |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | return result; |
| 217 | } |
| 218 | |
| 219 | namespace { |
| 220 | |