1d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka/*
2d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * Copyright (C) 2017 The Android Open Source Project
3d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka *
4d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License");
5d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * you may not use this file except in compliance with the License.
6d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * You may obtain a copy of the License at
7d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka *
8d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka *      http://www.apache.org/licenses/LICENSE-2.0
9d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka *
10d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * Unless required by applicable law or agreed to in writing, software
11d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS,
12d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * See the License for the specific language governing permissions and
14d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka * limitations under the License.
15d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka */
16d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
17d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka#ifndef MINIKIN_RANGE_H
18d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka#define MINIKIN_RANGE_H
19d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
20366f57fb4efd0ddf5d48cd232cd88d3777517ea2Seigo Nonaka#include <algorithm>
21524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka#include <limits>
22366f57fb4efd0ddf5d48cd232cd88d3777517ea2Seigo Nonaka#include <utility>
23524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka
24d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonakanamespace minikin {
25d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
26d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka// An undirected range.
27d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonakaclass Range {
28d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonakapublic:
29524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    static constexpr uint32_t NOWHERE = std::numeric_limits<uint32_t>::max();
30524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka
31d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    // start must be smaller than or equal to end otherwise the behavior is undefined.
32d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    Range(uint32_t start, uint32_t end) : mStart(start), mEnd(end) {}
3356f8ea51818c682991c1e700e07f93e26167ed89Seigo Nonaka    Range() : Range(NOWHERE, NOWHERE) {}
34d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
35d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    Range(const Range&) = default;
36d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    Range& operator=(const Range&) = default;
37d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
38524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    static Range invalidRange() { return Range(NOWHERE, NOWHERE); }
39524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    inline bool isValid() const { return mStart != NOWHERE && mEnd != NOWHERE; }
40524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka
416c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    inline uint32_t getStart() const { return mStart; }       // inclusive
42d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline void setStart(uint32_t start) { mStart = start; }  // inclusive
43d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
446c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    inline uint32_t getEnd() const { return mEnd; }   // exclusive
45d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline void setEnd(uint32_t end) { mEnd = end; }  // exclusive
46d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
47d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline uint32_t getLength() const { return mEnd - mStart; }
48d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
49d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline bool isEmpty() const { return mStart == mEnd; }
50d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
51d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline uint32_t toRangeOffset(uint32_t globalPos) const { return globalPos - mStart; }
52d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline uint32_t toGlobalOffset(uint32_t rangePos) const { return mStart + rangePos; }
53d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
54d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    // The behavior is undefined if pos is out of range.
55d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline std::pair<Range, Range> split(uint32_t pos) const {
56d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka        return std::make_pair(Range(mStart, pos), Range(pos, mEnd));
57d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    }
58d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
59d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline bool contains(const Range& other) const {
60d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka        return mStart <= other.mStart && other.mEnd <= mEnd;
61d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    }
62d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
63d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    // Returns true if the pos is in this range.
64d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    // For example,
65d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    //   const Range range(1, 2);  // 1 is inclusive, 2 is exclusive.
66d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    //   range.contains(0);  // false
67d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    //   range.contains(1);  // true
68d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    //   range.contains(2);  // false
696c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka    inline bool contains(uint32_t pos) const { return mStart <= pos && pos < mEnd; }
70d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
71524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    // Returns true if left and right intersect.
72524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    inline static bool intersects(const Range& left, const Range& right) {
73524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka        return left.isValid() && right.isValid() && left.mStart < right.mEnd &&
74524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka               right.mStart < left.mEnd;
75524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    }
763da4269e6097e0dafdb438c760dafdde13feda95Seigo Nonaka    inline static Range intersection(const Range& left, const Range& right) {
773da4269e6097e0dafdb438c760dafdde13feda95Seigo Nonaka        return Range(std::max(left.mStart, right.mStart), std::min(left.mEnd, right.mEnd));
783da4269e6097e0dafdb438c760dafdde13feda95Seigo Nonaka    }
79524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka
80524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    // Returns merged range. This method assumes left and right are not invalid ranges and they have
81524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    // an intersection.
82524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    static Range merge(const Range& left, const Range& right) {
83524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka        return Range({std::min(left.mStart, right.mStart), std::max(left.mEnd, right.mEnd)});
84524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka    }
85524d294be051584e5506e5a4ad6ec70471bf4c08Seigo Nonaka
8656f8ea51818c682991c1e700e07f93e26167ed89Seigo Nonaka    inline bool operator==(const Range& o) const { return mStart == o.mStart && mEnd == o.mEnd; }
8756f8ea51818c682991c1e700e07f93e26167ed89Seigo Nonaka
8856f8ea51818c682991c1e700e07f93e26167ed89Seigo Nonaka    inline bool operator!=(const Range& o) const { return !(*this == o); }
8956f8ea51818c682991c1e700e07f93e26167ed89Seigo Nonaka
90d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonakaprivate:
91d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    // Helper class for "for (uint32_t i : range)" style for-loop.
92d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    class RangeIterator {
93d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    public:
94d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka        RangeIterator(uint32_t pos) : mPos(pos) {}
95d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
96d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka        inline bool operator!=(const RangeIterator& o) const { return o.mPos != mPos; }
97d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka        inline uint32_t operator*() const { return mPos; }
986c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        inline RangeIterator& operator++() {
996c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            mPos++;
1006c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka            return *this;
1016c8722e217ff5238f0b849152d7936959a728103Seigo Nonaka        }
102d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
103d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    private:
104d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka        uint32_t mPos;
105d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    };
106d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
107d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonakapublic:
108d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline RangeIterator begin() const { return RangeIterator(mStart); }
109d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    inline RangeIterator end() const { return RangeIterator(mEnd); }
110d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
111d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonakaprivate:
112d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    uint32_t mStart;
113d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka    uint32_t mEnd;
114d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka};
115d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
116d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka}  // namespace minikin
117d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka
118d565f7d88018f09a740ff6cf26cb2b068139c784Seigo Nonaka#endif  // MINIKIN_RANGE_H
119