Commit 0e3d4cdc9753ae59d42ff8478b0769196899032b

Authored by Jay Berkenbilt
1 parent 8ad39a6c

Fix/clarify meaning of depth parameter to json write methods

include/qpdf/JSON.hh
@@ -65,16 +65,26 @@ class JSON @@ -65,16 +65,26 @@ class JSON
65 QPDF_DLL 65 QPDF_DLL
66 void write(Pipeline*, size_t depth = 0) const; 66 void write(Pipeline*, size_t depth = 0) const;
67 67
68 - // Helper methods for writing JSON incrementally. Several methods  
69 - // take a `bool& first` parameter. The open methods always set it  
70 - // to true, and the methods to output items always set it to  
71 - // false. This way, the item and close methods can always know  
72 - // whether or not a first item is being written. The intended mode  
73 - // of operation is to start with `bool first = true` (though it  
74 - // doesn't matter how it's initialized) and just pass the same  
75 - // `first` through to all the methods, letting the JSON object use  
76 - // it to keep track of when it's writing a first object and when  
77 - // it's not. 68 + // Helper methods for writing JSON incrementally.
  69 + //
  70 + // "first" -- Several methods take a `bool& first` parameter. The
  71 + // open methods always set it to true, and the methods to output
  72 + // items always set it to false. This way, the item and close
  73 + // methods can always know whether or not a first item is being
  74 + // written. The intended mode of operation is to start with a new
  75 + // `bool first = true` each time a new container is opened and
  76 + // to pass that `first` through to all the methods that are
  77 + // called to add top-level items to the container as well as to
  78 + // close the container. This lets the JSON object use it to keep
  79 + // track of when it's writing a first object and when it's not. If
  80 + // incrementally writing multiple levels of depth, a new `first`
  81 + // should used for each new container that is opened.
  82 + //
  83 + // "depth" -- Indicate the level of depth. This is used for
  84 + // consistent indentation. When writing incrementally, whenever
  85 + // you call a method to add an item to a container, the value of
  86 + // `depth` should be one more than whatever value is passed to the
  87 + // container open and close methods.
78 88
79 // Open methods ignore the value of first and set it to false 89 // Open methods ignore the value of first and set it to false
80 QPDF_DLL 90 QPDF_DLL
@@ -106,9 +116,12 @@ class JSON @@ -106,9 +116,12 @@ class JSON
106 Pipeline*, bool& first, JSON const& element, size_t depth = 0); 116 Pipeline*, bool& first, JSON const& element, size_t depth = 0);
107 // If writing nested structures incrementally, call writeNext 117 // If writing nested structures incrementally, call writeNext
108 // before opening a new array or container in the midst of an 118 // before opening a new array or container in the midst of an
109 - // existing one. The first you pass to writeNext should be the one  
110 - // for the parent object. Then start a new first for the nested  
111 - // item. 119 + // existing one. The `first` you pass to writeNext should be the
  120 + // one for the parent object. The depth should be the one for the
  121 + // child object. Then start a new `first` for the nested item.
  122 + // Note that writeDictionaryKey and writeArrayItem call writeNext
  123 + // for you, so this is most important when writing subsequent
  124 + // items or container openers to an array.
