1 | #ifndef __RANDOMFILE_HH__␊ |
2 | #define __RANDOMFILE_HH__␊ |
3 | ␊ |
4 | // copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>␊ |
5 | // all rights reserved.␊ |
6 | // licensed to the public under the terms of the GNU GPL (>= 2)␊ |
7 | // see the file COPYING for details␊ |
8 | ␊ |
9 | #include <string>␊ |
10 | #include <vector>␊ |
11 | #include <stdlib.h>␊ |
12 | #include <boost/lexical_cast.hpp>␊ |
13 | ␊ |
14 | struct file_randomizer␊ |
15 | {␊ |
16 | ␊ |
17 | std::vector<std::string> lines;␊ |
18 | std::string prefix;␊ |
19 | ␊ |
20 | void seed(int seed = 0xf00feed) ␊ |
21 | { ␊ |
22 | srand (seed); ␊ |
23 | }␊ |
24 | ␊ |
25 | size_t random_index(bool last_line_ok = true)␊ |
26 | {␊ |
27 | if (last_line_ok)␊ |
28 | return static_cast<size_t>(rand() % lines.size());␊ |
29 | else␊ |
30 | {␊ |
31 | ␉if (lines.size() == 0)␊ |
32 | ␉ return 0;␊ |
33 | ␉else␊ |
34 | ␉ return static_cast<size_t>(rand() % (lines.size() - 1));␊ |
35 | }␊ |
36 | }␊ |
37 | ␊ |
38 | bool random_bool()␊ |
39 | {␊ |
40 | return (rand() % 2 == 0);␊ |
41 | }␊ |
42 | ␊ |
43 | void set_prefix(std::string const & p)␊ |
44 | {␊ |
45 | prefix = p;␊ |
46 | }␊ |
47 | ␊ |
48 | void append_to(std::vector<std::string> & other)␊ |
49 | {␊ |
50 | for (std::vector<std::string>::const_iterator i = lines.begin();␊ |
51 | ␉ i != lines.end(); ++i)␊ |
52 | other.push_back(prefix + *i);␊ |
53 | }␊ |
54 | ␊ |
55 | void initial_sequential_lines(int num_lines = 100) {␊ |
56 | lines.clear();␊ |
57 | for (int i = 0; i < num_lines; ++i)␊ |
58 | {␊ |
59 | ␉lines.push_back(std::string("initial ") + boost::lexical_cast<std::string>(i));␊ |
60 | }␊ |
61 | }␊ |
62 | ␊ |
63 | void append_sequential_lines(int num_lines = 10) {␊ |
64 | lines.clear();␊ |
65 | for (int i = 0; i < num_lines; ++i)␊ |
66 | {␊ |
67 | ␉lines.push_back(std::string("append ") + boost::lexical_cast<std::string>(i));␊ |
68 | }␊ |
69 | }␊ |
70 | ␊ |
71 | void prepend_sequential_lines(int num_lines = 10) {␊ |
72 | lines.clear();␊ |
73 | for (int i = 0; i < num_lines; ++i)␊ |
74 | {␊ |
75 | ␉lines.push_back(std::string("prepend ") + boost::lexical_cast<std::string>(i));␊ |
76 | }␊ |
77 | }␊ |
78 | ␊ |
79 | void delete_percent_of_lines_randomly(int percent = 50) {␊ |
80 | double scale = static_cast<double>(percent) / 100.0;␊ |
81 | double nlines_d = static_cast<double>(lines.size()) * scale;␊ |
82 | int nlines = static_cast<int>(nlines_d);␊ |
83 | for (int i = 0; i < nlines; ++i)␊ |
84 | lines.erase(lines.begin() + random_index(false));␊ |
85 | }␊ |
86 | ␊ |
87 | void insert_sequential_percent_of_lines_randomly(int percent = 50) {␊ |
88 | double scale = static_cast<double>(percent) / 100.0;␊ |
89 | double nlines_d = static_cast<double>(lines.size()) * scale;␊ |
90 | int nlines = static_cast<int>(nlines_d);␊ |
91 | for (int i = 0; i < nlines; ++i)␊ |
92 | {␊ |
93 | ␉lines.insert(lines.begin() + random_index(),␊ |
94 | ␉␉ std::string("insert ") + boost::lexical_cast<std::string>(i));␊ |
95 | }␊ |
96 | }␊ |
97 | ␊ |
98 | static void build_random_fork(std::vector<std::string> & ancestor,␊ |
99 | ␉␉␉␉std::vector<std::string> & left,␊ |
100 | ␉␉␉␉std::vector<std::string> & right,␊ |
101 | ␉␉␉␉std::vector<std::string> & merged,␊ |
102 | ␉␉␉␉int seed,␊ |
103 | ␉␉␉␉int n_hunks = 10)␊ |
104 | { ␊ |
105 | ␊ |
106 | file_randomizer fr;␊ |
107 | fr.seed(seed);␊ |
108 | // maybe prepend something to one side or the other␊ |
109 | if (fr.random_bool())␊ |
110 | {␊ |
111 | ␉fr.prepend_sequential_lines();␊ |
112 | ␉if (fr.random_bool())␊ |
113 | ␉ fr.append_to(left);␊ |
114 | ␉else␊ |
115 | ␉ fr.append_to(right);␊ |
116 | ␉fr.append_to(merged);␊ |
117 | }␊ |
118 | fr.lines.clear();␊ |
119 | ␊ |
120 | for (int h = 0; h < n_hunks; ++h)␊ |
121 | {␊ |
122 | ␉file_randomizer hr;␊ |
123 | ␉hr.seed(seed + h);␊ |
124 | ␉hr.set_prefix(std::string("hunk ") + boost::lexical_cast<std::string>(h) + " -- ");␊ |
125 | ␉hr.initial_sequential_lines(10);␊ |
126 | ␉hr.append_to(ancestor);␊ |
127 | ␉if (hr.random_bool())␊ |
128 | ␉ {␊ |
129 | ␉ // doing an insert␊ |
130 | ␉ if (hr.random_bool())␊ |
131 | ␉ {␊ |
132 | ␉␉// inserting in left␊ |
133 | ␉␉hr.append_to(right);␊ |
134 | ␉␉hr.insert_sequential_percent_of_lines_randomly();␊ |
135 | ␉␉hr.append_to(left);␊ |
136 | ␉ }␊ |
137 | ␉ else␊ |
138 | ␉ {␊ |
139 | ␉␉// inserting in right␊ |
140 | ␉␉hr.append_to(left);␊ |
141 | ␉␉hr.insert_sequential_percent_of_lines_randomly();␊ |
142 | ␉␉hr.append_to(right);␊ |
143 | ␉ }␊ |
144 | ␉ hr.append_to(merged);␊ |
145 | ␉ }␊ |
146 | ␉else␊ |
147 | ␉ {␊ |
148 | ␉ // doing a delete␊ |
149 | ␉ if (hr.random_bool())␊ |
150 | ␉ {␊ |
151 | ␉␉// deleting in left␊ |
152 | ␉␉hr.append_to(right);␊ |
153 | ␉␉hr.delete_percent_of_lines_randomly();␊ |
154 | ␉␉hr.append_to(left);␊ |
155 | ␉ }␊ |
156 | ␉ else␊ |
157 | ␉ {␊ |
158 | ␉␉// deleting in right␊ |
159 | ␉␉hr.append_to(left);␊ |
160 | ␉␉hr.delete_percent_of_lines_randomly();␊ |
161 | ␉␉hr.append_to(right);␊ |
162 | ␉ }␊ |
163 | ␉ hr.append_to(merged);␊ |
164 | ␉ }␊ |
165 | }␊ |
166 | ␊ |
167 | // maybe append something to one side or the other␊ |
168 | if (fr.random_bool())␊ |
169 | {␊ |
170 | ␉fr.append_sequential_lines();␊ |
171 | ␉if (fr.random_bool())␊ |
172 | ␉ fr.append_to(left);␊ |
173 | ␉else␊ |
174 | ␉ fr.append_to(right);␊ |
175 | ␉fr.append_to(merged);␊ |
176 | }␊ |
177 | }␊ |
178 | };␊ |
179 | ␊ |
180 | #endif // __RANDOMFILE_HH__␊ |