Commit 1b7c87279a1f78c881c1e7010102f8909e8356d4
1 parent
117a35dc
Use QPDFObjectHandle::as_array to iterate over arrays in library
Showing
7 changed files
with
58 additions
and
92 deletions
libqpdf/QPDF.cc
| ... | ... | @@ -2346,9 +2346,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top) |
| 2346 | 2346 | |
| 2347 | 2347 | if (foreign_tc == ::ot_array) { |
| 2348 | 2348 | QTC::TC("qpdf", "QPDF reserve array"); |
| 2349 | - int n = foreign.getArrayNItems(); | |
| 2350 | - for (int i = 0; i < n; ++i) { | |
| 2351 | - reserveObjects(foreign.getArrayItem(i), obj_copier, false); | |
| 2349 | + for (auto const& item: foreign.as_array()) { | |
| 2350 | + reserveObjects(item, obj_copier, false); | |
| 2352 | 2351 | } |
| 2353 | 2352 | } else if (foreign_tc == ::ot_dictionary) { |
| 2354 | 2353 | QTC::TC("qpdf", "QPDF reserve dictionary"); |
| ... | ... | @@ -2384,11 +2383,8 @@ QPDF::replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_cop |
| 2384 | 2383 | } else if (foreign_tc == ::ot_array) { |
| 2385 | 2384 | QTC::TC("qpdf", "QPDF replace array"); |
| 2386 | 2385 | result = QPDFObjectHandle::newArray(); |
| 2387 | - int n = foreign.getArrayNItems(); | |
| 2388 | - for (int i = 0; i < n; ++i) { | |
| 2389 | - result.appendItem( | |
| 2390 | - // line-break | |
| 2391 | - replaceForeignIndirectObjects(foreign.getArrayItem(i), obj_copier, false)); | |
| 2386 | + for (auto const& item: foreign.as_array()) { | |
| 2387 | + result.appendItem(replaceForeignIndirectObjects(item, obj_copier, false)); | |
| 2392 | 2388 | } |
| 2393 | 2389 | } else if (foreign_tc == ::ot_dictionary) { |
| 2394 | 2390 | QTC::TC("qpdf", "QPDF replace dictionary"); |
| ... | ... | @@ -2714,11 +2710,8 @@ QPDF::getCompressibleObjGens() |
| 2714 | 2710 | queue.emplace_back(iter->second); |
| 2715 | 2711 | } |
| 2716 | 2712 | } |
| 2717 | - } else if (obj.isArray()) { | |
| 2718 | - int n = obj.getArrayNItems(); | |
| 2719 | - for (int i = 1; i <= n; ++i) { | |
| 2720 | - queue.push_back(obj.getArrayItem(n - i)); | |
| 2721 | - } | |
| 2713 | + } else if (auto items = obj.as_array()) { | |
| 2714 | + queue.insert(queue.end(), items.crbegin(), items.crend()); | |
| 2722 | 2715 | } |
| 2723 | 2716 | } |
| 2724 | 2717 | ... | ... |
libqpdf/QPDFAcroFormDocumentHelper.cc
| ... | ... | @@ -7,6 +7,8 @@ |
| 7 | 7 | #include <qpdf/QUtil.hh> |
| 8 | 8 | #include <qpdf/ResourceFinder.hh> |
| 9 | 9 | |
| 10 | +using namespace qpdf; | |
| 11 | + | |
| 10 | 12 | QPDFAcroFormDocumentHelper::Members::Members() : |
| 11 | 13 | cache_valid(false) |
| 12 | 14 | { |
| ... | ... | @@ -239,26 +241,25 @@ QPDFAcroFormDocumentHelper::analyze() |
| 239 | 241 | return; |
| 240 | 242 | } |
| 241 | 243 | m->cache_valid = true; |
| 242 | - QPDFObjectHandle acroform = this->qpdf.getRoot().getKey("/AcroForm"); | |
| 244 | + QPDFObjectHandle acroform = qpdf.getRoot().getKey("/AcroForm"); | |
| 243 | 245 | if (!(acroform.isDictionary() && acroform.hasKey("/Fields"))) { |
| 244 | 246 | return; |
| 245 | 247 | } |
| 246 | 248 | QPDFObjectHandle fields = acroform.getKey("/Fields"); |
| 247 | - if (!fields.isArray()) { | |
| 249 | + if (auto fa = fields.as_array(strict)) { | |
| 250 | + // Traverse /AcroForm to find annotations and map them bidirectionally to fields. | |
| 251 | + | |
| 252 | + QPDFObjGen::set visited; | |
| 253 | + QPDFObjectHandle null(QPDFObjectHandle::newNull()); | |
| 254 | + for (auto const& field: fa) { | |
| 255 | + traverseField(field, null, 0, visited); | |
| 256 | + } | |
| 257 | + } else { | |
| 248 | 258 | QTC::TC("qpdf", "QPDFAcroFormDocumentHelper fields not array"); |
| 249 | 259 | acroform.warnIfPossible("/Fields key of /AcroForm dictionary is not an array; ignoring"); |
| 250 | 260 | fields = QPDFObjectHandle::newArray(); |
| 251 | 261 | } |
| 252 | 262 | |
| 253 | - // Traverse /AcroForm to find annotations and map them bidirectionally to fields. | |
| 254 | - | |
| 255 | - QPDFObjGen::set visited; | |
| 256 | - int nfields = fields.getArrayNItems(); | |
| 257 | - QPDFObjectHandle null(QPDFObjectHandle::newNull()); | |
| 258 | - for (int i = 0; i < nfields; ++i) { | |
| 259 | - traverseField(fields.getArrayItem(i), null, 0, visited); | |
| 260 | - } | |
| 261 | - | |
| 262 | 263 | // All Widget annotations should have been encountered by traversing /AcroForm, but in case any |
| 263 | 264 | // weren't, find them by walking through pages, and treat any widget annotation that is not |
| 264 | 265 | // associated with a field as its own field. This just ensures that requesting the field for any |
| ... | ... | @@ -325,12 +326,10 @@ QPDFAcroFormDocumentHelper::traverseField( |
| 325 | 326 | |
| 326 | 327 | bool is_annotation = false; |
| 327 | 328 | bool is_field = (0 == depth); |
| 328 | - QPDFObjectHandle kids = field.getKey("/Kids"); | |
| 329 | - if (kids.isArray()) { | |
| 329 | + if (auto a = field.getKey("/Kids").as_array(strict)) { | |
| 330 | 330 | is_field = true; |
| 331 | - int nkids = kids.getArrayNItems(); | |
| 332 | - for (int k = 0; k < nkids; ++k) { | |
| 333 | - traverseField(kids.getArrayItem(k), field, 1 + depth, visited); | |
| 331 | + for (auto const& item: a) { | |
| 332 | + traverseField(item, field, 1 + depth, visited); | |
| 334 | 333 | } |
| 335 | 334 | } else { |
| 336 | 335 | if (field.hasKey("/Parent")) { | ... | ... |
libqpdf/QPDFFormFieldObjectHelper.cc
| ... | ... | @@ -272,14 +272,9 @@ QPDFFormFieldObjectHelper::getChoices() |
| 272 | 272 | if (!isChoice()) { |
| 273 | 273 | return result; |
| 274 | 274 | } |
| 275 | - QPDFObjectHandle opt = getInheritableFieldValue("/Opt"); | |
| 276 | - if (opt.isArray()) { | |
| 277 | - int n = opt.getArrayNItems(); | |
| 278 | - for (int i = 0; i < n; ++i) { | |
| 279 | - QPDFObjectHandle item = opt.getArrayItem(i); | |
| 280 | - if (item.isString()) { | |
| 281 | - result.push_back(item.getUTF8Value()); | |
| 282 | - } | |
| 275 | + for (auto const& item: getInheritableFieldValue("/Opt").as_array()) { | |
| 276 | + if (item.isString()) { | |
| 277 | + result.emplace_back(item.getUTF8Value()); | |
| 283 | 278 | } |
| 284 | 279 | } |
| 285 | 280 | return result; |
| ... | ... | @@ -369,30 +364,21 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) |
| 369 | 364 | |
| 370 | 365 | QPDFObjectHandle kids = oh().getKey("/Kids"); |
| 371 | 366 | if (!(isRadioButton() && parent.isNull() && kids.isArray())) { |
| 372 | - oh().warnIfPossible( | |
| 373 | - "don't know how to set the value" | |
| 374 | - " of this field as a radio button"); | |
| 367 | + oh().warnIfPossible("don't know how to set the value of this field as a radio button"); | |
| 375 | 368 | return; |
| 376 | 369 | } |
| 377 | 370 | setFieldAttribute("/V", name); |
| 378 | - int nkids = kids.getArrayNItems(); | |
| 379 | - for (int i = 0; i < nkids; ++i) { | |
| 380 | - QPDFObjectHandle kid = kids.getArrayItem(i); | |
| 371 | + for (auto const& kid: kids.as_array()) { | |
| 381 | 372 | QPDFObjectHandle AP = kid.getKey("/AP"); |
| 382 | 373 | QPDFObjectHandle annot; |
| 383 | - if (AP.isNull()) { | |
| 374 | + if (AP.null()) { | |
| 384 | 375 | // The widget may be below. If there is more than one, just find the first one. |
| 385 | - QPDFObjectHandle grandkids = kid.getKey("/Kids"); | |
| 386 | - if (grandkids.isArray()) { | |
| 387 | - int ngrandkids = grandkids.getArrayNItems(); | |
| 388 | - for (int j = 0; j < ngrandkids; ++j) { | |
| 389 | - QPDFObjectHandle grandkid = grandkids.getArrayItem(j); | |
| 390 | - AP = grandkid.getKey("/AP"); | |
| 391 | - if (!AP.isNull()) { | |
| 392 | - QTC::TC("qpdf", "QPDFFormFieldObjectHelper radio button grandkid"); | |
| 393 | - annot = grandkid; | |
| 394 | - break; | |
| 395 | - } | |
| 376 | + for (auto const& grandkid: kid.getKey("/Kids").as_array()) { | |
| 377 | + AP = grandkid.getKey("/AP"); | |
| 378 | + if (!AP.null()) { | |
| 379 | + QTC::TC("qpdf", "QPDFFormFieldObjectHelper radio button grandkid"); | |
| 380 | + annot = grandkid; | |
| 381 | + break; | |
| 396 | 382 | } |
| 397 | 383 | } |
| 398 | 384 | } else { |
| ... | ... | @@ -419,20 +405,16 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) |
| 419 | 405 | { |
| 420 | 406 | QPDFObjectHandle AP = oh().getKey("/AP"); |
| 421 | 407 | QPDFObjectHandle annot; |
| 422 | - if (AP.isNull()) { | |
| 408 | + if (AP.null()) { | |
| 423 | 409 | // The widget may be below. If there is more than one, just |
| 424 | 410 | // find the first one. |
| 425 | 411 | QPDFObjectHandle kids = oh().getKey("/Kids"); |
| 426 | - if (kids.isArray()) { | |
| 427 | - int nkids = kids.getArrayNItems(); | |
| 428 | - for (int i = 0; i < nkids; ++i) { | |
| 429 | - QPDFObjectHandle kid = kids.getArrayItem(i); | |
| 430 | - AP = kid.getKey("/AP"); | |
| 431 | - if (!AP.isNull()) { | |
| 432 | - QTC::TC("qpdf", "QPDFFormFieldObjectHelper checkbox kid widget"); | |
| 433 | - annot = kid; | |
| 434 | - break; | |
| 435 | - } | |
| 412 | + for (auto const& kid: oh().getKey("/Kids").as_array(qpdf::strict)) { | |
| 413 | + AP = kid.getKey("/AP"); | |
| 414 | + if (!AP.null()) { | |
| 415 | + QTC::TC("qpdf", "QPDFFormFieldObjectHelper checkbox kid widget"); | |
| 416 | + annot = kid; | |
| 417 | + break; | |
| 436 | 418 | } |
| 437 | 419 | } |
| 438 | 420 | } else { | ... | ... |
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -365,7 +365,7 @@ QPDFObject::copy(bool shallow) |
| 365 | 365 | case ::ot_reference: |
| 366 | 366 | return qpdf->getObject(og).getObj(); |
| 367 | 367 | } |
| 368 | - return {}; // does not return | |
| 368 | + return {}; // unreachable | |
| 369 | 369 | } |
| 370 | 370 | |
| 371 | 371 | std::string |
| ... | ... | @@ -446,7 +446,7 @@ QPDFObject::unparse() |
| 446 | 446 | case ::ot_reference: |
| 447 | 447 | return og.unparse(' ') + " R"; |
| 448 | 448 | } |
| 449 | - return {}; // does not return | |
| 449 | + return {}; // unreachable | |
| 450 | 450 | } |
| 451 | 451 | |
| 452 | 452 | void |
| ... | ... | @@ -644,9 +644,8 @@ QPDFObject::getStringValue() const |
| 644 | 644 | return std::get<QPDF_Reference>(value).obj->getStringValue(); |
| 645 | 645 | default: |
| 646 | 646 | throw std::logic_error("Internal error in QPDFObject::getStringValue"); |
| 647 | - return ""; // does not return | |
| 648 | 647 | } |
| 649 | - return {}; // does not return | |
| 648 | + return ""; // unreachable | |
| 650 | 649 | } |
| 651 | 650 | |
| 652 | 651 | bool |
| ... | ... | @@ -1927,12 +1926,10 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) |
| 1927 | 1926 | |
| 1928 | 1927 | if (isBool() || isInteger() || isName() || isNull() || isReal() || isString()) { |
| 1929 | 1928 | this->obj = obj->copy(true); |
| 1930 | - } else if (isArray()) { | |
| 1929 | + } else if (auto a = as_array(strict)) { | |
| 1931 | 1930 | std::vector<QPDFObjectHandle> items; |
| 1932 | - auto array = as_array(strict); | |
| 1933 | - int n = array.size(); | |
| 1934 | - for (int i = 0; i < n; ++i) { | |
| 1935 | - items.emplace_back(array.at(i).second); | |
| 1931 | + for (auto const& item: a) { | |
| 1932 | + items.emplace_back(item); | |
| 1936 | 1933 | items.back().makeDirect(visited, stop_at_streams); |
| 1937 | 1934 | } |
| 1938 | 1935 | this->obj = QPDFObject::create<QPDF_Array>(items); | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -1129,7 +1129,7 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) |
| 1129 | 1129 | return; |
| 1130 | 1130 | } else if (!m->linearized) { |
| 1131 | 1131 | if (object.isArray()) { |
| 1132 | - for (auto& item: object.getArrayAsVector()) { | |
| 1132 | + for (auto& item: object.as_array()) { | |
| 1133 | 1133 | enqueueObject(item); |
| 1134 | 1134 | } |
| 1135 | 1135 | } else if (auto d = object.as_dictionary()) { |
| ... | ... | @@ -1350,7 +1350,7 @@ QPDFWriter::unparseObject( |
| 1350 | 1350 | // [ in the /H key of the linearization parameter dictionary. We'll do this unconditionally |
| 1351 | 1351 | // for all arrays because it looks nicer and doesn't make the files that much bigger. |
| 1352 | 1352 | writeString("["); |
| 1353 | - for (auto const& item: object.getArrayAsVector()) { | |
| 1353 | + for (auto const& item: object.as_array()) { | |
| 1354 | 1354 | writeString(indent); |
| 1355 | 1355 | writeStringQDF(" "); |
| 1356 | 1356 | unparseChild(item, level + 1, child_flags); |
| ... | ... | @@ -1892,12 +1892,10 @@ QPDFWriter::generateID() |
| 1892 | 1892 | } |
| 1893 | 1893 | seed += " QPDF "; |
| 1894 | 1894 | if (trailer.hasKey("/Info")) { |
| 1895 | - QPDFObjectHandle info = trailer.getKey("/Info"); | |
| 1896 | - for (auto const& key: info.getKeys()) { | |
| 1897 | - QPDFObjectHandle obj = info.getKey(key); | |
| 1898 | - if (obj.isString()) { | |
| 1895 | + for (auto const& item: trailer.getKey("/Info").as_dictionary()) { | |
| 1896 | + if (item.second.isString()) { | |
| 1899 | 1897 | seed += " "; |
| 1900 | - seed += obj.getStringValue(); | |
| 1898 | + seed += item.second.getStringValue(); | |
| 1901 | 1899 | } |
| 1902 | 1900 | } |
| 1903 | 1901 | } |
| ... | ... | @@ -1923,8 +1921,7 @@ QPDFWriter::generateID() |
| 1923 | 1921 | void |
| 1924 | 1922 | QPDFWriter::initializeSpecialStreams() |
| 1925 | 1923 | { |
| 1926 | - // Mark all page content streams in case we are filtering or | |
| 1927 | - // normalizing. | |
| 1924 | + // Mark all page content streams in case we are filtering or normalizing. | |
| 1928 | 1925 | std::vector<QPDFObjectHandle> pages = m->pdf.getAllPages(); |
| 1929 | 1926 | int num = 0; |
| 1930 | 1927 | for (auto& page: pages) { | ... | ... |
libqpdf/QPDF_optimization.cc
| ... | ... | @@ -319,9 +319,8 @@ QPDF::updateObjectMaps( |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | if (cur.oh.isArray()) { |
| 322 | - int n = cur.oh.getArrayNItems(); | |
| 323 | - for (int i = 0; i < n; ++i) { | |
| 324 | - pending.emplace_back(cur.ou, cur.oh.getArrayItem(i), false); | |
| 322 | + for (auto const& item: cur.oh.as_array()) { | |
| 323 | + pending.emplace_back(cur.ou, item, false); | |
| 325 | 324 | } |
| 326 | 325 | } else if (cur.oh.isDictionary() || cur.oh.isStream()) { |
| 327 | 326 | QPDFObjectHandle dict = cur.oh; | ... | ... |
libqpdf/QPDF_pages.cc
| 1 | 1 | #include <qpdf/QPDF.hh> |
| 2 | 2 | |
| 3 | 3 | #include <qpdf/QPDFExc.hh> |
| 4 | +#include <qpdf/QPDFObjectHandle_private.hh> | |
| 4 | 5 | #include <qpdf/QTC.hh> |
| 5 | 6 | #include <qpdf/QUtil.hh> |
| 6 | 7 | |
| ... | ... | @@ -108,9 +109,9 @@ QPDF::getAllPagesInternal( |
| 108 | 109 | QTC::TC("qpdf", "QPDF inherit mediabox", media_box ? 0 : 1); |
| 109 | 110 | } |
| 110 | 111 | auto kids = cur_node.getKey("/Kids"); |
| 111 | - int n = kids.getArrayNItems(); | |
| 112 | - for (int i = 0; i < n; ++i) { | |
| 113 | - auto kid = kids.getArrayItem(i); | |
| 112 | + int i = -1; | |
| 113 | + for (auto& kid: kids.as_array()) { | |
| 114 | + ++i; | |
| 114 | 115 | if (!kid.isDictionary()) { |
| 115 | 116 | kid.warnIfPossible("Pages tree includes non-dictionary object; ignoring"); |
| 116 | 117 | m->invalid_page_found = true; |
| ... | ... | @@ -133,7 +134,6 @@ QPDF::getAllPagesInternal( |
| 133 | 134 | cur_node.warnIfPossible( |
| 134 | 135 | "kid " + std::to_string(i) + " (from 0) is direct; converting to indirect"); |
| 135 | 136 | kid = makeIndirectObject(kid); |
| 136 | - kids.setArrayItem(i, kid); | |
| 137 | 137 | } else if (!seen.add(kid)) { |
| 138 | 138 | // Make a copy of the page. This does the same as shallowCopyPage in |
| 139 | 139 | // QPDFPageObjectHelper. |
| ... | ... | @@ -144,7 +144,6 @@ QPDF::getAllPagesInternal( |
| 144 | 144 | " creating a new page object as a copy"); |
| 145 | 145 | kid = makeIndirectObject(QPDFObjectHandle(kid).shallowCopy()); |
| 146 | 146 | seen.add(kid); |
| 147 | - kids.setArrayItem(i, kid); | |
| 148 | 147 | } |
| 149 | 148 | if (!kid.isDictionaryOfType("/Page")) { |
| 150 | 149 | kid.warnIfPossible("/Type key should be /Page but is not; overriding"); | ... | ... |