| 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 |