1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-04 02:09:35 +02:00

fb2 plugin code is included into master branch

This commit is contained in:
Nikolay Pultsin 2012-03-23 23:35:09 +00:00
parent 29e018ee65
commit ae40ca59a6
12 changed files with 1248 additions and 0 deletions

View file

@ -0,0 +1,326 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <cstdlib>
#include <cstring>
#include <ZLInputStream.h>
#include <ZLStringUtil.h>
#include <ZLBase64EncodedImage.h>
#include <ZLTextParagraph.h>
#include "FB2BookReader.h"
#include "../../library/Book.h"
#include "../../bookmodel/BookModel.h"
FB2BookReader::FB2BookReader(BookModel &model) : myModelReader(model) {
myInsideCoverpage = false;
myParagraphsBeforeBodyNumber = (size_t)-1;
myInsidePoem = false;
mySectionDepth = 0;
myBodyCounter = 0;
myReadMainText = false;
myCurrentImage = 0;
myProcessingImage = false;
mySectionStarted = false;
myInsideTitle = false;
}
void FB2BookReader::characterDataHandler(const char *text, size_t len) {
if ((len > 0) && (myProcessingImage || myModelReader.paragraphIsOpen())) {
std::string str(text, len);
if (myProcessingImage) {
myImageBuffer.push_back(str);
} else {
myModelReader.addData(str);
if (myInsideTitle) {
myModelReader.addContentsData(str);
}
}
}
}
void FB2BookReader::startElementHandler(int tag, const char **xmlattributes) {
const char *id = attributeValue(xmlattributes, "id");
if (id != 0) {
if (!myReadMainText) {
myModelReader.setFootnoteTextModel(id);
}
myModelReader.addHyperlinkLabel(id);
}
switch (tag) {
case _P:
if (mySectionStarted) {
mySectionStarted = false;
} else if (myInsideTitle) {
static const std::string SPACE = " ";
myModelReader.addContentsData(SPACE);
}
myModelReader.beginParagraph();
break;
case _V:
myModelReader.pushKind(VERSE);
myModelReader.beginParagraph();
break;
case _SUBTITLE:
myModelReader.pushKind(SUBTITLE);
myModelReader.beginParagraph();
break;
case _TEXT_AUTHOR:
myModelReader.pushKind(AUTHOR);
myModelReader.beginParagraph();
break;
case _DATE:
myModelReader.pushKind(DATEKIND);
myModelReader.beginParagraph();
break;
case _CITE:
myModelReader.pushKind(CITE);
break;
case _SECTION:
if (myReadMainText) {
myModelReader.insertEndOfSectionParagraph();
++mySectionDepth;
myModelReader.beginContentsParagraph();
mySectionStarted = true;
}
break;
case _TITLE:
if (myInsidePoem) {
myModelReader.pushKind(POEM_TITLE);
} else if (mySectionDepth == 0) {
myModelReader.insertEndOfSectionParagraph();
myModelReader.pushKind(TITLE);
} else {
myModelReader.pushKind(SECTION_TITLE);
myModelReader.enterTitle();
myInsideTitle = true;
}
break;
case _POEM:
myInsidePoem = true;
break;
case _STANZA:
myModelReader.pushKind(STANZA);
myModelReader.beginParagraph(ZLTextParagraph::BEFORE_SKIP_PARAGRAPH);
myModelReader.endParagraph();
break;
case _EPIGRAPH:
myModelReader.pushKind(EPIGRAPH);
break;
case _ANNOTATION:
if (myBodyCounter == 0) {
myModelReader.setMainTextModel();
}
myModelReader.pushKind(ANNOTATION);
break;
case _COVERPAGE:
if (myBodyCounter == 0) {
myInsideCoverpage = true;
myModelReader.setMainTextModel();
}
break;
case _SUB:
myModelReader.addControl(SUB, true);
break;
case _SUP:
myModelReader.addControl(SUP, true);
break;
case _CODE:
myModelReader.addControl(CODE, true);
break;
case _STRIKETHROUGH:
myModelReader.addControl(STRIKETHROUGH, true);
break;
case _STRONG:
myModelReader.addControl(STRONG, true);
break;
case _EMPHASIS:
myModelReader.addControl(EMPHASIS, true);
break;
case _A:
{
const std::string hrefName = xlinkNamespace() + ":href";
const char *ref = attributeValue(xmlattributes, hrefName.c_str());
if (ref != 0) {
if (ref[0] == '#') {
const char *type = attributeValue(xmlattributes, "type");
static const std::string NOTE = "note";
if ((type != 0) && (NOTE == type)) {
myHyperlinkType = FOOTNOTE;
} else {
myHyperlinkType = INTERNAL_HYPERLINK;
}
++ref;
} else {
myHyperlinkType = EXTERNAL_HYPERLINK;
}
myModelReader.addHyperlinkControl(myHyperlinkType, ref);
} else {
myHyperlinkType = FOOTNOTE;
myModelReader.addControl(myHyperlinkType, true);
}
break;
}
case _IMAGE:
{
const std::string hrefName = xlinkNamespace() + ":href";
const char *ref = attributeValue(xmlattributes, hrefName.c_str());
//const char *vOffset = attributeValue(xmlattributes, "voffset");
//char offset = (vOffset != 0) ? atoi(vOffset) : 0;
if ((ref != 0) && (*ref == '#')) {
++ref;
if ((myCoverImageReference != ref) ||
(myParagraphsBeforeBodyNumber != myModelReader.model().bookTextModel()->paragraphsNumber())) {
myModelReader.addImageReference(ref);
}
if (myInsideCoverpage) {
myCoverImageReference = ref;
}
}
break;
}
case _BINARY:
{
static const std::string STRANGE_MIME_TYPE = "text/xml";
const char *contentType = attributeValue(xmlattributes, "content-type");
if ((contentType != 0) && (id != 0) && (STRANGE_MIME_TYPE != contentType)) {
myCurrentImage = new ZLBase64EncodedImage(contentType);
myCurrentImageId.assign(id);
myProcessingImage = true;
}
break;
}
case _EMPTY_LINE:
myModelReader.beginParagraph(ZLTextParagraph::EMPTY_LINE_PARAGRAPH);
myModelReader.endParagraph();
break;
case _BODY:
++myBodyCounter;
myParagraphsBeforeBodyNumber = myModelReader.model().bookTextModel()->paragraphsNumber();
if ((myBodyCounter == 1) || (attributeValue(xmlattributes, "name") == 0)) {
myModelReader.setMainTextModel();
myReadMainText = true;
}
myModelReader.pushKind(REGULAR);
break;
default:
break;
}
}
void FB2BookReader::endElementHandler(int tag) {
switch (tag) {
case _P:
myModelReader.endParagraph();
break;
case _V:
case _SUBTITLE:
case _TEXT_AUTHOR:
case _DATE:
myModelReader.popKind();
myModelReader.endParagraph();
break;
case _CITE:
myModelReader.popKind();
break;
case _SECTION:
if (myReadMainText) {
myModelReader.endContentsParagraph();
--mySectionDepth;
mySectionStarted = false;
} else {
myModelReader.unsetTextModel();
}
break;
case _TITLE:
myModelReader.exitTitle();
myModelReader.popKind();
myInsideTitle = false;
break;
case _POEM:
myInsidePoem = false;
break;
case _STANZA:
myModelReader.beginParagraph(ZLTextParagraph::AFTER_SKIP_PARAGRAPH);
myModelReader.endParagraph();
myModelReader.popKind();
break;
case _EPIGRAPH:
myModelReader.popKind();
break;
case _ANNOTATION:
myModelReader.popKind();
if (myBodyCounter == 0) {
myModelReader.insertEndOfSectionParagraph();
myModelReader.unsetTextModel();
}
break;
case _COVERPAGE:
if (myBodyCounter == 0) {
myInsideCoverpage = false;
myModelReader.insertEndOfSectionParagraph();
myModelReader.unsetTextModel();
}
break;
case _SUB:
myModelReader.addControl(SUB, false);
break;
case _SUP:
myModelReader.addControl(SUP, false);
break;
case _CODE:
myModelReader.addControl(CODE, false);
break;
case _STRIKETHROUGH:
myModelReader.addControl(STRIKETHROUGH, false);
break;
case _STRONG:
myModelReader.addControl(STRONG, false);
break;
case _EMPHASIS:
myModelReader.addControl(EMPHASIS, false);
break;
case _A:
myModelReader.addControl(myHyperlinkType, false);
break;
case _BINARY:
if (!myImageBuffer.empty() && !myCurrentImageId.empty() && myCurrentImage != 0) {
myCurrentImage->addData(myImageBuffer);
myModelReader.addImage(myCurrentImageId, myCurrentImage);
myImageBuffer.clear();
myCurrentImageId.clear();
myCurrentImage = 0;
}
myProcessingImage = false;
break;
case _BODY:
myModelReader.popKind();
myModelReader.unsetTextModel();
myReadMainText = false;
break;
default:
break;
}
}
bool FB2BookReader::readBook() {
return readDocument(myModelReader.model().book()->file());
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __FB2BOOKREADER_H__
#define __FB2BOOKREADER_H__
#include "FB2Reader.h"
#include "../../bookmodel/BookReader.h"
class BookModel;
class ZLBase64EncodedImage;
class FB2BookReader : public FB2Reader {
public:
FB2BookReader(BookModel &model);
bool readBook();
void startElementHandler(int tag, const char **attributes);
void endElementHandler(int tag);
void characterDataHandler(const char *text, size_t len);
private:
int mySectionDepth;
int myBodyCounter;
bool myReadMainText;
bool myInsideCoverpage;
size_t myParagraphsBeforeBodyNumber;
std::string myCoverImageReference;
bool myInsidePoem;
BookReader myModelReader;
ZLBase64EncodedImage *myCurrentImage;
std::string myCurrentImageId;
bool myProcessingImage;
std::vector<std::string> myImageBuffer;
bool mySectionStarted;
bool myInsideTitle;
FBTextKind myHyperlinkType;
};
#endif /* __FB2BOOKREADER_H__ */

View file

@ -0,0 +1,90 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <ZLFile.h>
#include <ZLBase64EncodedImage.h>
#include "FB2CoverReader.h"
#include "../../library/Book.h"
FB2CoverReader::FB2CoverReader(const ZLFile &file) : myFile(file) {
}
shared_ptr<ZLImage> FB2CoverReader::readCover() {
myReadCoverPage = false;
myImageReference.erase();
readDocument(myFile);
return myImage;
}
void FB2CoverReader::startElementHandler(int tag, const char **attributes) {
switch (tag) {
case _COVERPAGE:
myReadCoverPage = true;
break;
case _IMAGE:
if (myReadCoverPage) {
const std::string hrefName = xlinkNamespace() + ":href";
const char *ref = attributeValue(attributes, hrefName.c_str());
if (ref != 0 && *ref == '#' && *(ref + 1) != '\0') {
myImageReference = ref + 1;
}
}
break;
case _BINARY:
{
const char *id = attributeValue(attributes, "id");
const char *contentType = attributeValue(attributes, "content-type");
if (id != 0 && contentType != 0 && myImageReference == id) {
myImage = new ZLBase64EncodedImage(contentType);
}
}
}
}
void FB2CoverReader::endElementHandler(int tag) {
switch (tag) {
case _COVERPAGE:
myReadCoverPage = false;
break;
case _DESCRIPTION:
if (myImageReference.empty()) {
interrupt();
}
break;
case _BINARY:
if (!myImage.isNull()) {
if (!myImageBuffer.empty()) {
((ZLBase64EncodedImage&)*myImage).addData(myImageBuffer);
myImageBuffer.clear();
} else {
myImage = 0;
}
interrupt();
}
break;
}
}
void FB2CoverReader::characterDataHandler(const char *text, size_t len) {
if (len > 0 && !myImage.isNull()) {
myImageBuffer.push_back(std::string(text, len));
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __FB2COVERREADER_H__
#define __FB2COVERREADER_H__
#include "FB2Reader.h"
class Book;
class ZLfile;
class ZLImage;
class FB2CoverReader : public FB2Reader {
public:
FB2CoverReader(const ZLFile &file);
shared_ptr<ZLImage> readCover();
private:
void startElementHandler(int tag, const char **attributes);
void endElementHandler(int tag);
void characterDataHandler(const char *text, size_t len);
private:
const ZLFile myFile;
bool myReadCoverPage;
std::string myImageReference;
shared_ptr<ZLImage> myImage;
std::vector<std::string> myImageBuffer;
};
#endif /* __FB2COVERREADER_H__ */

View file

@ -0,0 +1,206 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <cstdlib>
#include <ZLInputStream.h>
#include <ZLStringUtil.h>
#include "FB2MetaInfoReader.h"
#include "FB2TagManager.h"
#include "../../library/Book.h"
FB2MetaInfoReader::FB2MetaInfoReader(Book &book) : myBook(book) {
myBook.removeAllAuthors();
myBook.setTitle(std::string());
myBook.setLanguage(std::string());
myBook.removeAllTags();
}
void FB2MetaInfoReader::characterDataHandler(const char *text, size_t len) {
switch (myReadState) {
case READ_TITLE:
myBuffer.append(text, len);
break;
case READ_LANGUAGE:
myBuffer.append(text, len);
break;
case READ_AUTHOR_NAME_0:
myAuthorNames[0].append(text, len);
break;
case READ_AUTHOR_NAME_1:
myAuthorNames[1].append(text, len);
break;
case READ_AUTHOR_NAME_2:
myAuthorNames[2].append(text, len);
break;
case READ_GENRE:
myBuffer.append(text, len);
break;
default:
break;
}
}
void FB2MetaInfoReader::startElementHandler(int tag, const char **attributes) {
switch (tag) {
case _BODY:
myReturnCode = true;
interrupt();
break;
case _TITLE_INFO:
myReadState = READ_SOMETHING;
break;
case _BOOK_TITLE:
if (myReadState == READ_SOMETHING) {
myReadState = READ_TITLE;
}
break;
case _GENRE:
if (myReadState == READ_SOMETHING) {
myReadState = READ_GENRE;
}
break;
case _AUTHOR:
if (myReadState == READ_SOMETHING) {
myReadState = READ_AUTHOR;
}
break;
case _LANG:
if (myReadState == READ_SOMETHING) {
myReadState = READ_LANGUAGE;
}
break;
case _FIRST_NAME:
if (myReadState == READ_AUTHOR) {
myReadState = READ_AUTHOR_NAME_0;
}
break;
case _MIDDLE_NAME:
if (myReadState == READ_AUTHOR) {
myReadState = READ_AUTHOR_NAME_1;
}
break;
case _LAST_NAME:
if (myReadState == READ_AUTHOR) {
myReadState = READ_AUTHOR_NAME_2;
}
break;
case _SEQUENCE:
if (myReadState == READ_SOMETHING) {
const char *name = attributeValue(attributes, "name");
if (name != 0) {
std::string seriesTitle = name;
ZLStringUtil::stripWhiteSpaces(seriesTitle);
const char *number = attributeValue(attributes, "number");
myBook.setSeries(seriesTitle, number != 0 ? atoi(number) : 0);
}
}
break;
default:
break;
}
}
void FB2MetaInfoReader::endElementHandler(int tag) {
switch (tag) {
case _TITLE_INFO:
myReadState = READ_NOTHING;
break;
case _BOOK_TITLE:
if (myReadState == READ_TITLE) {
myBook.setTitle(myBuffer);
myBuffer.erase();
myReadState = READ_SOMETHING;
}
break;
case _GENRE:
if (myReadState == READ_GENRE) {
ZLStringUtil::stripWhiteSpaces(myBuffer);
if (!myBuffer.empty()) {
const std::vector<std::string> &tags =
FB2TagManager::Instance().humanReadableTags(myBuffer);
if (!tags.empty()) {
for (std::vector<std::string>::const_iterator it = tags.begin(); it != tags.end(); ++it) {
myBook.addTag(*it);
}
} else {
myBook.addTag(myBuffer);
}
myBuffer.erase();
}
myReadState = READ_SOMETHING;
}
break;
case _AUTHOR:
if (myReadState == READ_AUTHOR) {
ZLStringUtil::stripWhiteSpaces(myAuthorNames[0]);
ZLStringUtil::stripWhiteSpaces(myAuthorNames[1]);
ZLStringUtil::stripWhiteSpaces(myAuthorNames[2]);
std::string fullName = myAuthorNames[0];
if (!fullName.empty() && !myAuthorNames[1].empty()) {
fullName += ' ';
}
fullName += myAuthorNames[1];
if (!fullName.empty() && !myAuthorNames[2].empty()) {
fullName += ' ';
}
fullName += myAuthorNames[2];
myBook.addAuthor(fullName, myAuthorNames[2]);
myAuthorNames[0].erase();
myAuthorNames[1].erase();
myAuthorNames[2].erase();
myReadState = READ_SOMETHING;
}
break;
case _LANG:
if (myReadState == READ_LANGUAGE) {
myBook.setLanguage(myBuffer);
myBuffer.erase();
myReadState = READ_SOMETHING;
}
break;
case _FIRST_NAME:
if (myReadState == READ_AUTHOR_NAME_0) {
myReadState = READ_AUTHOR;
}
break;
case _MIDDLE_NAME:
if (myReadState == READ_AUTHOR_NAME_1) {
myReadState = READ_AUTHOR;
}
break;
case _LAST_NAME:
if (myReadState == READ_AUTHOR_NAME_2) {
myReadState = READ_AUTHOR;
}
break;
default:
break;
}
}
bool FB2MetaInfoReader::readMetaInfo() {
myReadState = READ_NOTHING;
for (int i = 0; i < 3; ++i) {
myAuthorNames[i].erase();
}
return readDocument(myBook.file());
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __FB2METAINFOREADER_H__
#define __FB2METAINFOREADER_H__
#include <string>
#include "FB2Reader.h"
class Book;
class FB2MetaInfoReader : public FB2Reader {
public:
FB2MetaInfoReader(Book &book);
bool readMetaInfo();
void startElementHandler(int tag, const char **attributes);
void endElementHandler(int tag);
void characterDataHandler(const char *text, size_t len);
private:
Book &myBook;
bool myReturnCode;
enum {
READ_NOTHING,
READ_SOMETHING,
READ_TITLE,
READ_AUTHOR,
READ_AUTHOR_NAME_0,
READ_AUTHOR_NAME_1,
READ_AUTHOR_NAME_2,
READ_LANGUAGE,
READ_GENRE
} myReadState;
std::string myAuthorNames[3];
std::string myBuffer;
};
#endif /* __FB2METAINFOREADER_H__ */

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <ZLFile.h>
#include <ZLImage.h>
#include "FB2Plugin.h"
#include "FB2MetaInfoReader.h"
#include "FB2BookReader.h"
#include "FB2CoverReader.h"
const std::string FB2Plugin::supportedFileType() const {
return "fb2";
}
bool FB2Plugin::readMetaInfo(Book &book) const {
return FB2MetaInfoReader(book).readMetaInfo();
}
bool FB2Plugin::readModel(BookModel &model) const {
return FB2BookReader(model).readBook();
}
shared_ptr<ZLImage> FB2Plugin::coverImage(const ZLFile &file) const {
return FB2CoverReader(file).readCover();
}
bool FB2Plugin::readLanguageAndEncoding(Book &book) const {
return true;
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __FB2PLUGIN_H__
#define __FB2PLUGIN_H__
#include "../FormatPlugin.h"
class FB2Plugin : public FormatPlugin {
public:
FB2Plugin();
~FB2Plugin();
bool providesMetaInfo() const;
const std::string supportedFileType() const;
bool readMetaInfo(Book &book) const;
bool readLanguageAndEncoding(Book &book) const;
bool readModel(BookModel &model) const;
shared_ptr<ZLImage> coverImage(const ZLFile &file) const;
};
inline FB2Plugin::FB2Plugin() {}
inline FB2Plugin::~FB2Plugin() {}
inline bool FB2Plugin::providesMetaInfo() const { return true; }
#endif /* __FB2PLUGIN_H__ */

View file

@ -0,0 +1,101 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <cstring>
#include <ZLibrary.h>
#include <ZLStringUtil.h>
#include <ZLXMLNamespace.h>
#include "FB2Reader.h"
#include "../util/EntityFilesCollector.h"
void FB2Reader::startElementHandler(const char *t, const char **attributes) {
startElementHandler(tag(t), attributes);
}
void FB2Reader::endElementHandler(const char *t) {
endElementHandler(tag(t));
}
static const FB2Reader::Tag TAGS[] = {
{"p", FB2Reader::_P},
{"subtitle", FB2Reader::_SUBTITLE},
{"cite", FB2Reader::_CITE},
{"text-author", FB2Reader::_TEXT_AUTHOR},
{"date", FB2Reader::_DATE},
{"section", FB2Reader::_SECTION},
{"v", FB2Reader::_V},
{"title", FB2Reader::_TITLE},
{"poem", FB2Reader::_POEM},
{"stanza", FB2Reader::_STANZA},
{"epigraph", FB2Reader::_EPIGRAPH},
{"annotation", FB2Reader::_ANNOTATION},
{"sub", FB2Reader::_SUB},
{"sup", FB2Reader::_SUP},
{"code", FB2Reader::_CODE},
{"strikethrough", FB2Reader::_STRIKETHROUGH},
{"strong", FB2Reader::_STRONG},
{"emphasis", FB2Reader::_EMPHASIS},
{"a", FB2Reader::_A},
{"image", FB2Reader::_IMAGE},
{"binary", FB2Reader::_BINARY},
{"description", FB2Reader::_DESCRIPTION},
{"body", FB2Reader::_BODY},
{"empty-line", FB2Reader::_EMPTY_LINE},
{"title-info", FB2Reader::_TITLE_INFO},
{"book-title", FB2Reader::_BOOK_TITLE},
{"author", FB2Reader::_AUTHOR},
{"lang", FB2Reader::_LANG},
{"first-name", FB2Reader::_FIRST_NAME},
{"middle-name", FB2Reader::_MIDDLE_NAME},
{"last-name", FB2Reader::_LAST_NAME},
{"coverpage", FB2Reader::_COVERPAGE},
{"sequence", FB2Reader::_SEQUENCE},
{"genre", FB2Reader::_GENRE},
{0, FB2Reader::_UNKNOWN}
};
int FB2Reader::tag(const char *name) {
for (int i = 0; ; ++i) {
if ((TAGS[i].tagName == 0) || (strcmp(name, TAGS[i].tagName) == 0)) {
return TAGS[i].tagCode;
}
}
}
bool FB2Reader::processNamespaces() const {
return true;
}
void FB2Reader::namespaceListChangedHandler() {
const std::map<std::string,std::string> namespaceMap = namespaces();
for (std::map<std::string,std::string>::const_iterator it = namespaceMap.begin(); it != namespaceMap.end(); ++it) {
if (ZLStringUtil::stringStartsWith(it->second, ZLXMLNamespace::XLink)) {
myXLinkNamespace = it->first;
return;
}
}
myXLinkNamespace.erase();
}
void FB2Reader::collectExternalEntities(std::map<std::string,std::string> &entityMap) {
entityMap["FBReaderVersion"] = ZLibrary::Version();
}

View file

@ -0,0 +1,100 @@
/*
* Copyright (C) 2004-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __FB2READER_H__
#define __FB2READER_H__
#include <ZLXMLReader.h>
class FB2Reader : public ZLXMLReader {
public:
struct Tag {
const char *tagName;
int tagCode;
};
protected:
virtual int tag(const char *name);
virtual void startElementHandler(int tag, const char **attributes) = 0;
virtual void endElementHandler(int tag) = 0;
const std::string &xlinkNamespace() const;
private:
void startElementHandler(const char *tag, const char **attributes);
void endElementHandler(const char *tag);
bool processNamespaces() const;
void namespaceListChangedHandler();
void collectExternalEntities(std::map<std::string,std::string> &entityMap);
public:
enum TagCode {
_P,
_SUBTITLE,
_CITE,
_TEXT_AUTHOR,
_DATE,
_SECTION,
_V,
_TITLE,
_POEM,
_STANZA,
_EPIGRAPH,
_ANNOTATION,
_SUB,
_SUP,
_CODE,
_STRIKETHROUGH,
_STRONG,
_EMPHASIS,
_A,
_IMAGE,
_BINARY,
_DESCRIPTION,
_BODY,
_EMPTY_LINE,
_TITLE_INFO,
_BOOK_TITLE,
_AUTHOR,
_LANG,
_FIRST_NAME,
_MIDDLE_NAME,
_LAST_NAME,
_COVERPAGE,
_SEQUENCE,
_GENRE,
_UNKNOWN
};
protected:
FB2Reader();
~FB2Reader();
private:
std::string myXLinkNamespace;
};
inline FB2Reader::FB2Reader() {}
inline FB2Reader::~FB2Reader() {}
inline const std::string &FB2Reader::xlinkNamespace() const { return myXLinkNamespace; }
#endif /* __FB2READER_H__ */

View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2008-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include <vector>
#include <ZLFile.h>
#include <ZLXMLReader.h>
#include <ZLibrary.h>
#include <ZLStringUtil.h>
#include "FB2TagManager.h"
class FB2TagInfoReader : public ZLXMLReader {
public:
FB2TagInfoReader(std::map<std::string,std::vector<std::string> > &tagMap);
void startElementHandler(const char *tag, const char **attributes);
void endElementHandler(const char *tag);
private:
std::map<std::string,std::vector<std::string> > &myTagMap;
std::string myCategoryName;
std::string mySubCategoryName;
std::vector<std::string> myGenreIds;
std::string myLanguage;
};
FB2TagInfoReader::FB2TagInfoReader(std::map<std::string,std::vector<std::string> > &tagMap) : myTagMap(tagMap) {
myLanguage = ZLibrary::Language();
if (myLanguage != "ru") {
myLanguage = "en";
}
}
static const std::string CATEGORY_NAME_TAG = "root-descr";
static const std::string SUBCATEGORY_NAME_TAG = "genre-descr";
static const std::string GENRE_TAG = "genre";
static const std::string SUBGENRE_TAG = "subgenre";
static const std::string SUBGENRE_ALT_TAG = "genre-alt";
void FB2TagInfoReader::startElementHandler(const char *tag, const char **attributes) {
if ((SUBGENRE_TAG == tag) || (SUBGENRE_ALT_TAG == tag)) {
const char *id = attributeValue(attributes, "value");
if (id != 0) {
myGenreIds.push_back(id);
}
} else if (CATEGORY_NAME_TAG == tag) {
const char *lang = attributeValue(attributes, "lang");
if ((lang != 0) && (myLanguage == lang)) {
const char *name = attributeValue(attributes, "genre-title");
if (name != 0) {
myCategoryName = name;
ZLStringUtil::stripWhiteSpaces(myCategoryName);
}
}
} else if (SUBCATEGORY_NAME_TAG == tag) {
const char *lang = attributeValue(attributes, "lang");
if ((lang != 0) && (myLanguage == lang)) {
const char *name = attributeValue(attributes, "title");
if (name != 0) {
mySubCategoryName = name;
ZLStringUtil::stripWhiteSpaces(mySubCategoryName);
}
}
}
}
void FB2TagInfoReader::endElementHandler(const char *tag) {
if (GENRE_TAG == tag) {
myCategoryName.erase();
mySubCategoryName.erase();
myGenreIds.clear();
} else if (SUBGENRE_TAG == tag) {
if (!myCategoryName.empty() && !mySubCategoryName.empty()) {
const std::string fullTagName = myCategoryName + '/' + mySubCategoryName;
for (std::vector<std::string>::const_iterator it = myGenreIds.begin(); it != myGenreIds.end(); ++it) {
myTagMap[*it].push_back(fullTagName);
}
}
mySubCategoryName.erase();
myGenreIds.clear();
}
}
FB2TagManager *FB2TagManager::ourInstance = 0;
const FB2TagManager &FB2TagManager::Instance() {
if (ourInstance == 0) {
ourInstance = new FB2TagManager();
}
return *ourInstance;
}
FB2TagManager::FB2TagManager() {
FB2TagInfoReader(myTagMap).readDocument(ZLFile(
ZLibrary::ApplicationDirectory() + ZLibrary::FileNameDelimiter +
"formats" + ZLibrary::FileNameDelimiter + "fb2" +
ZLibrary::FileNameDelimiter + "fb2genres.xml"
));
}
const std::vector<std::string> &FB2TagManager::humanReadableTags(const std::string &id) const {
static const std::vector<std::string> EMPTY;
std::map<std::string,std::vector<std::string> >::const_iterator it = myTagMap.find(id);
return (it != myTagMap.end()) ? it->second : EMPTY;
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2008-2012 Geometer Plus <contact@geometerplus.com>
*
* This program 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.
*
* This program 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 Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#ifndef __FB2TAGMANAGER_H__
#define __FB2TAGMANAGER_H__
#include <string>
#include <map>
#include <vector>
class FB2TagManager {
private:
static FB2TagManager *ourInstance;
public:
static const FB2TagManager &Instance();
private:
FB2TagManager();
public:
const std::vector<std::string> &humanReadableTags(const std::string &id) const;
private:
std::map<std::string,std::vector<std::string> > myTagMap;
};
#endif /* __FB2TAGMANAGER_H__ */