eliot-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Eliot-dev] eliot dic/Makefile.am dic/compdic.cpp dic/dic.c... [cppdic]


From: eliot-dev
Subject: [Eliot-dev] eliot dic/Makefile.am dic/compdic.cpp dic/dic.c... [cppdic]
Date: Wed, 21 Nov 2007 16:25:45 +0000

CVSROOT:        /cvsroot/eliot
Module name:    eliot
Branch:         cppdic
Changes by:     Olivier Teulière <ipkiss>      07/11/21 16:25:45

Modified files:
        dic            : Makefile.am compdic.cpp dic.cpp dic.h 
                         header.cpp header.h listdic.cpp regexpmain.cpp 
        game           : game_factory.cpp game_factory.h 
        utils          : eliottxt.cpp 
        wxwin          : mainframe.cc 
Added files:
        dic            : dic_exception.cpp dic_exception.h 

Log message:
        DicException:
         - New exception class used in the dic/ module.
           It simplifies the code in many places.
        Header:
         - When creating a Header Object from a file, do it in one step instead 
of two
         - Fixed encoding of the dictionary name
         - Moved iconv usage into separate functions
         - Improved the textual display of the header
         - Added conversion functions between a wchar_t and its internal code
        Compdic:
         - Removed some global variables
         - New command-line parameters to set the dictionary name and the 
letters
         - Use getopt for options parsing
        Listdic:
         - Handle wide chars correctly
        Dictionary:
         - The load() method has disappeared, its code is now in the 
constructor of the class. It throws exceptions in case of errors, to avoid 
duplicating the error handling code in all the callers.
        
        It is now possibly to fully compress and decompress a dictionary made 
of any character!
        The old dictionary format is still supported.
        Note that the upper layer of the dic/ module still had to be adapted.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/Makefile.am?cvsroot=eliot&only_with_tag=cppdic&r1=1.14.4.4&r2=1.14.4.5
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/compdic.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.7&r2=1.1.2.8
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.5&r2=1.1.2.6
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.13.2.3&r2=1.13.2.4
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/header.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.6&r2=1.1.2.7
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/header.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.4&r2=1.1.2.5
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/listdic.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.5&r2=1.1.2.6
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/regexpmain.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.1.2.2&r2=1.1.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_exception.cpp?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/dic/dic_exception.h?cvsroot=eliot&only_with_tag=cppdic&rev=1.1.2.1
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game_factory.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.8.2.2&r2=1.8.2.3
http://cvs.savannah.gnu.org/viewcvs/eliot/game/game_factory.h?cvsroot=eliot&only_with_tag=cppdic&r1=1.8.2.1&r2=1.8.2.2
http://cvs.savannah.gnu.org/viewcvs/eliot/utils/eliottxt.cpp?cvsroot=eliot&only_with_tag=cppdic&r1=1.16.2.5&r2=1.16.2.6
http://cvs.savannah.gnu.org/viewcvs/eliot/wxwin/mainframe.cc?cvsroot=eliot&only_with_tag=cppdic&r1=1.21.2.2&r2=1.21.2.3

Patches:
Index: dic/Makefile.am
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Makefile.am,v
retrieving revision 1.14.4.4
retrieving revision 1.14.4.5
diff -u -b -r1.14.4.4 -r1.14.4.5
--- dic/Makefile.am     20 Nov 2007 12:54:03 -0000      1.14.4.4
+++ dic/Makefile.am     21 Nov 2007 16:25:43 -0000      1.14.4.5
@@ -26,8 +26,8 @@
 libdic_a_SOURCES = \
        ery.ypp \
        erl.lpp \
-       header.h \
-       header.cpp \
+       dic_exception.cpp dic_exception.h \
+       header.cpp header.h \
        dic_internals.h \
        dic_search.cpp dic_search.h \
        dic.cpp dic.h \
@@ -62,18 +62,11 @@
        listdic \
        regexp
 
-compdic_SOURCES= \
-       dic_internals.h \
-       hashtable.cpp hashtble.h \
-       encoding.cpp encoding.h \
-       header.cpp header.h \
-       compdic.cpp
+compdic_SOURCES=compdic.cpp
+compdic_LDADD=libdic.a
 
-listdic_SOURCES= \
-       dic_internals.h \
-       dic.cpp dic.h \
-       header.cpp header.h \
-       listdic.cpp
+listdic_SOURCES=listdic.cpp
+listdic_LDADD=libdic.a
 
 #regexp_CFLAGS=-DDEBUG_RE
 regexp_SOURCES=regexpmain.cpp

Index: dic/compdic.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/compdic.cpp,v
retrieving revision 1.1.2.7
retrieving revision 1.1.2.8
diff -u -b -r1.1.2.7 -r1.1.2.8
--- dic/compdic.cpp     20 Nov 2007 12:54:03 -0000      1.1.2.7
+++ dic/compdic.cpp     21 Nov 2007 16:25:44 -0000      1.1.2.8
@@ -25,10 +25,11 @@
  */
 
 #include <fstream>
+#include <iostream>
 #include <vector>
 #include <map>
-#include <memory>
 #include <iconv.h>
+#include <getopt.h>
 #include <time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -41,6 +42,9 @@
 #include "encoding.h"
 #include "header.h"
 #include "dic_internals.h"
+#include "dic_exception.h"
+
+using namespace std;
 
 //#define DEBUG_LIST
 //#define DEBUG_OUTPUT
@@ -48,7 +52,7 @@
 #define CHECK_RECURSION
 
 
-wchar_t* load_uncompressed(const string &iFileName, unsigned int iDicSize)
+wchar_t* load_uncompressed(const string &iFileName, unsigned int &ioDicSize)
 {
     // TODO: we should throw exceptions everywhere instead of returning NULL
 
@@ -56,10 +60,10 @@
     if (!file.is_open())
         return NULL;
 
-    // Place the buffer in an auto_ptr to avoid worrying about memory handling
-    std::auto_ptr<char> buffer(new char[iDicSize]);
+    // Place the buffer in a vector to avoid worrying about memory handling
+    std::vector<char> buffer(ioDicSize);
     // Load the file data, everything in one shot
-    file.read(buffer.get(), iDicSize);
+    file.read(&buffer.front(), ioDicSize);
     file.close();
 
     // The words are supposed to be in utf-8, so convert everything to
@@ -70,48 +74,44 @@
 
     // Buffer for the wide characters (it will use at most as many characters
     // as the utf-8 version)
-    std::auto_ptr<wchar_t> wide_buf(new wchar_t[iDicSize]);
+    // FIXME: not exception safe
+    wchar_t *wide_buf = new wchar_t[ioDicSize];
 
-    size_t inChars = iDicSize;
-    size_t outChars = sizeof(wchar_t) * iDicSize;
-    char *in = buffer.get();
-    char *out = (char*)wide_buf.get();
+    size_t inChars = ioDicSize;
+    size_t outChars = sizeof(wchar_t) * ioDicSize;
+    char *in = &buffer.front();
+    char *out = (char*)wide_buf;
     size_t res = iconv(handle, &in, &inChars, &out, &outChars);
     iconv_close(handle);
     // Problem during encoding conversion?
     if (res == (size_t)(-1))
         return NULL;
 
-    return wide_buf.release();
-}
-
+    // Update ioDicSize with the actual length of the wchar_t array
+    ioDicSize -= outChars / sizeof(wchar_t);
 
-int file_length(const string &iFileName)
-{
-    struct stat stat_buf;
-    if (stat(iFileName.c_str(), &stat_buf) < 0)
-        return -1;
-    return (int)stat_buf.st_size;
+    return wide_buf;
 }
 
 
-void skip_init_header(ostream &outfile, Dict_header_info *headerInfo)
+Header skip_init_header(ostream &outfile, Dict_header_info &ioHeaderInfo)
 {
-    headerInfo->root       = 0;
-    headerInfo->nwords     = 0;
-    headerInfo->nodesused  = 1;
-    headerInfo->edgesused  = 1;
-    headerInfo->nodessaved = 0;
-    headerInfo->edgessaved = 0;
+    ioHeaderInfo.root       = 0;
+    ioHeaderInfo.nwords     = 0;
+    ioHeaderInfo.nodesused  = 1;
+    ioHeaderInfo.edgesused  = 1;
+    ioHeaderInfo.nodessaved = 0;
+    ioHeaderInfo.edgessaved = 0;
 
-    Header aHeader(*headerInfo);
+    Header aHeader(ioHeaderInfo);
     aHeader.write(outfile);
+    return aHeader;
 }
 
 
