Commit 884d36becd8403eefa9cbaceb7d85b37ecaa61c5
Committed by
GitHub
Merge pull request #1380 from m-holger/object
Move QPDFObject::copy, disconnect, unparse and write_json to BaseHandle
Showing
7 changed files
with
122 additions
and
124 deletions
include/qpdf/ObjectHandle.hh
| @@ -47,6 +47,8 @@ namespace qpdf | @@ -47,6 +47,8 @@ namespace qpdf | ||
| 47 | // QPDFObjGen and bool. | 47 | // QPDFObjGen and bool. |
| 48 | class BaseHandle | 48 | class BaseHandle |
| 49 | { | 49 | { |
| 50 | + friend class QPDF; | ||
| 51 | + | ||
| 50 | public: | 52 | public: |
| 51 | explicit inline operator bool() const; | 53 | explicit inline operator bool() const; |
| 52 | inline operator QPDFObjectHandle() const; | 54 | inline operator QPDFObjectHandle() const; |
| @@ -54,12 +56,18 @@ namespace qpdf | @@ -54,12 +56,18 @@ namespace qpdf | ||
| 54 | 56 | ||
| 55 | // The rest of the header file is for qpdf internal use only. | 57 | // The rest of the header file is for qpdf internal use only. |
| 56 | 58 | ||
| 59 | + std::shared_ptr<QPDFObject> copy(bool shallow = false) const; | ||
| 60 | + // Recursively remove association with any QPDF object. This method may only be called | ||
| 61 | + // during final destruction. | ||
| 62 | + void disconnect(bool only_direct = true); | ||
| 57 | inline QPDFObjGen id_gen() const; | 63 | inline QPDFObjGen id_gen() const; |
| 58 | inline bool indirect() const; | 64 | inline bool indirect() const; |
| 59 | inline bool null() const; | 65 | inline bool null() const; |
| 60 | inline QPDF* qpdf() const; | 66 | inline QPDF* qpdf() const; |
| 61 | inline qpdf_object_type_e raw_type_code() const; | 67 | inline qpdf_object_type_e raw_type_code() const; |
| 62 | inline qpdf_object_type_e type_code() const; | 68 | inline qpdf_object_type_e type_code() const; |
| 69 | + std::string unparse() const; | ||
| 70 | + void write_json(int json_version, JSON::Writer& p) const; | ||
| 63 | 71 | ||
| 64 | protected: | 72 | protected: |
| 65 | BaseHandle() = default; | 73 | BaseHandle() = default; |
include/qpdf/QPDFObjectHandle.hh
| @@ -1242,19 +1242,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | @@ -1242,19 +1242,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | ||
| 1242 | QPDF_DLL | 1242 | QPDF_DLL |
| 1243 | void warnIfPossible(std::string const& warning) const; | 1243 | void warnIfPossible(std::string const& warning) const; |
| 1244 | 1244 | ||
| 1245 | - // Provide access to specific classes for recursive disconnected(). | ||
| 1246 | - class DisconnectAccess | ||
| 1247 | - { | ||
| 1248 | - friend class QPDFObject; | ||
| 1249 | - | ||
| 1250 | - private: | ||
| 1251 | - static void | ||
| 1252 | - disconnect(QPDFObjectHandle o) | ||
| 1253 | - { | ||
| 1254 | - o.disconnect(); | ||
| 1255 | - } | ||
| 1256 | - }; | ||
| 1257 | - | ||
| 1258 | // Convenience routine: Throws if the assumption is violated. Your code will be better if you | 1245 | // Convenience routine: Throws if the assumption is violated. Your code will be better if you |
| 1259 | // call one of the isType methods and handle the case of the type being wrong, but these can be | 1246 | // call one of the isType methods and handle the case of the type being wrong, but these can be |
| 1260 | // convenient if you have already verified the type. | 1247 | // convenient if you have already verified the type. |
| @@ -1354,7 +1341,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | @@ -1354,7 +1341,6 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | ||
| 1354 | void objectWarning(std::string const& warning) const; | 1341 | void objectWarning(std::string const& warning) const; |
| 1355 | void assertType(char const* type_name, bool istype) const; | 1342 | void assertType(char const* type_name, bool istype) const; |
| 1356 | void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); | 1343 | void makeDirect(QPDFObjGen::set& visited, bool stop_at_streams); |
| 1357 | - void disconnect(); | ||
| 1358 | void setParsedOffset(qpdf_offset_t offset); | 1344 | void setParsedOffset(qpdf_offset_t offset); |
| 1359 | void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); | 1345 | void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks); |
| 1360 | static void parseContentStream_data( | 1346 | static void parseContentStream_data( |
libqpdf/QPDF.cc
| @@ -212,6 +212,25 @@ QPDF::QPDF() : | @@ -212,6 +212,25 @@ QPDF::QPDF() : | ||
| 212 | m->unique_id = unique_id.fetch_add(1ULL); | 212 | m->unique_id = unique_id.fetch_add(1ULL); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | +// Provide access to disconnect(). Disconnect will in due course be merged into the current ObjCache | ||
| 216 | +// (future Objects::Entry) to centralize all QPDF access to QPDFObject. | ||
| 217 | +class Disconnect: BaseHandle | ||
| 218 | +{ | ||
| 219 | + public: | ||
| 220 | + Disconnect(std::shared_ptr<QPDFObject> const& obj) : | ||
| 221 | + BaseHandle(obj) | ||
| 222 | + { | ||
| 223 | + } | ||
| 224 | + void | ||
| 225 | + disconnect() | ||
| 226 | + { | ||
| 227 | + BaseHandle::disconnect(false); | ||
| 228 | + if (raw_type_code() != ::ot_null) { | ||
| 229 | + obj->value = QPDF_Destroyed(); | ||
| 230 | + } | ||
| 231 | + } | ||
| 232 | +}; | ||
| 233 | + | ||
| 215 | QPDF::~QPDF() | 234 | QPDF::~QPDF() |
| 216 | { | 235 | { |
| 217 | // If two objects are mutually referential (through each object having an array or dictionary | 236 | // If two objects are mutually referential (through each object having an array or dictionary |
| @@ -228,10 +247,7 @@ QPDF::~QPDF() | @@ -228,10 +247,7 @@ QPDF::~QPDF() | ||
| 228 | // the xref table anyway just to prevent any possibility of resolve() succeeding. | 247 | // the xref table anyway just to prevent any possibility of resolve() succeeding. |
| 229 | m->xref_table.clear(); | 248 | m->xref_table.clear(); |
| 230 | for (auto const& iter: m->obj_cache) { | 249 | for (auto const& iter: m->obj_cache) { |
| 231 | - iter.second.object->disconnect(); | ||
| 232 | - if (iter.second.object->getTypeCode() != ::ot_null) { | ||
| 233 | - iter.second.object->destroy(); | ||
| 234 | - } | 250 | + Disconnect(iter.second.object).disconnect(); |
| 235 | } | 251 | } |
| 236 | } | 252 | } |
| 237 | 253 |
libqpdf/QPDFObjectHandle.cc
| @@ -289,29 +289,29 @@ Name::normalize(std::string const& name) | @@ -289,29 +289,29 @@ Name::normalize(std::string const& name) | ||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | std::shared_ptr<QPDFObject> | 291 | std::shared_ptr<QPDFObject> |
| 292 | -QPDFObject::copy(bool shallow) | 292 | +BaseHandle::copy(bool shallow) const |
| 293 | { | 293 | { |
| 294 | - switch (getResolvedTypeCode()) { | 294 | + switch (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 |
| 298 | case ::ot_reserved: | 298 | case ::ot_reserved: |
| 299 | - return create<QPDF_Reserved>(); | 299 | + return QPDFObject::create<QPDF_Reserved>(); |
| 300 | case ::ot_null: | 300 | case ::ot_null: |
| 301 | - return create<QPDF_Null>(); | 301 | + return QPDFObject::create<QPDF_Null>(); |
| 302 | case ::ot_boolean: | 302 | case ::ot_boolean: |
| 303 | - return create<QPDF_Bool>(std::get<QPDF_Bool>(value).val); | 303 | + return QPDFObject::create<QPDF_Bool>(std::get<QPDF_Bool>(obj->value).val); |
| 304 | case ::ot_integer: | 304 | case ::ot_integer: |
| 305 | - return create<QPDF_Integer>(std::get<QPDF_Integer>(value).val); | 305 | + return QPDFObject::create<QPDF_Integer>(std::get<QPDF_Integer>(obj->value).val); |
| 306 | case ::ot_real: | 306 | case ::ot_real: |
| 307 | - return create<QPDF_Real>(std::get<QPDF_Real>(value).val); | 307 | + return QPDFObject::create<QPDF_Real>(std::get<QPDF_Real>(obj->value).val); |
| 308 | case ::ot_string: | 308 | case ::ot_string: |
| 309 | - return create<QPDF_String>(std::get<QPDF_String>(value).val); | 309 | + return QPDFObject::create<QPDF_String>(std::get<QPDF_String>(obj->value).val); |
| 310 | case ::ot_name: | 310 | case ::ot_name: |
| 311 | - return create<QPDF_Name>(std::get<QPDF_Name>(value).name); | 311 | + return QPDFObject::create<QPDF_Name>(std::get<QPDF_Name>(obj->value).name); |
| 312 | case ::ot_array: | 312 | case ::ot_array: |
| 313 | { | 313 | { |
| 314 | - auto const& a = std::get<QPDF_Array>(value); | 314 | + auto const& a = std::get<QPDF_Array>(obj->value); |
| 315 | if (shallow) { | 315 | if (shallow) { |
| 316 | return QPDFObject::create<QPDF_Array>(a); | 316 | return QPDFObject::create<QPDF_Array>(a); |
| 317 | } else { | 317 | } else { |
| @@ -321,7 +321,7 @@ QPDFObject::copy(bool shallow) | @@ -321,7 +321,7 @@ QPDFObject::copy(bool shallow) | ||
| 321 | result.sp = std::make_unique<QPDF_Array::Sparse>(); | 321 | result.sp = std::make_unique<QPDF_Array::Sparse>(); |
| 322 | result.sp->size = a.sp->size; | 322 | result.sp->size = a.sp->size; |
| 323 | for (auto const& [idx, oh]: a.sp->elements) { | 323 | for (auto const& [idx, oh]: a.sp->elements) { |
| 324 | - result.sp->elements[idx] = oh.indirect() ? oh : oh.getObj()->copy(); | 324 | + result.sp->elements[idx] = oh.indirect() ? oh : oh.copy(); |
| 325 | } | 325 | } |
| 326 | return QPDFObject::create<QPDF_Array>(std::move(result)); | 326 | return QPDFObject::create<QPDF_Array>(std::move(result)); |
| 327 | } else { | 327 | } else { |
| @@ -329,8 +329,7 @@ QPDFObject::copy(bool shallow) | @@ -329,8 +329,7 @@ QPDFObject::copy(bool shallow) | ||
| 329 | result.reserve(a.elements.size()); | 329 | result.reserve(a.elements.size()); |
| 330 | for (auto const& element: a.elements) { | 330 | for (auto const& element: a.elements) { |
| 331 | result.emplace_back( | 331 | result.emplace_back( |
| 332 | - element ? (element.indirect() ? element : element.getObj()->copy()) | ||
| 333 | - : element); | 332 | + element ? (element.indirect() ? element : element.copy()) : element); |
| 334 | } | 333 | } |
| 335 | return QPDFObject::create<QPDF_Array>(std::move(result), false); | 334 | return QPDFObject::create<QPDF_Array>(std::move(result), false); |
| 336 | } | 335 | } |
| @@ -338,13 +337,13 @@ QPDFObject::copy(bool shallow) | @@ -338,13 +337,13 @@ QPDFObject::copy(bool shallow) | ||
| 338 | } | 337 | } |
| 339 | case ::ot_dictionary: | 338 | case ::ot_dictionary: |
| 340 | { | 339 | { |
| 341 | - auto const& d = std::get<QPDF_Dictionary>(value); | 340 | + auto const& d = std::get<QPDF_Dictionary>(obj->value); |
| 342 | if (shallow) { | 341 | if (shallow) { |
| 343 | return QPDFObject::create<QPDF_Dictionary>(d.items); | 342 | return QPDFObject::create<QPDF_Dictionary>(d.items); |
| 344 | } else { | 343 | } else { |
| 345 | std::map<std::string, QPDFObjectHandle> new_items; | 344 | std::map<std::string, QPDFObjectHandle> new_items; |
| 346 | for (auto const& [key, val]: d.items) { | 345 | for (auto const& [key, val]: d.items) { |
| 347 | - new_items[key] = val.indirect() ? val : val.getObj()->copy(); | 346 | + new_items[key] = val.indirect() ? val : val.copy(); |
| 348 | } | 347 | } |
| 349 | return QPDFObject::create<QPDF_Dictionary>(new_items); | 348 | return QPDFObject::create<QPDF_Dictionary>(new_items); |
| 350 | } | 349 | } |
| @@ -354,9 +353,9 @@ QPDFObject::copy(bool shallow) | @@ -354,9 +353,9 @@ QPDFObject::copy(bool shallow) | ||
| 354 | throw std::runtime_error("stream objects cannot be cloned"); | 353 | throw std::runtime_error("stream objects cannot be cloned"); |
| 355 | return {}; // does not return | 354 | return {}; // does not return |
| 356 | case ::ot_operator: | 355 | case ::ot_operator: |
| 357 | - return create<QPDF_Operator>(std::get<QPDF_Operator>(value).val); | 356 | + return QPDFObject::create<QPDF_Operator>(std::get<QPDF_Operator>(obj->value).val); |
| 358 | case ::ot_inlineimage: | 357 | case ::ot_inlineimage: |
| 359 | - return create<QPDF_InlineImage>(std::get<QPDF_InlineImage>(value).val); | 358 | + return QPDFObject::create<QPDF_InlineImage>(std::get<QPDF_InlineImage>(obj->value).val); |
| 360 | case ::ot_unresolved: | 359 | case ::ot_unresolved: |
| 361 | throw std::logic_error("QPDFObjectHandle: attempting to unparse a reserved object"); | 360 | throw std::logic_error("QPDFObjectHandle: attempting to unparse a reserved object"); |
| 362 | return {}; // does not return | 361 | return {}; // does not return |
| @@ -364,15 +363,15 @@ QPDFObject::copy(bool shallow) | @@ -364,15 +363,15 @@ QPDFObject::copy(bool shallow) | ||
| 364 | throw std::logic_error("attempted to shallow copy QPDFObjectHandle from destroyed QPDF"); | 363 | throw std::logic_error("attempted to shallow copy QPDFObjectHandle from destroyed QPDF"); |
| 365 | return {}; // does not return | 364 | return {}; // does not return |
| 366 | case ::ot_reference: | 365 | case ::ot_reference: |
| 367 | - return qpdf->getObject(og).getObj(); | 366 | + return obj->qpdf->getObject(obj->og).getObj(); |
| 368 | } | 367 | } |
| 369 | return {}; // unreachable | 368 | return {}; // unreachable |
| 370 | } | 369 | } |
| 371 | 370 | ||
| 372 | std::string | 371 | std::string |
| 373 | -QPDFObject::unparse() | 372 | +BaseHandle::unparse() const |
| 374 | { | 373 | { |
| 375 | - switch (getResolvedTypeCode()) { | 374 | + switch (type_code()) { |
| 376 | case ::ot_uninitialized: | 375 | case ::ot_uninitialized: |
| 377 | throw std::logic_error("QPDFObjectHandle: attempting to unparse an uninitialized object"); | 376 | throw std::logic_error("QPDFObjectHandle: attempting to unparse an uninitialized object"); |
| 378 | return ""; // does not return | 377 | return ""; // does not return |
| @@ -382,18 +381,18 @@ QPDFObject::unparse() | @@ -382,18 +381,18 @@ QPDFObject::unparse() | ||
| 382 | case ::ot_null: | 381 | case ::ot_null: |
| 383 | return "null"; | 382 | return "null"; |
| 384 | case ::ot_boolean: | 383 | case ::ot_boolean: |
| 385 | - return std::get<QPDF_Bool>(value).val ? "true" : "false"; | 384 | + return std::get<QPDF_Bool>(obj->value).val ? "true" : "false"; |
| 386 | case ::ot_integer: | 385 | case ::ot_integer: |
| 387 | - return std::to_string(std::get<QPDF_Integer>(value).val); | 386 | + return std::to_string(std::get<QPDF_Integer>(obj->value).val); |
| 388 | case ::ot_real: | 387 | case ::ot_real: |
| 389 | - return std::get<QPDF_Real>(value).val; | 388 | + return std::get<QPDF_Real>(obj->value).val; |
| 390 | case ::ot_string: | 389 | case ::ot_string: |
| 391 | - return std::get<QPDF_String>(value).unparse(false); | 390 | + return std::get<QPDF_String>(obj->value).unparse(false); |
| 392 | case ::ot_name: | 391 | case ::ot_name: |
| 393 | - return Name::normalize(std::get<QPDF_Name>(value).name); | 392 | + return Name::normalize(std::get<QPDF_Name>(obj->value).name); |
| 394 | case ::ot_array: | 393 | case ::ot_array: |
| 395 | { | 394 | { |
| 396 | - auto const& a = std::get<QPDF_Array>(value); | 395 | + auto const& a = std::get<QPDF_Array>(obj->value); |
| 397 | std::string result = "[ "; | 396 | std::string result = "[ "; |
| 398 | if (a.sp) { | 397 | if (a.sp) { |
| 399 | int next = 0; | 398 | int next = 0; |
| @@ -402,9 +401,7 @@ QPDFObject::unparse() | @@ -402,9 +401,7 @@ QPDFObject::unparse() | ||
| 402 | for (int j = next; j < key; ++j) { | 401 | for (int j = next; j < key; ++j) { |
| 403 | result += "null "; | 402 | result += "null "; |
| 404 | } | 403 | } |
| 405 | - auto item_og = item.second.id_gen(); | ||
| 406 | - result += item_og.isIndirect() ? item_og.unparse(' ') + " R " | ||
| 407 | - : item.second.getObj()->unparse() + " "; | 404 | + result += item.second.unparse() + " "; |
| 408 | next = ++key; | 405 | next = ++key; |
| 409 | } | 406 | } |
| 410 | for (int j = next; j < a.sp->size; ++j) { | 407 | for (int j = next; j < a.sp->size; ++j) { |
| @@ -412,9 +409,7 @@ QPDFObject::unparse() | @@ -412,9 +409,7 @@ QPDFObject::unparse() | ||
| 412 | } | 409 | } |
| 413 | } else { | 410 | } else { |
| 414 | for (auto const& item: a.elements) { | 411 | for (auto const& item: a.elements) { |
| 415 | - auto item_og = item.id_gen(); | ||
| 416 | - result += item_og.isIndirect() ? item_og.unparse(' ') + " R " | ||
| 417 | - : item.getObj()->unparse() + " "; | 412 | + result += item.unparse() + " "; |
| 418 | } | 413 | } |
| 419 | } | 414 | } |
| 420 | result += "]"; | 415 | result += "]"; |
| @@ -422,7 +417,7 @@ QPDFObject::unparse() | @@ -422,7 +417,7 @@ QPDFObject::unparse() | ||
| 422 | } | 417 | } |
| 423 | case ::ot_dictionary: | 418 | case ::ot_dictionary: |
| 424 | { | 419 | { |
| 425 | - auto const& items = std::get<QPDF_Dictionary>(value).items; | 420 | + auto const& items = std::get<QPDF_Dictionary>(obj->value).items; |
| 426 | std::string result = "<< "; | 421 | std::string result = "<< "; |
| 427 | for (auto& iter: items) { | 422 | for (auto& iter: items) { |
| 428 | if (!iter.second.null()) { | 423 | if (!iter.second.null()) { |
| @@ -433,11 +428,11 @@ QPDFObject::unparse() | @@ -433,11 +428,11 @@ QPDFObject::unparse() | ||
| 433 | return result; | 428 | return result; |
| 434 | } | 429 | } |
| 435 | case ::ot_stream: | 430 | case ::ot_stream: |
| 436 | - return og.unparse(' ') + " R"; | 431 | + return obj->og.unparse(' ') + " R"; |
| 437 | case ::ot_operator: | 432 | case ::ot_operator: |
| 438 | - return std::get<QPDF_Operator>(value).val; | 433 | + return std::get<QPDF_Operator>(obj->value).val; |
| 439 | case ::ot_inlineimage: | 434 | case ::ot_inlineimage: |
| 440 | - return std::get<QPDF_InlineImage>(value).val; | 435 | + return std::get<QPDF_InlineImage>(obj->value).val; |
| 441 | case ::ot_unresolved: | 436 | case ::ot_unresolved: |
| 442 | throw std::logic_error("QPDFObjectHandle: attempting to unparse a unresolved object"); | 437 | throw std::logic_error("QPDFObjectHandle: attempting to unparse a unresolved object"); |
| 443 | return ""; // does not return | 438 | return ""; // does not return |
| @@ -445,15 +440,15 @@ QPDFObject::unparse() | @@ -445,15 +440,15 @@ QPDFObject::unparse() | ||
| 445 | throw std::logic_error("attempted to unparse a QPDFObjectHandle from a destroyed QPDF"); | 440 | throw std::logic_error("attempted to unparse a QPDFObjectHandle from a destroyed QPDF"); |
| 446 | return ""; // does not return | 441 | return ""; // does not return |
| 447 | case ::ot_reference: | 442 | case ::ot_reference: |
| 448 | - return og.unparse(' ') + " R"; | 443 | + return obj->og.unparse(' ') + " R"; |
| 449 | } | 444 | } |
| 450 | return {}; // unreachable | 445 | return {}; // unreachable |
| 451 | } | 446 | } |
| 452 | 447 | ||
| 453 | void | 448 | void |
| 454 | -QPDFObject::write_json(int json_version, JSON::Writer& p) | 449 | +BaseHandle::write_json(int json_version, JSON::Writer& p) const |
| 455 | { | 450 | { |
| 456 | - switch (getResolvedTypeCode()) { | 451 | + switch (type_code()) { |
| 457 | case ::ot_uninitialized: | 452 | case ::ot_uninitialized: |
| 458 | throw std::logic_error( | 453 | throw std::logic_error( |
| 459 | "QPDFObjectHandle: attempting to get JSON from a uninitialized object"); | 454 | "QPDFObjectHandle: attempting to get JSON from a uninitialized object"); |
| @@ -464,14 +459,14 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -464,14 +459,14 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 464 | p << "null"; | 459 | p << "null"; |
| 465 | break; | 460 | break; |
| 466 | case ::ot_boolean: | 461 | case ::ot_boolean: |
| 467 | - p << std::get<QPDF_Bool>(value).val; | 462 | + p << std::get<QPDF_Bool>(obj->value).val; |
| 468 | break; | 463 | break; |
| 469 | case ::ot_integer: | 464 | case ::ot_integer: |
| 470 | - p << std::to_string(std::get<QPDF_Integer>(value).val); | 465 | + p << std::to_string(std::get<QPDF_Integer>(obj->value).val); |
| 471 | break; | 466 | break; |
| 472 | case ::ot_real: | 467 | case ::ot_real: |
| 473 | { | 468 | { |
| 474 | - auto const& val = std::get<QPDF_Real>(value).val; | 469 | + auto const& val = std::get<QPDF_Real>(obj->value).val; |
| 475 | if (val.length() == 0) { | 470 | if (val.length() == 0) { |
| 476 | // Can't really happen... | 471 | // Can't really happen... |
| 477 | p << "0"; | 472 | p << "0"; |
| @@ -488,11 +483,11 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -488,11 +483,11 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 488 | } | 483 | } |
| 489 | break; | 484 | break; |
| 490 | case ::ot_string: | 485 | case ::ot_string: |
| 491 | - std::get<QPDF_String>(value).writeJSON(json_version, p); | 486 | + std::get<QPDF_String>(obj->value).writeJSON(json_version, p); |
| 492 | break; | 487 | break; |
| 493 | case ::ot_name: | 488 | case ::ot_name: |
| 494 | { | 489 | { |
| 495 | - auto const& n = std::get<QPDF_Name>(value); | 490 | + auto const& n = std::get<QPDF_Name>(obj->value); |
| 496 | // For performance reasons this code is duplicated in QPDF_Dictionary::writeJSON. When | 491 | // For performance reasons this code is duplicated in QPDF_Dictionary::writeJSON. When |
| 497 | // updating this method make sure QPDF_Dictionary is also update. | 492 | // updating this method make sure QPDF_Dictionary is also update. |
| 498 | if (json_version == 1) { | 493 | if (json_version == 1) { |
| @@ -512,7 +507,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -512,7 +507,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 512 | break; | 507 | break; |
| 513 | case ::ot_array: | 508 | case ::ot_array: |
| 514 | { | 509 | { |
| 515 | - auto const& a = std::get<QPDF_Array>(value); | 510 | + auto const& a = std::get<QPDF_Array>(obj->value); |
| 516 | p.writeStart('['); | 511 | p.writeStart('['); |
| 517 | if (a.sp) { | 512 | if (a.sp) { |
| 518 | int next = 0; | 513 | int next = 0; |
| @@ -526,7 +521,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -526,7 +521,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 526 | if (item_og.isIndirect()) { | 521 | if (item_og.isIndirect()) { |
| 527 | p << "\"" << item_og.unparse(' ') << " R\""; | 522 | p << "\"" << item_og.unparse(' ') << " R\""; |
| 528 | } else { | 523 | } else { |
| 529 | - item.second.getObj()->write_json(json_version, p); | 524 | + item.second.write_json(json_version, p); |
| 530 | } | 525 | } |
| 531 | next = ++key; | 526 | next = ++key; |
| 532 | } | 527 | } |
| @@ -540,7 +535,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -540,7 +535,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 540 | if (item_og.isIndirect()) { | 535 | if (item_og.isIndirect()) { |
| 541 | p << "\"" << item_og.unparse(' ') << " R\""; | 536 | p << "\"" << item_og.unparse(' ') << " R\""; |
| 542 | } else { | 537 | } else { |
| 543 | - item.getObj()->write_json(json_version, p); | 538 | + item.write_json(json_version, p); |
| 544 | } | 539 | } |
| 545 | } | 540 | } |
| 546 | } | 541 | } |
| @@ -549,7 +544,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -549,7 +544,7 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 549 | break; | 544 | break; |
| 550 | case ::ot_dictionary: | 545 | case ::ot_dictionary: |
| 551 | { | 546 | { |
| 552 | - auto const& d = std::get<QPDF_Dictionary>(value); | 547 | + auto const& d = std::get<QPDF_Dictionary>(obj->value); |
| 553 | p.writeStart('{'); | 548 | p.writeStart('{'); |
| 554 | for (auto& iter: d.items) { | 549 | for (auto& iter: d.items) { |
| 555 | if (!iter.second.null()) { | 550 | if (!iter.second.null()) { |
| @@ -574,10 +569,10 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -574,10 +569,10 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 574 | } | 569 | } |
| 575 | break; | 570 | break; |
| 576 | case ::ot_stream: | 571 | case ::ot_stream: |
| 577 | - std::get<QPDF_Stream>(value).m->stream_dict.writeJSON(json_version, p); | 572 | + std::get<QPDF_Stream>(obj->value).m->stream_dict.writeJSON(json_version, p); |
| 578 | break; | 573 | break; |
| 579 | case ::ot_reference: | 574 | case ::ot_reference: |
| 580 | - p << "\"" << getObjGen().unparse(' ') << " R\""; | 575 | + p << "\"" << obj->og.unparse(' ') << " R\""; |
| 581 | break; | 576 | break; |
| 582 | default: | 577 | default: |
| 583 | throw std::logic_error("attempted to write an unsuitable object as JSON"); | 578 | throw std::logic_error("attempted to write an unsuitable object as JSON"); |
| @@ -585,48 +580,49 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | @@ -585,48 +580,49 @@ QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 585 | } | 580 | } |
| 586 | 581 | ||
| 587 | void | 582 | void |
| 588 | -QPDFObject::disconnect() | 583 | +BaseHandle::disconnect(bool only_direct) |
| 589 | { | 584 | { |
| 590 | - // Disconnect an object from its owning QPDF. This is called by QPDF's destructor. | 585 | + // QPDF::~QPDF() calls disconnect for indirect objects, so we don't do that here. |
| 586 | + if (only_direct && indirect()) { | ||
| 587 | + return; | ||
| 588 | + } | ||
| 591 | 589 | ||
| 592 | - switch (getTypeCode()) { | 590 | + switch (raw_type_code()) { |
| 593 | case ::ot_array: | 591 | case ::ot_array: |
| 594 | { | 592 | { |
| 595 | - auto& a = std::get<QPDF_Array>(value); | 593 | + auto& a = std::get<QPDF_Array>(obj->value); |
| 596 | if (a.sp) { | 594 | if (a.sp) { |
| 597 | for (auto& item: a.sp->elements) { | 595 | for (auto& item: a.sp->elements) { |
| 598 | - auto& obj = item.second; | ||
| 599 | - if (!obj.indirect()) { | ||
| 600 | - obj.getObj()->disconnect(); | ||
| 601 | - } | 596 | + item.second.disconnect(); |
| 602 | } | 597 | } |
| 603 | } else { | 598 | } else { |
| 604 | - for (auto& obj: a.elements) { | ||
| 605 | - if (!obj.indirect()) { | ||
| 606 | - obj.getObj()->disconnect(); | ||
| 607 | - } | 599 | + for (auto& oh: a.elements) { |
| 600 | + oh.disconnect(); | ||
| 608 | } | 601 | } |
| 609 | } | 602 | } |
| 610 | } | 603 | } |
| 611 | break; | 604 | break; |
| 612 | case ::ot_dictionary: | 605 | case ::ot_dictionary: |
| 613 | - for (auto& iter: std::get<QPDF_Dictionary>(value).items) { | ||
| 614 | - QPDFObjectHandle::DisconnectAccess::disconnect(iter.second); | 606 | + for (auto& iter: std::get<QPDF_Dictionary>(obj->value).items) { |
| 607 | + iter.second.disconnect(); | ||
| 615 | } | 608 | } |
| 616 | break; | 609 | break; |
| 617 | case ::ot_stream: | 610 | case ::ot_stream: |
| 618 | { | 611 | { |
| 619 | - auto& s = std::get<QPDF_Stream>(value); | 612 | + auto& s = std::get<QPDF_Stream>(obj->value); |
| 620 | s.m->stream_provider = nullptr; | 613 | s.m->stream_provider = nullptr; |
| 621 | - QPDFObjectHandle::DisconnectAccess::disconnect(s.m->stream_dict); | 614 | + s.m->stream_dict.disconnect(); |
| 622 | } | 615 | } |
| 623 | break; | 616 | break; |
| 617 | + case ::ot_uninitialized: | ||
| 618 | + return; | ||
| 624 | default: | 619 | default: |
| 625 | break; | 620 | break; |
| 626 | } | 621 | } |
| 627 | - qpdf = nullptr; | ||
| 628 | - og = QPDFObjGen(); | 622 | + obj->qpdf = nullptr; |
| 623 | + obj->og = QPDFObjGen(); | ||
| 629 | } | 624 | } |
| 625 | + | ||
| 630 | std::string | 626 | std::string |
| 631 | QPDFObject::getStringValue() const | 627 | QPDFObject::getStringValue() const |
| 632 | { | 628 | { |
| @@ -654,16 +650,6 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const | @@ -654,16 +650,6 @@ QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const | ||
| 654 | { | 650 | { |
| 655 | return this->obj == rhs.obj; | 651 | return this->obj == rhs.obj; |
| 656 | } | 652 | } |
| 657 | -void | ||
| 658 | -QPDFObjectHandle::disconnect() | ||
| 659 | -{ | ||
| 660 | - // Recursively remove association with any QPDF object. This method may only be called during | ||
| 661 | - // final destruction. QPDF::~QPDF() calls it for indirect objects using the object pointer | ||
| 662 | - // itself, so we don't do that here. Other objects call it through this method. | ||
| 663 | - if (obj && !isIndirect()) { | ||
| 664 | - this->obj->disconnect(); | ||
| 665 | - } | ||
| 666 | -} | ||
| 667 | 653 | ||
| 668 | qpdf_object_type_e | 654 | qpdf_object_type_e |
| 669 | QPDFObjectHandle::getTypeCode() const | 655 | QPDFObjectHandle::getTypeCode() const |
| @@ -1439,7 +1425,7 @@ QPDFObjectHandle::unparseResolved() const | @@ -1439,7 +1425,7 @@ QPDFObjectHandle::unparseResolved() const | ||
| 1439 | if (!obj) { | 1425 | if (!obj) { |
| 1440 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); | 1426 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1441 | } | 1427 | } |
| 1442 | - return obj->unparse(); | 1428 | + return BaseHandle::unparse(); |
| 1443 | } | 1429 | } |
| 1444 | 1430 | ||
| 1445 | std::string | 1431 | std::string |
| @@ -1476,7 +1462,7 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_ | @@ -1476,7 +1462,7 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_ | ||
| 1476 | } else if (!obj) { | 1462 | } else if (!obj) { |
| 1477 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); | 1463 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1478 | } else { | 1464 | } else { |
| 1479 | - obj->write_json(json_version, p); | 1465 | + write_json(json_version, p); |
| 1480 | } | 1466 | } |
| 1481 | } | 1467 | } |
| 1482 | 1468 | ||
| @@ -1902,7 +1888,7 @@ QPDFObjectHandle::shallowCopy() | @@ -1902,7 +1888,7 @@ QPDFObjectHandle::shallowCopy() | ||
| 1902 | if (!obj) { | 1888 | if (!obj) { |
| 1903 | throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); | 1889 | throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); |
| 1904 | } | 1890 | } |
| 1905 | - return {obj->copy()}; | 1891 | + return {copy()}; |
| 1906 | } | 1892 | } |
| 1907 | 1893 | ||
| 1908 | QPDFObjectHandle | 1894 | QPDFObjectHandle |
| @@ -1911,7 +1897,7 @@ QPDFObjectHandle::unsafeShallowCopy() | @@ -1911,7 +1897,7 @@ QPDFObjectHandle::unsafeShallowCopy() | ||
| 1911 | if (!obj) { | 1897 | if (!obj) { |
| 1912 | throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); | 1898 | throw std::logic_error("operation attempted on uninitialized QPDFObjectHandle"); |
| 1913 | } | 1899 | } |
| 1914 | - return {obj->copy(true)}; | 1900 | + return {copy(true)}; |
| 1915 | } | 1901 | } |
| 1916 | 1902 | ||
| 1917 | void | 1903 | void |
| @@ -1926,7 +1912,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | @@ -1926,7 +1912,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | ||
| 1926 | } | 1912 | } |
| 1927 | 1913 | ||
| 1928 | if (isBool() || isInteger() || isName() || isNull() || isReal() || isString()) { | 1914 | if (isBool() || isInteger() || isName() || isNull() || isReal() || isString()) { |
| 1929 | - this->obj = obj->copy(true); | 1915 | + this->obj = copy(true); |
| 1930 | } else if (auto a = as_array(strict)) { | 1916 | } else if (auto a = as_array(strict)) { |
| 1931 | std::vector<QPDFObjectHandle> items; | 1917 | std::vector<QPDFObjectHandle> items; |
| 1932 | for (auto const& item: a) { | 1918 | for (auto const& item: a) { |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| @@ -358,7 +358,7 @@ namespace qpdf | @@ -358,7 +358,7 @@ namespace qpdf | ||
| 358 | inline bool | 358 | inline bool |
| 359 | BaseHandle::null() const | 359 | BaseHandle::null() const |
| 360 | { | 360 | { |
| 361 | - return !obj || obj->getResolvedTypeCode() == ::ot_null; | 361 | + return !obj || type_code() == ::ot_null; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | inline QPDF* | 364 | inline QPDF* |
| @@ -383,7 +383,7 @@ namespace qpdf | @@ -383,7 +383,7 @@ namespace qpdf | ||
| 383 | return QPDF::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode(); | 383 | return QPDF::Resolver::resolved(obj->qpdf, obj->og)->getTypeCode(); |
| 384 | } | 384 | } |
| 385 | if (raw_type_code() == ::ot_reference) { | 385 | if (raw_type_code() == ::ot_reference) { |
| 386 | - return std::get<QPDF_Reference>(obj->value).obj->getResolvedTypeCode(); | 386 | + return std::get<QPDF_Reference>(obj->value).obj->getTypeCode(); |
| 387 | } | 387 | } |
| 388 | return raw_type_code(); | 388 | return raw_type_code(); |
| 389 | } | 389 | } |
libqpdf/qpdf/QPDFObject_private.hh
| @@ -18,6 +18,7 @@ | @@ -18,6 +18,7 @@ | ||
| 18 | #include <variant> | 18 | #include <variant> |
| 19 | #include <vector> | 19 | #include <vector> |
| 20 | 20 | ||
| 21 | +class Disconnect; | ||
| 21 | class QPDFObject; | 22 | class QPDFObject; |
| 22 | class QPDFObjectHandle; | 23 | class QPDFObjectHandle; |
| 23 | 24 | ||
| @@ -50,7 +51,9 @@ class QPDF_Array final | @@ -50,7 +51,9 @@ class QPDF_Array final | ||
| 50 | 51 | ||
| 51 | private: | 52 | private: |
| 52 | friend class QPDFObject; | 53 | friend class QPDFObject; |
| 54 | + friend class qpdf::BaseHandle; | ||
| 53 | friend class qpdf::Array; | 55 | friend class qpdf::Array; |
| 56 | + | ||
| 54 | QPDF_Array(std::vector<QPDFObjectHandle> const& items) : | 57 | QPDF_Array(std::vector<QPDFObjectHandle> const& items) : |
| 55 | elements(items) | 58 | elements(items) |
| 56 | { | 59 | { |
| @@ -75,6 +78,7 @@ class QPDF_Array final | @@ -75,6 +78,7 @@ class QPDF_Array final | ||
| 75 | class QPDF_Bool final | 78 | class QPDF_Bool final |
| 76 | { | 79 | { |
| 77 | friend class QPDFObject; | 80 | friend class QPDFObject; |
| 81 | + friend class qpdf::BaseHandle; | ||
| 78 | friend class QPDFObjectHandle; | 82 | friend class QPDFObjectHandle; |
| 79 | 83 | ||
| 80 | explicit QPDF_Bool(bool val) : | 84 | explicit QPDF_Bool(bool val) : |
| @@ -92,6 +96,7 @@ class QPDF_Dictionary final | @@ -92,6 +96,7 @@ class QPDF_Dictionary final | ||
| 92 | { | 96 | { |
| 93 | friend class QPDFObject; | 97 | friend class QPDFObject; |
| 94 | friend class qpdf::BaseDictionary; | 98 | friend class qpdf::BaseDictionary; |
| 99 | + friend class qpdf::BaseHandle; | ||
| 95 | 100 | ||
| 96 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items) : | 101 | QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items) : |
| 97 | items(items) | 102 | items(items) |
| @@ -105,6 +110,7 @@ class QPDF_Dictionary final | @@ -105,6 +110,7 @@ class QPDF_Dictionary final | ||
| 105 | class QPDF_InlineImage final | 110 | class QPDF_InlineImage final |
| 106 | { | 111 | { |
| 107 | friend class QPDFObject; | 112 | friend class QPDFObject; |
| 113 | + friend class qpdf::BaseHandle; | ||
| 108 | 114 | ||
| 109 | explicit QPDF_InlineImage(std::string val) : | 115 | explicit QPDF_InlineImage(std::string val) : |
| 110 | val(std::move(val)) | 116 | val(std::move(val)) |
| @@ -116,6 +122,7 @@ class QPDF_InlineImage final | @@ -116,6 +122,7 @@ class QPDF_InlineImage final | ||
| 116 | class QPDF_Integer final | 122 | class QPDF_Integer final |
| 117 | { | 123 | { |
| 118 | friend class QPDFObject; | 124 | friend class QPDFObject; |
| 125 | + friend class qpdf::BaseHandle; | ||
| 119 | friend class QPDFObjectHandle; | 126 | friend class QPDFObjectHandle; |
| 120 | 127 | ||
| 121 | QPDF_Integer(long long val) : | 128 | QPDF_Integer(long long val) : |
| @@ -128,6 +135,7 @@ class QPDF_Integer final | @@ -128,6 +135,7 @@ class QPDF_Integer final | ||
| 128 | class QPDF_Name final | 135 | class QPDF_Name final |
| 129 | { | 136 | { |
| 130 | friend class QPDFObject; | 137 | friend class QPDFObject; |
| 138 | + friend class qpdf::BaseHandle; | ||
| 131 | 139 | ||
| 132 | explicit QPDF_Name(std::string name) : | 140 | explicit QPDF_Name(std::string name) : |
| 133 | name(std::move(name)) | 141 | name(std::move(name)) |
| @@ -139,6 +147,7 @@ class QPDF_Name final | @@ -139,6 +147,7 @@ class QPDF_Name final | ||
| 139 | class QPDF_Null final | 147 | class QPDF_Null final |
| 140 | { | 148 | { |
| 141 | friend class QPDFObject; | 149 | friend class QPDFObject; |
| 150 | + friend class qpdf::BaseHandle; | ||
| 142 | 151 | ||
| 143 | public: | 152 | public: |
| 144 | static inline std::shared_ptr<QPDFObject> create( | 153 | static inline std::shared_ptr<QPDFObject> create( |
| @@ -150,6 +159,7 @@ class QPDF_Null final | @@ -150,6 +159,7 @@ class QPDF_Null final | ||
| 150 | class QPDF_Operator final | 159 | class QPDF_Operator final |
| 151 | { | 160 | { |
| 152 | friend class QPDFObject; | 161 | friend class QPDFObject; |
| 162 | + friend class qpdf::BaseHandle; | ||
| 153 | 163 | ||
| 154 | QPDF_Operator(std::string val) : | 164 | QPDF_Operator(std::string val) : |
| 155 | val(std::move(val)) | 165 | val(std::move(val)) |
| @@ -162,6 +172,7 @@ class QPDF_Operator final | @@ -162,6 +172,7 @@ class QPDF_Operator final | ||
| 162 | class QPDF_Real final | 172 | class QPDF_Real final |
| 163 | { | 173 | { |
| 164 | friend class QPDFObject; | 174 | friend class QPDFObject; |
| 175 | + friend class qpdf::BaseHandle; | ||
| 165 | 176 | ||
| 166 | QPDF_Real(std::string val) : | 177 | QPDF_Real(std::string val) : |
| 167 | val(std::move(val)) | 178 | val(std::move(val)) |
| @@ -199,6 +210,7 @@ class QPDF_Stream final | @@ -199,6 +210,7 @@ class QPDF_Stream final | ||
| 199 | friend class QPDF_Stream; | 210 | friend class QPDF_Stream; |
| 200 | friend class QPDFObject; | 211 | friend class QPDFObject; |
| 201 | friend class qpdf::Stream; | 212 | friend class qpdf::Stream; |
| 213 | + friend class qpdf::BaseHandle; | ||
| 202 | 214 | ||
| 203 | public: | 215 | public: |
| 204 | Members(QPDFObjectHandle stream_dict, size_t length) : | 216 | Members(QPDFObjectHandle stream_dict, size_t length) : |
| @@ -217,6 +229,7 @@ class QPDF_Stream final | @@ -217,6 +229,7 @@ class QPDF_Stream final | ||
| 217 | }; | 229 | }; |
| 218 | 230 | ||
| 219 | friend class QPDFObject; | 231 | friend class QPDFObject; |
| 232 | + friend class qpdf::BaseHandle; | ||
| 220 | friend class qpdf::Stream; | 233 | friend class qpdf::Stream; |
| 221 | 234 | ||
| 222 | QPDF_Stream(QPDFObjectHandle stream_dict, size_t length) : | 235 | QPDF_Stream(QPDFObjectHandle stream_dict, size_t length) : |
| @@ -235,6 +248,7 @@ class QPDF_Stream final | @@ -235,6 +248,7 @@ class QPDF_Stream final | ||
| 235 | class QPDF_String final | 248 | class QPDF_String final |
| 236 | { | 249 | { |
| 237 | friend class QPDFObject; | 250 | friend class QPDFObject; |
| 251 | + friend class qpdf::BaseHandle; | ||
| 238 | friend class QPDFWriter; | 252 | friend class QPDFWriter; |
| 239 | 253 | ||
| 240 | public: | 254 | public: |
| @@ -284,10 +298,6 @@ class QPDFObject | @@ -284,10 +298,6 @@ class QPDFObject | ||
| 284 | qpdf, og, std::forward<T>(T(std::forward<Args>(args)...))); | 298 | qpdf, og, std::forward<T>(T(std::forward<Args>(args)...))); |
| 285 | } | 299 | } |
| 286 | 300 | ||
| 287 | - std::shared_ptr<QPDFObject> copy(bool shallow = false); | ||
| 288 | - std::string unparse(); | ||
| 289 | - void write_json(int json_version, JSON::Writer& p); | ||
| 290 | - void disconnect(); | ||
| 291 | std::string getStringValue() const; | 301 | std::string getStringValue() const; |
| 292 | 302 | ||
| 293 | // Return a unique type code for the resolved object | 303 | // Return a unique type code for the resolved object |
| @@ -298,7 +308,7 @@ class QPDFObject | @@ -298,7 +308,7 @@ class QPDFObject | ||
| 298 | return QPDF::Resolver::resolved(qpdf, og)->getTypeCode(); | 308 | return QPDF::Resolver::resolved(qpdf, og)->getTypeCode(); |
| 299 | } | 309 | } |
| 300 | if (getTypeCode() == ::ot_reference) { | 310 | if (getTypeCode() == ::ot_reference) { |
| 301 | - return std::get<QPDF_Reference>(value).obj->getResolvedTypeCode(); | 311 | + return std::get<QPDF_Reference>(value).obj->getTypeCode(); |
| 302 | } | 312 | } |
| 303 | return getTypeCode(); | 313 | return getTypeCode(); |
| 304 | } | 314 | } |
| @@ -344,23 +354,12 @@ class QPDFObject | @@ -344,23 +354,12 @@ class QPDFObject | ||
| 344 | qpdf = a_qpdf; | 354 | qpdf = a_qpdf; |
| 345 | og = a_og; | 355 | og = a_og; |
| 346 | } | 356 | } |
| 347 | - // Mark an object as destroyed. Used by QPDF's destructor for its indirect objects. | ||
| 348 | - void | ||
| 349 | - destroy() | ||
| 350 | - { | ||
| 351 | - value = QPDF_Destroyed(); | ||
| 352 | - } | ||
| 353 | 357 | ||
| 354 | bool | 358 | bool |
| 355 | isUnresolved() const | 359 | isUnresolved() const |
| 356 | { | 360 | { |
| 357 | return getTypeCode() == ::ot_unresolved; | 361 | return getTypeCode() == ::ot_unresolved; |
| 358 | } | 362 | } |
| 359 | - const QPDFObject* | ||
| 360 | - resolved_object() const | ||
| 361 | - { | ||
| 362 | - return isUnresolved() ? QPDF::Resolver::resolved(qpdf, og).get() : this; | ||
| 363 | - } | ||
| 364 | 363 | ||
| 365 | struct JSON_Descr | 364 | struct JSON_Descr |
| 366 | { | 365 | { |
| @@ -457,6 +456,7 @@ class QPDFObject | @@ -457,6 +456,7 @@ class QPDFObject | ||
| 457 | private: | 456 | private: |
| 458 | friend class QPDF_Stream; | 457 | friend class QPDF_Stream; |
| 459 | friend class qpdf::BaseHandle; | 458 | friend class qpdf::BaseHandle; |
| 459 | + friend class Disconnect; | ||
| 460 | 460 | ||
| 461 | typedef std::variant< | 461 | typedef std::variant< |
| 462 | std::monostate, | 462 | std::monostate, |
libtests/sparse_array.cc
| @@ -95,12 +95,14 @@ main() | @@ -95,12 +95,14 @@ main() | ||
| 95 | assert(b.at(3).second.isNull()); | 95 | assert(b.at(3).second.isNull()); |
| 96 | assert(b.at(8).second.isNull()); | 96 | assert(b.at(8).second.isNull()); |
| 97 | assert(b.at(5).second.isIndirect()); | 97 | assert(b.at(5).second.isIndirect()); |
| 98 | - assert(obj->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); | ||
| 99 | - auto c = obj->copy(true); | ||
| 100 | - auto d = obj->copy(false); | 98 | + assert( |
| 99 | + QPDFObjectHandle(obj).unparse() == | ||
| 100 | + "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); | ||
| 101 | + auto c = QPDFObjectHandle(obj).unsafeShallowCopy(); | ||
| 102 | + auto d = QPDFObjectHandle(obj).shallowCopy(); | ||
| 101 | b.at(7).second.setArrayItem(2, "42"_qpdf); | 103 | 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 ]"); | ||
| 103 | - assert(d->unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); | 104 | + assert(c.unparse() == "[ null null null null null 3 0 R null [ 0 1 42 3 ] null null ]"); |
| 105 | + assert(d.unparse() == "[ null null null null null 3 0 R null [ 0 1 2 3 ] null null ]"); | ||
| 104 | 106 | ||
| 105 | try { | 107 | try { |
| 106 | b.setAt(3, {}); | 108 | b.setAt(3, {}); |