diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 1a73085..08e877e 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -2346,9 +2346,8 @@ QPDF::reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top) if (foreign_tc == ::ot_array) { QTC::TC("qpdf", "QPDF reserve array"); - int n = foreign.getArrayNItems(); - for (int i = 0; i < n; ++i) { - reserveObjects(foreign.getArrayItem(i), obj_copier, false); + for (auto const& item: foreign.as_array()) { + reserveObjects(item, obj_copier, false); } } else if (foreign_tc == ::ot_dictionary) { QTC::TC("qpdf", "QPDF reserve dictionary"); @@ -2384,11 +2383,8 @@ QPDF::replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_cop } else if (foreign_tc == ::ot_array) { QTC::TC("qpdf", "QPDF replace array"); result = QPDFObjectHandle::newArray(); - int n = foreign.getArrayNItems(); - for (int i = 0; i < n; ++i) { - result.appendItem( - // line-break - replaceForeignIndirectObjects(foreign.getArrayItem(i), obj_copier, false)); + for (auto const& item: foreign.as_array()) { + result.appendItem(replaceForeignIndirectObjects(item, obj_copier, false)); } } else if (foreign_tc == ::ot_dictionary) { QTC::TC("qpdf", "QPDF replace dictionary"); @@ -2714,11 +2710,8 @@ QPDF::getCompressibleObjGens() queue.emplace_back(iter->second); } } - } else if (obj.isArray()) { - int n = obj.getArrayNItems(); - for (int i = 1; i <= n; ++i) { - queue.push_back(obj.getArrayItem(n - i)); - } + } else if (auto items = obj.as_array()) { + queue.insert(queue.end(), items.crbegin(), items.crend()); } } diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index da5db4c..2857870 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -7,6 +7,8 @@ #include #include +using namespace qpdf; + QPDFAcroFormDocumentHelper::Members::Members() : cache_valid(false) { @@ -239,26 +241,25 @@ QPDFAcroFormDocumentHelper::analyze() return; } m->cache_valid = true; - QPDFObjectHandle acroform = this->qpdf.getRoot().getKey("/AcroForm"); + QPDFObjectHandle acroform = qpdf.getRoot().getKey("/AcroForm"); if (!(acroform.isDictionary() && acroform.hasKey("/Fields"))) { return; } QPDFObjectHandle fields = acroform.getKey("/Fields"); - if (!fields.isArray()) { + if (auto fa = fields.as_array(strict)) { + // Traverse /AcroForm to find annotations and map them bidirectionally to fields. + + QPDFObjGen::set visited; + QPDFObjectHandle null(QPDFObjectHandle::newNull()); + for (auto const& field: fa) { + traverseField(field, null, 0, visited); + } + } else { QTC::TC("qpdf", "QPDFAcroFormDocumentHelper fields not array"); acroform.warnIfPossible("/Fields key of /AcroForm dictionary is not an array; ignoring"); fields = QPDFObjectHandle::newArray(); } - // Traverse /AcroForm to find annotations and map them bidirectionally to fields. - - QPDFObjGen::set visited; - int nfields = fields.getArrayNItems(); - QPDFObjectHandle null(QPDFObjectHandle::newNull()); - for (int i = 0; i < nfields; ++i) { - traverseField(fields.getArrayItem(i), null, 0, visited); - } - // All Widget annotations should have been encountered by traversing /AcroForm, but in case any // weren't, find them by walking through pages, and treat any widget annotation that is not // associated with a field as its own field. This just ensures that requesting the field for any @@ -325,12 +326,10 @@ QPDFAcroFormDocumentHelper::traverseField( bool is_annotation = false; bool is_field = (0 == depth); - QPDFObjectHandle kids = field.getKey("/Kids"); - if (kids.isArray()) { + if (auto a = field.getKey("/Kids").as_array(strict)) { is_field = true; - int nkids = kids.getArrayNItems(); - for (int k = 0; k < nkids; ++k) { - traverseField(kids.getArrayItem(k), field, 1 + depth, visited); + for (auto const& item: a) { + traverseField(item, field, 1 + depth, visited); } } else { if (field.hasKey("/Parent")) { diff --git a/libqpdf/QPDFFormFieldObjectHelper.cc b/libqpdf/QPDFFormFieldObjectHelper.cc index 1e62c24..b333202 100644 --- a/libqpdf/QPDFFormFieldObjectHelper.cc +++ b/libqpdf/QPDFFormFieldObjectHelper.cc @@ -272,14 +272,9 @@ QPDFFormFieldObjectHelper::getChoices() if (!isChoice()) { return result; } - QPDFObjectHandle opt = getInheritableFieldValue("/Opt"); - if (opt.isArray()) { - int n = opt.getArrayNItems(); - for (int i = 0; i < n; ++i) { - QPDFObjectHandle item = opt.getArrayItem(i); - if (item.isString()) { - result.push_back(item.getUTF8Value()); - } + for (auto const& item: getInheritableFieldValue("/Opt").as_array()) { + if (item.isString()) { + result.emplace_back(item.getUTF8Value()); } } return result; @@ -369,30 +364,21 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) QPDFObjectHandle kids = oh().getKey("/Kids"); if (!(isRadioButton() && parent.isNull() && kids.isArray())) { - oh().warnIfPossible( - "don't know how to set the value" - " of this field as a radio button"); + oh().warnIfPossible("don't know how to set the value of this field as a radio button"); return; } setFieldAttribute("/V", name); - int nkids = kids.getArrayNItems(); - for (int i = 0; i < nkids; ++i) { - QPDFObjectHandle kid = kids.getArrayItem(i); + for (auto const& kid: kids.as_array()) { QPDFObjectHandle AP = kid.getKey("/AP"); QPDFObjectHandle annot; - if (AP.isNull()) { + if (AP.null()) { // The widget may be below. If there is more than one, just find the first one. - QPDFObjectHandle grandkids = kid.getKey("/Kids"); - if (grandkids.isArray()) { - int ngrandkids = grandkids.getArrayNItems(); - for (int j = 0; j < ngrandkids; ++j) { - QPDFObjectHandle grandkid = grandkids.getArrayItem(j); - AP = grandkid.getKey("/AP"); - if (!AP.isNull()) { - QTC::TC("qpdf", "QPDFFormFieldObjectHelper radio button grandkid"); - annot = grandkid; - break; - } + for (auto const& grandkid: kid.getKey("/Kids").as_array()) { + AP = grandkid.getKey("/AP"); + if (!AP.null()) { + QTC::TC("qpdf", "QPDFFormFieldObjectHelper radio button grandkid"); + annot = grandkid; + break; } } } else { @@ -419,20 +405,16 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) { QPDFObjectHandle AP = oh().getKey("/AP"); QPDFObjectHandle annot; - if (AP.isNull()) { + if (AP.null()) { // The widget may be below. If there is more than one, just // find the first one. QPDFObjectHandle kids = oh().getKey("/Kids"); - if (kids.isArray()) { - int nkids = kids.getArrayNItems(); - for (int i = 0; i < nkids; ++i) { - QPDFObjectHandle kid = kids.getArrayItem(i); - AP = kid.getKey("/AP"); - if (!AP.isNull()) { - QTC::TC("qpdf", "QPDFFormFieldObjectHelper checkbox kid widget"); - annot = kid; - break; - } + for (auto const& kid: oh().getKey("/Kids").as_array(qpdf::strict)) { + AP = kid.getKey("/AP"); + if (!AP.null()) { + QTC::TC("qpdf", "QPDFFormFieldObjectHelper checkbox kid widget"); + annot = kid; + break; } } } else { diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 46053e1..ffe2509 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -365,7 +365,7 @@ QPDFObject::copy(bool shallow) case ::ot_reference: return qpdf->getObject(og).getObj(); } - return {}; // does not return + return {}; // unreachable } std::string @@ -446,7 +446,7 @@ QPDFObject::unparse() case ::ot_reference: return og.unparse(' ') + " R"; } - return {}; // does not return + return {}; // unreachable } void @@ -644,9 +644,8 @@ QPDFObject::getStringValue() const return std::get(value).obj->getStringValue(); default: throw std::logic_error("Internal error in QPDFObject::getStringValue"); - return ""; // does not return } - return {}; // does not return + return ""; // unreachable } bool @@ -1927,12 +1926,10 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) if (isBool() || isInteger() || isName() || isNull() || isReal() || isString()) { this->obj = obj->copy(true); - } else if (isArray()) { + } else if (auto a = as_array(strict)) { std::vector items; - auto array = as_array(strict); - int n = array.size(); - for (int i = 0; i < n; ++i) { - items.emplace_back(array.at(i).second); + for (auto const& item: a) { + items.emplace_back(item); items.back().makeDirect(visited, stop_at_streams); } this->obj = QPDFObject::create(items); diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 401300f..c9b90cc 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -1129,7 +1129,7 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) return; } else if (!m->linearized) { if (object.isArray()) { - for (auto& item: object.getArrayAsVector()) { + for (auto& item: object.as_array()) { enqueueObject(item); } } else if (auto d = object.as_dictionary()) { @@ -1350,7 +1350,7 @@ QPDFWriter::unparseObject( // [ 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()) { + for (auto const& item: object.as_array()) { writeString(indent); writeStringQDF(" "); unparseChild(item, level + 1, child_flags); @@ -1892,12 +1892,10 @@ QPDFWriter::generateID() } seed += " QPDF "; if (trailer.hasKey("/Info")) { - QPDFObjectHandle info = trailer.getKey("/Info"); - for (auto const& key: info.getKeys()) { - QPDFObjectHandle obj = info.getKey(key); - if (obj.isString()) { + for (auto const& item: trailer.getKey("/Info").as_dictionary()) { + if (item.second.isString()) { seed += " "; - seed += obj.getStringValue(); + seed += item.second.getStringValue(); } } } @@ -1923,8 +1921,7 @@ QPDFWriter::generateID() void QPDFWriter::initializeSpecialStreams() { - // Mark all page content streams in case we are filtering or - // normalizing. + // Mark all page content streams in case we are filtering or normalizing. std::vector pages = m->pdf.getAllPages(); int num = 0; for (auto& page: pages) { diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc index 0c757f0..d19c2c6 100644 --- a/libqpdf/QPDF_optimization.cc +++ b/libqpdf/QPDF_optimization.cc @@ -319,9 +319,8 @@ QPDF::updateObjectMaps( } if (cur.oh.isArray()) { - int n = cur.oh.getArrayNItems(); - for (int i = 0; i < n; ++i) { - pending.emplace_back(cur.ou, cur.oh.getArrayItem(i), false); + for (auto const& item: cur.oh.as_array()) { + pending.emplace_back(cur.ou, item, false); } } else if (cur.oh.isDictionary() || cur.oh.isStream()) { QPDFObjectHandle dict = cur.oh; diff --git a/libqpdf/QPDF_pages.cc b/libqpdf/QPDF_pages.cc index aa90f7f..ece5c32 100644 --- a/libqpdf/QPDF_pages.cc +++ b/libqpdf/QPDF_pages.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -108,9 +109,9 @@ QPDF::getAllPagesInternal( QTC::TC("qpdf", "QPDF inherit mediabox", media_box ? 0 : 1); } auto kids = cur_node.getKey("/Kids"); - int n = kids.getArrayNItems(); - for (int i = 0; i < n; ++i) { - auto kid = kids.getArrayItem(i); + int i = -1; + for (auto& kid: kids.as_array()) { + ++i; if (!kid.isDictionary()) { kid.warnIfPossible("Pages tree includes non-dictionary object; ignoring"); m->invalid_page_found = true; @@ -133,7 +134,6 @@ QPDF::getAllPagesInternal( cur_node.warnIfPossible( "kid " + std::to_string(i) + " (from 0) is direct; converting to indirect"); kid = makeIndirectObject(kid); - kids.setArrayItem(i, kid); } else if (!seen.add(kid)) { // Make a copy of the page. This does the same as shallowCopyPage in // QPDFPageObjectHelper. @@ -144,7 +144,6 @@ QPDF::getAllPagesInternal( " creating a new page object as a copy"); kid = makeIndirectObject(QPDFObjectHandle(kid).shallowCopy()); seen.add(kid); - kids.setArrayItem(i, kid); } if (!kid.isDictionaryOfType("/Page")) { kid.warnIfPossible("/Type key should be /Page but is not; overriding");