-void fix_header(ostream &outfile, Dict_header_info* headerInfo)
+void fix_header(ostream &outfile, Dict_header_info &ioHeaderInfo)
 {
-    headerInfo->root = headerInfo->edgesused;
+    ioHeaderInfo.root = ioHeaderInfo.edgesused;
     // Go back to the beginning of the stream to overwrite the header
     outfile.seekp(0, ios::beg);
 #if defined(WORDS_BIGENDIAN)
@@ -119,7 +119,7 @@
 #warning "compdic does not run yet on bigendian machines"
 #warning "**********************************************"
 #else
-    Header aHeader(*headerInfo);
+    Header aHeader(ioHeaderInfo);
     aHeader.write(outfile);
 #endif
 }
@@ -185,8 +185,6 @@
 #endif
 
 /* global variables */
-ofstream global_outfile;
-Dict_header_info global_header_info;
 HashTable<vector<Dawg_edge>, unsigned int, HashVector> *global_hashtable;
 
 wchar_t  global_stringbuf[MAX_STRING_LENGTH]; /* Space for current string */
@@ -196,22 +194,22 @@
 #ifdef CHECK_RECURSION
 map<int, vector<Dawg_edge> > global_mapfordepth;
 #endif
-map<wchar_t, unsigned int> global_chartocode;
 
-unsigned int charToCode(wchar_t iChar)
-{
-    // TODO: throw an exception if the result is 0
-    return global_chartocode[iChar];
-}
-
-/*
+/**
  * Makenode takes a prefix (as position relative to stringbuf) and
  * returns an index of the start node of a dawg that recognizes all
  * words beginning with that prefix.  String is a pointer (relative
- * to stringbuf) indicating how much of prefix is matched in the
+ * to stringbuf) indicating how much of iPrefix is matched in the
  * input.
+ * @param iPrefix: prefix to work on
+ * @param outfile: stream where to write the nodes
+ * @param ioHeaderInfo: information needed to build the final header, updated
+ *      during the processing
+ * @param iHeader: temporary header, used only to do the conversion between
+ *      the (wide) chars and their corresponding internal code
  */
-unsigned int makenode(wchar_t *prefix)
+unsigned int makenode(const wchar_t *iPrefix, ostream &outfile,
+                      Dict_header_info &ioHeaderInfo, const Header &iHeader)
 {
 #ifdef CHECK_RECURSION
     IncDec inc(current_rec);
@@ -231,25 +229,25 @@
 #endif
     Dawg_edge newEdge;
 
-    while (prefix == global_endstring)
+    while (iPrefix == global_endstring)
     {
         // More edges out of node
         newEdge.ptr  = 0;
         newEdge.term = 0;
         newEdge.last = 0;
         newEdge.fill = 0;
-        newEdge.chr = charToCode(*global_endstring++ = *global_input++);
+        newEdge.chr = iHeader.getCodeFromChar(*global_endstring++ = 
*global_input++);
         edges.push_back(newEdge);
 
         // End of a word?
         // TODO: handle \r as well
         if (*global_input == L'\n')
         {
-            global_header_info.nwords++;
+            ioHeaderInfo.nwords++;
             // Mark edge as word
             edges.back().term = 1;
             // Skip \n
-            *global_endstring++ = *global_input++;
+            *global_endstring = *global_input++;
             // At the end of input?
             if (global_input == global_endofinput)
                 break;
@@ -261,8 +259,9 @@
                 global_input++;
             }
         }
-        // make dawg pointed to by this edge
-        edges.back().ptr = makenode(prefix + 1);
+        // Make dawg pointed to by this edge
+        edges.back().ptr =
+            makenode(iPrefix + 1, outfile, ioHeaderInfo, iHeader);
     }
 
     int numedges = edges.size();
@@ -278,52 +277,123 @@
     const unsigned int *saved_position = global_hashtable->find(edges);
     if (saved_position)
     {
-        global_header_info.edgessaved += numedges;
-        global_header_info.nodessaved++;
+        ioHeaderInfo.edgessaved += numedges;
+        ioHeaderInfo.nodessaved++;
 
         return *saved_position;
     }
     else
     {
-        unsigned int node_pos = global_header_info.edgesused;
-        global_hashtable->add(edges, global_header_info.edgesused);
-        global_header_info.edgesused += numedges;
-        global_header_info.nodesused++;
-        write_node(&edges.front(), numedges, global_outfile);
+        unsigned int node_pos = ioHeaderInfo.edgesused;
+        global_hashtable->add(edges, ioHeaderInfo.edgesused);
+        ioHeaderInfo.edgesused += numedges;
+        ioHeaderInfo.nodesused++;
+        write_node(&edges.front(), numedges, outfile);
 
         return node_pos;
     }
 }
 
 
