OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium 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 "core/editing/markers/DocumentMarkerListEditor.h" | |
6 | |
7 namespace blink { | |
8 | |
9 DocumentMarkerVector::iterator | |
10 DocumentMarkerListEditor::GetPosOfFirstMarkerNotEndingBeforeInSortedList( | |
11 DocumentMarkerVector* marker_list, | |
12 size_t start_offset) { | |
13 return std::upper_bound( | |
14 marker_list->begin(), marker_list->end(), start_offset, | |
15 [](size_t start_offset, const Member<DocumentMarker>& rhv) -> bool { | |
16 return start_offset < rhv->EndOffset(); | |
17 }); | |
18 } | |
19 | |
20 DocumentMarkerList::DidMoveMarkerOrNot | |
21 DocumentMarkerListEditor::MoveUnsortedMarkers(DocumentMarkerVector* marker_list, | |
22 int length, | |
23 DocumentMarkerList* dst_list) { | |
24 return MoveMarkersHelper(marker_list, length, dst_list, false); | |
25 } | |
26 | |
27 DocumentMarkerList::DidMoveMarkerOrNot | |
28 DocumentMarkerListEditor::MoveSortedMarkers(DocumentMarkerVector* marker_list, | |
29 int length, | |
30 DocumentMarkerList* dst_list) { | |
31 return MoveMarkersHelper(marker_list, length, dst_list, true); | |
32 } | |
33 | |
34 DocumentMarkerList::DidRemoveMarkerOrNot | |
35 DocumentMarkerListEditor::RemoveUnsortedMarkers( | |
36 DocumentMarkerVector* marker_list, | |
37 unsigned start_offset, | |
38 int length) { | |
39 unsigned end_offset = start_offset + length; | |
40 DocumentMarkerList::DidRemoveMarkerOrNot didRemoveMarker = | |
41 DocumentMarkerList::DidRemoveMarkerOrNot::kDidNotRemoveMarker; | |
42 | |
43 for (auto it = marker_list->begin(); it != marker_list->end(); ++it) { | |
44 const DocumentMarker& marker = **it; | |
45 | |
46 // markers have non-empty overlap | |
47 if (marker.StartOffset() < end_offset && | |
48 marker.EndOffset() > start_offset) { | |
49 // Erase by doing a swap-and-shrink to get O(1) performance | |
50 std::swap(*it, marker_list->back()); | |
51 marker_list->Shrink(marker_list->size() - 1); | |
52 --it; | |
53 | |
54 didRemoveMarker = | |
55 DocumentMarkerList::DidRemoveMarkerOrNot::kDidRemoveMarker; | |
56 } | |
57 } | |
58 | |
59 return didRemoveMarker; | |
60 } | |
61 | |
62 DocumentMarkerList::DocumentMarkerList::DidRemoveMarkerOrNot | |
63 DocumentMarkerListEditor::RemoveSortedMarkers(DocumentMarkerVector* marker_list, | |
64 unsigned start_offset, | |
65 int length) { | |
66 unsigned end_offset = start_offset + length; | |
67 | |
68 const auto startPos = | |
69 GetPosOfFirstMarkerNotEndingBeforeInSortedList(marker_list, start_offset); | |
70 auto it = startPos; | |
71 for (; it != marker_list->end(); ++it) { | |
72 if ((*it)->StartOffset() >= end_offset) | |
73 break; | |
74 } | |
75 | |
76 // it should now point at the first marker *not* to be removed (or at | |
77 // marker_list->end()) | |
78 marker_list->erase(startPos - marker_list->begin(), it - startPos); | |
79 | |
80 if (it == startPos) | |
81 return DocumentMarkerList::DidRemoveMarkerOrNot::kDidNotRemoveMarker; | |
82 | |
83 return DocumentMarkerList::DidRemoveMarkerOrNot::kDidRemoveMarker; | |
84 } | |
85 | |
86 DocumentMarkerList::DidShiftMarkerOrNot | |
87 DocumentMarkerListEditor::ShiftUnsortedMarkers( | |
88 DocumentMarkerVector* marker_list, | |
89 unsigned offset, | |
90 unsigned old_length, | |
91 unsigned new_length) { | |
92 DocumentMarkerList::DidShiftMarkerOrNot didShift = | |
93 DocumentMarkerList::DidShiftMarkerOrNot::kDidNotShiftMarker; | |
94 for (auto it = marker_list->begin(); it != marker_list->end(); ++it) { | |
95 DocumentMarker& marker = **it; | |
96 Optional<DocumentMarker::MarkerOffsets> result = | |
97 marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | |
98 | |
99 if (result == WTF::kNullopt) { | |
100 didShift = DocumentMarkerList::DidShiftMarkerOrNot::kDidShiftMarker; | |
101 // Erase by doing a swap-and-shrink to get O(1) performance | |
102 std::swap(*it, marker_list->back()); | |
103 marker_list->Shrink(marker_list->size() - 1); | |
104 --it; | |
105 continue; | |
106 } | |
107 | |
108 if (result.value().start_offset != marker.StartOffset() || | |
109 result.value().end_offset != marker.EndOffset()) { | |
110 marker.SetStartOffset(result.value().start_offset); | |
111 marker.SetEndOffset(result.value().end_offset); | |
112 | |
113 didShift = DocumentMarkerList::DidShiftMarkerOrNot::kDidShiftMarker; | |
114 } | |
115 } | |
116 | |
117 return didShift; | |
118 } | |
119 | |
120 DocumentMarkerList::DidShiftMarkerOrNot | |
121 DocumentMarkerListEditor::ShiftSortedMarkers(DocumentMarkerVector* marker_list, | |
122 unsigned offset, | |
123 unsigned old_length, | |
124 unsigned new_length) { | |
125 DocumentMarkerVector newMarkerList; | |
126 DocumentMarkerList::DidShiftMarkerOrNot didShift = | |
127 DocumentMarkerList::DidShiftMarkerOrNot::kDidNotShiftMarker; | |
128 for (Member<DocumentMarker> marker : *marker_list) { | |
129 Optional<DocumentMarker::MarkerOffsets> result = | |
130 marker->ComputeOffsetsAfterShift(offset, old_length, new_length); | |
131 | |
132 if (result == WTF::kNullopt) { | |
133 didShift = DocumentMarkerList::DidShiftMarkerOrNot::kDidShiftMarker; | |
134 continue; | |
135 } | |
136 | |
137 if (result.value().start_offset != marker->StartOffset() || | |
138 result.value().end_offset != marker->EndOffset()) { | |
139 marker->SetStartOffset(result.value().start_offset); | |
140 marker->SetEndOffset(result.value().end_offset); | |
141 | |
142 didShift = DocumentMarkerList::DidShiftMarkerOrNot::kDidShiftMarker; | |
143 } | |
144 | |
145 newMarkerList.push_back(marker); | |
146 } | |
147 | |
148 swap(*marker_list, newMarkerList); | |
149 return didShift; | |
150 } | |
151 | |
152 DocumentMarkerList::DidMoveMarkerOrNot | |
153 DocumentMarkerListEditor::MoveMarkersHelper(DocumentMarkerVector* marker_list, | |
154 int length, | |
155 DocumentMarkerList* dst_list, | |
156 bool is_sorted) { | |
157 DocumentMarkerList::DidMoveMarkerOrNot didMoveMarker = | |
158 DocumentMarkerList::DidMoveMarkerOrNot::kDidNotMoveMarker; | |
159 unsigned end_offset = length - 1; | |
160 | |
161 for (auto it = marker_list->begin(); it != marker_list->end(); ++it) { | |
162 DocumentMarker& marker = **it; | |
163 if (marker.StartOffset() > end_offset) { | |
164 if (is_sorted) | |
165 break; | |
166 continue; | |
167 } | |
168 | |
169 // pin the marker to the specified range and apply the shift delta | |
170 if (marker.StartOffset() <= end_offset) { | |
rlanday
2017/04/11 02:59:09
This is redundant, I will remove
| |
171 didMoveMarker = DocumentMarkerList::DidMoveMarkerOrNot::kDidMoveMarker; | |
172 | |
173 if (marker.EndOffset() > end_offset) | |
174 marker.SetEndOffset(end_offset); | |
175 | |
176 dst_list->Add(&marker); | |
177 } | |
178 } | |
179 | |
180 return didMoveMarker; | |
181 } | |
182 | |
183 } // namespace blink | |
OLD | NEW |