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