+void printUsage(const string &iBinaryName)
+{
+    cout << "Usage: " << iBinaryName << " [options]" << endl
+         << "Mandatory options:" << endl
+         << "  -d, --dicname <string>  Set the dictionary name and version" << 
endl
+         << "  -l, --letters <string>  Set the dictionary letters" << endl
+         << "  -i, --input <string>    Name of the uncompressed dictionary 
file" << endl
+         << "  -o, --output <string    Name of the generated compressed 
dictionary file" << endl
+         << "Other options:" << endl
+         << "  -h, --help              Print this help and exit" << endl
+         << "Example:" << endl
+         << "  " << iBinaryName << " -d 'ODS 5.0' -l 
ABCDEFGHIJKLMNOPQRSTUVWXYZ -i list -o ods5.dawg" << endl;
+}
+
+
 int main(int argc, char* argv[])
 {
-    if (argc < 2)
+    setlocale(LC_ALL, "");
+
+    static const struct option long_options[] =
     {
-        fprintf(stderr, "usage: %s uncompressed_dic [compressed_dic]\n", 
argv[0]);
-        exit(1);
+        {"help", no_argument, NULL, 'h'},
+        {"dicname", required_argument, NULL, 'd'},
+        {"letters", required_argument, NULL, 'l'},
+        {"input", required_argument, NULL, 'i'},
+        {"output", required_argument, NULL, 'o'},
+        {0, 0, 0, 0}
+    };
+    static const char short_options[] = "hd:l:i:o:";
+
+    bool found_d = false;
+    bool found_l = false;
+    bool found_i = false;
+    bool found_o = false;
+    wstring dicName;
+    wstring letters;
+    string inFileName;
+    string outFileName;
+
+    int res;
+    int option_index = 1;
+    while ((res = getopt_long(argc, argv, short_options,
+                              long_options, &option_index)) != -1)
+    {
+        switch (res)
+        {
+            case 'h':
+                printUsage(argv[0]);
+                exit(0);
+            case 'd':
+                found_d = true;
+                dicName = convertToWc(optarg);
+                break;
+            case 'l':
+                found_l = true;
+                letters = convertToWc(optarg);
+                // Ensure that the letters are uppercase
+                for (unsigned int i = 0; i < letters.size(); ++i)
+                    letters[i] = towupper(letters[i]);
+                break;
+            case 'i':
+                found_i = true;
+                inFileName = optarg;
+                break;
+            case 'o':
+                found_o = true;
+                outFileName = optarg;
+                break;
+        }
     }
 
-    int size = file_length(argv[1]);
-    if (size < 0)
+    // Check mandatory options
+    if (!found_d || !found_l || !found_i || !found_o)
     {
-        fprintf(stderr, "Cannot stat uncompressed dictionary %s\n", argv[1]);
+        cerr << "A mandatory option is missing" << endl;
+        printUsage(argv[0]);
         exit(1);
     }
 
-    const char *outfilename = (argc == 3) ? argv[2] : "dict.daw";
+    struct stat stat_buf;
+    if (stat(inFileName.c_str(), &stat_buf) < 0)
+    {
+        cerr << "Cannot stat uncompressed dictionary " << inFileName << endl;
+        exit(1);
+    }
+    unsigned int dicsize = (unsigned int)stat_buf.st_size;
 
-    global_outfile.open(outfilename, ios::out | ios::binary | ios::trunc);
-    if (!global_outfile.is_open())
+    ofstream outfile(outFileName.c_str(), ios::out | ios::binary | ios::trunc);
+    if (!outfile.is_open())
     {
-        fprintf(stderr, "Cannot open output file %s\n", outfilename);
+        cerr << "Cannot open output file " << outFileName << endl;
         exit(1);
     }
 
-    unsigned int dicsize = size;
-    wchar_t *uncompressed;
+    try
+    {
     clock_t startLoadTime = clock();
-    if ((uncompressed = load_uncompressed(argv[1], dicsize)) == NULL)
+        wchar_t *uncompressed = load_uncompressed(inFileName, dicsize);
+        if (uncompressed == NULL)
     {
         fprintf(stderr, "Cannot load uncompressed dictionary into memory\n");
         exit(1);
@@ -337,46 +407,48 @@
     global_hashtable = new HashTable<vector<Dawg_edge>, unsigned int, 
HashVector>((unsigned int)(dicsize * SCALE));
 #undef SCALE
 
-    skip_init_header(global_outfile, &global_header_info);
-
-    // TODO: remove hard-coding
-    global_header_info.letters = convertToWc("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
-    // Init the map char --> code
-    for (string::size_type i = 0; i < global_header_info.letters.size(); ++i)
-    {
-        global_chartocode[global_header_info.letters[i]] = i + 1;
-        global_chartocode[towlower(global_header_info.letters[i])] = i + 1;
-    }
+        Dict_header_info headerInfo;
+        headerInfo.dicName = dicName;
+        headerInfo.letters = letters;
+        headerInfo.dawg = true;
+        Header tempHeader = skip_init_header(outfile, headerInfo);
 
     Dawg_edge specialnode = {0, 0, 0, 0, 0};
     specialnode.last = 1;
-    write_node(&specialnode, 1, global_outfile);
+        write_node(&specialnode, 1, outfile);
 
     /*
      * Call makenode with null (relative to stringbuf) prefix;
      * Initialize string to null; Put index of start node on output
      */
-    clock_t startBuildTime = clock();
     Dawg_edge rootnode = {0, 0, 0, 0, 0};
-    rootnode.ptr = makenode(global_endstring = global_stringbuf);
+        global_endstring = global_stringbuf;
+        clock_t startBuildTime = clock();
+        rootnode.ptr = makenode(global_endstring, outfile, headerInfo, 
tempHeader);
     clock_t endBuildTime = clock();
-    write_node(&rootnode, 1, global_outfile);
+        write_node(&rootnode, 1, outfile);
 
-    fix_header(global_outfile, &global_header_info);
+        fix_header(outfile, headerInfo);
 
-    Header aHeader(global_header_info);
+        Header aHeader(headerInfo);
     aHeader.print();
 
     delete global_hashtable;
     delete[] uncompressed;
-    global_outfile.close();
+        outfile.close();
 
-    printf(" Load time: %f s\n", 1.0 * (endLoadTime - startLoadTime) / 
CLOCKS_PER_SEC);
-    printf(" Compression time: %f s\n", 1.0 * (endBuildTime - startBuildTime) 
/ CLOCKS_PER_SEC);
+        printf(" Load time: %.3f s\n", 1.0 * (endLoadTime - startLoadTime) / 
CLOCKS_PER_SEC);
+        printf(" Compression time: %.3f s\n", 1.0 * (endBuildTime - 
startBuildTime) / CLOCKS_PER_SEC);
 #ifdef CHECK_RECURSION
     printf(" Maximum recursion level reached: %d\n", max_rec);
 #endif
     return 0;
-}
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
+        return 1;
+    }
 
+}
 

Index: dic/dic.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/dic.cpp,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -b -r1.1.2.5 -r1.1.2.6
--- dic/dic.cpp 11 Nov 2007 19:34:32 -0000      1.1.2.5
+++ dic/dic.cpp 21 Nov 2007 16:25:44 -0000      1.1.2.6
@@ -33,6 +33,7 @@
 #include "config.h"
 #include "dic.h"
 #include "header.h"
+#include "dic_exception.h"
 #include "dic_internals.h"
 
 
@@ -58,7 +59,7 @@
 {
 #if defined(WORDS_BIGENDIAN)
     uint32_t *p = (uint32_t*)m_dawg;
-    for (int i = 0; i < (m_nbEdges + 1); i++)
+    for (int i = 0; i < (m_header->getNbEdgesUsed() + 1); i++)
     {
         p[i] = swap4(p[i]);
     }
@@ -66,53 +67,35 @@
 }
 
 
-Dictionary::Dictionary()
+Dictionary::Dictionary(const string &iPath)
     : m_dawg(NULL)
 {
-}
-
-
-Dictionary::~Dictionary()
-{
-    if (m_dawg != NULL)
-        delete[] m_dawg;
-}
-
-
-int Dictionary::load(const string &iPath)
-{
     ifstream file(iPath.c_str(), ios::in | ios::binary);
 
     if (!file.is_open())
-        return 1;
+        throw DicException("Cannot open " + iPath);
 
-    Header aHeader;
-    if (!aHeader.read(file))
-        return 2;
+    // XXX: we should protect these allocations with auto_ptr
+    m_header = new Header(file);
+    m_dawg = new Dawg_edge[m_header->getNbEdgesUsed() + 1];
 
-    m_dawg = new Dawg_edge[aHeader.getNbEdgesUsed() + 1];
-    if (m_dawg == NULL)
-    {
-        return 4;
-    }
-
-    streamsize toRead = (aHeader.getNbEdgesUsed() + 1) * sizeof(Dawg_edge);
+    streamsize toRead = (m_header->getNbEdgesUsed() + 1) * sizeof(Dawg_edge);
     file.read((char*)m_dawg, toRead);
     if (file.gcount() != toRead)
     {
         delete[] m_dawg;
-        m_dawg = NULL;
-        return 5;
+        delete m_header;
+        throw DicException("Problem reading dictionary arcs");
     }
 
-    m_root = aHeader.getRoot();
-    m_nbWords = aHeader.getNbWords();
-    m_nbNodes = aHeader.getNbNodesUsed();
-    m_nbEdges = aHeader.getNbEdgesUsed();
-
     convertDataToArch();
+}
 
-    return 0;
+
+Dictionary::~Dictionary()
+{
+    delete[] m_dawg;
+    delete m_header;
 }
 
 
@@ -132,7 +115,8 @@
 
 const dic_elt_t Dictionary::getRoot() const
 {
-    return m_root;
+    return m_header->getRoot();
+
 }
 
 

Index: dic/dic.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/dic.h,v
retrieving revision 1.13.2.3
retrieving revision 1.13.2.4
diff -u -b -r1.13.2.3 -r1.13.2.4
--- dic/dic.h   20 Nov 2007 12:54:03 -0000      1.13.2.3
+++ dic/dic.h   21 Nov 2007 16:25:44 -0000      1.13.2.4
@@ -27,6 +27,9 @@
 #ifndef _DIC_H_
 #define _DIC_H_
 
+#include <string>
+
+
 /**
  * different letters in the dictionary
  */
@@ -37,33 +40,27 @@
  */
 #define DIC_WORD_MAX 16
 
-//typedef struct _Dawg_edge Dawg_edge;
+class Header;
 class Dawg_edge;
 typedef unsigned int dic_elt_t;
 typedef unsigned char dic_code_t;
 
-#include <string>
-
 using namespace std;
 
 class Dictionary
 {
 public:
-    /// Constructor
-    Dictionary();
-
-    /// Destructor
-    ~Dictionary();
-
     /**
      * Dictionary creation and loading from a file
-     * @param dic : pointer to a dictionary
-     * @param path : compressed dictionary path
-     * @return 0 ok, 1 error
+     * @param path: compressed dictionary path
      */
-    int load(const string &path);
+    Dictionary(const string &path);
+
+    /// Destructor
+    ~Dictionary();
 
-    int getNbEdges() const { return m_nbEdges; }
+    /** Give access to the dictionary header */
+    const Header& getHeader() const { return *m_header; }
 
     /**
      * Returns the character code associated with an element,
@@ -145,11 +142,8 @@
     Dictionary &operator=(const Dictionary&);
     Dictionary(const Dictionary&);
 
+    Header *m_header;
     Dawg_edge *m_dawg;
-    dic_elt_t m_root;
-    int m_nbWords;
-    int m_nbNodes;
-    int m_nbEdges;
 
     void convertDataToArch();
 };

Index: dic/header.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/header.cpp,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.7
diff -u -b -r1.1.2.6 -r1.1.2.7
--- dic/header.cpp      20 Nov 2007 12:54:03 -0000      1.1.2.6
+++ dic/header.cpp      21 Nov 2007 16:25:44 -0000      1.1.2.7
@@ -1,5 +1,5 @@
 /* Eliot                                                                     */
-/* Copyright (C) 2006  Olivier Teuliere                                      */
+/* Copyright (C) 2007  Olivier Teuliere                                      */
 /*                                                                           */
 /* This file is part of Eliot.                                               */
 /*                                                                           */
@@ -18,9 +18,13 @@
 /* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
 
 #include <string>
+#include <sstream>
+#include <iostream>
 
 #include "config.h"
 #include "header.h"
+#include "encoding.h"
+#include "dic_exception.h"
 #include <iconv.h>
 
 
@@ -57,7 +61,7 @@
     /// Identification string
     char ident[sizeof(_COMPIL_KEYWORD_)];
     /// Version of the serialization format
-    char version;
+    uint8_t version;
     /// Unused at the moment, reserved for further use
     char unused;
     uint32_t root;
@@ -73,7 +77,7 @@
 
 // Do not change these values, as they impact the size of the structure
 #define _USER_HOST_MAX_ 24
-#define _DIC_NAME_MAX_ 16
+#define _MAX_DIC_NAME_SIZE_ 32
 #define _MAX_LETTERS_SIZE_ 80
 
 /** Extension of the old format */
@@ -89,32 +93,40 @@
     // Endianness (XXX: currently unused)
     char bigEndian;
 
-    // Dictionary official name and version
-    char dicName[_DIC_NAME_MAX_];
-    char dicVersion;
-    char dicRevision;
+    // Dictionary official name and version (e.g.: ODS 5.0)
+    char dicName[_MAX_DIC_NAME_SIZE_];
+    // Size taken by the dictionary name
+    uint32_t dicNameSize;
 
     // Letters used in the dictionary
     // We should have: nbLetters <= lettersSize <= _MAX_LETTERS_SIZE_
-    // Number of letters (XXX: in theory useless, but allows a sanity check)
-    uint32_t nbLetters;
-    // Size taken by the letters
-    uint32_t lettersSize;
     // The letters themselves, in UTF-8
     char letters[_MAX_LETTERS_SIZE_];
+    // Size taken by the letters
+    uint32_t lettersSize;
+    // Number of letters (XXX: in theory useless, but allows a sanity check)
+    uint32_t nbLetters;
     //@}
 };
 
 
-Header::Header()
+Header::Header(istream &iStream)
     : m_root(0), m_nbWords(0), m_nodesUsed(0), m_edgesUsed(0),
       m_nodesSaved(0), m_edgesSaved(0), m_type(kDAWG)
 {
+    // Simply delegate to the read() method
+    // The code is not moved here because I find it more natural to have a
+    // read() method symmetrical to the write() one
+    read(iStream);
+    buildMapCodeFromChar();
 }
 
 
 Header::Header(const Dict_header_info &iInfo)
 {
+    // Use the latest serialization format
+    m_version = 1;
+
     m_root = iInfo.root;
     m_nbWords = iInfo.nwords;
     m_nodesUsed = iInfo.nodesused;
@@ -122,23 +134,65 @@
     m_nodesSaved = iInfo.nodessaved;
     m_edgesSaved = iInfo.edgessaved;
     m_type = iInfo.dawg ? kDAWG : kGADDAG;
-    if (iInfo.letters.size() < _MAX_LETTERS_SIZE_)
+    m_dicName = iInfo.dicName;
+    // First protection, but it is not enough
+    if (iInfo.letters.size() >= _MAX_LETTERS_SIZE_)
+    {
+        throw DicException("Header::Header: Too many different letters for "
+                           "the current format");
+    }
+    m_letters = iInfo.letters;
+    buildMapCodeFromChar();
+}
+
+
+void Header::buildMapCodeFromChar()
+{
+    for (unsigned int i = 0; i < m_letters.size(); ++i)
+    {
+        // We don't differentiate uppercase and lowercase letters
+        m_mapCodeFromChar[towlower(m_letters[i])] = i + 1;
+        m_mapCodeFromChar[towupper(m_letters[i])] = i + 1;
+    }
+}
+
+
+wchar_t Header::getCharFromCode(unsigned int iCode) const
+{
+    // Safety check
+    if (iCode == 0 || iCode > m_letters.size())
     {
-        wcscpy(m_letters, iInfo.letters.c_str());
+        ostringstream ss;
+        ss << iCode;
+        throw DicException("Header::getCharFromCode: no letter for code " + 
ss.str());
     }
+    return m_letters[iCode - 1];
 }
 
 
-bool Header::read(istream &iStream)
+unsigned int Header::getCodeFromChar(wchar_t iChar) const
+{
+    map<wchar_t, unsigned int>::const_iterator pair =
+        m_mapCodeFromChar.find(iChar);
+    if (pair == m_mapCodeFromChar.end())
+    {
+        throw DicException("Header::getCodeFromChar: No code for letter " +
+                           convertToMb(iChar));
+    }
+    return pair->second;
+}
+
+
+void Header::read(istream &iStream)
 {
     Dict_header_old aHeader;
     iStream.read((char*)&aHeader, sizeof(Dict_header_old));
     if (iStream.gcount() != sizeof(Dict_header_old))
-        return false;
+        throw DicException("Header::read: expected to read more bytes");
 
     // Check the identification string
     if (string(aHeader.ident) != _COMPIL_KEYWORD_)
-        return false;
+        throw DicException("Header::read: incorrect header keyword; is it a 
dictionary file?");
 
 #if defined(WORDS_BIGENDIAN)
     aHeader.root       = swap4(aHeader.root);
@@ -155,62 +209,50 @@
     m_edgesUsed = aHeader.edgesused;
     m_nodesSaved = aHeader.nodessaved;
     m_edgesSaved = aHeader.edgessaved;
+    m_version = aHeader.version;
 
-    if (aHeader.version > 0)
+    if (m_version == 0)
+    {
+        m_letters = convertToWc("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+        m_dicName = convertToWc("Unspecified (old format)");
+    }
+    else
     {
         // This header doesn't use the old serialization format, so read the
         // extension as well
         Dict_header_ext aHeaderExt;
         iStream.read((char*)&aHeaderExt, sizeof(Dict_header_ext));
         if (iStream.gcount() != sizeof(Dict_header_ext))
-            return false;
+            throw DicException("Header::read: expected to read more bytes");
 
         if (aHeaderExt.algorithm == kDAWG)
             m_type = kDAWG;
         else if (aHeaderExt.algorithm == kGADDAG)
             m_type = kGADDAG;
         else
-            return false;
-        aHeaderExt.dicName[_DIC_NAME_MAX_ - 1] = '\0';
-        m_dicName = aHeaderExt.dicName;
-        m_dicVersion = aHeaderExt.dicVersion;
-        m_dicRevision = aHeaderExt.dicRevision;
+            throw DicException("Header::read: unrecognized algorithm type");
 
-        // Convert the letters from UTF-8 to wchar_t*
-        iconv_t handle = iconv_open("WCHAR_T", "UTF-8");
-        if (handle == (iconv_t)(-1))
-            return false;
-        size_t inChars = aHeaderExt.lettersSize;
-        size_t outChars = sizeof(wchar_t) * (_MAX_NB_LETTERS_ - 1);
-        char *in = aHeaderExt.letters;
-        char *out = (char*)m_letters;
-        size_t res = iconv(handle, &in, &inChars, &out, &outChars);
-        iconv_close(handle);
-        // Problem during encoding conversion?
-        if (res == (size_t)(-1))
-            return false;
+        // Convert the dictionary letters from UTF-8 to wchar_t*
+        readFromUTF8(m_dicName, aHeaderExt.dicName,
+                     aHeaderExt.dicNameSize, "dictionary name");
+
+        // Convert the dictionary letters from UTF-8 to wchar_t*
+        readFromUTF8(m_letters, aHeaderExt.letters,
+                     aHeaderExt.lettersSize, "dictionary letters");
         // Safety check: correct number of letters?
-        if (outChars + sizeof(wchar_t) * aHeaderExt.nbLetters !=
-            sizeof(wchar_t) * (_MAX_NB_LETTERS_ - 1))
+        if (m_letters.size() != aHeaderExt.nbLetters)
         {
-            return false;
+            throw DicException("Header::read: inconsistent header");
         }
-        // Make sure there is a \0 at the end of the letters array
-        wchar_t *wout = (wchar_t*)out;
-        *wout = '\0';
     }
-    return true;
 }
 
 
-bool Header::write(ostream &oStream, bool iOldFormat) const
+void Header::write(ostream &oStream) const
 {
     Dict_header_old aHeader;
     strcpy(aHeader.ident, _COMPIL_KEYWORD_);
-    if (iOldFormat)
-        aHeader.version = 0;
-    else
-        aHeader.version = 1;
+    aHeader.version = m_version;
     aHeader.unused = 0;
     aHeader.root = m_root;
     aHeader.nwords = m_nbWords;
@@ -221,66 +263,99 @@
 
     oStream.write((char*)&aHeader, sizeof(Dict_header_old));
     if (!oStream.good())
-        return false;
+        throw DicException("Header::write: error when writing to file");
 
-    if (!iOldFormat)
+    if (m_version != 0)
     {
         Dict_header_ext aHeaderExt;
         string userHost = ELIOT_COMPILE_BY + string("@") + ELIOT_COMPILE_HOST;
         strncpy(aHeaderExt.compileUserHost, userHost.c_str(), _USER_HOST_MAX_);
         aHeaderExt.compileUserHost[_USER_HOST_MAX_ - 1] = '\0';
         aHeaderExt.algorithm = m_type;
-        strncpy(aHeaderExt.dicName, m_dicName.c_str(), _DIC_NAME_MAX_);
-        aHeaderExt.dicName[_DIC_NAME_MAX_ - 1] = '\0';
-        aHeaderExt.dicVersion = m_dicVersion;
-        aHeaderExt.dicRevision = m_dicRevision;
-
-        size_t length = wcslen(m_letters);
-        // Sanity check
-        if (length >= _MAX_NB_LETTERS_)
-            return false;
-        aHeaderExt.nbLetters = (uint32_t)length;
+
+        // Convert the dictionary name to UTF-8
+        aHeaderExt.dicNameSize =
+            writeInUTF8(m_dicName, aHeaderExt.dicName,
+                        _MAX_DIC_NAME_SIZE_, "dictionary name");
 
         // Convert the dictionary letters to UTF-8
+        aHeaderExt.lettersSize =
+            writeInUTF8(m_letters, aHeaderExt.letters,
+                        _MAX_LETTERS_SIZE_, "dictionary letters");
+        aHeaderExt.nbLetters = (uint32_t)m_letters.size();
+
+        // Write the extension
+        oStream.write((char*)&aHeaderExt, sizeof(Dict_header_ext));
+        if (!oStream.good())
+            throw DicException("Header::write: error when writing to file");
+    }
+}
+
+
+void Header::readFromUTF8(wstring &oString, const char *iBuffer,
+                          unsigned int iBufSize, const string &iContext) const
+{
+    iconv_t handle = iconv_open("WCHAR_T", "UTF-8");
+    if (handle == (iconv_t)(-1))
+        throw DicException("Header::readFromUTF8: iconv_open failed");
+    // Temporary buffer for output
+    // We will have at most as many characters as in the UTF-8 string
+    wchar_t outbuf[iBufSize];
+    size_t inChars = iBufSize;
+    size_t outChars = sizeof(wchar_t) * iBufSize;
+    char *in = const_cast<char *>(iBuffer);
+    char *out = (char*)outbuf;
+    size_t res = iconv(handle, &in, &inChars, &out, &outChars);
+    iconv_close(handle);
+    // Problem during encoding conversion?
+    if (res == (size_t)(-1))
+    {
+        throw DicException("Header::readFromUTF8: iconv failed (" +
+                           iContext + ")");
+    }
+    // We finally have the letters as a wstring!
+    oString = wstring(outbuf, iBufSize - outChars / sizeof(wchar_t));
+}
+
+
+unsigned int Header::writeInUTF8(const wstring &iString, char *oBuffer,
+                                 unsigned int iBufSize, const string 
&iContext) const
+{
         iconv_t handle = iconv_open("UTF-8", "WCHAR_T");
         if (handle == (iconv_t)(-1))
-            return false;
+        throw DicException("Header::writeInUTF8: iconv_open failed");
+    size_t length = iString.size();
         size_t inChars = sizeof(wchar_t) * length;
-        size_t outChars = _MAX_LETTERS_SIZE_;
-        char *in = (char*)m_letters;
-        char *out = aHeaderExt.letters;
+    size_t outChars = iBufSize;
+    char *in = (char*)&iString[0];
+    char *out = oBuffer;
         size_t res = iconv(handle, &in, &inChars, &out, &outChars);
         iconv_close(handle);
         // Problem during encoding conversion?
         if (res == (size_t)(-1))
-            return false;
-        aHeaderExt.lettersSize = _MAX_LETTERS_SIZE_ - outChars;
-
-        // Write the extension
-        oStream.write((char*)&aHeaderExt, sizeof(Dict_header_ext));
-        if (!oStream.good())
-            return false;
+    {
+        throw DicException("Header::writeInUTF8: iconv failed (" +
+                           iContext + ")");
     }
-    return true;
+    // Return the number of written bytes
+    return iBufSize - outChars;
 }
 
 
 void Header::print() const
 {
     printf("============================\n");
-    printf("keyword length %u bytes\n", strlen(_COMPIL_KEYWORD_));
-    printf("keyword size   %u bytes\n", sizeof(_COMPIL_KEYWORD_));
-    printf("header size    %u bytes\n", sizeof(Dict_header_old));
-    printf("\n");
-    printf("%d words\n", m_nbWords);
-    printf("\n");
-    printf("root: %7d (edge)\n", m_root);
+    printf("dictionary name: %s\n", convertToMb(m_dicName).c_str());
+    printf("dictionary type: %s\n", m_type == kDAWG ? "DAWG" : "GADDAG");
+    printf("letters: %s\n", convertToMb(m_letters).c_str());
+    printf("number of letters: %d\n", m_letters.size());
+    printf("number of words: %d\n", m_nbWords);
+    printf("header size: %u bytes\n", sizeof(Dict_header_old) +
+           m_version ? sizeof(Dict_header_ext) : 0);
+    printf("root: %d (edge)\n", m_root);
 //     printf("root: %7u (byte)\n", m_root * sizeof(Dawg_edge));
-    printf("\n");
-    printf("nodes: %d+%d\n", m_nodesUsed, m_nodesSaved);
-    printf("edges: %d+%d\n", m_edgesUsed, m_edgesSaved);
-    printf("number of letters: %d\n", wcslen(m_letters));
-    printf("letters: %ls\n", m_letters);
+    printf("nodes: %d used + %d saved\n", m_nodesUsed, m_nodesSaved);
+    printf("edges: %d used + %d saved\n", m_edgesUsed, m_edgesSaved);
     printf("============================\n");
 
 #if 0

Index: dic/header.h
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/header.h,v
retrieving revision 1.1.2.4
retrieving revision 1.1.2.5
diff -u -b -r1.1.2.4 -r1.1.2.5
--- dic/header.h        20 Nov 2007 12:54:04 -0000      1.1.2.4
+++ dic/header.h        21 Nov 2007 16:25:44 -0000      1.1.2.5
@@ -20,13 +20,11 @@
 #ifndef _HEADER_H
 #define _HEADER_H
 
-#include <iostream>
+#include <iosfwd>
+#include <map>
 
 using namespace std;
 
-/// Maximum number of distinct letters allowed for the dictionary
-#define _MAX_NB_LETTERS_ 64
-
 
 /**
  * Structure used to create a Header object.
@@ -43,6 +41,7 @@
     unsigned int edgessaved;
     bool dawg;
     wstring letters;
+    wstring dicName;
 };
 
 
@@ -51,13 +50,16 @@
  * There are 2 ways to create a Header object:
  *  - fill a Dict_header_info structure and give it in the constructor of the
  *    Header class (usually to call write() afterwards)
- *  - use the default constructor, then call read() on a dictionary file
+ *  - give it an input stream on a compiled dictionary
+ *
+ * The class is immutable: a Header object cannot be modified after creation.
  *
  * Serialization:
  * Several formats of headers will be handled by this class, even though only
  * the first one is handled at the moment. You can use the write() method to
- * write the latest version of the header into a given file. The read() method
- * can be used to read any header format.
+ * write the latest version of the header into a given file.
+ * When using the constructor taking an input stream, all the header versions
+ * are supported.
  */
 class Header
 {
@@ -70,10 +72,16 @@
         kGADDAG = 2
     };
 
-    /// Default constructor (usually used to call read() afterwards)
-    Header();
+    /**
+     * Constructor from an input stream
+     * @param iStream: Input stream where to read the header
+     */
+    Header(istream &iStream);
 
-    /// Constructor from a filled structure
+    /**
+     * Constructor from a filled structure
+     * @param iInfo: info needed to build the header
+     */
     Header(const Dict_header_info &iInfo);
 
     /// Getters
@@ -89,25 +97,31 @@
     //@}
 
     /**
-     * Print a readable summary of the header on standard output
+     * Return the letter corresponding to the given code
      */
-    void print() const;
+    wchar_t getCharFromCode(unsigned int iCode) const;
 
     /**
-     * Load the header from a file
-     * @param iStream: Input stream where to read the header
-     * @return true if the header was read correctly, false otherwise
+     * Return the code corresponding to the given letter
+     */
+    unsigned int getCodeFromChar(wchar_t iChar) const;
+
+    /**
+     * Print a readable summary of the header on standard output
      */
-    bool read(istream &iStream);
+    void print() const;
 
     /**
      * Write the header to a file, using the latest format
      * @param oStream: Output stream where to write the header
-     * @return true if the header was written correctly, false otherwise
+     * @exception: Throw a DicException in case of problem
      */
-    bool write(ostream &oStream, bool iOldFormat = false) const;
+    void write(ostream &oStream) const;
 
 private:
+    /// Version of the serialization
+    uint8_t m_version;
+
     uint32_t m_root;
     uint32_t m_nbWords;
     uint32_t m_nodesUsed;
@@ -118,16 +132,45 @@
     /// Specify whether the dictionary is a DAWG or a GADDAG
     DictType m_type;
 
-    /// Dictionary name (e.g.: ODS)
-    string m_dicName;
-    /// Dictionary major version (e.g.: 4 for ODS 4.1);
-    char m_dicVersion;
-    /// Dictionary revision (e.g.: 1 for ODS 4.1)
-    char m_dicRevision;
-
-    /// The letters themselves. The array is terminated with \0.
-    // XXX: use a wstring instead?
-    wchar_t m_letters[_MAX_NB_LETTERS_];
+    /// Dictionary name (e.g.: ODS 5.0)
+    wstring m_dicName;
+
+    /// The letters constituting the words of the dictionary
+    wstring m_letters;
+
+    map<wchar_t, unsigned int> m_mapCodeFromChar;
+
+    /**
+     * Load the header from a file
+     * @param iStream: Input stream where to read the header
+     * @exception: Throw a DicException in case of problem
+     */
+    void read(istream &iStream);
+
+    /** Build m_mapCodeFromChar */
+    void buildMapCodeFromChar();
+
+    /**
+     * Utility function to convert a char* buffer encoded in UTF-8 into a
+     * wide wstring
+     * @param oString: where to write the converted string
+     * @param iBuffer: UTF-8 string to convert
+     * @param iBufSize: available size in iBuffer
+     * @param iContext: free text used in case of exception
+     */
+    void readFromUTF8(wstring &oString, const char *iBuffer,
+                      unsigned int iBufSize, const string &iContext) const;
+
+    /**
+     * Utility function to convert a wstring into an UTF-8 char* buffer
+     * @param iString: the wide string to encode
+     * @param oBuffer: where to write the encoded string
+     * @param iBufSize: available size in oBuffer
+     * @param iContext: free text used in case of exception
+     * @return: number of bytes actually written
+     */
+    unsigned int writeInUTF8(const wstring &iString, char *oBuffer,
+                             unsigned int iBufSize, const string &iContext) 
const;
 };
 
 

Index: dic/listdic.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/listdic.cpp,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -b -r1.1.2.5 -r1.1.2.6
--- dic/listdic.cpp     11 Nov 2007 19:56:58 -0000      1.1.2.5
+++ dic/listdic.cpp     21 Nov 2007 16:25:44 -0000      1.1.2.6
@@ -25,73 +25,45 @@
  */
 
 #include <fstream>
+#include <iostream>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stddef.h>
+
 #include "header.h"
+#include "encoding.h"
 #include "dic_internals.h"
 #include "dic.h"
 
+using namespace std;
+
 
-static void print_dic_rec(FILE* out, const Dictionary &dic, char *buf, char* 
s, Dawg_edge i)
+static void print_dic_rec(ostream &out, const Dictionary &iDic, wchar_t *buf, 
wchar_t *s, Dawg_edge i)
 {
     if (i.term)  /* edge points at a complete word */
     {
         *s = '\0';
-        fprintf(out, "%s\n", buf);
+        out << convertToMb(buf) << endl;
     }
     if (i.ptr)
     {           /* Compute index: is it non-zero ? */
-        const Dawg_edge *p = dic.getDawg() + i.ptr;
+        const Dawg_edge *p = iDic.getDawg() + i.ptr;
         do
         {                         /* for each edge out of this node */
-            *s = p->chr + 'a' - 1;
-            print_dic_rec(out, dic, buf, s + 1, *p);
+            *s = iDic.getHeader().getCharFromCode(p->chr);
+            print_dic_rec(out, iDic, buf, s + 1, *p);
         }
         while (!(*p++).last);
     }
 }
 
 
-void dic_load(Dictionary &dic, const string &iFileName)
+void print_dic_list(const string &iFileName)
 {
-    int res;
-    if ((res = dic.load(iFileName)) != 0)
-    {
-        switch (res)
-        {
-            case 1: printf("chargement: problème d'ouverture de %s\n", 
iFileName.c_str()); break;
-            case 2: printf("chargement: mauvais en-tete de dictionnaire\n"); 
break;
-            case 3: printf("chargement: problème 3 d'allocation mémoire\n"); 
break;
-            case 4: printf("chargement: problème 4 d'allocation mémoire\n"); 
break;
-            case 5: printf("chargement: problème de lecture des arcs du 
dictionnaire\n"); break;
-            default: printf("chargement: problème non-repertorié\n"); break;
-        }
-        exit(res);
-    }
-}
-
-
-void print_dic_list(const string &iFileName, const char* out)
-{
-    Dictionary dic;
-    static char buf[80];
-
-    dic_load(dic, iFileName);
-
-    if (strcmp(out, "stdout") == 0)
-        print_dic_rec(stdout, dic, buf, buf, dic.getDawg()[dic.getRoot()]);
-    else if (strcmp(out, "stderr") == 0)
-        print_dic_rec(stderr, dic, buf, buf, dic.getDawg()[dic.getRoot()]);
-    else
-    {
-        FILE *fout;
-        if ((fout = fopen(out, "w")) == NULL)
-            return;
-        print_dic_rec(fout, dic, buf, buf, dic.getDawg()[dic.getRoot()]);
-        fclose(fout);
-    }
+    static wchar_t buf[80];
+    Dictionary dic(iFileName);
+    print_dic_rec(cout, dic, buf, buf, dic.getDawg()[dic.getRoot()]);
 }
 
 
@@ -100,16 +72,11 @@
     ifstream file(iFileName.c_str(), ios::in | ios::binary);
     if (!file.is_open())
     {
-        fprintf(stderr, "Couldn't open file: %s\n", iFileName.c_str());
+        cerr << "Couldn't open file: " << iFileName << endl;
         exit(1);
     }
 
-    Header header;
-    if (!header.read(file))
-    {
-        fprintf(stderr, "Invalid header in '%s'\n", iFileName.c_str());
-        exit(1);
-    }
+    Header header(file);
     header.print();
 }
 
@@ -132,12 +99,11 @@
 
 void print_dic_hex(const string &iFileName)
 {
-    Dictionary dic;
-    dic_load(dic, iFileName);
+    Dictionary dic(iFileName);
 
     printf("offs binary       structure\n");
     printf("---- -------- |   ------------------\n");
-    for (int i = 0; i < (dic.getNbEdges() + 1); i++)
+    for (unsigned int i = 0; i < (dic.getHeader().getNbEdgesUsed() + 1); i++)
         print_node_hex(dic, i);
 }
 
@@ -154,6 +120,8 @@
 
 int main(int argc, char *argv[])
 {
+    setlocale(LC_ALL, "");
+
     int arg_count;
     int option_print_all      = 0;
     int option_print_header   = 0;
@@ -181,6 +149,8 @@
         arg_count++;
     }
 
+    try
+    {
     if (option_print_header || option_print_all)
     {
         print_header(argv[arg_count]);
@@ -191,7 +161,13 @@
     }
     if (option_print_dic_list || option_print_all)
     {
-        print_dic_list(argv[arg_count], "stdout");
+            print_dic_list(argv[arg_count]);
     }
     return 0;
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
+        return 1;
+    }
 }

Index: dic/regexpmain.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/dic/Attic/regexpmain.cpp,v
retrieving revision 1.1.2.2
retrieving revision 1.1.2.3
diff -u -b -r1.1.2.2 -r1.1.2.3
--- dic/regexpmain.cpp  11 Nov 2007 19:56:58 -0000      1.1.2.2
+++ dic/regexpmain.cpp  21 Nov 2007 16:25:44 -0000      1.1.2.3
@@ -25,6 +25,9 @@
  */
 
 #include "config.h"
+
+#include <exception>
+#include <iostream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -33,6 +36,7 @@
 #include "regexp.h"
 #include "dic_search.h"
 
+
 #define __UNUSED__ __attribute__((unused))
 
 /********************************************************/
@@ -99,12 +103,10 @@
         return 0;
     }
 
-    Dictionary dic;
-    if (dic.load(argv[1]))
+    setlocale(LC_ALL, "");
+    try
     {
-        fprintf(stdout, "impossible de lire le dictionnaire\n");
-        return 1;
-    }
+        Dictionary dic(argv[1]);
 
     char er[200];
     strcpy(er, ".");
@@ -135,4 +137,15 @@
     }
 
     return 0;
