Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: components/enhanced_bookmarks/stars_position.cc

Issue 510543002: Introduce ItemPosition class for enhanced bookmarks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Comments and comparison functions Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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 "components/enhanced_bookmarks/stars_position.h"
6
7 #include "base/logging.h"
8
9 namespace {
10 const int kPositionBase = 64;
11 const char kPositionAlphabet[] =
12 ".0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
13 } // namespace
14
15 namespace enhanced_bookmarks {
16
17 StarsPosition::StarsPosition() {
18 }
19
20 StarsPosition::StarsPosition(const PositionVector& position)
21 : position_(position) {
22 }
23
24 StarsPosition::~StarsPosition() {
25 }
26
27 // static
28 StarsPosition StarsPosition::CreateInitialPosition() {
29 PositionVector position(1, kPositionBase / 2);
30 return StarsPosition(position);
31 }
32
33 bool StarsPosition::IsValid() const {
Yaron 2014/09/05 03:52:02 nit: ordering should match header file
Rune Fevang 2014/09/05 19:02:30 Done.
34 return !position_.empty() && position_[position_.size() - 1] != 0;
35 }
36
37 // static
38 StarsPosition StarsPosition::CreateBefore(const StarsPosition& other) {
39 DCHECK(other.IsValid());
40 return StarsPosition(CreateBeforeImpl(other.position_, 0));
41 }
42
43 // static
44 StarsPosition::PositionVector StarsPosition::CreateBeforeImpl(
45 const PositionVector& other,
46 size_t from_index) {
47 DCHECK(from_index < other.size());
Yaron 2014/09/05 03:52:02 DCHECK_LT (and similar changes throughout)
Rune Fevang 2014/09/05 19:02:30 Done.
48 PositionVector before(other.begin() + from_index, other.end());
49
50 // Decrement the last character instead of going half-way to 0 in order to
51 // make sure chaining CreateBefore calls result in logarithmic rather than
52 // linear length growth.
53 before[before.size() - 1] /= 2;
54 if (before[before.size() - 1] != 0) {
55 // If the last digit didn't change to 0, we're done!
56 return before;
57 }
58
59 // Reset trailing zeros, then decrement the last non-zero digit.
60 int index = before.size() - 1;
61 while (index >= 0 && before[index] == 0) {
62 before[index--] = kPositionBase / 2;
63 }
64
65 // Negative index means all digits were zeros. Put that many zeros to the
66 // front of the string to get one that is comes before the input given.
67 // This will cause the returned string will be twice as long as the input one,
Yaron 2014/09/05 03:52:02 Needs slight reversing. "returned string to be twi
Yaron 2014/09/05 03:52:22 err. "revising"
Rune Fevang 2014/09/05 19:02:30 Done.
68 // (and about twice as long as needed for a valid return value), however that
69 // means this function can be called many times more before we need to
70 // increase the string size again. Increasing it with the minimum length
71 // would result in a linear string size growth.
72 if (index < 0) {
73 before.insert(before.begin(), before.size(), 0);
74 } else {
75 before[index] /= 2;
76 }
77 return before;
78 }
79
80 // static
81 StarsPosition StarsPosition::CreateAfter(const StarsPosition& other) {
82 DCHECK(other.IsValid());
83 return StarsPosition(CreateAfterImpl(other.position_, 0));
84 }
85
86 // static
87 StarsPosition::PositionVector StarsPosition::CreateAfterImpl(
88 const PositionVector& other,
89 size_t from_index) {
90 DCHECK(from_index <= other.size());
91 if (from_index == other.size()) {
92 return PositionVector(1, kPositionBase / 2);
93 }
94
95 PositionVector after(other.begin() + from_index, other.end());
96
97 // Instead of splitting the position with infinity, increment the last digit
98 // possible, and reset all digits after. This makes sure chaining createAfter
99 // will result in a logarithmic rather than linear length growth.
100 size_t index = after.size() - 1;
101 do {
102 after[index] += (kPositionBase - after[index] + 1) / 2;
103 if (after[index] != kPositionBase)
104 return after;
105 after[index] = kPositionBase / 2;
106 } while (index-- > 0);
107
108 // All digits must have been at the maximal value already, so the string
109 // length has to increase. Double it's size to ensure CreateAfter can be
110 // called exponentially more times every time this needs to happen.
111 after.insert(after.begin(), after.size(), kPositionBase - 1);
112
113 return after;
114 }
115
116 // static
117 StarsPosition StarsPosition::CreateBetween(const StarsPosition& before,
118 const StarsPosition& after) {
119 DCHECK(before.IsValid() && after.IsValid());
120 return StarsPosition(CreateBetweenImpl(before.position_, after.position_));
121 }
122
123 // static
124 StarsPosition::PositionVector StarsPosition::CreateBetweenImpl(
125 const PositionVector& before,
126 const PositionVector& after) {
127 DCHECK(before < after);
128
129 PositionVector between;
130 for (size_t i = 0; i < before.size(); i++) {
131 if (before[i] == after[i]) {
132 // Add the common prefix to the return value.
133 between.push_back(before[i]);
134 continue;
135 }
136 if (before[i] < after[i] - 1) {
137 // Split the difference between the two characters.
138 between.push_back((before[i] + after[i]) / 2);
139 return between;
140 }
141 // The difference between before[i] and after[i] is one character. A valid
142 // return is that character, plus something that comes after the remaining
143 // characters of before.
144 between.push_back(before[i]);
145 PositionVector suffix = CreateAfterImpl(before, i + 1);
146 between.insert(between.end(), suffix.begin(), suffix.end());
147 return between;
148 }
149
150 // |before| must be a prefix of |after|, so return that prefix followed by
151 // something that comes before the remaining digits of |after|.
152 PositionVector suffix = CreateBeforeImpl(after, before.size());
153 between.insert(between.end(), suffix.begin(), suffix.end());
154 return between;
155 }
156
157 std::string StarsPosition::ToString() const {
158 DCHECK(arraysize(kPositionAlphabet) > kPositionBase);
159
160 std::string str;
161 str.reserve(position_.size());
162 for (size_t i = 0; i < position_.size(); i++) {
163 int val = position_[i];
164 CHECK(val >= 0 && val < kPositionBase);
165 str.push_back(kPositionAlphabet[position_[i]]);
166 }
167 return str;
168 }
169
170 bool StarsPosition::Equals(const StarsPosition& other) {
171 return position_ == other.position_;
172 }
173
174 bool StarsPosition::LessThan(const StarsPosition& other) {
175 return position_ < other.position_;
176 }
177
178 } // namespace enhanced_bookmarks
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698