Commit f40a96bdeb5d34c1bb7894445df8d981b7399dbd
1 parent
e063f323
Fix two BaseHandle bugs
- Add missing export for operator QPDFObjGen. - Fix handling of indirect references. The use of the type_code method in various switch statements bypassed the special handling of ::ot_reference objects. Replace with new method resolved_type_code. Add tests for ::ot_reference objects.
Showing
4 changed files
with
41 additions
and
5 deletions
include/qpdf/ObjectHandle.hh
| @@ -52,6 +52,7 @@ namespace qpdf | @@ -52,6 +52,7 @@ namespace qpdf | ||
| 52 | public: | 52 | public: |
| 53 | explicit inline operator bool() const; | 53 | explicit inline operator bool() const; |
| 54 | inline operator QPDFObjectHandle() const; | 54 | inline operator QPDFObjectHandle() const; |
| 55 | + QPDF_DLL | ||
| 55 | operator QPDFObjGen() const; | 56 | operator QPDFObjGen() const; |
| 56 | 57 | ||
| 57 | // The rest of the header file is for qpdf internal use only. | 58 | // The rest of the header file is for qpdf internal use only. |
| @@ -65,6 +66,7 @@ namespace qpdf | @@ -65,6 +66,7 @@ namespace qpdf | ||
| 65 | inline bool null() const; | 66 | inline bool null() const; |
| 66 | inline QPDF* qpdf() const; | 67 | inline QPDF* qpdf() const; |
| 67 | inline qpdf_object_type_e raw_type_code() const; | 68 | inline qpdf_object_type_e raw_type_code() const; |
| 69 | + inline qpdf_object_type_e resolved_type_code() const; | ||
| 68 | inline qpdf_object_type_e type_code() const; | 70 | inline qpdf_object_type_e type_code() const; |
| 69 | std::string unparse() const; | 71 | std::string unparse() const; |
| 70 | void write_json(int json_version, JSON::Writer& p) const; | 72 | void write_json(int json_version, JSON::Writer& p) const; |
libqpdf/QPDFObjectHandle.cc
| @@ -291,7 +291,7 @@ Name::normalize(std::string const& name) | @@ -291,7 +291,7 @@ Name::normalize(std::string const& name) | ||
| 291 | std::shared_ptr<QPDFObject> | 291 | std::shared_ptr<QPDFObject> |
| 292 | BaseHandle::copy(bool shallow) const | 292 | BaseHandle::copy(bool shallow) const |
| 293 | { | 293 | { |
| 294 | - switch (type_code()) { | 294 | + switch (resolved_type_code()) { |
| 295 | case ::ot_uninitialized: | 295 | case ::ot_uninitialized: |
| 296 | throw std::logic_error("QPDFObjectHandle: attempting to copy an uninitialized object"); | 296 | throw std::logic_error("QPDFObjectHandle: attempting to copy an uninitialized object"); |
| 297 | return {}; // does not return | 297 | return {}; // does not return |
| @@ -371,7 +371,7 @@ BaseHandle::copy(bool shallow) const | @@ -371,7 +371,7 @@ BaseHandle::copy(bool shallow) const | ||
| 371 | std::string | 371 | std::string |
| 372 | BaseHandle::unparse() const | 372 | BaseHandle::unparse() const |
| 373 | { | 373 | { |
| 374 | - switch (type_code()) { | 374 | + switch (resolved_type_code()) { |
| 375 | case ::ot_uninitialized: | 375 | case ::ot_uninitialized: |
| 376 | throw std::logic_error("QPDFObjectHandle: attempting to unparse an uninitialized object"); | 376 | throw std::logic_error("QPDFObjectHandle: attempting to unparse an uninitialized object"); |
| 377 | return ""; // does not return | 377 | return ""; // does not return |
| @@ -448,7 +448,7 @@ BaseHandle::unparse() const | @@ -448,7 +448,7 @@ BaseHandle::unparse() const | ||
| 448 | void | 448 | void |
| 449 | BaseHandle::write_json(int json_version, JSON::Writer& p) const | 449 | BaseHandle::write_json(int json_version, JSON::Writer& p) const |
| 450 | { | 450 | { |
| 451 | - switch (type_code()) { | 451 | + switch (resolved_type_code()) { |
| 452 | case ::ot_uninitialized: | 452 | case ::ot_uninitialized: |
| 453 | throw std::logic_error( | 453 | throw std::logic_error( |
| 454 | "QPDFObjectHandle: attempting to get JSON from a uninitialized object"); | 454 | "QPDFObjectHandle: attempting to get JSON from a uninitialized object"); |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| @@ -374,6 +374,18 @@ namespace qpdf | @@ -374,6 +374,18 @@ namespace qpdf | ||
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | inline qpdf_object_type_e | 376 | inline qpdf_object_type_e |
| 377 | + BaseHandle::resolved_type_code() const | ||
| 378 | + { | ||
| 379 | + if (!obj) { | ||
| 380 | + return ::ot_uninitialized; | ||
| 381 | + } | ||
| 382 | + if (raw_type_code() == ::ot_unresolved) { | ||
| 383 | + return QPDF::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode(); | ||
| 384 | + } | ||
| 385 | + return raw_type_code(); | ||
| 386 | + } | ||
| 387 | + | ||
| 388 | + inline qpdf_object_type_e | ||
| 377 | BaseHandle::type_code() const | 389 | BaseHandle::type_code() const |
| 378 | { | 390 | { |
| 379 | if (!obj) { | 391 | if (!obj) { |
qpdf/test_driver.cc
| @@ -1403,8 +1403,7 @@ test_41(QPDF& pdf, char const* arg2) | @@ -1403,8 +1403,7 @@ test_41(QPDF& pdf, char const* arg2) | ||
| 1403 | static void | 1403 | static void |
| 1404 | test_42(QPDF& pdf, char const* arg2) | 1404 | test_42(QPDF& pdf, char const* arg2) |
| 1405 | { | 1405 | { |
| 1406 | - // Access objects as wrong type. This test case is crafted to | ||
| 1407 | - // work with object-types.pdf. | 1406 | + // Access objects as wrong type. This test case is crafted to work with object-types.pdf. |
| 1408 | QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); | 1407 | QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); |
| 1409 | QPDFObjectHandle array = qtest.getKey("/Dictionary").getKey("/Key2"); | 1408 | QPDFObjectHandle array = qtest.getKey("/Dictionary").getKey("/Key2"); |
| 1410 | QPDFObjectHandle dictionary = qtest.getKey("/Dictionary"); | 1409 | QPDFObjectHandle dictionary = qtest.getKey("/Dictionary"); |
| @@ -1537,12 +1536,35 @@ test_42(QPDF& pdf, char const* arg2) | @@ -1537,12 +1536,35 @@ test_42(QPDF& pdf, char const* arg2) | ||
| 1537 | assert(!"42"_qpdf.isMatrix()); | 1536 | assert(!"42"_qpdf.isMatrix()); |
| 1538 | m1 = "42"_qpdf.getArrayAsMatrix(); | 1537 | m1 = "42"_qpdf.getArrayAsMatrix(); |
| 1539 | assert(m1.a == 0 && m1.b == 0 && m1.c == 0 && m1.d == 0 && m1.e == 0 && m1.f == 0); | 1538 | assert(m1.a == 0 && m1.b == 0 && m1.c == 0 && m1.d == 0 && m1.e == 0 && m1.f == 0); |
| 1539 | + | ||
| 1540 | // Uninitialized | 1540 | // Uninitialized |
| 1541 | QPDFObjectHandle uninitialized; | 1541 | QPDFObjectHandle uninitialized; |
| 1542 | assert(!uninitialized); | 1542 | assert(!uninitialized); |
| 1543 | assert(!uninitialized.isInteger()); | 1543 | assert(!uninitialized.isInteger()); |
| 1544 | assert(!uninitialized.isDictionary()); | 1544 | assert(!uninitialized.isDictionary()); |
| 1545 | assert(!uninitialized.isScalar()); | 1545 | assert(!uninitialized.isScalar()); |
| 1546 | + | ||
| 1547 | + // Reference | ||
| 1548 | + auto indirect = pdf.newIndirectNull(); | ||
| 1549 | + QPDFObjGen indirect_og{indirect.getObjGen()}; | ||
| 1550 | + pdf.replaceObject(indirect, array); | ||
| 1551 | + assert(array.isIndirect()); | ||
| 1552 | + assert(indirect.isArray()); | ||
| 1553 | + assert(array.getObjGen() == indirect_og); | ||
| 1554 | + assert(array.isArray()); | ||
| 1555 | + assert(indirect.isArray()); | ||
| 1556 | + assert(indirect.unparse() == indirect_og.unparse(' ') + " R"); | ||
| 1557 | + | ||
| 1558 | + auto pl1 = Pl_Buffer(""); | ||
| 1559 | + array.writeJSON(2, &pl1, true); | ||
| 1560 | + pl1.finish(); | ||
| 1561 | + assert(pl1.getString() == std::string("\"" + indirect_og.unparse(' ') + " R\"")); | ||
| 1562 | + | ||
| 1563 | + array.setArrayItem(1, "42"_qpdf); | ||
| 1564 | + assert(indirect.getArrayItem(1).getIntValue() == 42); | ||
| 1565 | + | ||
| 1566 | + pdf.replaceObject(indirect, "42"_qpdf); | ||
| 1567 | + assert(array.isInteger()); | ||
| 1546 | } | 1568 | } |
| 1547 | 1569 | ||
| 1548 | static void | 1570 | static void |