+    }
+    catch (std::exception &e)
+    {
+        std::cerr << e.what() << endl;
+        return 1;
+    }
+    catch (...)
+    {
+        std::cerr << "Unkown exception taken" << endl;
+        return 1;
+    }
 }

Index: game/game_factory.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game_factory.cpp,v
retrieving revision 1.8.2.2
retrieving revision 1.8.2.3
diff -u -b -r1.8.2.2 -r1.8.2.3
--- game/game_factory.cpp       11 Nov 2007 19:33:09 -0000      1.8.2.2
+++ game/game_factory.cpp       21 Nov 2007 16:25:44 -0000      1.8.2.3
@@ -19,6 +19,8 @@
 
 #include <getopt.h>
 #include <string>
+#include <fstream>
+#include <exception>
 
 #include "config.h"
 #include "dic.h"
@@ -35,7 +37,6 @@
 
 GameFactory::~GameFactory()
 {
-    if (m_dic)
         delete m_dic;
 }
 
@@ -50,7 +51,6 @@
 
 void GameFactory::Destroy()
 {
-    if (m_factory)
         delete m_factory;
     m_factory = NULL;
 }
@@ -146,10 +146,13 @@
     }
 
     // 3) Try to load the dictionary
-    m_dic = new Dictionary();
-    if (m_dic->load(m_dicStr.c_str()))
+    try
     {
-        cerr << "Could not load dictionary '" << m_dicStr << "'" << endl;
+        m_dic = new Dictionary(m_dicStr);
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
         return NULL;
     }
 
