Commit 0b1623d07db963ecf3789aba7163321812cba88e

Authored by Jay Berkenbilt
1 parent f21e4f26

Add QUtil::path_basename

ChangeLog
1 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 5 * Add examples/pdf-attach-file.cc to illustrate new file
4 6 attachment method and also new parse that takes indirect objects.
5 7  
... ...
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&amp; 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 &quot;\n&quot;;
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>
... ...