Add forgotten files 1.4.70b
[polyglot.git] / book_merge.cpp
1 \r
2 // book_merge.cpp\r
3 \r
4 // includes\r
5 \r
6 #include <cerrno>\r
7 #include <cstdio>\r
8 #include <cstdlib>\r
9 #include <cstring>\r
10 \r
11 #include "book_merge.h"\r
12 #include "util.h"\r
13 \r
14 // types\r
15 \r
16 struct book_t {\r
17    FILE * file;\r
18    int size;\r
19 };\r
20 \r
21 struct entry_t {\r
22    uint64 key;\r
23    uint16 move;\r
24    uint16 count;\r
25    uint16 n;\r
26    uint16 sum;\r
27 };\r
28 \r
29 // variables\r
30 \r
31 static book_t In1[1];\r
32 static book_t In2[1];\r
33 static book_t Out[1];\r
34 \r
35 // prototypes\r
36 \r
37 static void   book_clear    (book_t * book);\r
38 \r
39 static void   book_open     (book_t * book, const char file_name[], const char mode[]);\r
40 static void   book_close    (book_t * book);\r
41 \r
42 static bool   read_entry    (book_t * book, entry_t * entry, int n);\r
43 static void   write_entry   (book_t * book, const entry_t * entry);\r
44 \r
45 static uint64 read_integer  (FILE * file, int size);\r
46 static void   write_integer (FILE * file, int size, uint64 n);\r
47 \r
48 // functions\r
49 \r
50 // book_merge()\r
51 \r
52 void book_merge(int argc, char * argv[]) {\r
53 \r
54    int i;\r
55    const char * in_file_1;\r
56    const char * in_file_2;\r
57    const char * out_file;\r
58    int i1, i2;\r
59    bool b1, b2;\r
60    entry_t e1[1], e2[1];\r
61    int skip;\r
62 \r
63    in_file_1 = NULL;\r
64    my_string_clear(&in_file_1);\r
65 \r
66    in_file_2 = NULL;\r
67    my_string_clear(&in_file_2);\r
68 \r
69    out_file = NULL;\r
70    my_string_set(&out_file,"out.bin");\r
71 \r
72    for (i = 1; i < argc; i++) {\r
73 \r
74       if (false) {\r
75 \r
76       } else if (my_string_equal(argv[i],"merge-book")) {\r
77 \r
78          // skip\r
79 \r
80       } else if (my_string_equal(argv[i],"-in1")) {\r
81 \r
82          i++;\r
83          if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
84 \r
85          my_string_set(&in_file_1,argv[i]);\r
86 \r
87       } else if (my_string_equal(argv[i],"-in2")) {\r
88 \r
89          i++;\r
90          if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
91 \r
92          my_string_set(&in_file_2,argv[i]);\r
93 \r
94       } else if (my_string_equal(argv[i],"-out")) {\r
95 \r
96          i++;\r
97          if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
98 \r
99          my_string_set(&out_file,argv[i]);\r
100 \r
101       } else {\r
102 \r
103          my_fatal("book_merge(): unknown option \"%s\"\n",argv[i]);\r
104       }\r
105    }\r
106 \r
107    book_clear(In1);\r
108    book_clear(In2);\r
109    book_clear(Out);\r
110 \r
111    book_open(In1,in_file_1,"rb");\r
112    book_open(In2,in_file_2,"rb");\r
113    book_open(Out,out_file,"wb");\r
114 \r
115    skip = 0;\r
116 \r
117    i1 = 0;\r
118    i2 = 0;\r
119 \r
120    while (true) {\r
121 \r
122       b1 = read_entry(In1,e1,i1);\r
123       b2 = read_entry(In2,e2,i2);\r
124 \r
125       if (false) {\r
126 \r
127       } else if (!b1 && !b2) {\r
128 \r
129          break;\r
130 \r
131       } else if (b1 && !b2) {\r
132 \r
133          write_entry(Out,e1);\r
134          i1++;\r
135 \r
136       } else if (b2 && !b1) {\r
137 \r
138          write_entry(Out,e2);\r
139          i2++;\r
140 \r
141       } else {\r
142 \r
143          ASSERT(b1);\r
144          ASSERT(b2);\r
145 \r
146          if (false) {\r
147          } else if (e1->key < e2->key) {\r
148             write_entry(Out,e1);\r
149             i1++;\r
150          } else if (e1->key > e2->key) {\r
151             write_entry(Out,e2);\r
152             i2++;\r
153          } else {\r
154             ASSERT(e1->key==e2->key);\r
155             skip++;\r
156             i2++;\r
157          }\r
158       }\r
159    }\r
160 \r
161    book_close(In1);\r
162    book_close(In2);\r
163    book_close(Out);\r
164 \r
165    if (skip != 0) {\r
166       printf("skipped %d entr%s.\n",skip,(skip>1)?"ies":"y");\r
167    }\r
168 \r
169    printf("done!\n");\r
170 }\r
171 \r
172 // book_clear()\r
173 \r
174 static void book_clear(book_t * book) {\r
175 \r
176    ASSERT(book!=NULL);\r
177 \r
178    book->file = NULL;\r
179    book->size = 0;\r
180 }\r
181 \r
182 // book_open()\r
183 \r
184 static void book_open(book_t * book, const char file_name[], const char mode[]) {\r
185 \r
186    ASSERT(book!=NULL);\r
187    ASSERT(file_name!=NULL);\r
188    ASSERT(mode!=NULL);\r
189 \r
190    book->file = fopen(file_name,mode);\r
191    if (book->file == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
192 \r
193    if (fseek(book->file,0,SEEK_END) == -1) {\r
194       my_fatal("book_open(): fseek(): %s\n",strerror(errno));\r
195    }\r
196 \r
197    book->size = ftell(book->file) / 16;\r
198 }\r
199 \r
200 // book_close()\r
201 \r
202 static void book_close(book_t * book) {\r
203 \r
204    ASSERT(book!=NULL);\r
205 \r
206    if (fclose(book->file) == EOF) {\r
207       my_fatal("book_close(): fclose(): %s\n",strerror(errno));\r
208    }\r
209 }\r
210 \r
211 // read_entry()\r
212 \r
213 static bool read_entry(book_t * book, entry_t * entry, int n) {\r
214 \r
215    ASSERT(book!=NULL);\r
216    ASSERT(entry!=NULL);\r
217 \r
218    if (n < 0 || n >= book->size) return false;\r
219 \r
220    ASSERT(n>=0&&n<book->size);\r
221 \r
222    if (fseek(book->file,n*16,SEEK_SET) == -1) {\r
223       my_fatal("read_entry(): fseek(): %s\n",strerror(errno));\r
224    }\r
225 \r
226    entry->key   = read_integer(book->file,8);\r
227    entry->move  = read_integer(book->file,2);\r
228    entry->count = read_integer(book->file,2);\r
229    entry->n     = read_integer(book->file,2);\r
230    entry->sum   = read_integer(book->file,2);\r
231 \r
232    return true;\r
233 }\r
234 \r
235 // write_entry()\r
236 \r
237 static void write_entry(book_t * book, const entry_t * entry) {\r
238 \r
239    ASSERT(book!=NULL);\r
240    ASSERT(entry!=NULL);\r
241 \r
242    write_integer(book->file,8,entry->key);\r
243    write_integer(book->file,2,entry->move);\r
244    write_integer(book->file,2,entry->count);\r
245    write_integer(book->file,2,entry->n);\r
246    write_integer(book->file,2,entry->sum);\r
247 }\r
248 \r
249 // read_integer()\r
250 \r
251 static uint64 read_integer(FILE * file, int size) {\r
252 \r
253    uint64 n;\r
254    int i;\r
255    int b;\r
256 \r
257    ASSERT(file!=NULL);\r
258    ASSERT(size>0&&size<=8);\r
259 \r
260    n = 0;\r
261 \r
262    for (i = 0; i < size; i++) {\r
263 \r
264       b = fgetc(file);\r
265 \r
266       if (b == EOF) {\r
267          if (feof(file)) {\r
268             my_fatal("read_integer(): fgetc(): EOF reached\n");\r
269          } else { // error\r
270             my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));\r
271          }\r
272       }\r
273 \r
274       ASSERT(b>=0&&b<256);\r
275       n = (n << 8) | b;\r
276    }\r
277 \r
278    return n;\r
279 }\r
280 \r
281 // write_integer()\r
282 \r
283 static void write_integer(FILE * file, int size, uint64 n) {\r
284 \r
285    int i;\r
286    int b;\r
287 \r
288    ASSERT(file!=NULL);\r
289    ASSERT(size>0&&size<=8);\r
290    ASSERT(size==8||n>>(size*8)==0);\r
291 \r
292    for (i = size-1; i >= 0; i--) {\r
293 \r
294       b = (n >> (i*8)) & 0xFF;\r
295       ASSERT(b>=0&&b<256);\r
296 \r
297       if (fputc(b,file) == EOF) {\r
298          my_fatal("write_integer(): fputc(): %s\n",strerror(errno));\r
299       }\r
300    }\r
301 }\r
302 \r
303 // end of book_merge.cpp\r
304 \r