@@ -186,21 +189,21 @@
     return game;
 }
 
-Game* GameFactory::load(string filename, const Dictionary &iDic)
+
+Game* GameFactory::load(const string &iFileName, const Dictionary &iDic)
 {
-    Game* game;
-    FILE* fin;
-    if ((fin = fopen(filename.c_str(), "r")) == NULL)
+    FILE* fin = fopen(iFileName.c_str(), "r");
+    if (fin == NULL)
         {
-            printf("impossible d'ouvrir %s\n",
-                   filename.c_str());
+        printf("Cannot open %s\n", iFileName.c_str());
             return NULL;
         }
-    game = Game::load(fin, iDic);
+    Game *game = Game::load(fin, iDic);
     fclose(fin);
     return game;
 }
 
+
 void GameFactory::releaseGame(Game &iGame)
 {
     delete &iGame;

Index: game/game_factory.h
===================================================================
RCS file: /cvsroot/eliot/eliot/game/game_factory.h,v
retrieving revision 1.8.2.1
retrieving revision 1.8.2.2
diff -u -b -r1.8.2.1 -r1.8.2.2
--- game/game_factory.h 15 Oct 2006 11:07:55 -0000      1.8.2.1
+++ game/game_factory.h 21 Nov 2007 16:25:45 -0000      1.8.2.2
@@ -52,7 +52,7 @@
      * load() might need some more work to be robust enough to
      * handle "hand written" files
      */
-    Game *load(string filename, const Dictionary &iDic);
+    Game *load(const string &iFileName, const Dictionary &iDic);
 
     Game *createFromCmdLine(int argc, char **argv);
 

Index: utils/eliottxt.cpp
===================================================================
RCS file: /cvsroot/eliot/eliot/utils/eliottxt.cpp,v
retrieving revision 1.16.2.5
retrieving revision 1.16.2.6
diff -u -b -r1.16.2.5 -r1.16.2.6
--- utils/eliottxt.cpp  20 Nov 2007 12:54:04 -0000      1.16.2.5
+++ utils/eliottxt.cpp  21 Nov 2007 16:25:45 -0000      1.16.2.6
@@ -974,37 +974,9 @@
         dicPath = argv[1];
     }
 
