#include #include #include #include #include "config.h" #include "BHeap.h" #include "FHeap.h" #include "BinHeap.h" #include "PLList.h" #include "Huffman.h" #include "numbers.h" void exception(int e, char *msg) { cerr << msg << endl; exit(-1); } PriorityList *newlist(int method) { switch (method) { case 0: return new BinHeap; break; case 1: return new BHeap; break; case 2: return new FHeap; break; case 3: return new PLList; break; default: cerr << _("Unknow priority list type: ") << method << endl; exit(-1); } } void Count(FILE * strm, PriorityList * P) { int tab[256], i; char t[2]; if (!strm) { cerr << _("Error opening file (") << strerror(errno) << ")\n"; exit(-1); } for (i = 0; i < 256; i++) { tab[i] = 0; } while ((i = getc(strm)) != EOF) { tab[i]++; } for (i = 0; i < 256; i++) { if (tab[i]) { t[0] = i; t[1] = 0; HInsert(P, tab[i], t); } } } void ReadDic(FILE * strm, PriorityList * P) { char t[1024], *f, *word, *p; int valid, freq; if (!strm) { cerr << _("Error opening file (") << strerror(errno) << ")\n"; exit(-1); } while (fgets(t, 1024, strm)) { if (!(f = strchr(t, ':'))) { cerr << _("Bad dictionnary structure. See doc/README.en (missing : separator)") << endl; exit(-1); } *(f++) = '\0'; word = t; while (*word == ' ') { word++; } p = word + strlen(word) - 1; while (*p == ' ') { *(p--) = '\0'; } if (!strlen(word)) { cerr << _("Bad dictionnary structure. See doc/README.en (missing word)") << endl; exit(-1); } while (*f == ' ') { f++; } p = f + strlen(f) - 1; while ((*p == ' ') || (*p == '\n')) { *(p--) = '\0'; } if (!strlen(f)) { cerr << _("Bad dictionnary structure. See doc/README.en (missing frequency)") << endl; exit(-1); } freq = char_to_number(f, &valid); if (!valid) { cerr << _("Error: \"") << f << _("\" is not a valid number.") << endl; exit(-1); } HInsert(P, freq, word); } } void Usage(void) { cerr << _("Huffman [{-f|-i} file] {type}") << endl; cerr << _("Huffman -h") << endl; cerr << _("By Nicolas Noble (nicolas@nobis-crew.org).") << endl; cerr << _("This will encode the input file with the Huffman code") << endl; cerr << _("using the priority list defined by type.") << endl; cerr << _("Type is a number taken from this list:") << endl; cerr << _(" 0 : Binary Heap (default)") << endl; cerr << _(" 1 : Binomial Heap") << endl; cerr << _(" 2 : Fibonacci Heap") << endl; cerr << _(" 3 : Sorted chained list") << endl; cerr << _("-f file means that you specify a dictionnary file which is") << endl; cerr << _(" structured as described into the README file.") << endl; cerr << _("-i file means that you specify a file to encode. It will") << endl; cerr << _(" built a quiet dumb dictionnary.") << endl; cerr << _("By default, a dictionnary will be built from stdin.") << endl; cerr << _("-h prints this help and exit.") << endl; exit(0); } int main(int argc, char **argv) { PriorityList *P; HTree *H; int method = -1, readm = -1; char *filename = NULL; while (--argc) { argv++; if ((*argv)[0] == '-') { if (strlen(*argv) != 2) { cerr << _("Unknow option: ") << *argv << endl; Usage(); } switch ((*argv)[1]) { case 'h': Usage(); break; case 'i': if (readm != -1) { cerr << _("-i and -f options are exclusive") << endl; Usage(); } readm = 1; filename = *(++argv); argc--; break; case 'f': if (readm != -1) { cerr << _("-i and -f options are exclusive") << endl; Usage(); } readm = 2; filename = *(++argv); argc--; break; } } else { if ((strlen(*argv) != 1) || (((*argv)[0] < '0' || (*argv)[0] > '3'))) { cerr << _("Unknow priority list type: ") << *argv << endl; Usage(); } if (method != -1) { cerr << _("Extra command: ") << *argv << endl; Usage(); } method = (*argv)[0] - '0'; } } if (method == -1) method = 0; P = newlist(method); switch (readm) { case -1: Count(stdin, P); break; case 1: if (!filename) cerr << _("-i needs a filename") << endl; Count(fopen(filename, "r"), P); break; case 2: if (!filename) cerr << _("-f needs a filename") << endl; ReadDic(fopen(filename, "r"), P); break; default: cerr << _("Internal error.") << endl; exit(-1); } H = Coder(P); delete P; H->Trace(cout); return 0; }