QuickCheck++  0.0.3
Automated testing library
generate.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Cyril Soldani
3  *
4  * This file is part of QuickCheck++.
5  *
6  * QuickCheck++ is free software: you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the Free
8  * Software Foundation, either version 3 of the License, or (at your option)
9  * any later version.
10  *
11  * QuickCheck++ is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * QuickCheck++. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
30 #ifndef QUICKCHECK_GENERATE_H
31 #define QUICKCHECK_GENERATE_H
32 
33 #include <algorithm>
34 #include <cassert>
35 #include <cstdlib>
36 #include <limits>
37 #include <vector>
38 
39 namespace quickcheck {
40 
51 template<class A>
52 A generateInRange(A low, A high)
53 {
54  assert(low <= high);
55  A offset = static_cast<A>(double(rand()) / RAND_MAX
56  * (double(high) - double(low) + 1));
57  return static_cast<A>(low + offset);
58 }
59 
68 template<class A, class Iter>
69 A oneOf(Iter first, Iter last)
70 {
71  assert(std::distance(first, last) > 0);
72  size_t len = size_t(std::distance(first, last));
73  assert(len > 0);
74  size_t index = generateInRange(size_t(0), len - 1);
75  Iter i;
76  for (i = first; index != 0; ++i)
77  --index;
78  return *i;
79 }
80 
93 template<class A>
94 A generateInteger(size_t n)
95 {
96  // not appropriate for floats as it chooses only integers
97  assert(std::numeric_limits<A>::is_integer);
98  // clips [-n, n] interval if necessary
99  A max = std::numeric_limits<A>::max();
100  A min = std::numeric_limits<A>::min();
101  A high = (n > size_t(max)) ? max : A(n);
102  A low = (n > size_t(-min)) ? min : A(-n);
103  // generates integer in clipped interval
104  return generateInRange(low, high);
105 }
106 
112 static inline void generate(size_t, bool& out)
113 {
114  static const bool booleans[] = { true, false };
115  out = oneOf<bool>(&booleans[0], &booleans[2]);
116 }
117 
131 static inline void generate(size_t n, char& out)
132 {
133  static const char *basicChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
134  "abcdefghijklmnopqrstuvwxyz";
135  if (n < sizeof (basicChars) - 1)
136  out = oneOf<char>(&basicChars[0], &basicChars[n]);
137  else if (n < 95)
138  out = generateInRange(' ', '~'); // any printable ASCII
139  else
140  out = generateInRange(char(0x00), char(0xff));
141 }
142 
146 static inline void generate(size_t n, unsigned char& out)
147 {
148  char c;
149  generate(n, c);
150  out = static_cast<unsigned char>(c);
151 }
152 
159 static inline void generate(size_t n, short& out)
160 {
161  out = generateInteger<short>(n);
162 }
163 
170 static inline void generate(size_t n, unsigned short& out)
171 {
172  out = generateInteger<unsigned short>(n);
173 }
174 
181 static inline void generate(size_t n, int& out)
182 {
183  out = generateInteger<int>(n);
184 }
185 
192 static inline void generate(size_t n, unsigned int& out)
193 {
194  out = generateInteger<unsigned int>(n);
195 }
196 
203 static inline void generate(size_t n, long& out)
204 {
205  out = generateInteger<long>(n);
206 }
207 
214 static inline void generate(size_t n, unsigned long& out)
215 {
216  out = generateInteger<unsigned long>(n);
217 }
218 
225 static inline void generate(size_t n, float& out)
226 {
227  out = float(rand()) / float(RAND_MAX) * 2 * float(n) - float(n);
228 }
229 
236 static inline void generate(size_t n, double& out)
237 {
238  out = double(rand()) / RAND_MAX * 2 * double(n) - double(n);
239 }
240 
247 static inline void generate(size_t n, long double& out)
248 {
249  out = static_cast<long double>(rand()) / RAND_MAX * 2 * n - n;
250 }
251 
260 template<class A>
261 void generate(size_t n, std::vector<A>& out)
262 {
263  unsigned len;
264  generate(n, len);
265  for (size_t i = 0; i < len; ++i) {
266  A a;
267  generate(n - 1, a);
268  out.push_back(a);
269  }
270 }
271 
272 }
273 
274 #endif // !QUICKCHECK_GENERATE_H