-    Dictionary dic;
-    switch (dic.load(dicPath))
+    try
     {
-        case 0:
-            /* Normal case */
-            break;
-        case 1:
-            printf("chargement: problème d'ouverture de %s\n", argv[1]);
-            exit(1);
-            break;
-        case 2:
-            printf("chargement: mauvais en-tete de dictionnaire\n");
-            exit(2);
-            break;
-        case 3:
-            printf("chargement: problème 3 d'allocation mémoire\n");
-            exit(3);
-            break;
-        case 4:
-            printf("chargement: problème 4 d'alocation mémoire\n");
-            exit(4);
-            break;
-        case 5:
-            printf("chargement: problème de lecture des arcs du 
dictionnaire\n");
-            exit(5);
-            break;
-        default:
-            printf("chargement: problème non-repertorié\n");
-            exit(6);
-            break;
-    }
+        Dictionary dic(dicPath);
 
     if (argc == 3)
         srand(atoi(argv[2]));
@@ -1019,6 +991,11 @@
         free(line_read);
     if (wline_read)
         delete[] wline_read;
+    }
+    catch (std::exception &e)
+    {
+        cerr << e.what() << endl;
+    }
 
     return 0;
 }

Index: wxwin/mainframe.cc
===================================================================
RCS file: /cvsroot/eliot/eliot/wxwin/mainframe.cc,v
retrieving revision 1.21.2.2
retrieving revision 1.21.2.3
diff -u -b -r1.21.2.2 -r1.21.2.3
--- wxwin/mainframe.cc  11 Nov 2007 19:57:00 -0000      1.21.2.2
+++ wxwin/mainframe.cc  21 Nov 2007 16:25:45 -0000      1.21.2.3
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <iostream>
 #include <fstream>
