Commit 0b1623d07db963ecf3789aba7163321812cba88e
1 parent
f21e4f26
Add QUtil::path_basename
Showing
6 changed files
with
83 additions
and
4 deletions
ChangeLog
include/qpdf/QUtil.hh
| ... | ... | @@ -130,14 +130,22 @@ namespace QUtil |
| 130 | 130 | // Write the contents of filename as a binary file to the |
| 131 | 131 | // pipeline. |
| 132 | 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 | 135 | // Return a function that will send the contents of the given file |
| 137 | 136 | // through the given pipeline as binary data. |
| 138 | 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 | 150 | QPDF_DLL |
| 143 | 151 | char* copy_string(std::string const&); | ... | ... |
libqpdf/QUtil.cc
| ... | ... | @@ -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 | 697 | char* |
| 667 | 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 | 97 | file1: -qutil.out-, file2: --; same: 0: PASS |
| 98 | 98 | file1: -qutil.out-, file2: -(null)-; same: 0: PASS |
| 99 | 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 | 107 | ---- read from file |
| 101 | 108 | This file is used for qutil testing. |
| 102 | 109 | It has mixed newlines. | ... | ... |
libtests/qutil.cc
| ... | ... | @@ -439,6 +439,29 @@ void same_file_test() |
| 439 | 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 | 465 | void read_from_file_test() |
| 443 | 466 | { |
| 444 | 467 | std::list<std::string> lines = QUtil::read_lines_from_file("other-file"); |
| ... | ... | @@ -636,6 +659,8 @@ int main(int argc, char* argv[]) |
| 636 | 659 | get_whoami_test(); |
| 637 | 660 | std::cout << "---- file" << std::endl; |
| 638 | 661 | same_file_test(); |
| 662 | + std::cout << "---- path" << std::endl; | |
| 663 | + path_test(); | |
| 639 | 664 | std::cout << "---- read from file" << std::endl; |
| 640 | 665 | read_from_file_test(); |
| 641 | 666 | std::cout << "---- hex encode/decode" << std::endl; | ... | ... |
manual/qpdf-manual.xml
| ... | ... | @@ -5283,6 +5283,12 @@ print "\n"; |
| 5283 | 5283 | matrices. |
| 5284 | 5284 | </para> |
| 5285 | 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 | 5292 | </itemizedlist> |
| 5287 | 5293 | </listitem> |
| 5288 | 5294 | <listitem> | ... | ... |