Commit 266d4797350044994ad1578eebdd104774bd38cf
Committed by
m-holger
1 parent
0afaaea2
Refactor QPDF_Array::at
Change the return type to a std::pair<bool, QPDFObjectHandle> in order to allow a default constructed object handle (which is currently returned to indicate failure) to become a valid object.
Showing
4 changed files
with
55 additions
and
54 deletions
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -1021,8 +1021,9 @@ QPDFObjectHandle::getArrayItem(int n) const |
| 1021 | 1021 | #endif |
| 1022 | 1022 | { |
| 1023 | 1023 | if (auto array = asArray()) { |
| 1024 | - if (auto result = array->at(n); result.obj != nullptr) { | |
| 1025 | - return result; | |
| 1024 | + auto result = array->at(n); | |
| 1025 | + if (result.first) { | |
| 1026 | + return result.second; | |
| 1026 | 1027 | } else { |
| 1027 | 1028 | objectWarning("returning null for out of bounds array access"); |
| 1028 | 1029 | QTC::TC("qpdf", "QPDFObjectHandle array bounds"); |
| ... | ... | @@ -1045,7 +1046,7 @@ QPDFObjectHandle::isRectangle() const |
| 1045 | 1046 | { |
| 1046 | 1047 | if (auto array = asArray()) { |
| 1047 | 1048 | for (int i = 0; i < 4; ++i) { |
| 1048 | - if (auto item = array->at(i); !(item.obj && item.isNumber())) { | |
| 1049 | + if (auto item = array->at(i).second; !item.isNumber()) { | |
| 1049 | 1050 | return false; |
| 1050 | 1051 | } |
| 1051 | 1052 | } |
| ... | ... | @@ -1064,7 +1065,7 @@ QPDFObjectHandle::isMatrix() const |
| 1064 | 1065 | { |
| 1065 | 1066 | if (auto array = asArray()) { |
| 1066 | 1067 | for (int i = 0; i < 6; ++i) { |
| 1067 | - if (auto item = array->at(i); !(item.obj && item.isNumber())) { | |
| 1068 | + if (auto item = array->at(i).second; !item.isNumber()) { | |
| 1068 | 1069 | return false; |
| 1069 | 1070 | } |
| 1070 | 1071 | } |
| ... | ... | @@ -1087,7 +1088,7 @@ QPDFObjectHandle::getArrayAsRectangle() const |
| 1087 | 1088 | } |
| 1088 | 1089 | double items[4]; |
| 1089 | 1090 | for (int i = 0; i < 4; ++i) { |
| 1090 | - if (!array->at(i).getValueAsNumber(items[i])) { | |
| 1091 | + if (auto item = array->at(i).second; !item.getValueAsNumber(items[i])) { | |
| 1091 | 1092 | return {}; |
| 1092 | 1093 | } |
| 1093 | 1094 | } |
| ... | ... | @@ -1114,7 +1115,7 @@ QPDFObjectHandle::getArrayAsMatrix() const |
| 1114 | 1115 | } |
| 1115 | 1116 | double items[6]; |
| 1116 | 1117 | for (int i = 0; i < 6; ++i) { |
| 1117 | - if (!array->at(i).getValueAsNumber(items[i])) { | |
| 1118 | + if (auto item = array->at(i).second; !item.getValueAsNumber(items[i])) { | |
| 1118 | 1119 | return {}; |
| 1119 | 1120 | } |
| 1120 | 1121 | } |
| ... | ... | @@ -1224,7 +1225,7 @@ QPDFObjectHandle |
| 1224 | 1225 | QPDFObjectHandle::eraseItemAndGetOld(int at) |
| 1225 | 1226 | { |
| 1226 | 1227 | auto array = asArray(); |
| 1227 | - auto result = (array && at < array->size() && at >= 0) ? array->at(at) : newNull(); | |
| 1228 | + auto result = (array && at < array->size() && at >= 0) ? array->at(at).second : newNull(); | |
| 1228 | 1229 | eraseItem(at); |
| 1229 | 1230 | return result; |
| 1230 | 1231 | } |
| ... | ... | @@ -1764,7 +1765,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( |
| 1764 | 1765 | if (auto array = asArray()) { |
| 1765 | 1766 | int n_items = array->size(); |
| 1766 | 1767 | for (int i = 0; i < n_items; ++i) { |
| 1767 | - QPDFObjectHandle item = array->at(i); | |
| 1768 | + QPDFObjectHandle item = array->at(i).second; | |
| 1768 | 1769 | if (item.isStream()) { |
| 1769 | 1770 | result.push_back(item); |
| 1770 | 1771 | } else { |
| ... | ... | @@ -2465,7 +2466,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) |
| 2465 | 2466 | auto array = asArray(); |
| 2466 | 2467 | int n = array->size(); |
| 2467 | 2468 | for (int i = 0; i < n; ++i) { |
| 2468 | - items.push_back(array->at(i)); | |
| 2469 | + items.push_back(array->at(i).second); | |
| 2469 | 2470 | items.back().makeDirect(visited, stop_at_streams); |
| 2470 | 2471 | } |
| 2471 | 2472 | this->obj = QPDF_Array::create(items); | ... | ... |
libqpdf/QPDF_Array.cc
| ... | ... | @@ -184,16 +184,16 @@ QPDF_Array::writeJSON(int json_version, JSON::Writer& p) |
| 184 | 184 | p.writeEnd(']'); |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | -QPDFObjectHandle | |
| 187 | +std::pair<bool, QPDFObjectHandle> | |
| 188 | 188 | QPDF_Array::at(int n) const noexcept |
| 189 | 189 | { |
| 190 | 190 | if (n < 0 || n >= size()) { |
| 191 | - return {}; | |
| 191 | + return {false, {}}; | |
| 192 | 192 | } else if (sp) { |
| 193 | 193 | auto const& iter = sp->elements.find(n); |
| 194 | - return iter == sp->elements.end() ? null_oh : (*iter).second; | |
| 194 | + return {true, iter == sp->elements.end() ? null_oh : (*iter).second}; | |
| 195 | 195 | } else { |
| 196 | - return elements[size_t(n)]; | |
| 196 | + return {true, elements[size_t(n)]}; | |
| 197 | 197 | } |
| 198 | 198 | } |
| 199 | 199 | ... | ... |
libqpdf/qpdf/QPDF_Array.hh
| ... | ... | @@ -30,7 +30,7 @@ class QPDF_Array: public QPDFValue |
| 30 | 30 | { |
| 31 | 31 | return sp ? sp->size : int(elements.size()); |
| 32 | 32 | } |
| 33 | - QPDFObjectHandle at(int n) const noexcept; | |
| 33 | + std::pair<bool, QPDFObjectHandle> at(int n) const noexcept; | |
| 34 | 34 | bool setAt(int n, QPDFObjectHandle const& oh); |
| 35 | 35 | std::vector<QPDFObjectHandle> getAsVector() const; |
| 36 | 36 | void setFromVector(std::vector<QPDFObjectHandle> const& items); | ... | ... |
libtests/sparse_array.cc
| ... | ... | @@ -21,69 +21,69 @@ main() |
| 21 | 21 | a.push_back(QPDFObjectHandle::parse("null")); |
| 22 | 22 | a.push_back(QPDFObjectHandle::parse("/Quack")); |
| 23 | 23 | assert(a.size() == 5); |
| 24 | - assert(a.at(0).isInteger() && (a.at(0).getIntValue() == 1)); | |
| 25 | - assert(a.at(1).isString() && (a.at(1).getStringValue() == "potato")); | |
| 26 | - assert(a.at(2).isNull()); | |
| 27 | - assert(a.at(3).isNull()); | |
| 28 | - assert(a.at(4).isName() && (a.at(4).getName() == "/Quack")); | |
| 24 | + assert(a.at(0).second.isInteger() && (a.at(0).second.getIntValue() == 1)); | |
| 25 | + assert(a.at(1).second.isString() && (a.at(1).second.getStringValue() == "potato")); | |
| 26 | + assert(a.at(2).second.isNull()); | |
| 27 | + assert(a.at(3).second.isNull()); | |
| 28 | + assert(a.at(4).second.isName() && (a.at(4).second.getName() == "/Quack")); | |
| 29 | 29 | |
| 30 | 30 | a.insert(4, QPDFObjectHandle::parse("/BeforeQuack")); |
| 31 | 31 | assert(a.size() == 6); |
| 32 | - assert(a.at(0).isInteger() && (a.at(0).getIntValue() == 1)); | |
| 33 | - assert(a.at(4).isName() && (a.at(4).getName() == "/BeforeQuack")); | |
| 34 | - assert(a.at(5).isName() && (a.at(5).getName() == "/Quack")); | |
| 32 | + assert(a.at(0).second.isInteger() && (a.at(0).second.getIntValue() == 1)); | |
| 33 | + assert(a.at(4).second.isName() && (a.at(4).second.getName() == "/BeforeQuack")); | |
| 34 | + assert(a.at(5).second.isName() && (a.at(5).second.getName() == "/Quack")); | |
| 35 | 35 | |
| 36 | 36 | a.insert(2, QPDFObjectHandle::parse("/Third")); |
| 37 | 37 | assert(a.size() == 7); |
| 38 | - assert(a.at(1).isString() && (a.at(1).getStringValue() == "potato")); | |
| 39 | - assert(a.at(2).isName() && (a.at(2).getName() == "/Third")); | |
| 40 | - assert(a.at(3).isNull()); | |
| 41 | - assert(a.at(6).isName() && (a.at(6).getName() == "/Quack")); | |
| 38 | + assert(a.at(1).second.isString() && (a.at(1).second.getStringValue() == "potato")); | |
| 39 | + assert(a.at(2).second.isName() && (a.at(2).second.getName() == "/Third")); | |
| 40 | + assert(a.at(3).second.isNull()); | |
| 41 | + assert(a.at(6).second.isName() && (a.at(6).second.getName() == "/Quack")); | |
| 42 | 42 | |
| 43 | 43 | a.insert(0, QPDFObjectHandle::parse("/First")); |
| 44 | 44 | assert(a.size() == 8); |
| 45 | - assert(a.at(0).isName() && (a.at(0).getName() == "/First")); | |
| 46 | - assert(a.at(1).isInteger() && (a.at(1).getIntValue() == 1)); | |
| 47 | - assert(a.at(7).isName() && (a.at(7).getName() == "/Quack")); | |
| 45 | + assert(a.at(0).second.isName() && (a.at(0).second.getName() == "/First")); | |
| 46 | + assert(a.at(1).second.isInteger() && (a.at(1).second.getIntValue() == 1)); | |
| 47 | + assert(a.at(7).second.isName() && (a.at(7).second.getName() == "/Quack")); | |
| 48 | 48 | |
| 49 | 49 | a.erase(6); |
| 50 | 50 | assert(a.size() == 7); |
| 51 | - assert(a.at(0).isName() && (a.at(0).getName() == "/First")); | |
| 52 | - assert(a.at(1).isInteger() && (a.at(1).getIntValue() == 1)); | |
| 53 | - assert(a.at(5).isNull()); | |
| 54 | - assert(a.at(6).isName() && (a.at(6).getName() == "/Quack")); | |
| 51 | + assert(a.at(0).second.isName() && (a.at(0).second.getName() == "/First")); | |
| 52 | + assert(a.at(1).second.isInteger() && (a.at(1).second.getIntValue() == 1)); | |
| 53 | + assert(a.at(5).second.isNull()); | |
| 54 | + assert(a.at(6).second.isName() && (a.at(6).second.getName() == "/Quack")); | |
| 55 | 55 | |
| 56 | 56 | a.erase(6); |
| 57 | 57 | assert(a.size() == 6); |
| 58 | - assert(a.at(0).isName() && (a.at(0).getName() == "/First")); | |
| 59 | - assert(a.at(1).isInteger() && (a.at(1).getIntValue() == 1)); | |
| 60 | - assert(a.at(3).isName() && (a.at(3).getName() == "/Third")); | |
| 61 | - assert(a.at(4).isNull()); | |
| 62 | - assert(a.at(5).isNull()); | |
| 58 | + assert(a.at(0).second.isName() && (a.at(0).second.getName() == "/First")); | |
| 59 | + assert(a.at(1).second.isInteger() && (a.at(1).second.getIntValue() == 1)); | |
| 60 | + assert(a.at(3).second.isName() && (a.at(3).second.getName() == "/Third")); | |
| 61 | + assert(a.at(4).second.isNull()); | |
| 62 | + assert(a.at(5).second.isNull()); | |
| 63 | 63 | |
| 64 | 64 | a.setAt(4, QPDFObjectHandle::parse("12")); |
| 65 | - assert(a.at(4).isInteger() && (a.at(4).getIntValue() == 12)); | |
| 65 | + assert(a.at(4).second.isInteger() && (a.at(4).second.getIntValue() == 12)); | |
| 66 | 66 | a.setAt(4, QPDFObjectHandle::newNull()); |
| 67 | - assert(a.at(4).isNull()); | |
| 67 | + assert(a.at(4).second.isNull()); | |
| 68 | 68 | |
| 69 | 69 | a.erase(a.size() - 1); |
| 70 | 70 | assert(a.size() == 5); |
| 71 | - assert(a.at(0).isName() && (a.at(0).getName() == "/First")); | |
| 72 | - assert(a.at(1).isInteger() && (a.at(1).getIntValue() == 1)); | |
| 73 | - assert(a.at(3).isName() && (a.at(3).getName() == "/Third")); | |
| 74 | - assert(a.at(4).isNull()); | |
| 71 | + assert(a.at(0).second.isName() && (a.at(0).second.getName() == "/First")); | |
| 72 | + assert(a.at(1).second.isInteger() && (a.at(1).second.getIntValue() == 1)); | |
| 73 | + assert(a.at(3).second.isName() && (a.at(3).second.getName() == "/Third")); | |
| 74 | + assert(a.at(4).second.isNull()); | |
| 75 | 75 | |
| 76 | 76 | a.erase(a.size() - 1); |
| 77 | 77 | assert(a.size() == 4); |
| 78 | - assert(a.at(0).isName() && (a.at(0).getName() == "/First")); | |
| 79 | - assert(a.at(1).isInteger() && (a.at(1).getIntValue() == 1)); | |
| 80 | - assert(a.at(3).isName() && (a.at(3).getName() == "/Third")); | |
| 78 | + assert(a.at(0).second.isName() && (a.at(0).second.getName() == "/First")); | |
| 79 | + assert(a.at(1).second.isInteger() && (a.at(1).second.getIntValue() == 1)); | |
| 80 | + assert(a.at(3).second.isName() && (a.at(3).second.getName() == "/Third")); | |
| 81 | 81 | |
| 82 | 82 | a.erase(a.size() - 1); |
| 83 | 83 | assert(a.size() == 3); |
| 84 | - assert(a.at(0).isName() && (a.at(0).getName() == "/First")); | |
| 85 | - assert(a.at(1).isInteger() && (a.at(1).getIntValue() == 1)); | |
| 86 | - assert(a.at(2).isString() && (a.at(2).getStringValue() == "potato")); | |
| 84 | + assert(a.at(0).second.isName() && (a.at(0).second.getName() == "/First")); | |
| 85 | + assert(a.at(1).second.isInteger() && (a.at(1).second.getIntValue() == 1)); | |
| 86 | + assert(a.at(2).second.isString() && (a.at(2).second.getStringValue() == "potato")); | |
| 87 | 87 | |
| 88 | 88 | QPDF pdf; |
| 89 | 89 | pdf.emptyPDF(); |
| ... | ... | @@ -92,13 +92,13 @@ main() |
| 92 | 92 | QPDF_Array& b = *obj->as<QPDF_Array>(); |
| 93 | 93 | b.setAt(5, pdf.newIndirectNull()); |
| 94 | 94 | b.setAt(7, "[0 1 2 3]"_qpdf); |
| 95 | - assert(b.at(3).isNull()); | |
| 96 | - assert(b.at(8).isNull()); | |
| 97 | - assert(b.at(5).isIndirect()); | |
| 95 | + assert(b.at(3).second.isNull()); | |
| 96 | + assert(b.at(8).second.isNull()); | |
| 97 | + assert(b.at(5).second.isIndirect()); | |
| 98 | 98 | assert(b.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); |
| 99 | 99 | auto c = b.copy(true); |
| 100 | 100 | auto d = b.copy(false); |
| 101 | - b.at(7).setArrayItem(2, "42"_qpdf); | |
| 101 | + b.at(7).second.setArrayItem(2, "42"_qpdf); | |
| 102 | 102 | assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); |
| 103 | 103 | assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); |
| 104 | 104 | ... | ... |