+#include <exception>
 
 using namespace std;
 
@@ -162,30 +163,29 @@
     reslist = NULL;
 #endif
     statusbar = NULL;
-    for(int i=0 ; i < MAX_FRAME_ID; i++)
+    for (int i = 0 ; i < MAX_FRAME_ID; i++)
       auxframes_ptr[i] = NULL;
 
-    Dictionary *dic = new Dictionary();
     wxString dicpath = config.getDicPath();
-    int res = dic->load(dicpath.mb_str().data());
-    if (res != 0)
+    try
+    {
+        Dictionary *dic = new Dictionary(dicpath.mb_str().data());
+        m_dic = dic;
+    }
+    catch (std::exception &e)
     {
         wxCommandEvent event;
         OnMenuConfGameDic(event);
     }
-    else
-    {
-        m_dic = dic;
         m_game = GameFactory::Instance()->createTraining(*m_dic);
         if (m_game)
         {
             m_game->start();
         }
-    }
 
     wxBoxSizer *listsizer = new wxBoxSizer(wxVERTICAL);
     rack = new wxTextCtrl(this, Rack_ID, wxU(""), wxPoint(-1, -1), wxSize(-1, 
-1), wxTE_PROCESS_ENTER);
-    listsizer->Add(rack    , 0 , wxEXPAND | wxALL, 1);
+    listsizer->Add(rack, 0, wxEXPAND | wxALL, 1);
     rack->SetToolTip(_("Tirage"));
 #ifdef ENABLE_RESLIST_IN_MAIN
     reslist = new GfxResult(this,(MainFrame*)this,m_game);
