summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Tardon <dtardon@redhat.com>2016-02-25 17:55:12 +0100
committerDavid Tardon <dtardon@redhat.com>2016-02-25 17:55:28 +0100
commit85eaf29e1798c98c2703dbabad818001c5a6ab00 (patch)
tree3cb39bb18b57bb2de4f77bf47991fa72fdee173e
parent0a4be9f5f22605d07d0d795c142d821571973b48 (diff)
refactor format detection
-rw-r--r--configure.ac1
-rw-r--r--src/lib/SW602Document.cpp104
-rw-r--r--src/lib/WinText602Header.cpp6
-rw-r--r--src/lib/WinText602Header.h4
-rw-r--r--src/lib/WinText602Parser.cpp7
5 files changed, 90 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac
index f9054a3..49e9b52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,6 +52,7 @@ AC_SUBST(REVENGE_LIBS)
# ==================
AC_CHECK_HEADERS(
boost/optional.hpp \
+ boost/scoped_ptr.hpp \
boost/shared_ptr.hpp \
,
[],
diff --git a/src/lib/SW602Document.cpp b/src/lib/SW602Document.cpp
index 2be0e20..038bd1f 100644
--- a/src/lib/SW602Document.cpp
+++ b/src/lib/SW602Document.cpp
@@ -9,6 +9,9 @@
#include <libsw602/SW602Document.h>
+#include <cassert>
+
+#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <librevenge-stream/librevenge-stream.h>
@@ -16,8 +19,6 @@
#include "WinText602Header.h"
#include "WinText602Parser.h"
-using boost::shared_ptr;
-
using librevenge::RVNGInputStream;
using std::string;
@@ -28,15 +29,63 @@ namespace libsw602
namespace
{
-shared_ptr<RVNGInputStream> getContent(librevenge::RVNGInputStream *const ip)
+struct DetectionInfo
+{
+ DetectionInfo();
+
+ SW602Document::Kind m_kind;
+ SW602Document::Type m_type;
+ SW602Document::Confidence m_confidence;
+ bool m_needsEncoding;
+};
+
+DetectionInfo::DetectionInfo()
+ : m_kind(SW602Document::KIND_UNKNOWN)
+ , m_type(SW602Document::TYPE_UNKNOWN)
+ , m_confidence(SW602Document::CONFIDENCE_NONE)
+ , m_needsEncoding(false)
{
- const shared_ptr<RVNGInputStream> input(ip, SW602_shared_ptr_noop_deleter<librevenge::RVNGInputStream>());
+}
- shared_ptr<RVNGInputStream> strm;
- if (input->isStructured())
- strm.reset(input->getSubStreamByName("CONTENTS"));
+template<class Header>
+void fillDetectionInfo(const Header &header, DetectionInfo &info);
+
+void fillDetectionInfo(const WinText602Header &/*header*/, DetectionInfo &info)
+{
+ info.m_kind = SW602Document::KIND_TEXT;
+ info.m_type = SW602Document::TYPE_WINTEXT602;
+ info.m_needsEncoding = false;
+ // TODO: handle encryption
+ info.m_confidence = SW602Document::CONFIDENCE_EXCELLENT;
+}
+
+template<class Header>
+bool probe(RVNGInputStream &input, DetectionInfo &info) try
+{
+ input.seek(0, librevenge::RVNG_SEEK_SET);
+ Header header;
+ header.construct(input);
+ if (header.isValid())
+ {
+ fillDetectionInfo(header, info);
+ assert(m_kind != SW602Document::KIND_UNKNOWN);
+ assert(m_type != SW602Document::TYPE_UNKNOWN);
+ }
+ return info.m_confidence != SW602Document::CONFIDENCE_NONE;
+}
+catch (...)
+{
+ return false;
+}
- return strm;
+SW602Document::Confidence pass(const DetectionInfo &info, SW602Document::Kind &kind, SW602Document::Type *const type, bool *const needsEncoding)
+{
+ kind = info.m_kind;
+ if (type)
+ *type = info.m_type;
+ if (needsEncoding)
+ *needsEncoding = info.m_needsEncoding;
+ return info.m_confidence;
}
}
@@ -46,20 +95,18 @@ SW602Document::Confidence SW602Document::isSupported(librevenge::RVNGInputStream
if (!input)
return CONFIDENCE_NONE;
- shared_ptr<RVNGInputStream> content = getContent(input);
- if (bool(content))
+ DetectionInfo info;
+
+ if (input->isStructured())
{
- content->seek(0, librevenge::RVNG_SEEK_SET);
- WinText602Header header(*content);
- // TODO: handle encryption
- if (header.isValid())
+ if (input->existsSubStream("CONTENTS"))
{
- kind = KIND_TEXT;
- if (type)
- *type = TYPE_WINTEXT602;
- if (needsEncoding)
- *needsEncoding = false;
- return CONFIDENCE_EXCELLENT;
+ const boost::scoped_ptr<RVNGInputStream> content(input->getSubStreamByName("CONTENTS"));
+ if (bool(content))
+ {
+ if (probe<WinText602Header>(*content, info))
+ return pass(info, kind, type, needsEncoding);
+ }
}
}
@@ -104,15 +151,14 @@ SW602Document::Result SW602Document::parse(librevenge::RVNGInputStream *const in
{
case TYPE_WINTEXT602:
{
- shared_ptr<RVNGInputStream> content = getContent(input);
- if (bool(content))
- {
- content->seek(0, librevenge::RVNG_SEEK_SET);
- WinText602Parser parser(content);
- parser.parse(document);
- return RESULT_OK;
- }
- break;
+ if (!input->existsSubStream("CONTENTS"))
+ return RESULT_UNSUPPORTED_FORMAT;
+ const boost::shared_ptr<RVNGInputStream> content(input->getSubStreamByName("CONTENTS"));
+ if (!content)
+ return RESULT_UNSUPPORTED_FORMAT;
+ WinText602Parser parser(content);
+ parser.parse(document);
+ return RESULT_OK;
}
default:
return RESULT_UNSUPPORTED_FORMAT;
diff --git a/src/lib/WinText602Header.cpp b/src/lib/WinText602Header.cpp
index 8f88a50..75237d2 100644
--- a/src/lib/WinText602Header.cpp
+++ b/src/lib/WinText602Header.cpp
@@ -18,10 +18,14 @@
namespace libsw602
{
-WinText602Header::WinText602Header(librevenge::RVNGInputStream &input)
+WinText602Header::WinText602Header()
: m_length(0)
, m_valid(false)
{
+}
+
+void WinText602Header::construct(librevenge::RVNGInputStream &input)
+{
m_length = readU32(input);
skip(input, 2);
const unsigned char *const sig = readNBytes(input, 5);
diff --git a/src/lib/WinText602Header.h b/src/lib/WinText602Header.h
index 7dd038d..9ed2656 100644
--- a/src/lib/WinText602Header.h
+++ b/src/lib/WinText602Header.h
@@ -18,7 +18,9 @@ namespace libsw602
class WinText602Header
{
public:
- explicit WinText602Header(librevenge::RVNGInputStream &input);
+ WinText602Header();
+
+ void construct(librevenge::RVNGInputStream &input);
bool isValid() const;
diff --git a/src/lib/WinText602Parser.cpp b/src/lib/WinText602Parser.cpp
index 96d371b..1bcd768 100644
--- a/src/lib/WinText602Parser.cpp
+++ b/src/lib/WinText602Parser.cpp
@@ -17,6 +17,7 @@
#include <librevenge/librevenge.h>
#include "SW602MemoryStream.h"
+#include "libsw602_utils.h"
using boost::shared_ptr;
@@ -111,7 +112,7 @@ namespace libsw602
WinText602Parser::WinText602Parser(const boost::shared_ptr<librevenge::RVNGInputStream> input)
: SW602TextParser(input)
- , m_header(*input)
+ , m_header()
, m_input(input)
, m_document(0)
, m_sectionMap()
@@ -122,6 +123,10 @@ void WinText602Parser::parse(librevenge::RVNGTextInterface *documentInterface)
{
m_document = documentInterface;
+ m_header.construct(*m_input);
+ if (!m_header.isValid())
+ throw ParseException();
+
m_sectionMap.reset(new WinText602SectionMap(*m_input));
m_document->startDocument(librevenge::RVNGPropertyList());