Commit cfd173232b3d0cc7d22cd64ffa01ad6dc4705947

Authored by m-holger
1 parent 0421e2ae

Refactor `QPDFAcroFormDocumentHelper::transformAnnotations`: replace `std::list`…

… with `std::deque` in `traverse_field` for better performance and simplify traversal logic.
libqpdf/QPDFAcroFormDocumentHelper.cc
@@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
8 #include <qpdf/QUtil.hh> 8 #include <qpdf/QUtil.hh>
9 #include <qpdf/ResourceFinder.hh> 9 #include <qpdf/ResourceFinder.hh>
10 10
  11 +#include <deque>
11 #include <utility> 12 #include <utility>
12 13
13 using namespace qpdf; 14 using namespace qpdf;
@@ -834,15 +835,15 @@ QPDFAcroFormDocumentHelper::transformAnnotations( @@ -834,15 +835,15 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
834 } 835 }
835 }; 836 };
836 837
  838 + // Traverse the field, copying kids, and preserving integrity.
837 auto traverse_field = [&](QPDFObjectHandle& top_field) -> void { 839 auto traverse_field = [&](QPDFObjectHandle& top_field) -> void {
838 - std::list<Dictionary> queue; 840 + std::deque<Dictionary> queue({top_field});
839 QPDFObjGen::set seen; 841 QPDFObjGen::set seen;
840 - queue.emplace_back(top_field);  
841 - for (; !queue.empty(); queue.pop_front()) {  
842 - auto& obj = queue.front(); 842 + for (auto it = queue.begin(); it != queue.end(); ++it) {
  843 + auto& obj = *it;
843 if (seen.add(obj)) { 844 if (seen.add(obj)) {
844 - auto parent = obj["/Parent"];  
845 - if (parent.isIndirect()) { 845 + Dictionary parent = obj["/Parent"];
  846 + if (parent.indirect()) {
846 auto parent_og = parent.id_gen(); 847 auto parent_og = parent.id_gen();
847 if (orig_to_copy.contains(parent_og)) { 848 if (orig_to_copy.contains(parent_og)) {
848 obj.replaceKey("/Parent", orig_to_copy[parent_og]); 849 obj.replaceKey("/Parent", orig_to_copy[parent_og]);
@@ -850,8 +851,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations( @@ -850,8 +851,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
850 parent.warn( 851 parent.warn(
851 "while traversing field " + obj.id_gen().unparse(',') + 852 "while traversing field " + obj.id_gen().unparse(',') +
852 ", found parent (" + parent_og.unparse(',') + 853 ", found parent (" + parent_og.unparse(',') +
853 - ") that had not been seen, indicating likely invalid field "  
854 - "structure"); 854 + ") that had not been seen, indicating likely invalid field structure");
855 } 855 }
856 } 856 }
857 size_t i = 0; 857 size_t i = 0;
@@ -946,7 +946,6 @@ QPDFAcroFormDocumentHelper::transformAnnotations( @@ -946,7 +946,6 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
946 old_fields.insert(top_field.getObjGen()); 946 old_fields.insert(top_field.getObjGen());
947 } 947 }
948 948
949 - // Traverse the field, copying kids, and preserving integrity.  
950 if (maybe_copy_object(top_field)) { 949 if (maybe_copy_object(top_field)) {
951 traverse_field(top_field); 950 traverse_field(top_field);
952 } 951 }
@@ -986,9 +985,9 @@ QPDFAcroFormDocumentHelper::transformAnnotations( @@ -986,9 +985,9 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
986 985
987 // Now we have copies, so we can safely mutate. 986 // Now we have copies, so we can safely mutate.
988 if (have_field && added_new_fields.add(top_field)) { 987 if (have_field && added_new_fields.add(top_field)) {
989 - new_fields.push_back(top_field); 988 + new_fields.emplace_back(top_field);
990 } 989 }
991 - new_annots.push_back(annot); 990 + new_annots.emplace_back(annot);
992 991
993 // Identify and copy any appearance streams 992 // Identify and copy any appearance streams
994 993