@@ -248,10 +248,7 @@
         m_game = NULL;
     }
 
-    if (m_dic)
-    {
         delete m_dic;
-    }
 }
 
 // ******************************
@@ -393,7 +390,6 @@
 void
 MainFrame::OnMenuGameOpen(wxCommandEvent&)
 {
-    wxString txt;
     wxFileDialog dialog(this, _("Ouvrir une partie"), wxT(""), wxT(""), 
wxT("*"), wxOPEN);
     if (m_dic == NULL)
     {
@@ -416,6 +412,7 @@
 
     if ((fin = fopen(dialog.GetPath().mb_str(), "rb")) == NULL)
     {
+        wxString txt;
         txt << _("Impossible d'ouvrir") << dialog.GetPath();
         wxMessageDialog msg(this, txt, _("Ouverture d'une partie"));
         msg.ShowModal();
@@ -552,7 +549,6 @@
                      wxICON_INFORMATION | wxOK);
         return;
     }
-    wxString txt;
     wxFileDialog dialog(this, _("Imprimer dans un fichier PostScript"), 
wxT(""), wxT(""), wxT("*.ps"), wxSAVE|wxOVERWRITE_PROMPT);
     if (dialog.ShowModal() == wxID_OK)
     {
@@ -600,47 +596,21 @@
 void
 MainFrame::OnMenuConfGameDic(wxCommandEvent& WXUNUSED(event))
 {
-    wxString txt, msg, dicpath;
     wxFileDialog dialog(this, _("Choisir un dictionnaire"), wxT(""), 
wxT("*.dawg"), wxT("*.dawg"), wxOPEN);
     if (dialog.ShowModal() == wxID_OK)
     {
         wxString dicpath = dialog.GetPath();
-        Dictionary *dic = new Dictionary();
-        int res = dic->load(dicpath.mb_str().data());
-        if (res == 0)
-        {
-            if (m_dic)
+        try
             {
+            Dictionary *dic = new Dictionary(dicpath.mb_str().data());
                 delete m_dic;
-            }
-
             m_dic = dic;
             config.setDicPath(dialog.GetPath(), 
::wxFileNameFromPath(dialog.GetPath()));
         }
-        else
-        {
-            switch (res)
+        catch (std::exception &e)
             {
-                case 0: /* cas normal */ break;
-// XXX:                case 1: msg << _("chargement: problème d'ouverture de 
") << dicpath << _("\n"); break;
-                case 1: msg << _("chargement: probleme d'ouverture de ") << 
dicpath << _("\n"); break;
-// XXX:                case 2: msg << _("chargement: mauvais en-tête de 
dictionnaire\n"); break;
-                case 2: msg << _("chargement: mauvais en-tete de 
dictionnaire\n"); break;
-// XXX:                case 3: msg << _("chargement: problème 3 d'allocation 
mémoire\n"); break;
-                case 3: msg << _("chargement: probleme 3 d'allocation 
memoire\n"); break;
-// XXX:                case 4: msg << _("chargement: problème 4 d'allocation 
mémoire\n"); break;
-                case 4: msg << _("chargement: probleme 4 d'allocation 
memoire\n"); break;
-// XXX:                case 5: msg << _("chargement: problème de lecture des 
arcs du dictionnaire\n"); break;
-                case 5: msg << _("chargement: probleme de lecture des arcs du 
dictionnaire\n"); break;
-// XXX:                default: msg << _("chargement: problème 
non-répertorié\n"); break;
-                default: msg << _("chargement: probleme non-repertorie\n"); 
break;
-            }
-            wxMessageDialog dlg(NULL, msg, wxT(APPNAME));
+            wxMessageDialog dlg(NULL, wxU(e.what()), wxT(APPNAME));
             dlg.ShowModal();
-            if (dic)
-            {
-                delete dic;
-            }
         }
     }
     UpdateStatusBar();
@@ -849,12 +819,9 @@
 
     for (int i = 0 ; i < MAX_FRAME_ID; i++)
     {
-        if (auxframes_ptr[i] != NULL)
-        {
             debug("   delete frame %d\n",i);
             delete auxframes_ptr[i];
         }
-    }
 
     auxframes_ptr[ ID_Frame_Verif  ] = new VerifFrame (this, m_game->getDic());
     debug("0 : Verif\n");
@@ -1078,9 +1045,5 @@
 /****************************************************************/
 /****************************************************************/
 
-/// Local Variables:
-/// mode: c++
-/// mode: hs-minor
-/// c-basic-offset: 4
-/// indent-tabs-mode: nil
-/// End:
+/// Local Variables: / mode: c++ / mode: hs-minor / c-basic-offset: 4 /
+//indent-tabs-mode: nil / End:

Index: dic/dic_exception.cpp
===================================================================
RCS file: dic/dic_exception.cpp
diff -N dic/dic_exception.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/dic_exception.cpp       21 Nov 2007 16:25:44 -0000      1.1.2.1
@@ -0,0 +1,35 @@
+/* Eliot                                                                     */
+/* Copyright (C) 2007  Olivier Teuliere                                      */
+/*                                                                           */
+/* This file is part of Eliot.                                               */
+/*                                                                           */
+/* Eliot is free software; you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* Eliot is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+
+#include "dic_exception.h"
+
+using namespace std;
+
+
+DicException::DicException(const string &iMessage)
+    : m_message(iMessage)
+{
+}
+
+
+const char *DicException::what() const throw()
+{
+    return m_message.c_str();
+}
+

Index: dic/dic_exception.h
===================================================================
RCS file: dic/dic_exception.h
diff -N dic/dic_exception.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ dic/dic_exception.h 21 Nov 2007 16:25:44 -0000      1.1.2.1
@@ -0,0 +1,43 @@
+/* Eliot                                                                     */
+/* Copyright (C) 2007  Olivier Teuliere                                      */
+/*                                                                           */
+/* This file is part of Eliot.                                               */
+/*                                                                           */
+/* Eliot is free software; you can redistribute it and/or modify             */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* Eliot is distributed in the hope that it will be useful,                  */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
*/
+
+#ifndef _DIC_EXCEPTION_H_
+#define _DIC_EXCEPTION_H_
+
+#include <exception>
+#include <string>
+
+
+/**
+ * Exception class for the dictionary.
+ * It simply inherits from the standard exception and overrides
+ * its what() method.
+ */
+class DicException: public std::exception
+{
+    public:
+        DicException(const std::string &iMessage);
+        ~DicException() throw() {}
+        virtual const char *what() const throw();
+
+    private:
+        std::string m_message;
+};
+
+#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]