Commit 67edbfd954a4249d6c78bd375294e4a5bbde3846

Authored by m-holger
1 parent fa8dd266

Un-inline QUtil functions

Add new private Util.hh header to define inline functions and expose as
ordinary functions in QUtil.
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&amp; line, int&amp; obj, int&amp; num, int&amp; 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&amp; f1, int&amp; f2, char&amp; 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&amp; f1, int&amp; f2, char&amp; 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&amp; f1, int&amp; f2, char&amp; 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&amp; 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&amp; 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&amp; 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&amp; v, int&amp; obj, int&amp; 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&amp; v, int&amp; obj, int&amp; 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&amp; v, std::string&amp; 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&amp; 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
... ...