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