diff options
Diffstat (limited to 'src/keys/versekey.cpp')
-rw-r--r-- | src/keys/versekey.cpp | 772 |
1 files changed, 418 insertions, 354 deletions
diff --git a/src/keys/versekey.cpp b/src/keys/versekey.cpp index 9b75e97..6ce0858 100644 --- a/src/keys/versekey.cpp +++ b/src/keys/versekey.cpp @@ -1,8 +1,11 @@ /****************************************************************************** - * VerseKey.cpp - code for class 'VerseKey'- a standard Biblical verse key * + * versekey.cpp - code for class 'VerseKey'- a standard Biblical + * verse key * - * Copyright 2009 CrossWire Bible Society (http://www.crosswire.org) + * $Id: versekey.cpp 2893 2013-07-16 03:07:02Z scribe $ + * + * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org) * CrossWire Bible Society * P. O. Box 2528 * Tempe, AZ 85280-2528 @@ -32,7 +35,7 @@ #include <versekey.h> #include <swlocale.h> #include <roman.h> -#include <versemgr.h> +#include <versificationmgr.h> SWORD_NAMESPACE_START @@ -55,7 +58,7 @@ void VerseKey::init(const char *v11n) { instance++; autonorm = 1; // default auto normalization to true - headings = 0; // default display headings option is false + intros = false; // default display intros option is false upperBound = 0; lowerBound = 0; boundSet = false; @@ -120,15 +123,19 @@ VerseKey::VerseKey(VerseKey const &k) : SWKey(k) void VerseKey::setFromOther(const VerseKey &ikey) { if (refSys == ikey.refSys) { - testament = ikey.Testament(); - book = ikey.Book(); - chapter = ikey.Chapter(); - verse = ikey.Verse(); + testament = ikey.getTestament(); + book = ikey.getBook(); + chapter = ikey.getChapter(); + verse = ikey.getVerse(); suffix = ikey.getSuffix(); } + // TODO: versification mapping // Here is where we will do v11n system conversions in the future - // when we have a conversion mechanism (Ben Morgan has started - // thinking about this) + // when we have a conversion mechanism + // Ben Morgan has started thinking about this + // Konstantin Maslyuk <kalemas@mail.ru> has submitted a patch) + // Asked Konstantin to try his patch out with his favorite + // SWORD frontend and report back how it goes. Need to follow up else { // For now, this is the best we can do setText(ikey.getText()); @@ -154,12 +161,12 @@ void VerseKey::positionFrom(const SWKey &ikey) { } // should we always perform bounds checks? Tried but seems to cause infinite recursion - if (_compare(UpperBound()) > 0) { - setFromOther(UpperBound()); + if (_compare(getUpperBound()) > 0) { + setFromOther(getUpperBound()); error = KEYERR_OUTOFBOUNDS; } - if (_compare(LowerBound()) < 0) { - setFromOther(LowerBound()); + if (_compare(getLowerBound()) < 0) { + setFromOther(getLowerBound()); error = KEYERR_OUTOFBOUNDS; } } @@ -171,17 +178,17 @@ void VerseKey::positionFrom(const SWKey &ikey) { void VerseKey::copyFrom(const VerseKey &ikey) { autonorm = ikey.autonorm; - headings = ikey.headings; - testament = ikey.Testament(); - book = ikey.Book(); - chapter = ikey.Chapter(); - verse = ikey.Verse(); + intros = ikey.intros; + testament = ikey.getTestament(); + book = ikey.getBook(); + chapter = ikey.getChapter(); + verse = ikey.getVerse(); suffix = ikey.getSuffix(); setLocale(ikey.getLocale()); setVersificationSystem(ikey.getVersificationSystem()); if (ikey.isBoundSet()) { - LowerBound(ikey.LowerBound()); - UpperBound(ikey.UpperBound()); + setLowerBound(ikey.getLowerBound()); + setUpperBound(ikey.getUpperBound()); } } @@ -213,15 +220,15 @@ void VerseKey::copyFrom(const SWKey &ikey) { VerseKey::VerseKey(const char *min, const char *max, const char *v11n) : SWKey() { init(v11n); - ListKey tmpListKey = ParseVerseList(min); - if (tmpListKey.Count()) { - VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement(0)); - LowerBound(*newElement); + ListKey tmpListKey = parseVerseList(min); + if (tmpListKey.getCount()) { + VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.getElement(0)); + setLowerBound(*newElement); } - tmpListKey = ParseVerseList(max, min, true); - if (tmpListKey.Count()) { - VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement(0)); - UpperBound((newElement->isBoundSet())?newElement->UpperBound():*newElement); + tmpListKey = parseVerseList(max, min, true); + if (tmpListKey.getCount()) { + VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.getElement(0)); + setUpperBound((newElement->isBoundSet())?newElement->getUpperBound():*newElement); } setPosition(TOP); } @@ -248,9 +255,9 @@ VerseKey::~VerseKey() { void VerseKey::setVersificationSystem(const char *name) { - const VerseMgr::System *newRefSys = VerseMgr::getSystemVerseMgr()->getVersificationSystem(name); + const VersificationMgr::System *newRefSys = VersificationMgr::getSystemVersificationMgr()->getVersificationSystem(name); // TODO: cheese, but what should we do if requested v11n system isn't found? - if (!newRefSys) newRefSys = VerseMgr::getSystemVerseMgr()->getVersificationSystem("KJV"); + if (!newRefSys) newRefSys = VersificationMgr::getSystemVersificationMgr()->getVersificationSystem("KJV"); if (refSys != newRefSys) { refSys = newRefSys; BMAX[0] = refSys->getBMAX()[0]; @@ -259,7 +266,7 @@ void VerseKey::setVersificationSystem(const char *name) { // TODO: adjust bounds for versificaion system ??? // TODO: when we have mapping done, rethink this //necessary as our bounds might not mean anything in the new v11n system - ClearBounds(); + clearBounds(); } } @@ -285,14 +292,15 @@ char VerseKey::parse(bool checkAutoNormalize) int error = 0; if (keytext) { - ListKey tmpListKey = ParseVerseList(keytext); - if (tmpListKey.Count()) { + // pass our own copy of keytext as keytext memory may be freshed during parse + ListKey tmpListKey = parseVerseList(SWBuf(keytext).c_str()); + if (tmpListKey.getCount()) { this->positionFrom(*tmpListKey.getElement(0)); error = this->error; } else error = 1; } if (checkAutoNormalize) { - Normalize(1); + normalize(true); } freshtext(); @@ -344,7 +352,7 @@ void VerseKey::freshtext() const * RET: book number or < 0 = not valid */ -int VerseKey::getBookAbbrev(const char *iabbr) const +int VerseKey::getBookFromAbbrev(const char *iabbr) const { int diff, abLen, min, max, target, retVal = -1; @@ -424,7 +432,7 @@ int VerseKey::getBookAbbrev(const char *iabbr) const void VerseKey::validateCurrentLocale() const { if (SWLog::getSystemLog()->getLogLevel() >= SWLog::LOG_DEBUG) { //make sure log is wanted, this loop stuff costs a lot of time for (int i = 0; i < refSys->getBookCount(); i++) { - const int bn = getBookAbbrev(getPrivateLocale()->translate(refSys->getBook(i)->getLongName())); + const int bn = getBookFromAbbrev(getPrivateLocale()->translate(refSys->getBook(i)->getLongName())); if (bn != i+1) { char *abbr = 0; stdstr(&abbr, getPrivateLocale()->translate(refSys->getBook(i)->getLongName()), 2); @@ -448,7 +456,7 @@ void VerseKey::validateCurrentLocale() const { /****************************************************************************** - * VerseKey::ParseVerseList - Attempts to parse a buffer into separate + * VerseKey::parseVerseList - Attempts to parse a buffer into separate * verse entries returned in a ListKey * * ENT: buf - buffer to parse; @@ -463,7 +471,7 @@ void VerseKey::validateCurrentLocale() const { * COMMENT: This code works but wreaks. Rewrite to make more maintainable. */ -ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool expandRange, bool useChapterAsVerse) { +ListKey VerseKey::parseVerseList(const char *buf, const char *defaultKey, bool expandRange, bool useChapterAsVerse) { // hold on to our own copy of params, as threads/recursion may change outside values const char *bufStart = buf; @@ -498,17 +506,17 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e VerseKey *curKey = (VerseKey *)this->clone(); VerseKey *lastKey = (VerseKey *)this->clone(); - lastKey->ClearBounds(); - curKey->ClearBounds(); + lastKey->clearBounds(); + curKey->clearBounds(); // some silly checks for corner cases if (!strcmp(buf, "[ Module Heading ]")) { - curKey->Verse(0); - curKey->Chapter(0); - curKey->Book(0); - curKey->Testament(0); - lastKey->LowerBound(*curKey); - lastKey->UpperBound(*curKey); + curKey->setVerse(0); + curKey->setChapter(0); + curKey->setBook(0); + curKey->setTestament(0); + lastKey->setLowerBound(*curKey); + lastKey->setUpperBound(*curKey); internalListKey << *lastKey; delete curKey; delete lastKey; @@ -517,20 +525,20 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if ((!strncmp(buf, "[ Testament ", 12)) && (isdigit(buf[12])) && (!strcmp(buf+13, " Heading ]"))) { - curKey->Verse(0); - curKey->Chapter(0); - curKey->Book(0); - curKey->Testament(buf[12]-48); - lastKey->LowerBound(*curKey); - lastKey->UpperBound(*curKey); + curKey->setVerse(0); + curKey->setChapter(0); + curKey->setBook(0); + curKey->setTestament(buf[12]-48); + lastKey->setLowerBound(*curKey); + lastKey->setUpperBound(*curKey); internalListKey << *lastKey; delete curKey; delete lastKey; return internalListKey; } - curKey->AutoNormalize(AutoNormalize()); - lastKey->AutoNormalize(0); + curKey->setAutoNormalize(isAutoNormalize()); + lastKey->setAutoNormalize(false); if (defaultKey) *lastKey = defaultKey; while (*buf) { @@ -539,8 +547,11 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if (buf[1] != ' ') { // for silly "Mat 1:1: this verse...." number[tonumber] = 0; tonumber = 0; - if (*number) - chap = atoi(number); + if (*number) { + if (chap >= 0) + verse = atoi(number); + else chap = atoi(number); + } *number = 0; comma = 0; break; @@ -558,7 +569,9 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e break; } if (inTerm) { - book[tobook++] = ' '; + if (tobook < 1 || book[tobook-1] != ' ') { + book[tobook++] = ' '; + } break; } @@ -567,7 +580,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e book[tobook] = *buf; book[tobook+1] = *(buf+1); book[tobook+2] = 0; - int bookno = getBookAbbrev(book); + int bookno = getBookFromAbbrev(book); if (bookno > -1) { tobook++; buf++; @@ -588,7 +601,14 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e tobook = 0; bookno = -1; if (*book) { - for (loop = strlen(book) - 1; loop+1; loop--) { + loop = strlen(book) - 1; + + for (; loop+1; loop--) { if (book[loop] == ' ') book[loop] = 0; else break; } + + if (loop > 0 && isdigit(book[loop-1]) && book[loop] >= 'a' && book[loop] <= 'z') { + book[loop--] = 0; + } + for (; loop+1; loop--) { if ((isdigit(book[loop])) || (book[loop] == ' ')) { book[loop] = 0; continue; @@ -618,30 +638,47 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e } } + // check for special inscriptio and subscriptio which are saved as book intro and chap 1 intro (for INTF) + for (loop = strlen(book) - 1; loop+1; loop--) { + if (book[loop] == ' ') { + if (!strnicmp(&book[loop+1], "inscriptio", strlen(&book[loop+1]))) { + book[loop] = 0; + verse = 0; + chap = 0; + } + else if (!strnicmp(&book[loop+1], "subscriptio", strlen(&book[loop+1]))) { + book[loop] = 0; + verse = 0; + chap = 1; + } + break; + } + } + if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev if (verse == -1) { verse = chap; - chap = lastKey->Chapter(); + chap = lastKey->getChapter(); *book = 0; } } if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev strcpy(book, lastKey->getBookName()); } - bookno = getBookAbbrev(book); + bookno = getBookFromAbbrev(book); if ((bookno > -1) && (suffix == 'f') && (book[strlen(book)-1] == 'f')) { suffix = 0; } } if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) { char partial = 0; - curKey->Verse(1); - curKey->Chapter(1); - curKey->Book(1); + curKey->setVerse(1); + curKey->setChapter(1); + curKey->setBook(1); if (bookno < 0) { - curKey->Testament(lastKey->Testament()); - curKey->Book(lastKey->Book()); + curKey->setTestament(lastKey->getTestament()); + curKey->setBook(lastKey->getBook()); } else { int t = 1; @@ -649,15 +686,15 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e t++; bookno -= BMAX[0]; } - curKey->Testament(t); - curKey->Book(bookno); + curKey->setTestament(t); + curKey->setBook(bookno); } if (((comma)||((verse < 0)&&(bookno < 0)))&&(!lastPartial)) { // if (comma) { - curKey->Chapter(lastKey->Chapter()); - curKey->Verse(chap); // chap because this is the first number captured + curKey->setChapter(lastKey->getChapter()); + curKey->setVerse(chap); // chap because this is the first number captured if (suffix) { curKey->setSuffix(suffix); } @@ -670,21 +707,21 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if (chap >= 0) { - curKey->Chapter(chap); + curKey->setChapter(chap); } else { partial++; - curKey->Chapter(1); + curKey->setChapter(1); } if (verse >= 0) { - curKey->Verse(verse); + curKey->setVerse(verse); if (suffix) { curKey->setSuffix(suffix); } } else { partial++; - curKey->Verse(1); + curKey->setVerse(1); } } @@ -692,23 +729,25 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e for (q = 0; ((buf[q]) && (buf[q] == ' ')); q++); if ((buf[q] == '-') && (expandRange)) { // if this is a dash save lowerBound and wait for upper buf+=q; - lastKey->LowerBound(*curKey); + lastKey->setLowerBound(*curKey); lastKey->setPosition(TOP); tmpListKey << *lastKey; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + ((VerseKey *)tmpListKey.getElement())->setAutoNormalize(isAutoNormalize()); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } else { if (!dash) { // if last separator was not a dash just add if (expandRange && partial) { - lastKey->LowerBound(*curKey); + lastKey->setLowerBound(*curKey); if (partial > 1) curKey->setPosition(MAXCHAPTER); if (partial > 0) *curKey = MAXVERSE; - lastKey->UpperBound(*curKey); + lastKey->setUpperBound(*curKey); *lastKey = TOP; tmpListKey << *lastKey; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + ((VerseKey *)tmpListKey.getElement())->setAutoNormalize(isAutoNormalize()); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } else { bool f = false; @@ -716,25 +755,27 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e curKey->setSuffix(0); f = true; } - lastKey->LowerBound(*curKey); + lastKey->setLowerBound(*curKey); if (f && doubleF) (*curKey) = MAXVERSE; else if (f) (*curKey)++; - lastKey->UpperBound(*curKey); + lastKey->setUpperBound(*curKey); *lastKey = TOP; tmpListKey << *lastKey; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + ((VerseKey *)tmpListKey.getElement())->setAutoNormalize(isAutoNormalize()); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } } else if (expandRange) { - VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement()); + VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.getElement()); if (newElement) { if (partial > 1) *curKey = MAXCHAPTER; if (partial > 0) *curKey = MAXVERSE; - newElement->UpperBound(*curKey); + newElement->setUpperBound(*curKey); + *lastKey = *curKey; *newElement = TOP; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } } } @@ -761,19 +802,27 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e case '}': break; case '.': - if (buf > orig) // ignore (break) if preceeding char is not a digit + if (buf > orig) { // ignore (break) if preceeding char is not a digit for (notAllDigits = tobook; notAllDigits; notAllDigits--) { if ((!isdigit(book[notAllDigits-1])) && (!strchr(" .", book[notAllDigits-1]))) break; } - if (!notAllDigits) + if (!notAllDigits && !isdigit(buf[1])) break; + } number[tonumber] = 0; tonumber = 0; - if (*number) - chap = atoi(number); - *number = 0; + if (*number) { + if (chap >= 0) + verse = atoi(number); + else chap = atoi(number); + *number = 0; + } + else if (chap == -1 && (tobook < 1 || book[tobook-1] != ' ')) { + book[tobook++] = ' '; + } + break; default: @@ -789,9 +838,15 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e break; default: // suffixes (and oddly 'f'-- ff.) - if (((*buf >= 'a' && *buf <= 'z') && (chap >=0)) || *buf == 'f') { + if ((*buf >= 'a' && *buf <= 'z' && (chap >=0 || bookno > -1 || lastKey->isBoundSet())) + || *buf == 'f') { // if suffix is already an 'f', then we need to mark if we're doubleF. doubleF = (*buf == 'f' && suffix == 'f'); + if (suffix && !doubleF) { + // we've already had a suffix one, so this is another letter, thus any number is not a number, e.g., '2jn'. We're on 'n' + number[tonumber] = 0; + tonumber = 0; + } suffix = *buf; } else { @@ -811,13 +866,25 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if (*number) { if (chap >= 0) verse = atoi(number); - else chap = atoi(number); + else chap = atoi(number); } *number = 0; book[tobook] = 0; tobook = 0; if (*book) { - for (loop = strlen(book) - 1; loop+1; loop--) { + loop = strlen(book) - 1; + + // strip trailing spaces + for (; loop+1; loop--) { if (book[loop] == ' ') book[loop] = 0; else break; } + + // check if endsWith([0-9][a-z]) and kill the last letter, e.g., ...12a, and chop off the 'a' + // why? What's this for? wouldn't this mess up 2t? + if (loop > 0 && isdigit(book[loop-1]) && book[loop] >= 'a' && book[loop] <= 'z') { + book[loop--] = 0; + } + + // skip trailing spaces and numbers + for (; loop+1; loop--) { if ((isdigit(book[loop])) || (book[loop] == ' ')) { book[loop] = 0; continue; @@ -833,6 +900,7 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e break; } + // check for roman numeral chapter for (loop = strlen(book) - 1; loop+1; loop--) { if (book[loop] == ' ') { // "PS C" is ok, but "II C" is not ok @@ -846,11 +914,29 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e break; } } + // check for special inscriptio and subscriptio which are saved as book intro and chap 1 intro (for INTF) + for (loop = strlen(book) - 1; loop+1; loop--) { + if (book[loop] == ' ') { + if (!strnicmp(&book[loop+1], "inscriptio", strlen(&book[loop+1]))) { + book[loop] = 0; + verse = 0; + chap = 0; + suffix = 0; + } + else if (!strnicmp(&book[loop+1], "subscriptio", strlen(&book[loop+1]))) { + book[loop] = 0; + verse = 0; + chap = 1; + suffix = 0; + } + break; + } + } if ((!stricmp(book, "V")) || (!stricmp(book, "VER"))) { // Verse abbrev. if (verse == -1) { verse = chap; - chap = lastKey->Chapter(); + chap = lastKey->getChapter(); *book = 0; } } @@ -858,20 +944,20 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if ((!stricmp(book, "ch")) || (!stricmp(book, "chap"))) { // Verse abbrev strcpy(book, lastKey->getBookName()); } - bookno = getBookAbbrev(book); + bookno = getBookFromAbbrev(book); if ((bookno > -1) && (suffix == 'f') && (book[strlen(book)-1] == 'f')) { suffix = 0; } } if (((bookno > -1) || (!*book)) && ((*book) || (chap >= 0) || (verse >= 0))) { char partial = 0; - curKey->Verse(1); - curKey->Chapter(1); - curKey->Book(1); + curKey->setVerse(1); + curKey->setChapter(1); + curKey->setBook(1); if (bookno < 0) { - curKey->Testament(lastKey->Testament()); - curKey->Book(lastKey->Book()); + curKey->setTestament(lastKey->getTestament()); + curKey->setBook(lastKey->getBook()); } else { int t = 1; @@ -879,13 +965,13 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e t++; bookno -= BMAX[0]; } - curKey->Testament(t); - curKey->Book(bookno); + curKey->setTestament(t); + curKey->setBook(bookno); } if (((comma)||((verse < 0)&&(bookno < 0)))&&(!lastPartial)) { - curKey->Chapter(lastKey->Chapter()); - curKey->Verse(chap); // chap because this is the first number captured + curKey->setChapter(lastKey->getChapter()); + curKey->setVerse(chap); // chap because this is the first number captured if (suffix) { curKey->setSuffix(suffix); } @@ -898,42 +984,42 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e if (chap >= 0) { - curKey->Chapter(chap); + curKey->setChapter(chap); } else { partial++; - curKey->Chapter(1); + curKey->setChapter(1); } if (verse >= 0) { - curKey->Verse(verse); + curKey->setVerse(verse); if (suffix) { curKey->setSuffix(suffix); } } else { partial++; - curKey->Verse(1); + curKey->setVerse(1); } } if ((*buf == '-') && (expandRange)) { // if this is a dash save lowerBound and wait for upper - lastKey->LowerBound(*curKey); + lastKey->setLowerBound(*curKey); *lastKey = TOP; tmpListKey << *lastKey; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } else { if (!dash) { // if last separator was not a dash just add if (expandRange && partial) { - lastKey->LowerBound(*curKey); + lastKey->setLowerBound(*curKey); if (partial > 1) *curKey = MAXCHAPTER; if (partial > 0) *curKey = MAXVERSE; - lastKey->UpperBound(*curKey); + lastKey->setUpperBound(*curKey); *lastKey = TOP; tmpListKey << *lastKey; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } else { bool f = false; @@ -941,25 +1027,25 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e curKey->setSuffix(0); f = true; } - lastKey->LowerBound(*curKey); + lastKey->setLowerBound(*curKey); if (f && doubleF) (*curKey) = MAXVERSE; else if (f) (*curKey)++; - lastKey->UpperBound(*curKey); + lastKey->setUpperBound(*curKey); *lastKey = TOP; tmpListKey << *lastKey; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } } else if (expandRange) { - VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.GetElement()); + VerseKey *newElement = SWDYNAMIC_CAST(VerseKey, tmpListKey.getElement()); if (newElement) { if (partial > 1) *curKey = MAXCHAPTER; if (partial > 0) *curKey = MAXVERSE; - newElement->UpperBound(*curKey); + newElement->setUpperBound(*curKey); *newElement = TOP; - tmpListKey.GetElement()->userData = (void *)(bufStart+(buf-iBuf.c_str())); + tmpListKey.getElement()->userData = (__u64)(bufStart+(buf-iBuf.c_str())); } } } @@ -977,14 +1063,14 @@ ListKey VerseKey::ParseVerseList(const char *buf, const char *defaultKey, bool e /****************************************************************************** - * VerseKey::LowerBound - sets / gets the lower boundary for this key + * VerseKey::setLowerBound - sets / gets the lower boundary for this key */ -VerseKey &VerseKey::LowerBound(const VerseKey &lb) +void VerseKey::setLowerBound(const VerseKey &lb) { initBounds(); - lowerBound = lb.Index(); + lowerBound = lb.getIndex(); lowerBoundComponents.test = lb.getTestament(); lowerBoundComponents.book = lb.getBook(); lowerBoundComponents.chap = lb.getChapter(); @@ -996,39 +1082,35 @@ VerseKey &VerseKey::LowerBound(const VerseKey &lb) // and set values without restrictions, as expected if (upperBound < lowerBound) upperBound = lowerBound; boundSet = true; - - return LowerBound(); } /****************************************************************************** - * VerseKey::UpperBound - sets / gets the upper boundary for this key + * VerseKey::setUpperBound - sets / gets the upper boundary for this key */ -VerseKey &VerseKey::UpperBound(const VerseKey &ub) +void VerseKey::setUpperBound(const VerseKey &ub) { initBounds(); - upperBound = ub.Index(); + upperBound = ub.getIndex(); upperBoundComponents.test = ub.getTestament(); upperBoundComponents.book = ub.getBook(); upperBoundComponents.chap = ub.getChapter(); upperBoundComponents.verse = ub.getVerse(); upperBoundComponents.suffix = ub.getSuffix(); - // see LowerBound comment, above + // see setLowerBound comment, above if (upperBound < lowerBound) upperBound = lowerBound; boundSet = true; - - return UpperBound(); } /****************************************************************************** - * VerseKey::LowerBound - sets / gets the lower boundary for this key + * VerseKey::getLowerBound - gets the lower boundary for this key */ -VerseKey &VerseKey::LowerBound() const +VerseKey &VerseKey::getLowerBound() const { initBounds(); if (!isAutoNormalize()) { @@ -1038,17 +1120,20 @@ VerseKey &VerseKey::LowerBound() const tmpClone->setVerse (lowerBoundComponents.verse); tmpClone->setSuffix (lowerBoundComponents.suffix); } - else tmpClone->Index(lowerBound); + else { + tmpClone->setIndex(lowerBound); + tmpClone->setSuffix (lowerBoundComponents.suffix); + } return (*tmpClone); } /****************************************************************************** - * VerseKey::UpperBound - sets / gets the upper boundary for this key + * VerseKey::getUpperBound - sets / gets the upper boundary for this key */ -VerseKey &VerseKey::UpperBound() const +VerseKey &VerseKey::getUpperBound() const { initBounds(); if (!isAutoNormalize()) { @@ -1058,17 +1143,20 @@ VerseKey &VerseKey::UpperBound() const tmpClone->setVerse (upperBoundComponents.verse); tmpClone->setSuffix (upperBoundComponents.suffix); } - else tmpClone->Index(upperBound); + else { + tmpClone->setIndex(upperBound); + tmpClone->setSuffix (upperBoundComponents.suffix); + } return (*tmpClone); } /****************************************************************************** - * VerseKey::ClearBounds - clears bounds for this VerseKey + * VerseKey::clearBounds - clears bounds for this VerseKey */ -void VerseKey::ClearBounds() +void VerseKey::clearBounds() { delete tmpClone; tmpClone = 0; @@ -1080,13 +1168,13 @@ void VerseKey::initBounds() const { if (!tmpClone) { tmpClone = (VerseKey *)this->clone(); - tmpClone->AutoNormalize(0); - tmpClone->Headings(1); - tmpClone->Testament((BMAX[1])?2:1); - tmpClone->Book(BMAX[(BMAX[1])?1:0]); - tmpClone->Chapter(tmpClone->getChapterMax()); - tmpClone->Verse(tmpClone->getVerseMax()); - upperBound = tmpClone->Index(); + tmpClone->setAutoNormalize(false); + tmpClone->setIntros(true); + tmpClone->setTestament((BMAX[1])?2:1); + tmpClone->setBook(BMAX[(BMAX[1])?1:0]); + tmpClone->setChapter(tmpClone->getChapterMax()); + tmpClone->setVerse(tmpClone->getVerseMax()); + upperBound = tmpClone->getIndex(); upperBoundComponents.test = tmpClone->getTestament(); upperBoundComponents.book = tmpClone->getBook(); upperBoundComponents.chap = tmpClone->getChapter(); @@ -1159,46 +1247,51 @@ const char *VerseKey::getBookAbbrev() const { void VerseKey::setPosition(SW_POSITION p) { switch (p) { case POS_TOP: { - const VerseKey *lb = &LowerBound(); - testament = (lb->Testament() || headings) ? lb->Testament() : 1; - book = (lb->Book() || headings) ? lb->Book() : 1; - chapter = (lb->Chapter() || headings) ? lb->Chapter() : 1; - verse = (lb->Verse() || headings) ? lb->Verse() : 1; + const VerseKey *lb = &getLowerBound(); + testament = (lb->getTestament() || intros) ? lb->getTestament() : 1; + book = (lb->getBook() || intros) ? lb->getBook() : 1; + chapter = (lb->getChapter() || intros) ? lb->getChapter() : 1; + verse = (lb->getVerse() || intros) ? lb->getVerse() : 1; suffix = lb->getSuffix(); break; } case POS_BOTTOM: { - const VerseKey *ub = &UpperBound(); - testament = (ub->Testament() || headings) ? ub->Testament() : 1; - book = (ub->Book() || headings) ? ub->Book() : 1; - chapter = (ub->Chapter() || headings) ? ub->Chapter() : 1; - verse = (ub->Verse() || headings) ? ub->Verse() : 1; + const VerseKey *ub = &getUpperBound(); + testament = (ub->getTestament() || intros) ? ub->getTestament() : 1; + book = (ub->getBook() || intros) ? ub->getBook() : 1; + chapter = (ub->getChapter() || intros) ? ub->getChapter() : 1; + verse = (ub->getVerse() || intros) ? ub->getVerse() : 1; suffix = ub->getSuffix(); break; } case POS_MAXVERSE: - Normalize(); + suffix = 0; + verse = 1; + normalize(); verse = getVerseMax(); suffix = 0; break; case POS_MAXCHAPTER: - verse = 1; suffix = 0; - Normalize(); + verse = 1; + chapter = 1; + normalize(); chapter = getChapterMax(); break; } - Normalize(1); - Error(); // clear error from normalize + normalize(true); + popError(); // clear error from normalize } int VerseKey::getChapterMax() const { - const VerseMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1); + if (book < 1) return 0; + const VersificationMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1); return (b) ? b->getChapterMax() : -1; } int VerseKey::getVerseMax() const { - const VerseMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1); + if (book < 1) return 0; + const VersificationMgr::Book *b = refSys->getBook(((testament>1)?BMAX[0]:0)+book-1); return (b) ? b->getVerseMax(chapter) : -1; } @@ -1212,11 +1305,17 @@ int VerseKey::getVerseMax() const { */ void VerseKey::increment(int step) { + // if we're not autonormalizing and we're already not normalized + if (!autonorm && chapter > 0 && verse > getVerseMax()) { + verse += step; + checkBounds(); + return; + } char ierror = 0; - Index(Index() + step); - while ((!verse) && (!headings) && (!ierror)) { - Index(Index() + 1); - ierror = Error(); + setIndex(getIndex() + step); + while ((!verse) && (!intros) && (!ierror)) { + setIndex(getIndex() + 1); + ierror = popError(); } error = (ierror) ? ierror : error; @@ -1232,14 +1331,19 @@ void VerseKey::increment(int step) { */ void VerseKey::decrement(int step) { + // if we're not autonormalizing and we're already not normalized + if (!autonorm && chapter > 0 && verse > getVerseMax()) { + verse -= step; + checkBounds(); + return; + } char ierror = 0; - - Index(Index() - step); - while ((!verse) && (!headings) && (!ierror)) { - Index(Index() - 1); - ierror = Error(); + setIndex(getIndex() - step); + while ((!verse) && (!intros) && (!ierror)) { + setIndex(getIndex() - 1); + ierror = popError(); } - if ((ierror) && (!headings)) + if ((ierror) && (!intros)) (*this)++; error = (ierror) ? ierror : error; @@ -1247,109 +1351,90 @@ void VerseKey::decrement(int step) { /****************************************************************************** - * VerseKey::Normalize - checks limits and normalizes if necessary (e.g. + * VerseKey::normalize - checks limits and normalizes if necessary (e.g. * Matthew 29:47 = Mark 2:2). If last verse is * exceeded, key is set to last Book CH:VS * RET: *this */ -void VerseKey::Normalize(char autocheck) +void VerseKey::normalize(bool autocheck) { - if (((!autocheck) || (autonorm)) // only normalize if we were explicitely called or if autonorm is turned on - && - ((!headings) || ((verse) && (chapter)))) { // this is cheeze and temporary until deciding what actions should be taken; so headings should only be turned on when positioning with Index() or incrementors + if ((!autocheck || autonorm) // only normalize if we were explicitely called or if autonorm is turned on + ) { error = 0; - while ((testament < 3) && (testament > 0)) { - - if (book > BMAX[testament-1]) { - book -= BMAX[testament-1]; - testament++; - continue; - } - - if (book < 1) { - if (--testament > 0) { - book += BMAX[testament-1]; - } - continue; - } - - if (chapter > getChapterMax()) { - chapter -= getChapterMax(); - book++; - continue; - } - - if (chapter < 1) { - if (--book > 0) { - chapter += getChapterMax(); - verse = getVerseMax(); + while ((testament < 3) && (testament > 0)) { + + + if (book > BMAX[testament-1]) { + book -= (BMAX[testament-1] + (intros?1:0)); + testament++; + continue; } - else { - if (testament > 1) { - chapter += refSys->getBook(BMAX[0]-1)->getChapterMax(); - verse = refSys->getBook(BMAX[0]-1)->getVerseMax(chapter); + if (book < (intros?0:1)) { + if (--testament > 0) { + book += (BMAX[testament-1] + (intros?1:0)); } + continue; + } + + + if (chapter > getChapterMax()) { + chapter -= (getChapterMax() + (intros?1:0)); + book++; + continue; + } + if (chapter < (intros?0:1)) { + --book; + chapter += (getChapterMax() + (intros?1:0)); + continue; } - continue; - } - if (verse > getVerseMax()) { // -1 because e.g chapter 1 of Matthew is books[1][0].versemax[0] - verse -= getVerseMax(); + + if (chapter > 0 && verse > getVerseMax()) { + verse -= (getVerseMax() + (intros?1:0)); chapter++; - continue; - } - - if (verse < 1) { - if (--chapter > 0) { - verse += getVerseMax(); - } - else { - if (book > 1) { - const VerseMgr::Book *prevBook = refSys->getBook(((testament>1)?BMAX[0]:0)+book-2); - verse += prevBook->getVerseMax(prevBook->getChapterMax()); - } - else { - if (testament > 1) { - const VerseMgr::Book *lastOTBook = refSys->getBook(BMAX[0]-1); - verse += lastOTBook->getVerseMax(lastOTBook->getChapterMax()); - } - } - } - continue; - } - - break; // If we've made it this far (all failure checks continue) we're ok - } - - if (testament > (BMAX[1]?2:1)) { - testament = BMAX[1]?2:1; - book = BMAX[testament-1]; - chapter = getChapterMax(); - verse = getVerseMax(); - error = KEYERR_OUTOFBOUNDS; - } - - if (testament < 1) { - error = ((!headings) || (testament < 0) || (book < 0)) ? KEYERR_OUTOFBOUNDS : 0; - testament = ((headings) ? 0 : 1); - book = ((headings) ? 0 : 1); - chapter = ((headings) ? 0 : 1); - verse = ((headings) ? 0 : 1); - } - - // should we always perform bounds checks? Tried but seems to cause infinite recursion - if (_compare(UpperBound()) > 0) { - positionFrom(UpperBound()); - error = KEYERR_OUTOFBOUNDS; - } - if (_compare(LowerBound()) < 0) { - positionFrom(LowerBound()); - error = KEYERR_OUTOFBOUNDS; - } - } + continue; + } + if (verse < (intros?0:1)) { + if (--chapter < (intros?0:1)) { + --book; + chapter += (getChapterMax() + (intros?1:0)); + } + verse += (getVerseMax() + (intros?1:0)); + continue; + } + + break; // If we've made it this far (all failure checks continue) we're ok + } + + if (testament > (BMAX[1]?2:1)) { + testament = BMAX[1]?2:1; + book = BMAX[testament-1]; + chapter = getChapterMax(); + verse = getVerseMax(); + error = KEYERR_OUTOFBOUNDS; + } + + if (testament < 1) { + error = ((!intros) || (testament < 0) || (book < 0)) ? KEYERR_OUTOFBOUNDS : 0; + testament = ((intros) ? 0 : 1); + book = ((intros) ? 0 : 1); + chapter = ((intros) ? 0 : 1); + verse = ((intros) ? 0 : 1); + } + + // should we always perform bounds checks? Tried but seems to cause infinite recursion + if (_compare(getUpperBound()) > 0) { + positionFrom(getUpperBound()); + error = KEYERR_OUTOFBOUNDS; + } + if (_compare(getLowerBound()) < 0) { + positionFrom(getLowerBound()); + error = KEYERR_OUTOFBOUNDS; + } + } } @@ -1378,7 +1463,7 @@ char VerseKey::getBook() const /****************************************************************************** - * VerseKey::Chapter - Gets chapter + * VerseKey::getChapter - Gets chapter * * RET: value of chapter */ @@ -1390,7 +1475,7 @@ int VerseKey::getChapter() const /****************************************************************************** - * VerseKey::Verse - Gets verse + * VerseKey::getVerse - Gets verse * * RET: value of verse */ @@ -1407,16 +1492,16 @@ int VerseKey::getVerse() const * ENT: itestament - value which to set testament * [MAXPOS(char)] - only get * - * RET: if unchanged -> value of testament - * if changed -> previous value of testament */ void VerseKey::setTestament(char itestament) { - if (itestament != MAXPOS(char)) { - testament = itestament; - Normalize(1); - } + suffix = 0; + verse = (intros) ? 0 : 1; + chapter = (intros) ? 0 : 1; + book = (intros) ? 0 : 1; + testament = itestament; + normalize(true); } @@ -1428,10 +1513,11 @@ void VerseKey::setTestament(char itestament) void VerseKey::setBook(char ibook) { - verse = 1; - chapter = 1; + suffix = 0; + verse = (intros) ? 0 : 1; + chapter = (intros) ? 0 : 1; book = ibook; - Normalize(1); + normalize(true); } @@ -1444,7 +1530,7 @@ void VerseKey::setBook(char ibook) void VerseKey::setBookName(const char *bname) { - int bnum = getBookAbbrev(bname); + int bnum = getBookFromAbbrev(bname); if (bnum > -1) { if (bnum > BMAX[0]) { bnum -= BMAX[0]; @@ -1465,11 +1551,10 @@ void VerseKey::setBookName(const char *bname) void VerseKey::setChapter(int ichapter) { - verse = 1; + suffix = 0; + verse = (intros) ? 0 : 1; chapter = ichapter; - Normalize(1); - // TODO: easiest fix, but should be in Normalize - verse = 1; + normalize(true); } @@ -1485,9 +1570,9 @@ void VerseKey::setChapter(int ichapter) void VerseKey::setVerse(int iverse) { - setSuffix(0); - verse = iverse; - Normalize(1); + suffix = 0; + verse = iverse; + normalize(true); } @@ -1500,7 +1585,7 @@ void VerseKey::setSuffix(char suf) { } /****************************************************************************** - * VerseKey::AutoNormalize - Sets/gets flag that tells VerseKey to auto- + * VerseKey::isAutoNormalize - gets flag that tells VerseKey to auto- * matically normalize itself when modified */ @@ -1512,67 +1597,37 @@ bool VerseKey::isAutoNormalize() const void VerseKey::setAutoNormalize(bool iautonorm) { autonorm = iautonorm?1:0; - Normalize(1); + normalize(true); } /****************************************************************************** - * VerseKey::Headings - Sets/gets flag that tells VerseKey to include - * chap/book/testmnt/module headings + * VerseKey::setIntros - Sets flag that tells VerseKey to include + * chap/book/testmnt/module introductions * - * ENT: iheadings - value which to set headings - * [MAXPOS(char)] - only get + * ENT: val - value which to set intros * - * RET: if unchanged -> value of headings - * if changed -> previous value of headings */ -char VerseKey::Headings(char iheadings) +void VerseKey::setIntros(bool val) { - char retval = headings; - - if (iheadings != MAXPOS(char)) { - headings = iheadings; - Normalize(1); - } - return retval; + intros = val; + normalize(true); } - -/****************************************************************************** - * VerseKey::findindex - binary search to find the index closest, but less - * than the given value. - * - * ENT: array - long * to array to search - * size - number of elements in the array - * value - value to find - * - * RET: the index into the array that is less than but closest to value - */ - -int VerseKey::findindex(long *array, int size, long value) +bool VerseKey::isIntros() const { - int lbound, ubound, tval; - - lbound = 0; - ubound = size - 1; - while ((ubound - lbound) > 1) { - tval = lbound + (ubound-lbound)/2; - if (array[tval] <= value) - lbound = tval; - else ubound = tval; - } - return (array[ubound] <= value) ? ubound : lbound; + return intros; } /****************************************************************************** - * VerseKey::Index - Gets index based upon current verse + * VerseKey::getIndex - Gets index based upon current verse * * RET: offset */ -long VerseKey::Index() const +long VerseKey::getIndex() const { long offset; @@ -1590,28 +1645,33 @@ long VerseKey::Index() const /****************************************************************************** - * VerseKey::TestamentIndex - Gets index based upon current verse + * VerseKey::getTestamentIndex - Gets index based upon current verse * * RET: offset */ -long VerseKey::TestamentIndex() const +long VerseKey::getTestamentIndex() const { - long offset = Index(); + long offset = getIndex(); return (testament > 1) ? offset - refSys->getNTStartOffset() : offset; } /****************************************************************************** - * VerseKey::Index - Sets index based upon current verse + * VerseKey::setIndex - Sets index based upon current verse * * ENT: iindex - value to set index to * - * RET: offset */ -long VerseKey::Index(long iindex) +void VerseKey::setIndex(long iindex) { + // assert we're sane + if (iindex < 0) { + error = KEYERR_OUTOFBOUNDS; + return; + } + int b; error = refSys->getVerseFromOffset(iindex, &b, &chapter, &verse); book = (unsigned char)b; @@ -1624,19 +1684,23 @@ long VerseKey::Index(long iindex) if (book < 0) { testament = 0; book = 0; } if (chapter < 0) { book = 0; chapter = 0; } - long i = Index(); + checkBounds(); +} + +void VerseKey::checkBounds() { + + long i = getIndex(); initBounds(); if (i > upperBound) { - i = Index(upperBound); + setIndex(upperBound); + i = getIndex(); error = KEYERR_OUTOFBOUNDS; } if (i < lowerBound) { - i = Index(lowerBound); + setIndex(lowerBound); error = KEYERR_OUTOFBOUNDS; } - - return i; } @@ -1677,14 +1741,14 @@ int VerseKey::_compare(const VerseKey &ivkey) unsigned long keyval1 = 0; unsigned long keyval2 = 0; - keyval1 += Testament() * 1000000000; - keyval2 += ivkey.Testament() * 1000000000; - keyval1 += Book() * 10000000; - keyval2 += ivkey.Book() * 10000000; - keyval1 += Chapter() * 10000; - keyval2 += ivkey.Chapter() * 10000; - keyval1 += Verse() * 50; - keyval2 += ivkey.Verse() * 50; + keyval1 += getTestament() * 1000000000; + keyval2 += ivkey.getTestament() * 1000000000; + keyval1 += getBook() * 10000000; + keyval2 += ivkey.getBook() * 10000000; + keyval1 += getChapter() * 10000; + keyval2 += ivkey.getChapter() * 10000; + keyval1 += getVerse() * 50; + keyval2 += ivkey.getVerse() * 50; keyval1 += (int)getSuffix(); keyval2 += (int)ivkey.getSuffix(); keyval1 = (keyval1 != keyval2) ? ((keyval1 > keyval2) ? 1 : -1) : 0; // -1 | 0 | 1 @@ -1699,11 +1763,11 @@ const char *VerseKey::getOSISRef() const { if (loop > 4) loop = 0; - if (Verse()) - sprintf(buf[loop], "%s.%d.%d", getOSISBookName(), (int)Chapter(), (int)Verse()); - else if (Chapter()) - sprintf(buf[loop], "%s.%d", getOSISBookName(), (int)Chapter()); - else if (Book()) + if (getVerse()) + sprintf(buf[loop], "%s.%d.%d", getOSISBookName(), getChapter(), getVerse()); + else if (getChapter()) + sprintf(buf[loop], "%s.%d", getOSISBookName(), getChapter()); + else if (getBook()) sprintf(buf[loop], "%s", getOSISBookName()); else buf[loop][0] = 0; return buf[loop++]; @@ -1716,9 +1780,9 @@ const char *VerseKey::getOSISRef() const { const char *VerseKey::getRangeText() const { if (isBoundSet() && lowerBound != upperBound) { - SWBuf buf = (const char *)LowerBound(); + SWBuf buf = (const char *)getLowerBound(); buf += "-"; - buf += (const char *)UpperBound(); + buf += (const char *)getUpperBound(); stdstr(&rangeText, buf.c_str()); } else stdstr(&rangeText, getText()); @@ -1732,9 +1796,9 @@ const char *VerseKey::getRangeText() const { const char *VerseKey::getOSISRefRangeText() const { if (isBoundSet() && (lowerBound != upperBound)) { - SWBuf buf = LowerBound().getOSISRef(); + SWBuf buf = getLowerBound().getOSISRef(); buf += "-"; - buf += UpperBound().getOSISRef(); + buf += getUpperBound().getOSISRef(); stdstr(&rangeText, buf.c_str()); } else stdstr(&rangeText, getOSISRef()); @@ -1750,10 +1814,10 @@ const char *VerseKey::convertToOSIS(const char *inRef, const SWKey *lastKnownKey outRef = ""; VerseKey defLanguage; - ListKey verses = defLanguage.ParseVerseList(inRef, (*lastKnownKey), true); + ListKey verses = defLanguage.parseVerseList(inRef, (*lastKnownKey), true); const char *startFrag = inRef; - for (int i = 0; i < verses.Count(); i++) { - SWKey *element = verses.GetElement(i); + for (int i = 0; i < verses.getCount(); i++) { + SWKey *element = verses.getElement(i); // VerseKey *element = SWDYNAMIC_CAST(VerseKey, verses.GetElement(i)); SWBuf buf; // TODO: This code really needs to not use fixed size arrays |