monotone

monotone Mtn Source Tree

Root/randomfile.hh

1#ifndef __RANDOMFILE_HH__
2#define __RANDOMFILE_HH__
3
4// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
5//
6// This program is made available under the GNU GPL version 2.0 or
7// greater. See the accompanying file COPYING for details.
8//
9// This program is distributed WITHOUT ANY WARRANTY; without even the
10// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11// PURPOSE.
12
13#include "vector.hh"
14#include "lexical_cast.hh"
15
16#include "randomizer.hh"
17
18struct file_randomizer
19{
20 randomizer & rng;
21 std::vector<std::string> lines;
22 std::string prefix;
23
24 file_randomizer(randomizer & rng)
25 : rng(rng)
26 {}
27
28 size_t random_index(bool last_line_ok = true)
29 {
30 if (last_line_ok)
31 return static_cast<size_t>(rng.uniform(lines.size()));
32 else
33 {
34 if (lines.size() == 0)
35 return 0;
36 else
37 return static_cast<size_t>(rng.uniform(lines.size() - 1));
38 }
39 }
40
41 void set_prefix(std::string const & p)
42 {
43 prefix = p;
44 }
45
46 void append_to(std::vector<std::string> & other)
47 {
48 for (std::vector<std::string>::const_iterator i = lines.begin();
49 i != lines.end(); ++i)
50 other.push_back(prefix + *i);
51 }
52
53 void initial_sequential_lines(int num_lines = 100) {
54 lines.clear();
55 for (int i = 0; i < num_lines; ++i)
56 {
57 lines.push_back(std::string("initial ") + boost::lexical_cast<std::string>(i));
58 }
59 }
60
61 void append_sequential_lines(int num_lines = 10) {
62 lines.clear();
63 for (int i = 0; i < num_lines; ++i)
64 {
65 lines.push_back(std::string("append ") + boost::lexical_cast<std::string>(i));
66 }
67 }
68
69 void prepend_sequential_lines(int num_lines = 10) {
70 lines.clear();
71 for (int i = 0; i < num_lines; ++i)
72 {
73 lines.push_back(std::string("prepend ") + boost::lexical_cast<std::string>(i));
74 }
75 }
76
77 void delete_percent_of_lines_randomly(int percent = 50) {
78 double scale = static_cast<double>(percent) / 100.0;
79 double nlines_d = static_cast<double>(lines.size()) * scale;
80 int nlines = static_cast<int>(nlines_d);
81 for (int i = 0; i < nlines; ++i)
82 lines.erase(lines.begin() + random_index(false));
83 }
84
85 void insert_sequential_percent_of_lines_randomly(int percent = 50) {
86 double scale = static_cast<double>(percent) / 100.0;
87 double nlines_d = static_cast<double>(lines.size()) * scale;
88 int nlines = static_cast<int>(nlines_d);
89 for (int i = 0; i < nlines; ++i)
90 {
91 lines.insert(lines.begin() + random_index(),
92 std::string("insert ") + boost::lexical_cast<std::string>(i));
93 }
94 }
95
96 static void build_random_fork(std::vector<std::string> & ancestor,
97 std::vector<std::string> & left,
98 std::vector<std::string> & right,
99 std::vector<std::string> & merged,
100 int n_hunks,
101 randomizer & rng)
102 {
103 bool last_was_insert = false;
104 bool last_insert_was_left = false;
105
106 file_randomizer fr(rng);
107 // maybe prepend something to one side or the other
108 if (rng.flip())
109 {
110 last_was_insert = true;
111 fr.prepend_sequential_lines();
112 last_insert_was_left = rng.flip();
113 if (last_insert_was_left)
114 fr.append_to(left);
115 else
116 fr.append_to(right);
117 fr.append_to(merged);
118 }
119 fr.lines.clear();
120
121 for (int h = 0; h < n_hunks; ++h)
122 {
123 file_randomizer hr(rng);
124 hr.set_prefix(std::string("hunk ") + boost::lexical_cast<std::string>(h) + " -- ");
125 hr.initial_sequential_lines(10);
126 if (rng.flip())
127 {
128 bool this_insert_is_left = rng.flip();
129 if (last_was_insert && (this_insert_is_left != last_insert_was_left))
130 {
131 fr.set_prefix("spacer ");
132 fr.initial_sequential_lines(3);
133 fr.append_to(left);
134 fr.append_to(right);
135 fr.append_to(ancestor);
136 fr.append_to(merged);
137 fr.set_prefix("");
138 }
139 last_insert_was_left = this_insert_is_left;
140 // doing an insert
141 hr.append_to(ancestor);
142 if (this_insert_is_left)
143 {
144 // inserting in left
145 hr.append_to(right);
146 hr.insert_sequential_percent_of_lines_randomly();
147 hr.append_to(left);
148 }
149 else
150 {
151 // inserting in right
152 hr.append_to(left);
153 hr.insert_sequential_percent_of_lines_randomly();
154 hr.append_to(right);
155 }
156 hr.append_to(merged);
157 last_was_insert = true;
158 }
159 else
160 {
161 // doing a delete
162 hr.append_to(ancestor);
163 if (rng.flip())
164 {
165 // deleting in left
166 hr.append_to(right);
167 hr.delete_percent_of_lines_randomly();
168 hr.append_to(left);
169 }
170 else
171 {
172 // deleting in right
173 hr.append_to(left);
174 hr.delete_percent_of_lines_randomly();
175 hr.append_to(right);
176 }
177 hr.append_to(merged);
178 last_was_insert = false;
179 }
180 }
181
182 // maybe append something to one side or the other
183 if (rng.flip())
184 {
185 bool this_insert_is_left = rng.flip();
186 if (last_was_insert && (this_insert_is_left != last_insert_was_left))
187 {
188 fr.set_prefix("spacer ");
189 fr.initial_sequential_lines(3);
190 fr.append_to(left);
191 fr.append_to(right);
192 fr.append_to(ancestor);
193 fr.append_to(merged);
194 fr.set_prefix("");
195 }
196 fr.append_sequential_lines();
197 if (this_insert_is_left)
198 fr.append_to(left);
199 else
200 fr.append_to(right);
201 fr.append_to(merged);
202 }
203 }
204};
205
206// Local Variables:
207// mode: C++
208// fill-column: 76
209// c-file-style: "gnu"
210// indent-tabs-mode: nil
211// End:
212// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
213
214#endif // __RANDOMFILE_HH__

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status