diff options
Diffstat (limited to 'libqpdf')
106 files changed, 1061 insertions, 1414 deletions
diff --git a/libqpdf/Buffer.cc b/libqpdf/Buffer.cc index ae04fbc8..3dddd5db 100644 --- a/libqpdf/Buffer.cc +++ b/libqpdf/Buffer.cc @@ -1,7 +1,20 @@ +#include <qpdf/assert_test.h> + #include <qpdf/Buffer.hh> #include <cstring> +bool test_mode = false; + +// During CI the Buffer copy constructor and copy assignment operator throw an assertion error to +// detect their accidental use. Call setTestMode to surpress the assertion errors for testing of +// copy construction and assignment. +void +Buffer::setTestMode() noexcept +{ + test_mode = true; +} + Buffer::Members::Members(size_t size, unsigned char* buf, bool own_memory) : own_memory(own_memory), size(size), @@ -38,12 +51,14 @@ Buffer::Buffer(unsigned char* buf, size_t size) : Buffer::Buffer(Buffer const& rhs) { + assert(test_mode); copy(rhs); } Buffer& Buffer::operator=(Buffer const& rhs) { + assert(test_mode); copy(rhs); return *this; } @@ -88,3 +103,13 @@ Buffer::getBuffer() { return m->buf; } + +Buffer +Buffer::copy() const +{ + auto result = Buffer(m->size); + if (m->size) { + memcpy(result.m->buf, m->buf, m->size); + } + return result; +} diff --git a/libqpdf/ClosedFileInputSource.cc b/libqpdf/ClosedFileInputSource.cc index 06ebb156..2a6cb897 100644 --- a/libqpdf/ClosedFileInputSource.cc +++ b/libqpdf/ClosedFileInputSource.cc @@ -9,10 +9,9 @@ ClosedFileInputSource::ClosedFileInputSource(char const* filename) : { } -ClosedFileInputSource::~ClosedFileInputSource() +ClosedFileInputSource::~ClosedFileInputSource() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void @@ -91,8 +90,7 @@ ClosedFileInputSource::unreadCh(char ch) { before(); this->fis->unreadCh(ch); - // Don't call after -- the file has to stay open after this - // operation. + // Don't call after -- the file has to stay open after this operation. } void diff --git a/libqpdf/ContentNormalizer.cc b/libqpdf/ContentNormalizer.cc index b05b4220..47830f42 100644 --- a/libqpdf/ContentNormalizer.cc +++ b/libqpdf/ContentNormalizer.cc @@ -41,9 +41,8 @@ ContentNormalizer::handleToken(QPDFTokenizer::Token const& token) break; case QPDFTokenizer::tt_string: - // Replacing string and name tokens in this way normalizes - // their representation as this will automatically handle - // quoting of unprintable characters, etc. + // Replacing string and name tokens in this way normalizes their representation as this will + // automatically handle quoting of unprintable characters, etc. writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, token.getValue())); break; diff --git a/libqpdf/FileInputSource.cc b/libqpdf/FileInputSource.cc index 0e0cfa50..ec6e84be 100644 --- a/libqpdf/FileInputSource.cc +++ b/libqpdf/FileInputSource.cc @@ -27,8 +27,7 @@ FileInputSource::FileInputSource(char const* description, FILE* filep, bool clos FileInputSource::~FileInputSource() { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer if (this->file && this->close_file) { fclose(this->file); } @@ -68,8 +67,7 @@ FileInputSource::findAndSkipNextEOL() char* p = (p1 && p2) ? std::min(p1, p2) : p1 ? p1 : p2; if (p) { result = cur_offset + (p - buf); - // We found \r or \n. Keep reading until we get past - // \r and \n characters. + // We found \r or \n. Keep reading until we get past \r and \n characters. this->seek(result + 1, SEEK_SET); char ch; while (!done) { diff --git a/libqpdf/InputSource.cc b/libqpdf/InputSource.cc index 597781fe..9389c2f5 100644 --- a/libqpdf/InputSource.cc +++ b/libqpdf/InputSource.cc @@ -20,12 +20,10 @@ InputSource::getLastOffset() const std::string InputSource::readLine(size_t max_line_length) { - // Return at most max_line_length characters from the next line. - // Lines are terminated by one or more \r or \n characters. - // Consume the trailing newline characters but don't return them. - // After this is called, the file will be positioned after a line - // terminator or at the end of the file, and last_offset will - // point to position the file had when this method was called. + // Return at most max_line_length characters from the next line. Lines are terminated by one or + // more \r or \n characters. Consume the trailing newline characters but don't return them. + // After this is called, the file will be positioned after a line terminator or at the end of + // the file, and last_offset will point to position the file had when this method was called. qpdf_offset_t offset = this->tell(); auto bp = std::make_unique<char[]>(max_line_length + 1); @@ -39,28 +37,24 @@ InputSource::readLine(size_t max_line_length) if (line_length < max_line_length) { buf[line_length] = '\0'; } - return std::string(buf); + return {buf}; } bool InputSource::findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder) { - // Basic approach: search for the first character of start_chars - // starting from offset but not going past len (if len != 0). Once - // the first character is found, see if it is the beginning of a - // sequence of characters matching start_chars. If so, call - // finder.check() to do caller-specific additional checks. If not, - // keep searching. + // Basic approach: search for the first character of start_chars starting from offset but not + // going past len (if len != 0). Once the first character is found, see if it is the beginning + // of a sequence of characters matching start_chars. If so, call finder.check() to do + // caller-specific additional checks. If not, keep searching. - // This code is tricky and highly subject to off-by-one or other - // edge case logic errors. See comments throughout that explain - // how we're not missing any edge cases. There are also tests - // specifically constructed to make sure we caught the edge cases - // in testing. + // This code is tricky and highly subject to off-by-one or other edge case logic errors. See + // comments throughout that explain how we're not missing any edge cases. There are also tests + // specifically constructed to make sure we caught the edge cases in testing. char buf[1025]; // size known to input_source.cc in libtests - // To enable us to guarantee null-termination, save an extra byte - // so that buf[size] is valid memory. + // To enable us to guarantee null-termination, save an extra byte so that buf[size] is valid + // memory. size_t size = sizeof(buf) - 1; if ((strlen(start_chars) < 1) || (strlen(start_chars) > size)) { throw std::logic_error("InputSource::findSource called with" @@ -71,19 +65,15 @@ InputSource::findFirst(char const* start_chars, qpdf_offset_t offset, size_t len qpdf_offset_t buf_offset = offset; size_t bytes_read = 0; - // Guarantee that we return from this loop. Each time through, we - // either return, advance p, or restart the loop with a condition - // that will cause return on the next pass. Eventually we will - // either be out of range or hit EOF, either of which forces us to - // return. + // Guarantee that we return from this loop. Each time through, we either return, advance p, or + // restart the loop with a condition that will cause return on the next pass. Eventually we will + // either be out of range or hit EOF, either of which forces us to return. while (true) { - // Do we need to read more data? Pretend size = 5, buf starts - // at 0, and start_chars has 3 characters. buf[5] is valid and - // null. If p == 2, start_chars could be buf[2] through - // buf[4], so p + strlen(start_chars) == buf + size is okay. - // If p points to buf[size], since strlen(start_chars) is - // always >= 1, this overflow test will be correct for that - // case regardless of start_chars. + // Do we need to read more data? Pretend size = 5, buf starts at 0, and start_chars has 3 + // characters. buf[5] is valid and null. If p == 2, start_chars could be buf[2] through + // buf[4], so p + strlen(start_chars) == buf + size is okay. If p points to buf[size], since + // strlen(start_chars) is always >= 1, this overflow test will be correct for that case + // regardless of start_chars. if ((p == nullptr) || ((p + strlen(start_chars)) > (buf + bytes_read))) { if (p) { QTC::TC( @@ -91,9 +81,8 @@ InputSource::findFirst(char const* start_chars, qpdf_offset_t offset, size_t len buf_offset += (p - buf); } this->seek(buf_offset, SEEK_SET); - // Read into buffer and zero out the rest of the buffer - // including buf[size]. We allocated an extra byte so that - // we could guarantee null termination as an extra + // Read into buffer and zero out the rest of the buffer including buf[size]. We + // allocated an extra byte so that we could guarantee null termination as an extra // protection against overrun when using string functions. bytes_read = this->read(buf, size); if (bytes_read < strlen(start_chars)) { @@ -122,19 +111,16 @@ InputSource::findFirst(char const* start_chars, qpdf_offset_t offset, size_t len } } if ((p + strlen(start_chars)) > (buf + bytes_read)) { - // If there are not enough bytes left in the file for - // start_chars, we will detect this on the next pass - // as EOF and return. + // If there are not enough bytes left in the file for start_chars, we will detect + // this on the next pass as EOF and return. QTC::TC("libtests", "InputSource not enough bytes"); continue; } - // See if p points to a sequence matching start_chars. We - // already checked above to make sure we are not going to - // overrun memory. + // See if p points to a sequence matching start_chars. We already checked above to make + // sure we are not going to overrun memory. if (strncmp(p, start_chars, strlen(start_chars)) == 0) { - // Call finder.check() with the input source - // positioned to the point of the match. + // Call finder.check() with the input source positioned to the point of the match. this->seek(buf_offset + (p - buf), SEEK_SET); if (finder.check()) { return true; @@ -144,8 +130,8 @@ InputSource::findFirst(char const* start_chars, qpdf_offset_t offset, size_t len } else { QTC::TC("libtests", "InputSource first char matched but not string"); } - // This occurrence of the first character wasn't a match. - // Skip over it and keep searching. + // This occurrence of the first character wasn't a match. Skip over it and keep + // searching. ++p; } else { // Trigger reading the next block diff --git a/libqpdf/InsecureRandomDataProvider.cc b/libqpdf/InsecureRandomDataProvider.cc index 5f247167..1c7fb9ef 100644 --- a/libqpdf/InsecureRandomDataProvider.cc +++ b/libqpdf/InsecureRandomDataProvider.cc @@ -21,9 +21,8 @@ long InsecureRandomDataProvider::random() { if (!this->seeded_random) { - // Seed the random number generator with something simple, but - // just to be interesting, don't use the unmodified current - // time. It would be better if this were a more secure seed. + // Seed the random number generator with something simple, but just to be interesting, don't + // use the unmodified current time. It would be better if this were a more secure seed. auto seed = static_cast<unsigned int>(QUtil::get_current_time() ^ 0xcccc); #ifdef HAVE_RANDOM ::srandom(seed); diff --git a/libqpdf/JSON.cc b/libqpdf/JSON.cc index a11d06f2..f6401642 100644 --- a/libqpdf/JSON.cc +++ b/libqpdf/JSON.cc @@ -269,7 +269,7 @@ JSON::encode_string(std::string const& str) JSON JSON::makeDictionary() { - return JSON(std::make_unique<JSON_dictionary>()); + return {std::make_unique<JSON_dictionary>()}; } JSON @@ -299,7 +299,7 @@ JSON::checkDictionaryKeySeen(std::string const& key) JSON JSON::makeArray() { - return JSON(std::make_unique<JSON_array>()); + return {std::make_unique<JSON_array>()}; } JSON @@ -320,43 +320,43 @@ JSON::addArrayElement(JSON const& val) JSON JSON::makeString(std::string const& utf8) { - return JSON(std::make_unique<JSON_string>(utf8)); + return {std::make_unique<JSON_string>(utf8)}; } JSON JSON::makeInt(long long int value) { - return JSON(std::make_unique<JSON_number>(value)); + return {std::make_unique<JSON_number>(value)}; } JSON JSON::makeReal(double value) { - return JSON(std::make_unique<JSON_number>(value)); + return {std::make_unique<JSON_number>(value)}; } JSON JSON::makeNumber(std::string const& encoded) { - return JSON(std::make_unique<JSON_number>(encoded)); + return {std::make_unique<JSON_number>(encoded)}; } JSON JSON::makeBool(bool value) { - return JSON(std::make_unique<JSON_bool>(value)); + return {std::make_unique<JSON_bool>(value)}; } JSON JSON::makeNull() { - return JSON(std::make_unique<JSON_null>()); + return {std::make_unique<JSON_null>()}; } JSON JSON::makeBlob(std::function<void(Pipeline*)> fn) { - return JSON(std::make_unique<JSON_blob>(fn)); + return {std::make_unique<JSON_blob>(fn)}; } bool @@ -588,14 +588,7 @@ namespace JSONParser(InputSource& is, JSON::Reactor* reactor) : is(is), reactor(reactor), - lex_state(ls_top), - bytes(0), - p(buf), - u_count(0), - offset(0), - done(false), - parser_state(ps_top), - dict_key_offset(0) + p(buf) { } @@ -665,20 +658,20 @@ namespace InputSource& is; JSON::Reactor* reactor; - lex_state_e lex_state; + lex_state_e lex_state{ls_top}; char buf[16384]; - size_t bytes; + size_t bytes{0}; char const* p; - qpdf_offset_t u_count; + qpdf_offset_t u_count{0}; unsigned long u_value{0}; - qpdf_offset_t offset; - bool done; + qpdf_offset_t offset{0}; + bool done{false}; std::string token; qpdf_offset_t token_start{0}; - parser_state_e parser_state; + parser_state_e parser_state{ps_top}; std::vector<StackFrame> stack; std::string dict_key; - qpdf_offset_t dict_key_offset; + qpdf_offset_t dict_key_offset{0}; }; } // namespace @@ -1282,7 +1275,7 @@ JSONParser::handleToken() case ps_top: if (!(item.isDictionary() || item.isArray())) { - stack.push_back({ps_done, item}); + stack.emplace_back(ps_done, item); parser_state = ps_done; return; } @@ -1311,7 +1304,7 @@ JSONParser::handleToken() } if (item.isDictionary() || item.isArray()) { - stack.push_back({parser_state, item}); + stack.emplace_back(parser_state, item); // Calling container start method is postponed until after adding the containers to their // parent containers, if any. This makes it much easier to keep track of the current nesting // level. diff --git a/libqpdf/JSONHandler.cc b/libqpdf/JSONHandler.cc index f4360a2d..4a69fd60 100644 --- a/libqpdf/JSONHandler.cc +++ b/libqpdf/JSONHandler.cc @@ -4,11 +4,48 @@ #include <qpdf/QTC.hh> #include <qpdf/QUtil.hh> +struct Handlers +{ + Handlers() = default; + + JSONHandler::json_handler_t any_handler{nullptr}; + JSONHandler::void_handler_t null_handler{nullptr}; + JSONHandler::string_handler_t string_handler{nullptr}; + JSONHandler::string_handler_t number_handler{nullptr}; + JSONHandler::bool_handler_t bool_handler{nullptr}; + JSONHandler::json_handler_t dict_start_handler{nullptr}; + JSONHandler::void_handler_t dict_end_handler{nullptr}; + JSONHandler::json_handler_t array_start_handler{nullptr}; + JSONHandler::void_handler_t array_end_handler{nullptr}; + JSONHandler::void_handler_t final_handler{nullptr}; + std::map<std::string, std::shared_ptr<JSONHandler>> dict_handlers; + std::shared_ptr<JSONHandler> fallback_dict_handler; + std::shared_ptr<JSONHandler> array_item_handler; +}; + +class JSONHandler::Members +{ + friend class JSONHandler; + + public: + ~Members() = default; + + private: + Members() = default; + Members(Members const&) = delete; + + Handlers h; +}; + JSONHandler::JSONHandler() : m(new Members()) { } +JSONHandler::~JSONHandler() +{ +} + void JSONHandler::usage(std::string const& msg) { @@ -80,24 +117,24 @@ JSONHandler::handle(std::string const& path, JSON j) m->h.any_handler(path, j); return; } - bool handled = false; + bool bvalue = false; std::string s_value; if (m->h.null_handler && j.isNull()) { m->h.null_handler(path); - handled = true; + return; } if (m->h.string_handler && j.getString(s_value)) { m->h.string_handler(path, s_value); - handled = true; + return; } if (m->h.number_handler && j.getNumber(s_value)) { m->h.number_handler(path, s_value); - handled = true; + return; } if (m->h.bool_handler && j.getBool(bvalue)) { m->h.bool_handler(path, bvalue); - handled = true; + return; } if (m->h.dict_start_handler && j.isDictionary()) { m->h.dict_start_handler(path, j); @@ -119,7 +156,7 @@ JSONHandler::handle(std::string const& path, JSON j) } }); m->h.dict_end_handler(path); - handled = true; + return; } if (m->h.array_start_handler && j.isArray()) { m->h.array_start_handler(path, j); @@ -129,17 +166,13 @@ JSONHandler::handle(std::string const& path, JSON j) ++i; }); m->h.array_end_handler(path); - handled = true; + return; } - if (!handled) { - // It would be nice to include information about what type the - // object was and what types were allowed, but we're relying - // on schema validation to make sure input is properly - // structured before calling the handlers. It would be - // different if this code were trying to be part of a - // general-purpose JSON package. - QTC::TC("libtests", "JSONHandler unhandled value"); - usage("JSON handler: value at " + path + " is not of expected type"); - } + // It would be nice to include information about what type the object was and what types were + // allowed, but we're relying on schema validation to make sure input is properly structured + // before calling the handlers. It would be different if this code were trying to be part of a + // general-purpose JSON package. + QTC::TC("libtests", "JSONHandler unhandled value"); + usage("JSON handler: value at " + path + " is not of expected type"); } diff --git a/libqpdf/MD5.cc b/libqpdf/MD5.cc index c0782124..b8e07cf9 100644 --- a/libqpdf/MD5.cc +++ b/libqpdf/MD5.cc @@ -78,8 +78,7 @@ MD5::encodeFile(char const* filename, qpdf_offset_t up_to_offset) } } while (len > 0); if (ferror(file)) { - // Assume, perhaps incorrectly, that errno was set by the - // underlying call to read.... + // Assume, perhaps incorrectly, that errno was set by the underlying call to read.... (void)fclose(file); QUtil::throw_system_error(std::string("MD5: read error on ") + filename); } diff --git a/libqpdf/NNTree.cc b/libqpdf/NNTree.cc index bbdd83f8..fa054794 100644 --- a/libqpdf/NNTree.cc +++ b/libqpdf/NNTree.cc @@ -36,23 +36,18 @@ NNTreeIterator::NNTreeIterator(NNTreeImpl& impl) : void NNTreeIterator::updateIValue(bool allow_invalid) { - // ivalue should never be used inside the class since we return a - // pointer/reference to it. Every bit of code that ever changes - // what object the iterator points to should take care to call - // updateIValue. Failure to do this means that any old references - // to *iter will point to incorrect objects, though the next - // dereference of the iterator will fix it. This isn't necessarily - // catastrophic, but it would be confusing. The test suite - // attempts to exercise various cases to ensure we don't introduce - // that bug in the future, but sadly it's tricky to verify by - // reasoning about the code that this constraint is always - // satisfied. Whenever we update what the iterator points to, we - // should call setItemNumber, which calls this. If we change what - // the iterator in some other way, such as replacing a value or - // removing an item and making the iterator point at a different - // item in potentially the same position, we must call - // updateIValue as well. These cases are handled, and for good - // measure, we also call updateIValue in operator* and operator->. + // ivalue should never be used inside the class since we return a pointer/reference to it. Every + // bit of code that ever changes what object the iterator points to should take care to call + // updateIValue. Failure to do this means that any old references to *iter will point to + // incorrect objects, though the next dereference of the iterator will fix it. This isn't + // necessarily catastrophic, but it would be confusing. The test suite attempts to exercise + // various cases to ensure we don't introduce that bug in the future, but sadly it's tricky to + // verify by reasoning about the code that this constraint is always satisfied. Whenever we + // update what the iterator points to, we should call setItemNumber, which calls this. If we + // change what the iterator points to in some other way, such as replacing a value or removing + // an item and making the iterator point at a different item in potentially the same position, + // we must call updateIValue as well. These cases are handled, and for good measure, we also + // call updateIValue in operator* and operator->. bool okay = false; if ((item_number >= 0) && this->node.isDictionary()) { @@ -228,12 +223,11 @@ NNTreeIterator::resetLimits(QPDFObjectHandle node, std::list<PathElement>::itera void NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterator parent) { - // Split some node along the path to the item pointed to by this - // iterator, and adjust the iterator so it points to the same - // item. + // Split some node along the path to the item pointed to by this iterator, and adjust the + // iterator so it points to the same item. - // In examples, for simplicity, /Nums is show to just contain - // numbers instead of pairs. Imagine this tree: + // In examples, for simplicity, /Nums is shown to just contain numbers instead of pairs. Imagine + // this tree: // // root: << /Kids [ A B C D ] >> // A: << /Nums [ 1 2 3 4 ] >> @@ -260,8 +254,7 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato throw std::logic_error("NNTreeIterator::split called an invalid iterator"); } - // Find the array we actually need to split, which is either this - // node's kids or items. + // Find the array we actually need to split, which is either this node's kids or items. auto kids = to_split.getKey("/Kids"); int nkids = kids.isArray() ? kids.getArrayNItems() : 0; auto items = to_split.getKey(impl.details.itemsKey()); @@ -294,30 +287,22 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato bool is_root = (parent == this->path.end()); bool is_leaf = (nitems > 0); - // CURRENT STATE: tree is in original state; iterator is valid and - // unchanged. + // CURRENT STATE: tree is in original state; iterator is valid and unchanged. if (is_root) { - // What we want to do is to create a new node for the second - // half of the items and put it in the parent's /Kids array - // right after the element that points to the current to_split - // node, but if we're splitting root, there is no parent, so - // handle that first. - - // In the non-root case, parent points to the path element - // whose /Kids contains the first half node, and the first - // half node is to_split. If we are splitting the root, we - // need to push everything down a level, but we want to keep - // the actual root object the same so that indirect references - // to it remain intact (and also in case it might be a direct - // object, which it shouldn't be but that case probably exists - // in the wild). To achieve this, we create a new node for the - // first half and then replace /Kids in the root to contain - // it. Then we adjust the path so that the first element is - // root and the second element, if any, is the new first half. - // In this way, we make the root case identical to the - // non-root case so remaining logic can handle them in the - // same way. + // What we want to do is to create a new node for the second half of the items and put it in + // the parent's /Kids array right after the element that points to the current to_split + // node, but if we're splitting root, there is no parent, so handle that first. + + // In the non-root case, parent points to the path element whose /Kids contains the first + // half node, and the first half node is to_split. If we are splitting the root, we need to + // push everything down a level, but we want to keep the actual root object the same so that + // indirect references to it remain intact (and also in case it might be a direct object, + // which it shouldn't be but that case probably exists in the wild). To achieve this, we + // create a new node for the first half and then replace /Kids in the root to contain it. + // Then we adjust the path so that the first element is root and the second element, if any, + // is the new first half. In this way, we make the root case identical to the non-root case + // so remaining logic can handle them in the same way. auto first_node = impl.qpdf.makeIndirectObject(QPDFObjectHandle::newDictionary()); first_node.replaceKey(key, first_half); @@ -334,17 +319,16 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato auto next = this->path.begin(); next->node = first_node; } - this->path.push_front(PathElement(to_split, 0)); + this->path.emplace_front(to_split, 0); parent = this->path.begin(); to_split = first_node; } - // CURRENT STATE: parent is guaranteed to be defined, and we have - // the invariants that parent[/Kids][kid_number] == to_split and - // (++parent).node == to_split. + // CURRENT STATE: parent is guaranteed to be defined, and we have the invariants that + // parent[/Kids][kid_number] == to_split and (++parent).node == to_split. - // Create a second half array, and transfer the second half of the - // items into the second half array. + // Create a second half array, and transfer the second half of the items into the second half + // array. QPDFObjectHandle second_half = QPDFObjectHandle::newArray(); int start_idx = ((n / 2) & ~1); while (first_half.getArrayNItems() > start_idx) { @@ -358,15 +342,13 @@ NNTreeIterator::split(QPDFObjectHandle to_split, std::list<PathElement>::iterato second_node.replaceKey(key, second_half); resetLimits(second_node, parent); - // CURRENT STATE: half the items from the kids or items array in - // the node being split have been moved into a new node. The new - // node is not yet attached to the tree. The iterator may have a + // CURRENT STATE: half the items from the kids or items array in the node being split have been + // moved into a new node. The new node is not yet attached to the tree. The iterator may have a // path element or leaf node that is out of bounds. - // We need to adjust the parent to add the second node to /Kids - // and, if needed, update kid_number to traverse through it. We - // need to update to_split's path element, or the node if this is - // a leaf, so that the kid/item number points to the right place. + // We need to adjust the parent to add the second node to /Kids and, if needed, update + // kid_number to traverse through it. We need to update to_split's path element, or the node if + // this is a leaf, so that the kid/item number points to the right place. auto parent_kids = parent->node.getKey("/Kids"); parent_kids.insertItem(parent->kid_number + 1, second_node); @@ -430,8 +412,7 @@ NNTreeIterator::insertAfter(QPDFObjectHandle key, QPDFObjectHandle value) void NNTreeIterator::remove() { - // Remove this item, leaving the tree valid and this iterator - // pointing to the next item. + // Remove this item, leaving the tree valid and this iterator pointing to the next item. if (!valid()) { throw std::logic_error("attempt made to remove an invalid iterator"); @@ -450,34 +431,32 @@ NNTreeIterator::remove() // There are still items left if ((this->item_number == 0) || (this->item_number == nitems)) { - // We removed either the first or last item of an items array - // that remains non-empty, so we have to adjust limits. + // We removed either the first or last item of an items array that remains non-empty, so + // we have to adjust limits. QTC::TC("qpdf", "NNTree remove reset limits"); resetLimits(this->node, lastPathElement()); } if (this->item_number == nitems) { - // We removed the last item of a non-empty items array, so - // advance to the successor of the previous item. + // We removed the last item of a non-empty items array, so advance to the successor of + // the previous item. QTC::TC("qpdf", "NNTree erased last item"); this->item_number -= 2; increment(false); } else if (this->item_number < nitems) { - // We don't have to do anything since the removed item's - // successor now occupies its former location. + // We don't have to do anything since the removed item's successor now occupies its + // former location. QTC::TC("qpdf", "NNTree erased non-last item"); updateIValue(); } else { - // We already checked to ensure this condition would not - // happen. + // We already checked to ensure this condition would not happen. throw std::logic_error("NNTreeIterator::remove: item_number > nitems after erase"); } return; } if (this->path.empty()) { - // Special case: if this is the root node, we can leave it - // empty. + // Special case: if this is the root node, we can leave it empty. QTC::TC("qpdf", "NNTree erased all items on leaf/root"); setItemNumber(impl.oh, -1); return; @@ -485,9 +464,8 @@ NNTreeIterator::remove() QTC::TC("qpdf", "NNTree items is empty after remove"); - // We removed the last item from this items array, so we need to - // remove this node from the parent on up the tree. Then we need - // to position ourselves at the removed item's successor. + // We removed the last item from this items array, so we need to remove this node from the + // parent on up the tree. Then we need to position ourselves at the removed item's successor. bool done = false; while (!done) { auto element = lastPathElement(); @@ -503,8 +481,7 @@ NNTreeIterator::remove() resetLimits(element->node, parent); } if (element->kid_number == nkids) { - // Move to the successor of the last child of the - // previous kid. + // Move to the successor of the last child of the previous kid. setItemNumber(QPDFObjectHandle(), -1); --element->kid_number; deepen(kids.getArrayItem(element->kid_number), false, true); @@ -523,8 +500,7 @@ NNTreeIterator::remove() } done = true; } else if (parent == this->path.end()) { - // We erased the very last item. Convert the root to an - // empty items array. + // We erased the very last item. Convert the root to an empty items array. QTC::TC("qpdf", "NNTree non-flat tree is empty after remove"); element->node.removeKey("/Kids"); element->node.replaceKey(impl.details.itemsKey(), QPDFObjectHandle::newArray()); @@ -602,21 +578,20 @@ NNTreeIterator::setItemNumber(QPDFObjectHandle const& node, int n) void NNTreeIterator::addPathElement(QPDFObjectHandle const& node, int kid_number) { - this->path.push_back(PathElement(node, kid_number)); + this->path.emplace_back(node, kid_number); } bool NNTreeIterator::deepen(QPDFObjectHandle node, bool first, bool allow_empty) { - // Starting at this node, descend through the first or last kid - // until we reach a node with items. If we succeed, return true; - // otherwise return false and leave path alone. + // Starting at this node, descend through the first or last kid until we reach a node with + // items. If we succeed, return true; otherwise return false and leave path alone. auto opath = this->path; bool failed = false; QPDFObjGen::set seen; - for (auto i: this->path) { + for (auto const& i: this->path) { seen.add(i.node); } while (!failed) { @@ -714,7 +689,7 @@ NNTreeImpl::begin() NNTreeImpl::iterator NNTreeImpl::end() { - return iterator(*this); + return {*this}; } NNTreeImpl::iterator diff --git a/libqpdf/Pl_AES_PDF.cc b/libqpdf/Pl_AES_PDF.cc index a71052a5..e1a3ea33 100644 --- a/libqpdf/Pl_AES_PDF.cc +++ b/libqpdf/Pl_AES_PDF.cc @@ -98,9 +98,8 @@ Pl_AES_PDF::finish() flush(false); } if (!this->disable_padding) { - // Pad as described in section 3.5.1 of version 1.7 of the PDF - // specification, including providing an entire block of padding - // if the input was a multiple of 16 bytes. + // Pad as described in section 3.5.1 of version 1.7 of the PDF specification, including + // providing an entire block of padding if the input was a multiple of 16 bytes. unsigned char pad = QIntC::to_uchar(this->buf_size - this->offset); memset(this->inbuf + this->offset, pad, pad); this->offset = this->buf_size; @@ -108,11 +107,9 @@ Pl_AES_PDF::finish() } } else { if (this->offset != this->buf_size) { - // This is never supposed to happen as the output is - // always supposed to be padded. However, we have - // encountered files for which the output is not a - // multiple of the block size. In this case, pad with - // zeroes and hope for the best. + // This is never supposed to happen as the output is always supposed to be padded. + // However, we have encountered files for which the output is not a multiple of the + // block size. In this case, pad with zeroes and hope for the best. if (this->offset >= this->buf_size) { throw std::logic_error("buffer overflow in AES encryption" " pipeline"); @@ -156,19 +153,19 @@ Pl_AES_PDF::flush(bool strip_padding) bool return_after_init = false; if (this->cbc_mode) { if (encrypt) { - // Set cbc_block to the initialization vector, and if - // not zero, write it to the output stream. + // Set cbc_block to the initialization vector, and if not zero, write it to the + // output stream. initializeVector(); if (!(this->use_zero_iv || this->use_specified_iv)) { getNext()->write(this->cbc_block, this->buf_size); } } else if (this->use_zero_iv || this->use_specified_iv) { - // Initialize vector with zeroes; zero vector was not - // written to the beginning of the input file. + // Initialize vector with zeroes; zero vector was not written to the beginning of + // the input file. initializeVector(); } else { - // Take the first block of input as the initialization - // vector. There's nothing to write at this time. + // Take the first block of input as the initialization vector. There's nothing to + // write at this time. memcpy(this->cbc_block, this->inbuf, this->buf_size); this->offset = 0; return_after_init = true; diff --git a/libqpdf/Pl_ASCII85Decoder.cc b/libqpdf/Pl_ASCII85Decoder.cc index e789a753..fd36722a 100644 --- a/libqpdf/Pl_ASCII85Decoder.cc +++ b/libqpdf/Pl_ASCII85Decoder.cc @@ -91,8 +91,7 @@ Pl_ASCII85Decoder::flush() } QTC::TC("libtests", "Pl_ASCII85Decoder partial flush", (this->pos == 5) ? 0 : 1); - // Reset before calling getNext()->write in case that throws an - // exception. + // Reset before calling getNext()->write in case that throws an exception. auto t = this->pos - 1; this->pos = 0; memset(this->inbuf, 117, 5); diff --git a/libqpdf/Pl_ASCIIHexDecoder.cc b/libqpdf/Pl_ASCIIHexDecoder.cc index 313d8fed..7cc57a70 100644 --- a/libqpdf/Pl_ASCIIHexDecoder.cc +++ b/libqpdf/Pl_ASCIIHexDecoder.cc @@ -79,8 +79,7 @@ Pl_ASCIIHexDecoder::flush() auto ch = static_cast<unsigned char>((b[0] << 4) + b[1]); QTC::TC("libtests", "Pl_ASCIIHexDecoder partial flush", (this->pos == 2) ? 0 : 1); - // Reset before calling getNext()->write in case that throws an - // exception. + // Reset before calling getNext()->write in case that throws an exception. this->pos = 0; this->inbuf[0] = '0'; this->inbuf[1] = '0'; diff --git a/libqpdf/Pl_Buffer.cc b/libqpdf/Pl_Buffer.cc index c3184104..b10cf544 100644 --- a/libqpdf/Pl_Buffer.cc +++ b/libqpdf/Pl_Buffer.cc @@ -11,7 +11,7 @@ Pl_Buffer::Pl_Buffer(char const* identifier, Pipeline* next) : { } -Pl_Buffer::~Pl_Buffer() +Pl_Buffer::~Pl_Buffer() // NOLINT (modernize-use-equals-default) { // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } diff --git a/libqpdf/Pl_Concatenate.cc b/libqpdf/Pl_Concatenate.cc index ecb20a44..82ec0bd4 100644 --- a/libqpdf/Pl_Concatenate.cc +++ b/libqpdf/Pl_Concatenate.cc @@ -5,10 +5,9 @@ Pl_Concatenate::Pl_Concatenate(char const* identifier, Pipeline* next) : { } -Pl_Concatenate::~Pl_Concatenate() +Pl_Concatenate::~Pl_Concatenate() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_Count.cc b/libqpdf/Pl_Count.cc index cb458f0c..4a0d6cef 100644 --- a/libqpdf/Pl_Count.cc +++ b/libqpdf/Pl_Count.cc @@ -14,10 +14,9 @@ Pl_Count::Pl_Count(char const* identifier, Pipeline* next) : { } -Pl_Count::~Pl_Count() +Pl_Count::~Pl_Count() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_DCT.cc b/libqpdf/Pl_DCT.cc index 5634e022..042d3977 100644 --- a/libqpdf/Pl_DCT.cc +++ b/libqpdf/Pl_DCT.cc @@ -75,10 +75,9 @@ Pl_DCT::Pl_DCT( { } -Pl_DCT::~Pl_DCT() +Pl_DCT::~Pl_DCT() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void @@ -92,14 +91,12 @@ Pl_DCT::finish() { m->buf.finish(); - // Using a std::shared_ptr<Buffer> here and passing it into compress - // and decompress causes a memory leak with setjmp/longjmp. Just - // use a pointer and delete it. + // Using a std::shared_ptr<Buffer> here and passing it into compress and decompress causes a + // memory leak with setjmp/longjmp. Just use a pointer and delete it. Buffer* b = m->buf.getBuffer(); if (b->getSize() == 0) { - // Special case: empty data will never succeed and probably - // means we're calling finish a second time from an exception - // handler. + // Special case: empty data will never succeed and probably means we're calling finish a + // second time from an exception handler. delete b; this->getNext()->finish(); return; @@ -114,8 +111,7 @@ Pl_DCT::finish() jerr.pub.error_exit = error_handler; bool error = false; - // The jpeg library is a "C" library, so we use setjmp and longjmp - // for exception handling. + // The jpeg library is a "C" library, so we use setjmp and longjmp for exception handling. if (setjmp(jerr.jmpbuf) == 0) { try { if (m->action == a_compress) { @@ -124,9 +120,8 @@ Pl_DCT::finish() decompress(reinterpret_cast<void*>(&cinfo_decompress), b); } } catch (std::exception& e) { - // Convert an exception back to a longjmp so we can ensure - // that the right cleanup happens. This will get converted - // back to an exception. + // Convert an exception back to a longjmp so we can ensure that the right cleanup + // happens. This will get converted back to an exception. jerr.msg = e.what(); longjmp(jerr.jmpbuf, 1); } @@ -205,9 +200,8 @@ init_buffer_source(j_decompress_ptr) static boolean fill_buffer_input_buffer(j_decompress_ptr) { - // The whole JPEG data is expected to reside in the supplied memory - // buffer, so any request for more data beyond the given buffer size - // is treated as an error. + // The whole JPEG data is expected to reside in the supplied memory buffer, so any request for + // more data beyond the given buffer size is treated as an error. throw std::runtime_error("invalid jpeg data reading from buffer"); return TRUE; } @@ -216,8 +210,8 @@ static void skip_buffer_input_data(j_decompress_ptr cinfo, long num_bytes) { if (num_bytes < 0) { - throw std::runtime_error("reading jpeg: jpeg library requested" - " skipping a negative number of bytes"); + throw std::runtime_error( + "reading jpeg: jpeg library requested skipping a negative number of bytes"); } size_t to_skip = QIntC::to_size(num_bytes); if ((to_skip > 0) && (to_skip <= cinfo->src->bytes_in_buffer)) { diff --git a/libqpdf/Pl_Discard.cc b/libqpdf/Pl_Discard.cc index f1078e3a..643d3e4f 100644 --- a/libqpdf/Pl_Discard.cc +++ b/libqpdf/Pl_Discard.cc @@ -7,10 +7,9 @@ Pl_Discard::Pl_Discard() : { } -Pl_Discard::~Pl_Discard() +Pl_Discard::~Pl_Discard() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc index c3e4a9f5..d332e635 100644 --- a/libqpdf/Pl_Flate.cc +++ b/libqpdf/Pl_Flate.cc @@ -16,16 +16,14 @@ Pl_Flate::Members::Members(size_t out_bufsize, action_e action) : zdata(nullptr) { this->outbuf = QUtil::make_shared_array<unsigned char>(out_bufsize); - // Indirect through zdata to reach the z_stream so we don't have - // to include zlib.h in Pl_Flate.hh. This means people using - // shared library versions of qpdf don't have to have zlib - // development files available, which particularly helps in a - // Windows environment. + // Indirect through zdata to reach the z_stream so we don't have to include zlib.h in + // Pl_Flate.hh. This means people using shared library versions of qpdf don't have to have zlib + // development files available, which particularly helps in a Windows environment. this->zdata = new z_stream; if (out_bufsize > UINT_MAX) { - throw std::runtime_error("Pl_Flate: zlib doesn't support buffer" - " sizes larger than unsigned int"); + throw std::runtime_error( + "Pl_Flate: zlib doesn't support buffer sizes larger than unsigned int"); } z_stream& zstream = *(static_cast<z_stream*>(this->zdata)); @@ -60,10 +58,9 @@ Pl_Flate::Pl_Flate( { } -Pl_Flate::~Pl_Flate() +Pl_Flate::~Pl_Flate() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void @@ -88,8 +85,7 @@ Pl_Flate::write(unsigned char const* data, size_t len) this->identifier + ": Pl_Flate: write() called after finish() called"); } - // Write in chunks in case len is too big to fit in an int. - // Assume int is at least 32 bits. + // Write in chunks in case len is too big to fit in an int. Assume int is at least 32 bits. static size_t const max_bytes = 1 << 30; size_t bytes_left = len; unsigned char const* buf = data; @@ -105,20 +101,18 @@ void Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) { if (len > UINT_MAX) { - throw std::runtime_error("Pl_Flate: zlib doesn't support data" - " blocks larger than int"); + throw std::runtime_error("Pl_Flate: zlib doesn't support data blocks larger than int"); } z_stream& zstream = *(static_cast<z_stream*>(m->zdata)); - // zlib is known not to modify the data pointed to by next_in but - // doesn't declare the field value const unless compiled to do so. + // zlib is known not to modify the data pointed to by next_in but doesn't declare the field + // value const unless compiled to do so. zstream.next_in = const_cast<unsigned char*>(data); zstream.avail_in = QIntC::to_uint(len); if (!m->initialized) { int err = Z_OK; - // deflateInit and inflateInit are macros that use old-style - // casts. + // deflateInit and inflateInit are macros that use old-style casts. #if ((defined(__GNUC__) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__)) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wold-style-cast" @@ -147,21 +141,18 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) } if ((m->action == a_inflate) && (err != Z_OK) && zstream.msg && (strcmp(zstream.msg, "incorrect data check") == 0)) { - // Other PDF readers ignore this specific error. Combining - // this with Z_SYNC_FLUSH enables qpdf to handle some - // broken zlib streams without losing data. + // Other PDF readers ignore this specific error. Combining this with Z_SYNC_FLUSH + // enables qpdf to handle some broken zlib streams without losing data. err = Z_STREAM_END; } switch (err) { case Z_BUF_ERROR: - // Probably shouldn't be able to happen, but possible as a - // boundary condition: if the last call to inflate exactly - // filled the output buffer, it's possible that the next - // call to inflate could have nothing to do. There are PDF - // files in the wild that have this error (including at - // least one in qpdf's test suite). In some cases, we want - // to know about this, because it indicates incorrect - // compression, so call a callback if provided. + // Probably shouldn't be able to happen, but possible as a boundary condition: if the + // last call to inflate exactly filled the output buffer, it's possible that the next + // call to inflate could have nothing to do. There are PDF files in the wild that have + // this error (including at least one in qpdf's test suite). In some cases, we want to + // know about this, because it indicates incorrect compression, so call a callback if + // provided. this->warn("input stream is complete but output may still be valid", err); done = true; break; @@ -173,9 +164,8 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush) case Z_OK: { if ((zstream.avail_in == 0) && (zstream.avail_out > 0)) { - // There is nothing left to read, and there was - // sufficient buffer space to write everything we - // needed, so we're done for now. + // There is nothing left to read, and there was sufficient buffer space to write + // everything we needed, so we're done for now. done = true; } uLong ready = QIntC::to_ulong(m->out_bufsize - zstream.avail_out); diff --git a/libqpdf/Pl_Function.cc b/libqpdf/Pl_Function.cc index 2cb22926..00d7f5b0 100644 --- a/libqpdf/Pl_Function.cc +++ b/libqpdf/Pl_Function.cc @@ -39,10 +39,9 @@ Pl_Function::Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t }; } -Pl_Function::~Pl_Function() +Pl_Function::~Pl_Function() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_LZWDecoder.cc b/libqpdf/Pl_LZWDecoder.cc index 8e5fd9d1..9abb69cd 100644 --- a/libqpdf/Pl_LZWDecoder.cc +++ b/libqpdf/Pl_LZWDecoder.cc @@ -129,7 +129,7 @@ Pl_LZWDecoder::addToTable(unsigned char next) unsigned char* new_data = entry.getBuffer(); memcpy(new_data, last_data, last_size); new_data[last_size] = next; - this->table.push_back(entry); + this->table.push_back(std::move(entry)); } void @@ -149,9 +149,8 @@ Pl_LZWDecoder::handleCode(unsigned int code) this->eod = true; } else { if (this->last_code != 256) { - // Add to the table from last time. New table entry would - // be what we read last plus the first character of what - // we're reading now. + // Add to the table from last time. New table entry would be what we read last plus the + // first character of what we're reading now. unsigned char next = '\0'; unsigned int table_size = QIntC::to_uint(table.size()); if (code < 256) { @@ -162,10 +161,8 @@ Pl_LZWDecoder::handleCode(unsigned int code) if (idx > table_size) { throw std::runtime_error("LZWDecoder: bad code received"); } else if (idx == table_size) { - // The encoder would have just created this entry, - // so the first character of this entry would have - // been the same as the first character of the - // last entry. + // The encoder would have just created this entry, so the first character of + // this entry would have been the same as the first character of the last entry. QTC::TC("libtests", "Pl_LZWDecoder last was table size"); next = getFirstChar(this->last_code); } else { diff --git a/libqpdf/Pl_MD5.cc b/libqpdf/Pl_MD5.cc index c0714839..8d45f17a 100644 --- a/libqpdf/Pl_MD5.cc +++ b/libqpdf/Pl_MD5.cc @@ -19,8 +19,7 @@ Pl_MD5::write(unsigned char const* buf, size_t len) this->in_progress = true; } - // Write in chunks in case len is too big to fit in an int. - // Assume int is at least 32 bits. + // Write in chunks in case len is too big to fit in an int. Assume int is at least 32 bits. static size_t const max_bytes = 1 << 30; size_t bytes_left = len; unsigned char const* data = buf; diff --git a/libqpdf/Pl_OStream.cc b/libqpdf/Pl_OStream.cc index 28a08bdc..9b1995a4 100644 --- a/libqpdf/Pl_OStream.cc +++ b/libqpdf/Pl_OStream.cc @@ -13,10 +13,9 @@ Pl_OStream::Pl_OStream(char const* identifier, std::ostream& os) : { } -Pl_OStream::~Pl_OStream() +Pl_OStream::~Pl_OStream() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_PNGFilter.cc b/libqpdf/Pl_PNGFilter.cc index b9e297d7..4c2dd623 100644 --- a/libqpdf/Pl_PNGFilter.cc +++ b/libqpdf/Pl_PNGFilter.cc @@ -33,8 +33,8 @@ Pl_PNGFilter::Pl_PNGFilter( } if (!((bits_per_sample == 1) || (bits_per_sample == 2) || (bits_per_sample == 4) || (bits_per_sample == 8) || (bits_per_sample == 16))) { - throw std::runtime_error("PNGFilter created with invalid bits_per_sample not" - " 1, 2, 4, 8, or 16"); + throw std::runtime_error( + "PNGFilter created with invalid bits_per_sample not 1, 2, 4, 8, or 16"); } this->bytes_per_pixel = ((bits_per_sample * samples_per_pixel) + 7) / 8; unsigned long long bpr = ((columns * bits_per_sample * samples_per_pixel) + 7) / 8; diff --git a/libqpdf/Pl_QPDFTokenizer.cc b/libqpdf/Pl_QPDFTokenizer.cc index f2612e85..7bb86d5f 100644 --- a/libqpdf/Pl_QPDFTokenizer.cc +++ b/libqpdf/Pl_QPDFTokenizer.cc @@ -21,10 +21,9 @@ Pl_QPDFTokenizer::Pl_QPDFTokenizer( m->tokenizer.includeIgnorable(); } -Pl_QPDFTokenizer::~Pl_QPDFTokenizer() +Pl_QPDFTokenizer::~Pl_QPDFTokenizer() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_RunLength.cc b/libqpdf/Pl_RunLength.cc index d9e6799a..0d3bba2c 100644 --- a/libqpdf/Pl_RunLength.cc +++ b/libqpdf/Pl_RunLength.cc @@ -16,10 +16,9 @@ Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, action_e acti { } -Pl_RunLength::~Pl_RunLength() +Pl_RunLength::~Pl_RunLength() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void @@ -135,10 +134,9 @@ Pl_RunLength::flush_encode() void Pl_RunLength::finish() { - // When decoding, we might have read a length byte not followed by - // data, which means the stream was terminated early, but we will - // just ignore this case since this is the only sensible thing to - // do. + // When decoding, we might have read a length byte not followed by data, which means the stream + // was terminated early, but we will just ignore this case since this is the only sensible thing + // to do. if (m->action == a_encode) { flush_encode(); unsigned char ch = 128; diff --git a/libqpdf/Pl_SHA2.cc b/libqpdf/Pl_SHA2.cc index f431ff7d..04ef924c 100644 --- a/libqpdf/Pl_SHA2.cc +++ b/libqpdf/Pl_SHA2.cc @@ -20,8 +20,7 @@ Pl_SHA2::write(unsigned char const* buf, size_t len) this->in_progress = true; } - // Write in chunks in case len is too big to fit in an int. - // Assume int is at least 32 bits. + // Write in chunks in case len is too big to fit in an int. Assume int is at least 32 bits. static size_t const max_bytes = 1 << 30; size_t bytes_left = len; unsigned char const* data = buf; diff --git a/libqpdf/Pl_StdioFile.cc b/libqpdf/Pl_StdioFile.cc index 918aacde..24e11244 100644 --- a/libqpdf/Pl_StdioFile.cc +++ b/libqpdf/Pl_StdioFile.cc @@ -17,10 +17,9 @@ Pl_StdioFile::Pl_StdioFile(char const* identifier, FILE* f) : { } -Pl_StdioFile::~Pl_StdioFile() +Pl_StdioFile::~Pl_StdioFile() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/Pl_String.cc b/libqpdf/Pl_String.cc index 0bee11b3..9009268a 100644 --- a/libqpdf/Pl_String.cc +++ b/libqpdf/Pl_String.cc @@ -13,10 +13,9 @@ Pl_String::Pl_String(char const* identifier, Pipeline* next, std::string& s) : { } -Pl_String::~Pl_String() +Pl_String::~Pl_String() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 64ff4715..396dfe8f 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -106,9 +106,8 @@ namespace throwException() { throw std::logic_error("QPDF operation attempted on a QPDF object with no input " - "source." - " QPDF operations are invalid before processFile (or another" - " process method) or after closeInputSource"); + "source. QPDF operations are invalid before processFile (or " + "another process method) or after closeInputSource"); } }; } // namespace @@ -841,7 +840,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset) } if (type == 'f') { // Save deleted items until after we've checked the XRefStm, if any. - deleted_items.push_back(QPDFObjGen(toI(i), f2)); + deleted_items.emplace_back(toI(i), f2); } else { insertXrefEntry(toI(i), 1, f1, f2); } @@ -1344,21 +1343,16 @@ QPDF::readObject( size_t length = 0; try { - std::map<std::string, QPDFObjectHandle> dict = object.getDictAsMap(); + auto length_obj = object.getKey("/Length"); - if (dict.count("/Length") == 0) { - QTC::TC("qpdf", "QPDF stream without length"); - throw damagedPDF(input, offset, "stream dictionary lacks /Length key"); - } - - QPDFObjectHandle length_obj = dict["/Length"]; if (!length_obj.isInteger()) { + if (length_obj.isNull()) { + QTC::TC("qpdf", "QPDF stream without length"); + throw damagedPDF(input, offset, "stream dictionary lacks /Length key"); + } QTC::TC("qpdf", "QPDF stream length not integer"); throw damagedPDF( - input, - offset, - "/Length key in stream dictionary is not " - "an integer"); + input, offset, "/Length key in stream dictionary is not an integer"); } length = toS(length_obj.getUIntValue()); @@ -1488,7 +1482,8 @@ QPDF::readObjectAtOffset( // Special case: if offset is 0, just return null. Some PDF writers, in particular // "Mac OS X 10.7.5 Quartz PDFContext", may store deleted objects in the xref table as - // "0000000000 00000 n", which is not correct, but it won't hurt anything for to ignore these. + // "0000000000 00000 n", which is not correct, but it won't hurt anything for us to ignore + // these. if (offset == 0) { QTC::TC("qpdf", "QPDF bogus 0 offset", 0); warn(damagedPDF(0, "object has offset 0")); @@ -2213,7 +2208,7 @@ QPDF::getVersionAsPDFVersion() minor = QUtil::string_to_int(match[2].str().c_str()); } - return PDFVersion(major, minor, extension_level); + return {major, minor, extension_level}; } std::string @@ -2484,7 +2479,7 @@ QPDF::damagedPDF( qpdf_offset_t offset, std::string const& message) { - return QPDFExc(qpdf_e_damaged_pdf, input->getName(), object, offset, message); + return {qpdf_e_damaged_pdf, input->getName(), object, offset, message}; } // Return an exception of type qpdf_e_damaged_pdf. The object is taken from @@ -2500,7 +2495,7 @@ QPDF::damagedPDF( QPDFExc QPDF::damagedPDF(std::string const& object, qpdf_offset_t offset, std::string const& message) { - return QPDFExc(qpdf_e_damaged_pdf, m->file->getName(), object, offset, message); + return {qpdf_e_damaged_pdf, m->file->getName(), object, offset, message}; } // Return an exception of type qpdf_e_damaged_pdf. The filename is taken from m->file and the diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index aca4bf1f..5a54bf75 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -70,7 +70,7 @@ QPDFAcroFormDocumentHelper::addAndRenameFormFields(std::vector<QPDFObjectHandle> if (seen.add(obj)) { auto kids = obj.getKey("/Kids"); if (kids.isArray()) { - for (auto kid: kids.aitems()) { + for (auto const& kid: kids.aitems()) { queue.push_back(kid); } } @@ -104,7 +104,7 @@ QPDFAcroFormDocumentHelper::addAndRenameFormFields(std::vector<QPDFObjectHandle> } } - for (auto i: fields) { + for (auto const& i: fields) { addFormField(i); } } @@ -165,7 +165,7 @@ QPDFAcroFormDocumentHelper::getFormFields() analyze(); std::vector<QPDFFormFieldObjectHelper> result; for (auto const& iter: m->field_to_annotations) { - result.push_back(this->qpdf.getObject(iter.first)); + result.emplace_back(this->qpdf.getObject(iter.first)); } return result; } @@ -279,7 +279,7 @@ QPDFAcroFormDocumentHelper::analyze() annot.warnIfPossible("this widget annotation is not" " reachable from /AcroForm in the document catalog"); m->annotation_to_field[og] = QPDFFormFieldObjectHelper(annot); - m->field_to_annotations[og].push_back(QPDFAnnotationObjectHelper(annot)); + m->field_to_annotations[og].emplace_back(annot); } } } @@ -342,7 +342,7 @@ QPDFAcroFormDocumentHelper::traverseField( if (is_annotation) { QPDFObjectHandle our_field = (is_field ? field : parent); - m->field_to_annotations[our_field.getObjGen()].push_back(QPDFAnnotationObjectHelper(field)); + m->field_to_annotations[our_field.getObjGen()].emplace_back(field); m->annotation_to_field[og] = QPDFFormFieldObjectHelper(our_field); } @@ -469,19 +469,18 @@ namespace ResourceReplacer( std::map<std::string, std::map<std::string, std::string>> const& dr_map, std::map<std::string, std::map<std::string, std::set<size_t>>> const& rnames); - virtual ~ResourceReplacer() = default; - virtual void handleToken(QPDFTokenizer::Token const&) override; + ~ResourceReplacer() override = default; + void handleToken(QPDFTokenizer::Token const&) override; private: - size_t offset; + size_t offset{0}; std::map<std::string, std::map<size_t, std::string>> to_replace; }; } // namespace ResourceReplacer::ResourceReplacer( std::map<std::string, std::map<std::string, std::string>> const& dr_map, - std::map<std::string, std::map<std::string, std::set<size_t>>> const& rnames) : - offset(0) + std::map<std::string, std::map<std::string, std::set<size_t>>> const& rnames) { // We have: // * dr_map[resource_type][key] == new_key @@ -1019,7 +1018,7 @@ QPDFAcroFormDocumentHelper::fixCopiedAnnotations( to_page.replaceKey("/Annots", QPDFObjectHandle::newArray(new_annots)); addAndRenameFormFields(new_fields); if (added_fields) { - for (auto f: new_fields) { + for (auto const& f: new_fields) { added_fields->insert(f.getObjGen()); } } diff --git a/libqpdf/QPDFAnnotationObjectHelper.cc b/libqpdf/QPDFAnnotationObjectHelper.cc index 81ea5a7f..b967a5b3 100644 --- a/libqpdf/QPDFAnnotationObjectHelper.cc +++ b/libqpdf/QPDFAnnotationObjectHelper.cc @@ -54,13 +54,10 @@ QPDFAnnotationObjectHelper::getAppearanceStream(std::string const& which, std::s if (ap.isDictionary()) { QPDFObjectHandle ap_sub = ap.getKey(which); if (ap_sub.isStream()) { - // According to the spec, Appearance State is supposed to - // refer to a subkey of the appearance stream when /AP is - // a dictionary, but files have been seen in the wild - // where Appearance State is `/N` and `/AP` is a stream. - // Therefore, if `which` points to a stream, disregard - // state and just use the stream. See qpdf issue #949 for - // details. + // According to the spec, Appearance State is supposed to refer to a subkey of the + // appearance stream when /AP is a dictionary, but files have been seen in the wild + // where Appearance State is `/N` and `/AP` is a stream. Therefore, if `which` points to + // a stream, disregard state and just use the stream. See qpdf issue #949 for details. QTC::TC("qpdf", "QPDFAnnotationObjectHelper AP stream"); return ap_sub; } @@ -85,84 +82,66 @@ QPDFAnnotationObjectHelper::getPageContentForAppearance( return ""; } - // The appearance matrix computed by this method is the - // transformation matrix that needs to be in effect when drawing - // this annotation's appearance stream on the page. The algorithm - // for computing the appearance matrix described in section 12.5.5 - // of the ISO-32000 PDF spec is similar but not identical to what - // we are doing here. + // The appearance matrix computed by this method is the transformation matrix that needs to be + // in effect when drawing this annotation's appearance stream on the page. The algorithm for + // computing the appearance matrix described in section 12.5.5 of the ISO-32000 PDF spec is + // similar but not identical to what we are doing here. - // When rendering an appearance stream associated with an - // annotation, there are four relevant components: + // When rendering an appearance stream associated with an annotation, there are four relevant + // components: // // * The appearance stream's bounding box (/BBox) // * The appearance stream's matrix (/Matrix) // * The annotation's rectangle (/Rect) - // * In the case of form fields with the NoRotate flag, the - // page's rotation + // * In the case of form fields with the NoRotate flag, the page's rotation - // When rendering a form xobject in isolation, just drawn with a - // /Do operator, there is no form field, so page rotation is not - // relevant, and there is no annotation, so /Rect is not relevant, - // so only /BBox and /Matrix are relevant. The effect of these are - // as follows: + // When rendering a form xobject in isolation, just drawn with a /Do operator, there is no form + // field, so page rotation is not relevant, and there is no annotation, so /Rect is not + // relevant, so only /BBox and /Matrix are relevant. The effect of these are as follows: // * /BBox is treated as a clipping region - // * /Matrix is applied as a transformation prior to rendering the - // appearance stream. - - // There is no relationship between /BBox and /Matrix in this - // case. - - // When rendering a form xobject in the context of an annotation, - // things are a little different. In particular, a matrix is - // established such that /BBox, when transformed by /Matrix, would - // fit completely inside of /Rect. /BBox is no longer a clipping - // region. To illustrate the difference, consider a /Matrix of - // [2 0 0 2 0 0], which is scaling by a factor of two along both - // axes. If the appearance stream drew a rectangle equal to /BBox, - // in the case of the form xobject in isolation, this matrix would - // cause only the lower-left quadrant of the rectangle to be - // visible since the scaling would cause the rest of it to fall - // outside of the clipping region. In the case of the form xobject - // displayed in the context of an annotation, such a matrix would - // have no effect at all because it would be applied to the - // bounding box first, and then when the resulting enclosing - // quadrilateral was transformed to fit into /Rect, the effect of - // the scaling would be undone. - - // Our job is to create a transformation matrix that compensates - // for these differences so that the appearance stream of an - // annotation can be drawn as a regular form xobject. - - // To do this, we perform the following steps, which overlap - // significantly with the algorithm in 12.5.5: - - // 1. Transform the four corners of /BBox by applying /Matrix to - // them, creating an arbitrarily transformed quadrilateral. - - // 2. Find the minimum upright rectangle that encompasses the - // resulting quadrilateral. This is the "transformed appearance - // box", T. - - // 3. Compute matrix A that maps the lower left and upper right - // corners of T to the annotation's /Rect. This can be done by - // scaling so that the sizes match and translating so that the + // * /Matrix is applied as a transformation prior to rendering the appearance stream. + + // There is no relationship between /BBox and /Matrix in this case. + + // When rendering a form xobject in the context of an annotation, things are a little different. + // In particular, a matrix is established such that /BBox, when transformed by /Matrix, would + // fit completely inside of /Rect. /BBox is no longer a clipping region. To illustrate the + // difference, consider a /Matrix of [2 0 0 2 0 0], which is scaling by a factor of two along + // both axes. If the appearance stream drew a rectangle equal to /BBox, in the case of the form + // xobject in isolation, this matrix would cause only the lower-left quadrant of the rectangle + // to be visible since the scaling would cause the rest of it to fall outside of the clipping + // region. In the case of the form xobject displayed in the context of an annotation, such a + // matrix would have no effect at all because it would be applied to the bounding box first, and + // then when the resulting enclosing quadrilateral was transformed to fit into /Rect, the effect + // of the scaling would be undone. + + // Our job is to create a transformation matrix that compensates for these differences so that + // the appearance stream of an annotation can be drawn as a regular form xobject. + + // To do this, we perform the following steps, which overlap significantly with the algorithm + // in 12.5.5: + + // 1. Transform the four corners of /BBox by applying /Matrix to them, creating an arbitrarily + // transformed quadrilateral. + + // 2. Find the minimum upright rectangle that encompasses the resulting quadrilateral. This is + // the "transformed appearance box", T. + + // 3. Compute matrix A that maps the lower left and upper right corners of T to the annotation's + // /Rect. This can be done by scaling so that the sizes match and translating so that the // scaled T exactly overlaps /Rect. - // If the annotation's /F flag has bit 4 set, this means that - // annotation is to be rotated about its upper left corner to - // counteract any rotation of the page so it remains upright. To + // If the annotation's /F flag has bit 4 set, this means that annotation is to be rotated about + // its upper left corner to counteract any rotation of the page so it remains upright. To // achieve this effect, we do the following extra steps: - // 1. Perform the rotation on /BBox box prior to transforming it - // with /Matrix (by replacing matrix with concatenation of - // matrix onto the rotation) + // 1. Perform the rotation on /BBox box prior to transforming it with /Matrix (by replacing + // matrix with concatenation of matrix onto the rotation) // 2. Rotate the destination rectangle by the specified amount - // 3. Apply the rotation to A as computed above to get the final - // appearance matrix. + // 3. Apply the rotation to A as computed above to get the final appearance matrix. QPDFObjectHandle rect_obj = this->oh.getKey("/Rect"); QPDFObjectHandle as = getAppearanceStream("/N").getDict(); @@ -192,14 +171,12 @@ QPDFAnnotationObjectHelper::getPageContentForAppearance( QPDFObjectHandle::Rectangle rect = rect_obj.getArrayAsRectangle(); bool do_rotate = (rotate && (flags & an_no_rotate)); if (do_rotate) { - // If the the annotation flags include the NoRotate bit and - // the page is rotated, we have to rotate the annotation about - // its upper left corner by the same amount in the opposite - // direction so that it will remain upright in absolute - // coordinates. Since the semantics of /Rotate for a page are - // to rotate the page, while the effect of rotating using a - // transformation matrix is to rotate the coordinate system, - // the opposite directionality is explicit in the code. + // If the the annotation flags include the NoRotate bit and the page is rotated, we have to + // rotate the annotation about its upper left corner by the same amount in the opposite + // direction so that it will remain upright in absolute coordinates. Since the semantics of + // /Rotate for a page are to rotate the page, while the effect of rotating using a + // transformation matrix is to rotate the coordinate system, the opposite directionality is + // explicit in the code. QPDFMatrix mr; mr.rotatex90(rotate); mr.concat(matrix); diff --git a/libqpdf/QPDFArgParser.cc b/libqpdf/QPDFArgParser.cc index 7e1980ad..3ebec29c 100644 --- a/libqpdf/QPDFArgParser.cc +++ b/libqpdf/QPDFArgParser.cc @@ -139,8 +139,8 @@ QPDFArgParser::addInvalidChoiceHandler(std::string const& arg, param_arg_handler auto i = m->option_table->find(arg); if (i == m->option_table->end()) { QTC::TC("libtests", "QPDFArgParser invalid choice handler to unknown"); - throw std::logic_error("QPDFArgParser: attempt to add invalid choice handler" - " to unknown argument"); + throw std::logic_error( + "QPDFArgParser: attempt to add invalid choice handler to unknown argument"); } auto& oe = i->second; oe.invalid_choice_handler = handler; @@ -231,9 +231,9 @@ QPDFArgParser::invalidHelpArg(std::string const& p) void QPDFArgParser::handleArgFileArguments() { - // Support reading arguments from files. Create a new argv. Ensure - // that argv itself as well as all its contents are automatically - // deleted by using shared pointers to back the pointers in argv. + // Support reading arguments from files. Create a new argv. Ensure that argv itself as well as + // all its contents are automatically deleted by using shared pointers back to the pointers in + // argv. m->new_argv.push_back(QUtil::make_shared_cstr(m->argv[0])); for (int i = 1; i < m->argc; ++i) { char const* argfile = nullptr; @@ -264,12 +264,10 @@ QPDFArgParser::handleArgFileArguments() void QPDFArgParser::handleBashArguments() { - // Do a minimal job of parsing bash_line into arguments. This - // doesn't do everything the shell does (e.g. $(...), variable - // expansion, arithmetic, globs, etc.), but it should be good - // enough for purposes of handling completion. As we build up the - // new argv, we can't use m->new_argv because this code has to - // interoperate with @file arguments, so memory for both ways of + // Do a minimal job of parsing bash_line into arguments. This doesn't do everything the shell + // does (e.g. $(...), variable expansion, arithmetic, globs, etc.), but it should be good enough + // for purposes of handling completion. As we build up the new argv, we can't use m->new_argv + // because this code has to interoperate with @file arguments, so memory for both ways of // fabricating argv has to be protected. bool last_was_backslash = false; @@ -321,12 +319,11 @@ QPDFArgParser::handleBashArguments() } } if (m->bash_argv.empty()) { - // This can't happen if properly invoked by bash, but ensure - // we have a valid argv[0] regardless. + // This can't happen if properly invoked by bash, but ensure we have a valid argv[0] + // regardless. m->bash_argv.push_back(QUtil::make_shared_cstr(m->argv[0])); } - // Explicitly discard any non-space-terminated word. The "current - // word" is handled specially. + // Explicitly discard any non-space-terminated word. The "current word" is handled specially. m->bash_argv_ph = QUtil::make_shared_array<char const*>(1 + m->bash_argv.size()); for (size_t i = 0; i < m->bash_argv.size(); ++i) { m->bash_argv_ph.get()[i] = m->bash_argv.at(i).get(); @@ -367,12 +364,10 @@ QPDFArgParser::checkCompletion() { // See if we're being invoked from bash completion. std::string bash_point_env; - // On Windows with mingw, there have been times when there appears - // to be no way to distinguish between an empty environment - // variable and an unset variable. There are also conditions under - // which bash doesn't set COMP_LINE. Therefore, enter this logic - // if either COMP_LINE or COMP_POINT are set. They will both be - // set together under ordinary circumstances. + // On Windows with mingw, there have been times when there appears to be no way to distinguish + // between an empty environment variable and an unset variable. There are also conditions under + // which bash doesn't set COMP_LINE. Therefore, enter this logic if either COMP_LINE or + // COMP_POINT are set. They will both be set together under ordinary circumstances. bool got_line = QUtil::get_env("COMP_LINE", &m->bash_line); bool got_point = QUtil::get_env("COMP_POINT", &bash_point_env); if (got_line || got_point) { @@ -385,15 +380,12 @@ QPDFArgParser::checkCompletion() if (p > m->bash_line.length()) { p = m->bash_line.length(); } - // Set bash_cur and bash_prev based on bash_line rather than - // relying on argv. This enables us to use bashcompinit to get - // completion in zsh too since bashcompinit sets COMP_LINE and - // COMP_POINT but doesn't invoke the command with options like - // bash does. - - // p is equal to length of the string. Walk backwards looking - // for the first separator. bash_cur is everything after the - // last separator, possibly empty. + // Set bash_cur and bash_prev based on bash_line rather than relying on argv. This enables + // us to use bashcompinit to get completion in zsh too since bashcompinit sets COMP_LINE and + // COMP_POINT but doesn't invoke the command with options like bash does. + + // p is equal to length of the string. Walk backwards looking for the first separator. + // bash_cur is everything after the last separator, possibly empty. char sep(0); while (p > 0) { --p; @@ -407,10 +399,9 @@ QPDFArgParser::checkCompletion() m->bash_cur = m->bash_line.substr(1 + p, std::string::npos); } if ((sep == ':') || (sep == '=')) { - // Bash sets prev to the non-space separator if any. - // Actually, if there are multiple separators in a row, - // they are all included in prev, but that detail is not - // important to us and not worth coding. + // Bash sets prev to the non-space separator if any. Actually, if there are multiple + // separators in a row, they are all included in prev, but that detail is not important + // to us and not worth coding. m->bash_prev = m->bash_line.substr(p, 1); } else { // Go back to the last separator and set prev based on @@ -429,8 +420,8 @@ QPDFArgParser::checkCompletion() m->bash_prev = m->bash_line.substr(0, p); } if (m->argc == 1) { - // This is probably zsh using bashcompinit. There are a - // few differences in the expected output. + // This is probably zsh using bashcompinit. There are a few differences in the expected + // output. m->zsh_completion = true; } handleBashArguments(); @@ -454,8 +445,7 @@ QPDFArgParser::parseArgs() std::string o_arg(arg); std::string arg_s(arg); if (strcmp(arg, "--") == 0) { - // Special case for -- option, which is used to break out - // of subparsers. + // Special case for -- option, which is used to break out of subparsers. oep = m->option_table->find("--"); end_option = true; if (oep == m->option_table->end()) { @@ -471,11 +461,9 @@ QPDFArgParser::parseArgs() QTC::TC("libtests", "QPDFArgParser single dash"); } - // Prevent --=something from being treated as an empty arg - // by searching for = from after the first character. We - // do this since the empty string in the option table is - // for positional arguments. Besides, it doesn't make - // sense to have an empty option. + // Prevent --=something from being treated as an empty arg by searching for = from after + // the first character. We do this since the empty string in the option table is for + // positional arguments. Besides, it doesn't make sense to have an empty option. arg_s = arg; size_t equal_pos = std::string::npos; if (arg_s.length() > 0) { @@ -489,8 +477,7 @@ QPDFArgParser::parseArgs() if ((!m->bash_completion) && (m->argc == 2) && (m->cur_arg == 1) && m->help_option_table.count(arg_s)) { - // Handle help option, which is only valid as the sole - // option. + // Handle help option, which is only valid as the sole option. QTC::TC("libtests", "QPDFArgParser help option"); oep = m->help_option_table.find(arg_s); help_option = true; @@ -500,8 +487,7 @@ QPDFArgParser::parseArgs() oep = m->option_table->find(arg_s); } } else { - // The empty string maps to the positional argument - // handler. + // The empty string maps to the positional argument handler. QTC::TC("libtests", "QPDFArgParser positional"); oep = m->option_table->find(""); parameter = arg; @@ -522,8 +508,7 @@ QPDFArgParser::parseArgs() std::string message = "--" + arg_s + " must be given as --" + arg_s + "="; if (oe.invalid_choice_handler) { oe.invalid_choice_handler(parameter); - // Method should call usage() or exit. Just in case it - // doesn't... + // Method should call usage() or exit. Just in case it doesn't... message += "option"; } else if (!oe.choices.empty()) { QTC::TC("libtests", "QPDFArgParser required choices"); @@ -609,8 +594,8 @@ QPDFArgParser::addOptionsToCompletions(option_table_t& option_table) std::string base = "--" + arg; if (oe.param_arg_handler) { if (m->zsh_completion) { - // zsh doesn't treat = as a word separator, so add all - // the options so we don't get a space after the =. + // zsh doesn't treat = as a word separator, so add all the options so we don't get a + // space after the =. addChoicesToCompletions(option_table, arg, base + "="); } m->completions.insert(base + "="); diff --git a/libqpdf/QPDFCryptoProvider.cc b/libqpdf/QPDFCryptoProvider.cc index 37f152c9..2a18a366 100644 --- a/libqpdf/QPDFCryptoProvider.cc +++ b/libqpdf/QPDFCryptoProvider.cc @@ -92,8 +92,7 @@ QPDFCryptoProvider::setDefaultProvider_internal(std::string const& name) { if (!m->providers.count(name)) { throw std::logic_error( - "QPDFCryptoProvider: request to set default" - " provider to unknown implementation \"" + + "QPDFCryptoProvider: request to set default provider to unknown implementation \"" + name + "\""); } m->default_provider = name; diff --git a/libqpdf/QPDFCrypto_gnutls.cc b/libqpdf/QPDFCrypto_gnutls.cc index c96cdfbc..ee460416 100644 --- a/libqpdf/QPDFCrypto_gnutls.cc +++ b/libqpdf/QPDFCrypto_gnutls.cc @@ -233,9 +233,8 @@ QPDFCrypto_gnutls::rijndael_process(unsigned char* in_data, unsigned char* out_d this->cipher_ctx, in_data, rijndael_buf_size, out_data, rijndael_buf_size); } - // Gnutls doesn't support AES in ECB (non-CBC) mode, but the - // result is the same as if you just reset the cbc block to all - // zeroes each time. We jump through a few hoops here to make this + // Gnutls doesn't support AES in ECB (non-CBC) mode, but the result is the same as if you just + // reset the cbc block to all zeroes each time. We jump through a few hoops here to make this // work. if (!this->cbc_mode) { static unsigned char zeroes[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/libqpdf/QPDFCrypto_openssl.cc b/libqpdf/QPDFCrypto_openssl.cc index 87591eb5..92125b45 100644 --- a/libqpdf/QPDFCrypto_openssl.cc +++ b/libqpdf/QPDFCrypto_openssl.cc @@ -83,8 +83,8 @@ static void check_openssl(int status) { if (status != 1) { - // OpenSSL creates a "queue" of errors; copy the first (innermost) - // error to the exception message. + // OpenSSL creates a "queue" of errors; copy the first (innermost) error to the exception + // message. char buf[256] = ""; ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); std::string what = "OpenSSL error: "; @@ -194,7 +194,7 @@ QPDFCrypto_openssl::MD5_digest(MD5_Digest d) std::string QPDFCrypto_openssl::SHA2_digest() { - return std::string(reinterpret_cast<char*>(md_out), sha2_bits / 8); + return {reinterpret_cast<char*>(md_out), sha2_bits / 8}; } void diff --git a/libqpdf/QPDFDocumentHelper.cc b/libqpdf/QPDFDocumentHelper.cc index ad23e6f8..9bda5b52 100644 --- a/libqpdf/QPDFDocumentHelper.cc +++ b/libqpdf/QPDFDocumentHelper.cc @@ -1,7 +1,6 @@ #include <qpdf/QPDFDocumentHelper.hh> -QPDFDocumentHelper::~QPDFDocumentHelper() +QPDFDocumentHelper::~QPDFDocumentHelper() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } diff --git a/libqpdf/QPDFEFStreamObjectHelper.cc b/libqpdf/QPDFEFStreamObjectHelper.cc index a7ece6ae..b21c8981 100644 --- a/libqpdf/QPDFEFStreamObjectHelper.cc +++ b/libqpdf/QPDFEFStreamObjectHelper.cc @@ -134,8 +134,8 @@ QPDFEFStreamObjectHelper::newFromStream(QPDFObjectHandle stream) QPDFEFStreamObjectHelper result(stream); stream.getDict().replaceKey("/Type", QPDFObjectHandle::newName("/EmbeddedFile")); Pl_Discard discard; - // The PDF spec specifies use of MD5 here and notes that it is not - // to be used for security. MD5 is known to be insecure. + // The PDF spec specifies use of MD5 here and notes that it is not to be used for security. MD5 + // is known to be insecure. Pl_MD5 md5("EF md5", &discard); Pl_Count count("EF size", &md5); if (!stream.pipeStreamData(&count, nullptr, 0, qpdf_dl_all)) { diff --git a/libqpdf/QPDFEmbeddedFileDocumentHelper.cc b/libqpdf/QPDFEmbeddedFileDocumentHelper.cc index d1c7a05c..fd735e79 100644 --- a/libqpdf/QPDFEmbeddedFileDocumentHelper.cc +++ b/libqpdf/QPDFEmbeddedFileDocumentHelper.cc @@ -1,10 +1,9 @@ #include <qpdf/QPDFEmbeddedFileDocumentHelper.hh> -// File attachments are stored in the /EmbeddedFiles (name tree) key -// of the /Names dictionary from the document catalog. Each entry -// points to a /FileSpec, which in turn points to one more Embedded -// File Streams. Note that file specs can appear in other places as -// well, such as file attachment annotations, among others. +// File attachments are stored in the /EmbeddedFiles (name tree) key of the /Names dictionary from +// the document catalog. Each entry points to a /FileSpec, which in turn points to one more Embedded +// File Streams. Note that file specs can appear in other places as well, such as file attachment +// annotations, among others. // // root -> /Names -> /EmbeddedFiles = name tree // filename -> filespec diff --git a/libqpdf/QPDFFormFieldObjectHelper.cc b/libqpdf/QPDFFormFieldObjectHelper.cc index 67975451..4f7ca0e1 100644 --- a/libqpdf/QPDFFormFieldObjectHelper.cc +++ b/libqpdf/QPDFFormFieldObjectHelper.cc @@ -481,8 +481,8 @@ namespace std::vector<std::string> opt; double tf; QPDFObjectHandle::Rectangle bbox; - enum { st_top, st_bmc, st_emc, st_end } state; - bool replaced; + enum { st_top, st_bmc, st_emc, st_end } state{st_top}; + bool replaced{false}; }; } // namespace @@ -496,9 +496,7 @@ ValueSetter::ValueSetter( V(V), opt(opt), tf(tf), - bbox(bbox), - state(st_top), - replaced(false) + bbox(bbox) { } @@ -649,34 +647,24 @@ namespace class TfFinder: public QPDFObjectHandle::TokenFilter { public: - TfFinder(); - ~TfFinder() override - { - } + TfFinder() = default; + ~TfFinder() override = default; void handleToken(QPDFTokenizer::Token const&) override; double getTf(); std::string getFontName(); std::string getDA(); private: - double tf; - int tf_idx; + double tf{11.0}; + int tf_idx{-1}; std::string font_name; - double last_num; - int last_num_idx; + double last_num{0.0}; + int last_num_idx{-1}; std::string last_name; std::vector<std::string> DA; }; } // namespace -TfFinder::TfFinder() : - tf(11.0), - tf_idx(-1), - last_num(0.0), - last_num_idx(-1) -{ -} - void TfFinder::handleToken(QPDFTokenizer::Token const& token) { diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index d254f338..bb17ae84 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -428,7 +428,7 @@ QPDFJob::parseNumrange(char const* range, int max) } catch (std::runtime_error& e) { usage(e.what()); } - return std::vector<int>(); + return {}; } std::unique_ptr<QPDF> @@ -894,7 +894,7 @@ QPDFJob::doListAttachments(QPDF& pdf) v << " " << i2.first << " -> " << i2.second << "\n"; } v << " all data streams:\n"; - for (auto i2: efoh->getEmbeddedFileStreams().ditems()) { + for (auto const& i2: efoh->getEmbeddedFileStreams().ditems()) { auto efs = QPDFEFStreamObjectHelper(i2.second); v << " " << i2.first << " -> " << efs.getObjectHandle().getObjGen().unparse(',') << "\n"; @@ -1329,7 +1329,7 @@ QPDFJob::doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf) j_names.addDictionaryMember(i2.first, JSON::makeString(i2.second)); } auto j_streams = j_details.addDictionaryMember("streams", JSON::makeDictionary()); - for (auto i2: fsoh->getEmbeddedFileStreams().ditems()) { + for (auto const& i2: fsoh->getEmbeddedFileStreams().ditems()) { auto efs = QPDFEFStreamObjectHelper(i2.second); auto j_stream = j_streams.addDictionaryMember(i2.first, JSON::makeDictionary()); j_stream.addDictionaryMember( @@ -2376,9 +2376,8 @@ QPDFJob::handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_hea // Read original pages from the PDF, and parse the page range associated with this // occurrence of the file. - parsed_specs.push_back( - // line-break - QPDFPageData(page_spec.filename, page_spec_qpdfs[page_spec.filename], page_spec.range)); + parsed_specs.emplace_back( + page_spec.filename, page_spec_qpdfs[page_spec.filename], page_spec.range); } std::map<unsigned long long, bool> remove_unreferenced; @@ -2427,9 +2426,8 @@ QPDFJob::handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_hea for (size_t j = 0; j < m->collate; ++j) { if (cur_page + j < page_data.selected_pages.size()) { got_pages = true; - new_parsed_specs.push_back( - // line-break - QPDFPageData(page_data, page_data.selected_pages.at(cur_page + j))); + new_parsed_specs.emplace_back( + page_data, page_data.selected_pages.at(cur_page + j)); } } } diff --git a/libqpdf/QPDFJob_argv.cc b/libqpdf/QPDFJob_argv.cc index 3116b097..aade34cd 100644 --- a/libqpdf/QPDFJob_argv.cc +++ b/libqpdf/QPDFJob_argv.cc @@ -40,18 +40,15 @@ namespace std::shared_ptr<QPDFJob::UOConfig> c_uo; std::shared_ptr<QPDFJob::EncConfig> c_enc; std::vector<std::string> accumulated_args; - std::shared_ptr<char> pages_password; - bool gave_input; - bool gave_output; + std::shared_ptr<char> pages_password{nullptr}; + bool gave_input{false}; + bool gave_output{false}; }; } // namespace ArgParser::ArgParser(QPDFArgParser& ap, std::shared_ptr<QPDFJob::Config> c_main) : ap(ap), - c_main(c_main), - pages_password(nullptr), - gave_input(false), - gave_output(false) + c_main(c_main) { initOptionTables(); } @@ -65,9 +62,9 @@ ArgParser::initOptionTables() this->ap.addFinalCheck([this]() { c_main->checkConfiguration(); }); // add_help is defined in auto_job_help.hh add_help(this->ap); - // Special case: ignore -- at the top level. This undocumented - // behavior is for backward compatibility; it was unintentionally - // the case prior to 10.6, and some users were relying on it. + // Special case: ignore -- at the top level. This undocumented behavior is for backward + // compatibility; it was unintentionally the case prior to 10.6, and some users were relying on + // it. this->ap.selectMainOptionTable(); this->ap.addBare("--", []() {}); } @@ -254,8 +251,7 @@ ArgParser::argPagesPositional(std::string const& arg) range_p = this->accumulated_args.at(1).c_str(); } - // See if the user omitted the range entirely, in which case we - // assume "1-z". + // See if the user omitted the range entirely, in which case we assume "1-z". std::string next_file; if (range_p == nullptr) { if (arg.empty()) { diff --git a/libqpdf/QPDFJob_config.cc b/libqpdf/QPDFJob_config.cc index 7c275f20..834de9ab 100644 --- a/libqpdf/QPDFJob_config.cc +++ b/libqpdf/QPDFJob_config.cc @@ -25,18 +25,14 @@ QPDFJob::Config* QPDFJob::Config::emptyInput() { if (o.m->infilename == nullptr) { - // Various places in QPDFJob.cc know that the empty string for - // infile means empty. We set it to something other than a - // null pointer as an indication that some input source has - // been specified. This approach means that passing "" as - // the argument to inputFile in job JSON, or equivalently - // using "" as a positional command-line argument would be the - // same as --empty. This probably isn't worth blocking or - // coding around. + // Various places in QPDFJob.cc know that the empty string for infile means empty. We set it + // to something other than a null pointer as an indication that some input source has been + // specified. This approach means that passing "" as the argument to inputFile in job JSON, + // or equivalently using "" as a positional command-line argument would be the same as + // --empty. This probably isn't worth blocking or coding around. o.m->infilename = QUtil::make_shared_cstr(""); } else { - usage("empty input can't be used" - " since input file has already been given"); + usage("empty input can't be used since input file has already been given"); } return this; } @@ -58,8 +54,7 @@ QPDFJob::Config::replaceInput() if ((o.m->outfilename == nullptr) && (!o.m->replace_input)) { o.m->replace_input = true; } else { - usage("replace-input can't be used" - " since output file has already been given"); + usage("replace-input can't be used since output file has already been given"); } return this; } @@ -298,8 +293,7 @@ QPDFJob::Config::jsonOutput(std::string const& parameter) o.m->json_output = true; json(parameter); if (!o.m->json_stream_data_set) { - // No need to set json_stream_data_set -- that indicates - // explicit use of --json-stream-data. + // No need to set json_stream_data_set -- that indicates explicit use of --json-stream-data. o.m->json_stream_data = qpdf_sj_inline; } if (!o.m->decode_level_set) { @@ -948,7 +942,7 @@ QPDFJob::PagesConfig* QPDFJob::PagesConfig::pageSpec( std::string const& filename, std::string const& range, char const* password) { - this->config->o.m->page_specs.push_back(QPDFJob::PageSpec(filename, password, range)); + this->config->o.m->page_specs.emplace_back(filename, password, range); return this; } diff --git a/libqpdf/QPDFJob_json.cc b/libqpdf/QPDFJob_json.cc index 126f9a13..95622f36 100644 --- a/libqpdf/QPDFJob_json.cc +++ b/libqpdf/QPDFJob_json.cc @@ -30,27 +30,20 @@ namespace typedef std::function<void(char const*)> param_handler_t; typedef std::function<void(JSON)> json_handler_t; - // The code that calls these methods is automatically - // generated by generate_auto_job. This describes how we - // implement what it does. We keep a stack of handlers in - // json_handlers. The top of the stack is the "current" json - // handler, intially for the top-level object. Whenever we - // encounter a scalar, we add a handler using addBare, - // addParameter, or addChoices. Whenever we encounter a - // dictionary, we first add the dictionary handlers. Then we - // walk into the dictionary and, for each key, we register a - // dict key handler and push it to the stack, then do the same - // process for the key's value. Then we pop the key handler - // off the stack. When we encounter an array, we add the array - // handlers, push an item handler to the stack, call - // recursively for the array's single item (as this is what is - // expected in a schema), and pop the item handler. Note that - // we don't pop dictionary start/end handlers. The dictionary - // handlers and the key handlers are at the same level in - // JSONHandler. This logic is subtle and took several tries to - // get right. It's best understood by carefully understanding - // the behavior of JSONHandler, the JSON schema, and the code - // in generate_auto_job. + // The code that calls these methods is automatically generated by generate_auto_job. This + // describes how we implement what it does. We keep a stack of handlers in json_handlers. + // The top of the stack is the "current" json handler, intially for the top-level object. + // Whenever we encounter a scalar, we add a handler using addBare, addParameter, or + // addChoices. Whenever we encounter a dictionary, we first add the dictionary handlers. + // Then we walk into the dictionary and, for each key, we register a dict key handler and + // push it to the stack, then do the same process for the key's value. Then we pop the key + // handler off the stack. When we encounter an array, we add the array handlers, push an + // item handler to the stack, call recursively for the array's single item (as this is what + // is expected in a schema), and pop the item handler. Note that we don't pop dictionary + // start/end handlers. The dictionary handlers and the key handlers are at the same level in + // JSONHandler. This logic is subtle and took several tries to get right. It's best + // understood by carefully understanding the behavior of JSONHandler, the JSON schema, and + // the code in generate_auto_job. void addBare(bare_handler_t); void addParameter(param_handler_t); @@ -66,7 +59,7 @@ namespace std::list<std::shared_ptr<JSONHandler>> json_handlers; bool partial; - JSONHandler* jh; // points to last of json_handlers + JSONHandler* jh{nullptr}; // points to last of json_handlers std::shared_ptr<QPDFJob::Config> c_main; std::shared_ptr<QPDFJob::CopyAttConfig> c_copy_att; std::shared_ptr<QPDFJob::AttConfig> c_att; @@ -78,7 +71,6 @@ namespace Handlers::Handlers(bool partial, std::shared_ptr<QPDFJob::Config> c_main) : partial(partial), - jh(nullptr), c_main(c_main) { initHandlers(); @@ -261,9 +253,8 @@ Handlers::setupReplaceInput() void Handlers::beginEncrypt(JSON j) { - // This method is only called if the overall JSON structure - // matches the schema, so we already know that keys that are - // present have the right types. + // This method is only called if the overall JSON structure matches the schema, so we already + // know that keys that are present have the right types. int key_len = 0; std::string user_password; std::string owner_password; @@ -284,14 +275,13 @@ Handlers::beginEncrypt(JSON j) }); if (key_len == 0) { QTC::TC("qpdf", "QPDFJob json encrypt no key length"); - usage("exactly one of 40bit, 128bit, or 256bit must be given;" - " an empty dictionary may be supplied for one of them" - " to set the key length without imposing any restrictions"); + usage("exactly one of 40bit, 128bit, or 256bit must be given; an empty dictionary may be " + "supplied for one of them to set the key length without imposing any restrictions"); } if (!(user_password_seen && owner_password_seen)) { QTC::TC("qpdf", "QPDFJob json encrypt missing password"); - usage("the user and owner password are both required; use the empty" - " string for the user password if you don't want a password"); + usage("the user and owner password are both required; use the empty string for the user " + "password if you don't want a password"); } this->c_enc = c_main->encrypt(key_len, user_password, owner_password); } diff --git a/libqpdf/QPDFLogger.cc b/libqpdf/QPDFLogger.cc index 76c3c70c..a704ea75 100644 --- a/libqpdf/QPDFLogger.cc +++ b/libqpdf/QPDFLogger.cc @@ -12,8 +12,7 @@ namespace { public: Pl_Track(char const* identifier, Pipeline* next) : - Pipeline(identifier, next), - used(false) + Pipeline(identifier, next) { } @@ -37,7 +36,7 @@ namespace } private: - bool used; + bool used{false}; }; }; // namespace diff --git a/libqpdf/QPDFMatrix.cc b/libqpdf/QPDFMatrix.cc index a54b4370..f38d7644 100644 --- a/libqpdf/QPDFMatrix.cc +++ b/libqpdf/QPDFMatrix.cc @@ -57,7 +57,7 @@ QPDFMatrix::unparse() const QPDFObjectHandle::Matrix QPDFMatrix::getAsMatrix() const { - return QPDFObjectHandle::Matrix(a, b, c, d, e, f); + return {a, b, c, d, e, f}; } void @@ -124,11 +124,11 @@ QPDFMatrix::transformRectangle(QPDFObjectHandle::Rectangle r) const transform(r.llx, r.ury, tx.at(1), ty.at(1)); transform(r.urx, r.lly, tx.at(2), ty.at(2)); transform(r.urx, r.ury, tx.at(3), ty.at(3)); - return QPDFObjectHandle::Rectangle( + return { *std::min_element(tx.begin(), tx.end()), *std::min_element(ty.begin(), ty.end()), *std::max_element(tx.begin(), tx.end()), - *std::max_element(ty.begin(), ty.end())); + *std::max_element(ty.begin(), ty.end())}; } bool diff --git a/libqpdf/QPDFNameTreeObjectHelper.cc b/libqpdf/QPDFNameTreeObjectHelper.cc index bfe67ecc..9a2a6284 100644 --- a/libqpdf/QPDFNameTreeObjectHelper.cc +++ b/libqpdf/QPDFNameTreeObjectHelper.cc @@ -34,11 +34,10 @@ namespace static NameTreeDetails name_tree_details; -QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper() +QPDFNameTreeObjectHelper::~QPDFNameTreeObjectHelper() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer. For this specific class, see github issue - // #745. + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer. For this specific + // class, see github issue #745. } QPDFNameTreeObjectHelper::Members::Members(QPDFObjectHandle& oh, QPDF& q, bool auto_repair) : @@ -55,8 +54,7 @@ QPDFNameTreeObjectHelper::QPDFNameTreeObjectHelper(QPDFObjectHandle oh, QPDF& q, QPDFNameTreeObjectHelper QPDFNameTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair) { - return QPDFNameTreeObjectHelper( - qpdf.makeIndirectObject("<< /Names [] >>"_qpdf), qpdf, auto_repair); + return {qpdf.makeIndirectObject("<< /Names [] >>"_qpdf), qpdf, auto_repair}; } QPDFNameTreeObjectHelper::iterator::iterator(std::shared_ptr<NNTreeIterator> const& i) : @@ -136,33 +134,33 @@ QPDFNameTreeObjectHelper::iterator::remove() QPDFNameTreeObjectHelper::iterator QPDFNameTreeObjectHelper::begin() const { - return iterator(std::make_shared<NNTreeIterator>(m->impl->begin())); + return {std::make_shared<NNTreeIterator>(m->impl->begin())}; } QPDFNameTreeObjectHelper::iterator QPDFNameTreeObjectHelper::end() const { - return iterator(std::make_shared<NNTreeIterator>(m->impl->end())); + return {std::make_shared<NNTreeIterator>(m->impl->end())}; } QPDFNameTreeObjectHelper::iterator QPDFNameTreeObjectHelper::last() const { - return iterator(std::make_shared<NNTreeIterator>(m->impl->last())); + return {std::make_shared<NNTreeIterator>(m->impl->last())}; } QPDFNameTreeObjectHelper::iterator QPDFNameTreeObjectHelper::find(std::string const& key, bool return_prev_if_not_found) { auto i = m->impl->find(QPDFObjectHandle::newUnicodeString(key), return_prev_if_not_found); - return iterator(std::make_shared<NNTreeIterator>(i)); + return {std::make_shared<NNTreeIterator>(i)}; } QPDFNameTreeObjectHelper::iterator QPDFNameTreeObjectHelper::insert(std::string const& key, QPDFObjectHandle value) { auto i = m->impl->insert(QPDFObjectHandle::newUnicodeString(key), value); - return iterator(std::make_shared<NNTreeIterator>(i)); + return {std::make_shared<NNTreeIterator>(i)}; } bool diff --git a/libqpdf/QPDFNumberTreeObjectHelper.cc b/libqpdf/QPDFNumberTreeObjectHelper.cc index f35158d5..478a1884 100644 --- a/libqpdf/QPDFNumberTreeObjectHelper.cc +++ b/libqpdf/QPDFNumberTreeObjectHelper.cc @@ -35,11 +35,10 @@ namespace static NumberTreeDetails number_tree_details; -QPDFNumberTreeObjectHelper::~QPDFNumberTreeObjectHelper() +QPDFNumberTreeObjectHelper::~QPDFNumberTreeObjectHelper() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer. For this specific class, see github issue - // #745. + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer. For this specific + // class, see github issue #745. } QPDFNumberTreeObjectHelper::Members::Members(QPDFObjectHandle& oh, QPDF& q, bool auto_repair) : @@ -57,8 +56,7 @@ QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper( QPDFNumberTreeObjectHelper QPDFNumberTreeObjectHelper::newEmpty(QPDF& qpdf, bool auto_repair) { - return QPDFNumberTreeObjectHelper( - qpdf.makeIndirectObject("<< /Nums [] >>"_qpdf), qpdf, auto_repair); + return {qpdf.makeIndirectObject("<< /Nums [] >>"_qpdf), qpdf, auto_repair}; } QPDFNumberTreeObjectHelper::iterator::iterator(std::shared_ptr<NNTreeIterator> const& i) : @@ -138,33 +136,33 @@ QPDFNumberTreeObjectHelper::iterator::remove() QPDFNumberTreeObjectHelper::iterator QPDFNumberTreeObjectHelper::begin() const { - return iterator(std::make_shared<NNTreeIterator>(m->impl->begin())); + return {std::make_shared<NNTreeIterator>(m->impl->begin())}; } QPDFNumberTreeObjectHelper::iterator QPDFNumberTreeObjectHelper::end() const { - return iterator(std::make_shared<NNTreeIterator>(m->impl->end())); + return {std::make_shared<NNTreeIterator>(m->impl->end())}; } QPDFNumberTreeObjectHelper::iterator QPDFNumberTreeObjectHelper::last() const { - return iterator(std::make_shared<NNTreeIterator>(m->impl->last())); + return {std::make_shared<NNTreeIterator>(m->impl->last())}; } QPDFNumberTreeObjectHelper::iterator QPDFNumberTreeObjectHelper::find(numtree_number key, bool return_prev_if_not_found) { auto i = m->impl->find(QPDFObjectHandle::newInteger(key), return_prev_if_not_found); - return iterator(std::make_shared<NNTreeIterator>(i)); + return {std::make_shared<NNTreeIterator>(i)}; } QPDFNumberTreeObjectHelper::iterator QPDFNumberTreeObjectHelper::insert(numtree_number key, QPDFObjectHandle value) { auto i = m->impl->insert(QPDFObjectHandle::newInteger(key), value); - return iterator(std::make_shared<NNTreeIterator>(i)); + return {std::make_shared<NNTreeIterator>(i)}; } bool diff --git a/libqpdf/QPDFObjGen.cc b/libqpdf/QPDFObjGen.cc index 8e5bd178..f3b19f6c 100644 --- a/libqpdf/QPDFObjGen.cc +++ b/libqpdf/QPDFObjGen.cc @@ -27,8 +27,8 @@ QPDFObjGen::set::add(QPDFObjectHandle const& oh) if (auto* ptr = oh.getObjectPtr()) { return add(ptr->getObjGen()); } else { - throw std::logic_error("attempt to retrieve QPDFObjGen from " - "uninitialized QPDFObjectHandle"); + throw std::logic_error( + "attempt to retrieve QPDFObjGen from uninitialized QPDFObjectHandle"); return false; } } @@ -39,8 +39,8 @@ QPDFObjGen::set::add(QPDFObjectHelper const& helper) if (auto* ptr = helper.getObjectHandle().getObjectPtr()) { return add(ptr->getObjGen()); } else { - throw std::logic_error("attempt to retrieve QPDFObjGen from " - "uninitialized QPDFObjectHandle"); + throw std::logic_error( + "attempt to retrieve QPDFObjGen from uninitialized QPDFObjectHandle"); return false; } } @@ -51,8 +51,8 @@ QPDFObjGen::set::erase(QPDFObjectHandle const& oh) if (auto* ptr = oh.getObjectPtr()) { erase(ptr->getObjGen()); } else { - throw std::logic_error("attempt to retrieve QPDFObjGen from " - "uninitialized QPDFObjectHandle"); + throw std::logic_error( + "attempt to retrieve QPDFObjGen from uninitialized QPDFObjectHandle"); } } @@ -62,7 +62,7 @@ QPDFObjGen::set::erase(QPDFObjectHelper const& helper) if (auto* ptr = helper.getObjectHandle().getObjectPtr()) { erase(ptr->getObjGen()); } else { - throw std::logic_error("attempt to retrieve QPDFObjGen from " - "uninitialized QPDFObjectHandle"); + throw std::logic_error( + "attempt to retrieve QPDFObjGen from uninitialized QPDFObjectHandle"); } } diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index fa5e52e8..3ce748b0 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -49,7 +49,7 @@ QPDFObjectHandle::StreamDataProvider::StreamDataProvider(bool supports_retry) : { } -QPDFObjectHandle::StreamDataProvider::~StreamDataProvider() +QPDFObjectHandle::StreamDataProvider::~StreamDataProvider() // NOLINT (modernize-use-equals-default) { // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } @@ -189,13 +189,12 @@ namespace unsigned char getLastChar(); private: - unsigned char last_char; + unsigned char last_char{0}; }; } // namespace LastChar::LastChar(Pipeline* next) : - Pipeline("lastchar", next), - last_char(0) + Pipeline("lastchar", next) { } @@ -229,11 +228,9 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const void QPDFObjectHandle::disconnect() { - // Recursively remove association with any QPDF object. This - // method may only be called during final destruction. - // QPDF::~QPDF() calls it for indirect objects using the object - // pointer itself, so we don't do that here. Other objects call it - // through this method. + // Recursively remove association with any QPDF object. This method may only be called during + // final destruction. QPDF::~QPDF() calls it for indirect objects using the object pointer + // itself, so we don't do that here. Other objects call it through this method. if (!isIndirect()) { this->obj->disconnect(); } @@ -754,7 +751,7 @@ QPDFObjectHandle::getValueAsInlineImage(std::string& value) QPDFObjectHandle::QPDFArrayItems QPDFObjectHandle::aitems() { - return QPDFArrayItems(*this); + return *this; } int @@ -828,11 +825,11 @@ QPDFObjectHandle::getArrayAsRectangle() return {}; } } - return Rectangle( + return { std::min(items[0], items[2]), std::min(items[1], items[3]), std::max(items[0], items[2]), - std::max(items[1], items[3])); + std::max(items[1], items[3])}; } return {}; } @@ -850,7 +847,7 @@ QPDFObjectHandle::getArrayAsMatrix() return {}; } } - return Matrix(items[0], items[1], items[2], items[3], items[4], items[5]); + return {items[0], items[1], items[2], items[3], items[4], items[5]}; } return {}; } @@ -961,7 +958,7 @@ QPDFObjectHandle::eraseItemAndGetOld(int at) QPDFObjectHandle::QPDFDictItems QPDFObjectHandle::ditems() { - return QPDFDictItems(*this); + return {*this}; } bool @@ -1051,7 +1048,7 @@ QPDFObjectHandle::makeResourcesIndirect(QPDF& owning_qpdf) if (!sub.isDictionary()) { continue; } - for (auto i2: sub.ditems()) { + for (auto const& i2: sub.ditems()) { std::string const& key = i2.first; QPDFObjectHandle val = i2.second; if (!val.isIndirect()) { @@ -1072,7 +1069,7 @@ QPDFObjectHandle::mergeResources( auto make_og_to_name = [](QPDFObjectHandle& dict, std::map<QPDFObjGen, std::string>& og_to_name) { - for (auto i: dict.ditems()) { + for (auto const& i: dict.ditems()) { if (i.second.isIndirect()) { og_to_name[i.second.getObjGen()] = i.first; } @@ -1081,7 +1078,7 @@ QPDFObjectHandle::mergeResources( // This algorithm is described in comments in QPDFObjectHandle.hh // above the declaration of mergeResources. - for (auto o_top: other.ditems()) { + for (auto const& o_top: other.ditems()) { std::string const& rtype = o_top.first; QPDFObjectHandle other_val = o_top.second; if (hasKey(rtype)) { @@ -1098,7 +1095,7 @@ QPDFObjectHandle::mergeResources( std::set<std::string> rnames; int min_suffix = 1; bool initialized_maps = false; - for (auto ov_iter: other_val.ditems()) { + for (auto const& ov_iter: other_val.ditems()) { std::string const& key = ov_iter.first; QPDFObjectHandle rval = ov_iter.second; if (!this_val.hasKey(key)) { @@ -1783,10 +1780,9 @@ QPDFObjectHandle::parseContentStream_data( tokenizer.allowEOF(); bool empty = false; while (QIntC::to_size(input->tell()) < stream_length) { - // Read a token and seek to the beginning. The offset we get - // from this process is the beginning of the next - // non-ignorable (space, comment) token. This way, the offset - // and don't including ignorable content. + // Read a token and seek to the beginning. The offset we get from this process is the + // beginning of the next non-ignorable (space, comment) token. This way, the offset and + // don't including ignorable content. tokenizer.readToken(input, "content", true); qpdf_offset_t offset = input->getLastOffset(); input->seek(offset, SEEK_SET); @@ -1865,61 +1861,61 @@ QPDFObjectHandle::getParsedOffset() QPDFObjectHandle QPDFObjectHandle::newBool(bool value) { - return QPDFObjectHandle(QPDF_Bool::create(value)); + return {QPDF_Bool::create(value)}; } QPDFObjectHandle QPDFObjectHandle::newNull() { - return QPDFObjectHandle(QPDF_Null::create()); + return {QPDF_Null::create()}; } QPDFObjectHandle QPDFObjectHandle::newInteger(long long value) { - return QPDFObjectHandle(QPDF_Integer::create(value)); + return {QPDF_Integer::create(value)}; } QPDFObjectHandle QPDFObjectHandle::newReal(std::string const& value) { - return QPDFObjectHandle(QPDF_Real::create(value)); + return {QPDF_Real::create(value)}; } QPDFObjectHandle QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_zeroes) { - return QPDFObjectHandle(QPDF_Real::create(value, decimal_places, trim_trailing_zeroes)); + return {QPDF_Real::create(value, decimal_places, trim_trailing_zeroes)}; } QPDFObjectHandle QPDFObjectHandle::newName(std::string const& name) { - return QPDFObjectHandle(QPDF_Name::create(name)); + return {QPDF_Name::create(name)}; } QPDFObjectHandle QPDFObjectHandle::newString(std::string const& str) { - return QPDFObjectHandle(QPDF_String::create(str)); + return {QPDF_String::create(str)}; } QPDFObjectHandle QPDFObjectHandle::newUnicodeString(std::string const& utf8_str) { - return QPDFObjectHandle(QPDF_String::create_utf16(utf8_str)); + return {QPDF_String::create_utf16(utf8_str)}; } QPDFObjectHandle QPDFObjectHandle::newOperator(std::string const& value) { - return QPDFObjectHandle(QPDF_Operator::create(value)); + return {QPDF_Operator::create(value)}; } QPDFObjectHandle QPDFObjectHandle::newInlineImage(std::string const& value) { - return QPDFObjectHandle(QPDF_InlineImage::create(value)); + return {QPDF_InlineImage::create(value)}; } QPDFObjectHandle @@ -1931,44 +1927,37 @@ QPDFObjectHandle::newArray() QPDFObjectHandle QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items) { - return QPDFObjectHandle(QPDF_Array::create(items)); + return {QPDF_Array::create(items)}; } QPDFObjectHandle QPDFObjectHandle::newArray(Rectangle const& rect) { - std::vector<QPDFObjectHandle> items; - items.push_back(newReal(rect.llx)); - items.push_back(newReal(rect.lly)); - items.push_back(newReal(rect.urx)); - items.push_back(newReal(rect.ury)); - return newArray(items); + return newArray({newReal(rect.llx), newReal(rect.lly), newReal(rect.urx), newReal(rect.ury)}); } QPDFObjectHandle QPDFObjectHandle::newArray(Matrix const& matrix) { - std::vector<QPDFObjectHandle> items; - items.push_back(newReal(matrix.a)); - items.push_back(newReal(matrix.b)); - items.push_back(newReal(matrix.c)); - items.push_back(newReal(matrix.d)); - items.push_back(newReal(matrix.e)); - items.push_back(newReal(matrix.f)); - return newArray(items); + return newArray( + {newReal(matrix.a), + newReal(matrix.b), + newReal(matrix.c), + newReal(matrix.d), + newReal(matrix.e), + newReal(matrix.f)}); } QPDFObjectHandle QPDFObjectHandle::newArray(QPDFMatrix const& matrix) { - std::vector<QPDFObjectHandle> items; - items.push_back(newReal(matrix.a)); - items.push_back(newReal(matrix.b)); - items.push_back(newReal(matrix.c)); - items.push_back(newReal(matrix.d)); - items.push_back(newReal(matrix.e)); - items.push_back(newReal(matrix.f)); - return newArray(items); + return newArray( + {newReal(matrix.a), + newReal(matrix.b), + newReal(matrix.c), + newReal(matrix.d), + newReal(matrix.e), + newReal(matrix.f)}); } QPDFObjectHandle @@ -1998,7 +1987,7 @@ QPDFObjectHandle::newDictionary() QPDFObjectHandle QPDFObjectHandle::newDictionary(std::map<std::string, QPDFObjectHandle> const& items) { - return QPDFObjectHandle(QPDF_Dictionary::create(items)); + return {QPDF_Dictionary::create(items)}; } QPDFObjectHandle @@ -2063,7 +2052,7 @@ QPDFObjectHandle::shallowCopy() if (!dereference()) { throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); } - return QPDFObjectHandle(obj->copy()); + return {obj->copy()}; } QPDFObjectHandle @@ -2072,7 +2061,7 @@ QPDFObjectHandle::unsafeShallowCopy() if (!dereference()) { throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); } - return QPDFObjectHandle(obj->copy(true)); + return {obj->copy(true)}; } void @@ -2474,13 +2463,13 @@ QPDFObjectHandle::QPDFDictItems::iterator::Members::Members(QPDFObjectHandle& oh QPDFObjectHandle::QPDFDictItems::iterator QPDFObjectHandle::QPDFDictItems::begin() { - return iterator(oh, true); + return {oh, true}; } QPDFObjectHandle::QPDFDictItems::iterator QPDFObjectHandle::QPDFDictItems::end() { - return iterator(oh, false); + return {oh, false}; } QPDFObjectHandle::QPDFArrayItems::QPDFArrayItems(QPDFObjectHandle const& oh) : @@ -2554,13 +2543,13 @@ QPDFObjectHandle::QPDFArrayItems::iterator::Members::Members(QPDFObjectHandle& o QPDFObjectHandle::QPDFArrayItems::iterator QPDFObjectHandle::QPDFArrayItems::begin() { - return iterator(oh, true); + return {oh, true}; } QPDFObjectHandle::QPDFArrayItems::iterator QPDFObjectHandle::QPDFArrayItems::end() { - return iterator(oh, false); + return {oh, false}; } QPDFObjGen diff --git a/libqpdf/QPDFObjectHelper.cc b/libqpdf/QPDFObjectHelper.cc index 3696dc03..cbd54f3d 100644 --- a/libqpdf/QPDFObjectHelper.cc +++ b/libqpdf/QPDFObjectHelper.cc @@ -1,7 +1,6 @@ #include <qpdf/QPDFObjectHelper.hh> -QPDFObjectHelper::~QPDFObjectHelper() +QPDFObjectHelper::~QPDFObjectHelper() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } diff --git a/libqpdf/QPDFOutlineObjectHelper.cc b/libqpdf/QPDFOutlineObjectHelper.cc index 37e2c0d2..3b5db47a 100644 --- a/libqpdf/QPDFOutlineObjectHelper.cc +++ b/libqpdf/QPDFOutlineObjectHelper.cc @@ -14,8 +14,8 @@ QPDFOutlineObjectHelper::QPDFOutlineObjectHelper( m(new Members(dh)) { if (depth > 50) { - // Not exercised in test suite, but was tested manually by - // temporarily changing max depth to 1. + // Not exercised in test suite, but was tested manually by temporarily changing max depth + // to 1. return; } if (QPDFOutlineDocumentHelper::Accessor::checkSeen(m->dh, this->oh.getObjGen())) { diff --git a/libqpdf/QPDFPageDocumentHelper.cc b/libqpdf/QPDFPageDocumentHelper.cc index 06ec5ff7..c9c2cf52 100644 --- a/libqpdf/QPDFPageDocumentHelper.cc +++ b/libqpdf/QPDFPageDocumentHelper.cc @@ -14,7 +14,7 @@ QPDFPageDocumentHelper::getAllPages() { std::vector<QPDFPageObjectHelper> pages; for (auto const& iter: this->qpdf.getAllPages()) { - pages.push_back(QPDFPageObjectHelper(iter)); + pages.emplace_back(iter); } return pages; } @@ -59,8 +59,8 @@ QPDFPageDocumentHelper::flattenAnnotations(int required_flags, int forbidden_fla if (afdh.getNeedAppearances()) { this->qpdf.getRoot() .getKey("/AcroForm") - .warnIfPossible("document does not have updated appearance streams," - " so form fields will not be flattened"); + .warnIfPossible("document does not have updated appearance streams, so form fields " + "will not be flattened"); } for (auto& ph: getAllPages()) { QPDFObjectHandle resources = ph.getAttribute("/Resources", true); @@ -126,11 +126,10 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage( } new_content += content; } else if (process) { - // If an annotation has no appearance stream, just drop - // the annotation when flattening. This can happen for - // unchecked checkboxes and radio buttons, popup windows - // associated with comments that aren't visible, and other - // types of annotations that aren't visible. + // If an annotation has no appearance stream, just drop the annotation when flattening. + // This can happen for unchecked checkboxes and radio buttons, popup windows associated + // with comments that aren't visible, and other types of annotations that aren't + // visible. QTC::TC("qpdf", "QPDFPageDocumentHelper ignore annotation with no appearance"); } else { new_annots.push_back(aoh.getObjectHandle()); diff --git a/libqpdf/QPDFPageLabelDocumentHelper.cc b/libqpdf/QPDFPageLabelDocumentHelper.cc index 4a9b456f..d94c41fd 100644 --- a/libqpdf/QPDFPageLabelDocumentHelper.cc +++ b/libqpdf/QPDFPageLabelDocumentHelper.cc @@ -57,19 +57,17 @@ QPDFPageLabelDocumentHelper::getLabelsForPageRange( long long new_start_idx, std::vector<QPDFObjectHandle>& new_labels) { - // Start off with a suitable label for the first page. For every - // remaining page, if that page has an explicit entry, copy it. - // Otherwise, let the subsequent page just sequence from the prior - // entry. If there is no entry for the first page, fabricate one - // that would match how the page would look in a new file in which - // it also didn't have an explicit label. + // Start off with a suitable label for the first page. For every remaining page, if that page + // has an explicit entry, copy it. Otherwise, let the subsequent page just sequence from the + // prior entry. If there is no entry for the first page, fabricate one that would match how the + // page would look in a new file in which it also didn't have an explicit label. QPDFObjectHandle label = getLabelForPage(start_idx); if (label.isNull()) { label = QPDFObjectHandle::newDictionary(); label.replaceKey("/St", QPDFObjectHandle::newInteger(1 + new_start_idx)); } - // See if the new label is redundant based on the previous entry - // in the vector. If so, don't add it. + // See if the new label is redundant based on the previous entry in the vector. If so, don't add + // it. size_t size = new_labels.size(); bool skip_first = false; if (size >= 2) { diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc index 608254e4..fd6e5215 100644 --- a/libqpdf/QPDFPageObjectHelper.cc +++ b/libqpdf/QPDFPageObjectHelper.cc @@ -20,8 +20,8 @@ namespace from_page(from_page) { } - virtual ~ContentProvider() = default; - virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline); + ~ContentProvider() override = default; + void provideStreamData(QPDFObjGen const&, Pipeline* pipeline) override; private: QPDFObjectHandle from_page; @@ -44,8 +44,8 @@ namespace { public: InlineImageTracker(QPDF*, size_t min_size, QPDFObjectHandle resources); - virtual ~InlineImageTracker() = default; - virtual void handleToken(QPDFTokenizer::Token const&); + ~InlineImageTracker() override = default; + void handleToken(QPDFTokenizer::Token const&) override; QPDFObjectHandle convertIIDict(QPDFObjectHandle odict); QPDF* qpdf; @@ -53,19 +53,16 @@ namespace QPDFObjectHandle resources; std::string dict_str; std::string bi_str; - int min_suffix; - bool any_images; - enum { st_top, st_bi } state; + int min_suffix{1}; + bool any_images{false}; + enum { st_top, st_bi } state{st_top}; }; } // namespace InlineImageTracker::InlineImageTracker(QPDF* qpdf, size_t min_size, QPDFObjectHandle resources) : qpdf(qpdf), min_size(min_size), - resources(resources), - min_suffix(1), - any_images(false), - state(st_top) + resources(resources) { } @@ -451,7 +448,7 @@ QPDFPageObjectHelper::getAnnotations(std::string const& only_subtype) for (int i = 0; i < nannots; ++i) { QPDFObjectHandle annot = annots.getArrayItem(i); if (annot.isDictionaryOfType("", only_subtype)) { - result.push_back(QPDFAnnotationObjectHelper(annot)); + result.emplace_back(annot); } } } @@ -662,7 +659,7 @@ QPDFPageObjectHelper::shallowCopyPage() QPDF& qpdf = this->oh.getQPDF("QPDFPageObjectHelper::shallowCopyPage called with a direct object"); QPDFObjectHandle new_page = this->oh.shallowCopy(); - return QPDFPageObjectHelper(qpdf.makeIndirectObject(new_page)); + return {qpdf.makeIndirectObject(new_page)}; } QPDFObjectHandle::Matrix @@ -758,7 +755,7 @@ QPDFPageObjectHelper::getMatrixForFormXObjectPlacement( QPDFObjectHandle fdict = fo.getDict(); QPDFObjectHandle bbox_obj = fdict.getKey("/BBox"); if (!bbox_obj.isRectangle()) { - return QPDFMatrix(); + return {}; } QPDFMatrix wmatrix; // work matrix @@ -793,7 +790,7 @@ QPDFPageObjectHelper::getMatrixForFormXObjectPlacement( // Calculate a scale factor, if needed. Shrink or expand if needed and allowed. if ((T.urx == T.llx) || (T.ury == T.lly)) { // avoid division by zero - return QPDFMatrix(); + return {}; } double rect_w = rect.urx - rect.llx; double rect_h = rect.ury - rect.lly; diff --git a/libqpdf/QPDFParser.cc b/libqpdf/QPDFParser.cc index 48227e55..6dcbddb5 100644 --- a/libqpdf/QPDFParser.cc +++ b/libqpdf/QPDFParser.cc @@ -55,7 +55,7 @@ QPDFParser::parse(bool& empty, bool content_stream) bool set_offset = false; std::vector<StackFrame> stack; - stack.push_back(StackFrame(input)); + stack.emplace_back(input); std::vector<parser_state_e> state_stack; state_stack.push_back(st_top); qpdf_offset_t offset; @@ -141,7 +141,7 @@ QPDFParser::parse(bool& empty, bool content_stream) (tokenizer.getType() == QPDFTokenizer::tt_array_open) ? st_array : st_dictionary); b_contents = false; - stack.push_back(StackFrame(input)); + stack.emplace_back(input); } break; diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 782a0c49..db3b42e0 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -26,10 +26,9 @@ #include <cstdlib> #include <stdexcept> -QPDFWriter::ProgressReporter::~ProgressReporter() +QPDFWriter::ProgressReporter::~ProgressReporter() // NOLINT (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } QPDFWriter::FunctionProgressReporter::FunctionProgressReporter(std::function<void(int)> handler) : @@ -37,10 +36,10 @@ QPDFWriter::FunctionProgressReporter::FunctionProgressReporter(std::function<voi { } -QPDFWriter::FunctionProgressReporter::~FunctionProgressReporter() +QPDFWriter::FunctionProgressReporter::~FunctionProgressReporter() // NOLINT + // (modernize-use-equals-default) { - // Must be explicit and not inline -- see QPDF_DLL_CLASS in - // README-maintainer + // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer } void @@ -534,8 +533,8 @@ QPDFWriter::interpretR3EncryptionParameters( clear.insert(5); } - // Note: these switch statements all "fall through" (no break - // statements). Each option clears successively more access bits. + // Note: these switch statements all "fall through" (no break statements). Each option clears + // successively more access bits. switch (print) { case qpdf_r3p_none: clear.insert(3); // any printing @@ -549,11 +548,9 @@ QPDFWriter::interpretR3EncryptionParameters( // no default so gcc warns for missing cases } - // Modify options. The qpdf_r3_modify_e options control groups of - // bits and lack the full flexibility of the spec. This is - // unfortunate, but it's been in the API for ages, and we're stuck - // with it. See also allow checks below to control the bits - // individually. + // Modify options. The qpdf_r3_modify_e options control groups of bits and lack the full + // flexibility of the spec. This is unfortunate, but it's been in the API for ages, and we're + // stuck with it. See also allow checks below to control the bits individually. // NOT EXERCISED IN TEST SUITE switch (modify) { @@ -607,9 +604,8 @@ QPDFWriter::setEncryptionParameters( bits_to_clear.insert(2); if (R > 3) { - // Bit 10 is deprecated and should always be set. This used - // to mean accessibility. There is no way to disable - // accessibility with R > 3. + // Bit 10 is deprecated and should always be set. This used to mean accessibility. There + // is no way to disable accessibility with R > 3. bits_to_clear.erase(10); } @@ -669,12 +665,10 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) m->encrypt_metadata = encrypt.getKey("/EncryptMetadata").getBoolValue(); } if (V >= 4) { - // When copying encryption parameters, use AES even if the - // original file did not. Acrobat doesn't create files - // with V >= 4 that don't use AES, and the logic of - // figuring out whether AES is used or not is complicated - // with /StmF, /StrF, and /EFF all potentially having - // different values. + // When copying encryption parameters, use AES even if the original file did not. + // Acrobat doesn't create files with V >= 4 that don't use AES, and the logic of + // figuring out whether AES is used or not is complicated with /StmF, /StrF, and /EFF + // all potentially having different values. m->encrypt_use_aes = true; } QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", m->encrypt_metadata ? 0 : 1); @@ -757,11 +751,9 @@ QPDFWriter::parseVersion(std::string const& version, int& major, int& minor) con } std::string tmp = std::to_string(major) + "." + std::to_string(minor); if (tmp != version) { - // The version number in the input is probably invalid. This - // happens with some files that are designed to exercise bugs, - // such as files in the fuzzer corpus. Unfortunately - // QPDFWriter doesn't have a way to give a warning, so we just - // ignore this case. + // The version number in the input is probably invalid. This happens with some files that + // are designed to exercise bugs, such as files in the fuzzer corpus. Unfortunately + // QPDFWriter doesn't have a way to give a warning, so we just ignore this case. } } @@ -826,15 +818,13 @@ QPDFWriter::setEncryptionParametersInternal( m->encryption_dictionary["/EncryptMetadata"] = "false"; } if ((V == 4) || (V == 5)) { - // The spec says the value for the crypt filter key can be - // anything, and xpdf seems to agree. However, Adobe Reader - // won't open our files unless we use /StdCF. + // The spec says the value for the crypt filter key can be anything, and xpdf seems to + // agree. However, Adobe Reader won't open our files unless we use /StdCF. m->encryption_dictionary["/StmF"] = "/StdCF"; m->encryption_dictionary["/StrF"] = "/StdCF"; std::string method = (m->encrypt_use_aes ? ((V < 5) ? "/AESV2" : "/AESV3") : "/V2"); - // The PDF spec says the /Length key is optional, but the PDF - // previewer on some versions of MacOS won't open encrypted - // files without it. + // The PDF spec says the /Length key is optional, but the PDF previewer on some versions of + // MacOS won't open encrypted files without it. m->encryption_dictionary["/CF"] = "<< /StdCF << /AuthEvent /DocOpen /CFM " + method + " /Length " + std::string((V < 5) ? "16" : "32") + " >> >>"; } @@ -950,12 +940,10 @@ QPDFWriter::PipelinePopper::~PipelinePopper() qpdf_assert_debug(qw->m->pipeline_stack.size() >= 2); qw->m->pipeline->finish(); qpdf_assert_debug(dynamic_cast<Pl_Count*>(qw->m->pipeline_stack.back()) == qw->m->pipeline); - // It might be possible for this assertion to fail if - // writeLinearized exits by exception when deterministic ID, but I - // don't think so. As of this writing, this is the only case in - // which two dynamically allocated PipelinePopper objects ever - // exist at the same time, so the assertion will fail if they get - // popped out of order from automatic destruction. + // It might be possible for this assertion to fail if writeLinearized exits by exception when + // deterministic ID, but I don't think so. As of this writing, this is the only case in which + // two dynamically allocated PipelinePopper objects ever exist at the same time, so the + // assertion will fail if they get popped out of order from automatic destruction. qpdf_assert_debug(qw->m->pipeline->getIdentifier() == stack_id); delete qw->m->pipeline_stack.back(); qw->m->pipeline_stack.pop_back(); @@ -978,9 +966,8 @@ void QPDFWriter::adjustAESStreamLength(size_t& length) { if (m->encrypted && (!m->cur_data_key.empty()) && m->encrypt_use_aes) { - // Stream length will be padded with 1 to 16 bytes to end up - // as a multiple of 16. It will also be prepended by 16 bits - // of random data. + // Stream length will be padded with 1 to 16 bytes to end up as a multiple of 16. It will + // also be prepended by 16 bits of random data. length += 32 - (length & 0xf); } } @@ -1006,8 +993,8 @@ QPDFWriter::pushEncryptionFilter(PipelinePopper& pp) } pushPipeline(p); } - // Must call this unconditionally so we can call popPipelineStack - // to balance pushEncryptionFilter(). + // Must call this unconditionally so we can call popPipelineStack to balance + // pushEncryptionFilter(). activatePipelineStack(pp); } @@ -1031,8 +1018,7 @@ QPDFWriter::pushMD5Pipeline(PipelinePopper& pp) qpdf_assert_debug(m->pipeline->getCount() == 0); m->md5_pipeline = new Pl_MD5("qpdf md5", m->pipeline); m->md5_pipeline->persistAcrossFinish(true); - // Special case code in popPipelineStack clears m->md5_pipeline - // upon deletion. + // Special case code in popPipelineStack clears m->md5_pipeline upon deletion. pushPipeline(m->md5_pipeline); activatePipelineStack(pp); } @@ -1061,8 +1047,7 @@ QPDFWriter::openObject(int objid) void QPDFWriter::closeObject(int objid) { - // Write a newline before endobj as it makes the file easier to - // repair. + // Write a newline before endobj as it makes the file easier to repair. writeString("\nendobj\n"); writeStringQDF("\n"); m->lengths[objid] = m->pipeline->getCount() - m->xref[objid].getOffset(); @@ -1077,8 +1062,7 @@ QPDFWriter::assignCompressedObjectNumbers(QPDFObjGen const& og) return; } - // Reserve numbers for the objects that belong to this object - // stream. + // Reserve numbers for the objects that belong to this object stream. for (auto const& iter: m->object_stream_to_objects[objid]) { m->obj_renumber[iter] = m->next_objid++; } @@ -1088,26 +1072,21 @@ void QPDFWriter::enqueueObject(QPDFObjectHandle object) { if (object.isIndirect()) { - // This owner check can only be done for indirect objects. It - // is possible for a direct object to have an owning QPDF that - // is from another file if a direct QPDFObjectHandle from one - // file was insert into another file without copying. Doing - // that is safe even if the original QPDF gets destroyed, - // which just disconnects the QPDFObjectHandle from its owner. + // This owner check can only be done for indirect objects. It is possible for a direct + // object to have an owning QPDF that is from another file if a direct QPDFObjectHandle from + // one file was insert into another file without copying. Doing that is safe even if the + // original QPDF gets destroyed, which just disconnects the QPDFObjectHandle from its owner. if (object.getOwningQPDF() != &(m->pdf)) { QTC::TC("qpdf", "QPDFWriter foreign object"); - throw std::logic_error("QPDFObjectHandle from different QPDF found while writing." - " Use QPDF::copyForeignObject to add objects from" - " another file."); + throw std::logic_error("QPDFObjectHandle from different QPDF found while writing. Use " + "QPDF::copyForeignObject to add objects from another file."); } if (m->qdf_mode && object.isStreamOfType("/XRef")) { - // As a special case, do not output any extraneous XRef - // streams in QDF mode. Doing so will confuse fix-qdf, - // which expects to see only one XRef stream at the end of - // the file. This case can occur when creating a QDF from - // a file with object streams when preserving unreferenced - // objects since the old cross reference streams are not + // As a special case, do not output any extraneous XRef streams in QDF mode. Doing so + // will confuse fix-qdf, which expects to see only one XRef stream at the end of the + // file. This case can occur when creating a QDF from a file with object streams when + // preserving unreferenced objects since the old cross reference streams are not // actually referenced by object number. QTC::TC("qpdf", "QPDFWriter ignore XRef in qdf mode"); return; @@ -1117,12 +1096,10 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) if (m->obj_renumber.count(og) == 0) { if (m->object_to_object_stream.count(og)) { - // This is in an object stream. Don't process it - // here. Instead, enqueue the object stream. Object - // streams always have generation 0. + // This is in an object stream. Don't process it here. Instead, enqueue the object + // stream. Object streams always have generation 0. int stream_id = m->object_to_object_stream[og]; - // Detect loops by storing invalid object ID 0, which - // will get overwritten later. + // Detect loops by storing invalid object ID 0, which will get overwritten later. m->obj_renumber[og] = 0; enqueueObject(m->pdf.getObjectByID(stream_id, 0)); } else { @@ -1130,9 +1107,8 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) m->obj_renumber[og] = m->next_objid++; if ((og.getGen() == 0) && m->object_stream_to_objects.count(og.getObj())) { - // For linearized files, uncompressed objects go - // at end, and we take care of assigning numbers - // to them elsewhere. + // For linearized files, uncompressed objects go at end, and we take care of + // assigning numbers to them elsewhere. if (!m->linearized) { assignCompressedObjectNumbers(og); } @@ -1142,8 +1118,8 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) } } } else if (m->obj_renumber[og] == 0) { - // This can happen if a specially constructed file - // indicates that an object stream is inside itself. + // This can happen if a specially constructed file indicates that an object stream is + // inside itself. QTC::TC("qpdf", "QPDFWriter ignore self-referential object stream"); } return; @@ -1223,12 +1199,10 @@ QPDFWriter::writeTrailer( if (original_id1.empty()) { writeString("<00000000000000000000000000000000>"); } else { - // Write a string of zeroes equal in length to the - // representation of the original ID. While writing the - // original ID would have the same number of bytes, it - // would cause a change to the deterministic ID generated - // by older versions of the software that hard-coded the - // length of the ID to 16 bytes. + // Write a string of zeroes equal in length to the representation of the original ID. + // While writing the original ID would have the same number of bytes, it would cause a + // change to the deterministic ID generated by older versions of the software that + // hard-coded the length of the ID to 16 bytes. writeString("<"); size_t len = QPDF_String(original_id1).unparse(true).length() - 2; for (size_t i = 0; i < len; ++i) { @@ -1284,11 +1258,9 @@ QPDFWriter::willFilterStream( filter = false; } if (filter_on_write && m->compress_streams) { - // Don't filter if the stream is already compressed with - // FlateDecode. This way we don't make it worse if the - // original file used a better Flate algorithm, and we - // don't spend time and CPU cycles uncompressing and - // recompressing stuff. This can be overridden with + // Don't filter if the stream is already compressed with FlateDecode. This way we don't make + // it worse if the original file used a better Flate algorithm, and we don't spend time and + // CPU cycles uncompressing and recompressing stuff. This can be overridden with // setRecompressFlate(true). QPDFObjectHandle filter_obj = stream_dict.getKey("/Filter"); if ((!m->recompress_flate) && (!stream.isDataModified()) && filter_obj.isName() && @@ -1351,8 +1323,8 @@ QPDFWriter::unparseObject( if (level < 0) { throw std::logic_error("invalid level in QPDFWriter::unparseObject"); } - // For non-qdf, "indent" is a single space between tokens. - // For qdf, indent includes the preceding newline. + // For non-qdf, "indent" is a single space between tokens. For qdf, indent includes the + // preceding newline. std::string indent = " "; if (m->qdf_mode) { indent.append(static_cast<size_t>(2 * level), ' '); @@ -1360,11 +1332,9 @@ QPDFWriter::unparseObject( } if (auto const tc = object.getTypeCode(); tc == ::ot_array) { - // Note: PDF spec 1.4 implementation note 121 states that - // Acrobat requires a space after the [ in the /H key of the - // linearization parameter dictionary. We'll do this - // unconditionally for all arrays because it looks nicer and - // doesn't make the files that much bigger. + // Note: PDF spec 1.4 implementation note 121 states that Acrobat requires a space after the + // [ in the /H key of the linearization parameter dictionary. We'll do this unconditionally + // for all arrays because it looks nicer and doesn't make the files that much bigger. writeString("["); for (auto const& item: object.getArrayAsVector()) { writeString(indent); @@ -1374,13 +1344,11 @@ QPDFWriter::unparseObject( writeString(indent); writeString("]"); } else if (tc == ::ot_dictionary) { - // Make a shallow copy of this object so we can modify it - // safely without affecting the original. This code has logic - // to skip certain keys in agreement with prepareFileForWrite - // and with skip_stream_parameters so that replacing them - // doesn't leave unreferenced objects in the output. We can - // use unsafeShallowCopy here because we are all we are doing - // is removing or replacing top-level keys. + // Make a shallow copy of this object so we can modify it safely without affecting the + // original. This code has logic to skip certain keys in agreement with prepareFileForWrite + // and with skip_stream_parameters so that replacing them doesn't leave unreferenced objects + // in the output. We can use unsafeShallowCopy here because all we are doing is removing or + // replacing top-level keys. object = object.unsafeShallowCopy(); // Handle special cases for specific dictionaries. @@ -1400,9 +1368,8 @@ QPDFWriter::unparseObject( // - If it has other things, keep those and remove ADBE // - We have no extensions: no action required // - // Before writing, we guarantee that /Extensions, if present, - // is direct through the ADBE dictionary, so we can modify in - // place. + // Before writing, we guarantee that /Extensions, if present, is direct through the ADBE + // dictionary, so we can modify in place. const bool is_root = (old_og == m->root_og); bool have_extensions_other = false; @@ -1431,8 +1398,7 @@ QPDFWriter::unparseObject( if (is_root) { if (need_extensions_adbe) { if (!(have_extensions_other || have_extensions_adbe)) { - // We need Extensions and don't have it. Create - // it here. + // We need Extensions and don't have it. Create it here. QTC::TC("qpdf", "QPDFWriter create Extensions", m->qdf_mode ? 0 : 1); extensions = object.replaceKeyAndGetNew( "/Extensions", QPDFObjectHandle::newDictionary()); @@ -1488,8 +1454,8 @@ QPDFWriter::unparseObject( object.removeKey("/Filter"); object.removeKey("/DecodeParms"); } else { - // Make sure, no matter what else we have, that we - // don't have /Crypt in the output filters. + // Make sure, no matter what else we have, that we don't have /Crypt in the output + // filters. QPDFObjectHandle filter = object.getKey("/Filter"); QPDFObjectHandle decode_parms = object.getKey("/DecodeParms"); if (filter.isOrHasName("/Crypt")) { @@ -1506,12 +1472,10 @@ QPDFWriter::unparseObject( } } if (idx >= 0) { - // If filter is an array, then the code in - // QPDF_Stream has already verified that - // DecodeParms and Filters are arrays of - // the same length, but if they weren't - // for some reason, eraseItem does type - // and bounds checking. + // If filter is an array, then the code in QPDF_Stream has already + // verified that DecodeParms and Filters are arrays of the same length, + // but if they weren't for some reason, eraseItem does type and bounds + // checking. QTC::TC("qpdf", "QPDFWriter remove Crypt"); filter.eraseItem(idx); decode_parms.eraseItem(idx); @@ -1659,8 +1623,8 @@ QPDFWriter::writeObjectStreamOffsets(std::vector<qpdf_offset_t>& offsets, int fi void QPDFWriter::writeObjectStream(QPDFObjectHandle object) { - // Note: object might be null if this is a place-holder for an - // object stream that we are generating from scratch. + // Note: object might be null if this is a place-holder for an object stream that we are + // generating from scratch. QPDFObjGen old_og = object.getObjGen(); qpdf_assert_debug(old_og.getGen() == 0); @@ -1670,8 +1634,8 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) std::vector<qpdf_offset_t> offsets; qpdf_offset_t first = 0; - // Generate stream itself. We have to do this in two passes so we - // can calculate offsets in the first pass. + // Generate stream itself. We have to do this in two passes so we can calculate offsets in the + // first pass. std::shared_ptr<Buffer> stream_buffer; int first_obj = -1; bool compressed = false; @@ -1687,8 +1651,7 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) iter -= first; } - // Take one pass at writing pairs of numbers so we can get - // their size information + // Take one pass at writing pairs of numbers so we can get their size information { PipelinePopper pp_discard(this); pushDiscardFilter(pp_discard); @@ -1721,11 +1684,9 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) std::to_string(count)); if (!m->suppress_original_object_ids) { writeString("; original object ID: " + std::to_string(obj.getObj())); - // For compatibility, only write the generation if - // non-zero. While object streams only allow - // objects with generation 0, if we are generating - // object streams, the old object could have a - // non-zero generation. + // For compatibility, only write the generation if non-zero. While object + // streams only allow objects with generation 0, if we are generating object + // streams, the old object could have a non-zero generation. if (obj.getGen() != 0) { QTC::TC("qpdf", "QPDFWriter original obj non-zero gen"); writeString(" " + std::to_string(obj.getGen())); @@ -1735,16 +1696,14 @@ QPDFWriter::writeObjectStream(QPDFObjectHandle object) } if (pass == 1) { offsets.push_back(m->pipeline->getCount()); - // To avoid double-counting objects being written in - // object streams for progress reporting, decrement in - // pass 1. + // To avoid double-counting objects being written in object streams for progress + // reporting, decrement in pass 1. indicateProgress(true, false); } QPDFObjectHandle obj_to_write = m->pdf.getObject(obj); if (obj_to_write.isStream()) { - // This condition occurred in a fuzz input. Ideally we - // should block it at at parse time, but it's not - // clear to me how to construct a case for this. + // This condition occurred in a fuzz input. Ideally we should block it at parse + // time, but it's not clear to me how to construct a case for this. QTC::TC("qpdf", "QPDFWriter stream in ostream"); obj_to_write.warnIfPossible("stream found inside object stream; treating as null"); obj_to_write = QPDFObjectHandle::newNull(); @@ -1867,8 +1826,8 @@ QPDFWriter::getOriginalID1() void QPDFWriter::generateID() { - // Generate the ID lazily so that we can handle the user's - // preference to use static or deterministic ID generation. + // Generate the ID lazily so that we can handle the user's preference to use static or + // deterministic ID generation. if (!m->id2.empty()) { return; @@ -1900,27 +1859,22 @@ QPDFWriter::generateID() 0x00}; result = reinterpret_cast<char*>(tmp); } else { - // The PDF specification has guidelines for creating IDs, but - // it states clearly that the only thing that's really - // important is that it is very likely to be unique. We can't - // really follow the guidelines in the spec exactly because we - // haven't written the file yet. This scheme should be fine - // though. The deterministic ID case uses a digest of a - // sufficient portion of the file's contents such no two - // non-matching files would match in the subsets used for this - // computation. Note that we explicitly omit the filename from - // the digest calculation for deterministic ID so that the same - // file converted with qpdf, in that case, would have the same - // ID regardless of the output file's name. + // The PDF specification has guidelines for creating IDs, but it states clearly that the + // only thing that's really important is that it is very likely to be unique. We can't + // really follow the guidelines in the spec exactly because we haven't written the file yet. + // This scheme should be fine though. The deterministic ID case uses a digest of a + // sufficient portion of the file's contents such no two non-matching files would match in + // the subsets used for this computation. Note that we explicitly omit the filename from + // the digest calculation for deterministic ID so that the same file converted with qpdf, in + // that case, would have the same ID regardless of the output file's name. std::string seed; if (m->deterministic_id) { if (m->deterministic_id_data.empty()) { QTC::TC("qpdf", "QPDFWriter deterministic with no data"); - throw std::logic_error("INTERNAL ERROR: QPDFWriter::generateID has no" - " data for deterministic ID. This may happen if" - " deterministic ID and file encryption are requested" - " together."); + throw std::logic_error("INTERNAL ERROR: QPDFWriter::generateID has no data for " + "deterministic ID. This may happen if deterministic ID and " + "file encryption are requested together."); } seed += m->deterministic_id_data; } else { @@ -1947,9 +1901,8 @@ QPDFWriter::generateID() result = std::string(reinterpret_cast<char*>(digest), sizeof(MD5::Digest)); } - // If /ID already exists, follow the spec: use the original first - // word and generate a new second word. Otherwise, we'll use the - // generated ID for both. + // If /ID already exists, follow the spec: use the original first word and generate a new second + // word. Otherwise, we'll use the generated ID for both. m->id2 = result; // Note: keep /ID from old file even if --static-id was given. @@ -1994,16 +1947,13 @@ QPDFWriter::preserveObjectStreams() if (omap.empty()) { return; } - // Our object_to_object_stream map has to map ObjGen -> ObjGen - // since we may be generating object streams out of old objects - // that have generation numbers greater than zero. However in an - // existing PDF, all object stream objects and all objects in them - // must have generation 0 because the PDF spec does not provide - // any way to do otherwise. This code filters out objects that are - // not allowed to be in object streams. In addition to removing - // objects that were erroneously included in object streams in the - // source PDF, it also prevents unreferenced objects from being - // included. + // Our object_to_object_stream map has to map ObjGen -> ObjGen since we may be generating object + // streams out of old objects that have generation numbers greater than zero. However in an + // existing PDF, all object stream objects and all objects in them must have generation 0 + // because the PDF spec does not provide any way to do otherwise. This code filters out objects + // that are not allowed to be in object streams. In addition to removing objects that were + // erroneously included in object streams in the source PDF, it also prevents unreferenced + // objects from being included. std::set<QPDFObjGen> eligible; if (!m->preserve_unreferenced_objects) { std::vector<QPDFObjGen> eligible_v = QPDF::Writer::getCompressibleObjGens(m->pdf); @@ -2023,13 +1973,11 @@ QPDFWriter::preserveObjectStreams() void QPDFWriter::generateObjectStreams() { - // Basic strategy: make a list of objects that can go into an - // object stream. Then figure out how many object streams are - // needed so that we can distribute objects approximately evenly - // without having any object stream exceed 100 members. We don't - // have to worry about linearized files here -- if the file is - // linearized, we take care of excluding things that aren't - // allowed here later. + // Basic strategy: make a list of objects that can go into an object stream. Then figure out + // how many object streams are needed so that we can distribute objects approximately evenly + // without having any object stream exceed 100 members. We don't have to worry about linearized + // files here -- if the file is linearized, we take care of excluding things that aren't allowed + // here later. // This code doesn't do anything with /Extends. @@ -2052,9 +2000,8 @@ QPDFWriter::generateObjectStreams() n = 0; } if (n == 0) { - // Construct a new null object as the "original" object - // stream. The rest of the code knows that this means - // we're creating the object stream from scratch. + // Construct a new null object as the "original" object stream. The rest of the code + // knows that this means we're creating the object stream from scratch. cur_ostream = m->pdf.makeIndirectObject(QPDFObjectHandle::newNull()).getObjectID(); } m->object_to_object_stream[iter] = cur_ostream; @@ -2065,8 +2012,7 @@ QPDFWriter::generateObjectStreams() QPDFObjectHandle QPDFWriter::getTrimmedTrailer() { - // Remove keys from the trailer that necessarily have to be - // replaced when writing the file. + // Remove keys from the trailer that necessarily have to be replaced when writing the file. QPDFObjectHandle trailer = m->pdf.getTrailer().unsafeShallowCopy(); @@ -2077,8 +2023,7 @@ QPDFWriter::getTrimmedTrailer() // Remove modification information trailer.removeKey("/Prev"); - // Remove all trailer keys that potentially come from a - // cross-reference stream + // Remove all trailer keys that potentially come from a cross-reference stream trailer.removeKey("/Index"); trailer.removeKey("/W"); trailer.removeKey("/Length"); @@ -2090,30 +2035,25 @@ QPDFWriter::getTrimmedTrailer() return trailer; } +// Make document extension level information direct as required by the spec. void QPDFWriter::prepareFileForWrite() { - // Make document extension level information direct as required by - // the spec. - m->pdf.fixDanglingReferences(); - QPDFObjectHandle root = m->pdf.getRoot(); - for (auto const& key: root.getKeys()) { - QPDFObjectHandle oh = root.getKey(key); - if ((key == "/Extensions") && (oh.isDictionary())) { - bool extensions_indirect = false; - if (oh.isIndirect()) { - QTC::TC("qpdf", "QPDFWriter make Extensions direct"); - extensions_indirect = true; - oh = root.replaceKeyAndGetNew(key, oh.shallowCopy()); - } - if (oh.hasKey("/ADBE")) { - QPDFObjectHandle adbe = oh.getKey("/ADBE"); - if (adbe.isIndirect()) { - QTC::TC("qpdf", "QPDFWriter make ADBE direct", extensions_indirect ? 0 : 1); - adbe.makeDirect(); - oh.replaceKey("/ADBE", adbe); - } + auto root = m->pdf.getRoot(); + auto oh = root.getKey("/Extensions"); + if (oh.isDictionary()) { + const bool extensions_indirect = oh.isIndirect(); + if (extensions_indirect) { + QTC::TC("qpdf", "QPDFWriter make Extensions direct"); + oh = root.replaceKeyAndGetNew("/Extensions", oh.shallowCopy()); + } + if (oh.hasKey("/ADBE")) { + auto adbe = oh.getKey("/ADBE"); + if (adbe.isIndirect()) { + QTC::TC("qpdf", "QPDFWriter make ADBE direct", extensions_indirect ? 0 : 1); + adbe.makeDirect(); + oh.replaceKey("/ADBE", adbe); } } } @@ -2155,8 +2095,8 @@ QPDFWriter::doWriteSetup() // Encryption has been explicitly set m->preserve_encryption = false; } else if (m->normalize_content || m->stream_decode_level || m->pclm || m->qdf_mode) { - // Encryption makes looking at contents pretty useless. If - // the user explicitly encrypted though, we still obey that. + // Encryption makes looking at contents pretty useless. If the user explicitly encrypted + // though, we still obey that. m->preserve_encryption = false; } @@ -2180,9 +2120,8 @@ QPDFWriter::doWriteSetup() } if (m->qdf_mode) { - // Generate indirect stream lengths for qdf mode since fix-qdf - // uses them for storing recomputed stream length data. - // Certain streams such as object streams, xref streams, and + // Generate indirect stream lengths for qdf mode since fix-qdf uses them for storing + // recomputed stream length data. Certain streams such as object streams, xref streams, and // hint streams always get direct stream lengths. m->direct_stream_lengths = false; } @@ -2215,11 +2154,10 @@ QPDFWriter::doWriteSetup() } if (m->linearized || m->encrypted) { - // The document catalog is not allowed to be compressed in - // linearized files either. It also appears that Adobe Reader - // 8.0.0 has a bug that prevents it from being able to handle - // encrypted files with compressed document catalogs, so we - // disable them in that case as well. + // The document catalog is not allowed to be compressed in linearized files either. It also + // appears that Adobe Reader 8.0.0 has a bug that prevents it from being able to handle + // encrypted files with compressed document catalogs, so we disable them in that case as + // well. if (m->object_to_object_stream.count(m->root_og)) { QTC::TC("qpdf", "QPDFWriter uncompressing root"); m->object_to_object_stream.erase(m->root_og); @@ -2254,9 +2192,8 @@ QPDFWriter::write() { doWriteSetup(); - // Set up progress reporting. For linearized files, we write two - // passes. events_expected is an approximation, but it's good - // enough for progress reporting, which is mostly a guess anyway. + // Set up progress reporting. For linearized files, we write two passes. events_expected is an + // approximation, but it's good enough for progress reporting, which is mostly a guess anyway. m->events_expected = QIntC::to_int(m->pdf.getObjectCount() * (m->linearized ? 2 : 1)); prepareFileForWrite(); @@ -2338,17 +2275,16 @@ QPDFWriter::writeHeader() // PCLm version writeString("\n%PCLm 1.0\n"); } else { - // This string of binary characters would not be valid UTF-8, so - // it really should be treated as binary. + // This string of binary characters would not be valid UTF-8, so it really should be treated + // as binary. writeString("\n%\xbf\xf7\xa2\xfe\n"); } writeStringQDF("%QDF-1.0\n\n"); - // Note: do not write extra header text here. Linearized PDFs - // must include the entire linearization parameter dictionary - // within the first 1024 characters of the PDF file, so for - // linearized files, we have to write extra header text after the - // linearization parameter dictionary. + // Note: do not write extra header text here. Linearized PDFs must include the entire + // linearization parameter dictionary within the first 1024 characters of the PDF file, so for + // linearized files, we have to write extra header text after the linearization parameter + // dictionary. } void @@ -2397,9 +2333,8 @@ QPDFWriter::writeHintStream(int hint_id) qpdf_offset_t QPDFWriter::writeXRefTable(trailer_e which, int first, int last, int size) { - // There are too many extra arguments to replace overloaded - // function with defaults in the header file...too much risk of - // leaving something off. + // There are too many extra arguments to replace overloaded function with defaults in the header + // file...too much risk of leaving something off. return writeXRefTable(which, first, last, size, 0, false, 0, 0, 0, 0); } @@ -2446,9 +2381,8 @@ qpdf_offset_t QPDFWriter::writeXRefStream( int objid, int max_id, qpdf_offset_t max_offset, trailer_e which, int first, int last, int size) { - // There are too many extra arguments to replace overloaded - // function with defaults in the header file...too much risk of - // leaving something off. + // There are too many extra arguments to replace overloaded function with defaults in the header + // file...too much risk of leaving something off. return writeXRefStream( objid, max_id, max_offset, which, first, last, size, 0, 0, 0, 0, false, 0); } @@ -2480,8 +2414,8 @@ QPDFWriter::writeXRefStream( unsigned int esize = 1 + f1_size + f2_size; - // Must store in xref table in advance of writing the actual data - // rather than waiting for openObject to do it. + // Must store in xref table in advance of writing the actual data rather than waiting for + // openObject to do it. m->xref[xref_id] = QPDFXRefEntry(m->pipeline->getCount()); Pipeline* p = pushPipeline(new Pl_Buffer("xref stream")); @@ -2489,9 +2423,8 @@ QPDFWriter::writeXRefStream( if ((m->compress_streams || (m->stream_decode_level == qpdf_dl_none)) && (!m->qdf_mode)) { compressed = true; if (!skip_compression) { - // Write the stream dictionary for compression but don't - // actually compress. This helps us with computation of - // padding for pass 1 of linearization. + // Write the stream dictionary for compression but don't actually compress. This helps + // us with computation of padding for pass 1 of linearization. p = pushPipeline(new Pl_Flate("compress xref", p, Pl_Flate::a_deflate)); } p = pushPipeline(new Pl_PNGFilter("pngify xref", p, Pl_PNGFilter::a_encode, esize)); @@ -2563,13 +2496,11 @@ QPDFWriter::writeXRefStream( size_t QPDFWriter::calculateXrefStreamPadding(qpdf_offset_t xref_bytes) { - // This routine is called right after a linearization first pass - // xref stream has been written without compression. Calculate - // the amount of padding that would be required in the worst case, - // assuming the number of uncompressed bytes remains the same. - // The worst case for zlib is that the output is larger than the - // input by 6 bytes plus 5 bytes per 16K, and then we'll add 10 - // extra bytes for number length increases. + // This routine is called right after a linearization first pass xref stream has been written + // without compression. Calculate the amount of padding that would be required in the worst + // case, assuming the number of uncompressed bytes remains the same. The worst case for zlib is + // that the output is larger than the input by 6 bytes plus 5 bytes per 16K, and then we'll add + // 10 extra bytes for number length increases. return QIntC::to_size(16 + (5 * ((xref_bytes + 16383) / 16384))); } @@ -2577,17 +2508,14 @@ QPDFWriter::calculateXrefStreamPadding(qpdf_offset_t xref_bytes) void QPDFWriter::discardGeneration(std::map<QPDFObjGen, int> const& in, std::map<int, int>& out) { - // There are deep assumptions in the linearization code in QPDF - // that there is only one object with each object number; i.e., - // you can't have two objects with the same object number and - // different generations. This is a pretty safe assumption - // because Adobe Reader and Acrobat can't actually handle this - // case. There is not much if any code in QPDF outside - // linearization that assumes this, but the linearization code as - // currently implemented would do weird things if we found such a - // case. In order to avoid breaking ABI changes in QPDF, we will - // first assert that this condition holds. Then we can create new - // maps for QPDF that throw away generation numbers. + // There are deep assumptions in the linearization code in QPDF that there is only one object + // with each object number; i.e., you can't have two objects with the same object number and + // different generations. This is a pretty safe assumption because Adobe Reader and Acrobat + // can't actually handle this case. There is not much if any code in QPDF outside linearization + // that assumes this, but the linearization code as currently implemented would do weird things + // if we found such a case. In order to avoid breaking ABI changes in QPDF, we will first + // assert that this condition holds. Then we can create new maps for QPDF that throw away + // generation numbers. out.clear(); for (auto const& iter: in) { @@ -2707,25 +2635,21 @@ QPDFWriter::writeLinearized() m->next_objid = part4_first_obj; enqueuePart(part4); if (m->next_objid != after_part4) { - // This can happen with very botched files as in the fuzzer - // test. There are likely some faulty assumptions in - // calculateLinearizationData - throw std::runtime_error("error encountered after" - " writing part 4 of linearized data"); + // This can happen with very botched files as in the fuzzer test. There are likely some + // faulty assumptions in calculateLinearizationData + throw std::runtime_error("error encountered after writing part 4 of linearized data"); } m->next_objid = part6_first_obj; enqueuePart(part6); if (m->next_objid != after_part6) { - throw std::runtime_error("error encountered after" - " writing part 6 of linearized data"); + throw std::runtime_error("error encountered after writing part 6 of linearized data"); } m->next_objid = second_half_first_obj; enqueuePart(part7); enqueuePart(part8); enqueuePart(part9); if (m->next_objid != after_second_half) { - throw std::runtime_error("error encountered after" - " writing part 9 of linearized data"); + throw std::runtime_error("error encountered after writing part 9 of linearized data"); } qpdf_offset_t hint_length = 0; @@ -2754,13 +2678,11 @@ QPDFWriter::writeLinearized() writeHeader(); - // Part 2: linearization parameter dictionary. Save enough - // space to write real dictionary. 200 characters is enough - // space if all numerical values in the parameter dictionary - // that contain offsets are 20 digits long plus a few extra - // characters for safety. The entire linearization parameter - // dictionary must appear within the first 1024 characters of - // the file. + // Part 2: linearization parameter dictionary. Save enough space to write real dictionary. + // 200 characters is enough space if all numerical values in the parameter dictionary that + // contain offsets are 20 digits long plus a few extra characters for safety. The entire + // linearization parameter dictionary must appear within the first 1024 characters of the + // file. qpdf_offset_t pos = m->pipeline->getCount(); openObject(lindict_id); @@ -2772,8 +2694,7 @@ QPDFWriter::writeLinearized() writeString(" /Linearized 1 /L "); writeString(std::to_string(file_size + hint_length)); - // Implementation note 121 states that a space is - // mandatory after this open bracket. + // Implementation note 121 states that a space is mandatory after this open bracket. writeString(" /H [ "); writeString(std::to_string(m->xref[hint_id].getOffset())); writeString(" "); @@ -2793,8 +2714,8 @@ QPDFWriter::writeLinearized() writePad(QIntC::to_size(pos - m->pipeline->getCount() + pad)); writeString("\n"); - // If the user supplied any additional header text, write it - // here after the linearization parameter dictionary. + // If the user supplied any additional header text, write it here after the linearization + // parameter dictionary. writeString(m->extra_header_text); // Part 3: first page cross reference table and trailer. @@ -2807,14 +2728,11 @@ QPDFWriter::writeLinearized() if (need_xref_stream) { // Must pad here too. if (pass == 1) { - // Set first_half_max_obj_offset to a value large - // enough to force four bytes to be reserved for each - // file offset. This would provide adequate space for - // the xref stream as long as the last object in page - // 1 starts with in the first 4 GB of the file, which - // is extremely likely. In the second pass, we will - // know the actual value for this, but it's okay if - // it's smaller. + // Set first_half_max_obj_offset to a value large enough to force four bytes to be + // reserved for each file offset. This would provide adequate space for the xref + // stream as long as the last object in page 1 starts with in the first 4 GB of the + // file, which is extremely likely. In the second pass, we will know the actual + // value for this, but it's okay if it's smaller. first_half_max_obj_offset = 1 << 25; } pos = m->pipeline->getCount(); @@ -2834,13 +2752,11 @@ QPDFWriter::writeLinearized() pass); qpdf_offset_t endpos = m->pipeline->getCount(); if (pass == 1) { - // Pad so we have enough room for the real xref - // stream. + // Pad so we have enough room for the real xref stream. writePad(calculateXrefStreamPadding(endpos - pos)); first_xref_end = m->pipeline->getCount(); } else { - // Pad so that the next object starts at the same - // place as in pass 1. + // Pad so that the next object starts at the same place as in pass 1. writePad(QIntC::to_size(first_xref_end - endpos)); if (m->pipeline->getCount() != first_xref_end) { @@ -2913,9 +2829,8 @@ QPDFWriter::writeLinearized() qpdf_offset_t endpos = m->pipeline->getCount(); if (pass == 1) { - // Pad so we have enough room for the real xref - // stream. See comments for previous xref stream on - // how we calculate the padding. + // Pad so we have enough room for the real xref stream. See comments for previous + // xref stream on how we calculate the padding. writePad(calculateXrefStreamPadding(endpos - pos)); writeString("\n"); second_xref_end = m->pipeline->getCount(); @@ -2925,11 +2840,10 @@ QPDFWriter::writeLinearized() QIntC::to_size(second_xref_end + hint_length - 1 - m->pipeline->getCount())); writeString("\n"); - // If this assertion fails, maybe we didn't have - // enough padding above. + // If this assertion fails, maybe we didn't have enough padding above. if (m->pipeline->getCount() != second_xref_end + hint_length) { - throw std::logic_error("count mismatch after xref stream;" - " possible insufficient padding?"); + throw std::logic_error( + "count mismatch after xref stream; possible insufficient padding?"); } } } else { @@ -2954,8 +2868,7 @@ QPDFWriter::writeLinearized() file_size = m->pipeline->getCount(); pp_pass1 = nullptr; - // Save hint offset since it will be set to zero by - // calling openObject. + // Save hint offset since it will be set to zero by calling openObject. qpdf_offset_t hint_offset1 = m->xref[hint_id].getOffset(); // Write hint stream to a buffer @@ -3003,10 +2916,8 @@ QPDFWriter::enqueueObjectsStandard() QPDFObjectHandle trailer = getTrimmedTrailer(); enqueueObject(trailer.getKey("/Root")); - // Next place any other objects referenced from the trailer - // dictionary into the queue, handling direct objects recursively. - // Root is already there, so enqueuing it a second time is a - // no-op. + // Next place any other objects referenced from the trailer dictionary into the queue, handling + // direct objects recursively. Root is already there, so enqueuing it a second time is a no-op. for (auto const& key: trailer.getKeys()) { enqueueObject(trailer.getKey(key)); } @@ -3015,9 +2926,8 @@ QPDFWriter::enqueueObjectsStandard() void QPDFWriter::enqueueObjectsPCLm() { - // Image transform stream content for page strip images. - // Each of this new stream has to come after every page image - // strip written in the pclm file. + // Image transform stream content for page strip images. Each of this new stream has to come + // after every page image strip written in the pclm file. std::string image_transform_content = "q /image Do Q\n"; // enqueue all pages first diff --git a/libqpdf/QPDFXRefEntry.cc b/libqpdf/QPDFXRefEntry.cc index 7be98b2a..731ad405 100644 --- a/libqpdf/QPDFXRefEntry.cc +++ b/libqpdf/QPDFXRefEntry.cc @@ -3,7 +3,7 @@ #include <qpdf/QIntC.hh> #include <qpdf/QPDFExc.hh> -QPDFXRefEntry::QPDFXRefEntry() +QPDFXRefEntry::QPDFXRefEntry() // NOLINT (modernize-use-equals-default) { } diff --git a/libqpdf/QPDF_Array.cc b/libqpdf/QPDF_Array.cc index 760db2e2..b5b182af 100644 --- a/libqpdf/QPDF_Array.cc +++ b/libqpdf/QPDF_Array.cc @@ -12,9 +12,9 @@ QPDF_Array::checkOwnership(QPDFObjectHandle const& item) const if (qpdf) { if (auto item_qpdf = obj->getQPDF()) { if (qpdf != item_qpdf) { - throw std::logic_error("Attempting to add an object from a different QPDF. " - "Use QPDF::copyForeignObject to add objects from " - "another file."); + throw std::logic_error( + "Attempting to add an object from a different QPDF. Use " + "QPDF::copyForeignObject to add objects from another file."); } } } @@ -201,7 +201,7 @@ QPDF_Array::getAsVector() const v.reserve(size_t(size())); for (auto const& item: sp_elements) { v.resize(size_t(item.first), null_oh); - v.push_back(item.second); + v.emplace_back(item.second); } v.resize(size_t(size()), null_oh); return v; diff --git a/libqpdf/QPDF_Dictionary.cc b/libqpdf/QPDF_Dictionary.cc index 6d259ef5..7700b81b 100644 --- a/libqpdf/QPDF_Dictionary.cc +++ b/libqpdf/QPDF_Dictionary.cc @@ -89,8 +89,7 @@ QPDF_Dictionary::hasKey(std::string const& key) QPDFObjectHandle QPDF_Dictionary::getKey(std::string const& key) { - // PDF spec says fetching a non-existent key from a dictionary - // returns the null object. + // PDF spec says fetching a non-existent key from a dictionary returns the null object. auto item = this->items.find(key); if (item != this->items.end()) { // May be a null object @@ -123,8 +122,7 @@ void QPDF_Dictionary::replaceKey(std::string const& key, QPDFObjectHandle value) { if (value.isNull()) { - // The PDF spec doesn't distinguish between keys with null - // values and missing keys. + // The PDF spec doesn't distinguish between keys with null values and missing keys. removeKey(key); } else { // add or replace value diff --git a/libqpdf/QPDF_Name.cc b/libqpdf/QPDF_Name.cc index 8e439213..4597372e 100644 --- a/libqpdf/QPDF_Name.cc +++ b/libqpdf/QPDF_Name.cc @@ -32,8 +32,7 @@ QPDF_Name::normalizeName(std::string const& name) char ch = name.at(i); // Don't use locale/ctype here; follow PDF spec guidelines. if (ch == '\0') { - // QPDFTokenizer embeds a null character to encode an - // invalid #. + // QPDFTokenizer embeds a null character to encode an invalid #. result += "#"; } else if ( ch < 33 || ch == '#' || ch == '/' || ch == '(' || ch == ')' || ch == '{' || ch == '}' || diff --git a/libqpdf/QPDF_Real.cc b/libqpdf/QPDF_Real.cc index 19b65a7e..1d954dcd 100644 --- a/libqpdf/QPDF_Real.cc +++ b/libqpdf/QPDF_Real.cc @@ -41,9 +41,8 @@ QPDF_Real::unparse() JSON QPDF_Real::getJSON(int json_version) { - // While PDF allows .x or -.x, JSON does not. Rather than - // converting from string to double and back, just handle this as a - // special case for JSON. + // While PDF allows .x or -.x, JSON does not. Rather than converting from string to double and + // back, just handle this as a special case for JSON. std::string result; if (this->val.length() == 0) { // Can't really happen... diff --git a/libqpdf/QPDF_String.cc b/libqpdf/QPDF_String.cc index 386d7672..3886b399 100644 --- a/libqpdf/QPDF_String.cc +++ b/libqpdf/QPDF_String.cc @@ -2,9 +2,8 @@ #include <qpdf/QUtil.hh> -// DO NOT USE ctype -- it is locale dependent for some things, and -// it's not worth the risk of including it in case it may accidentally -// be used. +// DO NOT USE ctype -- it is locale dependent for some things, and it's not worth the risk of +// including it in case it may accidentally be used. static bool is_iso_latin1_printable(char ch) @@ -62,8 +61,7 @@ QPDF_String::getJSON(int json_version) } else if (!useHexString()) { std::string test; if (QUtil::utf8_to_pdf_doc(candidate, test, '?') && (test == this->val)) { - // This is a PDF-doc string that can be losslessly encoded - // as Unicode. + // This is a PDF-doc string that can be losslessly encoded as Unicode. is_unicode = true; result = candidate; } @@ -79,9 +77,8 @@ QPDF_String::getJSON(int json_version) bool QPDF_String::useHexString() const { - // Heuristic: use the hexadecimal representation of a string if - // there are any non-printable (in PDF Doc encoding) characters or - // if too large of a proportion of the string consists of + // Heuristic: use the hexadecimal representation of a string if there are any non-printable (in + // PDF Doc encoding) characters or if too large of a proportion of the string consists of // non-ASCII characters. unsigned int non_ascii = 0; for (auto const ch: this->val) { @@ -172,8 +169,8 @@ QPDF_String::getUTF8Val() const if (QUtil::is_utf16(this->val)) { return QUtil::utf16_to_utf8(this->val); } else if (QUtil::is_explicit_utf8(this->val)) { - // PDF 2.0 allows UTF-8 strings when explicitly prefixed with - // the three-byte representation of U+FEFF. + // PDF 2.0 allows UTF-8 strings when explicitly prefixed with the three-byte representation + // of U+FEFF. return this->val.substr(3); } else { return QUtil::pdf_doc_to_utf8(this->val); diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index 26044500..b5cc44ee 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -164,7 +164,7 @@ pad_or_truncate_password_V4(std::string const& password) { char k1[key_bytes]; pad_or_truncate_password_V4(password, k1); - return std::string(k1, key_bytes); + return {k1, key_bytes}; } static std::string @@ -235,7 +235,7 @@ process_with_aes( } else { outlength = std::min(outlength, bufp->getSize()); } - return std::string(reinterpret_cast<char*>(bufp->getBuffer()), outlength); + return {reinterpret_cast<char*>(bufp->getBuffer()), outlength}; } static std::string @@ -355,7 +355,7 @@ QPDF::compute_data_key( md5.encodeDataIncrementally(result.c_str(), result.length()); MD5::Digest digest; md5.digest(digest); - return std::string(reinterpret_cast<char*>(digest), std::min(result.length(), toS(16))); + return {reinterpret_cast<char*>(digest), std::min(result.length(), toS(16))}; } std::string @@ -401,7 +401,7 @@ QPDF::compute_encryption_key_from_password(std::string const& password, Encrypti MD5::Digest digest; int key_len = std::min(toI(sizeof(digest)), data.getLengthBytes()); iterate_md5_digest(md5, digest, ((data.getR() >= 3) ? 50 : 0), key_len); - return std::string(reinterpret_cast<char*>(digest), toS(key_len)); + return {reinterpret_cast<char*>(digest), toS(key_len)}; } static void @@ -448,7 +448,7 @@ compute_O_value( data.getLengthBytes(), (data.getR() >= 3) ? 20 : 1, false); - return std::string(upass, key_bytes); + return {upass, key_bytes}; } static std::string @@ -467,7 +467,7 @@ compute_U_value_R2(std::string const& user_password, QPDF::EncryptionData const& data.getLengthBytes(), 1, false); - return std::string(udata, key_bytes); + return {udata, key_bytes}; } static std::string @@ -496,7 +496,7 @@ compute_U_value_R3(std::string const& user_password, QPDF::EncryptionData const& for (unsigned int i = sizeof(MD5::Digest); i < key_bytes; ++i) { result[i] = static_cast<char>((i * i) % 0xff); } - return std::string(result, key_bytes); + return {result, key_bytes}; } static std::string diff --git a/libqpdf/QPDF_json.cc b/libqpdf/QPDF_json.cc index c74cf4f7..f8fd689a 100644 --- a/libqpdf/QPDF_json.cc +++ b/libqpdf/QPDF_json.cc @@ -238,7 +238,7 @@ class QPDF::JSONReactor: public JSON::Reactor } } } - virtual ~JSONReactor() = default; + ~JSONReactor() override = default; void dictionaryStart() override; void arrayStart() override; void containerEnd(JSON const& value) override; diff --git a/libqpdf/QPDF_linearization.cc b/libqpdf/QPDF_linearization.cc index faebf5b6..fe25c6d9 100644 --- a/libqpdf/QPDF_linearization.cc +++ b/libqpdf/QPDF_linearization.cc @@ -1367,7 +1367,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data) for (auto& oh: m->part6) { int obj = oh.getObjectID(); obj_to_index[obj] = toI(shared.size()); - shared.push_back(CHSharedObjectEntry(obj)); + shared.emplace_back(obj); } QTC::TC("qpdf", "QPDF lin part 8 empty", m->part8.empty() ? 1 : 0); if (!m->part8.empty()) { @@ -1375,7 +1375,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data) for (auto& oh: m->part8) { int obj = oh.getObjectID(); obj_to_index[obj] = toI(shared.size()); - shared.push_back(CHSharedObjectEntry(obj)); + shared.emplace_back(obj); } } if (static_cast<size_t>(m->c_shared_object_data.nshared_total) != @@ -1585,7 +1585,7 @@ QPDF::calculateHSharedObject( int length = outputLengthNextN(csoe.at(i).object, 1, lengths, obj_renumber); min_length = std::min(min_length, length); max_length = std::max(max_length, length); - soe.push_back(HSharedObjectEntry()); + soe.emplace_back(); soe.at(i).delta_group_length = length; } if (soe.size() != toS(cso.nshared_total)) { diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc index 5fa3c9ca..0fb03579 100644 --- a/libqpdf/QUtil.cc +++ b/libqpdf/QUtil.cc @@ -296,9 +296,8 @@ template <typename T> static std::string int_to_string_base_internal(T num, int base, int length) { - // Backward compatibility -- int_to_string, which calls this - // function, used to use sprintf with %0*d, so we interpret length - // such that a negative value appends spaces and a positive value + // Backward compatibility -- int_to_string, which calls this function, used to use sprintf with + // %0*d, so we interpret length such that a negative value appends spaces and a positive value // prepends zeroes. if (!((base == 8) || (base == 10) || (base == 16))) { throw std::logic_error("int_to_string_base called with unsupported base"); @@ -352,9 +351,8 @@ QUtil::uint_to_string_base(unsigned long long num, int base, int length) std::string QUtil::double_to_string(double num, int decimal_places, bool trim_trailing_zeroes) { - // Backward compatibility -- this code used to use sprintf and - // treated decimal_places <= 0 to mean to use the default, which - // was six decimal places. Starting in 10.2, we trim trailing + // Backward compatibility -- this code used to use sprintf and treated decimal_places <= 0 to + // mean to use the default, which was six decimal places. Starting in 10.2, we trim trailing // zeroes by default. if (decimal_places <= 0) { decimal_places = 6; @@ -739,8 +737,8 @@ std::string QUtil::hex_decode(std::string const& input) { std::string result; - // We know result.size() <= 0.5 * input.size() + 1. However, reserving - // string space for this upper bound has a negative impact. + // We know result.size() <= 0.5 * input.size() + 1. However, reserving string space for this + // upper bound has a negative impact. bool first = true; char decoded; for (auto ch: input) { @@ -905,14 +903,14 @@ QUtil::get_current_qpdf_time() // Don't know how to get timezone on this platform int tzoff = 0; # endif - return QPDFTime( + return { static_cast<int>(ltime.tm_year + 1900), static_cast<int>(ltime.tm_mon + 1), static_cast<int>(ltime.tm_mday), static_cast<int>(ltime.tm_hour), static_cast<int>(ltime.tm_min), static_cast<int>(ltime.tm_sec), - tzoff); + tzoff}; #endif } @@ -1003,15 +1001,12 @@ QUtil::toUTF8(unsigned long uval) { std::string result; - // A UTF-8 encoding of a Unicode value is a single byte for - // Unicode values <= 127. For larger values, the first byte of - // the UTF-8 encoding has '1' as each of its n highest bits and - // '0' for its (n+1)th highest bit where n is the total number of - // bytes required. Subsequent bytes start with '10' and have the - // remaining 6 bits free for encoding. For example, an 11-bit - // Unicode value can be stored in two bytes where the first is - // 110zzzzz, the second is 10zzzzzz, and the z's represent the - // remaining bits. + // A UTF-8 encoding of a Unicode value is a single byte for Unicode values <= 127. For larger + // values, the first byte of the UTF-8 encoding has '1' as each of its n highest bits and '0' + // for its (n+1)th highest bit where n is the total number of bytes required. Subsequent bytes + // start with '10' and have the remaining 6 bits free for encoding. For example, an 11-bit + // Unicode value can be stored in two bytes where the first is 110zzzzz, the second is 10zzzzzz, + // and the z's represent the remaining bits. if (uval > 0x7fffffff) { throw std::runtime_error("bounds error in QUtil::toUTF8"); @@ -1026,8 +1021,7 @@ QUtil::toUTF8(unsigned long uval) unsigned char maxval = 0x3f; // six bits while (uval > QIntC::to_ulong(maxval)) { - // Assign low six bits plus 10000000 to lowest unused - // byte position, then shift + // Assign low six bits plus 10000000 to lowest unused byte position, then shift *cur_byte = static_cast<unsigned char>(0x80 + (uval & 0x3f)); uval >>= 6; // Maximum that will fit in high byte now shrinks by one bit @@ -1038,8 +1032,7 @@ QUtil::toUTF8(unsigned long uval) } --cur_byte; } - // If maxval is k bits long, the high (7 - k) bits of the - // resulting byte must be high. + // If maxval is k bits long, the high (7 - k) bits of the resulting byte must be high. *cur_byte = static_cast<unsigned char>(QIntC::to_ulong(0xff - (1 + (maxval << 1))) + uval); result += reinterpret_cast<char*>(cur_byte); @@ -1089,13 +1082,12 @@ namespace private: RandomDataProvider* default_provider; - RandomDataProvider* current_provider; + RandomDataProvider* current_provider{nullptr}; }; } // namespace RandomDataProviderProvider::RandomDataProviderProvider() : - default_provider(CryptoRandomDataProvider::getInstance()), - current_provider(nullptr) + default_provider(CryptoRandomDataProvider::getInstance()) { this->current_provider = default_provider; } @@ -1253,7 +1245,7 @@ QUtil::read_lines_from_file( char c; while (next_char(c)) { if (buf == nullptr) { - lines.push_back(""); + lines.emplace_back(""); buf = &(lines.back()); buf->reserve(80); } @@ -1265,8 +1257,7 @@ QUtil::read_lines_from_file( if (preserve_eol) { buf->append(1, c); } else { - // Remove any carriage return that preceded the - // newline and discard the newline + // Remove any carriage return that preceded the newline and discard the newline if ((!buf->empty()) && ((*(buf->rbegin())) == '\r')) { buf->erase(buf->length() - 1); } @@ -1391,8 +1382,7 @@ QUtil::parse_numrange(char const* range, int max) p = nullptr; for (size_t i = 0; i < work.size(); i += 2) { int num = work.at(i); - // max == 0 means we don't know the max and are just - // testing for valid syntax. + // max == 0 means we don't know the max and are just testing for valid syntax. if ((max > 0) && ((num < 1) || (num > max))) { throw std::runtime_error("number " + QUtil::int_to_string(num) + " out of range"); } @@ -1519,21 +1509,18 @@ transcode_utf8(std::string const& utf8_val, std::string& result, encoding_e enco result += "\xfe\xff"; break; case e_pdfdoc: - // We need to avoid having the result start with something - // that will be interpreted as UTF-16 or UTF-8, meaning we - // can't end up with a string that starts with "fe ff", - // (UTF-16-BE) "ff fe" (UTF-16-LE, not officially part of the - // PDF spec, but recognized by most readers including qpdf), - // or "ef bb bf" (UTF-8). It's more efficient to check the - // input string to see if it will map to one of those - // sequences than to check the output string since all cases - // start with the same starting character. + // We need to avoid having the result start with something that will be interpreted as + // UTF-16 or UTF-8, meaning we can't end up with a string that starts with "fe ff", + // (UTF-16-BE) "ff fe" (UTF-16-LE, not officially part of the PDF spec, but recognized by + // most readers including qpdf), or "ef bb bf" (UTF-8). It's more efficient to check the + // input string to see if it will map to one of those sequences than to check the output + // string since all cases start with the same starting character. if ((len >= 4) && (utf8_val[0] == '\xc3')) { static std::string fe_ff("\xbe\xc3\xbf"); static std::string ff_fe("\xbf\xc3\xbe"); static std::string ef_bb_bf("\xaf\xc2\xbb\xc2\xbf"); - // C++-20 has starts_with, but when this was written, qpdf - // had a minimum supported version of C++-17. + // C++-20 has starts_with, but when this was written, qpdf had a minimum supported + // version of C++-17. if ((utf8_val.compare(1, 3, fe_ff) == 0) || (utf8_val.compare(1, 3, ff_fe) == 0) || (utf8_val.compare(1, 5, ef_bb_bf) == 0)) { result += unknown; @@ -1560,10 +1547,9 @@ transcode_utf8(std::string const& utf8_val, std::string& result, encoding_e enco if (encoding == e_utf16) { result += QUtil::toUTF16(QIntC::to_ulong(ch)); } else if ((encoding == e_pdfdoc) && (((ch >= 0x18) && (ch <= 0x1f)) || (ch == 127))) { - // PDFDocEncoding maps some low characters to Unicode, - // so if we encounter those invalid UTF-8 code points, - // map them to unknown so reversing the mapping - // doesn't change them into other characters. + // PDFDocEncoding maps some low characters to Unicode, so if we encounter those + // invalid UTF-8 code points, map them to unknown so reversing the mapping doesn't + // change them into other characters. okay = false; result.append(1, unknown); } else { @@ -1682,10 +1668,9 @@ std::string QUtil::utf16_to_utf8(std::string const& val) { std::string result; - // This code uses unsigned long and unsigned short to hold - // codepoint values. It requires unsigned long to be at least - // 32 bits and unsigned short to be at least 16 bits, but it - // will work fine if they are larger. + // This code uses unsigned long and unsigned short to hold codepoint values. It requires + // unsigned long to be at least 32 bits and unsigned short to be at least 16 bits, but it will + // work fine if they are larger. unsigned long codepoint = 0L; size_t len = val.length(); size_t start = 0; @@ -1696,14 +1681,11 @@ QUtil::utf16_to_utf8(std::string const& val) } start += 2; } - // If the string has an odd number of bytes, the last byte is - // ignored. + // If the string has an odd number of bytes, the last byte is ignored. for (size_t i = start; i + 1 < len; i += 2) { - // Convert from UTF16-BE. If we get a malformed - // codepoint, this code will generate incorrect output - // without giving a warning. Specifically, a high - // codepoint not followed by a low codepoint will be - // discarded, and a low codepoint not preceded by a high + // Convert from UTF16-BE. If we get a malformed codepoint, this code will generate + // incorrect output without giving a warning. Specifically, a high codepoint not followed + // by a low codepoint will be discarded, and a low codepoint not preceded by a high // codepoint will just get its low 10 bits output. auto msb = is_le ? i + 1 : i; auto lsb = is_le ? i : i + 1; @@ -1829,8 +1811,7 @@ QUtil::possible_repaired_encodings(std::string supplied) } std::string output; if (is_valid_utf8) { - // Maybe we were given UTF-8 but wanted one of the single-byte - // encodings. + // Maybe we were given UTF-8 but wanted one of the single-byte encodings. if (utf8_to_pdf_doc(supplied, output)) { result.push_back(output); } @@ -1841,8 +1822,7 @@ QUtil::possible_repaired_encodings(std::string supplied) result.push_back(output); } } else { - // Maybe we were given one of the single-byte encodings but - // wanted UTF-8. + // Maybe we were given one of the single-byte encodings but wanted UTF-8. std::string from_pdf_doc(pdf_doc_to_utf8(supplied)); result.push_back(from_pdf_doc); std::string from_win_ansi(win_ansi_to_utf8(supplied)); @@ -1850,8 +1830,8 @@ QUtil::possible_repaired_encodings(std::string supplied) std::string from_mac_roman(mac_roman_to_utf8(supplied)); result.push_back(from_mac_roman); - // Maybe we were given one of the other single-byte encodings - // but wanted one of the other ones. + // Maybe we were given one of the other single-byte encodings but wanted one of the other + // ones. if (utf8_to_win_ansi(from_pdf_doc, output)) { result.push_back(output); } @@ -1888,9 +1868,8 @@ static int call_main_from_wmain( bool, int argc, wchar_t const* const argv[], std::function<int(int, char*[])> realmain) { - // argv contains UTF-16-encoded strings with a 16-bit wchar_t. - // Convert this to UTF-8-encoded strings for compatibility with - // other systems. That way the rest of qpdf.cc can just act like + // argv contains UTF-16-encoded strings with a 16-bit wchar_t. Convert this to UTF-8-encoded + // strings for compatibility with other systems. That way the rest of qpdf.cc can just act like // arguments are UTF-8. std::vector<std::unique_ptr<char[]>> utf8_argv; @@ -1950,16 +1929,13 @@ QUtil::get_max_memory_usage() fprintf(stderr, "%s", buf); } - // Warning: this code uses regular expression to extract data from - // an XML string. This is generally a bad idea, but we're going to - // do it anyway because QUtil.hh warns against using this function - // for other than development/testing, and if this function fails - // to generate reasonable output during performance testing, it - // will be noticed. + // Warning: this code uses regular expression to extract data from an XML string. This is + // generally a bad idea, but we're going to do it anyway because QUtil.hh warns against using + // this function for other than development/testing, and if this function fails to generate + // reasonable output during performance testing, it will be noticed. - // This is my best guess at how to interpret malloc_info. Anyway - // it seems to provide useful information for detecting code - // changes that drastically change memory usage. + // This is my best guess at how to interpret malloc_info. Anyway it seems to provide useful + // information for detecting code changes that drastically change memory usage. size_t result = 0; try { std::cregex_iterator m_begin(buf, buf + size, tag_re); diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc index c47c8707..64199903 100644 --- a/libqpdf/SecureRandomDataProvider.cc +++ b/libqpdf/SecureRandomDataProvider.cc @@ -89,10 +89,9 @@ SecureRandomDataProvider::provideRandomData(unsigned char* data, size_t len) # elif defined(RANDOM_DEVICE) - // Optimization: wrap the file open and close in a class so that - // the file is closed in a destructor, then make this static to - // keep the file handle open. Only do this if it can be done in a - // thread-safe fashion. + // Optimization: wrap the file open and close in a class so that the file is closed in a + // destructor, then make this static to keep the file handle open. Only do this if it can be + // done in a thread-safe fashion. FILE* f = QUtil::safe_fopen(RANDOM_DEVICE, "rb"); size_t fr = fread(data, 1, len, f); fclose(f); diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index 05568558..1f7b85cb 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -269,9 +269,8 @@ qpdf_read(qpdf_data qpdf, char const* filename, char const* password) qpdf->filename = filename; qpdf->password = password; status = trap_errors(qpdf, &call_read); - // We no longer have a good way to exercise a file with both - // warnings and errors because qpdf is getting much better at - // recovering. + // We no longer have a good way to exercise a file with both warnings and errors because qpdf is + // getting much better at recovering. QTC::TC( "qpdf", "qpdf-c called qpdf_read", @@ -806,23 +805,21 @@ template <class RET> static RET trap_oh_errors(qpdf_data qpdf, std::function<RET()> fallback, std::function<RET(qpdf_data)> fn) { - // Note: fallback is a function so we don't have to evaluate it - // unless needed. This is important because sometimes the fallback - // creates an object. + // Note: fallback is a function so we don't have to evaluate it unless needed. This is important + // because sometimes the fallback creates an object. RET ret; QPDF_ERROR_CODE status = trap_errors(qpdf, [&ret, fn](qpdf_data q) { ret = fn(q); }); if (status & QPDF_ERRORS) { if (!qpdf->silence_errors) { QTC::TC("qpdf", "qpdf-c warn about oh error", qpdf->oh_error_occurred ? 0 : 1); if (!qpdf->oh_error_occurred) { - qpdf->warnings.push_back(QPDFExc( + qpdf->warnings.emplace_back( qpdf_e_internal, qpdf->qpdf->getFilename(), "", 0, - "C API function caught an exception that it isn't" - " returning; please point the application developer" - " to ERROR HANDLING in qpdf-c.h")); + "C API function caught an exception that it isn't returning; please point the " + "application developer to ERROR HANDLING in qpdf-c.h"); qpdf->oh_error_occurred = true; } *QPDFLogger::defaultLogger()->getError() << qpdf->error->what() << "\n"; diff --git a/libqpdf/qpdf/BitStream.hh b/libqpdf/qpdf/BitStream.hh index b807f56c..329c486d 100644 --- a/libqpdf/qpdf/BitStream.hh +++ b/libqpdf/qpdf/BitStream.hh @@ -12,8 +12,7 @@ class BitStream void reset(); unsigned long long getBits(size_t nbits); long long getBitsSigned(size_t nbits); - // Only call getBitsInt when requesting a number of bits that will - // definitely fit in an int. + // Only call getBitsInt when requesting a number of bits that definitely fit in an int. int getBitsInt(size_t nbits); void skipToNextByte(); diff --git a/libqpdf/qpdf/BitWriter.hh b/libqpdf/qpdf/BitWriter.hh index 33fdd8f4..24c74162 100644 --- a/libqpdf/qpdf/BitWriter.hh +++ b/libqpdf/qpdf/BitWriter.hh @@ -10,8 +10,8 @@ class Pipeline; class BitWriter { public: - // Write bits to the pipeline. It is the caller's responsibility - // to eventually call finish on the pipeline. + // Write bits to the pipeline. It is the caller's responsibility to eventually call finish on + // the pipeline. BitWriter(Pipeline* pl); void writeBits(unsigned long long val, size_t bits); void writeBitsSigned(long long val, size_t bits); diff --git a/libqpdf/qpdf/JSONHandler.hh b/libqpdf/qpdf/JSONHandler.hh index e4a76af5..653924f6 100644 --- a/libqpdf/qpdf/JSONHandler.hh +++ b/libqpdf/qpdf/JSONHandler.hh @@ -7,37 +7,32 @@ #include <memory> #include <string> -// This class allows a sax-like walk through a JSON object with -// functionality that mostly mirrors QPDFArgParser. It is primarily -// here to facilitate automatic generation of some of the code to help -// keep QPDFJob json consistent with command-line arguments. +// This class allows a sax-like walk through a JSON object with functionality that mostly mirrors +// QPDFArgParser. It is primarily here to facilitate automatic generation of some of the code to +// help keep QPDFJob json consistent with command-line arguments. class JSONHandler { public: - // A QPDFUsage exception is thrown if there are any errors - // validating the JSON object. + // A QPDFUsage exception is thrown if there are any errors validating the JSON object. JSONHandler(); - ~JSONHandler() = default; + ~JSONHandler(); - // Based on the type of handler, expect the object to be of a - // certain type. QPDFUsage is thrown otherwise. Multiple handlers - // may be registered, which allows the object to be of various - // types. If an anyHandler is added, no other handler will be - // called. There is no "final" handler -- if the top-level is a - // dictionary or array, just use its end handler. + // Based on the type of handler, expect the object to be of a certain type. QPDFUsage is thrown + // otherwise. Multiple handlers may be registered, which allows the object to be of various + // types. If an anyHandler is added, no other handler will be called. There is no "final" + // handler -- if the top-level is a dictionary or array, just use its end handler. typedef std::function<void(std::string const& path, JSON value)> json_handler_t; typedef std::function<void(std::string const& path)> void_handler_t; typedef std::function<void(std::string const& path, std::string const& value)> string_handler_t; typedef std::function<void(std::string const& path, bool value)> bool_handler_t; - // If an any handler is added, it will be called for any value - // including null, and no other handler will be called. + // If an any handler is added, it will be called for any value including null, and no other + // handler will be called. void addAnyHandler(json_handler_t fn); - // If any of the remaining handlers are registered, each - // registered handle will be called. + // If any of the remaining handlers are registered, each registered handle will be called. void addNullHandler(void_handler_t fn); void addStringHandler(string_handler_t fn); void addNumberHandler(string_handler_t fn); @@ -58,51 +53,10 @@ class JSONHandler static void usage(std::string const& msg); - struct Handlers - { - Handlers() : - any_handler(nullptr), - null_handler(nullptr), - string_handler(nullptr), - number_handler(nullptr), - bool_handler(nullptr), - dict_start_handler(nullptr), - dict_end_handler(nullptr), - array_start_handler(nullptr), - array_end_handler(nullptr), - final_handler(nullptr) - { - } - - json_handler_t any_handler; - void_handler_t null_handler; - string_handler_t string_handler; - string_handler_t number_handler; - bool_handler_t bool_handler; - json_handler_t dict_start_handler; - void_handler_t dict_end_handler; - json_handler_t array_start_handler; - void_handler_t array_end_handler; - void_handler_t final_handler; - std::map<std::string, std::shared_ptr<JSONHandler>> dict_handlers; - std::shared_ptr<JSONHandler> fallback_dict_handler; - std::shared_ptr<JSONHandler> array_item_handler; - }; - - class Members - { - friend class JSONHandler; - - public: - ~Members() = default; - - private: - Members() = default; - Members(Members const&) = delete; - - Handlers h; - }; - std::shared_ptr<Members> m; + + class Members; + + std::unique_ptr<Members> m; }; #endif // JSONHANDLER_HH diff --git a/libqpdf/qpdf/MD5.hh b/libqpdf/qpdf/MD5.hh index 977cd4b5..be97edb5 100644 --- a/libqpdf/qpdf/MD5.hh +++ b/libqpdf/qpdf/MD5.hh @@ -29,8 +29,7 @@ class MD5 // computes a raw digest void digest(Digest); - // prints the digest to stdout terminated with \r\n (primarily for - // testing) + // prints the digest to stdout terminated with \r\n (primarily for testing) void print(); // returns the digest as a hexadecimal string diff --git a/libqpdf/qpdf/NNTree.hh b/libqpdf/qpdf/NNTree.hh index 6345b105..4b5ba200 100644 --- a/libqpdf/qpdf/NNTree.hh +++ b/libqpdf/qpdf/NNTree.hh @@ -104,9 +104,8 @@ class NNTreeImpl iterator insert(QPDFObjectHandle key, QPDFObjectHandle value); bool remove(QPDFObjectHandle key, QPDFObjectHandle* value = nullptr); - // Change the split threshold for easier testing. There's no real - // reason to expose this to downstream tree helpers, but it has to - // be public so we can call it from the test suite. + // Change the split threshold for easier testing. There's no real reason to expose this to + // downstream tree helpers, but it has to be public so we can call it from the test suite. void setSplitThreshold(int split_threshold); private: diff --git a/libqpdf/qpdf/OffsetInputSource.hh b/libqpdf/qpdf/OffsetInputSource.hh index 2d506f80..f9246363 100644 --- a/libqpdf/qpdf/OffsetInputSource.hh +++ b/libqpdf/qpdf/OffsetInputSource.hh @@ -1,8 +1,8 @@ #ifndef QPDF_OFFSETINPUTSOURCE_HH #define QPDF_OFFSETINPUTSOURCE_HH -// This class implements an InputSource that proxies for an underlying -// input source but offset a specific number of bytes. +// This class implements an InputSource that proxies for an underlying input source but offset a +// specific number of bytes. #include <qpdf/InputSource.hh> diff --git a/libqpdf/qpdf/Pl_AES_PDF.hh b/libqpdf/qpdf/Pl_AES_PDF.hh index b3fde312..32f4c351 100644 --- a/libqpdf/qpdf/Pl_AES_PDF.hh +++ b/libqpdf/qpdf/Pl_AES_PDF.hh @@ -5,8 +5,8 @@ #include <qpdf/QPDFCryptoImpl.hh> #include <memory> -// This pipeline implements AES-128 and AES-256 with CBC and block -// padding as specified in the PDF specification. +// This pipeline implements AES-128 and AES-256 with CBC and block padding as specified in the PDF +// specification. class Pl_AES_PDF: public Pipeline { diff --git a/libqpdf/qpdf/Pl_LZWDecoder.hh b/libqpdf/qpdf/Pl_LZWDecoder.hh index b2135aa9..792fa8ef 100644 --- a/libqpdf/qpdf/Pl_LZWDecoder.hh +++ b/libqpdf/qpdf/Pl_LZWDecoder.hh @@ -10,9 +10,9 @@ class Pl_LZWDecoder: public Pipeline { public: Pl_LZWDecoder(char const* identifier, Pipeline* next, bool early_code_change); - virtual ~Pl_LZWDecoder() = default; - virtual void write(unsigned char const* buf, size_t len); - virtual void finish(); + ~Pl_LZWDecoder() override = default; + void write(unsigned char const* buf, size_t len) override; + void finish() override; private: void sendNextCode(); diff --git a/libqpdf/qpdf/Pl_MD5.hh b/libqpdf/qpdf/Pl_MD5.hh index bd56f9c6..fb9a2184 100644 --- a/libqpdf/qpdf/Pl_MD5.hh +++ b/libqpdf/qpdf/Pl_MD5.hh @@ -1,13 +1,11 @@ #ifndef PL_MD5_HH #define PL_MD5_HH -// This pipeline sends its output to its successor unmodified. After -// calling finish, the MD5 checksum of the data that passed through -// the pipeline is available. +// This pipeline sends its output to its successor unmodified. After calling finish, the MD5 +// checksum of the data that passed through the pipeline is available. -// This pipeline is reusable; i.e., it is safe to call write() after -// calling finish(). The first call to write() after a call to -// finish() initializes a new MD5 object. +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first +// call to write() after a call to finish() initializes a new MD5 object. #include <qpdf/MD5.hh> #include <qpdf/Pipeline.hh> @@ -16,19 +14,16 @@ class Pl_MD5: public Pipeline { public: Pl_MD5(char const* identifier, Pipeline* next); - virtual ~Pl_MD5() = default; - virtual void write(unsigned char const*, size_t); - virtual void finish(); + ~Pl_MD5() override = default; + void write(unsigned char const*, size_t) override; + void finish() override; std::string getHexDigest(); - // Enable/disable. Disabling the pipeline causes it to become a - // pass-through. This makes it possible to stick an MD5 pipeline - // in a pipeline when it may or may not be required. Disabling it - // avoids incurring the runtime overhead of doing needless - // digest computation. + // Enable/disable. Disabling the pipeline causes it to become a pass-through. This makes it + // possible to stick an MD5 pipeline in a pipeline when it may or may not be required. Disabling + // it avoids incurring the runtime overhead of doing needless digest computation. void enable(bool enabled); - // If persistAcrossFinish is called, calls to finish do not - // finalize the underlying md5 object. In this case, the object is - // not finalized until getHexDigest() is called. + // If persistAcrossFinish is called, calls to finish do not finalize the underlying md5 object. + // In this case, the object is not finalized until getHexDigest() is called. void persistAcrossFinish(bool); private: diff --git a/libqpdf/qpdf/Pl_PNGFilter.hh b/libqpdf/qpdf/Pl_PNGFilter.hh index 7ab7bf0d..ed8e1e9c 100644 --- a/libqpdf/qpdf/Pl_PNGFilter.hh +++ b/libqpdf/qpdf/Pl_PNGFilter.hh @@ -1,11 +1,11 @@ #ifndef PL_PNGFILTER_HH #define PL_PNGFILTER_HH -// This pipeline applies or reverses the application of a PNG filter -// as described in the PNG specification. +// This pipeline applies or reverses the application of a PNG filter as described in the PNG +// specification. -// NOTE: In its current implementation, this filter always encodes -// using the "up" filter, but it decodes all the filters. +// NOTE: In its current implementation, this filter always encodes using the "up" filter, but it +// decodes all the filters. #include <qpdf/Pipeline.hh> diff --git a/libqpdf/qpdf/Pl_SHA2.hh b/libqpdf/qpdf/Pl_SHA2.hh index 571271eb..9b3275f0 100644 --- a/libqpdf/qpdf/Pl_SHA2.hh +++ b/libqpdf/qpdf/Pl_SHA2.hh @@ -1,16 +1,13 @@ #ifndef PL_SHA2_HH #define PL_SHA2_HH -// Bits must be a supported number of bits, currently only 256, 384, -// or 512. Passing 0 as bits leaves the pipeline uncommitted, in -// which case resetBits must be called before the pipeline is used. -// If a next is provided, this pipeline sends its output to its -// successor unmodified. After calling finish, the SHA2 checksum of -// the data that passed through the pipeline is available. +// Bits must be a supported number of bits, currently only 256, 384, or 512. Passing 0 as bits +// leaves the pipeline uncommitted, in which case resetBits must be called before the pipeline is +// used. If a next is provided, this pipeline sends its output to its successor unmodified. After +// calling finish, the SHA2 checksum of the data that passed through the pipeline is available. -// This pipeline is reusable; i.e., it is safe to call write() after -// calling finish(). The first call to write() after a call to -// finish() initializes a new SHA2 object. resetBits may also be +// This pipeline is reusable; i.e., it is safe to call write() after calling finish(). The first +// call to write() after a call to finish() initializes a new SHA2 object. resetBits may also be // called between finish and the next call to write. #include <qpdf/Pipeline.hh> diff --git a/libqpdf/qpdf/Pl_TIFFPredictor.hh b/libqpdf/qpdf/Pl_TIFFPredictor.hh index 6bc48e72..21757593 100644 --- a/libqpdf/qpdf/Pl_TIFFPredictor.hh +++ b/libqpdf/qpdf/Pl_TIFFPredictor.hh @@ -1,8 +1,8 @@ #ifndef PL_TIFFPREDICTOR_HH #define PL_TIFFPREDICTOR_HH -// This pipeline reverses the application of a TIFF predictor as -// described in the TIFF specification. +// This pipeline reverses the application of a TIFF predictor as described in the TIFF +// specification. #include <qpdf/Pipeline.hh> diff --git a/libqpdf/qpdf/QPDFArgParser.hh b/libqpdf/qpdf/QPDFArgParser.hh index d9e33b5a..ed161d53 100644 --- a/libqpdf/qpdf/QPDFArgParser.hh +++ b/libqpdf/qpdf/QPDFArgParser.hh @@ -9,41 +9,33 @@ #include <string> #include <vector> -// This is not a general-purpose argument parser. It is tightly -// crafted to work with qpdf. qpdf's command-line syntax is very -// complex because of its long history, and it doesn't really follow -// any kind of normal standard for arguments, but it's important for -// backward compatibility to ensure we don't break what constitutes a -// valid command. This class handles the quirks of qpdf's argument -// parsing, bash/zsh completion, and support for @argfile to read -// arguments from a file. For the qpdf CLI, setup of QPDFArgParser is -// done mostly by automatically-generated code (one-off code for -// qpdf), though the handlers themselves are hand-coded. See -// generate_auto_job at the top of the source tree for details. +// This is not a general-purpose argument parser. It is tightly crafted to work with qpdf. qpdf's +// command-line syntax is very complex because of its long history, and it doesn't really follow any +// kind of normal standard for arguments, but it's important for backward compatibility to ensure we +// don't break what constitutes a valid command. This class handles the quirks of qpdf's argument +// parsing, bash/zsh completion, and support for @argfile to read arguments from a file. For the +// qpdf CLI, setup of QPDFArgParser is done mostly by automatically-generated code (one-off code for +// qpdf), though the handlers themselves are hand-coded. See generate_auto_job at the top of the +// source tree for details. class QPDFArgParser { public: - // progname_env is used to override argv[0] when figuring out the - // name of the executable for setting up completion. This may be - // needed if the program is invoked by a wrapper. + // progname_env is used to override argv[0] when figuring out the name of the executable for + // setting up completion. This may be needed if the program is invoked by a wrapper. QPDFArgParser(int argc, char const* const argv[], char const* progname_env); - // Calls exit(0) if a help option is given or if in completion - // mode. If there are argument parsing errors, QPDFUsage is - // thrown. + // Calls exit(0) if a help option is given or if in completion mode. If there are argument + // parsing errors, QPDFUsage is thrown. void parseArgs(); - // Return the program name as the last path element of the program - // executable. + // Return the program name as the last path element of the program executable. std::string getProgname(); - // Methods for registering arguments. QPDFArgParser starts off - // with the main option table selected. You can add handlers for - // arguments in the current option table, and you can select which - // option table is current. The help option table is special and - // contains arguments that are only valid as the first and only - // option. Named option tables are for subparsers and always start - // a series of options that end with `--`. + // Methods for registering arguments. QPDFArgParser starts off with the main option table + // selected. You can add handlers for arguments in the current option table, and you can select + // which option table is current. The help option table is special and contains arguments that + // are only valid as the first and only option. Named option tables are for subparsers and + // always start a series of options that end with `--`. typedef std::function<void()> bare_arg_handler_t; typedef std::function<void(std::string const&)> param_arg_handler_t; @@ -65,9 +57,8 @@ class QPDFArgParser void addChoices(std::string const& arg, param_arg_handler_t, bool required, char const** choices); - // The default behavior when an invalid choice is specified with - // an option that takes choices is to list all the choices. This - // may not be good if there are too many choices, so you can + // The default behavior when an invalid choice is specified with an option that takes choices is + // to list all the choices. This may not be good if there are too many choices, so you can // provide your own handler in this case. void addInvalidChoiceHandler(std::string const& arg, param_arg_handler_t); @@ -77,42 +68,33 @@ class QPDFArgParser // Help generation methods - // Help is available on topics and options. Options may be - // associated with topics. Users can run --help, --help=topic, or - // --help=--arg to get help. The top-level help tells the user how - // to run help and lists available topics. Help for a topic prints - // a short synopsis about the topic and lists any options that may - // be associated with the topic. Help for an option provides a - // short synopsis for that option. All help output is appended - // with a blurb (if supplied) directing the user to the full - // documentation. Help is not shown for options for which help has - // not been added. This makes it possible to have undocumented - // options for testing, backward-compatibility, etc. Also, it - // could be quite confusing to handle appropriate help for some - // inner options that may be repeated with different semantics - // inside different option tables. There is also no checking for - // whether an option that has help actually exists. In other - // words, it's up to the caller to ensure that help actually - // corresponds to the program's actual options. Rather than this - // being an intentional design decision, it is because this class - // is specifically for qpdf, qpdf generates its help and has other - // means to ensure consistency. + // Help is available on topics and options. Options may be associated with topics. Users can run + // --help, --help=topic, or --help=--arg to get help. The top-level help tells the user how + // to run help and lists available topics. Help for a topic prints a short synopsis about the + // topic and lists any options that may be associated with the topic. Help for an option + // provides a short synopsis for that option. All help output is appended with a blurb (if + // supplied) directing the user to the full documentation. Help is not shown for options for + // which help has not been added. This makes it possible to have undocumented options for + // testing, backward-compatibility, etc. Also, it could be quite confusing to handle appropriate + // help for some inner options that may be repeated with different semantics inside different + // option tables. There is also no checking for whether an option that has help actually exists. + // In other words, it's up to the caller to ensure that help actually corresponds to the + // program's actual options. Rather than this being an intentional design decision, it is + // because this class is specifically for qpdf, qpdf generates its help and has other means to + // ensure consistency. // Note about newlines: // - // short_text should fit easily after the topic/option on the same - // line and should not end with a newline. Keep it to around 40 to - // 60 characters. + // short_text should fit easily after the topic/option on the same line and should not end with + // a newline. Keep it to around 40 to 60 characters. // - // long_text and footer should end with a single newline. They can - // have embedded newlines. Keep lines to under 80 columns. + // long_text and footer should end with a single newline. They can have embedded newlines. Keep + // lines to under 80 columns. // - // QPDFArgParser does reformat the text, but it may add blank - // lines in some situations. Following the above conventions will - // keep the help looking uniform. + // QPDFArgParser does reformat the text, but it may add blank lines in some situations. + // Following the above conventions will keep the help looking uniform. - // If provided, this footer is appended to all help, separated by - // a blank line. + // If provided, this footer is appended to all help, separated by a blank line. void addHelpFooter(std::string const&); // Add a help topic along with the text for that topic @@ -126,14 +108,12 @@ class QPDFArgParser std::string const& short_text, std::string const& long_text); - // Return the help text for a topic or option. Passing a null - // pointer returns the top-level help information. Passing an - // unknown value returns a string directing the user to run the + // Return the help text for a topic or option. Passing a null pointer returns the top-level help + // information. Passing an unknown value returns a string directing the user to run the // top-level --help option. std::string getHelp(std::string const& topic_or_option); - // Convenience methods for adding member functions of a class as - // handlers. + // Convenience methods for adding member functions of a class as handlers. template <class T> static bare_arg_handler_t bindBare(void (T::*f)(), T* o) @@ -147,39 +127,30 @@ class QPDFArgParser return std::bind(std::mem_fn(f), o, std::placeholders::_1); } - // When processing arguments, indicate how many arguments remain - // after the one whose handler is being called. + // When processing arguments, indicate how many arguments remain after the one whose handler is + // being called. int argsLeft() const; // Indicate whether we are in completion mode. bool isCompleting() const; - // Insert a completion during argument parsing; useful for - // customizing completion in the position argument handler. Should - // only be used in completion mode. + // Insert a completion during argument parsing; useful for customizing completion in the + // position argument handler. Should only be used in completion mode. void insertCompletion(std::string const&); - // Throw a Usage exception with the given message. In completion - // mode, this just exits to prevent errors from partial commands - // or other error messages from messing up completion. + // Throw a Usage exception with the given message. In completion mode, this just exits to + // prevent errors from partial commands or other error messages from messing up completion. void usage(std::string const& message); private: struct OptionEntry { - OptionEntry() : - parameter_needed(false), - bare_arg_handler(nullptr), - param_arg_handler(nullptr), - invalid_choice_handler(nullptr) - { - } - bool parameter_needed; + bool parameter_needed{false}; std::string parameter_name; std::set<std::string> choices; - bare_arg_handler_t bare_arg_handler; - param_arg_handler_t param_arg_handler; - param_arg_handler_t invalid_choice_handler; + bare_arg_handler_t bare_arg_handler{nullptr}; + param_arg_handler_t param_arg_handler{nullptr}; + param_arg_handler_t invalid_choice_handler{nullptr}; }; typedef std::map<std::string, OptionEntry> option_table_t; diff --git a/libqpdf/qpdf/QPDFCrypto_gnutls.hh b/libqpdf/qpdf/QPDFCrypto_gnutls.hh index efec1bbf..00f25857 100644 --- a/libqpdf/qpdf/QPDFCrypto_gnutls.hh +++ b/libqpdf/qpdf/QPDFCrypto_gnutls.hh @@ -4,8 +4,8 @@ #include <qpdf/QPDFCryptoImpl.hh> #include <memory> -// gnutls headers must be last to prevent them from interfering with -// other headers. gnutls.h has to be included first. +// gnutls headers must be last to prevent them from interfering with other headers. gnutls.h has to +// be included first. #include <gnutls/gnutls.h> // This comment prevents clang-format from putting crypto.h before gnutls.h #include <gnutls/crypto.h> diff --git a/libqpdf/qpdf/QPDFObject_private.hh b/libqpdf/qpdf/QPDFObject_private.hh index bbd6ccf1..5e87c215 100644 --- a/libqpdf/qpdf/QPDFObject_private.hh +++ b/libqpdf/qpdf/QPDFObject_private.hh @@ -1,9 +1,8 @@ #ifndef QPDFOBJECT_HH #define QPDFOBJECT_HH -// NOTE: This file is called QPDFObject_private.hh instead of -// QPDFObject.hh because of include/qpdf/QPDFObject.hh. See comments -// there for an explanation. +// NOTE: This file is called QPDFObject_private.hh instead of QPDFObject.hh because of +// include/qpdf/QPDFObject.hh. See comments there for an explanation. #include <qpdf/Constants.h> #include <qpdf/DLL.h> @@ -51,8 +50,7 @@ class QPDFObject return value->type_code; } - // Return a string literal that describes the type, useful for - // debugging and testing + // Return a string literal that describes the type, useful for debugging and testing char const* getTypeName() const { @@ -146,14 +144,12 @@ class QPDFObject void disconnect() { - // Disconnect an object from its owning QPDF. This is called - // by QPDF's destructor. + // Disconnect an object from its owning QPDF. This is called by QPDF's destructor. value->disconnect(); value->qpdf = nullptr; value->og = QPDFObjGen(); } - // Mark an object as destroyed. Used by QPDF's destructor for its - // indirect objects. + // Mark an object as destroyed. Used by QPDF's destructor for its indirect objects. void destroy(); bool diff --git a/libqpdf/qpdf/QPDF_Array.hh b/libqpdf/qpdf/QPDF_Array.hh index 51a366a6..10ac9f8c 100644 --- a/libqpdf/qpdf/QPDF_Array.hh +++ b/libqpdf/qpdf/QPDF_Array.hh @@ -9,14 +9,14 @@ class QPDF_Array: public QPDFValue { public: - virtual ~QPDF_Array() = default; + ~QPDF_Array() override = default; static std::shared_ptr<QPDFObject> create(std::vector<QPDFObjectHandle> const& items); static std::shared_ptr<QPDFObject> create(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); - virtual void disconnect(); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; + void disconnect() override; int size() const noexcept diff --git a/libqpdf/qpdf/QPDF_Bool.hh b/libqpdf/qpdf/QPDF_Bool.hh index 215d359a..0b4a71fd 100644 --- a/libqpdf/qpdf/QPDF_Bool.hh +++ b/libqpdf/qpdf/QPDF_Bool.hh @@ -6,11 +6,11 @@ class QPDF_Bool: public QPDFValue { public: - virtual ~QPDF_Bool() = default; + ~QPDF_Bool() override = default; static std::shared_ptr<QPDFObject> create(bool val); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; bool getVal() const; private: diff --git a/libqpdf/qpdf/QPDF_Destroyed.hh b/libqpdf/qpdf/QPDF_Destroyed.hh index c8e35557..72e9130a 100644 --- a/libqpdf/qpdf/QPDF_Destroyed.hh +++ b/libqpdf/qpdf/QPDF_Destroyed.hh @@ -6,10 +6,10 @@ class QPDF_Destroyed: public QPDFValue { public: - virtual ~QPDF_Destroyed() = default; - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + ~QPDF_Destroyed() override = default; + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; static std::shared_ptr<QPDFValue> getInstance(); private: diff --git a/libqpdf/qpdf/QPDF_Dictionary.hh b/libqpdf/qpdf/QPDF_Dictionary.hh index bf3dfb2d..0fb6636e 100644 --- a/libqpdf/qpdf/QPDF_Dictionary.hh +++ b/libqpdf/qpdf/QPDF_Dictionary.hh @@ -11,24 +11,23 @@ class QPDF_Dictionary: public QPDFValue { public: - virtual ~QPDF_Dictionary() = default; + ~QPDF_Dictionary() override = default; static std::shared_ptr<QPDFObject> create(std::map<std::string, QPDFObjectHandle> const& items); static std::shared_ptr<QPDFObject> create(std::map<std::string, QPDFObjectHandle>&& items); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); - virtual void disconnect(); - - // hasKey() and getKeys() treat keys with null values as if they - // aren't there. getKey() returns null for the value of a - // non-existent key. This is as per the PDF spec. + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; + void disconnect() override; + + // hasKey() and getKeys() treat keys with null values as if they aren't there. getKey() returns + // null for the value of a non-existent key. This is as per the PDF spec. bool hasKey(std::string const&); QPDFObjectHandle getKey(std::string const&); std::set<std::string> getKeys(); std::map<std::string, QPDFObjectHandle> const& getAsMap() const; - // If value is null, remove key; otherwise, replace the value of - // key, adding it if it does not exist. + // If value is null, remove key; otherwise, replace the value of key, adding it if it does not + // exist. void replaceKey(std::string const& key, QPDFObjectHandle value); // Remove key, doing nothing if key does not exist void removeKey(std::string const& key); diff --git a/libqpdf/qpdf/QPDF_InlineImage.hh b/libqpdf/qpdf/QPDF_InlineImage.hh index 553d1d71..bee12354 100644 --- a/libqpdf/qpdf/QPDF_InlineImage.hh +++ b/libqpdf/qpdf/QPDF_InlineImage.hh @@ -6,13 +6,13 @@ class QPDF_InlineImage: public QPDFValue { public: - virtual ~QPDF_InlineImage() = default; + ~QPDF_InlineImage() override = default; static std::shared_ptr<QPDFObject> create(std::string const& val); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); - virtual std::string - getStringValue() const + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; + std::string + getStringValue() const override { return val; } diff --git a/libqpdf/qpdf/QPDF_Integer.hh b/libqpdf/qpdf/QPDF_Integer.hh index 180bb48a..2c2cf2f9 100644 --- a/libqpdf/qpdf/QPDF_Integer.hh +++ b/libqpdf/qpdf/QPDF_Integer.hh @@ -6,11 +6,11 @@ class QPDF_Integer: public QPDFValue { public: - virtual ~QPDF_Integer() = default; + ~QPDF_Integer() override = default; static std::shared_ptr<QPDFObject> create(long long value); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; long long getVal() const; private: diff --git a/libqpdf/qpdf/QPDF_Name.hh b/libqpdf/qpdf/QPDF_Name.hh index 136ad5cb..c14d8659 100644 --- a/libqpdf/qpdf/QPDF_Name.hh +++ b/libqpdf/qpdf/QPDF_Name.hh @@ -6,16 +6,16 @@ class QPDF_Name: public QPDFValue { public: - virtual ~QPDF_Name() = default; + ~QPDF_Name() override = default; static std::shared_ptr<QPDFObject> create(std::string const& name); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; // Put # into strings with characters unsuitable for name token static std::string normalizeName(std::string const& name); - virtual std::string - getStringValue() const + std::string + getStringValue() const override { return name; } diff --git a/libqpdf/qpdf/QPDF_Null.hh b/libqpdf/qpdf/QPDF_Null.hh index 2bbb3db5..a59b7509 100644 --- a/libqpdf/qpdf/QPDF_Null.hh +++ b/libqpdf/qpdf/QPDF_Null.hh @@ -6,7 +6,7 @@ class QPDF_Null: public QPDFValue { public: - virtual ~QPDF_Null() = default; + ~QPDF_Null() override = default; static std::shared_ptr<QPDFObject> create(); static std::shared_ptr<QPDFObject> create( std::shared_ptr<QPDFObject> parent, @@ -16,9 +16,9 @@ class QPDF_Null: public QPDFValue std::shared_ptr<QPDFValue> parent, std::string_view const& static_descr, std::string var_descr); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; private: QPDF_Null(); diff --git a/libqpdf/qpdf/QPDF_Operator.hh b/libqpdf/qpdf/QPDF_Operator.hh index 4fedb808..77aa5a17 100644 --- a/libqpdf/qpdf/QPDF_Operator.hh +++ b/libqpdf/qpdf/QPDF_Operator.hh @@ -6,13 +6,13 @@ class QPDF_Operator: public QPDFValue { public: - virtual ~QPDF_Operator() = default; + ~QPDF_Operator() override = default; static std::shared_ptr<QPDFObject> create(std::string const& val); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); - virtual std::string - getStringValue() const + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; + std::string + getStringValue() const override { return val; } diff --git a/libqpdf/qpdf/QPDF_Real.hh b/libqpdf/qpdf/QPDF_Real.hh index f470e1a6..db5e0940 100644 --- a/libqpdf/qpdf/QPDF_Real.hh +++ b/libqpdf/qpdf/QPDF_Real.hh @@ -6,15 +6,15 @@ class QPDF_Real: public QPDFValue { public: - virtual ~QPDF_Real() = default; + ~QPDF_Real() override = default; static std::shared_ptr<QPDFObject> create(std::string const& val); static std::shared_ptr<QPDFObject> create(double value, int decimal_places, bool trim_trailing_zeroes); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); - virtual std::string - getStringValue() const + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; + std::string + getStringValue() const override { return val; } diff --git a/libqpdf/qpdf/QPDF_Reserved.hh b/libqpdf/qpdf/QPDF_Reserved.hh index 8d6c74f8..9ba855b7 100644 --- a/libqpdf/qpdf/QPDF_Reserved.hh +++ b/libqpdf/qpdf/QPDF_Reserved.hh @@ -6,11 +6,11 @@ class QPDF_Reserved: public QPDFValue { public: - virtual ~QPDF_Reserved() = default; + ~QPDF_Reserved() override = default; static std::shared_ptr<QPDFObject> create(); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; private: QPDF_Reserved(); diff --git a/libqpdf/qpdf/QPDF_Stream.hh b/libqpdf/qpdf/QPDF_Stream.hh index 88331201..8488e157 100644 --- a/libqpdf/qpdf/QPDF_Stream.hh +++ b/libqpdf/qpdf/QPDF_Stream.hh @@ -16,19 +16,19 @@ class QPDF; class QPDF_Stream: public QPDFValue { public: - virtual ~QPDF_Stream() = default; + ~QPDF_Stream() override = default; static std::shared_ptr<QPDFObject> create( QPDF*, QPDFObjGen const& og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); - virtual void setDescription( - QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset); - virtual void disconnect(); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; + void setDescription( + QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) override; + void disconnect() override; QPDFObjectHandle getDict() const; bool isDataModified() const; void setFilterOnWrite(bool); diff --git a/libqpdf/qpdf/QPDF_String.hh b/libqpdf/qpdf/QPDF_String.hh index d4a1bfd4..c34cafef 100644 --- a/libqpdf/qpdf/QPDF_String.hh +++ b/libqpdf/qpdf/QPDF_String.hh @@ -10,16 +10,16 @@ class QPDF_String: public QPDFValue friend class QPDFWriter; public: - virtual ~QPDF_String() = default; + ~QPDF_String() override = default; static std::shared_ptr<QPDFObject> create(std::string const& val); static std::shared_ptr<QPDFObject> create_utf16(std::string const& utf8_val); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; std::string unparse(bool force_binary); - virtual JSON getJSON(int json_version); + JSON getJSON(int json_version) override; std::string getUTF8Val() const; - virtual std::string - getStringValue() const + std::string + getStringValue() const override { return val; } diff --git a/libqpdf/qpdf/QPDF_Unresolved.hh b/libqpdf/qpdf/QPDF_Unresolved.hh index 43d2af31..0a1fa9a5 100644 --- a/libqpdf/qpdf/QPDF_Unresolved.hh +++ b/libqpdf/qpdf/QPDF_Unresolved.hh @@ -6,11 +6,11 @@ class QPDF_Unresolved: public QPDFValue { public: - virtual ~QPDF_Unresolved() = default; + ~QPDF_Unresolved() override = default; static std::shared_ptr<QPDFObject> create(QPDF* qpdf, QPDFObjGen const& og); - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false); - virtual std::string unparse(); - virtual JSON getJSON(int json_version); + std::shared_ptr<QPDFObject> copy(bool shallow = false) override; + std::string unparse() override; + JSON getJSON(int json_version) override; private: QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og); diff --git a/libqpdf/qpdf/RC4.hh b/libqpdf/qpdf/RC4.hh index 257e6980..08bde7a3 100644 --- a/libqpdf/qpdf/RC4.hh +++ b/libqpdf/qpdf/RC4.hh @@ -11,8 +11,7 @@ class RC4 // key_len of -1 means treat key_data as a null-terminated string RC4(unsigned char const* key_data, int key_len = -1); - // It is safe to pass the same pointer to in_data and out_data to - // encrypt/decrypt in place + // It is safe to pass the same pointer to in_data and out_data to encrypt/decrypt in place void process(unsigned char const* in_data, size_t len, unsigned char* out_data); private: diff --git a/libqpdf/qpdf/ResourceFinder.hh b/libqpdf/qpdf/ResourceFinder.hh index d8cb32e6..1c4c59a7 100644 --- a/libqpdf/qpdf/ResourceFinder.hh +++ b/libqpdf/qpdf/ResourceFinder.hh @@ -7,7 +7,7 @@ class ResourceFinder: public QPDFObjectHandle::ParserCallbacks { public: ResourceFinder(); - virtual ~ResourceFinder() = default; + ~ResourceFinder() override = default; void handleObject(QPDFObjectHandle, size_t, size_t) override; void handleEOF() override; std::set<std::string> const& getNames() const; diff --git a/libqpdf/qpdf/SF_ASCII85Decode.hh b/libqpdf/qpdf/SF_ASCII85Decode.hh index 8cf85e66..d474904c 100644 --- a/libqpdf/qpdf/SF_ASCII85Decode.hh +++ b/libqpdf/qpdf/SF_ASCII85Decode.hh @@ -9,7 +9,7 @@ class SF_ASCII85Decode: public QPDFStreamFilter { public: SF_ASCII85Decode() = default; - virtual ~SF_ASCII85Decode() = default; + ~SF_ASCII85Decode() override = default; Pipeline* getDecodePipeline(Pipeline* next) override diff --git a/libqpdf/qpdf/SF_ASCIIHexDecode.hh b/libqpdf/qpdf/SF_ASCIIHexDecode.hh index cd87761e..bb21ede6 100644 --- a/libqpdf/qpdf/SF_ASCIIHexDecode.hh +++ b/libqpdf/qpdf/SF_ASCIIHexDecode.hh @@ -9,7 +9,7 @@ class SF_ASCIIHexDecode: public QPDFStreamFilter { public: SF_ASCIIHexDecode() = default; - virtual ~SF_ASCIIHexDecode() = default; + ~SF_ASCIIHexDecode() override = default; Pipeline* getDecodePipeline(Pipeline* next) override diff --git a/libqpdf/qpdf/SF_DCTDecode.hh b/libqpdf/qpdf/SF_DCTDecode.hh index 997ba89a..619cf9c4 100644 --- a/libqpdf/qpdf/SF_DCTDecode.hh +++ b/libqpdf/qpdf/SF_DCTDecode.hh @@ -9,7 +9,7 @@ class SF_DCTDecode: public QPDFStreamFilter { public: SF_DCTDecode() = default; - virtual ~SF_DCTDecode() = default; + ~SF_DCTDecode() override = default; Pipeline* getDecodePipeline(Pipeline* next) override diff --git a/libqpdf/qpdf/SF_FlateLzwDecode.hh b/libqpdf/qpdf/SF_FlateLzwDecode.hh index 2230ec58..203d893b 100644 --- a/libqpdf/qpdf/SF_FlateLzwDecode.hh +++ b/libqpdf/qpdf/SF_FlateLzwDecode.hh @@ -9,10 +9,10 @@ class SF_FlateLzwDecode: public QPDFStreamFilter { public: SF_FlateLzwDecode(bool lzw); - virtual ~SF_FlateLzwDecode() = default; + ~SF_FlateLzwDecode() override = default; - virtual bool setDecodeParms(QPDFObjectHandle decode_parms); - virtual Pipeline* getDecodePipeline(Pipeline* next); + bool setDecodeParms(QPDFObjectHandle decode_parms) override; + Pipeline* getDecodePipeline(Pipeline* next) override; static std::shared_ptr<QPDFStreamFilter> flate_factory(); static std::shared_ptr<QPDFStreamFilter> lzw_factory(); diff --git a/libqpdf/qpdf/SF_RunLengthDecode.hh b/libqpdf/qpdf/SF_RunLengthDecode.hh index 83c498dc..4a51cf6f 100644 --- a/libqpdf/qpdf/SF_RunLengthDecode.hh +++ b/libqpdf/qpdf/SF_RunLengthDecode.hh @@ -9,7 +9,7 @@ class SF_RunLengthDecode: public QPDFStreamFilter { public: SF_RunLengthDecode() = default; - virtual ~SF_RunLengthDecode() = default; + ~SF_RunLengthDecode() override = default; Pipeline* getDecodePipeline(Pipeline* next) override diff --git a/libqpdf/qpdf/SecureRandomDataProvider.hh b/libqpdf/qpdf/SecureRandomDataProvider.hh index d701a905..f6a29b76 100644 --- a/libqpdf/qpdf/SecureRandomDataProvider.hh +++ b/libqpdf/qpdf/SecureRandomDataProvider.hh @@ -7,8 +7,8 @@ class SecureRandomDataProvider: public RandomDataProvider { public: SecureRandomDataProvider() = default; - virtual ~SecureRandomDataProvider() = default; - virtual void provideRandomData(unsigned char* data, size_t len); + ~SecureRandomDataProvider() override = default; + void provideRandomData(unsigned char* data, size_t len) override; static RandomDataProvider* getInstance(); }; |