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

Side by Side Diff: sync/internal_api/public/base/ordinal.h

Issue 1545553003: Switch to standard integer types in sync/. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_ 5 #ifndef SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_
6 #define SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_ 6 #define SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_
7 7
8 #include <stdint.h>
9
8 #include <algorithm> 10 #include <algorithm>
9 #include <cstddef> 11 #include <cstddef>
10 #include <string> 12 #include <string>
11 13
12 #include "base/basictypes.h"
13 #include "base/json/string_escape.h" 14 #include "base/json/string_escape.h"
14 #include "base/logging.h" 15 #include "base/logging.h"
15 16
16 namespace syncer { 17 namespace syncer {
17 18
18 // An Ordinal<T> is an object that can be used for ordering. The 19 // An Ordinal<T> is an object that can be used for ordering. The
19 // Ordinal<T> class has an unbounded dense strict total order, which 20 // Ordinal<T> class has an unbounded dense strict total order, which
20 // mean for any Ordinal<T>s a, b and c: 21 // mean for any Ordinal<T>s a, b and c:
21 // 22 //
22 // - a < b and b < c implies a < c (transitivity); 23 // - a < b and b < c implies a < c (transitivity);
23 // - exactly one of a < b, b < a and a = b holds (trichotomy); 24 // - exactly one of a < b, b < a and a = b holds (trichotomy);
24 // - if a < b, there is a Ordinal<T> x such that a < x < b (density); 25 // - if a < b, there is a Ordinal<T> x such that a < x < b (density);
25 // - there are Ordinals<T> x and y such that x < a < y (unboundedness). 26 // - there are Ordinals<T> x and y such that x < a < y (unboundedness).
26 // 27 //
27 // This means that when Ordinal<T> is used for sorting a list, if any 28 // This means that when Ordinal<T> is used for sorting a list, if any
28 // item changes its position in the list, only its Ordinal<T> value 29 // item changes its position in the list, only its Ordinal<T> value
29 // has to change to represent the new order, and all the other values 30 // has to change to represent the new order, and all the other values
30 // can stay the same. 31 // can stay the same.
31 // 32 //
32 // An Ordinal<T> is internally represented as an array of bytes, so it 33 // An Ordinal<T> is internally represented as an array of bytes, so it
33 // can be serialized to and deserialized from disk. 34 // can be serialized to and deserialized from disk.
34 // 35 //
35 // The Traits class should look like the following: 36 // The Traits class should look like the following:
36 // 37 //
37 // // Don't forget to #include "base/basictypes.h". 38 // // Don't forget to #include "base/basictypes.h".
38 // struct MyOrdinalTraits { 39 // struct MyOrdinalTraits {
39 // // There must be at least two distinct values greater than kZeroDigit 40 // // There must be at least two distinct values greater than kZeroDigit
40 // // and less than kMaxDigit. 41 // // and less than kMaxDigit.
41 // static const uint8 kZeroDigit = '0'; 42 // static const uint8_t kZeroDigit = '0';
42 // static const uint8 kMaxDigit = '9'; 43 // static const uint8_t kMaxDigit = '9';
43 // // kMinLength must be positive. 44 // // kMinLength must be positive.
44 // static const size_t kMinLength = 1; 45 // static const size_t kMinLength = 1;
45 // }; 46 // };
46 // 47 //
47 // An Ordinal<T> is valid iff its corresponding string has at least 48 // An Ordinal<T> is valid iff its corresponding string has at least
48 // kMinLength characters, does not contain any characters less than 49 // kMinLength characters, does not contain any characters less than
49 // kZeroDigit or greater than kMaxDigit, is not all zero digits, and 50 // kZeroDigit or greater than kMaxDigit, is not all zero digits, and
50 // does not have any unnecessary trailing zero digits. 51 // does not have any unnecessary trailing zero digits.
51 // 52 //
52 // Note that even if the native char type is signed, strings still 53 // Note that even if the native char type is signed, strings still
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 Ordinal CreateAfter() const; 126 Ordinal CreateAfter() const;
126 127
127 // Returns the string of bytes representing the Ordinal. It is 128 // Returns the string of bytes representing the Ordinal. It is
128 // guaranteed that an Ordinal constructed from the returned string 129 // guaranteed that an Ordinal constructed from the returned string
129 // will be valid. 130 // will be valid.
130 std::string ToInternalValue() const; 131 std::string ToInternalValue() const;
131 132
132 // Use of copy constructor and default assignment for this class is allowed. 133 // Use of copy constructor and default assignment for this class is allowed.
133 134
134 // Constants for Ordinal digits. 135 // Constants for Ordinal digits.
135 static const uint8 kZeroDigit = Traits::kZeroDigit; 136 static const uint8_t kZeroDigit = Traits::kZeroDigit;
136 static const uint8 kMaxDigit = Traits::kMaxDigit; 137 static const uint8_t kMaxDigit = Traits::kMaxDigit;
137 static const size_t kMinLength = Traits::kMinLength; 138 static const size_t kMinLength = Traits::kMinLength;
138 static const uint8 kOneDigit = kZeroDigit + 1; 139 static const uint8_t kOneDigit = kZeroDigit + 1;
139 static const uint8 kMidDigit = kOneDigit + (kMaxDigit - kOneDigit) / 2; 140 static const uint8_t kMidDigit = kOneDigit + (kMaxDigit - kOneDigit) / 2;
140 static const unsigned int kMidDigitValue = kMidDigit - kZeroDigit; 141 static const unsigned int kMidDigitValue = kMidDigit - kZeroDigit;
141 static const unsigned int kMaxDigitValue = kMaxDigit - kZeroDigit; 142 static const unsigned int kMaxDigitValue = kMaxDigit - kZeroDigit;
142 static const unsigned int kRadix = kMaxDigitValue + 1; 143 static const unsigned int kRadix = kMaxDigitValue + 1;
143 144
144 static_assert(kOneDigit > kZeroDigit, "incorrect ordinal one digit"); 145 static_assert(kOneDigit > kZeroDigit, "incorrect ordinal one digit");
145 static_assert(kMidDigit > kOneDigit, "incorrect ordinal mid digit"); 146 static_assert(kMidDigit > kOneDigit, "incorrect ordinal mid digit");
146 static_assert(kMaxDigit > kMidDigit, "incorrect ordinal max digit"); 147 static_assert(kMaxDigit > kMidDigit, "incorrect ordinal max digit");
147 static_assert(kMinLength > 0, "incorrect ordinal min length"); 148 static_assert(kMinLength > 0, "incorrect ordinal min length");
148 static_assert(kMidDigitValue > 1, "incorrect ordinal mid digit"); 149 static_assert(kMidDigitValue > 1, "incorrect ordinal mid digit");
149 static_assert(kMaxDigitValue > kMidDigitValue, "incorrect ordinal max digit"); 150 static_assert(kMaxDigitValue > kMidDigitValue, "incorrect ordinal max digit");
150 static_assert(kRadix == kMaxDigitValue + 1, "incorrect ordinal radix"); 151 static_assert(kRadix == kMaxDigitValue + 1, "incorrect ordinal radix");
151 152
152 private: 153 private:
153 // Returns true iff the given byte string satisfies the criteria for 154 // Returns true iff the given byte string satisfies the criteria for
154 // a valid Ordinal. 155 // a valid Ordinal.
155 static bool IsValidOrdinalBytes(const std::string& bytes); 156 static bool IsValidOrdinalBytes(const std::string& bytes);
156 157
157 // Returns the length that bytes.substr(0, length) would be with 158 // Returns the length that bytes.substr(0, length) would be with
158 // trailing zero digits removed. 159 // trailing zero digits removed.
159 static size_t GetLengthWithoutTrailingZeroDigits( 160 static size_t GetLengthWithoutTrailingZeroDigits(
160 const std::string& bytes, 161 const std::string& bytes,
161 size_t length); 162 size_t length);
162 163
163 // Returns the digit at position i, padding with zero digits if 164 // Returns the digit at position i, padding with zero digits if
164 // required. 165 // required.
165 static uint8 GetDigit(const std::string& bytes, size_t i); 166 static uint8_t GetDigit(const std::string& bytes, size_t i);
166 167
167 // Returns the digit value at position i, padding with 0 if required. 168 // Returns the digit value at position i, padding with 0 if required.
168 static int GetDigitValue(const std::string& bytes, size_t i); 169 static int GetDigitValue(const std::string& bytes, size_t i);
169 170
170 // Adds the given value to |bytes| at position i, carrying when 171 // Adds the given value to |bytes| at position i, carrying when
171 // necessary. Returns the left-most carry. 172 // necessary. Returns the left-most carry.
172 static int AddDigitValue(std::string* bytes, size_t i, int digit_value); 173 static int AddDigitValue(std::string* bytes, size_t i, int digit_value);
173 174
174 // Returns the proper length |bytes| should be resized to, i.e. the 175 // Returns the proper length |bytes| should be resized to, i.e. the
175 // smallest length such that |bytes| is still greater than 176 // smallest length such that |bytes| is still greater than
(...skipping 14 matching lines...) Expand all
190 const Ordinal<Traits>& end); 191 const Ordinal<Traits>& end);
191 192
192 // The internal byte string representation of the Ordinal. Never 193 // The internal byte string representation of the Ordinal. Never
193 // changes after construction except for assignment. 194 // changes after construction except for assignment.
194 std::string bytes_; 195 std::string bytes_;
195 196
196 // A cache of the result of IsValidOrdinalBytes(bytes_). 197 // A cache of the result of IsValidOrdinalBytes(bytes_).
197 bool is_valid_; 198 bool is_valid_;
198 }; 199 };
199 200
200 template <typename Traits> const uint8 Ordinal<Traits>::kZeroDigit; 201 template <typename Traits>
201 template <typename Traits> const uint8 Ordinal<Traits>::kMaxDigit; 202 const uint8_t Ordinal<Traits>::kZeroDigit;
203 template <typename Traits>
204 const uint8_t Ordinal<Traits>::kMaxDigit;
202 template <typename Traits> const size_t Ordinal<Traits>::kMinLength; 205 template <typename Traits> const size_t Ordinal<Traits>::kMinLength;
203 template <typename Traits> const uint8 Ordinal<Traits>::kOneDigit; 206 template <typename Traits>
204 template <typename Traits> const uint8 Ordinal<Traits>::kMidDigit; 207 const uint8_t Ordinal<Traits>::kOneDigit;
208 template <typename Traits>
209 const uint8_t Ordinal<Traits>::kMidDigit;
205 template <typename Traits> const unsigned int Ordinal<Traits>::kMidDigitValue; 210 template <typename Traits> const unsigned int Ordinal<Traits>::kMidDigitValue;
206 template <typename Traits> const unsigned int Ordinal<Traits>::kMaxDigitValue; 211 template <typename Traits> const unsigned int Ordinal<Traits>::kMaxDigitValue;
207 template <typename Traits> const unsigned int Ordinal<Traits>::kRadix; 212 template <typename Traits> const unsigned int Ordinal<Traits>::kRadix;
208 213
209 template <typename Traits> 214 template <typename Traits>
210 Ordinal<Traits>::LessThanFn::LessThanFn() {} 215 Ordinal<Traits>::LessThanFn::LessThanFn() {}
211 216
212 template <typename Traits> 217 template <typename Traits>
213 bool Ordinal<Traits>::LessThanFn::operator()(const Ordinal<Traits>& lhs, 218 bool Ordinal<Traits>::LessThanFn::operator()(const Ordinal<Traits>& lhs,
214 const Ordinal<Traits>& rhs) const { 219 const Ordinal<Traits>& rhs) const {
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 } 346 }
342 347
343 template <typename Traits> 348 template <typename Traits>
344 bool Ordinal<Traits>::IsValidOrdinalBytes(const std::string& bytes) { 349 bool Ordinal<Traits>::IsValidOrdinalBytes(const std::string& bytes) {
345 const size_t length = bytes.length(); 350 const size_t length = bytes.length();
346 if (length < kMinLength) 351 if (length < kMinLength)
347 return false; 352 return false;
348 353
349 bool found_non_zero = false; 354 bool found_non_zero = false;
350 for (size_t i = 0; i < length; ++i) { 355 for (size_t i = 0; i < length; ++i) {
351 const uint8 byte = bytes[i]; 356 const uint8_t byte = bytes[i];
352 if (byte < kZeroDigit || byte > kMaxDigit) 357 if (byte < kZeroDigit || byte > kMaxDigit)
353 return false; 358 return false;
354 if (byte > kZeroDigit) 359 if (byte > kZeroDigit)
355 found_non_zero = true; 360 found_non_zero = true;
356 } 361 }
357 if (!found_non_zero) 362 if (!found_non_zero)
358 return false; 363 return false;
359 364
360 if (length > kMinLength) { 365 if (length > kMinLength) {
361 const uint8 last_byte = bytes[length - 1]; 366 const uint8_t last_byte = bytes[length - 1];
362 if (last_byte == kZeroDigit) 367 if (last_byte == kZeroDigit)
363 return false; 368 return false;
364 } 369 }
365 370
366 return true; 371 return true;
367 } 372 }
368 373
369 template <typename Traits> 374 template <typename Traits>
370 size_t Ordinal<Traits>::GetLengthWithoutTrailingZeroDigits( 375 size_t Ordinal<Traits>::GetLengthWithoutTrailingZeroDigits(
371 const std::string& bytes, size_t length) { 376 const std::string& bytes, size_t length) {
372 DCHECK(!bytes.empty()); 377 DCHECK(!bytes.empty());
373 DCHECK_GT(length, 0U); 378 DCHECK_GT(length, 0U);
374 379
375 size_t end_position = 380 size_t end_position =
376 bytes.find_last_not_of(static_cast<char>(kZeroDigit), length - 1); 381 bytes.find_last_not_of(static_cast<char>(kZeroDigit), length - 1);
377 382
378 // If no non kZeroDigit is found then the string is a string of all zeros 383 // If no non kZeroDigit is found then the string is a string of all zeros
379 // digits so we return 0 as the correct length. 384 // digits so we return 0 as the correct length.
380 if (end_position == std::string::npos) 385 if (end_position == std::string::npos)
381 return 0; 386 return 0;
382 387
383 return end_position + 1; 388 return end_position + 1;
384 } 389 }
385 390
386 template <typename Traits> 391 template <typename Traits>
387 uint8 Ordinal<Traits>::GetDigit(const std::string& bytes, size_t i) { 392 uint8_t Ordinal<Traits>::GetDigit(const std::string& bytes, size_t i) {
388 return (i < bytes.length()) ? bytes[i] : kZeroDigit; 393 return (i < bytes.length()) ? bytes[i] : kZeroDigit;
389 } 394 }
390 395
391 template <typename Traits> 396 template <typename Traits>
392 int Ordinal<Traits>::GetDigitValue(const std::string& bytes, size_t i) { 397 int Ordinal<Traits>::GetDigitValue(const std::string& bytes, size_t i) {
393 return GetDigit(bytes, i) - kZeroDigit; 398 return GetDigit(bytes, i) - kZeroDigit;
394 } 399 }
395 400
396 template <typename Traits> 401 template <typename Traits>
397 int Ordinal<Traits>::AddDigitValue(std::string* bytes, 402 int Ordinal<Traits>::AddDigitValue(std::string* bytes,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 DCHECK_LT(midpoint, end_bytes); 480 DCHECK_LT(midpoint, end_bytes);
476 481
477 Ordinal<Traits> midpoint_ordinal(midpoint); 482 Ordinal<Traits> midpoint_ordinal(midpoint);
478 DCHECK(midpoint_ordinal.IsValid()); 483 DCHECK(midpoint_ordinal.IsValid());
479 return midpoint_ordinal; 484 return midpoint_ordinal;
480 } 485 }
481 486
482 } // namespace syncer 487 } // namespace syncer
483 488
484 #endif // SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_ 489 #endif // SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_
OLDNEW
« no previous file with comments | « sync/internal_api/public/base/node_ordinal_unittest.cc ('k') | sync/internal_api/public/base/unique_position.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698