112 QPDF_DLL 125 QPDF_DLL
113 static void writeNext(Pipeline* p, bool& first, size_t depth = 0); 126 static void writeNext(Pipeline* p, bool& first, size_t depth = 0);
114 127
libqpdf/JSON.cc
@@ -56,7 +56,7 @@ JSON::writeNext(Pipeline* p, bool& first, size_t depth) @@ -56,7 +56,7 @@ JSON::writeNext(Pipeline* p, bool& first, size_t depth)
56 *p << ","; 56 *p << ",";
57 } 57 }
58 *p << "\n"; 58 *p << "\n";
59 - writeIndent(p, 1 + depth); 59 + writeIndent(p, depth);
60 } 60 }
61 61
62 void 62 void
@@ -102,7 +102,7 @@ JSON::writeDictionaryItem( @@ -102,7 +102,7 @@ JSON::writeDictionaryItem(
102 size_t depth) 102 size_t depth)
103 { 103 {
104 writeDictionaryKey(p, first, key, depth); 104 writeDictionaryKey(p, first, key, depth);
105 - value.write(p, 1 + depth); 105 + value.write(p, depth);
106 } 106 }
107 107
108 void 108 void
@@ -110,7 +110,7 @@ JSON::writeArrayItem( @@ -110,7 +110,7 @@ JSON::writeArrayItem(
110 Pipeline* p, bool& first, JSON const& element, size_t depth) 110 Pipeline* p, bool& first, JSON const& element, size_t depth)
111 { 111 {
112 writeNext(p, first, depth); 112 writeNext(p, first, depth);
113 - element.write(p, 1 + depth); 113 + element.write(p, depth);
114 } 114 }
115 115
116 void 116 void
@@ -119,7 +119,7 @@ JSON::JSON_dictionary::write(Pipeline* p, size_t depth) const @@ -119,7 +119,7 @@ JSON::JSON_dictionary::write(Pipeline* p, size_t depth) const
119 bool first = true; 119 bool first = true;
120 writeDictionaryOpen(p, first, depth); 120 writeDictionaryOpen(p, first, depth);
121 for (auto const& iter: members) { 121 for (auto const& iter: members) {
122 - writeDictionaryItem(p, first, iter.first, iter.second, depth); 122 + writeDictionaryItem(p, first, iter.first, iter.second, 1 + depth);
123 } 123 }
124 writeDictionaryClose(p, first, depth); 124 writeDictionaryClose(p, first, depth);
125 } 125 }
@@ -130,7 +130,7 @@ JSON::JSON_array::write(Pipeline* p, size_t depth) const @@ -130,7 +130,7 @@ JSON::JSON_array::write(Pipeline* p, size_t depth) const
130 bool first = true; 130 bool first = true;
131 writeArrayOpen(p, first, depth); 131 writeArrayOpen(p, first, depth);
132 for (auto const& element: elements) { 132 for (auto const& element: elements) {
133 - writeArrayItem(p, first, element, depth); 133 + writeArrayItem(p, first, element, 1 + depth);
134 } 134 }
135 writeArrayClose(p, first, depth); 135 writeArrayClose(p, first, depth);
136 } 136 }
libqpdf/QPDFJob.cc
@@ -1082,7 +1082,7 @@ QPDFJob::doJSONObject( @@ -1082,7 +1082,7 @@ QPDFJob::doJSONObject(
1082 Pipeline* p, bool& first, std::string const& key, QPDFObjectHandle& obj) 1082 Pipeline* p, bool& first, std::string const& key, QPDFObjectHandle& obj)
1083 { 1083 {
1084 if (this->m->json_version == 1) { 1084 if (this->m->json_version == 1) {
1085 - JSON::writeDictionaryItem(p, first, key, obj.getJSON(1, true), 1); 1085 + JSON::writeDictionaryItem(p, first, key, obj.getJSON(1, true), 2);
1086 } else { 1086 } else {
1087 auto j = JSON::makeDictionary(); 1087 auto j = JSON::makeDictionary();
1088 if (obj.isStream()) { 1088 if (obj.isStream()) {
@@ -1093,14 +1093,14 @@ QPDFJob::doJSONObject( @@ -1093,14 +1093,14 @@ QPDFJob::doJSONObject(
1093 j.addDictionaryMember( 1093 j.addDictionaryMember(
1094 "value", obj.getJSON(this->m->json_version, true)); 1094 "value", obj.getJSON(this->m->json_version, true));
1095 } 1095 }
1096 - JSON::writeDictionaryItem(p, first, key, j, 1); 1096 + JSON::writeDictionaryItem(p, first, key, j, 2);
1097 } 1097 }
1098 } 1098 }
1099 1099
1100 void 1100 void
1101 QPDFJob::doJSONObjects(Pipeline* p, bool& first, QPDF& pdf) 1101 QPDFJob::doJSONObjects(Pipeline* p, bool& first, QPDF& pdf)
1102 { 1102 {
1103 - JSON::writeDictionaryKey(p, first, "objects", 0); 1103 + JSON::writeDictionaryKey(p, first, "objects", 1);
1104 bool first_object = true; 1104 bool first_object = true;
1105 JSON::writeDictionaryOpen(p, first_object, 1); 1105 JSON::writeDictionaryOpen(p, first_object, 1);
1106 bool all_objects = m->json_objects.empty(); 1106 bool all_objects = m->json_objects.empty();
@@ -1124,7 +1124,7 @@ QPDFJob::doJSONObjects(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1124,7 +1124,7 @@ QPDFJob::doJSONObjects(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1124 void 1124 void
1125 QPDFJob::doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf) 1125 QPDFJob::doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf)
1126 { 1126 {
1127 - JSON::writeDictionaryKey(p, first, "objectinfo", 0); 1127 + JSON::writeDictionaryKey(p, first, "objectinfo", 1);
1128 bool first_object = true; 1128 bool first_object = true;
1129 JSON::writeDictionaryOpen(p, first_object, 1); 1129 JSON::writeDictionaryOpen(p, first_object, 1);
1130 bool all_objects = m->json_objects.empty(); 1130 bool all_objects = m->json_objects.empty();
@@ -1147,7 +1147,7 @@ QPDFJob::doJSONObjectinfo(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1147,7 +1147,7 @@ QPDFJob::doJSONObjectinfo(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1147 this->m->json_version, true) 1147 this->m->json_version, true)
1148 : JSON::makeNull())); 1148 : JSON::makeNull()));
1149 JSON::writeDictionaryItem( 1149 JSON::writeDictionaryItem(
1150 - p, first_object, obj.unparse(), j_details, 1); 1150 + p, first_object, obj.unparse(), j_details, 2);
1151 } 1151 }
1152 } 1152 }
1153 JSON::writeDictionaryClose(p, first_object, 1); 1153 JSON::writeDictionaryClose(p, first_object, 1);
@@ -1156,9 +1156,9 @@ QPDFJob::doJSONObjectinfo(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1156,9 +1156,9 @@ QPDFJob::doJSONObjectinfo(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1156 void 1156 void
1157 QPDFJob::doJSONPages(Pipeline* p, bool& first, QPDF& pdf) 1157 QPDFJob::doJSONPages(Pipeline* p, bool& first, QPDF& pdf)
1158 { 1158 {
1159 - JSON::writeDictionaryKey(p, first, "pages", 0); 1159 + JSON::writeDictionaryKey(p, first, "pages", 1);
1160 bool first_page = true; 1160 bool first_page = true;
1161 - JSON::writeArrayOpen(p, first_page, 1); 1161 + JSON::writeArrayOpen(p, first_page, 2);
1162 QPDFPageLabelDocumentHelper pldh(pdf); 1162 QPDFPageLabelDocumentHelper pldh(pdf);
1163 QPDFOutlineDocumentHelper odh(pdf); 1163 QPDFOutlineDocumentHelper odh(pdf);
1164 int pageno = -1; 1164 int pageno = -1;
@@ -1232,7 +1232,7 @@ QPDFJob::doJSONPages(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1232,7 +1232,7 @@ QPDFJob::doJSONPages(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1232 "dest", oiter.getDest().getJSON(this->m->json_version, true)); 1232 "dest", oiter.getDest().getJSON(this->m->json_version, true));
1233 } 1233 }
1234 j_page.addDictionaryMember("pageposfrom1", JSON::makeInt(1 + pageno)); 1234 j_page.addDictionaryMember("pageposfrom1", JSON::makeInt(1 + pageno));
1235 - JSON::writeArrayItem(p, first_page, j_page, 1); 1235 + JSON::writeArrayItem(p, first_page, j_page, 2);
1236 } 1236 }
1237 JSON::writeArrayClose(p, first_page, 1); 1237 JSON::writeArrayClose(p, first_page, 1);
1238 } 1238 }
@@ -1262,7 +1262,7 @@ QPDFJob::doJSONPageLabels(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1262,7 +1262,7 @@ QPDFJob::doJSONPageLabels(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1262 "label", (*iter).getJSON(this->m->json_version)); 1262 "label", (*iter).getJSON(this->m->json_version));
1263 } 1263 }
1264 } 1264 }
1265 - JSON::writeDictionaryItem(p, first, "pagelabels", j_labels, 0); 1265 + JSON::writeDictionaryItem(p, first, "pagelabels", j_labels, 1);
1266 } 1266 }
1267 1267
1268 void 1268 void
@@ -1306,7 +1306,7 @@ QPDFJob::doJSONOutlines(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1306,7 +1306,7 @@ QPDFJob::doJSONOutlines(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1306 JSON j_outlines = JSON::makeArray(); 1306 JSON j_outlines = JSON::makeArray();
1307 QPDFOutlineDocumentHelper odh(pdf); 1307 QPDFOutlineDocumentHelper odh(pdf);
1308 addOutlinesToJson(odh.getTopLevelOutlines(), j_outlines, page_numbers); 1308 addOutlinesToJson(odh.getTopLevelOutlines(), j_outlines, page_numbers);
1309 - JSON::writeDictionaryItem(p, first, "outlines", j_outlines, 0); 1309 + JSON::writeDictionaryItem(p, first, "outlines", j_outlines, 1);
1310 } 1310 }
1311 1311
1312 void 1312 void
@@ -1374,7 +1374,7 @@ QPDFJob::doJSONAcroform(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1374,7 +1374,7 @@ QPDFJob::doJSONAcroform(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1374 "annotationflags", JSON::makeInt(aoh.getFlags())); 1374 "annotationflags", JSON::makeInt(aoh.getFlags()));
1375 } 1375 }
1376 } 1376 }
1377 - JSON::writeDictionaryItem(p, first, "acroform", j_acroform, 0); 1377 + JSON::writeDictionaryItem(p, first, "acroform", j_acroform, 1);
1378 } 1378 }
1379 1379
1380 void 1380 void
@@ -1470,7 +1470,7 @@ QPDFJob::doJSONEncrypt(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1470,7 +1470,7 @@ QPDFJob::doJSONEncrypt(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1470 "stringmethod", JSON::makeString(s_string_method)); 1470 "stringmethod", JSON::makeString(s_string_method));
1471 j_parameters.addDictionaryMember( 1471 j_parameters.addDictionaryMember(
1472 "filemethod", JSON::makeString(s_file_method)); 1472 "filemethod", JSON::makeString(s_file_method));
1473 - JSON::writeDictionaryItem(p, first, "encrypt", j_encrypt, 0); 1473 + JSON::writeDictionaryItem(p, first, "encrypt", j_encrypt, 1);
1474 } 1474 }
1475 1475
1476 void 1476 void
@@ -1532,7 +1532,7 @@ QPDFJob::doJSONAttachments(Pipeline* p, bool&amp; first, QPDF&amp; pdf) @@ -1532,7 +1532,7 @@ QPDFJob::doJSONAttachments(Pipeline* p, bool&amp; first, QPDF&amp; pdf)
1532 null_or_string(QUtil::hex_encode(efs.getChecksum()))); 1532 null_or_string(QUtil::hex_encode(efs.getChecksum())));
1533 } 1533 }
1534 } 1534 }
1535 - JSON::writeDictionaryItem(p, first, "attachments", j_attachments, 0); 1535 + JSON::writeDictionaryItem(p, first, "attachments", j_attachments, 1);
1536 } 1536 }
1537 1537
1538 JSON 1538 JSON
@@ -1755,7 +1755,7 @@ QPDFJob::doJSON(QPDF&amp; pdf, Pipeline* p) @@ -1755,7 +1755,7 @@ QPDFJob::doJSON(QPDF&amp; pdf, Pipeline* p)
1755 // ignore unrecognized keys, so we only update the version of a 1755 // ignore unrecognized keys, so we only update the version of a
1756 // key disappears or if its value changes meaning. 1756 // key disappears or if its value changes meaning.
1757 JSON::writeDictionaryItem( 1757 JSON::writeDictionaryItem(
1758 - p, first, "version", JSON::makeInt(this->m->json_version), 0); 1758 + p, first, "version", JSON::makeInt(this->m->json_version), 1);
1759 JSON j_params = JSON::makeDictionary(); 1759 JSON j_params = JSON::makeDictionary();
1760 std::string decode_level_str; 1760 std::string decode_level_str;
1761 switch (m->decode_level) { 1761 switch (m->decode_level) {
@@ -1774,7 +1774,7 @@ QPDFJob::doJSON(QPDF&amp; pdf, Pipeline* p) @@ -1774,7 +1774,7 @@ QPDFJob::doJSON(QPDF&amp; pdf, Pipeline* p)
1774 } 1774 }
1775 j_params.addDictionaryMember( 1775 j_params.addDictionaryMember(
1776 "decodelevel", JSON::makeString(decode_level_str)); 1776 "decodelevel", JSON::makeString(decode_level_str));
1777 - JSON::writeDictionaryItem(p, first, "parameters", j_params, 0); 1777 + JSON::writeDictionaryItem(p, first, "parameters", j_params, 1);
1778 1778
1779 bool all_keys = m->json_keys.empty(); 1779 bool all_keys = m->json_keys.empty();
1780 // The list of selectable top-level keys id duplicated in the 1780 // The list of selectable top-level keys id duplicated in the
libqpdf/QPDF_json.cc
@@ -739,7 +739,7 @@ QPDF::writeJSONStream( @@ -739,7 +739,7 @@ QPDF::writeJSONStream(
739 obj.getStreamJSON( 739 obj.getStreamJSON(
740 version, json_stream_data, decode_level, stream_p, filename)); 740 version, json_stream_data, decode_level, stream_p, filename));
741 741
742 - JSON::writeDictionaryItem(p, first, key, j, 2); 742 + JSON::writeDictionaryItem(p, first, key, j, 3);
743 if (f) { 743 if (f) {
744 f_pl->finish(); 744 f_pl->finish();
745 f_pl = nullptr; 745 f_pl = nullptr;
@@ -757,7 +757,7 @@ QPDF::writeJSONObject( @@ -757,7 +757,7 @@ QPDF::writeJSONObject(
757 { 757 {
758 auto j = JSON::makeDictionary(); 758 auto j = JSON::makeDictionary();
759 j.addDictionaryMember("value", obj.getJSON(version, true)); 759 j.addDictionaryMember("value", obj.getJSON(version, true));
760 - JSON::writeDictionaryItem(p, first, key, j, 2); 760 + JSON::writeDictionaryItem(p, first, key, j, 3);
761 } 761 }
762 762
763 void 763 void
@@ -774,19 +774,23 @@ QPDF::writeJSON( @@ -774,19 +774,23 @@ QPDF::writeJSON(
774 "QPDF::writeJSON: only version 2 is supported"); 774 "QPDF::writeJSON: only version 2 is supported");
775 } 775 }
776 bool first = true; 776 bool first = true;
777 - JSON::writeDictionaryOpen(p, first, 0);  
778 - JSON::writeDictionaryKey(p, first, "qpdf-v2", 0); 777 + if (complete) {
  778 + JSON::writeDictionaryOpen(p, first, 0);
  779 + } else {
  780 + first = first_key;
  781 + }
  782 + JSON::writeDictionaryKey(p, first, "qpdf-v2", 1);
779 bool first_qpdf = true; 783 bool first_qpdf = true;
780 - JSON::writeDictionaryOpen(p, first_qpdf, 1); 784 + JSON::writeDictionaryOpen(p, first_qpdf, 2);
781 JSON::writeDictionaryItem( 785 JSON::writeDictionaryItem(
782 - p, first_qpdf, "pdfversion", JSON::makeString(getPDFVersion()), 1); 786 + p, first_qpdf, "pdfversion", JSON::makeString(getPDFVersion()), 2);
783 JSON::writeDictionaryItem( 787 JSON::writeDictionaryItem(
784 p, 788 p,
785 first_qpdf, 789 first_qpdf,
786 "maxobjectid", 790 "maxobjectid",
787 JSON::makeInt(QIntC::to_longlong(getObjectCount())), 791 JSON::makeInt(QIntC::to_longlong(getObjectCount())),
788 - 1);  
789 - JSON::writeDictionaryKey(p, first_qpdf, "objects", 1); 792 + 2);
  793 + JSON::writeDictionaryKey(p, first_qpdf, "objects", 2);
790 bool first_object = true; 794 bool first_object = true;
791 JSON::writeDictionaryOpen(p, first_object, 2); 795 JSON::writeDictionaryOpen(p, first_object, 2);
792 bool all_objects = wanted_objects.empty(); 796 bool all_objects = wanted_objects.empty();