File: string_ordinal.h

package info (click to toggle)
chromium 138.0.7204.92-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,576 kB
  • sloc: cpp: 34,933,512; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,956; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (211 lines) | stat: -rw-r--r-- 8,194 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SYNC_MODEL_STRING_ORDINAL_H_
#define COMPONENTS_SYNC_MODEL_STRING_ORDINAL_H_

#include <cstddef>
#include <cstdint>
#include <string>

namespace mojo {
template <typename DataViewType, typename T>
struct StructTraits;
}

namespace syncer {

namespace mojom {
class StringOrdinalDataView;
}

// WARNING, DO NOT USE! Use UniquePosition instead.
//
//
// A StringOrdinal is an object that can be used for ordering. The
// StringOrdinal class has an unbounded dense strict total order, which
// mean for any StringOrdinals a, b and c:
//
//  - a < b and b < c implies a < c (transitivity);
//  - exactly one of a < b, b < a and a = b holds (trichotomy);
//  - if a < b, there is a StringOrdinal x such that a < x < b (density);
//  - there are Ordinals<T> x and y such that x < a < y (unboundedness).
//
// This means that when StringOrdinal is used for sorting a list, if any
// item changes its position in the list, only its StringOrdinal value
// has to change to represent the new order, and all the other values
// can stay the same.
//
// A StringOrdinal is internally represented as an array of bytes, so it
// can be serialized to and deserialized from disk.
//
// A StringOrdinal is valid iff its corresponding string has at least
// kMinLength characters, does not contain any characters less than
// kZeroDigit or greater than kMaxDigit, is not all zero digits, and
// does not have any unnecessary trailing zero digits.
//
// Since StringOrdinals contain only printable characters, it is safe
// to store as a string in a protobuf.
class StringOrdinal {
 public:
  // Functors for use with STL algorithms and containers.
  class LessThanFn {
   public:
    LessThanFn();

    bool operator()(const StringOrdinal& lhs, const StringOrdinal& rhs) const;
  };

  class EqualsFn {
   public:
    EqualsFn();

    bool operator()(const StringOrdinal& lhs, const StringOrdinal& rhs) const;
  };

  // Creates an StringOrdinal from the given string of bytes. The StringOrdinal
  // may be valid or invalid.
  explicit StringOrdinal(std::string bytes);

  // Creates an invalid StringOrdinal.
  StringOrdinal();

  // Creates a valid initial StringOrdinal. This is called to create the first
  // element of StringOrdinal list (i.e. before we have any other values we can
  // generate from).
  static StringOrdinal CreateInitialOrdinal();

  // Returns true iff this StringOrdinal is valid.  This takes constant
  // time.
  bool IsValid() const;

  // Returns true iff `*this` == `other` or `*this` and `other`
  // are both invalid.
  bool EqualsOrBothInvalid(const StringOrdinal& other) const;

  // Returns a printable string representation of the StringOrdinal suitable
  // for logging.
  std::string ToDebugString() const;

  // All remaining functions can only be called if IsValid() holds.
  // It is an error to call them if IsValid() is false.

  // Order-related functions.

  // Returns true iff `*this` < `other`.
  bool LessThan(const StringOrdinal& other) const;

  // Returns true iff `*this` > `other`.
  bool GreaterThan(const StringOrdinal& other) const;

  // Returns true iff `*this` == `other` (i.e. `*this` < `other` and
  // `other` < `*this` are both false).
  bool Equals(const StringOrdinal& other) const;

  // Given `*this` != `other`, returns a StringOrdinal x such that
  // min(`*this`, `other`) < x < max(`*this`, `other`). It is an error
  // to call this function when `*this` == `other`.
  StringOrdinal CreateBetween(const StringOrdinal& other) const;

  // Returns a StringOrdinal `x` such that `x` < `*this`.
  StringOrdinal CreateBefore() const;

  // Returns a StringOrdinal `x` such that `*this` < `x`.
  StringOrdinal CreateAfter() const;

  // Returns the string of bytes representing the StringOrdinal.  It is
  // guaranteed that an StringOrdinal constructed from the returned string
  // will be valid.
  std::string ToInternalValue() const;

  // Use of copy constructor and default assignment for this class is allowed.

