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

Side by Side Diff: chrome/common/string_index.cc

Issue 8236002: Create StringOrdinal to allow placement of strings in sorted lists (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Add comment about copy and assignment of StringIndex Created 9 years, 2 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "chrome/common/string_index.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10
11 namespace {
12 // Constants
13 static const char kZeroDigit = 'A';
akalin 2011/10/17 22:25:25 no need for static since we're in anon namespace
14 static const char kMinDigit = 'B';
15 static const char kMidDigit = 'N';
16 static const char kMaxDigit = 'Z';
17 static const int kMaxDigitValue = kMaxDigit - kZeroDigit;
18 static const int kMidDigitValue = kMidDigit - kZeroDigit;
19 static const int kFullDigitValue = (kMaxDigit + 1) - kZeroDigit;
20
21 // Helper Functions
22
23 // Remove all trailing zeros from a value as they provide no value.
24 std::string RemoveTrailingZeros(const std::string& value) {
25 DCHECK(!value.empty());
26
27 int end_position = value.length() - 1;
28 while (value[end_position] == kZeroDigit) {
29 --end_position;
30 }
31
32 return value.substr(0, end_position + 1);
33 }
34
35 // Add kMidDigitValue to the value at position index because
36 // the previous index values had an odd difference, so their correct
37 // middle value is x and a half, so the half is now inserted.
38 void AddHalf(size_t position, std::string& value) {
39 DCHECK_GT(position, static_cast<size_t>(0));
40 value[position] += kMidDigitValue;
41
42 for (size_t i = position; value[i] > kMaxDigit; --i) {
43 CHECK_GT(i, static_cast<size_t>(0));
44 value[i] -= kFullDigitValue;
45 ++value[i - 1];
46 }
47 }
48
49 // Return the digit value at position i, padding with kZeroDigit if required.
50 int GetPositionValue(std::string str, size_t i) {
51 return (i < str.length()) ? (str[i] - kZeroDigit) : 0;
52 }
53
54 // Compute the midpoint string that is between start and end.
akalin 2011/10/17 22:25:25 This is what I want, basically: // Given strings
55 std::string ComputeMidpoint(const std::string& start,
56 const std::string& end) {
57 size_t max_size = std::max(start.length(),
58 end.length());
59 std::string middle_string(max_size, kZeroDigit);
60
61 bool add_half = false;
62 for (size_t i = 0; i < max_size; ++i) {
63 int char_value = GetPositionValue(start, i);
64 char_value += GetPositionValue(end, i);
65
66 middle_string[i] += (char_value / 2);
67 if (add_half) {
68 AddHalf(i, middle_string);
69 }
70 add_half = (char_value % 2 == 1);
71 }
72
73 return middle_string;
74 }
75
76 // Create a StringIndex that is lexigraphically greater than start and
77 // lexigraphically less than end, ideally the StringIndex will be a
78 // middle value between the two StringIndexs.
79 StringIndex CreateStringIndexBetween(const StringIndex& start,
80 const StringIndex& end) {
81 CHECK(start.IsValid());
82 CHECK(end.IsValid());
83 std::string start_string = start.ToString();
84 std::string end_string = end.ToString();
85 DCHECK_LT(start_string, end_string);
86
87 std::string middle_string = ComputeMidpoint(start_string, end_string);
88
89 // We only add an extra digit if it is required for uniqueness, otherwise
akalin 2011/10/17 22:25:25 Although you can decomp this logic (which will tur
90 // we accept a close to middle placement.
91 if (RemoveTrailingZeros(middle_string) == start_string) {
92 middle_string += kMidDigit;
93 }
94 middle_string = RemoveTrailingZeros(middle_string);
95
96 DCHECK_GT(middle_string, start_string);
97 DCHECK_LT(middle_string, end_string);
98
99 return StringIndex(middle_string);
100 }
101 } // namespace
102
103 StringIndex::StringIndex(const std::string& str) : string_index_(str),
104 is_valid_(true) {
105 if (string_index_.empty()) {
106 is_valid_ = false;
akalin 2011/10/17 22:25:25 decomp this into a function. That is, have: bool
107 }
108
109 for (size_t i = 0; i < string_index_.length(); ++i) {
110 if (string_index_[i] < kZeroDigit || string_index_[i] > kMaxDigit) {
111 is_valid_ = false;
112 }
113 }
114
115 if (string_index_[string_index_.length() - 1] == kZeroDigit) {
116 is_valid_ = false;
117 }
118 }
119
120 StringIndex::StringIndex() : string_index_(""), is_valid_(false) {
akalin 2011/10/17 22:25:25 omit string_index_ (it's already default-initializ
121 }
122
123 bool StringIndex::IsValid() const {
124 return is_valid_;
125 }
126
127 bool StringIndex::LessThan(const StringIndex& other) const {
128 CHECK(other.IsValid());
akalin 2011/10/17 22:25:25 nit: prefer CHECK(IsValid()) before CHECK(other.Is
129 CHECK(IsValid());
130 return string_index_ < other.string_index_;
131 }
132
133 bool StringIndex::Equal(const StringIndex& other) const {
134 CHECK(other.IsValid());
akalin 2011/10/17 22:25:25 here too
135 CHECK(IsValid());
136
akalin 2011/10/17 22:25:25 omit extra line
137 return string_index_ == other.string_index_;
138 }
139
140 StringIndex StringIndex::CreateBetween(const StringIndex& other) const {
141 CHECK(other.IsValid());
akalin 2011/10/17 22:25:25 here too
142 CHECK(IsValid());
143 CHECK(LessThan(other));
144
145 return CreateStringIndexBetween(*this, other);
146 }
147
148 StringIndex StringIndex::CreateBefore() const {
149 CHECK(IsValid());
akalin 2011/10/17 22:25:25 I think the following would be clearer: const siz
150 // Create the smallest, valid StringIndex to be the minimum boundary.
151 std::string start_string = std::string(string_index_.length(),
152 kZeroDigit);
153 *(start_string.rbegin()) = kMinDigit;
154 if (start_string == string_index_) {
155 *(start_string.rbegin()) = kZeroDigit;
156 start_string += kMinDigit;
157 }
158
159 return CreateStringIndexBetween(StringIndex(start_string), *this);
akalin 2011/10/17 22:25:25 return StringIndex(start_string).CreateBetween(*th
akalin 2011/10/17 22:25:25 Add comment saying that, even though start_string
160 }
161
162 StringIndex StringIndex::CreateAfter() const {
163 CHECK(IsValid());
164 std::string end = std::string(string_index_.length(), kMaxDigit);
165 if (end == string_index_) {
166 end += kMaxDigit;
167 }
168
akalin 2011/10/17 22:25:25 return CreateBetween(StringIndex(end))
169 return CreateStringIndexBetween(*this, StringIndex(end));
akalin 2011/10/17 22:25:25 Add comment similar to CreateBefore
170 }
171
172 std::string StringIndex::ToString() const {
173 return string_index_;
174 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698