Commit 0b1623d07db963ecf3789aba7163321812cba88e
1 parent
f21e4f26
Add QUtil::path_basename
Showing
6 changed files
with
83 additions
and
4 deletions
ChangeLog
| 1 | 2021-02-18 Jay Berkenbilt <ejb@ql.org> | 1 | 2021-02-18 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | ||
| 3 | + * Add QUtil::path_basename to get last element of a path. | ||
| 4 | + | ||
| 3 | * Add examples/pdf-attach-file.cc to illustrate new file | 5 | * Add examples/pdf-attach-file.cc to illustrate new file |
| 4 | attachment method and also new parse that takes indirect objects. | 6 | attachment method and also new parse that takes indirect objects. |
| 5 | 7 |
include/qpdf/QUtil.hh
| @@ -130,14 +130,22 @@ namespace QUtil | @@ -130,14 +130,22 @@ namespace QUtil | ||
| 130 | // Write the contents of filename as a binary file to the | 130 | // Write the contents of filename as a binary file to the |
| 131 | // pipeline. | 131 | // pipeline. |
| 132 | QPDF_DLL | 132 | QPDF_DLL |
| 133 | - void | ||
| 134 | - pipe_file(char const* filename, Pipeline* p); | 133 | + void pipe_file(char const* filename, Pipeline* p); |
| 135 | 134 | ||
| 136 | // Return a function that will send the contents of the given file | 135 | // Return a function that will send the contents of the given file |
| 137 | // through the given pipeline as binary data. | 136 | // through the given pipeline as binary data. |
| 138 | QPDF_DLL | 137 | QPDF_DLL |
| 139 | - std::function<void(Pipeline*)> | ||
| 140 | - file_provider(std::string const& filename); | 138 | + std::function<void(Pipeline*)> file_provider(std::string const& filename); |
| 139 | + | ||
| 140 | + // Return the last path element. On Windows, either / or \ are | ||
| 141 | + // path separators. Otherwise, only / is a path separator. Strip | ||
| 142 | + // any trailing path separators. Then, if any path separators | ||
| 143 | + // remain, return everything after the last path separator. | ||
| 144 | + // Otherwise, return the whole string. As a special case, if a | ||
| 145 | + // string consists entirely of path separators, the first | ||
| 146 | + // character is returned. | ||
| 147 | + QPDF_DLL | ||
| 148 | + std::string path_basename(std::string const& filename); | ||
| 141 | 149 | ||
| 142 | QPDF_DLL | 150 | QPDF_DLL |
| 143 | char* copy_string(std::string const&); | 151 | char* copy_string(std::string const&); |
libqpdf/QUtil.cc
| @@ -663,6 +663,37 @@ QUtil::file_provider(std::string const& filename) | @@ -663,6 +663,37 @@ QUtil::file_provider(std::string const& filename) | ||
| 663 | }; | 663 | }; |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | +std::string | ||
| 667 | +QUtil::path_basename(std::string const& filename) | ||
| 668 | +{ | ||
| 669 | +#ifdef _WIN32 | ||
| 670 | + char const* pathsep = "/\\"; | ||
| 671 | +#else | ||
| 672 | + char const* pathsep = "/"; | ||
| 673 | +#endif | ||
| 674 | + std::string last = filename; | ||
| 675 | + auto len = last.length(); | ||
| 676 | + while (len > 1) | ||
| 677 | + { | ||
| 678 | + auto pos = last.find_last_of(pathsep); | ||
| 679 | + if (pos == len - 1) | ||
| 680 | + { | ||
| 681 | + last.pop_back(); | ||
| 682 | + --len; | ||
| 683 | + } | ||
| 684 | + else if (pos == std::string::npos) | ||
| 685 | + { | ||
| 686 | + break; | ||
| 687 | + } | ||
| 688 | + else | ||
| 689 | + { | ||
| 690 | + last = last.substr(pos + 1); | ||
| 691 | + break; | ||
| 692 | + } | ||
| 693 | + } | ||
| 694 | + return last; | ||
| 695 | +} | ||
| 696 | + | ||
| 666 | char* | 697 | char* |
| 667 | QUtil::copy_string(std::string const& str) | 698 | QUtil::copy_string(std::string const& str) |
| 668 | { | 699 | { |
libtests/qtest/qutil/qutil.out
| @@ -97,6 +97,13 @@ file1: -qutil.out-, file2: -other-file-; same: 0: PASS | @@ -97,6 +97,13 @@ file1: -qutil.out-, file2: -other-file-; same: 0: PASS | ||
| 97 | file1: -qutil.out-, file2: --; same: 0: PASS | 97 | file1: -qutil.out-, file2: --; same: 0: PASS |
| 98 | file1: -qutil.out-, file2: -(null)-; same: 0: PASS | 98 | file1: -qutil.out-, file2: -(null)-; same: 0: PASS |
| 99 | file1: --, file2: -qutil.out-; same: 0: PASS | 99 | file1: --, file2: -qutil.out-; same: 0: PASS |
| 100 | +---- path | ||
| 101 | +//// -> / | ||
| 102 | +a/b/cdef -> cdef | ||
| 103 | +a/b/cdef/ -> cdef | ||
| 104 | +/ -> / | ||
| 105 | + -> | ||
| 106 | +quack -> quack | ||
| 100 | ---- read from file | 107 | ---- read from file |
| 101 | This file is used for qutil testing. | 108 | This file is used for qutil testing. |
| 102 | It has mixed newlines. | 109 | It has mixed newlines. |
libtests/qutil.cc
| @@ -439,6 +439,29 @@ void same_file_test() | @@ -439,6 +439,29 @@ void same_file_test() | ||
| 439 | assert_same_file("", "qutil.out", false); | 439 | assert_same_file("", "qutil.out", false); |
| 440 | } | 440 | } |
| 441 | 441 | ||
| 442 | +void path_test() | ||
| 443 | +{ | ||
| 444 | + auto check = [](bool print, std::string const& a, std::string const& b) { | ||
| 445 | + auto result = QUtil::path_basename(a); | ||
| 446 | + if (print) | ||
| 447 | + { | ||
| 448 | + std::cout << a << " -> " << result << std::endl; | ||
| 449 | + } | ||
| 450 | + assert(result == b); | ||
| 451 | + }; | ||
| 452 | + | ||
| 453 | +#ifdef _WIN32 | ||
| 454 | + check(false, "asdf\\qwer", "qwer"); | ||
| 455 | + check(false, "asdf\\qwer/\\", "qwer"); | ||
| 456 | +#endif | ||
| 457 | + check(true, "////", "/"); | ||
| 458 | + check(true, "a/b/cdef", "cdef"); | ||
| 459 | + check(true, "a/b/cdef/", "cdef"); | ||
| 460 | + check(true, "/", "/"); | ||
| 461 | + check(true, "", ""); | ||
| 462 | + check(true, "quack", "quack"); | ||
| 463 | +} | ||
| 464 | + | ||
| 442 | void read_from_file_test() | 465 | void read_from_file_test() |
| 443 | { | 466 | { |
| 444 | std::list<std::string> lines = QUtil::read_lines_from_file("other-file"); | 467 | std::list<std::string> lines = QUtil::read_lines_from_file("other-file"); |
| @@ -636,6 +659,8 @@ int main(int argc, char* argv[]) | @@ -636,6 +659,8 @@ int main(int argc, char* argv[]) | ||
| 636 | get_whoami_test(); | 659 | get_whoami_test(); |
| 637 | std::cout << "---- file" << std::endl; | 660 | std::cout << "---- file" << std::endl; |
| 638 | same_file_test(); | 661 | same_file_test(); |
| 662 | + std::cout << "---- path" << std::endl; | ||
| 663 | + path_test(); | ||
| 639 | std::cout << "---- read from file" << std::endl; | 664 | std::cout << "---- read from file" << std::endl; |
| 640 | read_from_file_test(); | 665 | read_from_file_test(); |
| 641 | std::cout << "---- hex encode/decode" << std::endl; | 666 | std::cout << "---- hex encode/decode" << std::endl; |
manual/qpdf-manual.xml
| @@ -5283,6 +5283,12 @@ print "\n"; | @@ -5283,6 +5283,12 @@ print "\n"; | ||
| 5283 | matrices. | 5283 | matrices. |
| 5284 | </para> | 5284 | </para> |
| 5285 | </listitem> | 5285 | </listitem> |
| 5286 | + <listitem> | ||
| 5287 | + <para> | ||
| 5288 | + Add <function>QUtil::path_basename</function> to return the | ||
| 5289 | + last element of a path. | ||
| 5290 | + </para> | ||
| 5291 | + </listitem> | ||
| 5286 | </itemizedlist> | 5292 | </itemizedlist> |
| 5287 | </listitem> | 5293 | </listitem> |
| 5288 | <listitem> | 5294 | <listitem> |