OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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_ |
OLD | NEW |