xref: /aosp_15_r20/external/regex-re2/re2/testing/string_generator.cc (revision ccdc9c3e24c519bfa4832a66aa2e83a52c19f295)
1*ccdc9c3eSSadaf Ebrahimi // Copyright 2008 The RE2 Authors.  All Rights Reserved.
2*ccdc9c3eSSadaf Ebrahimi // Use of this source code is governed by a BSD-style
3*ccdc9c3eSSadaf Ebrahimi // license that can be found in the LICENSE file.
4*ccdc9c3eSSadaf Ebrahimi 
5*ccdc9c3eSSadaf Ebrahimi // String generator: generates all possible strings of up to
6*ccdc9c3eSSadaf Ebrahimi // maxlen letters using the set of letters in alpha.
7*ccdc9c3eSSadaf Ebrahimi // Fetch strings using a Java-like Next()/HasNext() interface.
8*ccdc9c3eSSadaf Ebrahimi 
9*ccdc9c3eSSadaf Ebrahimi #include <stddef.h>
10*ccdc9c3eSSadaf Ebrahimi #include <stdint.h>
11*ccdc9c3eSSadaf Ebrahimi #include <string>
12*ccdc9c3eSSadaf Ebrahimi #include <vector>
13*ccdc9c3eSSadaf Ebrahimi 
14*ccdc9c3eSSadaf Ebrahimi #include "util/test.h"
15*ccdc9c3eSSadaf Ebrahimi #include "util/logging.h"
16*ccdc9c3eSSadaf Ebrahimi #include "re2/testing/string_generator.h"
17*ccdc9c3eSSadaf Ebrahimi 
18*ccdc9c3eSSadaf Ebrahimi namespace re2 {
19*ccdc9c3eSSadaf Ebrahimi 
StringGenerator(int maxlen,const std::vector<string> & alphabet)20*ccdc9c3eSSadaf Ebrahimi StringGenerator::StringGenerator(int maxlen,
21*ccdc9c3eSSadaf Ebrahimi                                  const std::vector<string>& alphabet)
22*ccdc9c3eSSadaf Ebrahimi     : maxlen_(maxlen), alphabet_(alphabet),
23*ccdc9c3eSSadaf Ebrahimi       generate_null_(false),
24*ccdc9c3eSSadaf Ebrahimi       random_(false), nrandom_(0) {
25*ccdc9c3eSSadaf Ebrahimi 
26*ccdc9c3eSSadaf Ebrahimi   // Degenerate case: no letters, no non-empty strings.
27*ccdc9c3eSSadaf Ebrahimi   if (alphabet_.empty())
28*ccdc9c3eSSadaf Ebrahimi     maxlen_ = 0;
29*ccdc9c3eSSadaf Ebrahimi 
30*ccdc9c3eSSadaf Ebrahimi   // Next() will return empty string (digits_ is empty).
31*ccdc9c3eSSadaf Ebrahimi   hasnext_ = true;
32*ccdc9c3eSSadaf Ebrahimi }
33*ccdc9c3eSSadaf Ebrahimi 
34*ccdc9c3eSSadaf Ebrahimi // Resets the string generator state to the beginning.
Reset()35*ccdc9c3eSSadaf Ebrahimi void StringGenerator::Reset() {
36*ccdc9c3eSSadaf Ebrahimi   digits_.clear();
37*ccdc9c3eSSadaf Ebrahimi   hasnext_ = true;
38*ccdc9c3eSSadaf Ebrahimi   random_ = false;
39*ccdc9c3eSSadaf Ebrahimi   nrandom_ = 0;
40*ccdc9c3eSSadaf Ebrahimi   generate_null_ = false;
41*ccdc9c3eSSadaf Ebrahimi }
42*ccdc9c3eSSadaf Ebrahimi 
43*ccdc9c3eSSadaf Ebrahimi // Increments the big number in digits_, returning true if successful.
44*ccdc9c3eSSadaf Ebrahimi // Returns false if all the numbers have been used.
IncrementDigits()45*ccdc9c3eSSadaf Ebrahimi bool StringGenerator::IncrementDigits() {
46*ccdc9c3eSSadaf Ebrahimi   // First try to increment the current number.
47*ccdc9c3eSSadaf Ebrahimi   for (int i = static_cast<int>(digits_.size()) - 1; i >= 0; i--) {
48*ccdc9c3eSSadaf Ebrahimi     if (++digits_[i] < static_cast<int>(alphabet_.size()))
49*ccdc9c3eSSadaf Ebrahimi       return true;
50*ccdc9c3eSSadaf Ebrahimi     digits_[i] = 0;
51*ccdc9c3eSSadaf Ebrahimi   }
52*ccdc9c3eSSadaf Ebrahimi 
53*ccdc9c3eSSadaf Ebrahimi   // If that failed, make a longer number.
54*ccdc9c3eSSadaf Ebrahimi   if (static_cast<int>(digits_.size()) < maxlen_) {
55*ccdc9c3eSSadaf Ebrahimi     digits_.push_back(0);
56*ccdc9c3eSSadaf Ebrahimi     return true;
57*ccdc9c3eSSadaf Ebrahimi   }
58*ccdc9c3eSSadaf Ebrahimi 
59*ccdc9c3eSSadaf Ebrahimi   return false;
60*ccdc9c3eSSadaf Ebrahimi }
61*ccdc9c3eSSadaf Ebrahimi 
62*ccdc9c3eSSadaf Ebrahimi // Generates random digits_, return true if successful.
63*ccdc9c3eSSadaf Ebrahimi // Returns false if the random sequence is over.
RandomDigits()64*ccdc9c3eSSadaf Ebrahimi bool StringGenerator::RandomDigits() {
65*ccdc9c3eSSadaf Ebrahimi   if (--nrandom_ <= 0)
66*ccdc9c3eSSadaf Ebrahimi     return false;
67*ccdc9c3eSSadaf Ebrahimi 
68*ccdc9c3eSSadaf Ebrahimi   std::uniform_int_distribution<int> random_len(0, maxlen_);
69*ccdc9c3eSSadaf Ebrahimi   std::uniform_int_distribution<int> random_alphabet_index(
70*ccdc9c3eSSadaf Ebrahimi       0, static_cast<int>(alphabet_.size()) - 1);
71*ccdc9c3eSSadaf Ebrahimi 
72*ccdc9c3eSSadaf Ebrahimi   // Pick length.
73*ccdc9c3eSSadaf Ebrahimi   int len = random_len(rng_);
74*ccdc9c3eSSadaf Ebrahimi   digits_.resize(len);
75*ccdc9c3eSSadaf Ebrahimi   for (int i = 0; i < len; i++)
76*ccdc9c3eSSadaf Ebrahimi     digits_[i] = random_alphabet_index(rng_);
77*ccdc9c3eSSadaf Ebrahimi   return true;
78*ccdc9c3eSSadaf Ebrahimi }
79*ccdc9c3eSSadaf Ebrahimi 
80*ccdc9c3eSSadaf Ebrahimi // Returns the next string in the iteration, which is the one
81*ccdc9c3eSSadaf Ebrahimi // currently described by digits_.  Calls IncrementDigits
82*ccdc9c3eSSadaf Ebrahimi // after computing the string, so that it knows the answer
83*ccdc9c3eSSadaf Ebrahimi // for subsequent HasNext() calls.
Next()84*ccdc9c3eSSadaf Ebrahimi const StringPiece& StringGenerator::Next() {
85*ccdc9c3eSSadaf Ebrahimi   CHECK(hasnext_);
86*ccdc9c3eSSadaf Ebrahimi   if (generate_null_) {
87*ccdc9c3eSSadaf Ebrahimi     generate_null_ = false;
88*ccdc9c3eSSadaf Ebrahimi     sp_ = StringPiece();
89*ccdc9c3eSSadaf Ebrahimi     return sp_;
90*ccdc9c3eSSadaf Ebrahimi   }
91*ccdc9c3eSSadaf Ebrahimi   s_.clear();
92*ccdc9c3eSSadaf Ebrahimi   for (size_t i = 0; i < digits_.size(); i++) {
93*ccdc9c3eSSadaf Ebrahimi     s_ += alphabet_[digits_[i]];
94*ccdc9c3eSSadaf Ebrahimi   }
95*ccdc9c3eSSadaf Ebrahimi   hasnext_ = random_ ? RandomDigits() : IncrementDigits();
96*ccdc9c3eSSadaf Ebrahimi   sp_ = s_;
97*ccdc9c3eSSadaf Ebrahimi   return sp_;
98*ccdc9c3eSSadaf Ebrahimi }
99*ccdc9c3eSSadaf Ebrahimi 
100*ccdc9c3eSSadaf Ebrahimi // Sets generator up to return n random strings.
Random(int32_t seed,int n)101*ccdc9c3eSSadaf Ebrahimi void StringGenerator::Random(int32_t seed, int n) {
102*ccdc9c3eSSadaf Ebrahimi   rng_.seed(seed);
103*ccdc9c3eSSadaf Ebrahimi 
104*ccdc9c3eSSadaf Ebrahimi   random_ = true;
105*ccdc9c3eSSadaf Ebrahimi   nrandom_ = n;
106*ccdc9c3eSSadaf Ebrahimi   hasnext_ = nrandom_ > 0;
107*ccdc9c3eSSadaf Ebrahimi }
108*ccdc9c3eSSadaf Ebrahimi 
GenerateNULL()109*ccdc9c3eSSadaf Ebrahimi void StringGenerator::GenerateNULL() {
110*ccdc9c3eSSadaf Ebrahimi   generate_null_ = true;
111*ccdc9c3eSSadaf Ebrahimi   hasnext_ = true;
112*ccdc9c3eSSadaf Ebrahimi }
113*ccdc9c3eSSadaf Ebrahimi 
114*ccdc9c3eSSadaf Ebrahimi }  // namespace re2
115