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 | 52 | public: |
| 53 | 53 | explicit inline operator bool() const; |
| 54 | 54 | inline operator QPDFObjectHandle() const; |
| 55 | + QPDF_DLL | |
| 55 | 56 | operator QPDFObjGen() const; |
| 56 | 57 | |
| 57 | 58 | // The rest of the header file is for qpdf internal use only. |
| ... | ... | @@ -65,6 +66,7 @@ namespace qpdf |
| 65 | 66 | inline bool null() const; |
| 66 | 67 | inline QPDF* qpdf() const; |
| 67 | 68 | inline qpdf_object_type_e raw_type_code() const; |
| 69 | + inline qpdf_object_type_e resolved_type_code() const; | |
| 68 | 70 | inline qpdf_object_type_e type_code() const; |
| 69 | 71 | std::string unparse() const; |
| 70 | 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 | 291 | std::shared_ptr<QPDFObject> |
| 292 | 292 | BaseHandle::copy(bool shallow) const |
| 293 | 293 | { |
| 294 | - switch (type_code()) { | |
| 294 | + switch (resolved_type_code()) { | |
| 295 | 295 | case ::ot_uninitialized: |
| 296 | 296 | throw std::logic_error("QPDFObjectHandle: attempting to copy an uninitialized object"); |
| 297 | 297 | return {}; // does not return |
| ... | ... | @@ -371,7 +371,7 @@ BaseHandle::copy(bool shallow) const |
| 371 | 371 | std::string |
| 372 | 372 | BaseHandle::unparse() const |
| 373 | 373 | { |
| 374 | - switch (type_code()) { | |
| 374 | + switch (resolved_type_code()) { | |
| 375 | 375 | case ::ot_uninitialized: |
| 376 | 376 | throw std::logic_error("QPDFObjectHandle: attempting to unparse an uninitialized object"); |
| 377 | 377 | return ""; // does not return |
| ... | ... | @@ -448,7 +448,7 @@ BaseHandle::unparse() const |
| 448 | 448 | void |
| 449 | 449 | BaseHandle::write_json(int json_version, JSON::Writer& p) const |
| 450 | 450 | { |
| 451 | - switch (type_code()) { | |
| 451 | + switch (resolved_type_code()) { | |
| 452 | 452 | case ::ot_uninitialized: |
| 453 | 453 | throw std::logic_error( |
| 454 | 454 | "QPDFObjectHandle: attempting to get JSON from a uninitialized object"); | ... | ... |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| ... | ... | @@ -374,6 +374,18 @@ namespace qpdf |
| 374 | 374 | } |
| 375 | 375 | |
| 376 | 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 | 389 | BaseHandle::type_code() const |
| 378 | 390 | { |
| 379 | 391 | if (!obj) { | ... | ... |
qpdf/test_driver.cc
| ... | ... | @@ -1403,8 +1403,7 @@ test_41(QPDF& pdf, char const* arg2) |
| 1403 | 1403 | static void |
| 1404 | 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 | 1407 | QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); |
| 1409 | 1408 | QPDFObjectHandle array = qtest.getKey("/Dictionary").getKey("/Key2"); |
| 1410 | 1409 | QPDFObjectHandle dictionary = qtest.getKey("/Dictionary"); |
| ... | ... | @@ -1537,12 +1536,35 @@ test_42(QPDF& pdf, char const* arg2) |
| 1537 | 1536 | assert(!"42"_qpdf.isMatrix()); |
| 1538 | 1537 | m1 = "42"_qpdf.getArrayAsMatrix(); |
| 1539 | 1538 | assert(m1.a == 0 && m1.b == 0 && m1.c == 0 && m1.d == 0 && m1.e == 0 && m1.f == 0); |
| 1539 | + | |
| 1540 | 1540 | // Uninitialized |
| 1541 | 1541 | QPDFObjectHandle uninitialized; |
| 1542 | 1542 | assert(!uninitialized); |
| 1543 | 1543 | assert(!uninitialized.isInteger()); |
| 1544 | 1544 | assert(!uninitialized.isDictionary()); |
| 1545 | 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 | 1570 | static void | ... | ... |