  // Constants for StringOrdinal digits.
  static const uint8_t kZeroDigit = 'a';
  static const uint8_t kMaxDigit = 'z';
  static const size_t kMinLength = 1;
  static const uint8_t kOneDigit = kZeroDigit + 1;
  static const uint8_t kMidDigit = kOneDigit + (kMaxDigit - kOneDigit) / 2;
  static const unsigned int kMidDigitValue = kMidDigit - kZeroDigit;
  static const unsigned int kMaxDigitValue = kMaxDigit - kZeroDigit;
  static const unsigned int kRadix = kMaxDigitValue + 1;

  static_assert(kOneDigit > kZeroDigit, "incorrect StringOrdinal one digit");
  static_assert(kMidDigit > kOneDigit, "incorrect StringOrdinal mid digit");
  static_assert(kMaxDigit > kMidDigit, "incorrect StringOrdinal max digit");
  static_assert(kMinLength > 0, "incorrect StringOrdinal min length");
  static_assert(kMidDigitValue > 1, "incorrect StringOrdinal mid digit");
  static_assert(kMaxDigitValue > kMidDigitValue,
                "incorrect StringOrdinal max digit");
  static_assert(kRadix == kMaxDigitValue + 1, "incorrect StringOrdinal radix");

 private:
  friend struct mojo::StructTraits<syncer::mojom::StringOrdinalDataView,
                                   StringOrdinal>;

  // Returns true iff the given byte string satisfies the criteria for
  // a valid StringOrdinal.
  static bool IsValidOrdinalBytes(const std::string& bytes);

  // Returns the length that bytes.substr(0, length) would be with
  // trailing zero digits removed.
  static size_t GetLengthWithoutTrailingZeroDigits(const std::string& bytes,
                                                   size_t length);

  // Returns the digit at position i, padding with zero digits if
  // required.
  static uint8_t GetDigit(const std::string& bytes, size_t i);

  // Returns the digit value at position i, padding with 0 if required.
  static int GetDigitValue(const std::string& bytes, size_t i);

  // Adds the given value to `bytes` at position i, carrying when
  // necessary.  Returns the left-most carry.
  static int AddDigitValue(std::string* bytes, size_t i, int digit_value);

  // Returns the proper length `bytes` should be resized to, i.e. the
  // smallest length such that `bytes` is still greater than
  // `lower_bound` and is still valid.  `bytes` should be greater than
  // `lower_bound`.
  static size_t GetProperLength(const std::string& lower_bound,
                                const std::string& bytes);

  // Compute the midpoint StringOrdinal byte string that is between `start`
  // and `end`.
  static std::string ComputeMidpoint(const std::string& start,
                                     const std::string& end);

  // Create a StringOrdinal that is lexicographically greater than `start` and
  // lexicographically less than `end`. The returned StringOrdinal will be
  // roughly between `start` and `end`.
  static StringOrdinal CreateOrdinalBetween(const StringOrdinal& start,
                                            const StringOrdinal& end);

  // The internal byte string representation of the StringOrdinal.  Never
  // changes after construction except for assignment.
  std::string bytes_;

  // A cache of the result of IsValidOrdinalBytes(bytes_).
  bool is_valid_;
};

bool operator==(const StringOrdinal& lhs, const StringOrdinal& rhs);

static_assert(StringOrdinal::kZeroDigit == 'a',
              "StringOrdinal has incorrect zero digit");
static_assert(StringOrdinal::kOneDigit == 'b',
              "StringOrdinal has incorrect one digit");
static_assert(StringOrdinal::kMidDigit == 'n',
              "StringOrdinal has incorrect mid digit");
static_assert(StringOrdinal::kMaxDigit == 'z',
              "StringOrdinal has incorrect max digit");
static_assert(StringOrdinal::kMidDigitValue == 13,
              "StringOrdinal has incorrect mid digit value");
static_assert(StringOrdinal::kMaxDigitValue == 25,
              "StringOrdinal has incorrect max digit value");
static_assert(StringOrdinal::kRadix == 26, "StringOrdinal has incorrect radix");

}  // namespace syncer

#endif  // COMPONENTS_SYNC_MODEL_STRING_ORDINAL_H_