blob: ffd71cf8c14c28442d421197219ad7f528533369 [file] [log] [blame]
Artem Strygin0e60b9e2017-09-28 18:46:03 +03001// Copyright 2017 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "testing/range_set.h"
6
7#include <algorithm>
8
9#include "core/fxcrt/fx_system.h"
10
Lei Zhang4affe8b2020-10-13 20:01:23 +000011RangeSet::RangeSet() = default;
12
Lei Zhang0e744a22020-06-02 00:44:28 +000013RangeSet::~RangeSet() = default;
Artem Strygin0e60b9e2017-09-28 18:46:03 +030014
15bool RangeSet::Contains(const Range& range) const {
16 if (IsEmptyRange(range))
17 return false;
18
19 const Range fixed_range = FixDirection(range);
20 auto it = ranges().upper_bound(fixed_range);
21
22 if (it == ranges().begin())
23 return false; // No ranges includes range.first.
24
25 --it; // Now it starts equal or before range.first.
26 return it->second >= fixed_range.second;
27}
28
29void RangeSet::Union(const Range& range) {
30 if (IsEmptyRange(range))
31 return;
32
33 Range fixed_range = FixDirection(range);
34 if (IsEmpty()) {
35 ranges_.insert(fixed_range);
36 return;
37 }
38
39 auto start = ranges_.upper_bound(fixed_range);
40 if (start != ranges_.begin())
41 --start; // start now points to the key equal or lower than offset.
42
43 if (start->second < fixed_range.first)
44 ++start; // start element is entirely before current range, skip it.
45
46 auto end = ranges_.upper_bound(Range(fixed_range.second, fixed_range.second));
47
48 if (start == end) { // No ranges to merge.
49 ranges_.insert(fixed_range);
50 return;
51 }
52
53 --end;
54
55 const int new_start = std::min<size_t>(start->first, fixed_range.first);
56 const int new_end = std::max(end->second, fixed_range.second);
57
58 ranges_.erase(start, ++end);
59 ranges_.insert(Range(new_start, new_end));
60}
61
62void RangeSet::Union(const RangeSet& range_set) {
63 ASSERT(&range_set != this);
64 for (const auto& it : range_set.ranges())
65 Union(it);
66}
67
68RangeSet::Range RangeSet::FixDirection(const Range& range) const {
69 return range.first <= range.second ? range
70 : Range(range.second + 1, range.first + 1);
71}
72
73bool RangeSet::IsEmptyRange(const Range& range) const {
74 return range.first == range.second;
75}