Commit 8a3cdfd2af4a95d8daede45bcb36eecdcdc8f964
1 parent
910a373a
Change QPDFObjectHandle == to isSameObjectAs
Replace operator== and operator!=, which were testing for the same underlying object, with isSameObjectAs. This change was motivated by the fact that pikepdf internally had its own operator== method for QPDFObjectHandle that did structural comparison. I backed out qpdf's operator== as a courtesy to pikepdf (in my own testing) but also because I think people might naturally assume that operator== does a structural comparison, and isSameObjectAs is clearer in its intent.
Showing
5 changed files
with
53 additions
and
61 deletions
ChangeLog
| 1 | 2022-09-09 Jay Berkenbilt <ejb@ql.org> | 1 | 2022-09-09 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | ||
| 3 | + * Add QPDFObjectHandle::isSameObjectAs to test whether two | ||
| 4 | + QPDFObjectHandle objects point to the same underlying object. | ||
| 5 | + | ||
| 3 | * Expose ability to create custom loggers and to get and set the | 6 | * Expose ability to create custom loggers and to get and set the |
| 4 | logger for QPDF and QPDFJob through the C API. | 7 | logger for QPDF and QPDFJob through the C API. |
| 5 | 8 | ||
| @@ -29,10 +32,6 @@ | @@ -29,10 +32,6 @@ | ||
| 29 | * Add new methods getArtBox and getBleedBox to | 32 | * Add new methods getArtBox and getBleedBox to |
| 30 | QPDFPageObjectHelper, completing the set of bounding box methods. | 33 | QPDFPageObjectHelper, completing the set of bounding box methods. |
| 31 | 34 | ||
| 32 | - * Add == equality for QPDFObjectHandle. Two QPDFObjectHandle | ||
| 33 | - objects are equal if they point to the same underlying object, | ||
| 34 | - meaning changes to one will be reflected in the other. | ||
| 35 | - | ||
| 36 | * The --show-encryption option now works even if a correct | 35 | * The --show-encryption option now works even if a correct |
| 37 | password is not supplied. If you were using --show-encryption to | 36 | password is not supplied. If you were using --show-encryption to |
| 38 | test whether you have the right password, use --requires-password | 37 | test whether you have the right password, use --requires-password |
include/qpdf/QPDFObjectHandle.hh
| @@ -334,14 +334,13 @@ class QPDFObjectHandle | @@ -334,14 +334,13 @@ class QPDFObjectHandle | ||
| 334 | QPDF_DLL | 334 | QPDF_DLL |
| 335 | inline bool isInitialized() const; | 335 | inline bool isInitialized() const; |
| 336 | 336 | ||
| 337 | - // Two QPDFObjectHandle objects are equal if they point to exactly | ||
| 338 | - // the same underlying object, meaning that changes to one are | ||
| 339 | - // reflected in the other, or "if you paint one, the other one | ||
| 340 | - // changes color." | 337 | + // This method returns true if the QPDFObjectHandle objects point |
| 338 | + // to exactly the same underlying object, meaning that changes to | ||
| 339 | + // one are reflected in the other, or "if you paint one, the other | ||
| 340 | + // one changes color." This does not perform a structural | ||
| 341 | + // comparison of the contents of the objects. | ||
| 341 | QPDF_DLL | 342 | QPDF_DLL |
| 342 | - bool operator==(QPDFObjectHandle const&) const; | ||
| 343 | - QPDF_DLL | ||
| 344 | - bool operator!=(QPDFObjectHandle const&) const; | 343 | + bool isSameObjectAs(QPDFObjectHandle const&) const; |
| 345 | 344 | ||
| 346 | // Return type code and type name of underlying object. These are | 345 | // Return type code and type name of underlying object. These are |
| 347 | // useful for doing rapid type tests (like switch statements) or | 346 | // useful for doing rapid type tests (like switch statements) or |
libqpdf/QPDFObjectHandle.cc
| @@ -237,17 +237,11 @@ LastChar::getLastChar() | @@ -237,17 +237,11 @@ LastChar::getLastChar() | ||
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | bool | 239 | bool |
| 240 | -QPDFObjectHandle::operator==(QPDFObjectHandle const& rhs) const | 240 | +QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const |
| 241 | { | 241 | { |
| 242 | return this->obj == rhs.obj; | 242 | return this->obj == rhs.obj; |
| 243 | } | 243 | } |
| 244 | 244 | ||
| 245 | -bool | ||
| 246 | -QPDFObjectHandle::operator!=(QPDFObjectHandle const& rhs) const | ||
| 247 | -{ | ||
| 248 | - return this->obj != rhs.obj; | ||
| 249 | -} | ||
| 250 | - | ||
| 251 | void | 245 | void |
| 252 | QPDFObjectHandle::disconnect() | 246 | QPDFObjectHandle::disconnect() |
| 253 | { | 247 | { |
manual/release-notes.rst
| @@ -231,12 +231,12 @@ For a detailed list of changes, please see the file | @@ -231,12 +231,12 @@ For a detailed list of changes, please see the file | ||
| 231 | still valid, but it's also possible to have direct objects that | 231 | still valid, but it's also possible to have direct objects that |
| 232 | don't have an owning ``QPDF``. | 232 | don't have an owning ``QPDF``. |
| 233 | 233 | ||
| 234 | - - It is now possible to test ``QPDFObjectHandle`` equality with | ||
| 235 | - ``==`` and ``!=``. Two ``QPDFObjectHandle`` objects are equal if | ||
| 236 | - they point to the same underlying object, meaning changes to one | ||
| 237 | - will be reflected in the other. Note that this method does not | ||
| 238 | - compare the contents of the objects, so two distinct but | ||
| 239 | - structurally identical objects will not be considered equal. | 234 | + - Add method ``QPDFObjectHandle::isSameObjectAs`` for testing |
| 235 | + whether two ``QPDFObjectHandle`` objects point to the same | ||
| 236 | + underlying object, meaning changes to one will be reflected in | ||
| 237 | + the other. Note that this method does not compare the contents | ||
| 238 | + of the objects, so two distinct but structurally identical | ||
| 239 | + objects will not be considered the same object. | ||
| 240 | 240 | ||
| 241 | - New factory method ``QPDF::create()`` returns a | 241 | - New factory method ``QPDF::create()`` returns a |
| 242 | ``std::shared_ptr<QPDF>``. | 242 | ``std::shared_ptr<QPDF>``. |
qpdf/test_driver.cc
| @@ -3340,22 +3340,22 @@ test_93(QPDF& pdf, char const* arg2) | @@ -3340,22 +3340,22 @@ test_93(QPDF& pdf, char const* arg2) | ||
| 3340 | auto trailer = pdf.getTrailer(); | 3340 | auto trailer = pdf.getTrailer(); |
| 3341 | auto root1 = trailer.getKey("/Root"); | 3341 | auto root1 = trailer.getKey("/Root"); |
| 3342 | auto root2 = pdf.getRoot(); | 3342 | auto root2 = pdf.getRoot(); |
| 3343 | - assert(root1 == root2); | 3343 | + assert(root1.isSameObjectAs(root2)); |
| 3344 | auto oh1 = "<< /One /Two >>"_qpdf; | 3344 | auto oh1 = "<< /One /Two >>"_qpdf; |
| 3345 | auto oh2 = oh1; | 3345 | auto oh2 = oh1; |
| 3346 | - assert(oh1 == oh2); | 3346 | + assert(oh1.isSameObjectAs(oh2)); |
| 3347 | auto oh3 = "<< /One /Two >>"_qpdf; | 3347 | auto oh3 = "<< /One /Two >>"_qpdf; |
| 3348 | - assert(oh1 != oh3); | 3348 | + assert(!oh1.isSameObjectAs(oh3)); |
| 3349 | oh2.replaceKey("/One", "/Three"_qpdf); | 3349 | oh2.replaceKey("/One", "/Three"_qpdf); |
| 3350 | - assert(oh1 == oh2); | 3350 | + assert(oh1.isSameObjectAs(oh2)); |
| 3351 | assert(oh2.unparse() == "<< /One /Three >>"); | 3351 | assert(oh2.unparse() == "<< /One /Three >>"); |
| 3352 | assert(!oh1.isIndirect()); | 3352 | assert(!oh1.isIndirect()); |
| 3353 | auto oh4 = pdf.makeIndirectObject(oh1); | 3353 | auto oh4 = pdf.makeIndirectObject(oh1); |
| 3354 | - assert(oh1 == oh4); | 3354 | + assert(oh1.isSameObjectAs(oh4)); |
| 3355 | assert(oh1.isIndirect()); | 3355 | assert(oh1.isIndirect()); |
| 3356 | assert(oh4.isIndirect()); | 3356 | assert(oh4.isIndirect()); |
| 3357 | trailer.replaceKey("/Potato", oh1); | 3357 | trailer.replaceKey("/Potato", oh1); |
| 3358 | - assert(trailer.getKey("/Potato") == oh2); | 3358 | + assert(trailer.getKey("/Potato").isSameObjectAs(oh2)); |
| 3359 | } | 3359 | } |
| 3360 | 3360 | ||
| 3361 | static void | 3361 | static void |
| @@ -3385,76 +3385,76 @@ test_94(QPDF& pdf, char const* arg2) | @@ -3385,76 +3385,76 @@ test_94(QPDF& pdf, char const* arg2) | ||
| 3385 | 3385 | ||
| 3386 | assert(p1.getObjectHandle().getKey("/MediaBox").isNull()); | 3386 | assert(p1.getObjectHandle().getKey("/MediaBox").isNull()); |
| 3387 | // MediaBox not present, so get inherited one | 3387 | // MediaBox not present, so get inherited one |
| 3388 | - assert(p1.getMediaBox(false) == root_media); | 3388 | + assert(p1.getMediaBox(false).isSameObjectAs(root_media)); |
| 3389 | // Other boxesBox not present, so fall back to MediaBox | 3389 | // Other boxesBox not present, so fall back to MediaBox |
| 3390 | - assert(p1.getCropBox(false, false) == root_media); | ||
| 3391 | - assert(p1.getBleedBox(false, false) == root_media); | ||
| 3392 | - assert(p1.getTrimBox(false, false) == root_media); | ||
| 3393 | - assert(p1.getArtBox(false, false) == root_media); | 3390 | + assert(p1.getCropBox(false, false).isSameObjectAs(root_media)); |
| 3391 | + assert(p1.getBleedBox(false, false).isSameObjectAs(root_media)); | ||
| 3392 | + assert(p1.getTrimBox(false, false).isSameObjectAs(root_media)); | ||
| 3393 | + assert(p1.getArtBox(false, false).isSameObjectAs(root_media)); | ||
| 3394 | // Make copy of artbox | 3394 | // Make copy of artbox |
| 3395 | auto p1_new_art = p1.getArtBox(false, true); | 3395 | auto p1_new_art = p1.getArtBox(false, true); |
| 3396 | assert(p1_new_art.unparse() == root_media_unparse); | 3396 | assert(p1_new_art.unparse() == root_media_unparse); |
| 3397 | - assert(p1_new_art != root_media); | 3397 | + assert(!p1_new_art.isSameObjectAs(root_media)); |
| 3398 | // This also copied cropbox | 3398 | // This also copied cropbox |
| 3399 | auto p1_new_crop = p1.getCropBox(false, false); | 3399 | auto p1_new_crop = p1.getCropBox(false, false); |
| 3400 | - assert(p1_new_crop != root_media); | ||
| 3401 | - assert(p1_new_crop != p1_new_art); | 3400 | + assert(!p1_new_crop.isSameObjectAs(root_media)); |
| 3401 | + assert(!p1_new_crop.isSameObjectAs(p1_new_art)); | ||
| 3402 | assert(p1_new_crop.unparse() == root_media_unparse); | 3402 | assert(p1_new_crop.unparse() == root_media_unparse); |
| 3403 | // But it didn't copy Media | 3403 | // But it didn't copy Media |
| 3404 | - assert(p1.getMediaBox(false) == root_media); | 3404 | + assert(p1.getMediaBox(false).isSameObjectAs(root_media)); |
| 3405 | // Now fall back to new crop | 3405 | // Now fall back to new crop |
| 3406 | - assert(p1.getTrimBox(false, false) == p1_new_crop); | 3406 | + assert(p1.getTrimBox(false, false).isSameObjectAs(p1_new_crop)); |
| 3407 | // Request copy. The value returned has the same structure but is | 3407 | // Request copy. The value returned has the same structure but is |
| 3408 | // a different object. | 3408 | // a different object. |
| 3409 | auto p1_effective_media = p1.getMediaBox(true); | 3409 | auto p1_effective_media = p1.getMediaBox(true); |
| 3410 | assert(p1_effective_media.unparse() == root_media_unparse); | 3410 | assert(p1_effective_media.unparse() == root_media_unparse); |
| 3411 | - assert(p1_effective_media != root_media); | 3411 | + assert(!p1_effective_media.isSameObjectAs(root_media)); |
| 3412 | 3412 | ||
| 3413 | // copy_on_fallback didn't have to copy media to crop | 3413 | // copy_on_fallback didn't have to copy media to crop |
| 3414 | - assert(p2.getMediaBox(false) == root_media); | 3414 | + assert(p2.getMediaBox(false).isSameObjectAs(root_media)); |
| 3415 | auto p2_crop = p2.getCropBox(false, false); | 3415 | auto p2_crop = p2.getCropBox(false, false); |
| 3416 | auto p2_new_trim = p2.getTrimBox(false, true); | 3416 | auto p2_new_trim = p2.getTrimBox(false, true); |
| 3417 | assert(p2_new_trim.unparse() == p2_crop.unparse()); | 3417 | assert(p2_new_trim.unparse() == p2_crop.unparse()); |
| 3418 | - assert(p2_new_trim != p2_crop); | ||
| 3419 | - assert(p2.getMediaBox(false) == root_media); | 3418 | + assert(!p2_new_trim.isSameObjectAs(p2_crop)); |
| 3419 | + assert(p2.getMediaBox(false).isSameObjectAs(root_media)); | ||
| 3420 | 3420 | ||
| 3421 | // We didn't need to copy anything | 3421 | // We didn't need to copy anything |
| 3422 | auto p3_media = p3.getMediaBox(false); | 3422 | auto p3_media = p3.getMediaBox(false); |
| 3423 | auto p3_crop = p3.getCropBox(false, false); | 3423 | auto p3_crop = p3.getCropBox(false, false); |
| 3424 | - assert(p3.getMediaBox(true) == p3_media); | ||
| 3425 | - assert(p3.getCropBox(true, true) == p3_crop); | 3424 | + assert(p3.getMediaBox(true).isSameObjectAs(p3_media)); |
| 3425 | + assert(p3.getCropBox(true, true).isSameObjectAs(p3_crop)); | ||
| 3426 | 3426 | ||
| 3427 | // We didn't have to copy for bleed but we did for art | 3427 | // We didn't have to copy for bleed but we did for art |
| 3428 | auto p4_orig_crop = p4.getObjectHandle().getKey("/CropBox"); | 3428 | auto p4_orig_crop = p4.getObjectHandle().getKey("/CropBox"); |
| 3429 | auto p4_crop = p4.getCropBox(false, false); | 3429 | auto p4_crop = p4.getCropBox(false, false); |
| 3430 | - assert(p4_orig_crop == p4_crop); | 3430 | + assert(p4_orig_crop.isSameObjectAs(p4_crop)); |
| 3431 | auto p4_bleed1 = p4.getBleedBox(false, false); | 3431 | auto p4_bleed1 = p4.getBleedBox(false, false); |
| 3432 | auto p4_bleed2 = p4.getBleedBox(false, true); | 3432 | auto p4_bleed2 = p4.getBleedBox(false, true); |
| 3433 | - assert(p4_bleed1 != p4_crop); | ||
| 3434 | - assert(p4_bleed1 == p4_bleed2); | 3433 | + assert(!p4_bleed1.isSameObjectAs(p4_crop)); |
| 3434 | + assert(p4_bleed1.isSameObjectAs(p4_bleed2)); | ||
| 3435 | auto p4_art1 = p4.getArtBox(false, false); | 3435 | auto p4_art1 = p4.getArtBox(false, false); |
| 3436 | - assert(p4_art1 == p4_crop); | 3436 | + assert(p4_art1.isSameObjectAs(p4_crop)); |
| 3437 | auto p4_art2 = p4.getArtBox(false, true); | 3437 | auto p4_art2 = p4.getArtBox(false, true); |
| 3438 | - assert(p4_art2 != p4_crop); | 3438 | + assert(!p4_art2.isSameObjectAs(p4_crop)); |
| 3439 | auto p4_new_crop = p4.getCropBox(true, false); | 3439 | auto p4_new_crop = p4.getCropBox(true, false); |
| 3440 | - assert(p4_new_crop != p4_orig_crop); | 3440 | + assert(!p4_new_crop.isSameObjectAs(p4_orig_crop)); |
| 3441 | assert(p4_orig_crop.isIndirect()); | 3441 | assert(p4_orig_crop.isIndirect()); |
| 3442 | assert(!p4_new_crop.isIndirect()); | 3442 | assert(!p4_new_crop.isIndirect()); |
| 3443 | assert(p4_new_crop.unparse() == p4_orig_crop.unparseResolved()); | 3443 | assert(p4_new_crop.unparse() == p4_orig_crop.unparseResolved()); |
| 3444 | 3444 | ||
| 3445 | // Exercise copying for inheritance and fallback | 3445 | // Exercise copying for inheritance and fallback |
| 3446 | - assert(p5.getMediaBox(false) == root_media); | ||
| 3447 | - assert(p5.getCropBox(false, false) == root_media); | ||
| 3448 | - assert(p5.getBleedBox(false, false) == root_media); | 3446 | + assert(p5.getMediaBox(false).isSameObjectAs(root_media)); |
| 3447 | + assert(p5.getCropBox(false, false).isSameObjectAs(root_media)); | ||
| 3448 | + assert(p5.getBleedBox(false, false).isSameObjectAs(root_media)); | ||
| 3449 | auto p5_new_bleed = p5.getBleedBox(true, true); | 3449 | auto p5_new_bleed = p5.getBleedBox(true, true); |
| 3450 | auto p5_new_media = p5.getMediaBox(false); | 3450 | auto p5_new_media = p5.getMediaBox(false); |
| 3451 | auto p5_new_crop = p5.getCropBox(false, false); | 3451 | auto p5_new_crop = p5.getCropBox(false, false); |
| 3452 | - assert(p5_new_media != root_media); | ||
| 3453 | - assert(p5_new_crop != root_media); | ||
| 3454 | - assert(p5_new_crop != p5_new_media); | ||
| 3455 | - assert(p5_new_bleed != root_media); | ||
| 3456 | - assert(p5_new_bleed != p5_new_media); | ||
| 3457 | - assert(p5_new_bleed != p5_new_crop); | 3452 | + assert(!p5_new_media.isSameObjectAs(root_media)); |
| 3453 | + assert(!p5_new_crop.isSameObjectAs(root_media)); | ||
| 3454 | + assert(!p5_new_crop.isSameObjectAs(p5_new_media)); | ||
| 3455 | + assert(!p5_new_bleed.isSameObjectAs(root_media)); | ||
| 3456 | + assert(!p5_new_bleed.isSameObjectAs(p5_new_media)); | ||
| 3457 | + assert(!p5_new_bleed.isSameObjectAs(p5_new_crop)); | ||
| 3458 | assert(p5_new_media.unparse() == root_media_unparse); | 3458 | assert(p5_new_media.unparse() == root_media_unparse); |
| 3459 | assert(p5_new_crop.unparse() == root_media_unparse); | 3459 | assert(p5_new_crop.unparse() == root_media_unparse); |
| 3460 | assert(p5_new_bleed.unparse() == root_media_unparse); | 3460 | assert(p5_new_bleed.unparse() == root_media_unparse); |