version 1.4.30b
[polyglot.git] / book_merge.c
diff --git a/book_merge.c b/book_merge.c
new file mode 100644 (file)
index 0000000..f68e2cc
--- /dev/null
@@ -0,0 +1,304 @@
+\r
+// book_merge.c\r
+\r
+// includes\r
+\r
+#include <errno.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "book_merge.h"\r
+#include "util.h"\r
+\r
+// types\r
+\r
+typedef struct {\r
+   FILE * file;\r
+   int size;\r
+} book_t;\r
+\r
+typedef struct {\r
+   uint64 key;\r
+   uint16 move;\r
+   uint16 count;\r
+   uint16 n;\r
+   uint16 sum;\r
+} entry_t;\r
+\r
+// variables\r
+\r
+static book_t In1[1];\r
+static book_t In2[1];\r
+static book_t Out[1];\r
+\r
+// prototypes\r
+\r
+static void   book_clear    (book_t * book);\r
+\r
+static void   book_open     (book_t * book, const char file_name[], const char mode[]);\r
+static void   book_close    (book_t * book);\r
+\r
+static bool   read_entry    (book_t * book, entry_t * entry, int n);\r
+static void   write_entry   (book_t * book, const entry_t * entry);\r
+\r
+static uint64 read_integer  (FILE * file, int size);\r
+static void   write_integer (FILE * file, int size, uint64 n);\r
+\r
+// functions\r
+\r
+// book_merge()\r
+\r
+void book_merge(int argc, char * argv[]) {\r
+\r
+   int i;\r
+   const char * in_file_1;\r
+   const char * in_file_2;\r
+   const char * out_file;\r
+   int i1, i2;\r
+   bool b1, b2;\r
+   entry_t e1[1], e2[1];\r
+   int skip;\r
+\r
+   in_file_1 = NULL;\r
+   my_string_clear(&in_file_1);\r
+\r
+   in_file_2 = NULL;\r
+   my_string_clear(&in_file_2);\r
+\r
+   out_file = NULL;\r
+   my_string_set(&out_file,"out.bin");\r
+\r
+   for (i = 1; i < argc; i++) {\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (my_string_equal(argv[i],"merge-book")) {\r
+\r
+         // skip\r
+\r
+      } else if (my_string_equal(argv[i],"-in1")) {\r
+\r
+         i++;\r
+         if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
+\r
+         my_string_set(&in_file_1,argv[i]);\r
+\r
+      } else if (my_string_equal(argv[i],"-in2")) {\r
+\r
+         i++;\r
+         if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
+\r
+         my_string_set(&in_file_2,argv[i]);\r
+\r
+      } else if (my_string_equal(argv[i],"-out")) {\r
+\r
+         i++;\r
+         if (argv[i] == NULL) my_fatal("book_merge(): missing argument\n");\r
+\r
+         my_string_set(&out_file,argv[i]);\r
+\r
+      } else {\r
+\r
+         my_fatal("book_merge(): unknown option \"%s\"\n",argv[i]);\r
+      }\r
+   }\r
+\r
+   book_clear(In1);\r
+   book_clear(In2);\r
+   book_clear(Out);\r
+\r
+   book_open(In1,in_file_1,"rb");\r
+   book_open(In2,in_file_2,"rb");\r
+   book_open(Out,out_file,"wb");\r
+\r
+   skip = 0;\r
+\r
+   i1 = 0;\r
+   i2 = 0;\r
+\r
+   while (TRUE) {\r
+\r
+      b1 = read_entry(In1,e1,i1);\r
+      b2 = read_entry(In2,e2,i2);\r
+\r
+      if (FALSE) {\r
+\r
+      } else if (!b1 && !b2) {\r
+\r
+         break;\r
+\r
+      } else if (b1 && !b2) {\r
+\r
+         write_entry(Out,e1);\r
+         i1++;\r
+\r
+      } else if (b2 && !b1) {\r
+\r
+         write_entry(Out,e2);\r
+         i2++;\r
+\r
+      } else {\r
+\r
+         ASSERT(b1);\r
+         ASSERT(b2);\r
+\r
+         if (FALSE) {\r
+         } else if (e1->key < e2->key) {\r
+            write_entry(Out,e1);\r
+            i1++;\r
+         } else if (e1->key > e2->key) {\r
+            write_entry(Out,e2);\r
+            i2++;\r
+         } else {\r
+            ASSERT(e1->key==e2->key);\r
+            skip++;\r
+            i2++;\r
+         }\r
+      }\r
+   }\r
+\r
+   book_close(In1);\r
+   book_close(In2);\r
+   book_close(Out);\r
+\r
+   if (skip != 0) {\r
+      printf("skipped %d entr%s.\n",skip,(skip>1)?"ies":"y");\r
+   }\r
+\r
+   printf("done!\n");\r
+}\r
+\r
+// book_clear()\r
+\r
+static void book_clear(book_t * book) {\r
+\r
+   ASSERT(book!=NULL);\r
+\r
+   book->file = NULL;\r
+   book->size = 0;\r
+}\r
+\r
+// book_open()\r
+\r
+static void book_open(book_t * book, const char file_name[], const char mode[]) {\r
+\r
+   ASSERT(book!=NULL);\r
+   ASSERT(file_name!=NULL);\r
+   ASSERT(mode!=NULL);\r
+\r
+   book->file = fopen(file_name,mode);\r
+   if (book->file == NULL) my_fatal("book_open(): can't open file \"%s\": %s\n",file_name,strerror(errno));\r
+\r
+   if (fseek(book->file,0,SEEK_END) == -1) {\r
+      my_fatal("book_open(): fseek(): %s\n",strerror(errno));\r
+   }\r
+\r
+   book->size = ftell(book->file) / 16;\r
+}\r
+\r
+// book_close()\r
+\r
+static void book_close(book_t * book) {\r
+\r
+   ASSERT(book!=NULL);\r
+\r
+   if (fclose(book->file) == EOF) {\r
+      my_fatal("book_close(): fclose(): %s\n",strerror(errno));\r
+   }\r
+}\r
+\r
+// read_entry()\r
+\r
+static bool read_entry(book_t * book, entry_t * entry, int n) {\r
+\r
+   ASSERT(book!=NULL);\r
+   ASSERT(entry!=NULL);\r
+\r
+   if (n < 0 || n >= book->size) return FALSE;\r
+\r
+   ASSERT(n>=0&&n<book->size);\r
+\r
+   if (fseek(book->file,n*16,SEEK_SET) == -1) {\r
+      my_fatal("read_entry(): fseek(): %s\n",strerror(errno));\r
+   }\r
+\r
+   entry->key   = read_integer(book->file,8);\r
+   entry->move  = read_integer(book->file,2);\r
+   entry->count = read_integer(book->file,2);\r
+   entry->n     = read_integer(book->file,2);\r
+   entry->sum   = read_integer(book->file,2);\r
+\r
+   return TRUE;\r
+}\r
+\r
+// write_entry()\r
+\r
+static void write_entry(book_t * book, const entry_t * entry) {\r
+\r
+   ASSERT(book!=NULL);\r
+   ASSERT(entry!=NULL);\r
+\r
+   write_integer(book->file,8,entry->key);\r
+   write_integer(book->file,2,entry->move);\r
+   write_integer(book->file,2,entry->count);\r
+   write_integer(book->file,2,entry->n);\r
+   write_integer(book->file,2,entry->sum);\r
+}\r
+\r
+// read_integer()\r
+\r
+static uint64 read_integer(FILE * file, int size) {\r
+\r
+   uint64 n;\r
+   int i;\r
+   int b;\r
+\r
+   ASSERT(file!=NULL);\r
+   ASSERT(size>0&&size<=8);\r
+\r
+   n = 0;\r
+\r
+   for (i = 0; i < size; i++) {\r
+\r
+      b = fgetc(file);\r
+\r
+      if (b == EOF) {\r
+         if (feof(file)) {\r
+            my_fatal("read_integer(): fgetc(): EOF reached\n");\r
+         } else { // error\r
+            my_fatal("read_integer(): fgetc(): %s\n",strerror(errno));\r
+         }\r
+      }\r
+\r
+      ASSERT(b>=0&&b<256);\r
+      n = (n << 8) | b;\r
+   }\r
+\r
+   return n;\r
+}\r
+\r
+// write_integer()\r
+\r
+static void write_integer(FILE * file, int size, uint64 n) {\r
+\r
+   int i;\r
+   int b;\r
+\r
+   ASSERT(file!=NULL);\r
+   ASSERT(size>0&&size<=8);\r
+   ASSERT(size==8||n>>(size*8)==0);\r
+\r
+   for (i = size-1; i >= 0; i--) {\r
+\r
+      b = (n >> (i*8)) & 0xFF;\r
+      ASSERT(b>=0&&b<256);\r
+\r
+      if (fputc(b,file) == EOF) {\r
+         my_fatal("write_integer(): fputc(): %s\n",strerror(errno));\r
+      }\r
+   }\r
+}\r
+\r
+// end of book_merge.cpp\r
+\r