1b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar/*
2b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * Copyright (C) 2014 The Android Open Source Project
3b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar *
4b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
5b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * you may not use this file except in compliance with the License.
6b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * You may obtain a copy of the License at
7b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar *
8b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
9b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar *
10b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * Unless required by applicable law or agreed to in writing, software
11b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
12b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * See the License for the specific language governing permissions and
14b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar * limitations under the License.
15b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar */
16b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
17b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarpackage android.media;
18b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
19b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Log;
20b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Pair;
21b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Range;
22b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Rational;
23b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport android.util.Size;
24b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
25b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Arrays;
26b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Comparator;
27b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarimport java.util.Vector;
28b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
29b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar// package private
30b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnarclass Utils {
31b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private static final String TAG = "Utils";
32b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
33b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /**
34b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * Sorts distinct (non-intersecting) range array in ascending order.
35b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @throws java.lang.IllegalArgumentException if ranges are not distinct
36b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
37b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    public static <T extends Comparable<? super T>> void sortDistinctRanges(Range<T>[] ranges) {
38b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Arrays.sort(ranges, new Comparator<Range<T>>() {
39b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            @Override
40b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            public int compare(Range<T> lhs, Range<T> rhs) {
41b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                if (lhs.getUpper().compareTo(rhs.getLower()) < 0) {
42b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return -1;
43b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                } else if (lhs.getLower().compareTo(rhs.getUpper()) > 0) {
44b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    return 1;
45b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                }
46b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                throw new IllegalArgumentException(
47b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        "sample rate ranges must be distinct (" + lhs + " and " + rhs + ")");
48b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
49b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        });
50b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
51b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
52b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /**
53b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * Returns the intersection of two sets of non-intersecting ranges
54b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @param one a sorted set of non-intersecting ranges in ascending order
55b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @param another another sorted set of non-intersecting ranges in ascending order
56b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @return the intersection of the two sets, sorted in ascending order
57b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
58b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    public static <T extends Comparable<? super T>>
59b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            Range<T>[] intersectSortedDistinctRanges(Range<T>[] one, Range<T>[] another) {
60b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        int ix = 0;
61b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Vector<Range<T>> result = new Vector<Range<T>>();
62b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        for (Range<T> range: another) {
63b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            while (ix < one.length &&
64b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    one[ix].getUpper().compareTo(range.getLower()) < 0) {
65b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                ++ix;
66b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
67b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            while (ix < one.length &&
68b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    one[ix].getUpper().compareTo(range.getUpper()) < 0) {
69b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                result.add(range.intersect(one[ix]));
70b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                ++ix;
71b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
72b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ix == one.length) {
73b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                break;
74b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
75b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (one[ix].getLower().compareTo(range.getUpper()) <= 0) {
76b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                result.add(range.intersect(one[ix]));
77b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
78b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
79b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return result.toArray(new Range[result.size()]);
80b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
81b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
82b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /**
83b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * Returns the index of the range that contains a value in a sorted array of distinct ranges.
84b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @param ranges a sorted array of non-intersecting ranges in ascending order
85b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @param value the value to search for
86b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * @return if the value is in one of the ranges, it returns the index of that range.  Otherwise,
87b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * the return value is {@code (-1-index)} for the {@code index} of the range that is
88b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * immediately following {@code value}.
89b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
90b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    public static <T extends Comparable<? super T>>
91b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int binarySearchDistinctRanges(Range<T>[] ranges, T value) {
92b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return Arrays.binarySearch(ranges, Range.create(value, value),
93b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                new Comparator<Range<T>>() {
94b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    @Override
95b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    public int compare(Range<T> lhs, Range<T> rhs) {
96b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        if (lhs.getUpper().compareTo(rhs.getLower()) < 0) {
97b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                            return -1;
98b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        } else if (lhs.getLower().compareTo(rhs.getUpper()) > 0) {
99b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                            return 1;
100b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        }
101b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        return 0;
102b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                    }
103b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                });
104b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
105b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
106b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /**
107b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * Returns greatest common divisor
108b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
109b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static int gcd(int a, int b) {
110b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (a == 0 && b == 0) {
111b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return 1;
112b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
113b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (b < 0) {
114b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            b = -b;
115b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
116b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (a < 0) {
117b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            a = -a;
118b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
119b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        while (a != 0) {
120b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int c = b % a;
121b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            b = a;
122b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            a = c;
123b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
124b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return b;
125b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
126b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
127b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /** Returns the equivalent factored range {@code newrange}, where for every
128b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * {@code e}: {@code newrange.contains(e)} implies that {@code range.contains(e * factor)},
129b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * and {@code !newrange.contains(e)} implies that {@code !range.contains(e * factor)}.
130b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
131b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Integer>factorRange(Range<Integer> range, int factor) {
132b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (factor == 1) {
133b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return range;
134b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
135b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return Range.create(divUp(range.getLower(), factor), range.getUpper() / factor);
136b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
137b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
138b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /** Returns the equivalent factored range {@code newrange}, where for every
139b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * {@code e}: {@code newrange.contains(e)} implies that {@code range.contains(e * factor)},
140b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * and {@code !newrange.contains(e)} implies that {@code !range.contains(e * factor)}.
141b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
142b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Long>factorRange(Range<Long> range, long factor) {
143b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (factor == 1) {
144b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return range;
145b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
146b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return Range.create(divUp(range.getLower(), factor), range.getUpper() / factor);
147b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
148b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
149b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private static Rational scaleRatio(Rational ratio, int num, int den) {
150b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        int common = gcd(num, den);
151b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        num /= common;
152b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        den /= common;
153b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return new Rational(
154b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                (int)(ratio.getNumerator() * (double)num),     // saturate to int
155b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                (int)(ratio.getDenominator() * (double)den));  // saturate to int
156b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
157b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
158b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Rational> scaleRange(Range<Rational> range, int num, int den) {
159b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (num == den) {
160b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return range;
161b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
162b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return Range.create(
163b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                scaleRatio(range.getLower(), num, den),
164b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                scaleRatio(range.getUpper(), num, den));
165b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
166b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
167b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Integer> alignRange(Range<Integer> range, int align) {
168b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return range.intersect(
169b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                divUp(range.getLower(), align) * align,
170b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                (range.getUpper() / align) * align);
171b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
172b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
173b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static int divUp(int num, int den) {
174b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return (num + den - 1) / den;
175b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
176b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
177f37f9ba8c8ee8629399981d710dcb9f93a5fb31dRonghua Wu    static long divUp(long num, long den) {
178b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return (num + den - 1) / den;
179b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
180b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
181b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    /**
182b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     * Returns least common multiple
183b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar     */
184b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    private static long lcm(int a, int b) {
185b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        if (a == 0 || b == 0) {
186b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            throw new IllegalArgumentException("lce is not defined for zero arguments");
187b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
188b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return (long)a * b / gcd(a, b);
189b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
190b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
191b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Integer> intRangeFor(double v) {
192b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return Range.create((int)v, (int)Math.ceil(v));
193b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
194b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
195b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Long> longRangeFor(double v) {
196b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return Range.create((long)v, (long)Math.ceil(v));
197b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
198b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
199b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Size parseSize(Object o, Size fallback) {
200b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        try {
201b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return Size.parseSize((String) o);
202b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (ClassCastException e) {
203b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NumberFormatException e) {
204b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NullPointerException e) {
205b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return fallback;
206b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
207b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Log.w(TAG, "could not parse size '" + o + "'");
208b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return fallback;
209b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
210b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
211981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar    static int parseIntSafely(Object o, int fallback) {
212dcb5ab97f66bc6e070da32fbf3fe720877662bd0Robert Shih        if (o == null) {
213dcb5ab97f66bc6e070da32fbf3fe720877662bd0Robert Shih            return fallback;
214dcb5ab97f66bc6e070da32fbf3fe720877662bd0Robert Shih        }
215981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        try {
216981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar            String s = (String)o;
217981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar            return Integer.parseInt(s);
218981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        } catch (ClassCastException e) {
219981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        } catch (NumberFormatException e) {
220981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        } catch (NullPointerException e) {
221981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar            return fallback;
222981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        }
223981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        Log.w(TAG, "could not parse integer '" + o + "'");
224981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar        return fallback;
225981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar    }
226981c344ee7a4472e2a331d66819c132267a681c6Lajos Molnar
227b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Integer> parseIntRange(Object o, Range<Integer> fallback) {
228b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        try {
229b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String s = (String)o;
230b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int ix = s.indexOf('-');
231b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ix >= 0) {
232b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return Range.create(
233b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Integer.parseInt(s.substring(0, ix), 10),
234b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Integer.parseInt(s.substring(ix + 1), 10));
235b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
236b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int value = Integer.parseInt(s);
237b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return Range.create(value, value);
238b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (ClassCastException e) {
239b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NumberFormatException e) {
240b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NullPointerException e) {
241b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return fallback;
242b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (IllegalArgumentException e) {
243b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
244b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Log.w(TAG, "could not parse integer range '" + o + "'");
245b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return fallback;
246b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
247b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
248b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Long> parseLongRange(Object o, Range<Long> fallback) {
249b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        try {
250b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String s = (String)o;
251b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int ix = s.indexOf('-');
252b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ix >= 0) {
253b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return Range.create(
254b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Long.parseLong(s.substring(0, ix), 10),
255b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Long.parseLong(s.substring(ix + 1), 10));
256b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
257b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            long value = Long.parseLong(s);
258b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return Range.create(value, value);
259b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (ClassCastException e) {
260b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NumberFormatException e) {
261b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NullPointerException e) {
262b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return fallback;
263b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (IllegalArgumentException e) {
264b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
265b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Log.w(TAG, "could not parse long range '" + o + "'");
266b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return fallback;
267b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
268b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
269b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Range<Rational> parseRationalRange(Object o, Range<Rational> fallback) {
270b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        try {
271b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String s = (String)o;
272b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int ix = s.indexOf('-');
273b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ix >= 0) {
274b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return Range.create(
275b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Rational.parseRational(s.substring(0, ix)),
276b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Rational.parseRational(s.substring(ix + 1)));
277b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
278b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            Rational value = Rational.parseRational(s);
279b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return Range.create(value, value);
280b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (ClassCastException e) {
281b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NumberFormatException e) {
282b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NullPointerException e) {
283b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return fallback;
284b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (IllegalArgumentException e) {
285b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
286b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Log.w(TAG, "could not parse rational range '" + o + "'");
287b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return fallback;
288b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
289b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
290b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    static Pair<Size, Size> parseSizeRange(Object o) {
291b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        try {
292b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            String s = (String)o;
293b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            int ix = s.indexOf('-');
294b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            if (ix >= 0) {
295b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                return Pair.create(
296b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Size.parseSize(s.substring(0, ix)),
297b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar                        Size.parseSize(s.substring(ix + 1)));
298b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            }
299b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            Size value = Size.parseSize(s);
300b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return Pair.create(value, value);
301b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (ClassCastException e) {
302b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NumberFormatException e) {
303b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (NullPointerException e) {
304b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            return null;
305b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        } catch (IllegalArgumentException e) {
306b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        }
307b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        Log.w(TAG, "could not parse size range '" + o + "'");
308b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return null;
309b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
310b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar}
311