2018-02-11 20:41:02 +00:00
|
|
|
//
|
|
|
|
// This example illustrates the use of QPDFObjectHandle::TokenFilter with filterContents. See also
|
2020-12-31 18:57:21 +00:00
|
|
|
// pdf-filter-tokens.cc for an example that uses QPDFObjectHandle::TokenFilter with
|
|
|
|
// addContentTokenFilter.
|
2018-02-11 20:41:02 +00:00
|
|
|
//
|
|
|
|
|
2023-05-20 11:22:32 +00:00
|
|
|
#include <cstdlib>
|
2018-02-11 20:41:02 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include <qpdf/Pl_StdioFile.hh>
|
|
|
|
#include <qpdf/QPDF.hh>
|
|
|
|
#include <qpdf/QPDFObjectHandle.hh>
|
2018-06-18 19:06:51 +00:00
|
|
|
#include <qpdf/QPDFPageDocumentHelper.hh>
|
2018-02-11 20:41:02 +00:00
|
|
|
#include <qpdf/QUtil.hh>
|
|
|
|
|
2022-07-26 11:37:50 +00:00
|
|
|
static char const* whoami = nullptr;
|
2018-02-11 20:41:02 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
usage()
|
|
|
|
{
|
|
|
|
std::cerr << "Usage: " << whoami << " infile" << std::endl
|
2022-02-08 14:18:08 +00:00
|
|
|
<< "Applies token filters to infile" << std::endl;
|
2018-02-11 20:41:02 +00:00
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
|
|
|
|
class StringCounter: public QPDFObjectHandle::TokenFilter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
StringCounter() :
|
|
|
|
count(0)
|
|
|
|
{
|
|
|
|
}
|
2023-05-20 13:25:46 +00:00
|
|
|
~StringCounter() override = default;
|
|
|
|
void handleToken(QPDFTokenizer::Token const&) override;
|
|
|
|
void handleEOF() override;
|
2018-02-11 20:41:02 +00:00
|
|
|
int getCount() const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
int count;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
StringCounter::handleToken(QPDFTokenizer::Token const& token)
|
|
|
|
{
|
|
|
|
// Count string tokens
|
|
|
|
if (token.getType() == QPDFTokenizer::tt_string) {
|
|
|
|
++this->count;
|
|
|
|
}
|
|
|
|
// Preserve input verbatim by passing each token to any specified downstream filter.
|
|
|
|
writeToken(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
StringCounter::handleEOF()
|
|
|
|
{
|
|
|
|
// Write a comment at the end of the stream just to show how we can enhance the output if we
|
|
|
|
// want.
|
|
|
|
write("\n% strings found: ");
|
2022-09-21 16:49:21 +00:00
|
|
|
write(std::to_string(this->count));
|
2018-02-11 20:41:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
StringCounter::getCount() const
|
|
|
|
{
|
|
|
|
return this->count;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
whoami = QUtil::getWhoami(argv[0]);
|
|
|
|
|
|
|
|
if (argc != 2) {
|
2022-02-08 14:18:08 +00:00
|
|
|
usage();
|
2018-02-11 20:41:02 +00:00
|
|
|
}
|
|
|
|
char const* infilename = argv[1];
|
|
|
|
|
|
|
|
try {
|
2022-02-08 14:18:08 +00:00
|
|
|
QPDF pdf;
|
|
|
|
pdf.processFile(infilename);
|
2018-02-11 20:41:02 +00:00
|
|
|
int pageno = 0;
|
2022-02-20 16:49:31 +00:00
|
|
|
for (auto& page: QPDFPageDocumentHelper(pdf).getAllPages()) {
|
2018-02-11 20:41:02 +00:00
|
|
|
++pageno;
|
|
|
|
// Pass the contents of a page through our string counter. If it's an even page, capture
|
|
|
|
// the output. This illustrates that you may capture any output generated by the filter,
|
|
|
|
// or you may ignore it.
|
|
|
|
StringCounter counter;
|
|
|
|
if (pageno % 2) {
|
|
|
|
// Ignore output for odd pages.
|
2022-02-20 16:49:31 +00:00
|
|
|
page.filterContents(&counter);
|
2018-02-11 20:41:02 +00:00
|
|
|
} else {
|
|
|
|
// Write output to stdout for even pages.
|
|
|
|
Pl_StdioFile out("stdout", stdout);
|
|
|
|
std::cout << "% Contents of page " << pageno << std::endl;
|
2022-02-20 16:49:31 +00:00
|
|
|
page.filterContents(&counter, &out);
|
2018-02-11 20:41:02 +00:00
|
|
|
std::cout << "\n% end " << pageno << std::endl;
|
|
|
|
}
|
|
|
|
std::cout << "Page " << pageno << ": strings = " << counter.getCount() << std::endl;
|
|
|
|
}
|
|
|
|
} catch (std::exception& e) {
|
2022-02-08 14:18:08 +00:00
|
|
|
std::cerr << whoami << ": " << e.what() << std::endl;
|
|
|
|
exit(2);
|
2018-02-11 20:41:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|