summaryrefslogtreecommitdiff
path: root/src/mgr/versificationmgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mgr/versificationmgr.cpp')
-rw-r--r--src/mgr/versificationmgr.cpp191
1 files changed, 180 insertions, 11 deletions
diff --git a/src/mgr/versificationmgr.cpp b/src/mgr/versificationmgr.cpp
index 7972488..027889f 100644
--- a/src/mgr/versificationmgr.cpp
+++ b/src/mgr/versificationmgr.cpp
@@ -3,7 +3,7 @@
* versificationmgr.cpp - implementation of class VersificationMgr used
* for managing versification systems
*
- * $Id: versificationmgr.cpp 2980 2013-09-14 21:51:47Z scribe $
+ * $Id: versificationmgr.cpp 3515 2017-11-01 11:38:09Z scribe $
*
* Copyright 2008-2013 CrossWire Bible Society (http://www.crosswire.org)
* CrossWire Bible Society
@@ -45,6 +45,9 @@
#include <canon_catholic2.h> // Catholic2 v11n system (16 chapter Esther)
#include <canon_lxx.h> // General LXX v11n system (includes GNT, as used in Orthodox Bibles)
#include <canon_orthodox.h> // Orthodox v11n system as used in Orthodox Bibles
+#include <canon_segond.h> // French v11n system as used by Segond Bibles and its derivatives
+#include <canon_calvin.h> // French v11n system
+#include <canon_darbyfr.h> // French v11n system based on John Darby's French translation
using std::vector;
using std::map;
@@ -62,17 +65,20 @@ VersificationMgr *VersificationMgr::getSystemVersificationMgr() {
systemVersificationMgr->registerVersificationSystem("Leningrad", otbooks_leningrad, ntbooks_null, vm_leningrad);
systemVersificationMgr->registerVersificationSystem("MT", otbooks_mt, ntbooks_null, vm_mt);
systemVersificationMgr->registerVersificationSystem("KJVA", otbooks_kjva, ntbooks, vm_kjva);
- systemVersificationMgr->registerVersificationSystem("NRSV", otbooks, ntbooks, vm_nrsv);
+ systemVersificationMgr->registerVersificationSystem("NRSV", otbooks, ntbooks, vm_nrsv, mappings_nrsv);
systemVersificationMgr->registerVersificationSystem("NRSVA", otbooks_nrsva, ntbooks, vm_nrsva);
- systemVersificationMgr->registerVersificationSystem("Synodal", otbooks_synodal, ntbooks_synodal, vm_synodal);
+ systemVersificationMgr->registerVersificationSystem("Synodal", otbooks_synodal, ntbooks_synodal, vm_synodal, mappings_synodal);
systemVersificationMgr->registerVersificationSystem("SynodalProt", otbooks_synodalProt, ntbooks_synodal, vm_synodalProt);
- systemVersificationMgr->registerVersificationSystem("Vulg", otbooks_vulg, ntbooks_vulg, vm_vulg);
+ systemVersificationMgr->registerVersificationSystem("Vulg", otbooks_vulg, ntbooks_vulg, vm_vulg, mappings_vulg);
systemVersificationMgr->registerVersificationSystem("German", otbooks_german, ntbooks, vm_german);
systemVersificationMgr->registerVersificationSystem("Luther", otbooks_luther, ntbooks_luther, vm_luther);
systemVersificationMgr->registerVersificationSystem("Catholic", otbooks_catholic, ntbooks, vm_catholic);
systemVersificationMgr->registerVersificationSystem("Catholic2", otbooks_catholic2, ntbooks, vm_catholic2);
systemVersificationMgr->registerVersificationSystem("LXX", otbooks_lxx, ntbooks, vm_lxx);
systemVersificationMgr->registerVersificationSystem("Orthodox", otbooks_orthodox, ntbooks, vm_orthodox);
+ systemVersificationMgr->registerVersificationSystem("Calvin", otbooks, ntbooks, vm_calvin, mappings_calvin);
+ systemVersificationMgr->registerVersificationSystem("DarbyFr", otbooks, ntbooks, vm_darbyfr, mappings_darbyfr);
+ systemVersificationMgr->registerVersificationSystem("Segond", otbooks, ntbooks, vm_segond, mappings_segond);
}
return systemVersificationMgr;
}
@@ -83,6 +89,19 @@ public:
/** Array[chapmax] of maximum verses in chapters */
vector<Book> books;
map<SWBuf, int> osisLookup;
+ /** General mapping rule is that first verse of every chapter corresponds first
+ verse of another chapter in default intermediate canon(kjva), so mapping data
+ contains expections. Intermediate canon could not contain corresponding data.
+
+ pointers on uchar[7]: 1 value - book id 1-based, ot+nt, 2-4 map to, 5-7 map
+ from (chap,verse from, verse to if greater then "verse from")
+
+ TODO what if book name in one v11n differs from cannon
+ special section in mapping for book transformation
+ */
+ typedef vector<const unsigned char*> mapping;
+ vector<mapping> mappings;
+ vector<const char*> mappingsExtraBooks;
Private() {
}
@@ -115,7 +134,8 @@ public:
}
VersificationMgr::Book::Private &operator =(const VersificationMgr::Book::Private &other) {
verseMax.clear();
- verseMax = other.verseMax;
+ int s = (int)other.verseMax.size();
+ if (s) verseMax = other.verseMax;
offsetPrecomputed = other.offsetPrecomputed;
return *this;
}
@@ -179,7 +199,7 @@ int VersificationMgr::System::getBookNumberByOSISName(const char *bookName) cons
}
-void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, int *chMax) {
+void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, int *chMax, const unsigned char *mappings) {
int chap = 0;
int book = 0;
long offset = 0; // module heading
@@ -188,7 +208,7 @@ void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, i
p->books.push_back(Book(ot->name, ot->osis, ot->prefAbbrev, ot->chapmax));
offset++; // book heading
Book &b = p->books[p->books.size()-1];
- p->osisLookup[b.getOSISName()] = p->books.size();
+ p->osisLookup[b.getOSISName()] = (int)p->books.size();
for (int i = 0; i < ot->chapmax; i++) {
b.p->verseMax.push_back(chMax[chap]);
offset++; // chapter heading
@@ -206,7 +226,7 @@ void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, i
p->books.push_back(Book(nt->name, nt->osis, nt->prefAbbrev, nt->chapmax));
offset++; // book heading
Book &b = p->books[p->books.size()-1];
- p->osisLookup[b.getOSISName()] = p->books.size();
+ p->osisLookup[b.getOSISName()] = (int)p->books.size();
for (int i = 0; i < nt->chapmax; i++) {
b.p->verseMax.push_back(chMax[chap]);
offset++; // chapter heading
@@ -219,6 +239,23 @@ void VersificationMgr::System::loadFromSBook(const sbook *ot, const sbook *nt, i
BMAX[1] = book;
// TODO: build offset speed array
+
+ // parse mappings
+ if (mappings != NULL) {
+ const unsigned char *m=mappings;
+ for (; *m != 0; m += strlen((const char*)m)+1) {
+ p->mappingsExtraBooks.push_back((const char*)m);
+ }
+ p->mappings.resize(p->books.size()+p->mappingsExtraBooks.size());
+
+ for (++m; *m != 0; m += 7) {
+ p->mappings[m[0]-1].push_back(m);
+ if (*m > p->books.size()) {
+ p->mappings[m[7]-1].push_back(m);
+ m += 1;
+ }
+ }
+ }
}
@@ -255,7 +292,7 @@ int VersificationMgr::Book::getVerseMax(int chapter) const {
int VersificationMgr::System::getBookCount() const {
- return (p ? p->books.size() : 0);
+ return (int)(p ? p->books.size() : 0);
}
@@ -372,10 +409,10 @@ const VersificationMgr::System *VersificationMgr::getVersificationSystem(const c
}
-void VersificationMgr::registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax) {
+void VersificationMgr::registerVersificationSystem(const char *name, const sbook *ot, const sbook *nt, int *chMax, const unsigned char *mappings) {
p->systems[name] = name;
System &s = p->systems[name];
- s.loadFromSBook(ot, nt, chMax);
+ s.loadFromSBook(ot, nt, chMax, mappings);
}
@@ -391,6 +428,138 @@ const StringList VersificationMgr::getVersificationSystems() const {
return retVal;
}
+void VersificationMgr::System::translateVerse(const System *dstSys, const char **book, int *chapter, int *verse, int *verse_end) const {
+ SWLog::getSystemLog()->logDebug("translate verse from %s to %s: %s.%i.%i-%i\n",getName(), dstSys->getName(), *book, *chapter, *verse, *verse_end);
+
+ if (!strcmp(getName(),"KJVA") || !strcmp(getName(),"KJV")) {
+ if (!strcmp(dstSys->getName(),"KJVA") || !strcmp(dstSys->getName(),"KJV"))
+ return;
+ // reversed mapping
+ SWLog::getSystemLog()->logDebug("Perform reversed mapping.\n");
+ int b = dstSys->getBookNumberByOSISName(*book)-1;
+
+ SWLog::getSystemLog()->logDebug("\tgetBookNumberByOSISName %i %s.\n", b, *book);
+
+ if (b < 0) {
+ SWLog::getSystemLog()->logDebug("\tmappingsExtraBooks.size() %i.\n", dstSys->p->mappingsExtraBooks.size());
+ for (int i=0; i<(int)dstSys->p->mappingsExtraBooks.size(); ++i) {
+ SWLog::getSystemLog()->logDebug("\t%s %s.\n", *book, dstSys->p->mappingsExtraBooks[i]);
+ if (!strcmp(*book, dstSys->p->mappingsExtraBooks[i])) {
+ b = (int)p->books.size()+i-2;
+ break;
+ }
+ }
+ }
+
+ SWLog::getSystemLog()->logDebug("\tb %i.\n", b);
+
+ if (b >= (int)dstSys->p->mappings.size() || b < 0) {
+ SWLog::getSystemLog()->logDebug("no modification");
+ return;
+ }
+
+ const unsigned char *a = NULL;
+
+ // reversed mapping should use forward search for item
+ for (unsigned int i=0; i<dstSys->p->mappings[b].size(); ++i) {
+ const unsigned char *m = dstSys->p->mappings[b][i];
+ if (m[4] == *chapter && m[5] <= *verse) {
+ SWLog::getSystemLog()->logDebug("found mapping %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]);
+ if (m[5] == *verse || (m[6] >= *verse && m[5] <= *verse)) {
+ // inside of any mapping range
+ *chapter = m[1];
+ *verse = m[2];
+ *verse_end = m[3];
+ if (*m >= dstSys->p->books.size()) {
+ SWLog::getSystemLog()->logWarning("map to extra books, possible bug source\n");
+ *book = dstSys->getBook(m[7]-1)->getOSISName();
+ }
+ return;
+ }
+ // destination mapping can have duplicate items, use the last (by using <=)
+ if (a == NULL || (a[5]>a[6]?a[5]:a[6]) <= (m[5]>m[6]?m[5]:m[6]))
+ a = m;
+ }
+ }
+ if (a != NULL) {
+ SWLog::getSystemLog()->logDebug("set appropriate: %i %i %i %i %i %i\n",a[1],a[2],a[3],a[4],a[5],a[6]);
+ (*chapter) = a[1];
+ // shift verse
+ const int d = (a[3]>a[2]?a[3]:a[2])-(a[6]>a[5]?a[6]:a[5]);
+ if (*verse < *verse_end)
+ *verse_end += d;
+ else
+ *verse_end = (*verse) + d;
+ *verse += d;
+ if (*a > dstSys->p->books.size()) {
+ SWLog::getSystemLog()->logDebug("appropriate: %i %i %i %i %i %i %i %i\n",a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);
+ SWLog::getSystemLog()->logDebug("book: %s\n", dstSys->getBook(a[7]-1)->getOSISName());
+ *book = dstSys->getBook(a[7]-1)->getOSISName();
+ }
+ return;
+ }
+ SWLog::getSystemLog()->logDebug("There is no mapping.\n");
+ }
+ else if (strcmp(dstSys->getName(),"KJVA") && strcmp(dstSys->getName(),"KJV")) {
+ const System *kjva = getSystemVersificationMgr()->getVersificationSystem("KJVA");
+ const int src_verse = *verse;
+
+ translateVerse(kjva, book, chapter, verse, verse_end);
+
+ int interm_verse = *verse, interm_range = *verse_end, interm_chapter = *chapter;
+ const char *interm_book = *book;
+
+ kjva->translateVerse(dstSys, book, chapter, verse, verse_end);
+
+ // contraction->expansion fix
+ if (verse < verse_end && !(interm_verse < interm_range)) {
+ kjva->translateVerse(this, &interm_book, &interm_chapter, &interm_verse, &interm_range);
+ if (interm_verse < interm_range) {
+ *verse += src_verse - interm_verse;
+ if (*verse > *verse_end)
+ *verse = *verse_end;
+ else
+ *verse_end = *verse;
+ }
+ }
+ }
+ else {
+ SWLog::getSystemLog()->logDebug("Perform forward mapping.\n");
+ const int b = getBookNumberByOSISName(*book)-1;
+ if (b >= (int)p->mappings.size())
+ return;
+ // forward mapping should use reversed search for item
+ for (int i = (int)p->mappings[b].size()-1; i>=0; --i) {
+ const unsigned char *m = p->mappings[b][i];
+ if (m[1] < *chapter) {
+ SWLog::getSystemLog()->logWarning("There is no mapping for this chapter.\n");
+ return;
+ }
+ if (m[1] == *chapter && m[2] <= *verse) {
+ SWLog::getSystemLog()->logDebug("found mapping %i %i %i %i %i %i\n",m[1],m[2],m[3],m[4],m[5],m[6]);
+ if (m[2] == *verse || (m[3] >= *verse && m[2] <= *verse)) {
+ *chapter = m[4];
+ *verse = m[5];
+ *verse_end = m[6];
+ }
+ else {
+ *chapter = m[4];
+ // shift verse
+ const int d = (m[6]>m[5]?m[6]:m[5])-(m[3]>m[2]?m[3]:m[2]);
+ if (*verse < *verse_end)
+ *verse_end += d;
+ else
+ *verse_end = (*verse) + d;
+ *verse += d;
+ }
+ if (*m > p->books.size())
+ *book = p->mappingsExtraBooks[m[0]-p->books.size()-1];
+ return;
+ }
+ }
+ SWLog::getSystemLog()->logDebug("No mapping.\n");
+ }
+}
SWORD_NAMESPACE_END