diff options
author | John Fultz <jfultz@wolfram.com> | 2015-08-22 01:39:47 -0500 |
---|---|---|
committer | John Fultz <jfultz@wolfram.com> | 2015-08-22 01:39:47 -0500 |
commit | 5e5d414c57d5c7dd8a3037dda1555db5fb7eb486 (patch) | |
tree | a442ebdafbb882f9fb3a620b8741e079a12e75a3 | |
parent | 6613f3fd45b4ecf6821ee7bb07c95f86f43b0db2 (diff) |
Add versioning of DAWGs.
If we're going to start writing these into user directories,
then we'd better start versioning them so we don't end
up generating bugs in the future.
LexiconParameters::loadDawg() implements a tiny
class factory which allows backward compatibility
of DAWGs. I'll soon be adding a "version 1" in
addition to the legacy "version 0". For now, version 1
is just dummied in.
-rw-r--r-- | generator.cpp | 11 | ||||
-rw-r--r-- | lexiconparameters.cpp | 81 | ||||
-rw-r--r-- | lexiconparameters.h | 64 |
3 files changed, 98 insertions, 58 deletions
diff --git a/generator.cpp b/generator.cpp index 2bfc199..f2923b8 100644 --- a/generator.cpp +++ b/generator.cpp @@ -440,16 +440,7 @@ void Generator::makeMove(const Move &move, bool regenerateCrosses) void Generator::readFromDawg(int index, unsigned int &p, Letter &letter, bool &t, bool &lastchild, bool &british, int &playability) const { - index *= 7; - p = (QUACKLE_LEXICON_PARAMETERS->dawgAt(index) << 16) + (QUACKLE_LEXICON_PARAMETERS->dawgAt(index + 1) << 8) + (QUACKLE_LEXICON_PARAMETERS->dawgAt(index + 2)); - letter = QUACKLE_LEXICON_PARAMETERS->dawgAt(index + 3); - - t = (letter & 32) != 0; - lastchild = (letter & 64) != 0; - british = !(letter & 128); - letter = (letter & 31) + QUACKLE_FIRST_LETTER; - - playability = (QUACKLE_LEXICON_PARAMETERS->dawgAt(index + 4) << 16) + (QUACKLE_LEXICON_PARAMETERS->dawgAt(index + 5) << 8) + (QUACKLE_LEXICON_PARAMETERS->dawgAt(index + 6)); + QUACKLE_LEXICON_PARAMETERS->dawgAt(index, p, letter, t, lastchild, british, playability); } bool Generator::checksuffix(int i, const LetterString &suffix) { diff --git a/lexiconparameters.cpp b/lexiconparameters.cpp index b32f632..9826ca3 100644 --- a/lexiconparameters.cpp +++ b/lexiconparameters.cpp @@ -25,6 +25,64 @@ using namespace Quackle; +class V0DawgInterpreter : public DawgInterpreter +{ + + virtual void loadDawg(ifstream &file, unsigned char *dawg) + { + int i = 0; + while (!file.eof()) + { + file.read((char*)(dawg) + i, 7); + i += 7; + } + } + + virtual void dawgAt(const unsigned char *dawg, int index, unsigned int &p, Letter &letter, bool &t, bool &lastchild, bool &british, int &playability) const + { + index *= 7; + p = (dawg[index] << 16) + (dawg[index + 1] << 8) + (dawg[index + 2]); + letter = dawg[index + 3]; + + t = (letter & 32) != 0; + lastchild = (letter & 64) != 0; + british = !(letter & 128); + letter = (letter & 31) + QUACKLE_FIRST_LETTER; + + playability = (dawg[index + 4] << 16) + (dawg[index + 5] << 8) + (dawg[index + 6]); + } + virtual int versionNumber() const { return 0; } +}; + +class V1DawgInterpreter : public DawgInterpreter +{ + + virtual void loadDawg(ifstream &file, unsigned char *dawg) + { + int i = 0; + while (!file.eof()) + { + file.read((char*)(dawg) + i, 7); + i += 7; + } + } + + virtual void dawgAt(const unsigned char *dawg, int index, unsigned int &p, Letter &letter, bool &t, bool &lastchild, bool &british, int &playability) const + { + index *= 7; + p = (dawg[index] << 16) + (dawg[index + 1] << 8) + (dawg[index + 2]); + letter = dawg[index + 3]; + + t = (letter & 32) != 0; + lastchild = (letter & 64) != 0; + british = !(letter & 128); + letter = (letter & 31) + QUACKLE_FIRST_LETTER; + + playability = (dawg[index + 4] << 16) + (dawg[index + 5] << 8) + (dawg[index + 6]); + } + virtual int versionNumber() const { return 1; } +}; + LexiconParameters::LexiconParameters() : m_dawg(0), m_gaddag(0) { @@ -45,6 +103,7 @@ void LexiconParameters::unloadDawg() { delete[] m_dawg; m_dawg = 0; + delete m_interpreter; } void LexiconParameters::unloadGaddag() @@ -64,14 +123,24 @@ void LexiconParameters::loadDawg(const string &filename) return; } - m_dawg = new unsigned char[7000000]; - - int i = 0; - while (!file.eof()) + char versionByte = file.get(); + file.unget(); + switch(versionByte) { - file.read((char*)(m_dawg) + i, 7); - i += 7; + case 0: + m_interpreter = new V0DawgInterpreter(); + break; + case 1: + m_interpreter = new V1DawgInterpreter(); + break; + default: + UVcout << "couldn't open dawg " << filename.c_str() << endl; + return; } + + m_dawg = new unsigned char[7000000]; + + m_interpreter->loadDawg(file, m_dawg); } void LexiconParameters::loadGaddag(const string &filename) diff --git a/lexiconparameters.h b/lexiconparameters.h index 612c103..4c77cd1 100644 --- a/lexiconparameters.h +++ b/lexiconparameters.h @@ -25,6 +25,16 @@ namespace Quackle { +class DawgInterpreter +{ +public: + virtual void loadDawg(ifstream &file, unsigned char *dawg) = 0; + virtual void dawgAt(const unsigned char *dawg, int index, unsigned int &p, Letter &letter, bool &t, bool &lastchild, bool &british, int &playability) const = 0; + virtual int versionNumber() const = 0; + virtual ~DawgInterpreter() {}; +}; + + class LexiconParameters { public: @@ -34,68 +44,38 @@ public: void unloadAll(); // true if we have a dawg or a gaddag - bool hasSomething() const; + bool hasSomething() const { return hasDawg() || hasGaddag(); }; // loadDawg unloads the dawg if filename can't be opened void loadDawg(const string &filename); void unloadDawg(); - bool hasDawg() const; + bool hasDawg() const { return m_dawg != NULL; }; + int dawgVersion() const { return m_interpreter->versionNumber(); }; // loadGaddag unloads the gaddag if filename can't be opened void loadGaddag(const string &filename); void unloadGaddag(); - bool hasGaddag() const; + bool hasGaddag() const { return m_gaddag != NULL; }; // finds a file in the lexica data directory static string findDictionaryFile(const string &lexicon); // a convenience field; this is unused by libquackle - string lexiconName() const; - void setLexiconName(const string &name); + string lexiconName() const { return m_lexiconName; }; + void setLexiconName(const string &name) { m_lexiconName = name; }; - unsigned char dawgAt(int index) const; - const GaddagNode *gaddagRoot() const; + void dawgAt(int index, unsigned int &p, Letter &letter, bool &t, bool &lastchild, bool &british, int &playability) const + { + m_interpreter->dawgAt(m_dawg, index, p, letter, t, lastchild, british, playability); + } + const GaddagNode *gaddagRoot() const { return (GaddagNode *) &m_gaddag[0]; }; protected: unsigned char *m_dawg; unsigned char *m_gaddag; string m_lexiconName; + DawgInterpreter *m_interpreter; }; -inline bool LexiconParameters::hasSomething() const -{ - return hasDawg() || hasGaddag(); -} - -inline bool LexiconParameters::hasDawg() const -{ - return m_dawg != NULL; -} - -inline bool LexiconParameters::hasGaddag() const -{ - return m_gaddag != NULL; -} - -inline unsigned char LexiconParameters::dawgAt(int index) const -{ - return m_dawg[index]; -} - -inline const GaddagNode *LexiconParameters::gaddagRoot() const -{ - return (GaddagNode *) &m_gaddag[0]; -} - -inline string LexiconParameters::lexiconName() const -{ - return m_lexiconName; -} - -inline void LexiconParameters::setLexiconName(const string &name) -{ - m_lexiconName = name; -} - } #endif |