summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Fultz <jfultz@wolfram.com>2015-08-22 01:39:47 -0500
committerJohn Fultz <jfultz@wolfram.com>2015-08-22 01:39:47 -0500
commit5e5d414c57d5c7dd8a3037dda1555db5fb7eb486 (patch)
treea442ebdafbb882f9fb3a620b8741e079a12e75a3
parent6613f3fd45b4ecf6821ee7bb07c95f86f43b0db2 (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.cpp11
-rw-r--r--lexiconparameters.cpp81
-rw-r--r--lexiconparameters.h64
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