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 COMPONENTS_SYNC_BASE_ORDINAL_H_ |
6 #define SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_ | 6 #define COMPONENTS_SYNC_BASE_ORDINAL_H_ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <cstddef> | 11 #include <cstddef> |
12 #include <string> | 12 #include <string> |
13 | 13 |
14 #include "base/json/string_escape.h" | 14 #include "base/json/string_escape.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 | 16 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 static_assert(kMaxDigitValue > kMidDigitValue, "incorrect ordinal max digit"); | 150 static_assert(kMaxDigitValue > kMidDigitValue, "incorrect ordinal max digit"); |
151 static_assert(kRadix == kMaxDigitValue + 1, "incorrect ordinal radix"); | 151 static_assert(kRadix == kMaxDigitValue + 1, "incorrect ordinal radix"); |
152 | 152 |
153 private: | 153 private: |
154 // Returns true iff the given byte string satisfies the criteria for | 154 // Returns true iff the given byte string satisfies the criteria for |
155 // a valid Ordinal. | 155 // a valid Ordinal. |
156 static bool IsValidOrdinalBytes(const std::string& bytes); | 156 static bool IsValidOrdinalBytes(const std::string& bytes); |
157 | 157 |
158 // Returns the length that bytes.substr(0, length) would be with | 158 // Returns the length that bytes.substr(0, length) would be with |
159 // trailing zero digits removed. | 159 // trailing zero digits removed. |
160 static size_t GetLengthWithoutTrailingZeroDigits( | 160 static size_t GetLengthWithoutTrailingZeroDigits(const std::string& bytes, |
161 const std::string& bytes, | 161 size_t length); |
162 size_t length); | |
163 | 162 |
164 // Returns the digit at position i, padding with zero digits if | 163 // Returns the digit at position i, padding with zero digits if |
165 // required. | 164 // required. |
166 static uint8_t GetDigit(const std::string& bytes, size_t i); | 165 static uint8_t GetDigit(const std::string& bytes, size_t i); |
167 | 166 |
168 // Returns the digit value at position i, padding with 0 if required. | 167 // Returns the digit value at position i, padding with 0 if required. |
169 static int GetDigitValue(const std::string& bytes, size_t i); | 168 static int GetDigitValue(const std::string& bytes, size_t i); |
170 | 169 |
171 // Adds the given value to |bytes| at position i, carrying when | 170 // Adds the given value to |bytes| at position i, carrying when |
172 // necessary. Returns the left-most carry. | 171 // necessary. Returns the left-most carry. |
(...skipping 22 matching lines...) Expand all Loading... |
195 std::string bytes_; | 194 std::string bytes_; |
196 | 195 |
197 // A cache of the result of IsValidOrdinalBytes(bytes_). | 196 // A cache of the result of IsValidOrdinalBytes(bytes_). |
198 bool is_valid_; | 197 bool is_valid_; |
199 }; | 198 }; |
200 | 199 |
201 template <typename Traits> | 200 template <typename Traits> |
202 const uint8_t Ordinal<Traits>::kZeroDigit; | 201 const uint8_t Ordinal<Traits>::kZeroDigit; |
203 template <typename Traits> | 202 template <typename Traits> |
204 const uint8_t Ordinal<Traits>::kMaxDigit; | 203 const uint8_t Ordinal<Traits>::kMaxDigit; |
205 template <typename Traits> const size_t Ordinal<Traits>::kMinLength; | 204 template <typename Traits> |
| 205 const size_t Ordinal<Traits>::kMinLength; |
206 template <typename Traits> | 206 template <typename Traits> |
207 const uint8_t Ordinal<Traits>::kOneDigit; | 207 const uint8_t Ordinal<Traits>::kOneDigit; |
208 template <typename Traits> | 208 template <typename Traits> |
209 const uint8_t Ordinal<Traits>::kMidDigit; | 209 const uint8_t Ordinal<Traits>::kMidDigit; |
210 template <typename Traits> const unsigned int Ordinal<Traits>::kMidDigitValue; | 210 template <typename Traits> |
211 template <typename Traits> const unsigned int Ordinal<Traits>::kMaxDigitValue; | 211 const unsigned int Ordinal<Traits>::kMidDigitValue; |
212 template <typename Traits> const unsigned int Ordinal<Traits>::kRadix; | 212 template <typename Traits> |
| 213 const unsigned int Ordinal<Traits>::kMaxDigitValue; |
| 214 template <typename Traits> |
| 215 const unsigned int Ordinal<Traits>::kRadix; |
213 | 216 |
214 template <typename Traits> | 217 template <typename Traits> |
215 Ordinal<Traits>::LessThanFn::LessThanFn() {} | 218 Ordinal<Traits>::LessThanFn::LessThanFn() {} |
216 | 219 |
217 template <typename Traits> | 220 template <typename Traits> |
218 bool Ordinal<Traits>::LessThanFn::operator()(const Ordinal<Traits>& lhs, | 221 bool Ordinal<Traits>::LessThanFn::operator()(const Ordinal<Traits>& lhs, |
219 const Ordinal<Traits>& rhs) const { | 222 const Ordinal<Traits>& rhs) const { |
220 return lhs.LessThan(rhs); | 223 return lhs.LessThan(rhs); |
221 } | 224 } |
222 | 225 |
223 template <typename Traits> | 226 template <typename Traits> |
224 Ordinal<Traits>::EqualsFn::EqualsFn() {} | 227 Ordinal<Traits>::EqualsFn::EqualsFn() {} |
225 | 228 |
226 template <typename Traits> | 229 template <typename Traits> |
227 bool Ordinal<Traits>::EqualsFn::operator()(const Ordinal<Traits>& lhs, | 230 bool Ordinal<Traits>::EqualsFn::operator()(const Ordinal<Traits>& lhs, |
228 const Ordinal<Traits>& rhs) const { | 231 const Ordinal<Traits>& rhs) const { |
229 return lhs.Equals(rhs); | 232 return lhs.Equals(rhs); |
230 } | 233 } |
231 | 234 |
232 template <typename Traits> | 235 template <typename Traits> |
233 Ordinal<Traits>::Ordinal(const std::string& bytes) | 236 Ordinal<Traits>::Ordinal(const std::string& bytes) |
234 : bytes_(bytes), | 237 : bytes_(bytes), is_valid_(IsValidOrdinalBytes(bytes_)) {} |
235 is_valid_(IsValidOrdinalBytes(bytes_)) {} | |
236 | 238 |
237 template <typename Traits> | 239 template <typename Traits> |
238 Ordinal<Traits>::Ordinal() : is_valid_(false) {} | 240 Ordinal<Traits>::Ordinal() : is_valid_(false) {} |
239 | 241 |
240 template <typename Traits> | 242 template <typename Traits> |
241 Ordinal<Traits> Ordinal<Traits>::CreateInitialOrdinal() { | 243 Ordinal<Traits> Ordinal<Traits>::CreateInitialOrdinal() { |
242 std::string bytes(Traits::kMinLength, kZeroDigit); | 244 std::string bytes(Traits::kMinLength, kZeroDigit); |
243 bytes[0] = kMidDigit; | 245 bytes[0] = kMidDigit; |
244 return Ordinal(bytes); | 246 return Ordinal(bytes); |
245 } | 247 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 const uint8_t last_byte = bytes[length - 1]; | 368 const uint8_t last_byte = bytes[length - 1]; |
367 if (last_byte == kZeroDigit) | 369 if (last_byte == kZeroDigit) |
368 return false; | 370 return false; |
369 } | 371 } |
370 | 372 |
371 return true; | 373 return true; |
372 } | 374 } |
373 | 375 |
374 template <typename Traits> | 376 template <typename Traits> |
375 size_t Ordinal<Traits>::GetLengthWithoutTrailingZeroDigits( | 377 size_t Ordinal<Traits>::GetLengthWithoutTrailingZeroDigits( |
376 const std::string& bytes, size_t length) { | 378 const std::string& bytes, |
| 379 size_t length) { |
377 DCHECK(!bytes.empty()); | 380 DCHECK(!bytes.empty()); |
378 DCHECK_GT(length, 0U); | 381 DCHECK_GT(length, 0U); |
379 | 382 |
380 size_t end_position = | 383 size_t end_position = |
381 bytes.find_last_not_of(static_cast<char>(kZeroDigit), length - 1); | 384 bytes.find_last_not_of(static_cast<char>(kZeroDigit), length - 1); |
382 | 385 |
383 // If no non kZeroDigit is found then the string is a string of all zeros | 386 // If no non kZeroDigit is found then the string is a string of all zeros |
384 // digits so we return 0 as the correct length. | 387 // digits so we return 0 as the correct length. |
385 if (end_position == std::string::npos) | 388 if (end_position == std::string::npos) |
386 return 0; | 389 return 0; |
387 | 390 |
388 return end_position + 1; | 391 return end_position + 1; |
389 } | 392 } |
390 | 393 |
391 template <typename Traits> | 394 template <typename Traits> |
392 uint8_t Ordinal<Traits>::GetDigit(const std::string& bytes, size_t i) { | 395 uint8_t Ordinal<Traits>::GetDigit(const std::string& bytes, size_t i) { |
393 return (i < bytes.length()) ? bytes[i] : kZeroDigit; | 396 return (i < bytes.length()) ? bytes[i] : kZeroDigit; |
394 } | 397 } |
395 | 398 |
396 template <typename Traits> | 399 template <typename Traits> |
397 int Ordinal<Traits>::GetDigitValue(const std::string& bytes, size_t i) { | 400 int Ordinal<Traits>::GetDigitValue(const std::string& bytes, size_t i) { |
398 return GetDigit(bytes, i) - kZeroDigit; | 401 return GetDigit(bytes, i) - kZeroDigit; |
399 } | 402 } |
400 | 403 |
401 template <typename Traits> | 404 template <typename Traits> |
402 int Ordinal<Traits>::AddDigitValue(std::string* bytes, | 405 int Ordinal<Traits>::AddDigitValue(std::string* bytes, |
403 size_t i, int digit_value) { | 406 size_t i, |
| 407 int digit_value) { |
404 DCHECK_GE(i, 0U); | 408 DCHECK_GE(i, 0U); |
405 DCHECK_LT(i, bytes->length()); | 409 DCHECK_LT(i, bytes->length()); |
406 | 410 |
407 for (int j = static_cast<int>(i); j >= 0 && digit_value > 0; --j) { | 411 for (int j = static_cast<int>(i); j >= 0 && digit_value > 0; --j) { |
408 int byte_j_value = GetDigitValue(*bytes, j) + digit_value; | 412 int byte_j_value = GetDigitValue(*bytes, j) + digit_value; |
409 digit_value = byte_j_value / kRadix; | 413 digit_value = byte_j_value / kRadix; |
410 DCHECK_LE(digit_value, 1); | 414 DCHECK_LE(digit_value, 1); |
411 byte_j_value %= kRadix; | 415 byte_j_value %= kRadix; |
412 (*bytes)[j] = static_cast<char>(kZeroDigit + byte_j_value); | 416 (*bytes)[j] = static_cast<char>(kZeroDigit + byte_j_value); |
413 } | 417 } |
(...skipping 14 matching lines...) Expand all Loading... |
428 GetLengthWithoutTrailingZeroDigits(bytes, drop_length - 1); | 432 GetLengthWithoutTrailingZeroDigits(bytes, drop_length - 1); |
429 | 433 |
430 if (truncated_length > 0 && | 434 if (truncated_length > 0 && |
431 bytes.compare(0, truncated_length, lower_bound) > 0) | 435 bytes.compare(0, truncated_length, lower_bound) > 0) |
432 drop_length = truncated_length; | 436 drop_length = truncated_length; |
433 } | 437 } |
434 return std::max(drop_length, kMinLength); | 438 return std::max(drop_length, kMinLength); |
435 } | 439 } |
436 | 440 |
437 template <typename Traits> | 441 template <typename Traits> |
438 std::string Ordinal<Traits>::ComputeMidpoint( | 442 std::string Ordinal<Traits>::ComputeMidpoint(const std::string& start, |
439 const std::string& start, | 443 const std::string& end) { |
440 const std::string& end) { | |
441 size_t max_size = std::max(start.length(), end.length()) + 1; | 444 size_t max_size = std::max(start.length(), end.length()) + 1; |
442 std::string midpoint(max_size, kZeroDigit); | 445 std::string midpoint(max_size, kZeroDigit); |
443 | 446 |
444 // Perform the operation (start + end) / 2 left-to-right by | 447 // Perform the operation (start + end) / 2 left-to-right by |
445 // maintaining a "forward carry" which is either 0 or | 448 // maintaining a "forward carry" which is either 0 or |
446 // kMidDigitValue. AddDigitValue() is in general O(n), but this | 449 // kMidDigitValue. AddDigitValue() is in general O(n), but this |
447 // operation is still O(n) despite that; calls to AddDigitValue() | 450 // operation is still O(n) despite that; calls to AddDigitValue() |
448 // will overflow at most to the last position where AddDigitValue() | 451 // will overflow at most to the last position where AddDigitValue() |
449 // last overflowed. | 452 // last overflowed. |
450 int forward_carry = 0; | 453 int forward_carry = 0; |
(...skipping 28 matching lines...) Expand all Loading... |
479 DCHECK_GT(midpoint, start_bytes); | 482 DCHECK_GT(midpoint, start_bytes); |
480 DCHECK_LT(midpoint, end_bytes); | 483 DCHECK_LT(midpoint, end_bytes); |
481 | 484 |
482 Ordinal<Traits> midpoint_ordinal(midpoint); | 485 Ordinal<Traits> midpoint_ordinal(midpoint); |
483 DCHECK(midpoint_ordinal.IsValid()); | 486 DCHECK(midpoint_ordinal.IsValid()); |
484 return midpoint_ordinal; | 487 return midpoint_ordinal; |
485 } | 488 } |
486 | 489 |
487 } // namespace syncer | 490 } // namespace syncer |
488 | 491 |
489 #endif // SYNC_INTERNAL_API_PUBLIC_BASE_ORDINAL_H_ | 492 #endif // COMPONENTS_SYNC_BASE_ORDINAL_H_ |
OLD | NEW |