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,8 +1021,9 @@ QPDFObjectHandle::getArrayItem(int n) const | ||
| 1021 | #endif | 1021 | #endif |
| 1022 | { | 1022 | { |
| 1023 | if (auto array = asArray()) { | 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 | } else { | 1027 | } else { |
| 1027 | objectWarning("returning null for out of bounds array access"); | 1028 | objectWarning("returning null for out of bounds array access"); |
| 1028 | QTC::TC("qpdf", "QPDFObjectHandle array bounds"); | 1029 | QTC::TC("qpdf", "QPDFObjectHandle array bounds"); |
| @@ -1045,7 +1046,7 @@ QPDFObjectHandle::isRectangle() const | @@ -1045,7 +1046,7 @@ QPDFObjectHandle::isRectangle() const | ||
| 1045 | { | 1046 | { |
| 1046 | if (auto array = asArray()) { | 1047 | if (auto array = asArray()) { |
| 1047 | for (int i = 0; i < 4; ++i) { | 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 | return false; | 1050 | return false; |
| 1050 | } | 1051 | } |
| 1051 | } | 1052 | } |
| @@ -1064,7 +1065,7 @@ QPDFObjectHandle::isMatrix() const | @@ -1064,7 +1065,7 @@ QPDFObjectHandle::isMatrix() const | ||
| 1064 | { | 1065 | { |
| 1065 | if (auto array = asArray()) { | 1066 | if (auto array = asArray()) { |
| 1066 | for (int i = 0; i < 6; ++i) { | 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 | return false; | 1069 | return false; |
| 1069 | } | 1070 | } |
| 1070 | } | 1071 | } |
| @@ -1087,7 +1088,7 @@ QPDFObjectHandle::getArrayAsRectangle() const | @@ -1087,7 +1088,7 @@ QPDFObjectHandle::getArrayAsRectangle() const | ||
| 1087 | } | 1088 | } |
| 1088 | double items[4]; | 1089 | double items[4]; |
| 1089 | for (int i = 0; i < 4; ++i) { | 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 | return {}; | 1092 | return {}; |
| 1092 | } | 1093 | } |
| 1093 | } | 1094 | } |
| @@ -1114,7 +1115,7 @@ QPDFObjectHandle::getArrayAsMatrix() const | @@ -1114,7 +1115,7 @@ QPDFObjectHandle::getArrayAsMatrix() const | ||
| 1114 | } | 1115 | } |
| 1115 | double items[6]; | 1116 | double items[6]; |
| 1116 | for (int i = 0; i < 6; ++i) { | 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 | return {}; | 1119 | return {}; |
| 1119 | } | 1120 | } |
| 1120 | } | 1121 | } |
| @@ -1224,7 +1225,7 @@ QPDFObjectHandle | @@ -1224,7 +1225,7 @@ QPDFObjectHandle | ||
| 1224 | QPDFObjectHandle::eraseItemAndGetOld(int at) | 1225 | QPDFObjectHandle::eraseItemAndGetOld(int at) |
| 1225 | { | 1226 | { |
| 1226 | auto array = asArray(); | 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 | eraseItem(at); | 1229 | eraseItem(at); |
| 1229 | return result; | 1230 | return result; |
| 1230 | } | 1231 | } |
| @@ -1764,7 +1765,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | @@ -1764,7 +1765,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray( | ||
| 1764 | if (auto array = asArray()) { | 1765 | if (auto array = asArray()) { |
| 1765 | int n_items = array->size(); | 1766 | int n_items = array->size(); |
| 1766 | for (int i = 0; i < n_items; ++i) { | 1767 | for (int i = 0; i < n_items; ++i) { |
| 1767 | - QPDFObjectHandle item = array->at(i); | 1768 | + QPDFObjectHandle item = array->at(i).second; |
| 1768 | if (item.isStream()) { | 1769 | if (item.isStream()) { |
| 1769 | result.push_back(item); | 1770 | result.push_back(item); |
| 1770 | } else { | 1771 | } else { |
| @@ -2465,7 +2466,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | @@ -2465,7 +2466,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | ||
| 2465 | auto array = asArray(); | 2466 | auto array = asArray(); |
| 2466 | int n = array->size(); | 2467 | int n = array->size(); |
| 2467 | for (int i = 0; i < n; ++i) { | 2468 | for (int i = 0; i < n; ++i) { |
| 2468 | - items.push_back(array->at(i)); | 2469 | + items.push_back(array->at(i).second); |
| 2469 | items.back().makeDirect(visited, stop_at_streams); | 2470 | items.back().makeDirect(visited, stop_at_streams); |
| 2470 | } | 2471 | } |
| 2471 | this->obj = QPDF_Array::create(items); | 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,16 +184,16 @@ QPDF_Array::writeJSON(int json_version, JSON::Writer& p) | ||
| 184 | p.writeEnd(']'); | 184 | p.writeEnd(']'); |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | -QPDFObjectHandle | 187 | +std::pair<bool, QPDFObjectHandle> |
| 188 | QPDF_Array::at(int n) const noexcept | 188 | QPDF_Array::at(int n) const noexcept |
| 189 | { | 189 | { |
| 190 | if (n < 0 || n >= size()) { | 190 | if (n < 0 || n >= size()) { |
| 191 | - return {}; | 191 | + return {false, {}}; |
| 192 | } else if (sp) { | 192 | } else if (sp) { |
| 193 | auto const& iter = sp->elements.find(n); | 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 | } else { | 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,7 +30,7 @@ class QPDF_Array: public QPDFValue | ||
| 30 | { | 30 | { |
| 31 | return sp ? sp->size : int(elements.size()); | 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 | bool setAt(int n, QPDFObjectHandle const& oh); | 34 | bool setAt(int n, QPDFObjectHandle const& oh); |
| 35 | std::vector<QPDFObjectHandle> getAsVector() const; | 35 | std::vector<QPDFObjectHandle> getAsVector() const; |
| 36 | void setFromVector(std::vector<QPDFObjectHandle> const& items); | 36 | void setFromVector(std::vector<QPDFObjectHandle> const& items); |
libtests/sparse_array.cc
| @@ -21,69 +21,69 @@ main() | @@ -21,69 +21,69 @@ main() | ||
| 21 | a.push_back(QPDFObjectHandle::parse("null")); | 21 | a.push_back(QPDFObjectHandle::parse("null")); |
| 22 | a.push_back(QPDFObjectHandle::parse("/Quack")); | 22 | a.push_back(QPDFObjectHandle::parse("/Quack")); |
| 23 | assert(a.size() == 5); | 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 | a.insert(4, QPDFObjectHandle::parse("/BeforeQuack")); | 30 | a.insert(4, QPDFObjectHandle::parse("/BeforeQuack")); |
| 31 | assert(a.size() == 6); | 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 | a.insert(2, QPDFObjectHandle::parse("/Third")); | 36 | a.insert(2, QPDFObjectHandle::parse("/Third")); |
| 37 | assert(a.size() == 7); | 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 | a.insert(0, QPDFObjectHandle::parse("/First")); | 43 | a.insert(0, QPDFObjectHandle::parse("/First")); |
| 44 | assert(a.size() == 8); | 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 | a.erase(6); | 49 | a.erase(6); |
| 50 | assert(a.size() == 7); | 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 | a.erase(6); | 56 | a.erase(6); |
| 57 | assert(a.size() == 6); | 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 | a.setAt(4, QPDFObjectHandle::parse("12")); | 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 | a.setAt(4, QPDFObjectHandle::newNull()); | 66 | a.setAt(4, QPDFObjectHandle::newNull()); |
| 67 | - assert(a.at(4).isNull()); | 67 | + assert(a.at(4).second.isNull()); |
| 68 | 68 | ||
| 69 | a.erase(a.size() - 1); | 69 | a.erase(a.size() - 1); |
| 70 | assert(a.size() == 5); | 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 | a.erase(a.size() - 1); | 76 | a.erase(a.size() - 1); |
| 77 | assert(a.size() == 4); | 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 | a.erase(a.size() - 1); | 82 | a.erase(a.size() - 1); |
| 83 | assert(a.size() == 3); | 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 | QPDF pdf; | 88 | QPDF pdf; |
| 89 | pdf.emptyPDF(); | 89 | pdf.emptyPDF(); |
| @@ -92,13 +92,13 @@ main() | @@ -92,13 +92,13 @@ main() | ||
| 92 | QPDF_Array& b = *obj->as<QPDF_Array>(); | 92 | QPDF_Array& b = *obj->as<QPDF_Array>(); |
| 93 | b.setAt(5, pdf.newIndirectNull()); | 93 | b.setAt(5, pdf.newIndirectNull()); |
| 94 | b.setAt(7, "[0 1 2 3]"_qpdf); | 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 | assert(b.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); | 98 | assert(b.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); |
| 99 | auto c = b.copy(true); | 99 | auto c = b.copy(true); |
| 100 | auto d = b.copy(false); | 100 | auto d = b.copy(false); |
| 101 | - b.at(7).setArrayItem(2, "42"_qpdf); | 101 | + b.at(7).second.setArrayItem(2, "42"_qpdf); |
| 102 | assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); | 102 | assert(c->unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); |
| 103 | assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); | 103 | assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); |
| 104 | 104 |