Repository navigation
Expand file tree
/
Copy pathcsv.mll
More file actions
183 lines (163 loc) · 6.56 KB
/
Copy pathcsv.mll
File metadata and controls
183 lines (163 loc) · 6.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
{
let input = ref "" and
output = ref "" and
append = ref 0 and
populate = ref false;;
Arg.parse [
("-o", Arg.String (fun s -> output := s), "Output file");
("-a", Arg.Int (fun i -> append := i), "Append # records");
("-p", Arg.Unit (fun () -> populate := true), "Populate records")
] (fun s -> input := s) "Input file";;
if !input = "" then
(
print_string "Invalid input file.\n";
exit 0
);;
if !output = "" then output := !input ^ ".out";;
Random.self_init();;
let recDel = ref "" and
key = Hashtbl.create 20 and
id = Hashtbl.create 4;;
let gen_int imin imax =
let amin = abs (min imin imax) and amax = abs (max imin imax) in
match amin, amax with
i, j when i = j -> i
| _, _ -> (Random.int (amax - amin)) + amin;;
let gen_float fmin fmax =
let amin = abs_float (min fmin fmax) and amax = abs_float (max fmin fmax) in
match amin, amax with
i, j when i = j -> i
| _, _ -> (Random.float (amax -. amin)) +. amin;;
let gen_char cap =
let c =
match cap with
true -> int_of_char 'A'
| false -> int_of_char 'a' in
char_of_int ((Random.int 26) + c);;
let gen_name min max =
let length = gen_int min max in
String.init length (fun i -> match i with
0 -> gen_char true;
| _ -> gen_char false
);;
let gen_postcode fi =
let pc = Buffer.create 8 in
Buffer.add_char pc (gen_char true);
Buffer.add_char pc (gen_char true);
Buffer.add_string pc (string_of_int (gen_int 1 29));
Buffer.add_char pc ' ';
Buffer.add_string pc (string_of_int (gen_int 1 9));
Buffer.add_char pc (gen_char true);
Buffer.add_char pc (gen_char true);
Buffer.contents pc;;
let gen_address fi =
let suf = [|"Street"; "Lane"; "Road"; "Crescent"; "Rise"; "Court"; "View"|] in
let add = Buffer.create 25 in
Buffer.add_string add (string_of_int (gen_int 1 100));
Buffer.add_char add ' ';
Buffer.add_string add (gen_name 3 10);
Buffer.add_char add ' ';
Buffer.add_string add (suf.(Random.int (Array.length suf)));
Buffer.contents add;;
let gen_email fi =
let suf = [|"com"; "net"; "org"; "co.uk"|] in
let em = Buffer.create 30 in
Buffer.add_string em (gen_name 3 10);
Buffer.add_char em '@';
Buffer.add_string em (gen_name 3 10);
Buffer.add_char em '.';
Buffer.add_string em (suf.(Random.int (Array.length suf)));
Buffer.contents em;;
let gen_id fi first inc =
let frst = abs first and
ic = abs inc in
if Hashtbl.mem id fi then
Hashtbl.replace id fi ((Hashtbl.find id fi) + ic)
else
Hashtbl.add id fi frst;
Hashtbl.find id fi;;
let gen_date fy fm fd ty tm td =
string_of_int (gen_int fy ty) ^ "-" ^ string_of_int (gen_int fm tm) ^ "-" ^ string_of_int (gen_int fd td) ^ " 00:00:00";;
let pick_option sep opts =
let vals = String.split_on_char sep opts in
List.nth vals (Random.int (List.length vals));;
let generate fi =
let k = Hashtbl.find key fi in
if Str.string_match (Str.regexp "ID \\([0-9]+\\)-\\([0-9]+\\)") k 0 then
string_of_int (gen_id fi (int_of_string (Str.matched_group 1 k)) (int_of_string (Str.matched_group 2 k)))
else if Str.string_match (Str.regexp "Name") k 0 then
gen_name 3 10
else if Str.string_match (Str.regexp "Address") k 0 then
gen_address fi
else if Str.string_match (Str.regexp "Postcode") k 0 then
gen_postcode fi
else if Str.string_match (Str.regexp "Email") k 0 then
gen_email fi
else if Str.string_match (Str.regexp "Word \\([0-9]+\\)-\\([0-9]+\\)") k 0 then
gen_name (int_of_string (Str.matched_group 1 k)) (int_of_string (Str.matched_group 2 k))
else if Str.string_match (Str.regexp "Integer \\([0-9]+\\)-\\([0-9]+\\)") k 0 then
string_of_int (gen_int (int_of_string (Str.matched_group 1 k)) (int_of_string (Str.matched_group 2 k)))
else if Str.string_match (Str.regexp "Decimal \\([0-9]+\\.[0-9]+\\)-\\([0-9]+\\.[0-9]+\\) \\([0-9]+\\)") k 0 then
Format.sprintf "%.*f" (int_of_string (Str.matched_group 3 k)) (gen_float (float_of_string (Str.matched_group 1 k)) (float_of_string (Str.matched_group 2 k)))
else if Str.string_match (Str.regexp "Literal \\(.*\\)") k 0 then
Str.matched_group 1 k
else if Str.string_match (Str.regexp "Date \\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]?\\)-\\([0-9][0-9]?\\) \\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]?\\)-\\([0-9][0-9]?\\)") k 0 then
gen_date (int_of_string (Str.matched_group 1 k)) (int_of_string (Str.matched_group 2 k)) (int_of_string (Str.matched_group 3 k)) (int_of_string (Str.matched_group 4 k)) (int_of_string (Str.matched_group 5 k)) (int_of_string (Str.matched_group 6 k))
else if Str.string_match (Str.regexp "Option \\(.\\) \\(.*\\)") k 0 then
pick_option (Str.matched_group 1 k).[0] (Str.matched_group 2 k)
else
"";;
let end_field file txt fi del =
match txt, !populate with
"" , true -> Printf.fprintf file "%s%s" (generate fi) del
| _, _ -> Printf.fprintf file "%s%s" txt del;;
let gen_field file count =
let cnt = abs count in
let rec gf ct =
if ct < cnt then
(end_field file "" ct ","; gf (ct + 1))
else
end_field file "" ct !recDel
in
gf 0;;
let gen_record file count =
let keys = (Hashtbl.length key) - 1 and
cnt = abs count in
let rec gr ct =
match ct with
0 -> ()
| _ -> gen_field file keys; gr (ct - 1)
in
gr cnt;;
}
rule tokens = parse
['\"'] { `Escape }
| [','] { `Field }
| ('\013'?'\n' as del) { `Record (del) }
| eof { `File }
| ([^',' '\"' '\013' '\n']+ as dat) { `Data (dat) }
{
let rec next_token txt esc ri fi outF lBuf =
let tok = tokens lBuf in
match tok, esc, ri with
`File, _, _ -> end_field outF txt fi !recDel
| `Record del, true, _ -> next_token (txt ^ del) esc ri fi outF lBuf
| `Record del, false, 0 -> recDel := del; Hashtbl.add key fi txt; next_token "" esc (ri + 1) 0 outF lBuf
| `Record del, false, _ -> end_field outF txt fi del; next_token "" esc (ri + 1) 0 outF lBuf
| `Field, true, _ -> next_token (txt ^ ",") esc ri fi outF lBuf
| `Field, false, 0 -> Hashtbl.add key fi txt; next_token "" esc ri (fi + 1) outF lBuf
| `Field, false, _ -> end_field outF txt fi ","; next_token "" esc ri (fi + 1) outF lBuf
| `Escape, _, _ -> next_token (txt ^ "\"") (not esc) ri fi outF lBuf
| `Data dat, _, _ -> next_token (txt ^ dat) esc ri fi outF lBuf;;
let _ =
let outFile = open_out !output and inFile = open_in !input in
let res = try
let lb = Lexing.from_channel inFile in
next_token "" false 0 0 outFile lb;
populate := true; gen_record outFile !append;
"Completed.\n"
with exn -> close_in inFile; close_out outFile; raise exn in
close_in inFile;
close_out outFile;
print_string res;;
}