ConfigureChecks.cmake | 2 ++ config.h.cmake | 3 +++ poppler/PageLabelInfo.cc | 7 ++++--- poppler/PageLabelInfo_p.h | 34 ++++++++++++++++++++++++++++++++++ qt5/tests/check_pagelabelinfo.cpp | 20 ++++++++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-)
New commits: commit a6f88881d41f064a4c2438d4e1b532872a879b0c Author: Adam Reichold <[email protected]> Date: Sun Sep 23 09:56:51 2018 +0200 Put (optional) usage of codecvt behind a configure check s.t. we at least compile even if we do not properly handle the unicode page label. diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake index 6a910394..fa0f1403 100644 --- a/ConfigureChecks.cmake +++ b/ConfigureChecks.cmake @@ -4,6 +4,7 @@ # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(CheckIncludeFile) +include(CheckIncludeFileCXX) include(CheckIncludeFiles) include(CheckSymbolExists) include(CheckFunctionExists) @@ -17,6 +18,7 @@ check_include_files(stdlib.h HAVE_STDLIB_H) check_include_files(sys/mman.h HAVE_SYS_MMAN_H) check_include_files(sys/stat.h HAVE_SYS_STAT_H) check_include_files(unistd.h HAVE_UNISTD_H) +check_include_file_cxx(codecvt HAVE_CODECVT) check_function_exists(fseek64 HAVE_FSEEK64) check_function_exists(fseeko HAVE_FSEEKO) diff --git a/config.h.cmake b/config.h.cmake index 74355a69..7989cbfb 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -117,6 +117,9 @@ /* Define to 1 if you have the <unistd.h> header file. */ #cmakedefine HAVE_UNISTD_H 1 +/* Define to 1 if you have the <codecvt> header file. */ +#cmakedefine HAVE_CODECVT + /* Define to 1 if you have a big endian machine */ #cmakedefine WORDS_BIGENDIAN 1 diff --git a/poppler/PageLabelInfo_p.h b/poppler/PageLabelInfo_p.h index 36abe0e1..6553c325 100644 --- a/poppler/PageLabelInfo_p.h +++ b/poppler/PageLabelInfo_p.h @@ -14,20 +14,19 @@ /* http://mathworld.wolfram.com/RomanNumerals.html */ +#include "config.h" + +#ifdef HAVE_CODECVT #include <locale> #include <codecvt> +#endif #include "goo/GooString.h" #include "Error.h" static std::pair<int,bool> fromDecimal(const char *const begin, const char *const end, const bool unicode) { - if (!unicode) { - char *parsed; - const int number = std::strtol(begin, &parsed, 10); - if (parsed >= end) { - return std::make_pair(number, true); - } - } else { +#ifdef HAVE_CODECVT + if (unicode) { std::wstring_convert<std::codecvt_utf16<wchar_t>> converter; const auto str = converter.from_bytes(begin, end); @@ -43,8 +42,13 @@ static std::pair<int,bool> fromDecimal(const char *const begin, const char *cons return std::make_pair(number, true); } } +#else + (void)unicode; +#endif - return std::make_pair(0, false); + char *parsed; + const int number = std::strtol(begin, &parsed, 10); + return std::make_pair(number, parsed >= end); } static int fromRoman(const char *buffer) { commit 65c8bc1eefea0b99e46d4190dc61ead216088283 Author: Adam Reichold <[email protected]> Date: Sun Sep 23 00:45:04 2018 +0200 Parse Unicode decimals as well as ASCII decimals when resolving page labels. diff --git a/poppler/PageLabelInfo.cc b/poppler/PageLabelInfo.cc index 96c4c333..3053aa05 100644 --- a/poppler/PageLabelInfo.cc +++ b/poppler/PageLabelInfo.cc @@ -102,8 +102,9 @@ GBool PageLabelInfo::labelToIndex(GooString *label, int *index) const { const char *const str = label->getCString(); const std::size_t strLen = label->getLength(); - char *end; + const bool strUnicode = label->hasUnicodeMarker(); int number; + bool ok; for (const auto& interval : intervals) { const std::size_t prefixLen = interval.prefix.size(); @@ -112,8 +113,8 @@ GBool PageLabelInfo::labelToIndex(GooString *label, int *index) const switch (interval.style) { case Interval::Arabic: - number = strtol(str + prefixLen, &end, 10); - if (*end == '\0' && number - interval.first < interval.length) { + std::tie(number, ok) = fromDecimal(str + prefixLen, str + strLen, strUnicode); + if (ok && number - interval.first < interval.length) { *index = interval.base + number - interval.first; return gTrue; } diff --git a/poppler/PageLabelInfo_p.h b/poppler/PageLabelInfo_p.h index 34823cc6..36abe0e1 100644 --- a/poppler/PageLabelInfo_p.h +++ b/poppler/PageLabelInfo_p.h @@ -14,9 +14,39 @@ /* http://mathworld.wolfram.com/RomanNumerals.html */ +#include <locale> +#include <codecvt> + #include "goo/GooString.h" #include "Error.h" +static std::pair<int,bool> fromDecimal(const char *const begin, const char *const end, const bool unicode) { + if (!unicode) { + char *parsed; + const int number = std::strtol(begin, &parsed, 10); + if (parsed >= end) { + return std::make_pair(number, true); + } + } else { + std::wstring_convert<std::codecvt_utf16<wchar_t>> converter; + const auto str = converter.from_bytes(begin, end); + + // Skip BOM since wcstol seems unable to handle it. + const wchar_t *c_str = str.c_str(); + if (*c_str == wchar_t{0xfeff}) { + ++c_str; + } + + wchar_t *parsed; + const int number = std::wcstol(c_str, &parsed, 10); + if (parsed >= str.data() + str.size()) { + return std::make_pair(number, true); + } + } + + return std::make_pair(0, false); +} + static int fromRoman(const char *buffer) { int digit_value, prev_digit_value, value; int i; diff --git a/qt5/tests/check_pagelabelinfo.cpp b/qt5/tests/check_pagelabelinfo.cpp index a428e059..1b13be95 100644 --- a/qt5/tests/check_pagelabelinfo.cpp +++ b/qt5/tests/check_pagelabelinfo.cpp @@ -1,17 +1,37 @@ #include <QtTest/QtTest> +#include <poppler-private.h> + #include "PageLabelInfo_p.h" class TestPageLabelInfo : public QObject { Q_OBJECT private slots: + void testFromDecimal(); + void testFromDecimalUnicode(); void testToRoman(); void testFromRoman(); void testToLatin(); void testFromLatin(); }; +void TestPageLabelInfo::testFromDecimal() +{ + std::string str{"2342"}; + const auto res = fromDecimal(str.data(), str.data() + str.size(), false); + QCOMPARE(res.first, 2342); + QCOMPARE(res.second, true); +} + +void TestPageLabelInfo::testFromDecimalUnicode() +{ + std::unique_ptr<GooString> str(Poppler::QStringToUnicodeGooString(QString::fromLocal8Bit("2342"))); + const auto res = fromDecimal(str->getCString(), str->getCString() + str->getLength(), str->hasUnicodeMarker()); + QCOMPARE(res.first, 2342); + QCOMPARE(res.second, true); +} + void TestPageLabelInfo::testToRoman() { GooString str; _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
