Commit 67edbfd954a4249d6c78bd375294e4a5bbde3846
1 parent
fa8dd266
Un-inline QUtil functions
Add new private Util.hh header to define inline functions and expose as ordinary functions in QUtil.
Showing
12 changed files
with
202 additions
and
123 deletions
include/qpdf/QUtil.hh
| ... | ... | @@ -190,7 +190,7 @@ namespace QUtil |
| 190 | 190 | |
| 191 | 191 | // Returns lower-case hex-encoded version of the char including a leading "#". |
| 192 | 192 | QPDF_DLL |
| 193 | - inline std::string hex_encode_char(char); | |
| 193 | + std::string hex_encode_char(char); | |
| 194 | 194 | |
| 195 | 195 | // Returns a string that is the result of decoding the input string. The input string may |
| 196 | 196 | // consist of mixed case hexadecimal digits. Any characters that are not hexadecimal digits will |
| ... | ... | @@ -202,7 +202,7 @@ namespace QUtil |
| 202 | 202 | // Decode a single hex digit into a char in the range 0 <= char < 16. Return a char >= 16 if |
| 203 | 203 | // digit is not a valid hex digit. |
| 204 | 204 | QPDF_DLL |
| 205 | - inline constexpr char hex_decode_char(char digit) noexcept; | |
| 205 | + char hex_decode_char(char digit); | |
| 206 | 206 | |
| 207 | 207 | // Set stdin, stdout to binary mode |
| 208 | 208 | QPDF_DLL |
| ... | ... | @@ -431,16 +431,16 @@ namespace QUtil |
| 431 | 431 | // These routines help the tokenizer recognize certain character classes without using ctype, |
| 432 | 432 | // which we avoid because of locale considerations. |
| 433 | 433 | QPDF_DLL |
| 434 | - inline bool is_hex_digit(char); | |
| 434 | + bool is_hex_digit(char); | |
| 435 | 435 | |
| 436 | 436 | QPDF_DLL |
| 437 | - inline bool is_space(char); | |
| 437 | + bool is_space(char); | |
| 438 | 438 | |
| 439 | 439 | QPDF_DLL |
| 440 | - inline bool is_digit(char); | |
| 440 | + bool is_digit(char); | |
| 441 | 441 | |
| 442 | 442 | QPDF_DLL |
| 443 | - inline bool is_number(char const*); | |
| 443 | + bool is_number(char const*); | |
| 444 | 444 | |
| 445 | 445 | // This method parses the numeric range syntax used by the qpdf command-line tool. May throw |
| 446 | 446 | // std::runtime_error. A numeric range is as comma-separated list of groups. A group may be a |
| ... | ... | @@ -489,65 +489,4 @@ namespace QUtil |
| 489 | 489 | size_t get_max_memory_usage(); |
| 490 | 490 | }; // namespace QUtil |
| 491 | 491 | |
| 492 | -inline bool | |
| 493 | -QUtil::is_hex_digit(char ch) | |
| 494 | -{ | |
| 495 | - return hex_decode_char(ch) < '\20'; | |
| 496 | -} | |
| 497 | - | |
| 498 | -inline bool | |
| 499 | -QUtil::is_space(char ch) | |
| 500 | -{ | |
| 501 | - return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\v'; | |
| 502 | -} | |
| 503 | - | |
| 504 | -inline bool | |
| 505 | -QUtil::is_digit(char ch) | |
| 506 | -{ | |
| 507 | - return ((ch >= '0') && (ch <= '9')); | |
| 508 | -} | |
| 509 | - | |
| 510 | -inline bool | |
| 511 | -QUtil::is_number(char const* p) | |
| 512 | -{ | |
| 513 | - // ^[\+\-]?(\.\d*|\d+(\.\d*)?)$ | |
| 514 | - if (!*p) { | |
| 515 | - return false; | |
| 516 | - } | |
| 517 | - if ((*p == '-') || (*p == '+')) { | |
| 518 | - ++p; | |
| 519 | - } | |
| 520 | - bool found_dot = false; | |
| 521 | - bool found_digit = false; | |
| 522 | - for (; *p; ++p) { | |
| 523 | - if (*p == '.') { | |
| 524 | - if (found_dot) { | |
| 525 | - // only one dot | |
| 526 | - return false; | |
| 527 | - } | |
| 528 | - found_dot = true; | |
| 529 | - } else if (QUtil::is_digit(*p)) { | |
| 530 | - found_digit = true; | |
| 531 | - } else { | |
| 532 | - return false; | |
| 533 | - } | |
| 534 | - } | |
| 535 | - return found_digit; | |
| 536 | -} | |
| 537 | - | |
| 538 | -inline std::string | |
| 539 | -QUtil::hex_encode_char(char c) | |
| 540 | -{ | |
| 541 | - static auto constexpr hexchars = "0123456789abcdef"; | |
| 542 | - return {'#', hexchars[static_cast<unsigned char>(c) >> 4], hexchars[c & 0x0f]}; | |
| 543 | -} | |
| 544 | - | |
| 545 | -inline constexpr char | |
| 546 | -QUtil::hex_decode_char(char digit) noexcept | |
| 547 | -{ | |
| 548 | - return digit <= '9' && digit >= '0' | |
| 549 | - ? char(digit - '0') | |
| 550 | - : (digit >= 'a' ? char(digit - 'a' + 10) : (digit >= 'A' ? char(digit - 'A' + 10) : '\20')); | |
| 551 | -} | |
| 552 | - | |
| 553 | 492 | #endif // QUTIL_HH | ... | ... |
libqpdf/JSON.cc
| ... | ... | @@ -8,9 +8,13 @@ |
| 8 | 8 | #include <qpdf/Pl_String.hh> |
| 9 | 9 | #include <qpdf/QTC.hh> |
| 10 | 10 | #include <qpdf/QUtil.hh> |
| 11 | +#include <qpdf/Util.hh> | |
| 12 | + | |
| 11 | 13 | #include <cstring> |
| 12 | 14 | #include <stdexcept> |
| 13 | 15 | |
| 16 | +using namespace qpdf; | |
| 17 | + | |
| 14 | 18 | JSON::Members::Members(std::unique_ptr<JSON_value> value) : |
| 15 | 19 | value(std::move(value)) |
| 16 | 20 | { |
| ... | ... | @@ -761,7 +765,7 @@ JSONParser::tokenError() |
| 761 | 765 | QTC::TC("libtests", "JSON parse unexpected sign"); |
| 762 | 766 | throw std::runtime_error( |
| 763 | 767 | "JSON: offset " + std::to_string(offset) + ": numeric literal: unexpected sign"); |
| 764 | - } else if (QUtil::is_space(*p) || strchr("{}[]:,", *p)) { | |
| 768 | + } else if (util::is_space(*p) || strchr("{}[]:,", *p)) { | |
| 765 | 769 | QTC::TC("libtests", "JSON parse incomplete number"); |
| 766 | 770 | throw std::runtime_error( |
| 767 | 771 | "JSON: offset " + std::to_string(offset) + ": numeric literal: incomplete number"); |
| ... | ... | @@ -1078,7 +1082,7 @@ JSONParser::getToken() |
| 1078 | 1082 | |
| 1079 | 1083 | case ls_u4: |
| 1080 | 1084 | using ui = unsigned int; |
| 1081 | - if (ui val = ui(QUtil::hex_decode_char(*p)); val < 16) { | |
| 1085 | + if (ui val = ui(util::hex_decode_char(*p)); val < 16) { | |
| 1082 | 1086 | u_value = 16 * u_value + val; |
| 1083 | 1087 | } else { |
| 1084 | 1088 | tokenError(); | ... | ... |
libqpdf/Pl_Base64.cc
| ... | ... | @@ -2,9 +2,13 @@ |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/QIntC.hh> |
| 4 | 4 | #include <qpdf/QUtil.hh> |
| 5 | +#include <qpdf/Util.hh> | |
| 6 | + | |
| 5 | 7 | #include <cstring> |
| 6 | 8 | #include <stdexcept> |
| 7 | 9 | |
| 10 | +using namespace qpdf; | |
| 11 | + | |
| 8 | 12 | static char |
| 9 | 13 | to_c(unsigned int ch) |
| 10 | 14 | { |
| ... | ... | @@ -50,7 +54,7 @@ Pl_Base64::decode(unsigned char const* data, size_t len) |
| 50 | 54 | { |
| 51 | 55 | unsigned char const* p = data; |
| 52 | 56 | while (len > 0) { |
| 53 | - if (!QUtil::is_space(to_c(*p))) { | |
| 57 | + if (!util::is_space(to_c(*p))) { | |
| 54 | 58 | this->buf[this->pos++] = *p; |
| 55 | 59 | if (this->pos == 4) { |
| 56 | 60 | flush(); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -22,6 +22,9 @@ |
| 22 | 22 | #include <qpdf/QPDFParser.hh> |
| 23 | 23 | #include <qpdf/QTC.hh> |
| 24 | 24 | #include <qpdf/QUtil.hh> |
| 25 | +#include <qpdf/Util.hh> | |
| 26 | + | |
| 27 | +using namespace qpdf; | |
| 25 | 28 | |
| 26 | 29 | // This must be a fixed value. This API returns a const reference to it, and the C API relies on its |
| 27 | 30 | // being static as well. |
| ... | ... | @@ -368,14 +371,14 @@ QPDF::numWarnings() const |
| 368 | 371 | bool |
| 369 | 372 | QPDF::validatePDFVersion(char const*& p, std::string& version) |
| 370 | 373 | { |
| 371 | - bool valid = QUtil::is_digit(*p); | |
| 374 | + bool valid = util::is_digit(*p); | |
| 372 | 375 | if (valid) { |
| 373 | - while (QUtil::is_digit(*p)) { | |
| 376 | + while (util::is_digit(*p)) { | |
| 374 | 377 | version.append(1, *p++); |
| 375 | 378 | } |
| 376 | - if ((*p == '.') && QUtil::is_digit(*(p + 1))) { | |
| 379 | + if ((*p == '.') && util::is_digit(*(p + 1))) { | |
| 377 | 380 | version.append(1, *p++); |
| 378 | - while (QUtil::is_digit(*p)) { | |
| 381 | + while (util::is_digit(*p)) { | |
| 379 | 382 | version.append(1, *p++); |
| 380 | 383 | } |
| 381 | 384 | } else { |
| ... | ... | @@ -709,7 +712,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) |
| 709 | 712 | while (!done) { |
| 710 | 713 | char ch; |
| 711 | 714 | if (1 == m->file->read(&ch, 1)) { |
| 712 | - if (QUtil::is_space(ch)) { | |
| 715 | + if (util::is_space(ch)) { | |
| 713 | 716 | skipped_space = true; |
| 714 | 717 | } else { |
| 715 | 718 | m->file->unreadCh(ch); |
| ... | ... | @@ -724,7 +727,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) |
| 724 | 727 | m->file->read(buf, sizeof(buf) - 1); |
| 725 | 728 | // The PDF spec says xref must be followed by a line terminator, but files exist in the wild |
| 726 | 729 | // where it is terminated by arbitrary whitespace. |
| 727 | - if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) { | |
| 730 | + if ((strncmp(buf, "xref", 4) == 0) && util::is_space(buf[4])) { | |
| 728 | 731 | if (skipped_space) { |
| 729 | 732 | QTC::TC("qpdf", "QPDF xref skipped space"); |
| 730 | 733 | warn(damagedPDF("", 0, "extraneous whitespace seen before xref")); |
| ... | ... | @@ -737,8 +740,8 @@ QPDF::read_xref(qpdf_offset_t xref_offset) |
| 737 | 740 | : (buf[4] == ' ') ? 2 |
| 738 | 741 | : 9999)); |
| 739 | 742 | int skip = 4; |
| 740 | - // buf is null-terminated, and QUtil::is_space('\0') is false, so this won't overrun. | |
| 741 | - while (QUtil::is_space(buf[skip])) { | |
| 743 | + // buf is null-terminated, and util::is_space('\0') is false, so this won't overrun. | |
| 744 | + while (util::is_space(buf[skip])) { | |
| 742 | 745 | ++skip; |
| 743 | 746 | } |
| 744 | 747 | xref_offset = read_xrefTable(xref_offset + skip); |
| ... | ... | @@ -795,37 +798,37 @@ QPDF::parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes) |
| 795 | 798 | char const* start = line.c_str(); |
| 796 | 799 | |
| 797 | 800 | // Skip zero or more spaces |
| 798 | - while (QUtil::is_space(*p)) { | |
| 801 | + while (util::is_space(*p)) { | |
| 799 | 802 | ++p; |
| 800 | 803 | } |
| 801 | 804 | // Require digit |
| 802 | - if (!QUtil::is_digit(*p)) { | |
| 805 | + if (!util::is_digit(*p)) { | |
| 803 | 806 | return false; |
| 804 | 807 | } |
| 805 | 808 | // Gather digits |
| 806 | 809 | std::string obj_str; |
| 807 | - while (QUtil::is_digit(*p)) { | |
| 810 | + while (util::is_digit(*p)) { | |
| 808 | 811 | obj_str.append(1, *p++); |
| 809 | 812 | } |
| 810 | 813 | // Require space |
| 811 | - if (!QUtil::is_space(*p)) { | |
| 814 | + if (!util::is_space(*p)) { | |
| 812 | 815 | return false; |
| 813 | 816 | } |
| 814 | 817 | // Skip spaces |
| 815 | - while (QUtil::is_space(*p)) { | |
| 818 | + while (util::is_space(*p)) { | |
| 816 | 819 | ++p; |
| 817 | 820 | } |
| 818 | 821 | // Require digit |
| 819 | - if (!QUtil::is_digit(*p)) { | |
| 822 | + if (!util::is_digit(*p)) { | |
| 820 | 823 | return false; |
| 821 | 824 | } |
| 822 | 825 | // Gather digits |
| 823 | 826 | std::string num_str; |
| 824 | - while (QUtil::is_digit(*p)) { | |
| 827 | + while (util::is_digit(*p)) { | |
| 825 | 828 | num_str.append(1, *p++); |
| 826 | 829 | } |
| 827 | 830 | // Skip any space including line terminators |
| 828 | - while (QUtil::is_space(*p)) { | |
| 831 | + while (util::is_space(*p)) { | |
| 829 | 832 | ++p; |
| 830 | 833 | } |
| 831 | 834 | bytes = toI(p - start); |
| ... | ... | @@ -847,51 +850,51 @@ QPDF::read_bad_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) |
| 847 | 850 | |
| 848 | 851 | // Skip zero or more spaces. There aren't supposed to be any. |
| 849 | 852 | bool invalid = false; |
| 850 | - while (QUtil::is_space(*p)) { | |
| 853 | + while (util::is_space(*p)) { | |
| 851 | 854 | ++p; |
| 852 | 855 | QTC::TC("qpdf", "QPDF ignore first space in xref entry"); |
| 853 | 856 | invalid = true; |
| 854 | 857 | } |
| 855 | 858 | // Require digit |
| 856 | - if (!QUtil::is_digit(*p)) { | |
| 859 | + if (!util::is_digit(*p)) { | |
| 857 | 860 | return false; |
| 858 | 861 | } |
| 859 | 862 | // Gather digits |
| 860 | 863 | std::string f1_str; |
| 861 | - while (QUtil::is_digit(*p)) { | |
| 864 | + while (util::is_digit(*p)) { | |
| 862 | 865 | f1_str.append(1, *p++); |
| 863 | 866 | } |
| 864 | 867 | // Require space |
| 865 | - if (!QUtil::is_space(*p)) { | |
| 868 | + if (!util::is_space(*p)) { | |
| 866 | 869 | return false; |
| 867 | 870 | } |
| 868 | - if (QUtil::is_space(*(p + 1))) { | |
| 871 | + if (util::is_space(*(p + 1))) { | |
| 869 | 872 | QTC::TC("qpdf", "QPDF ignore first extra space in xref entry"); |
| 870 | 873 | invalid = true; |
| 871 | 874 | } |
| 872 | 875 | // Skip spaces |
| 873 | - while (QUtil::is_space(*p)) { | |
| 876 | + while (util::is_space(*p)) { | |
| 874 | 877 | ++p; |
| 875 | 878 | } |
| 876 | 879 | // Require digit |
| 877 | - if (!QUtil::is_digit(*p)) { | |
| 880 | + if (!util::is_digit(*p)) { | |
| 878 | 881 | return false; |
| 879 | 882 | } |
| 880 | 883 | // Gather digits |
| 881 | 884 | std::string f2_str; |
| 882 | - while (QUtil::is_digit(*p)) { | |
| 885 | + while (util::is_digit(*p)) { | |
| 883 | 886 | f2_str.append(1, *p++); |
| 884 | 887 | } |
| 885 | 888 | // Require space |
| 886 | - if (!QUtil::is_space(*p)) { | |
| 889 | + if (!util::is_space(*p)) { | |
| 887 | 890 | return false; |
| 888 | 891 | } |
| 889 | - if (QUtil::is_space(*(p + 1))) { | |
| 892 | + if (util::is_space(*(p + 1))) { | |
| 890 | 893 | QTC::TC("qpdf", "QPDF ignore second extra space in xref entry"); |
| 891 | 894 | invalid = true; |
| 892 | 895 | } |
| 893 | 896 | // Skip spaces |
| 894 | - while (QUtil::is_space(*p)) { | |
| 897 | + while (util::is_space(*p)) { | |
| 895 | 898 | ++p; |
| 896 | 899 | } |
| 897 | 900 | if ((*p == 'f') || (*p == 'n')) { |
| ... | ... | @@ -938,12 +941,12 @@ QPDF::read_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) |
| 938 | 941 | ++f1_len; |
| 939 | 942 | ++p; |
| 940 | 943 | } |
| 941 | - while (QUtil::is_digit(*p) && f1_len++ < 10) { | |
| 944 | + while (util::is_digit(*p) && f1_len++ < 10) { | |
| 942 | 945 | f1 *= 10; |
| 943 | 946 | f1 += *p++ - '0'; |
| 944 | 947 | } |
| 945 | 948 | // Require space |
| 946 | - if (!QUtil::is_space(*p++)) { | |
| 949 | + if (!util::is_space(*p++)) { | |
| 947 | 950 | // Entry doesn't start with space or digit. |
| 948 | 951 | // C++20: [[unlikely]] |
| 949 | 952 | return false; |
| ... | ... | @@ -953,11 +956,11 @@ QPDF::read_xrefEntry(qpdf_offset_t& f1, int& f2, char& type) |
| 953 | 956 | ++f2_len; |
| 954 | 957 | ++p; |
| 955 | 958 | } |
| 956 | - while (QUtil::is_digit(*p) && f2_len++ < 5) { | |
| 959 | + while (util::is_digit(*p) && f2_len++ < 5) { | |
| 957 | 960 | f2 *= 10; |
| 958 | 961 | f2 += static_cast<int>(*p++ - '0'); |
| 959 | 962 | } |
| 960 | - if (QUtil::is_space(*p++) && (*p == 'f' || *p == 'n')) { | |
| 963 | + if (util::is_space(*p++) && (*p == 'f' || *p == 'n')) { | |
| 961 | 964 | // C++20: [[likely]] |
| 962 | 965 | type = *p; |
| 963 | 966 | // No test for valid line[19]. |
| ... | ... | @@ -1602,7 +1605,7 @@ QPDF::validateStreamLineEnd(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset |
| 1602 | 1605 | } |
| 1603 | 1606 | return; |
| 1604 | 1607 | } |
| 1605 | - if (!QUtil::is_space(ch)) { | |
| 1608 | + if (!util::is_space(ch)) { | |
| 1606 | 1609 | QTC::TC("qpdf", "QPDF stream without newline"); |
| 1607 | 1610 | m->file->unreadCh(ch); |
| 1608 | 1611 | warn(damagedPDF( | ... | ... |
libqpdf/QPDFArgParser.cc
| ... | ... | @@ -5,10 +5,13 @@ |
| 5 | 5 | #include <qpdf/QPDFUsage.hh> |
| 6 | 6 | #include <qpdf/QTC.hh> |
| 7 | 7 | #include <qpdf/QUtil.hh> |
| 8 | +#include <qpdf/Util.hh> | |
| 9 | + | |
| 8 | 10 | #include <cstdlib> |
| 9 | 11 | #include <cstring> |
| 10 | 12 | #include <iostream> |
| 11 | 13 | |
| 14 | +using namespace qpdf; | |
| 12 | 15 | using namespace std::literals; |
| 13 | 16 | |
| 14 | 17 | QPDFArgParser::Members::Members(int argc, char const* const argv[], char const* progname_env) : |
| ... | ... | @@ -285,7 +288,7 @@ QPDFArgParser::handleBashArguments() |
| 285 | 288 | bool append = false; |
| 286 | 289 | switch (state) { |
| 287 | 290 | case st_top: |
| 288 | - if (QUtil::is_space(ch)) { | |
| 291 | + if (util::is_space(ch)) { | |
| 289 | 292 | if (!arg.empty()) { |
| 290 | 293 | m->bash_argv.push_back(QUtil::make_shared_cstr(arg)); |
| 291 | 294 | arg.clear(); | ... | ... |
libqpdf/QPDFJob.cc
| ... | ... | @@ -29,9 +29,12 @@ |
| 29 | 29 | #include <qpdf/QPDFWriter.hh> |
| 30 | 30 | #include <qpdf/QTC.hh> |
| 31 | 31 | #include <qpdf/QUtil.hh> |
| 32 | +#include <qpdf/Util.hh> | |
| 32 | 33 | |
| 33 | 34 | #include <qpdf/auto_job_schema.hh> // JOB_SCHEMA_DATA |
| 34 | 35 | |
| 36 | +using namespace qpdf; | |
| 37 | + | |
| 35 | 38 | namespace |
| 36 | 39 | { |
| 37 | 40 | class ImageOptimizer: public QPDFObjectHandle::StreamDataProvider |
| ... | ... | @@ -388,7 +391,7 @@ QPDFJob::parseRotationParameter(std::string const& parameter) |
| 388 | 391 | if ((first == '+') || (first == '-')) { |
| 389 | 392 | relative = ((first == '+') ? 1 : -1); |
| 390 | 393 | angle_str = angle_str.substr(1); |
| 391 | - } else if (!QUtil::is_digit(angle_str.at(0))) { | |
| 394 | + } else if (!util::is_digit(angle_str.at(0))) { | |
| 392 | 395 | angle_str = ""; |
| 393 | 396 | } |
| 394 | 397 | } | ... | ... |
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #include <qpdf/QIntC.hh> |
| 16 | 16 | #include <qpdf/QTC.hh> |
| 17 | 17 | #include <qpdf/QUtil.hh> |
| 18 | +#include <qpdf/Util.hh> | |
| 18 | 19 | |
| 19 | 20 | #include <algorithm> |
| 20 | 21 | #include <array> |
| ... | ... | @@ -279,7 +280,7 @@ Name::normalize(std::string const& name) |
| 279 | 280 | } else if ( |
| 280 | 281 | ch < 33 || ch == '#' || ch == '/' || ch == '(' || ch == ')' || ch == '{' || ch == '}' || |
| 281 | 282 | ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '%' || ch > 126) { |
| 282 | - result += QUtil::hex_encode_char(ch); | |
| 283 | + result += util::hex_encode_char(ch); | |
| 283 | 284 | } else { |
| 284 | 285 | result += ch; |
| 285 | 286 | } | ... | ... |
libqpdf/QPDFTokenizer.cc
| ... | ... | @@ -8,11 +8,14 @@ |
| 8 | 8 | #include <qpdf/QPDFObjectHandle.hh> |
| 9 | 9 | #include <qpdf/QTC.hh> |
| 10 | 10 | #include <qpdf/QUtil.hh> |
| 11 | +#include <qpdf/Util.hh> | |
| 11 | 12 | |
| 12 | 13 | #include <cstdlib> |
| 13 | 14 | #include <cstring> |
| 14 | 15 | #include <stdexcept> |
| 15 | 16 | |
| 17 | +using namespace qpdf; | |
| 18 | + | |
| 16 | 19 | static inline bool |
| 17 | 20 | is_delimiter(char ch) |
| 18 | 21 | { |
| ... | ... | @@ -123,7 +126,7 @@ QPDFTokenizer::includeIgnorable() |
| 123 | 126 | bool |
| 124 | 127 | QPDFTokenizer::isSpace(char ch) |
| 125 | 128 | { |
| 126 | - return ((ch == '\0') || QUtil::is_space(ch)); | |
| 129 | + return (ch == '\0' || util::is_space(ch)); | |
| 127 | 130 | } |
| 128 | 131 | |
| 129 | 132 | bool |
| ... | ... | @@ -440,7 +443,7 @@ QPDFTokenizer::inNameHex1(char ch) |
| 440 | 443 | { |
| 441 | 444 | this->hex_char = ch; |
| 442 | 445 | |
| 443 | - if (char hval = QUtil::hex_decode_char(ch); hval < '0') { | |
| 446 | + if (char hval = util::hex_decode_char(ch); hval < '0') { | |
| 444 | 447 | this->char_code = int(hval) << 4; |
| 445 | 448 | this->state = st_name_hex2; |
| 446 | 449 | } else { |
| ... | ... | @@ -456,7 +459,7 @@ QPDFTokenizer::inNameHex1(char ch) |
| 456 | 459 | void |
| 457 | 460 | QPDFTokenizer::inNameHex2(char ch) |
| 458 | 461 | { |
| 459 | - if (char hval = QUtil::hex_decode_char(ch); hval < '0') { | |
| 462 | + if (char hval = util::hex_decode_char(ch); hval < '0') { | |
| 460 | 463 | this->char_code |= int(hval); |
| 461 | 464 | } else { |
| 462 | 465 | QTC::TC("qpdf", "QPDFTokenizer bad name 2"); |
| ... | ... | @@ -483,7 +486,7 @@ QPDFTokenizer::inNameHex2(char ch) |
| 483 | 486 | void |
| 484 | 487 | QPDFTokenizer::inSign(char ch) |
| 485 | 488 | { |
| 486 | - if (QUtil::is_digit(ch)) { | |
| 489 | + if (util::is_digit(ch)) { | |
| 487 | 490 | this->state = st_number; |
| 488 | 491 | } else if (ch == '.') { |
| 489 | 492 | this->state = st_decimal; |
| ... | ... | @@ -496,7 +499,7 @@ QPDFTokenizer::inSign(char ch) |
| 496 | 499 | void |
| 497 | 500 | QPDFTokenizer::inDecimal(char ch) |
| 498 | 501 | { |
| 499 | - if (QUtil::is_digit(ch)) { | |
| 502 | + if (util::is_digit(ch)) { | |
| 500 | 503 | this->state = st_real; |
| 501 | 504 | } else { |
| 502 | 505 | this->state = st_literal; |
| ... | ... | @@ -507,7 +510,7 @@ QPDFTokenizer::inDecimal(char ch) |
| 507 | 510 | void |
| 508 | 511 | QPDFTokenizer::inNumber(char ch) |
| 509 | 512 | { |
| 510 | - if (QUtil::is_digit(ch)) { | |
| 513 | + if (util::is_digit(ch)) { | |
| 511 | 514 | } else if (ch == '.') { |
| 512 | 515 | this->state = st_real; |
| 513 | 516 | } else if (isDelimiter(ch)) { |
| ... | ... | @@ -523,7 +526,7 @@ QPDFTokenizer::inNumber(char ch) |
| 523 | 526 | void |
| 524 | 527 | QPDFTokenizer::inReal(char ch) |
| 525 | 528 | { |
| 526 | - if (QUtil::is_digit(ch)) { | |
| 529 | + if (util::is_digit(ch)) { | |
| 527 | 530 | } else if (isDelimiter(ch)) { |
| 528 | 531 | this->type = tt_real; |
| 529 | 532 | this->state = st_token_ready; |
| ... | ... | @@ -645,7 +648,7 @@ QPDFTokenizer::inLiteral(char ch) |
| 645 | 648 | void |
| 646 | 649 | QPDFTokenizer::inHexstring(char ch) |
| 647 | 650 | { |
| 648 | - if (char hval = QUtil::hex_decode_char(ch); hval < '0') { | |
| 651 | + if (char hval = util::hex_decode_char(ch); hval < '0') { | |
| 649 | 652 | this->char_code = int(hval) << 4; |
| 650 | 653 | this->state = st_in_hexstring_2nd; |
| 651 | 654 | |
| ... | ... | @@ -667,7 +670,7 @@ QPDFTokenizer::inHexstring(char ch) |
| 667 | 670 | void |
| 668 | 671 | QPDFTokenizer::inHexstring2nd(char ch) |
| 669 | 672 | { |
| 670 | - if (char hval = QUtil::hex_decode_char(ch); hval < '0') { | |
| 673 | + if (char hval = util::hex_decode_char(ch); hval < '0') { | |
| 671 | 674 | this->val += char(this->char_code) | hval; |
| 672 | 675 | this->state = st_in_hexstring; |
| 673 | 676 | ... | ... |
libqpdf/QPDF_json.cc
| ... | ... | @@ -9,9 +9,13 @@ |
| 9 | 9 | #include <qpdf/QPDFObject_private.hh> |
| 10 | 10 | #include <qpdf/QTC.hh> |
| 11 | 11 | #include <qpdf/QUtil.hh> |
| 12 | +#include <qpdf/Util.hh> | |
| 13 | + | |
| 12 | 14 | #include <algorithm> |
| 13 | 15 | #include <cstring> |
| 14 | 16 | |
| 17 | +using namespace qpdf; | |
| 18 | + | |
| 15 | 19 | // This chart shows an example of the state transitions that would occur in parsing a minimal file. |
| 16 | 20 | |
| 17 | 21 | // | |
| ... | ... | @@ -67,10 +71,10 @@ is_indirect_object(std::string const& v, int& obj, int& gen) |
| 67 | 71 | char const* p = v.c_str(); |
| 68 | 72 | std::string o_str; |
| 69 | 73 | std::string g_str; |
| 70 | - if (!QUtil::is_digit(*p)) { | |
| 74 | + if (!util::is_digit(*p)) { | |
| 71 | 75 | return false; |
| 72 | 76 | } |
| 73 | - while (QUtil::is_digit(*p)) { | |
| 77 | + while (util::is_digit(*p)) { | |
| 74 | 78 | o_str.append(1, *p++); |
| 75 | 79 | } |
| 76 | 80 | if (*p != ' ') { |
| ... | ... | @@ -79,10 +83,10 @@ is_indirect_object(std::string const& v, int& obj, int& gen) |
| 79 | 83 | while (*p == ' ') { |
| 80 | 84 | ++p; |
| 81 | 85 | } |
| 82 | - if (!QUtil::is_digit(*p)) { | |
| 86 | + if (!util::is_digit(*p)) { | |
| 83 | 87 | return false; |
| 84 | 88 | } |
| 85 | - while (QUtil::is_digit(*p)) { | |
| 89 | + while (util::is_digit(*p)) { | |
| 86 | 90 | g_str.append(1, *p++); |
| 87 | 91 | } |
| 88 | 92 | if (*p != ' ') { |
| ... | ... | @@ -128,7 +132,7 @@ is_binary_string(std::string const& v, std::string& str) |
| 128 | 132 | str = v.substr(2); |
| 129 | 133 | int count = 0; |
| 130 | 134 | for (char c: str) { |
| 131 | - if (!QUtil::is_hex_digit(c)) { | |
| 135 | + if (!util::is_hex_digit(c)) { | |
| 132 | 136 | return false; |
| 133 | 137 | } |
| 134 | 138 | ++count; | ... | ... |
libqpdf/QPDF_linearization.cc
| ... | ... | @@ -12,11 +12,14 @@ |
| 12 | 12 | #include <qpdf/QPDFWriter_private.hh> |
| 13 | 13 | #include <qpdf/QTC.hh> |
| 14 | 14 | #include <qpdf/QUtil.hh> |
| 15 | +#include <qpdf/Util.hh> | |
| 15 | 16 | |
| 16 | 17 | #include <algorithm> |
| 17 | 18 | #include <cmath> |
| 18 | 19 | #include <cstring> |
| 19 | 20 | |
| 21 | +using namespace qpdf; | |
| 22 | + | |
| 20 | 23 | template <class T, class int_type> |
| 21 | 24 | static void |
| 22 | 25 | load_vector_int( |
| ... | ... | @@ -105,7 +108,7 @@ QPDF::isLinearized() |
| 105 | 108 | char* p = buf; |
| 106 | 109 | while (lindict_obj == -1) { |
| 107 | 110 | // Find a digit or end of buffer |
| 108 | - while (((p - buf) < tbuf_size) && (!QUtil::is_digit(*p))) { | |
| 111 | + while (((p - buf) < tbuf_size) && (!util::is_digit(*p))) { | |
| 109 | 112 | ++p; |
| 110 | 113 | } |
| 111 | 114 | if (p - buf == tbuf_size) { |
| ... | ... | @@ -114,7 +117,7 @@ QPDF::isLinearized() |
| 114 | 117 | // Seek to the digit. Then skip over digits for a potential |
| 115 | 118 | // next iteration. |
| 116 | 119 | m->file->seek(p - buf, SEEK_SET); |
| 117 | - while (((p - buf) < tbuf_size) && QUtil::is_digit(*p)) { | |
| 120 | + while (((p - buf) < tbuf_size) && util::is_digit(*p)) { | |
| 118 | 121 | ++p; |
| 119 | 122 | } |
| 120 | 123 | ... | ... |
libqpdf/QUtil.cc
| ... | ... | @@ -8,6 +8,7 @@ |
| 8 | 8 | #include <qpdf/QIntC.hh> |
| 9 | 9 | #include <qpdf/QPDFSystemError.hh> |
| 10 | 10 | #include <qpdf/QTC.hh> |
| 11 | +#include <qpdf/Util.hh> | |
| 11 | 12 | |
| 12 | 13 | #include <cerrno> |
| 13 | 14 | #include <cstdlib> |
| ... | ... | @@ -37,6 +38,8 @@ |
| 37 | 38 | # include <malloc.h> |
| 38 | 39 | #endif |
| 39 | 40 | |
| 41 | +using namespace qpdf; | |
| 42 | + | |
| 40 | 43 | // First element is 24 |
| 41 | 44 | static unsigned short pdf_doc_low_to_unicode[] = { |
| 42 | 45 | 0x02d8, // 0x18 BREVE |
| ... | ... | @@ -396,7 +399,7 @@ unsigned long long |
| 396 | 399 | QUtil::string_to_ull(char const* str) |
| 397 | 400 | { |
| 398 | 401 | char const* p = str; |
| 399 | - while (*p && is_space(*p)) { | |
| 402 | + while (*p && util::is_space(*p)) { | |
| 400 | 403 | ++p; |
| 401 | 404 | } |
| 402 | 405 | if (*p == '-') { |
| ... | ... | @@ -739,7 +742,7 @@ QUtil::hex_decode(std::string const& input) |
| 739 | 742 | bool first = true; |
| 740 | 743 | char decoded; |
| 741 | 744 | for (auto ch: input) { |
| 742 | - ch = hex_decode_char(ch); | |
| 745 | + ch = util::hex_decode_char(ch); | |
| 743 | 746 | if (ch < '\20') { |
| 744 | 747 | if (first) { |
| 745 | 748 | decoded = static_cast<char>(ch << 4); |
| ... | ... | @@ -2002,3 +2005,63 @@ QUtil::get_max_memory_usage() |
| 2002 | 2005 | return 0; |
| 2003 | 2006 | #endif |
| 2004 | 2007 | } |
| 2008 | + | |
| 2009 | +char | |
| 2010 | +QUtil::hex_decode_char(char digit) | |
| 2011 | +{ | |
| 2012 | + return util::hex_decode_char(digit); | |
| 2013 | +} | |
| 2014 | + | |
| 2015 | +std::string | |
| 2016 | +QUtil::hex_encode_char(char c) | |
| 2017 | +{ | |
| 2018 | + return util::hex_encode_char(c); | |
| 2019 | +} | |
| 2020 | + | |
| 2021 | +bool | |
| 2022 | +QUtil::is_number(char const* p) | |
| 2023 | +{ | |
| 2024 | + // No longer used by qpdf. | |
| 2025 | + | |
| 2026 | + // ^[\+\-]?(\.\d*|\d+(\.\d*)?)$ | |
| 2027 | + if (!*p) { | |
| 2028 | + return false; | |
| 2029 | + } | |
| 2030 | + if ((*p == '-') || (*p == '+')) { | |
| 2031 | + ++p; | |
| 2032 | + } | |
| 2033 | + bool found_dot = false; | |
| 2034 | + bool found_digit = false; | |
| 2035 | + for (; *p; ++p) { | |
| 2036 | + if (*p == '.') { | |
| 2037 | + if (found_dot) { | |
| 2038 | + // only one dot | |
| 2039 | + return false; | |
| 2040 | + } | |
| 2041 | + found_dot = true; | |
| 2042 | + } else if (util::is_digit(*p)) { | |
| 2043 | + found_digit = true; | |
| 2044 | + } else { | |
| 2045 | + return false; | |
| 2046 | + } | |
| 2047 | + } | |
| 2048 | + return found_digit; | |
| 2049 | +} | |
| 2050 | + | |
| 2051 | +bool | |
| 2052 | +QUtil::is_space(char c) | |
| 2053 | +{ | |
| 2054 | + return util::is_space(c); | |
| 2055 | +} | |
| 2056 | + | |
| 2057 | +bool | |
| 2058 | +QUtil::is_digit(char c) | |
| 2059 | +{ | |
| 2060 | + return util::is_digit(c); | |
| 2061 | +} | |
| 2062 | + | |
| 2063 | +bool | |
| 2064 | +QUtil::is_hex_digit(char c) | |
| 2065 | +{ | |
| 2066 | + return util::is_hex_digit(c); | |
| 2067 | +} | ... | ... |
libqpdf/qpdf/Util.hh
0 → 100644
| 1 | +#ifndef UTIL_HH | |
| 2 | +#define UTIL_HH | |
| 3 | + | |
| 4 | +#include <string> | |
| 5 | + | |
| 6 | +namespace qpdf::util | |
| 7 | +{ | |
| 8 | + // This is a collection of useful utility functions for qpdf internal use. They include inline | |
| 9 | + // functions, some of which are exposed as regular functions in QUtil. Implementations are in | |
| 10 | + // QUtil.cc. | |
| 11 | + | |
| 12 | + inline constexpr char | |
| 13 | + hex_decode_char(char digit) | |
| 14 | + { | |
| 15 | + return digit <= '9' && digit >= '0' | |
| 16 | + ? char(digit - '0') | |
| 17 | + : (digit >= 'a' ? char(digit - 'a' + 10) | |
| 18 | + : (digit >= 'A' ? char(digit - 'A' + 10) : '\20')); | |
| 19 | + } | |
| 20 | + | |
| 21 | + inline constexpr bool | |
| 22 | + is_hex_digit(char ch) | |
| 23 | + { | |
| 24 | + return hex_decode_char(ch) < '\20'; | |
| 25 | + } | |
| 26 | + | |
| 27 | + inline constexpr bool | |
| 28 | + is_space(char ch) | |
| 29 | + { | |
| 30 | + return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f' || ch == '\v'; | |
| 31 | + } | |
| 32 | + | |
| 33 | + inline bool | |
| 34 | + is_digit(char ch) | |
| 35 | + { | |
| 36 | + return (ch >= '0' && ch <= '9'); | |
| 37 | + } | |
| 38 | + | |
| 39 | + // Returns lower-case hex-encoded version of the char including a leading "#". | |
| 40 | + inline std::string | |
| 41 | + hex_encode_char(char c) | |
| 42 | + { | |
| 43 | + static auto constexpr hexchars = "0123456789abcdef"; | |
| 44 | + return {'#', hexchars[static_cast<unsigned char>(c) >> 4], hexchars[c & 0x0f]}; | |
| 45 | + } | |
| 46 | + | |
| 47 | +} // namespace qpdf::util | |
| 48 | + | |
| 49 | +#endif // UTIL_HH | ... | ... |