blob: 2fc540f17c932f666d71a7c442fa4d723f1a8abb [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
11RangeSet::RangeSet() {}
12RangeSet::~RangeSet() {}
13
14bool RangeSet::Contains(const Range& range) const {
15 if (IsEmptyRange(range))
16 return false;
17
18 const Range fixed_range = FixDirection(range);
19 auto it = ranges().upper_bound(fixed_range);
20
21 if (it == ranges().begin())
22 return false; // No ranges includes range.first.
23
24 --it; // Now it starts equal or before range.first.
25 return it->second >= fixed_range.second;
26}
27
28void RangeSet::Union(const Range& range) {
29 if (IsEmptyRange(range))
30 return;
31
32 Range fixed_range = FixDirection(range);
33 if (IsEmpty()) {
34 ranges_.insert(fixed_range);
35 return;
36 }
37
38 auto start = ranges_.upper_bound(fixed_range);
39 if (start != ranges_.begin())
40 --start; // start now points to the key equal or lower than offset.
41
42 if (start->second < fixed_range.first)
43 ++start; // start element is entirely before current range, skip it.
44
45 auto end = ranges_.upper_bound(Range(fixed_range.second, fixed_range.second));
46
47 if (start == end) { // No ranges to merge.
48 ranges_.insert(fixed_range);
49 return;
50 }
51
52 --end;
53
54 const int new_start = std::min<size_t>(start->first, fixed_range.first);
55 const int new_end = std::max(end->second, fixed_range.second);
56
57 ranges_.erase(start, ++end);
58 ranges_.insert(Range(new_start, new_end));
59}
60
61void RangeSet::Union(const RangeSet& range_set) {
62 ASSERT(&range_set != this);
63 for (const auto& it : range_set.ranges())
64 Union(it);
65}
66
67RangeSet::Range RangeSet::FixDirection(const Range& range) const {
68 return range.first <= range.second ? range
69 : Range(range.second + 1, range.first + 1);
70}
71
72bool RangeSet::IsEmptyRange(const Range& range) const {
73 return range.first == range.second;
74}