| // Copyright 2015 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package io.v.todos.persistence.syncbase; |
| |
| import com.google.common.collect.ContiguousSet; |
| import com.google.common.collect.ImmutableList; |
| |
| /** |
| * A {@link DigitMapping} optimized for mappings where ranges of consecutive characters map to |
| * consecutive values. The overall mapping need not be monotonic to take advantage of this |
| * optimization. |
| */ |
| public class DigitRangeMapping implements DigitMapping { |
| private final ImmutableList<ContiguousSet<Character>> mRanges; |
| private final int mRadix; |
| |
| public DigitRangeMapping(Iterable<ContiguousSet<Character>> ranges) { |
| mRanges = ImmutableList.copyOf(ranges); |
| int size = 0; |
| for (ContiguousSet<Character> range : mRanges) { |
| size += range.size(); |
| } |
| mRadix = size; |
| } |
| |
| @Override |
| public char encode(int digit) { |
| for (ContiguousSet<Character> range : mRanges) { |
| if (digit < range.size()) { |
| return range.asList().get(digit); |
| } else { |
| digit -= range.size(); |
| } |
| } |
| throw new IllegalArgumentException("No encoding for digit " + digit + " (radix " + radix() + |
| ")"); |
| } |
| |
| @Override |
| public int decode(char encoded) { |
| int digit = 0; |
| for (ContiguousSet<Character> range : mRanges) { |
| if (range.contains(encoded)) { |
| return digit + encoded - range.first(); |
| } |
| digit += range.size(); |
| } |
| throw new IllegalArgumentException(); |
| } |
| |
| @Override |
| public int radix() { |
| return mRadix; |
| } |
| } |