Commit 8d7ed7644e4ac27ccdf456ad779540f73612bd6a
1 parent
3b90f899
Refactor QPDFObject to use std::variant instead of std::shared_pointer
Showing
46 changed files
with
1066 additions
and
1728 deletions
include/qpdf/Constants.h
| @@ -126,6 +126,7 @@ enum qpdf_object_type_e { | @@ -126,6 +126,7 @@ enum qpdf_object_type_e { | ||
| 126 | /* Object types internal to qpdf */ | 126 | /* Object types internal to qpdf */ |
| 127 | ot_unresolved, | 127 | ot_unresolved, |
| 128 | ot_destroyed, | 128 | ot_destroyed, |
| 129 | + ot_reference, | ||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | /* Write Parameters. See QPDFWriter.hh for details. */ | 132 | /* Write Parameters. See QPDFWriter.hh for details. */ |
include/qpdf/QPDF.hh
| @@ -1087,7 +1087,8 @@ class QPDF | @@ -1087,7 +1087,8 @@ class QPDF | ||
| 1087 | QPDFObjGen og, | 1087 | QPDFObjGen og, |
| 1088 | std::shared_ptr<QPDFObject> const& object, | 1088 | std::shared_ptr<QPDFObject> const& object, |
| 1089 | qpdf_offset_t end_before_space, | 1089 | qpdf_offset_t end_before_space, |
| 1090 | - qpdf_offset_t end_after_space); | 1090 | + qpdf_offset_t end_after_space, |
| 1091 | + bool destroy = true); | ||
| 1091 | static QPDFExc damagedPDF( | 1092 | static QPDFExc damagedPDF( |
| 1092 | InputSource& input, | 1093 | InputSource& input, |
| 1093 | std::string const& object, | 1094 | std::string const& object, |
include/qpdf/QPDFObjectHandle.hh
| @@ -1254,8 +1254,7 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | @@ -1254,8 +1254,7 @@ class QPDFObjectHandle final: public qpdf::BaseHandle | ||
| 1254 | // Provide access to specific classes for recursive disconnected(). | 1254 | // Provide access to specific classes for recursive disconnected(). |
| 1255 | class DisconnectAccess | 1255 | class DisconnectAccess |
| 1256 | { | 1256 | { |
| 1257 | - friend class QPDF_Dictionary; | ||
| 1258 | - friend class QPDF_Stream; | 1257 | + friend class QPDFObject; |
| 1259 | 1258 | ||
| 1260 | private: | 1259 | private: |
| 1261 | static void | 1260 | static void |
include/qpdf/QPDFObjectHandle_future.hh deleted
libqpdf/CMakeLists.txt
| @@ -86,23 +86,12 @@ set(libqpdf_SOURCES | @@ -86,23 +86,12 @@ set(libqpdf_SOURCES | ||
| 86 | QPDFSystemError.cc | 86 | QPDFSystemError.cc |
| 87 | QPDFTokenizer.cc | 87 | QPDFTokenizer.cc |
| 88 | QPDFUsage.cc | 88 | QPDFUsage.cc |
| 89 | - QPDFValue.cc | ||
| 90 | QPDFWriter.cc | 89 | QPDFWriter.cc |
| 91 | QPDFXRefEntry.cc | 90 | QPDFXRefEntry.cc |
| 92 | QPDF_Array.cc | 91 | QPDF_Array.cc |
| 93 | - QPDF_Bool.cc | ||
| 94 | - QPDF_Destroyed.cc | ||
| 95 | QPDF_Dictionary.cc | 92 | QPDF_Dictionary.cc |
| 96 | - QPDF_InlineImage.cc | ||
| 97 | - QPDF_Integer.cc | ||
| 98 | - QPDF_Name.cc | ||
| 99 | - QPDF_Null.cc | ||
| 100 | - QPDF_Operator.cc | ||
| 101 | - QPDF_Real.cc | ||
| 102 | - QPDF_Reserved.cc | ||
| 103 | QPDF_Stream.cc | 93 | QPDF_Stream.cc |
| 104 | QPDF_String.cc | 94 | QPDF_String.cc |
| 105 | - QPDF_Unresolved.cc | ||
| 106 | QPDF_encryption.cc | 95 | QPDF_encryption.cc |
| 107 | QPDF_json.cc | 96 | QPDF_json.cc |
| 108 | QPDF_linearization.cc | 97 | QPDF_linearization.cc |
libqpdf/QPDF.cc
| @@ -20,11 +20,6 @@ | @@ -20,11 +20,6 @@ | ||
| 20 | #include <qpdf/QPDFObjectHandle_private.hh> | 20 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 21 | #include <qpdf/QPDFObject_private.hh> | 21 | #include <qpdf/QPDFObject_private.hh> |
| 22 | #include <qpdf/QPDFParser.hh> | 22 | #include <qpdf/QPDFParser.hh> |
| 23 | -#include <qpdf/QPDF_Dictionary.hh> | ||
| 24 | -#include <qpdf/QPDF_Null.hh> | ||
| 25 | -#include <qpdf/QPDF_Reserved.hh> | ||
| 26 | -#include <qpdf/QPDF_Stream.hh> | ||
| 27 | -#include <qpdf/QPDF_Unresolved.hh> | ||
| 28 | #include <qpdf/QTC.hh> | 23 | #include <qpdf/QTC.hh> |
| 29 | #include <qpdf/QUtil.hh> | 24 | #include <qpdf/QUtil.hh> |
| 30 | 25 | ||
| @@ -1565,7 +1560,7 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset) | @@ -1565,7 +1560,7 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset) | ||
| 1565 | throw; | 1560 | throw; |
| 1566 | } | 1561 | } |
| 1567 | } | 1562 | } |
| 1568 | - object = {QPDF_Stream::create(this, og, object, stream_offset, length)}; | 1563 | + object = QPDFObjectHandle(qpdf::Stream(*this, og, object, stream_offset, length)); |
| 1569 | } | 1564 | } |
| 1570 | 1565 | ||
| 1571 | void | 1566 | void |
| @@ -1884,7 +1879,7 @@ QPDF::resolve(QPDFObjGen og) | @@ -1884,7 +1879,7 @@ QPDF::resolve(QPDFObjGen og) | ||
| 1884 | // has to be resolved during object parsing, such as stream length. | 1879 | // has to be resolved during object parsing, such as stream length. |
| 1885 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); | 1880 | QTC::TC("qpdf", "QPDF recursion loop in resolve"); |
| 1886 | warn(damagedPDF("", "loop detected resolving object " + og.unparse(' '))); | 1881 | warn(damagedPDF("", "loop detected resolving object " + og.unparse(' '))); |
| 1887 | - updateCache(og, QPDF_Null::create(), -1, -1); | 1882 | + updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); |
| 1888 | return m->obj_cache[og].object.get(); | 1883 | return m->obj_cache[og].object.get(); |
| 1889 | } | 1884 | } |
| 1890 | ResolveRecorder rr(this, og); | 1885 | ResolveRecorder rr(this, og); |
| @@ -1921,7 +1916,7 @@ QPDF::resolve(QPDFObjGen og) | @@ -1921,7 +1916,7 @@ QPDF::resolve(QPDFObjGen og) | ||
| 1921 | if (isUnresolved(og)) { | 1916 | if (isUnresolved(og)) { |
| 1922 | // PDF spec says unknown objects resolve to the null object. | 1917 | // PDF spec says unknown objects resolve to the null object. |
| 1923 | QTC::TC("qpdf", "QPDF resolve failure to null"); | 1918 | QTC::TC("qpdf", "QPDF resolve failure to null"); |
| 1924 | - updateCache(og, QPDF_Null::create(), -1, -1); | 1919 | + updateCache(og, QPDFObject::create<QPDF_Null>(), -1, -1); |
| 1925 | } | 1920 | } |
| 1926 | 1921 | ||
| 1927 | auto result(m->obj_cache[og].object); | 1922 | auto result(m->obj_cache[og].object); |
| @@ -2034,12 +2029,13 @@ QPDF::updateCache( | @@ -2034,12 +2029,13 @@ QPDF::updateCache( | ||
| 2034 | QPDFObjGen og, | 2029 | QPDFObjGen og, |
| 2035 | std::shared_ptr<QPDFObject> const& object, | 2030 | std::shared_ptr<QPDFObject> const& object, |
| 2036 | qpdf_offset_t end_before_space, | 2031 | qpdf_offset_t end_before_space, |
| 2037 | - qpdf_offset_t end_after_space) | 2032 | + qpdf_offset_t end_after_space, |
| 2033 | + bool destroy) | ||
| 2038 | { | 2034 | { |
| 2039 | object->setObjGen(this, og); | 2035 | object->setObjGen(this, og); |
| 2040 | if (isCached(og)) { | 2036 | if (isCached(og)) { |
| 2041 | auto& cache = m->obj_cache[og]; | 2037 | auto& cache = m->obj_cache[og]; |
| 2042 | - cache.object->assign(object); | 2038 | + object->move_to(cache.object, destroy); |
| 2043 | cache.end_before_space = end_before_space; | 2039 | cache.end_before_space = end_before_space; |
| 2044 | cache.end_after_space = end_after_space; | 2040 | cache.end_after_space = end_after_space; |
| 2045 | } else { | 2041 | } else { |
| @@ -2089,20 +2085,20 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) | @@ -2089,20 +2085,20 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh) | ||
| 2089 | QPDFObjectHandle | 2085 | QPDFObjectHandle |
| 2090 | QPDF::newReserved() | 2086 | QPDF::newReserved() |
| 2091 | { | 2087 | { |
| 2092 | - return makeIndirectFromQPDFObject(QPDF_Reserved::create()); | 2088 | + return makeIndirectFromQPDFObject(QPDFObject::create<QPDF_Reserved>()); |
| 2093 | } | 2089 | } |
| 2094 | 2090 | ||
| 2095 | QPDFObjectHandle | 2091 | QPDFObjectHandle |
| 2096 | QPDF::newIndirectNull() | 2092 | QPDF::newIndirectNull() |
| 2097 | { | 2093 | { |
| 2098 | - return makeIndirectFromQPDFObject(QPDF_Null::create()); | 2094 | + return makeIndirectFromQPDFObject(QPDFObject::create<QPDF_Null>()); |
| 2099 | } | 2095 | } |
| 2100 | 2096 | ||
| 2101 | QPDFObjectHandle | 2097 | QPDFObjectHandle |
| 2102 | QPDF::newStream() | 2098 | QPDF::newStream() |
| 2103 | { | 2099 | { |
| 2104 | - return makeIndirectFromQPDFObject( | ||
| 2105 | - QPDF_Stream::create(this, nextObjGen(), QPDFObjectHandle::newDictionary(), 0, 0)); | 2100 | + return makeIndirectObject( |
| 2101 | + qpdf::Stream(*this, nextObjGen(), QPDFObjectHandle::newDictionary(), 0, 0)); | ||
| 2106 | } | 2102 | } |
| 2107 | 2103 | ||
| 2108 | QPDFObjectHandle | 2104 | QPDFObjectHandle |
| @@ -2130,12 +2126,13 @@ QPDF::getObjectForParser(int id, int gen, bool parse_pdf) | @@ -2130,12 +2126,13 @@ QPDF::getObjectForParser(int id, int gen, bool parse_pdf) | ||
| 2130 | return iter->second.object; | 2126 | return iter->second.object; |
| 2131 | } | 2127 | } |
| 2132 | if (m->xref_table.count(og) || !m->parsed) { | 2128 | if (m->xref_table.count(og) || !m->parsed) { |
| 2133 | - return m->obj_cache.insert({og, QPDF_Unresolved::create(this, og)}).first->second.object; | 2129 | + return m->obj_cache.insert({og, QPDFObject::create<QPDF_Unresolved>(this, og)}) |
| 2130 | + .first->second.object; | ||
| 2134 | } | 2131 | } |
| 2135 | if (parse_pdf) { | 2132 | if (parse_pdf) { |
| 2136 | - return QPDF_Null::create(); | 2133 | + return QPDFObject::create<QPDF_Null>(); |
| 2137 | } | 2134 | } |
| 2138 | - return m->obj_cache.insert({og, QPDF_Null::create(this, og)}).first->second.object; | 2135 | + return m->obj_cache.insert({og, QPDFObject::create<QPDF_Null>(this, og)}).first->second.object; |
| 2139 | } | 2136 | } |
| 2140 | 2137 | ||
| 2141 | std::shared_ptr<QPDFObject> | 2138 | std::shared_ptr<QPDFObject> |
| @@ -2145,8 +2142,9 @@ QPDF::getObjectForJSON(int id, int gen) | @@ -2145,8 +2142,9 @@ QPDF::getObjectForJSON(int id, int gen) | ||
| 2145 | auto [it, inserted] = m->obj_cache.try_emplace(og); | 2142 | auto [it, inserted] = m->obj_cache.try_emplace(og); |
| 2146 | auto& obj = it->second.object; | 2143 | auto& obj = it->second.object; |
| 2147 | if (inserted) { | 2144 | if (inserted) { |
| 2148 | - obj = (m->parsed && !m->xref_table.count(og)) ? QPDF_Null::create(this, og) | ||
| 2149 | - : QPDF_Unresolved::create(this, og); | 2145 | + obj = (m->parsed && !m->xref_table.count(og)) |
| 2146 | + ? QPDFObject::create<QPDF_Null>(this, og) | ||
| 2147 | + : QPDFObject::create<QPDF_Unresolved>(this, og); | ||
| 2150 | } | 2148 | } |
| 2151 | return obj; | 2149 | return obj; |
| 2152 | } | 2150 | } |
| @@ -2157,9 +2155,10 @@ QPDF::getObject(QPDFObjGen og) | @@ -2157,9 +2155,10 @@ QPDF::getObject(QPDFObjGen og) | ||
| 2157 | if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) { | 2155 | if (auto it = m->obj_cache.find(og); it != m->obj_cache.end()) { |
| 2158 | return {it->second.object}; | 2156 | return {it->second.object}; |
| 2159 | } else if (m->parsed && !m->xref_table.count(og)) { | 2157 | } else if (m->parsed && !m->xref_table.count(og)) { |
| 2160 | - return QPDF_Null::create(); | 2158 | + return QPDFObject::create<QPDF_Null>(); |
| 2161 | } else { | 2159 | } else { |
| 2162 | - auto result = m->obj_cache.try_emplace(og, QPDF_Unresolved::create(this, og), -1, -1); | 2160 | + auto result = |
| 2161 | + m->obj_cache.try_emplace(og, QPDFObject::create<QPDF_Unresolved>(this, og), -1, -1); | ||
| 2163 | return {result.first->second.object}; | 2162 | return {result.first->second.object}; |
| 2164 | } | 2163 | } |
| 2165 | } | 2164 | } |
| @@ -2195,7 +2194,7 @@ QPDF::replaceObject(QPDFObjGen og, QPDFObjectHandle oh) | @@ -2195,7 +2194,7 @@ QPDF::replaceObject(QPDFObjGen og, QPDFObjectHandle oh) | ||
| 2195 | QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); | 2194 | QTC::TC("qpdf", "QPDF replaceObject called with indirect object"); |
| 2196 | throw std::logic_error("QPDF::replaceObject called with indirect object handle"); | 2195 | throw std::logic_error("QPDF::replaceObject called with indirect object handle"); |
| 2197 | } | 2196 | } |
| 2198 | - updateCache(og, oh.getObj(), -1, -1); | 2197 | + updateCache(og, oh.getObj(), -1, -1, false); |
| 2199 | } | 2198 | } |
| 2200 | 2199 | ||
| 2201 | void | 2200 | void |
| @@ -2204,7 +2203,7 @@ QPDF::removeObject(QPDFObjGen og) | @@ -2204,7 +2203,7 @@ QPDF::removeObject(QPDFObjGen og) | ||
| 2204 | m->xref_table.erase(og); | 2203 | m->xref_table.erase(og); |
| 2205 | if (auto cached = m->obj_cache.find(og); cached != m->obj_cache.end()) { | 2204 | if (auto cached = m->obj_cache.find(og); cached != m->obj_cache.end()) { |
| 2206 | // Take care of any object handles that may be floating around. | 2205 | // Take care of any object handles that may be floating around. |
| 2207 | - cached->second.object->assign(QPDF_Null::create()); | 2206 | + cached->second.object->assign_null(); |
| 2208 | cached->second.object->setObjGen(nullptr, QPDFObjGen()); | 2207 | cached->second.object->setObjGen(nullptr, QPDFObjGen()); |
| 2209 | m->obj_cache.erase(cached); | 2208 | m->obj_cache.erase(cached); |
| 2210 | } | 2209 | } |
libqpdf/QPDFObject.cc
| 1 | #include <qpdf/QPDFObject_private.hh> | 1 | #include <qpdf/QPDFObject_private.hh> |
| 2 | 2 | ||
| 3 | -#include <qpdf/QPDF.hh> | ||
| 4 | -#include <qpdf/QPDF_Destroyed.hh> | ||
| 5 | - | ||
| 6 | -void | ||
| 7 | -QPDFObject::destroy() | 3 | +std::string |
| 4 | +QPDFObject::getDescription() | ||
| 8 | { | 5 | { |
| 9 | - value = QPDF_Destroyed::getInstance(); | 6 | + if (object_description) { |
| 7 | + switch (object_description->index()) { | ||
| 8 | + case 0: | ||
| 9 | + { | ||
| 10 | + // Simple template string | ||
| 11 | + auto description = std::get<0>(*object_description); | ||
| 12 | + | ||
| 13 | + if (auto pos = description.find("$OG"); pos != std::string::npos) { | ||
| 14 | + description.replace(pos, 3, og.unparse(' ')); | ||
| 15 | + } | ||
| 16 | + if (auto pos = description.find("$PO"); pos != std::string::npos) { | ||
| 17 | + qpdf_offset_t shift = (getTypeCode() == ::ot_dictionary) ? 2 | ||
| 18 | + : (getTypeCode() == ::ot_array) ? 1 | ||
| 19 | + : 0; | ||
| 20 | + | ||
| 21 | + description.replace(pos, 3, std::to_string(parsed_offset + shift)); | ||
| 22 | + } | ||
| 23 | + return description; | ||
| 24 | + } | ||
| 25 | + case 1: | ||
| 26 | + { | ||
| 27 | + // QPDF::JSONReactor generated description | ||
| 28 | + auto j_descr = std::get<1>(*object_description); | ||
| 29 | + return ( | ||
| 30 | + *j_descr.input + (j_descr.object.empty() ? "" : ", " + j_descr.object) + | ||
| 31 | + " at offset " + std::to_string(parsed_offset)); | ||
| 32 | + } | ||
| 33 | + case 2: | ||
| 34 | + { | ||
| 35 | + // Child object description | ||
| 36 | + auto j_descr = std::get<2>(*object_description); | ||
| 37 | + std::string result; | ||
| 38 | + if (auto p = j_descr.parent.lock()) { | ||
| 39 | + result = p->getDescription(); | ||
| 40 | + } | ||
| 41 | + result += j_descr.static_descr; | ||
| 42 | + if (auto pos = result.find("$VD"); pos != std::string::npos) { | ||
| 43 | + result.replace(pos, 3, j_descr.var_descr); | ||
| 44 | + } | ||
| 45 | + return result; | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | + } else if (og.isIndirect()) { | ||
| 49 | + return "object " + og.unparse(' '); | ||
| 50 | + } | ||
| 51 | + return {}; | ||
| 10 | } | 52 | } |
libqpdf/QPDFObjectHandle.cc
| @@ -11,19 +11,6 @@ | @@ -11,19 +11,6 @@ | ||
| 11 | #include <qpdf/QPDFObject_private.hh> | 11 | #include <qpdf/QPDFObject_private.hh> |
| 12 | #include <qpdf/QPDFPageObjectHelper.hh> | 12 | #include <qpdf/QPDFPageObjectHelper.hh> |
| 13 | #include <qpdf/QPDFParser.hh> | 13 | #include <qpdf/QPDFParser.hh> |
| 14 | -#include <qpdf/QPDF_Array.hh> | ||
| 15 | -#include <qpdf/QPDF_Bool.hh> | ||
| 16 | -#include <qpdf/QPDF_Dictionary.hh> | ||
| 17 | -#include <qpdf/QPDF_InlineImage.hh> | ||
| 18 | -#include <qpdf/QPDF_Integer.hh> | ||
| 19 | -#include <qpdf/QPDF_Name.hh> | ||
| 20 | -#include <qpdf/QPDF_Null.hh> | ||
| 21 | -#include <qpdf/QPDF_Operator.hh> | ||
| 22 | -#include <qpdf/QPDF_Real.hh> | ||
| 23 | -#include <qpdf/QPDF_Reserved.hh> | ||
| 24 | -#include <qpdf/QPDF_Stream.hh> | ||
| 25 | -#include <qpdf/QPDF_String.hh> | ||
| 26 | -#include <qpdf/QPDF_Unresolved.hh> | ||
| 27 | 14 | ||
| 28 | #include <qpdf/QIntC.hh> | 15 | #include <qpdf/QIntC.hh> |
| 29 | #include <qpdf/QTC.hh> | 16 | #include <qpdf/QTC.hh> |
| @@ -228,6 +215,443 @@ LastChar::getLastChar() | @@ -228,6 +215,443 @@ LastChar::getLastChar() | ||
| 228 | return this->last_char; | 215 | return this->last_char; |
| 229 | } | 216 | } |
| 230 | 217 | ||
| 218 | +std::pair<bool, bool> | ||
| 219 | +Name::analyzeJSONEncoding(const std::string& name) | ||
| 220 | +{ | ||
| 221 | + int tail = 0; // Number of continuation characters expected. | ||
| 222 | + bool tail2 = false; // Potential overlong 3 octet utf-8. | ||
| 223 | + bool tail3 = false; // potential overlong 4 octet | ||
| 224 | + bool needs_escaping = false; | ||
| 225 | + for (auto const& it: name) { | ||
| 226 | + auto c = static_cast<unsigned char>(it); | ||
| 227 | + if (tail) { | ||
| 228 | + if ((c & 0xc0) != 0x80) { | ||
| 229 | + return {false, false}; | ||
| 230 | + } | ||
| 231 | + if (tail2) { | ||
| 232 | + if ((c & 0xe0) == 0x80) { | ||
| 233 | + return {false, false}; | ||
| 234 | + } | ||
| 235 | + tail2 = false; | ||
| 236 | + } else if (tail3) { | ||
| 237 | + if ((c & 0xf0) == 0x80) { | ||
| 238 | + return {false, false}; | ||
| 239 | + } | ||
| 240 | + tail3 = false; | ||
| 241 | + } | ||
| 242 | + tail--; | ||
| 243 | + } else if (c < 0x80) { | ||
| 244 | + if (!needs_escaping) { | ||
| 245 | + needs_escaping = !((c > 34 && c != '\\') || c == ' ' || c == 33); | ||
| 246 | + } | ||
| 247 | + } else if ((c & 0xe0) == 0xc0) { | ||
| 248 | + if ((c & 0xfe) == 0xc0) { | ||
| 249 | + return {false, false}; | ||
| 250 | + } | ||
| 251 | + tail = 1; | ||
| 252 | + } else if ((c & 0xf0) == 0xe0) { | ||
| 253 | + tail2 = (c == 0xe0); | ||
| 254 | + tail = 2; | ||
| 255 | + } else if ((c & 0xf8) == 0xf0) { | ||
| 256 | + tail3 = (c == 0xf0); | ||
| 257 | + tail = 3; | ||
| 258 | + } else { | ||
| 259 | + return {false, false}; | ||
| 260 | + } | ||
| 261 | + } | ||
| 262 | + return {tail == 0, !needs_escaping}; | ||
| 263 | +} | ||
| 264 | + | ||
| 265 | +std::string | ||
| 266 | +Name::normalize(std::string const& name) | ||
| 267 | +{ | ||
| 268 | + if (name.empty()) { | ||
| 269 | + return name; | ||
| 270 | + } | ||
| 271 | + std::string result; | ||
| 272 | + result += name.at(0); | ||
| 273 | + for (size_t i = 1; i < name.length(); ++i) { | ||
| 274 | + char ch = name.at(i); | ||
| 275 | + // Don't use locale/ctype here; follow PDF spec guidelines. | ||
| 276 | + if (ch == '\0') { | ||
| 277 | + // QPDFTokenizer embeds a null character to encode an invalid #. | ||
| 278 | + result += "#"; | ||
| 279 | + } else if ( | ||
| 280 | + ch < 33 || ch == '#' || ch == '/' || ch == '(' || ch == ')' || ch == '{' || ch == '}' || | ||
| 281 | + ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '%' || ch > 126) { | ||
| 282 | + result += QUtil::hex_encode_char(ch); | ||
| 283 | + } else { | ||
| 284 | + result += ch; | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | + return result; | ||
| 288 | +} | ||
| 289 | + | ||
| 290 | +std::shared_ptr<QPDFObject> | ||
| 291 | +QPDFObject::copy(bool shallow) | ||
| 292 | +{ | ||
| 293 | + switch (getResolvedTypeCode()) { | ||
| 294 | + case ::ot_uninitialized: | ||
| 295 | + throw std::logic_error("QPDFObjectHandle: attempting to copy an uninitialized object"); | ||
| 296 | + return {}; // does not return | ||
| 297 | + case ::ot_reserved: | ||
| 298 | + return create<QPDF_Reserved>(); | ||
| 299 | + case ::ot_null: | ||
| 300 | + return create<QPDF_Null>(); | ||
| 301 | + case ::ot_boolean: | ||
| 302 | + return create<QPDF_Bool>(std::get<QPDF_Bool>(value).val); | ||
| 303 | + case ::ot_integer: | ||
| 304 | + return create<QPDF_Integer>(std::get<QPDF_Integer>(value).val); | ||
| 305 | + case ::ot_real: | ||
| 306 | + return create<QPDF_Real>(std::get<QPDF_Real>(value).val); | ||
| 307 | + case ::ot_string: | ||
| 308 | + return create<QPDF_String>(std::get<QPDF_String>(value).val); | ||
| 309 | + case ::ot_name: | ||
| 310 | + return create<QPDF_Name>(std::get<QPDF_Name>(value).name); | ||
| 311 | + case ::ot_array: | ||
| 312 | + { | ||
| 313 | + auto const& a = std::get<QPDF_Array>(value); | ||
| 314 | + if (shallow) { | ||
| 315 | + return QPDFObject::create<QPDF_Array>(a); | ||
| 316 | + } else { | ||
| 317 | + QTC::TC("qpdf", "QPDF_Array copy", a.sp ? 0 : 1); | ||
| 318 | + if (a.sp) { | ||
| 319 | + QPDF_Array result; | ||
| 320 | + result.sp = std::make_unique<QPDF_Array::Sparse>(); | ||
| 321 | + result.sp->size = a.sp->size; | ||
| 322 | + for (auto const& element: a.sp->elements) { | ||
| 323 | + auto const& obj = element.second; | ||
| 324 | + result.sp->elements[element.first] = | ||
| 325 | + obj->getObjGen().isIndirect() ? obj : obj->copy(); | ||
| 326 | + } | ||
| 327 | + return QPDFObject::create<QPDF_Array>(std::move(result)); | ||
| 328 | + } else { | ||
| 329 | + std::vector<std::shared_ptr<QPDFObject>> result; | ||
| 330 | + result.reserve(a.elements.size()); | ||
| 331 | + for (auto const& element: a.elements) { | ||
| 332 | + result.push_back( | ||
| 333 | + element | ||
| 334 | + ? (element->getObjGen().isIndirect() ? element : element->copy()) | ||
| 335 | + : element); | ||
| 336 | + } | ||
| 337 | + return QPDFObject::create<QPDF_Array>(std::move(result), false); | ||
| 338 | + } | ||
| 339 | + } | ||
| 340 | + } | ||
| 341 | + case ::ot_dictionary: | ||
| 342 | + { | ||
| 343 | + auto const& d = std::get<QPDF_Dictionary>(value); | ||
| 344 | + if (shallow) { | ||
| 345 | + return QPDFObject::create<QPDF_Dictionary>(d.items); | ||
| 346 | + } else { | ||
| 347 | + std::map<std::string, QPDFObjectHandle> new_items; | ||
| 348 | + for (auto const& [key, val]: d.items) { | ||
| 349 | + new_items[key] = val.isIndirect() ? val : val.getObj()->copy(); | ||
| 350 | + } | ||
| 351 | + return QPDFObject::create<QPDF_Dictionary>(new_items); | ||
| 352 | + } | ||
| 353 | + } | ||
| 354 | + case ::ot_stream: | ||
| 355 | + QTC::TC("qpdf", "QPDF_Stream ERR shallow copy stream"); | ||
| 356 | + throw std::runtime_error("stream objects cannot be cloned"); | ||
| 357 | + return {}; // does not return | ||
| 358 | + case ::ot_operator: | ||
| 359 | + return create<QPDF_Operator>(std::get<QPDF_Operator>(value).val); | ||
| 360 | + case ::ot_inlineimage: | ||
| 361 | + return create<QPDF_InlineImage>(std::get<QPDF_InlineImage>(value).val); | ||
| 362 | + case ::ot_unresolved: | ||
| 363 | + throw std::logic_error("QPDFObjectHandle: attempting to unparse a reserved object"); | ||
| 364 | + return {}; // does not return | ||
| 365 | + case ::ot_destroyed: | ||
| 366 | + throw std::logic_error("attempted to shallow copy QPDFObjectHandle from destroyed QPDF"); | ||
| 367 | + return {}; // does not return | ||
| 368 | + case ::ot_reference: | ||
| 369 | + return qpdf->getObject(og).getObj(); | ||
| 370 | + } | ||
| 371 | + return {}; // does not return | ||
| 372 | +} | ||
| 373 | + | ||
| 374 | +std::string | ||
| 375 | +QPDFObject::unparse() | ||
| 376 | +{ | ||
| 377 | + switch (getResolvedTypeCode()) { | ||
| 378 | + case ::ot_uninitialized: | ||
| 379 | + throw std::logic_error("QPDFObjectHandle: attempting to unparse an uninitialized object"); | ||
| 380 | + return ""; // does not return | ||
| 381 | + case ::ot_reserved: | ||
| 382 | + throw std::logic_error("QPDFObjectHandle: attempting to unparse a reserved object"); | ||
| 383 | + return ""; // does not return | ||
| 384 | + case ::ot_null: | ||
| 385 | + return "null"; | ||
| 386 | + case ::ot_boolean: | ||
| 387 | + return std::get<QPDF_Bool>(value).val ? "true" : "false"; | ||
| 388 | + case ::ot_integer: | ||
| 389 | + return std::to_string(std::get<QPDF_Integer>(value).val); | ||
| 390 | + case ::ot_real: | ||
| 391 | + return std::get<QPDF_Real>(value).val; | ||
| 392 | + case ::ot_string: | ||
| 393 | + return std::get<QPDF_String>(value).unparse(false); | ||
| 394 | + case ::ot_name: | ||
| 395 | + return Name::normalize(std::get<QPDF_Name>(value).name); | ||
| 396 | + case ::ot_array: | ||
| 397 | + { | ||
| 398 | + auto const& a = std::get<QPDF_Array>(value); | ||
| 399 | + std::string result = "[ "; | ||
| 400 | + if (a.sp) { | ||
| 401 | + int next = 0; | ||
| 402 | + for (auto& item: a.sp->elements) { | ||
| 403 | + int key = item.first; | ||
| 404 | + for (int j = next; j < key; ++j) { | ||
| 405 | + result += "null "; | ||
| 406 | + } | ||
| 407 | + auto item_og = item.second->resolved_object()->getObjGen(); | ||
| 408 | + result += item_og.isIndirect() ? item_og.unparse(' ') + " R " | ||
| 409 | + : item.second->unparse() + " "; | ||
| 410 | + next = ++key; | ||
| 411 | + } | ||
| 412 | + for (int j = next; j < a.sp->size; ++j) { | ||
| 413 | + result += "null "; | ||
| 414 | + } | ||
| 415 | + } else { | ||
| 416 | + for (auto const& item: a.elements) { | ||
| 417 | + auto item_og = item->resolved_object()->getObjGen(); | ||
| 418 | + result += | ||
| 419 | + item_og.isIndirect() ? item_og.unparse(' ') + " R " : item->unparse() + " "; | ||
| 420 | + } | ||
| 421 | + } | ||
| 422 | + result += "]"; | ||
| 423 | + return result; | ||
| 424 | + } | ||
| 425 | + case ::ot_dictionary: | ||
| 426 | + { | ||
| 427 | + auto const& items = std::get<QPDF_Dictionary>(value).items; | ||
| 428 | + std::string result = "<< "; | ||
| 429 | + for (auto& iter: items) { | ||
| 430 | + if (!iter.second.isNull()) { | ||
| 431 | + result += Name::normalize(iter.first) + " " + iter.second.unparse() + " "; | ||
| 432 | + } | ||
| 433 | + } | ||
| 434 | + result += ">>"; | ||
| 435 | + return result; | ||
| 436 | + } | ||
| 437 | + case ::ot_stream: | ||
| 438 | + return og.unparse(' ') + " R"; | ||
| 439 | + case ::ot_operator: | ||
| 440 | + return std::get<QPDF_Operator>(value).val; | ||
| 441 | + case ::ot_inlineimage: | ||
| 442 | + return std::get<QPDF_InlineImage>(value).val; | ||
| 443 | + case ::ot_unresolved: | ||
| 444 | + throw std::logic_error("QPDFObjectHandle: attempting to unparse a unresolved object"); | ||
| 445 | + return ""; // does not return | ||
| 446 | + case ::ot_destroyed: | ||
| 447 | + throw std::logic_error("attempted to unparse a QPDFObjectHandle from a destroyed QPDF"); | ||
| 448 | + return ""; // does not return | ||
| 449 | + case ::ot_reference: | ||
| 450 | + return og.unparse(' ') + " R"; | ||
| 451 | + } | ||
| 452 | + return {}; // does not return | ||
| 453 | +} | ||
| 454 | + | ||
| 455 | +void | ||
| 456 | +QPDFObject::write_json(int json_version, JSON::Writer& p) | ||
| 457 | +{ | ||
| 458 | + switch (getResolvedTypeCode()) { | ||
| 459 | + case ::ot_uninitialized: | ||
| 460 | + throw std::logic_error( | ||
| 461 | + "QPDFObjectHandle: attempting to get JSON from a uninitialized object"); | ||
| 462 | + break; // unreachable | ||
| 463 | + case ::ot_null: | ||
| 464 | + case ::ot_operator: | ||
| 465 | + case ::ot_inlineimage: | ||
| 466 | + p << "null"; | ||
| 467 | + break; | ||
| 468 | + case ::ot_boolean: | ||
| 469 | + p << std::get<QPDF_Bool>(value).val; | ||
| 470 | + break; | ||
| 471 | + case ::ot_integer: | ||
| 472 | + p << std::to_string(std::get<QPDF_Integer>(value).val); | ||
| 473 | + break; | ||
| 474 | + case ::ot_real: | ||
| 475 | + { | ||
| 476 | + auto const& val = std::get<QPDF_Real>(value).val; | ||
| 477 | + if (val.length() == 0) { | ||
| 478 | + // Can't really happen... | ||
| 479 | + p << "0"; | ||
| 480 | + } else if (val.at(0) == '.') { | ||
| 481 | + p << "0" << val; | ||
| 482 | + } else if (val.length() >= 2 && val.at(0) == '-' && val.at(1) == '.') { | ||
| 483 | + p << "-0." << val.substr(2); | ||
| 484 | + } else { | ||
| 485 | + p << val; | ||
| 486 | + } | ||
| 487 | + if (val.back() == '.') { | ||
| 488 | + p << "0"; | ||
| 489 | + } | ||
| 490 | + } | ||
| 491 | + break; | ||
| 492 | + case ::ot_string: | ||
| 493 | + std::get<QPDF_String>(value).writeJSON(json_version, p); | ||
| 494 | + break; | ||
| 495 | + case ::ot_name: | ||
| 496 | + { | ||
| 497 | + auto const& n = std::get<QPDF_Name>(value); | ||
| 498 | + // For performance reasons this code is duplicated in QPDF_Dictionary::writeJSON. When | ||
| 499 | + // updating this method make sure QPDF_Dictionary is also update. | ||
| 500 | + if (json_version == 1) { | ||
| 501 | + p << "\"" << JSON::Writer::encode_string(Name::normalize(n.name)) << "\""; | ||
| 502 | + } else { | ||
| 503 | + if (auto res = Name::analyzeJSONEncoding(n.name); res.first) { | ||
| 504 | + if (res.second) { | ||
| 505 | + p << "\"" << n.name << "\""; | ||
| 506 | + } else { | ||
| 507 | + p << "\"" << JSON::Writer::encode_string(n.name) << "\""; | ||
| 508 | + } | ||
| 509 | + } else { | ||
| 510 | + p << "\"n:" << JSON::Writer::encode_string(Name::normalize(n.name)) << "\""; | ||
| 511 | + } | ||
| 512 | + } | ||
| 513 | + } | ||
| 514 | + break; | ||
| 515 | + case ::ot_array: | ||
| 516 | + { | ||
| 517 | + auto const& a = std::get<QPDF_Array>(value); | ||
| 518 | + p.writeStart('['); | ||
| 519 | + if (a.sp) { | ||
| 520 | + int next = 0; | ||
| 521 | + for (auto& item: a.sp->elements) { | ||
| 522 | + int key = item.first; | ||
| 523 | + for (int j = next; j < key; ++j) { | ||
| 524 | + p.writeNext() << "null"; | ||
| 525 | + } | ||
| 526 | + p.writeNext(); | ||
| 527 | + auto item_og = item.second->getObjGen(); | ||
| 528 | + if (item_og.isIndirect()) { | ||
| 529 | + p << "\"" << item_og.unparse(' ') << " R\""; | ||
| 530 | + } else { | ||
| 531 | + item.second->write_json(json_version, p); | ||
| 532 | + } | ||
| 533 | + next = ++key; | ||
| 534 | + } | ||
| 535 | + for (int j = next; j < a.sp->size; ++j) { | ||
| 536 | + p.writeNext() << "null"; | ||
| 537 | + } | ||
| 538 | + } else { | ||
| 539 | + for (auto const& item: a.elements) { | ||
| 540 | + p.writeNext(); | ||
| 541 | + auto item_og = item->getObjGen(); | ||
| 542 | + if (item_og.isIndirect()) { | ||
| 543 | + p << "\"" << item_og.unparse(' ') << " R\""; | ||
| 544 | + } else { | ||
| 545 | + item->write_json(json_version, p); | ||
| 546 | + } | ||
| 547 | + } | ||
| 548 | + } | ||
| 549 | + p.writeEnd(']'); | ||
| 550 | + } | ||
| 551 | + break; | ||
| 552 | + case ::ot_dictionary: | ||
| 553 | + { | ||
| 554 | + auto const& d = std::get<QPDF_Dictionary>(value); | ||
| 555 | + p.writeStart('{'); | ||
| 556 | + for (auto& iter: d.items) { | ||
| 557 | + if (!iter.second.isNull()) { | ||
| 558 | + p.writeNext(); | ||
| 559 | + if (json_version == 1) { | ||
| 560 | + p << "\"" << JSON::Writer::encode_string(Name::normalize(iter.first)) | ||
| 561 | + << "\": "; | ||
| 562 | + } else if (auto res = Name::analyzeJSONEncoding(iter.first); res.first) { | ||
| 563 | + if (res.second) { | ||
| 564 | + p << "\"" << iter.first << "\": "; | ||
| 565 | + } else { | ||
| 566 | + p << "\"" << JSON::Writer::encode_string(iter.first) << "\": "; | ||
| 567 | + } | ||
| 568 | + } else { | ||
| 569 | + p << "\"n:" << JSON::Writer::encode_string(Name::normalize(iter.first)) | ||
| 570 | + << "\": "; | ||
| 571 | + } | ||
| 572 | + iter.second.writeJSON(json_version, p); | ||
| 573 | + } | ||
| 574 | + } | ||
| 575 | + p.writeEnd('}'); | ||
| 576 | + } | ||
| 577 | + break; | ||
| 578 | + case ::ot_stream: | ||
| 579 | + std::get<QPDF_Stream>(value).m->stream_dict.writeJSON(json_version, p); | ||
| 580 | + break; | ||
| 581 | + case ::ot_reference: | ||
| 582 | + p << "\"" << getObjGen().unparse(' ') << " R\""; | ||
| 583 | + break; | ||
| 584 | + default: | ||
| 585 | + throw std::logic_error("attempted to write an unsuitable object as JSON"); | ||
| 586 | + } | ||
| 587 | +} | ||
| 588 | + | ||
| 589 | +void | ||
| 590 | +QPDFObject::disconnect() | ||
| 591 | +{ | ||
| 592 | + // Disconnect an object from its owning QPDF. This is called by QPDF's destructor. | ||
| 593 | + | ||
| 594 | + switch (getTypeCode()) { | ||
| 595 | + case ::ot_array: | ||
| 596 | + { | ||
| 597 | + auto& a = std::get<QPDF_Array>(value); | ||
| 598 | + if (a.sp) { | ||
| 599 | + for (auto& item: a.sp->elements) { | ||
| 600 | + auto& obj = item.second; | ||
| 601 | + if (!obj->getObjGen().isIndirect()) { | ||
| 602 | + obj->disconnect(); | ||
| 603 | + } | ||
| 604 | + } | ||
| 605 | + } else { | ||
| 606 | + for (auto& obj: a.elements) { | ||
| 607 | + if (!obj->getObjGen().isIndirect()) { | ||
| 608 | + obj->disconnect(); | ||
| 609 | + } | ||
| 610 | + } | ||
| 611 | + } | ||
| 612 | + } | ||
| 613 | + break; | ||
| 614 | + case ::ot_dictionary: | ||
| 615 | + for (auto& iter: std::get<QPDF_Dictionary>(value).items) { | ||
| 616 | + QPDFObjectHandle::DisconnectAccess::disconnect(iter.second); | ||
| 617 | + } | ||
| 618 | + break; | ||
| 619 | + case ::ot_stream: | ||
| 620 | + { | ||
| 621 | + auto& s = std::get<QPDF_Stream>(value); | ||
| 622 | + s.m->stream_provider = nullptr; | ||
| 623 | + QPDFObjectHandle::DisconnectAccess::disconnect(s.m->stream_dict); | ||
| 624 | + } | ||
| 625 | + break; | ||
| 626 | + default: | ||
| 627 | + break; | ||
| 628 | + } | ||
| 629 | + qpdf = nullptr; | ||
| 630 | + og = QPDFObjGen(); | ||
| 631 | +} | ||
| 632 | +std::string | ||
| 633 | +QPDFObject::getStringValue() const | ||
| 634 | +{ | ||
| 635 | + switch (getResolvedTypeCode()) { | ||
| 636 | + case ::ot_real: | ||
| 637 | + return std::get<QPDF_Real>(value).val; | ||
| 638 | + case ::ot_string: | ||
| 639 | + return std::get<QPDF_String>(value).val; | ||
| 640 | + case ::ot_name: | ||
| 641 | + return std::get<QPDF_Name>(value).name; | ||
| 642 | + case ::ot_operator: | ||
| 643 | + return std::get<QPDF_Operator>(value).val; | ||
| 644 | + case ::ot_inlineimage: | ||
| 645 | + return std::get<QPDF_InlineImage>(value).val; | ||
| 646 | + case ::ot_reference: | ||
| 647 | + return std::get<QPDF_Reference>(value).obj->getStringValue(); | ||
| 648 | + default: | ||
| 649 | + throw std::logic_error("Internal error in QPDFObject::getStringValue"); | ||
| 650 | + return ""; // does not return | ||
| 651 | + } | ||
| 652 | + return {}; // does not return | ||
| 653 | +} | ||
| 654 | + | ||
| 231 | bool | 655 | bool |
| 232 | QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const | 656 | QPDFObjectHandle::isSameObjectAs(QPDFObjectHandle const& rhs) const |
| 233 | { | 657 | { |
| @@ -253,7 +677,7 @@ QPDFObjectHandle::getTypeCode() const | @@ -253,7 +677,7 @@ QPDFObjectHandle::getTypeCode() const | ||
| 253 | char const* | 677 | char const* |
| 254 | QPDFObjectHandle::getTypeName() const | 678 | QPDFObjectHandle::getTypeName() const |
| 255 | { | 679 | { |
| 256 | - static constexpr std::array<char const*, 15> tn{ | 680 | + static constexpr std::array<char const*, 16> tn{ |
| 257 | "uninitialized", | 681 | "uninitialized", |
| 258 | "reserved", | 682 | "reserved", |
| 259 | "null", | 683 | "null", |
| @@ -268,84 +692,23 @@ QPDFObjectHandle::getTypeName() const | @@ -268,84 +692,23 @@ QPDFObjectHandle::getTypeName() const | ||
| 268 | "operator", | 692 | "operator", |
| 269 | "inline-image", | 693 | "inline-image", |
| 270 | "unresolved", | 694 | "unresolved", |
| 271 | - "destroyed"}; | 695 | + "destroyed", |
| 696 | + "reference"}; | ||
| 272 | return obj ? tn[getTypeCode()] : "uninitialized"; | 697 | return obj ? tn[getTypeCode()] : "uninitialized"; |
| 273 | } | 698 | } |
| 274 | 699 | ||
| 275 | -QPDF_Array* | ||
| 276 | -QPDFObjectHandle::asArray() const | ||
| 277 | -{ | ||
| 278 | - return obj ? obj->as<QPDF_Array>() : nullptr; | ||
| 279 | -} | ||
| 280 | - | ||
| 281 | QPDF_Bool* | 700 | QPDF_Bool* |
| 282 | QPDFObjectHandle::asBool() const | 701 | QPDFObjectHandle::asBool() const |
| 283 | { | 702 | { |
| 284 | return obj ? obj->as<QPDF_Bool>() : nullptr; | 703 | return obj ? obj->as<QPDF_Bool>() : nullptr; |
| 285 | } | 704 | } |
| 286 | 705 | ||
| 287 | -QPDF_Dictionary* | ||
| 288 | -QPDFObjectHandle::asDictionary() const | ||
| 289 | -{ | ||
| 290 | - return obj ? obj->as<QPDF_Dictionary>() : nullptr; | ||
| 291 | -} | ||
| 292 | - | ||
| 293 | -QPDF_InlineImage* | ||
| 294 | -QPDFObjectHandle::asInlineImage() const | ||
| 295 | -{ | ||
| 296 | - return obj ? obj->as<QPDF_InlineImage>() : nullptr; | ||
| 297 | -} | ||
| 298 | - | ||
| 299 | QPDF_Integer* | 706 | QPDF_Integer* |
| 300 | QPDFObjectHandle::asInteger() const | 707 | QPDFObjectHandle::asInteger() const |
| 301 | { | 708 | { |
| 302 | return obj ? obj->as<QPDF_Integer>() : nullptr; | 709 | return obj ? obj->as<QPDF_Integer>() : nullptr; |
| 303 | } | 710 | } |
| 304 | 711 | ||
| 305 | -QPDF_Name* | ||
| 306 | -QPDFObjectHandle::asName() const | ||
| 307 | -{ | ||
| 308 | - return obj ? obj->as<QPDF_Name>() : nullptr; | ||
| 309 | -} | ||
| 310 | - | ||
| 311 | -QPDF_Null* | ||
| 312 | -QPDFObjectHandle::asNull() const | ||
| 313 | -{ | ||
| 314 | - return obj ? obj->as<QPDF_Null>() : nullptr; | ||
| 315 | -} | ||
| 316 | - | ||
| 317 | -QPDF_Operator* | ||
| 318 | -QPDFObjectHandle::asOperator() const | ||
| 319 | -{ | ||
| 320 | - return obj ? obj->as<QPDF_Operator>() : nullptr; | ||
| 321 | -} | ||
| 322 | - | ||
| 323 | -QPDF_Real* | ||
| 324 | -QPDFObjectHandle::asReal() const | ||
| 325 | -{ | ||
| 326 | - return obj ? obj->as<QPDF_Real>() : nullptr; | ||
| 327 | -} | ||
| 328 | - | ||
| 329 | -QPDF_Reserved* | ||
| 330 | -QPDFObjectHandle::asReserved() const | ||
| 331 | -{ | ||
| 332 | - return obj ? obj->as<QPDF_Reserved>() : nullptr; | ||
| 333 | -} | ||
| 334 | - | ||
| 335 | -QPDF_Stream* | ||
| 336 | -QPDFObjectHandle::asStream() const | ||
| 337 | -{ | ||
| 338 | - return obj ? obj->as<QPDF_Stream>() : nullptr; | ||
| 339 | -} | ||
| 340 | - | ||
| 341 | -QPDF_Stream* | ||
| 342 | -QPDFObjectHandle::asStreamWithAssert() const | ||
| 343 | -{ | ||
| 344 | - auto stream = asStream(); | ||
| 345 | - assertType("stream", stream); | ||
| 346 | - return stream; | ||
| 347 | -} | ||
| 348 | - | ||
| 349 | QPDF_String* | 712 | QPDF_String* |
| 350 | QPDFObjectHandle::asString() const | 713 | QPDFObjectHandle::asString() const |
| 351 | { | 714 | { |
| @@ -500,7 +863,7 @@ QPDFObjectHandle::getBoolValue() const | @@ -500,7 +863,7 @@ QPDFObjectHandle::getBoolValue() const | ||
| 500 | { | 863 | { |
| 501 | auto boolean = asBool(); | 864 | auto boolean = asBool(); |
| 502 | if (boolean) { | 865 | if (boolean) { |
| 503 | - return boolean->getVal(); | 866 | + return boolean->val; |
| 504 | } else { | 867 | } else { |
| 505 | typeWarning("boolean", "returning false"); | 868 | typeWarning("boolean", "returning false"); |
| 506 | QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); | 869 | QTC::TC("qpdf", "QPDFObjectHandle boolean returning false"); |
| @@ -515,7 +878,7 @@ QPDFObjectHandle::getValueAsBool(bool& value) const | @@ -515,7 +878,7 @@ QPDFObjectHandle::getValueAsBool(bool& value) const | ||
| 515 | if (boolean == nullptr) { | 878 | if (boolean == nullptr) { |
| 516 | return false; | 879 | return false; |
| 517 | } | 880 | } |
| 518 | - value = boolean->getVal(); | 881 | + value = boolean->val; |
| 519 | return true; | 882 | return true; |
| 520 | } | 883 | } |
| 521 | 884 | ||
| @@ -526,7 +889,7 @@ QPDFObjectHandle::getIntValue() const | @@ -526,7 +889,7 @@ QPDFObjectHandle::getIntValue() const | ||
| 526 | { | 889 | { |
| 527 | auto integer = asInteger(); | 890 | auto integer = asInteger(); |
| 528 | if (integer) { | 891 | if (integer) { |
| 529 | - return integer->getVal(); | 892 | + return integer->val; |
| 530 | } else { | 893 | } else { |
| 531 | typeWarning("integer", "returning 0"); | 894 | typeWarning("integer", "returning 0"); |
| 532 | QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); | 895 | QTC::TC("qpdf", "QPDFObjectHandle integer returning 0"); |
| @@ -541,7 +904,7 @@ QPDFObjectHandle::getValueAsInt(long long& value) const | @@ -541,7 +904,7 @@ QPDFObjectHandle::getValueAsInt(long long& value) const | ||
| 541 | if (integer == nullptr) { | 904 | if (integer == nullptr) { |
| 542 | return false; | 905 | return false; |
| 543 | } | 906 | } |
| 544 | - value = integer->getVal(); | 907 | + value = integer->val; |
| 545 | return true; | 908 | return true; |
| 546 | } | 909 | } |
| 547 | 910 | ||
| @@ -1155,7 +1518,7 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_ | @@ -1155,7 +1518,7 @@ QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_ | ||
| 1155 | } else if (!obj) { | 1518 | } else if (!obj) { |
| 1156 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); | 1519 | throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle"); |
| 1157 | } else { | 1520 | } else { |
| 1158 | - obj->writeJSON(json_version, p); | 1521 | + obj->write_json(json_version, p); |
| 1159 | } | 1522 | } |
| 1160 | } | 1523 | } |
| 1161 | 1524 | ||
| @@ -1392,43 +1755,43 @@ QPDFObjectHandle::getParsedOffset() const | @@ -1392,43 +1755,43 @@ QPDFObjectHandle::getParsedOffset() const | ||
| 1392 | QPDFObjectHandle | 1755 | QPDFObjectHandle |
| 1393 | QPDFObjectHandle::newBool(bool value) | 1756 | QPDFObjectHandle::newBool(bool value) |
| 1394 | { | 1757 | { |
| 1395 | - return {QPDF_Bool::create(value)}; | 1758 | + return {QPDFObject::create<QPDF_Bool>(value)}; |
| 1396 | } | 1759 | } |
| 1397 | 1760 | ||
| 1398 | QPDFObjectHandle | 1761 | QPDFObjectHandle |
| 1399 | QPDFObjectHandle::newNull() | 1762 | QPDFObjectHandle::newNull() |
| 1400 | { | 1763 | { |
| 1401 | - return {QPDF_Null::create()}; | 1764 | + return {QPDFObject::create<QPDF_Null>()}; |
| 1402 | } | 1765 | } |
| 1403 | 1766 | ||
| 1404 | QPDFObjectHandle | 1767 | QPDFObjectHandle |
| 1405 | QPDFObjectHandle::newInteger(long long value) | 1768 | QPDFObjectHandle::newInteger(long long value) |
| 1406 | { | 1769 | { |
| 1407 | - return {QPDF_Integer::create(value)}; | 1770 | + return {QPDFObject::create<QPDF_Integer>(value)}; |
| 1408 | } | 1771 | } |
| 1409 | 1772 | ||
| 1410 | QPDFObjectHandle | 1773 | QPDFObjectHandle |
| 1411 | QPDFObjectHandle::newReal(std::string const& value) | 1774 | QPDFObjectHandle::newReal(std::string const& value) |
| 1412 | { | 1775 | { |
| 1413 | - return {QPDF_Real::create(value)}; | 1776 | + return {QPDFObject::create<QPDF_Real>(value)}; |
| 1414 | } | 1777 | } |
| 1415 | 1778 | ||
| 1416 | QPDFObjectHandle | 1779 | QPDFObjectHandle |
| 1417 | QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_zeroes) | 1780 | QPDFObjectHandle::newReal(double value, int decimal_places, bool trim_trailing_zeroes) |
| 1418 | { | 1781 | { |
| 1419 | - return {QPDF_Real::create(value, decimal_places, trim_trailing_zeroes)}; | 1782 | + return {QPDFObject::create<QPDF_Real>(value, decimal_places, trim_trailing_zeroes)}; |
| 1420 | } | 1783 | } |
| 1421 | 1784 | ||
| 1422 | QPDFObjectHandle | 1785 | QPDFObjectHandle |
| 1423 | QPDFObjectHandle::newName(std::string const& name) | 1786 | QPDFObjectHandle::newName(std::string const& name) |
| 1424 | { | 1787 | { |
| 1425 | - return {QPDF_Name::create(name)}; | 1788 | + return {QPDFObject::create<QPDF_Name>(name)}; |
| 1426 | } | 1789 | } |
| 1427 | 1790 | ||
| 1428 | QPDFObjectHandle | 1791 | QPDFObjectHandle |
| 1429 | QPDFObjectHandle::newString(std::string const& str) | 1792 | QPDFObjectHandle::newString(std::string const& str) |
| 1430 | { | 1793 | { |
| 1431 | - return {QPDF_String::create(str)}; | 1794 | + return {QPDFObject::create<QPDF_String>(str)}; |
| 1432 | } | 1795 | } |
| 1433 | 1796 | ||
| 1434 | QPDFObjectHandle | 1797 | QPDFObjectHandle |
| @@ -1440,13 +1803,13 @@ QPDFObjectHandle::newUnicodeString(std::string const& utf8_str) | @@ -1440,13 +1803,13 @@ QPDFObjectHandle::newUnicodeString(std::string const& utf8_str) | ||
| 1440 | QPDFObjectHandle | 1803 | QPDFObjectHandle |
| 1441 | QPDFObjectHandle::newOperator(std::string const& value) | 1804 | QPDFObjectHandle::newOperator(std::string const& value) |
| 1442 | { | 1805 | { |
| 1443 | - return {QPDF_Operator::create(value)}; | 1806 | + return {QPDFObject::create<QPDF_Operator>(value)}; |
| 1444 | } | 1807 | } |
| 1445 | 1808 | ||
| 1446 | QPDFObjectHandle | 1809 | QPDFObjectHandle |
| 1447 | QPDFObjectHandle::newInlineImage(std::string const& value) | 1810 | QPDFObjectHandle::newInlineImage(std::string const& value) |
| 1448 | { | 1811 | { |
| 1449 | - return {QPDF_InlineImage::create(value)}; | 1812 | + return {QPDFObject::create<QPDF_InlineImage>(value)}; |
| 1450 | } | 1813 | } |
| 1451 | 1814 | ||
| 1452 | QPDFObjectHandle | 1815 | QPDFObjectHandle |
| @@ -1458,7 +1821,7 @@ QPDFObjectHandle::newArray() | @@ -1458,7 +1821,7 @@ QPDFObjectHandle::newArray() | ||
| 1458 | QPDFObjectHandle | 1821 | QPDFObjectHandle |
| 1459 | QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items) | 1822 | QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items) |
| 1460 | { | 1823 | { |
| 1461 | - return {QPDF_Array::create(items)}; | 1824 | + return {QPDFObject::create<QPDF_Array>(items)}; |
| 1462 | } | 1825 | } |
| 1463 | 1826 | ||
| 1464 | QPDFObjectHandle | 1827 | QPDFObjectHandle |
| @@ -1518,7 +1881,7 @@ QPDFObjectHandle::newDictionary() | @@ -1518,7 +1881,7 @@ QPDFObjectHandle::newDictionary() | ||
| 1518 | QPDFObjectHandle | 1881 | QPDFObjectHandle |
| 1519 | QPDFObjectHandle::newDictionary(std::map<std::string, QPDFObjectHandle> const& items) | 1882 | QPDFObjectHandle::newDictionary(std::map<std::string, QPDFObjectHandle> const& items) |
| 1520 | { | 1883 | { |
| 1521 | - return {QPDF_Dictionary::create(items)}; | 1884 | + return {QPDFObject::create<QPDF_Dictionary>(items)}; |
| 1522 | } | 1885 | } |
| 1523 | 1886 | ||
| 1524 | QPDFObjectHandle | 1887 | QPDFObjectHandle |
| @@ -1564,7 +1927,7 @@ void | @@ -1564,7 +1927,7 @@ void | ||
| 1564 | QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& object_description) | 1927 | QPDFObjectHandle::setObjectDescription(QPDF* owning_qpdf, std::string const& object_description) |
| 1565 | { | 1928 | { |
| 1566 | if (obj) { | 1929 | if (obj) { |
| 1567 | - auto descr = std::make_shared<QPDFValue::Description>(object_description); | 1930 | + auto descr = std::make_shared<QPDFObject::Description>(object_description); |
| 1568 | obj->setDescription(owning_qpdf, descr); | 1931 | obj->setDescription(owning_qpdf, descr); |
| 1569 | } | 1932 | } |
| 1570 | } | 1933 | } |
| @@ -1614,7 +1977,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | @@ -1614,7 +1977,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | ||
| 1614 | items.emplace_back(array.at(i).second); | 1977 | items.emplace_back(array.at(i).second); |
| 1615 | items.back().makeDirect(visited, stop_at_streams); | 1978 | items.back().makeDirect(visited, stop_at_streams); |
| 1616 | } | 1979 | } |
| 1617 | - this->obj = QPDF_Array::create(items); | 1980 | + this->obj = QPDFObject::create<QPDF_Array>(items); |
| 1618 | } else if (isDictionary()) { | 1981 | } else if (isDictionary()) { |
| 1619 | std::map<std::string, QPDFObjectHandle> items; | 1982 | std::map<std::string, QPDFObjectHandle> items; |
| 1620 | auto dict = as_dictionary(strict); | 1983 | auto dict = as_dictionary(strict); |
| @@ -1622,7 +1985,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | @@ -1622,7 +1985,7 @@ QPDFObjectHandle::makeDirect(QPDFObjGen::set& visited, bool stop_at_streams) | ||
| 1622 | items[key] = dict.getKey(key); | 1985 | items[key] = dict.getKey(key); |
| 1623 | items[key].makeDirect(visited, stop_at_streams); | 1986 | items[key].makeDirect(visited, stop_at_streams); |
| 1624 | } | 1987 | } |
| 1625 | - this->obj = QPDF_Dictionary::create(items); | 1988 | + this->obj = QPDFObject::create<QPDF_Dictionary>(items); |
| 1626 | } else if (isStream()) { | 1989 | } else if (isStream()) { |
| 1627 | QTC::TC("qpdf", "QPDFObjectHandle copy stream", stop_at_streams ? 0 : 1); | 1990 | QTC::TC("qpdf", "QPDFObjectHandle copy stream", stop_at_streams ? 0 : 1); |
| 1628 | if (!stop_at_streams) { | 1991 | if (!stop_at_streams) { |
libqpdf/QPDFParser.cc
| @@ -4,18 +4,6 @@ | @@ -4,18 +4,6 @@ | ||
| 4 | #include <qpdf/QPDFObjGen.hh> | 4 | #include <qpdf/QPDFObjGen.hh> |
| 5 | #include <qpdf/QPDFObjectHandle.hh> | 5 | #include <qpdf/QPDFObjectHandle.hh> |
| 6 | #include <qpdf/QPDFObject_private.hh> | 6 | #include <qpdf/QPDFObject_private.hh> |
| 7 | -#include <qpdf/QPDF_Array.hh> | ||
| 8 | -#include <qpdf/QPDF_Bool.hh> | ||
| 9 | -#include <qpdf/QPDF_Dictionary.hh> | ||
| 10 | -#include <qpdf/QPDF_InlineImage.hh> | ||
| 11 | -#include <qpdf/QPDF_Integer.hh> | ||
| 12 | -#include <qpdf/QPDF_Name.hh> | ||
| 13 | -#include <qpdf/QPDF_Null.hh> | ||
| 14 | -#include <qpdf/QPDF_Operator.hh> | ||
| 15 | -#include <qpdf/QPDF_Real.hh> | ||
| 16 | -#include <qpdf/QPDF_Reserved.hh> | ||
| 17 | -#include <qpdf/QPDF_Stream.hh> | ||
| 18 | -#include <qpdf/QPDF_String.hh> | ||
| 19 | #include <qpdf/QTC.hh> | 7 | #include <qpdf/QTC.hh> |
| 20 | #include <qpdf/QUtil.hh> | 8 | #include <qpdf/QUtil.hh> |
| 21 | 9 | ||
| @@ -47,27 +35,27 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -47,27 +35,27 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 47 | } | 35 | } |
| 48 | QTC::TC("qpdf", "QPDFParser eof in parse"); | 36 | QTC::TC("qpdf", "QPDFParser eof in parse"); |
| 49 | warn("unexpected EOF"); | 37 | warn("unexpected EOF"); |
| 50 | - return {QPDF_Null::create()}; | 38 | + return {QPDFObject::create<QPDF_Null>()}; |
| 51 | 39 | ||
| 52 | case QPDFTokenizer::tt_bad: | 40 | case QPDFTokenizer::tt_bad: |
| 53 | QTC::TC("qpdf", "QPDFParser bad token in parse"); | 41 | QTC::TC("qpdf", "QPDFParser bad token in parse"); |
| 54 | - return {QPDF_Null::create()}; | 42 | + return {QPDFObject::create<QPDF_Null>()}; |
| 55 | 43 | ||
| 56 | case QPDFTokenizer::tt_brace_open: | 44 | case QPDFTokenizer::tt_brace_open: |
| 57 | case QPDFTokenizer::tt_brace_close: | 45 | case QPDFTokenizer::tt_brace_close: |
| 58 | QTC::TC("qpdf", "QPDFParser bad brace"); | 46 | QTC::TC("qpdf", "QPDFParser bad brace"); |
| 59 | warn("treating unexpected brace token as null"); | 47 | warn("treating unexpected brace token as null"); |
| 60 | - return {QPDF_Null::create()}; | 48 | + return {QPDFObject::create<QPDF_Null>()}; |
| 61 | 49 | ||
| 62 | case QPDFTokenizer::tt_array_close: | 50 | case QPDFTokenizer::tt_array_close: |
| 63 | QTC::TC("qpdf", "QPDFParser bad array close"); | 51 | QTC::TC("qpdf", "QPDFParser bad array close"); |
| 64 | warn("treating unexpected array close token as null"); | 52 | warn("treating unexpected array close token as null"); |
| 65 | - return {QPDF_Null::create()}; | 53 | + return {QPDFObject::create<QPDF_Null>()}; |
| 66 | 54 | ||
| 67 | case QPDFTokenizer::tt_dict_close: | 55 | case QPDFTokenizer::tt_dict_close: |
| 68 | QTC::TC("qpdf", "QPDFParser bad dictionary close"); | 56 | QTC::TC("qpdf", "QPDFParser bad dictionary close"); |
| 69 | warn("unexpected dictionary close token"); | 57 | warn("unexpected dictionary close token"); |
| 70 | - return {QPDF_Null::create()}; | 58 | + return {QPDFObject::create<QPDF_Null>()}; |
| 71 | 59 | ||
| 72 | case QPDFTokenizer::tt_array_open: | 60 | case QPDFTokenizer::tt_array_open: |
| 73 | case QPDFTokenizer::tt_dict_open: | 61 | case QPDFTokenizer::tt_dict_open: |
| @@ -82,7 +70,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -82,7 +70,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 82 | return withDescription<QPDF_Bool>(tokenizer.getValue() == "true"); | 70 | return withDescription<QPDF_Bool>(tokenizer.getValue() == "true"); |
| 83 | 71 | ||
| 84 | case QPDFTokenizer::tt_null: | 72 | case QPDFTokenizer::tt_null: |
| 85 | - return {QPDF_Null::create()}; | 73 | + return {QPDFObject::create<QPDF_Null>()}; |
| 86 | 74 | ||
| 87 | case QPDFTokenizer::tt_integer: | 75 | case QPDFTokenizer::tt_integer: |
| 88 | return withDescription<QPDF_Integer>(QUtil::string_to_ll(tokenizer.getValue().c_str())); | 76 | return withDescription<QPDF_Integer>(QUtil::string_to_ll(tokenizer.getValue().c_str())); |
| @@ -103,7 +91,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -103,7 +91,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 103 | // not move the input source's offset. | 91 | // not move the input source's offset. |
| 104 | input.seek(input.getLastOffset(), SEEK_SET); | 92 | input.seek(input.getLastOffset(), SEEK_SET); |
| 105 | empty = true; | 93 | empty = true; |
| 106 | - return {QPDF_Null::create()}; | 94 | + return {QPDFObject::create<QPDF_Null>()}; |
| 107 | } else { | 95 | } else { |
| 108 | QTC::TC("qpdf", "QPDFParser treat word as string"); | 96 | QTC::TC("qpdf", "QPDFParser treat word as string"); |
| 109 | warn("unknown token while reading object; treating as string"); | 97 | warn("unknown token while reading object; treating as string"); |
| @@ -122,7 +110,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | @@ -122,7 +110,7 @@ QPDFParser::parse(bool& empty, bool content_stream) | ||
| 122 | 110 | ||
| 123 | default: | 111 | default: |
| 124 | warn("treating unknown token type as null while reading object"); | 112 | warn("treating unknown token type as null while reading object"); |
| 125 | - return {QPDF_Null::create()}; | 113 | + return {QPDFObject::create<QPDF_Null>()}; |
| 126 | } | 114 | } |
| 127 | } | 115 | } |
| 128 | 116 | ||
| @@ -194,12 +182,12 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -194,12 +182,12 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 194 | } | 182 | } |
| 195 | QTC::TC("qpdf", "QPDFParser eof in parseRemainder"); | 183 | QTC::TC("qpdf", "QPDFParser eof in parseRemainder"); |
| 196 | warn("unexpected EOF"); | 184 | warn("unexpected EOF"); |
| 197 | - return {QPDF_Null::create()}; | 185 | + return {QPDFObject::create<QPDF_Null>()}; |
| 198 | 186 | ||
| 199 | case QPDFTokenizer::tt_bad: | 187 | case QPDFTokenizer::tt_bad: |
| 200 | QTC::TC("qpdf", "QPDFParser bad token in parseRemainder"); | 188 | QTC::TC("qpdf", "QPDFParser bad token in parseRemainder"); |
| 201 | if (tooManyBadTokens()) { | 189 | if (tooManyBadTokens()) { |
| 202 | - return {QPDF_Null::create()}; | 190 | + return {QPDFObject::create<QPDF_Null>()}; |
| 203 | } | 191 | } |
| 204 | addNull(); | 192 | addNull(); |
| 205 | continue; | 193 | continue; |
| @@ -209,7 +197,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -209,7 +197,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 209 | QTC::TC("qpdf", "QPDFParser bad brace in parseRemainder"); | 197 | QTC::TC("qpdf", "QPDFParser bad brace in parseRemainder"); |
| 210 | warn("treating unexpected brace token as null"); | 198 | warn("treating unexpected brace token as null"); |
| 211 | if (tooManyBadTokens()) { | 199 | if (tooManyBadTokens()) { |
| 212 | - return {QPDF_Null::create()}; | 200 | + return {QPDFObject::create<QPDF_Null>()}; |
| 213 | } | 201 | } |
| 214 | addNull(); | 202 | addNull(); |
| 215 | continue; | 203 | continue; |
| @@ -218,10 +206,11 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -218,10 +206,11 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 218 | if (bad_count && !max_bad_count) { | 206 | if (bad_count && !max_bad_count) { |
| 219 | // Trigger warning. | 207 | // Trigger warning. |
| 220 | (void)tooManyBadTokens(); | 208 | (void)tooManyBadTokens(); |
| 221 | - return {QPDF_Null::create()}; | 209 | + return {QPDFObject::create<QPDF_Null>()}; |
| 222 | } | 210 | } |
| 223 | if (frame->state == st_array) { | 211 | if (frame->state == st_array) { |
| 224 | - auto object = QPDF_Array::create(std::move(frame->olist), frame->null_count > 100); | 212 | + auto object = QPDFObject::create<QPDF_Array>( |
| 213 | + std::move(frame->olist), frame->null_count > 100); | ||
| 225 | setDescription(object, frame->offset - 1); | 214 | setDescription(object, frame->offset - 1); |
| 226 | // The `offset` points to the next of "[". Set the rewind offset to point to the | 215 | // The `offset` points to the next of "[". Set the rewind offset to point to the |
| 227 | // beginning of "[". This has been explicitly tested with whitespace surrounding the | 216 | // beginning of "[". This has been explicitly tested with whitespace surrounding the |
| @@ -237,7 +226,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -237,7 +226,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 237 | QTC::TC("qpdf", "QPDFParser bad array close in parseRemainder"); | 226 | QTC::TC("qpdf", "QPDFParser bad array close in parseRemainder"); |
| 238 | warn("treating unexpected array close token as null"); | 227 | warn("treating unexpected array close token as null"); |
| 239 | if (tooManyBadTokens()) { | 228 | if (tooManyBadTokens()) { |
| 240 | - return {QPDF_Null::create()}; | 229 | + return {QPDFObject::create<QPDF_Null>()}; |
| 241 | } | 230 | } |
| 242 | addNull(); | 231 | addNull(); |
| 243 | } | 232 | } |
| @@ -247,7 +236,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -247,7 +236,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 247 | if (bad_count && !max_bad_count) { | 236 | if (bad_count && !max_bad_count) { |
| 248 | // Trigger warning. | 237 | // Trigger warning. |
| 249 | (void)tooManyBadTokens(); | 238 | (void)tooManyBadTokens(); |
| 250 | - return {QPDF_Null::create()}; | 239 | + return {QPDFObject::create<QPDF_Null>()}; |
| 251 | } | 240 | } |
| 252 | if (frame->state <= st_dictionary_value) { | 241 | if (frame->state <= st_dictionary_value) { |
| 253 | // Attempt to recover more or less gracefully from invalid dictionaries. | 242 | // Attempt to recover more or less gracefully from invalid dictionaries. |
| @@ -258,7 +247,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -258,7 +247,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 258 | warn( | 247 | warn( |
| 259 | frame->offset, | 248 | frame->offset, |
| 260 | "dictionary ended prematurely; using null as value for last key"); | 249 | "dictionary ended prematurely; using null as value for last key"); |
| 261 | - dict[frame->key] = QPDF_Null::create(); | 250 | + dict[frame->key] = QPDFObject::create<QPDF_Null>(); |
| 262 | } | 251 | } |
| 263 | 252 | ||
| 264 | if (!frame->olist.empty()) { | 253 | if (!frame->olist.empty()) { |
| @@ -271,7 +260,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -271,7 +260,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 271 | dict["/Contents"] = QPDFObjectHandle::newString(frame->contents_string); | 260 | dict["/Contents"] = QPDFObjectHandle::newString(frame->contents_string); |
| 272 | dict["/Contents"].setParsedOffset(frame->contents_offset); | 261 | dict["/Contents"].setParsedOffset(frame->contents_offset); |
| 273 | } | 262 | } |
| 274 | - auto object = QPDF_Dictionary::create(std::move(dict)); | 263 | + auto object = QPDFObject::create<QPDF_Dictionary>(std::move(dict)); |
| 275 | setDescription(object, frame->offset - 2); | 264 | setDescription(object, frame->offset - 2); |
| 276 | // The `offset` points to the next of "<<". Set the rewind offset to point to the | 265 | // The `offset` points to the next of "<<". Set the rewind offset to point to the |
| 277 | // beginning of "<<". This has been explicitly tested with whitespace surrounding | 266 | // beginning of "<<". This has been explicitly tested with whitespace surrounding |
| @@ -287,7 +276,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -287,7 +276,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 287 | QTC::TC("qpdf", "QPDFParser bad dictionary close in parseRemainder"); | 276 | QTC::TC("qpdf", "QPDFParser bad dictionary close in parseRemainder"); |
| 288 | warn("unexpected dictionary close token"); | 277 | warn("unexpected dictionary close token"); |
| 289 | if (tooManyBadTokens()) { | 278 | if (tooManyBadTokens()) { |
| 290 | - return {QPDF_Null::create()}; | 279 | + return {QPDFObject::create<QPDF_Null>()}; |
| 291 | } | 280 | } |
| 292 | addNull(); | 281 | addNull(); |
| 293 | } | 282 | } |
| @@ -298,7 +287,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -298,7 +287,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 298 | if (stack.size() > 499) { | 287 | if (stack.size() > 499) { |
| 299 | QTC::TC("qpdf", "QPDFParser too deep"); | 288 | QTC::TC("qpdf", "QPDFParser too deep"); |
| 300 | warn("ignoring excessively deeply nested data structure"); | 289 | warn("ignoring excessively deeply nested data structure"); |
| 301 | - return {QPDF_Null::create()}; | 290 | + return {QPDFObject::create<QPDF_Null>()}; |
| 302 | } else { | 291 | } else { |
| 303 | b_contents = false; | 292 | b_contents = false; |
| 304 | stack.emplace_back( | 293 | stack.emplace_back( |
| @@ -350,7 +339,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -350,7 +339,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 350 | QTC::TC("qpdf", "QPDFParser treat word as string in parseRemainder"); | 339 | QTC::TC("qpdf", "QPDFParser treat word as string in parseRemainder"); |
| 351 | warn("unknown token while reading object; treating as string"); | 340 | warn("unknown token while reading object; treating as string"); |
| 352 | if (tooManyBadTokens()) { | 341 | if (tooManyBadTokens()) { |
| 353 | - return {QPDF_Null::create()}; | 342 | + return {QPDFObject::create<QPDF_Null>()}; |
| 354 | } | 343 | } |
| 355 | addScalar<QPDF_String>(tokenizer.getValue()); | 344 | addScalar<QPDF_String>(tokenizer.getValue()); |
| 356 | } | 345 | } |
| @@ -377,7 +366,7 @@ QPDFParser::parseRemainder(bool content_stream) | @@ -377,7 +366,7 @@ QPDFParser::parseRemainder(bool content_stream) | ||
| 377 | default: | 366 | default: |
| 378 | warn("treating unknown token type as null while reading object"); | 367 | warn("treating unknown token type as null while reading object"); |
| 379 | if (tooManyBadTokens()) { | 368 | if (tooManyBadTokens()) { |
| 380 | - return {QPDF_Null::create()}; | 369 | + return {QPDFObject::create<QPDF_Null>()}; |
| 381 | } | 370 | } |
| 382 | addNull(); | 371 | addNull(); |
| 383 | } | 372 | } |
| @@ -402,7 +391,7 @@ QPDFParser::add(std::shared_ptr<QPDFObject>&& obj) | @@ -402,7 +391,7 @@ QPDFParser::add(std::shared_ptr<QPDFObject>&& obj) | ||
| 402 | void | 391 | void |
| 403 | QPDFParser::addNull() | 392 | QPDFParser::addNull() |
| 404 | { | 393 | { |
| 405 | - const static ObjectPtr null_obj = QPDF_Null::create(); | 394 | + const static ObjectPtr null_obj = QPDFObject::create<QPDF_Null>(); |
| 406 | 395 | ||
| 407 | if (frame->state != st_dictionary_value) { | 396 | if (frame->state != st_dictionary_value) { |
| 408 | // If state is st_dictionary_key then there is a missing key. Push onto olist for | 397 | // If state is st_dictionary_key then there is a missing key. Push onto olist for |
| @@ -420,7 +409,7 @@ QPDFParser::addNull() | @@ -420,7 +409,7 @@ QPDFParser::addNull() | ||
| 420 | void | 409 | void |
| 421 | QPDFParser::addInt(int count) | 410 | QPDFParser::addInt(int count) |
| 422 | { | 411 | { |
| 423 | - auto obj = QPDF_Integer::create(int_buffer[count % 2]); | 412 | + auto obj = QPDFObject::create<QPDF_Integer>(int_buffer[count % 2]); |
| 424 | obj->setDescription(context, description, last_offset_buffer[count % 2]); | 413 | obj->setDescription(context, description, last_offset_buffer[count % 2]); |
| 425 | add(std::move(obj)); | 414 | add(std::move(obj)); |
| 426 | } | 415 | } |
| @@ -435,7 +424,7 @@ QPDFParser::addScalar(Args&&... args) | @@ -435,7 +424,7 @@ QPDFParser::addScalar(Args&&... args) | ||
| 435 | max_bad_count = 0; | 424 | max_bad_count = 0; |
| 436 | return; | 425 | return; |
| 437 | } | 426 | } |
| 438 | - auto obj = T::create(args...); | 427 | + auto obj = QPDFObject::create<T>(std::forward<Args>(args)...); |
| 439 | obj->setDescription(context, description, input.getLastOffset()); | 428 | obj->setDescription(context, description, input.getLastOffset()); |
| 440 | add(std::move(obj)); | 429 | add(std::move(obj)); |
| 441 | } | 430 | } |
| @@ -444,7 +433,7 @@ template <typename T, typename... Args> | @@ -444,7 +433,7 @@ template <typename T, typename... Args> | ||
| 444 | QPDFObjectHandle | 433 | QPDFObjectHandle |
| 445 | QPDFParser::withDescription(Args&&... args) | 434 | QPDFParser::withDescription(Args&&... args) |
| 446 | { | 435 | { |
| 447 | - auto obj = T::create(args...); | 436 | + auto obj = QPDFObject::create<T>(std::forward<Args>(args)...); |
| 448 | obj->setDescription(context, description, start); | 437 | obj->setDescription(context, description, start); |
| 449 | return {obj}; | 438 | return {obj}; |
| 450 | } | 439 | } |
libqpdf/QPDFValue.cc deleted
| 1 | -#include <qpdf/QPDFValue.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/QPDFObject_private.hh> | ||
| 4 | - | ||
| 5 | -std::shared_ptr<QPDFObject> | ||
| 6 | -QPDFValue::do_create(QPDFValue* object) | ||
| 7 | -{ | ||
| 8 | - std::shared_ptr<QPDFObject> obj(new QPDFObject()); | ||
| 9 | - obj->value = std::shared_ptr<QPDFValue>(object); | ||
| 10 | - return obj; | ||
| 11 | -} | ||
| 12 | - | ||
| 13 | -std::string | ||
| 14 | -QPDFValue::getDescription() | ||
| 15 | -{ | ||
| 16 | - if (object_description) { | ||
| 17 | - switch (object_description->index()) { | ||
| 18 | - case 0: | ||
| 19 | - { | ||
| 20 | - // Simple template string | ||
| 21 | - auto description = std::get<0>(*object_description); | ||
| 22 | - | ||
| 23 | - if (auto pos = description.find("$OG"); pos != std::string::npos) { | ||
| 24 | - description.replace(pos, 3, og.unparse(' ')); | ||
| 25 | - } | ||
| 26 | - if (auto pos = description.find("$PO"); pos != std::string::npos) { | ||
| 27 | - qpdf_offset_t shift = (type_code == ::ot_dictionary) ? 2 | ||
| 28 | - : (type_code == ::ot_array) ? 1 | ||
| 29 | - : 0; | ||
| 30 | - | ||
| 31 | - description.replace(pos, 3, std::to_string(parsed_offset + shift)); | ||
| 32 | - } | ||
| 33 | - return description; | ||
| 34 | - } | ||
| 35 | - case 1: | ||
| 36 | - { | ||
| 37 | - // QPDF::JSONReactor generated description | ||
| 38 | - auto j_descr = std::get<1>(*object_description); | ||
| 39 | - return ( | ||
| 40 | - *j_descr.input + (j_descr.object.empty() ? "" : ", " + j_descr.object) + | ||
| 41 | - " at offset " + std::to_string(parsed_offset)); | ||
| 42 | - } | ||
| 43 | - case 2: | ||
| 44 | - { | ||
| 45 | - // Child object description | ||
| 46 | - auto j_descr = std::get<2>(*object_description); | ||
| 47 | - std::string result; | ||
| 48 | - if (auto p = j_descr.parent.lock()) { | ||
| 49 | - result = p->getDescription(); | ||
| 50 | - } | ||
| 51 | - result += j_descr.static_descr; | ||
| 52 | - if (auto pos = result.find("$VD"); pos != std::string::npos) { | ||
| 53 | - result.replace(pos, 3, j_descr.var_descr); | ||
| 54 | - } | ||
| 55 | - return result; | ||
| 56 | - } | ||
| 57 | - } | ||
| 58 | - } else if (og.isIndirect()) { | ||
| 59 | - return "object " + og.unparse(' '); | ||
| 60 | - } | ||
| 61 | - return {}; | ||
| 62 | -} |
libqpdf/QPDFWriter.cc
| @@ -16,8 +16,7 @@ | @@ -16,8 +16,7 @@ | ||
| 16 | #include <qpdf/QIntC.hh> | 16 | #include <qpdf/QIntC.hh> |
| 17 | #include <qpdf/QPDF.hh> | 17 | #include <qpdf/QPDF.hh> |
| 18 | #include <qpdf/QPDFObjectHandle_private.hh> | 18 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 19 | -#include <qpdf/QPDF_Name.hh> | ||
| 20 | -#include <qpdf/QPDF_String.hh> | 19 | +#include <qpdf/QPDFObject_private.hh> |
| 21 | #include <qpdf/QTC.hh> | 20 | #include <qpdf/QTC.hh> |
| 22 | #include <qpdf/QUtil.hh> | 21 | #include <qpdf/QUtil.hh> |
| 23 | #include <qpdf/RC4.hh> | 22 | #include <qpdf/RC4.hh> |
libqpdf/QPDF_Array.cc
| 1 | -#include <qpdf/QPDF_Array.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | #include <qpdf/QPDFObjectHandle_private.hh> | 1 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 5 | -#include <qpdf/QPDFObject_private.hh> | ||
| 6 | -#include <qpdf/QPDF_Null.hh> | 2 | + |
| 7 | #include <qpdf/QTC.hh> | 3 | #include <qpdf/QTC.hh> |
| 8 | 4 | ||
| 9 | using namespace std::literals; | 5 | using namespace std::literals; |
| @@ -40,25 +36,12 @@ Array::checkOwnership(QPDFObjectHandle const& item) const | @@ -40,25 +36,12 @@ Array::checkOwnership(QPDFObjectHandle const& item) const | ||
| 40 | } | 36 | } |
| 41 | } | 37 | } |
| 42 | 38 | ||
| 43 | -QPDF_Array::QPDF_Array() : | ||
| 44 | - QPDFValue(::ot_array) | ||
| 45 | -{ | ||
| 46 | -} | ||
| 47 | - | ||
| 48 | -QPDF_Array::QPDF_Array(QPDF_Array const& other) : | ||
| 49 | - QPDFValue(::ot_array), | ||
| 50 | - sp(other.sp ? std::make_unique<Sparse>(*other.sp) : nullptr) | ||
| 51 | -{ | ||
| 52 | -} | ||
| 53 | - | ||
| 54 | -QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) : | ||
| 55 | - QPDFValue(::ot_array) | 39 | +QPDF_Array::QPDF_Array(std::vector<QPDFObjectHandle> const& v) |
| 56 | { | 40 | { |
| 57 | setFromVector(v); | 41 | setFromVector(v); |
| 58 | } | 42 | } |
| 59 | 43 | ||
| 60 | -QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse) : | ||
| 61 | - QPDFValue(::ot_array) | 44 | +QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse) |
| 62 | { | 45 | { |
| 63 | if (sparse) { | 46 | if (sparse) { |
| 64 | sp = std::make_unique<Sparse>(); | 47 | sp = std::make_unique<Sparse>(); |
| @@ -73,132 +56,6 @@ QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse | @@ -73,132 +56,6 @@ QPDF_Array::QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& v, bool sparse | ||
| 73 | } | 56 | } |
| 74 | } | 57 | } |
| 75 | 58 | ||
| 76 | -std::shared_ptr<QPDFObject> | ||
| 77 | -QPDF_Array::create(std::vector<QPDFObjectHandle> const& items) | ||
| 78 | -{ | ||
| 79 | - return do_create(new QPDF_Array(items)); | ||
| 80 | -} | ||
| 81 | - | ||
| 82 | -std::shared_ptr<QPDFObject> | ||
| 83 | -QPDF_Array::create(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse) | ||
| 84 | -{ | ||
| 85 | - return do_create(new QPDF_Array(std::move(items), sparse)); | ||
| 86 | -} | ||
| 87 | - | ||
| 88 | -std::shared_ptr<QPDFObject> | ||
| 89 | -QPDF_Array::copy(bool shallow) | ||
| 90 | -{ | ||
| 91 | - if (shallow) { | ||
| 92 | - return do_create(new QPDF_Array(*this)); | ||
| 93 | - } else { | ||
| 94 | - QTC::TC("qpdf", "QPDF_Array copy", sp ? 0 : 1); | ||
| 95 | - if (sp) { | ||
| 96 | - auto* result = new QPDF_Array(); | ||
| 97 | - result->sp = std::make_unique<Sparse>(); | ||
| 98 | - result->sp->size = sp->size; | ||
| 99 | - for (auto const& element: sp->elements) { | ||
| 100 | - auto const& obj = element.second; | ||
| 101 | - result->sp->elements[element.first] = | ||
| 102 | - obj->getObjGen().isIndirect() ? obj : obj->copy(); | ||
| 103 | - } | ||
| 104 | - return do_create(result); | ||
| 105 | - } else { | ||
| 106 | - std::vector<std::shared_ptr<QPDFObject>> result; | ||
| 107 | - result.reserve(elements.size()); | ||
| 108 | - for (auto const& element: elements) { | ||
| 109 | - result.push_back( | ||
| 110 | - element ? (element->getObjGen().isIndirect() ? element : element->copy()) | ||
| 111 | - : element); | ||
| 112 | - } | ||
| 113 | - return create(std::move(result), false); | ||
| 114 | - } | ||
| 115 | - } | ||
| 116 | -} | ||
| 117 | - | ||
| 118 | -void | ||
| 119 | -QPDF_Array::disconnect() | ||
| 120 | -{ | ||
| 121 | - if (sp) { | ||
| 122 | - for (auto& item: sp->elements) { | ||
| 123 | - auto& obj = item.second; | ||
| 124 | - if (!obj->getObjGen().isIndirect()) { | ||
| 125 | - obj->disconnect(); | ||
| 126 | - } | ||
| 127 | - } | ||
| 128 | - } else { | ||
| 129 | - for (auto& obj: elements) { | ||
| 130 | - if (!obj->getObjGen().isIndirect()) { | ||
| 131 | - obj->disconnect(); | ||
| 132 | - } | ||
| 133 | - } | ||
| 134 | - } | ||
| 135 | -} | ||
| 136 | - | ||
| 137 | -std::string | ||
| 138 | -QPDF_Array::unparse() | ||
| 139 | -{ | ||
| 140 | - std::string result = "[ "; | ||
| 141 | - if (sp) { | ||
| 142 | - int next = 0; | ||
| 143 | - for (auto& item: sp->elements) { | ||
| 144 | - int key = item.first; | ||
| 145 | - for (int j = next; j < key; ++j) { | ||
| 146 | - result += "null "; | ||
| 147 | - } | ||
| 148 | - auto og = item.second->resolved_object()->getObjGen(); | ||
| 149 | - result += og.isIndirect() ? og.unparse(' ') + " R " : item.second->unparse() + " "; | ||
| 150 | - next = ++key; | ||
| 151 | - } | ||
| 152 | - for (int j = next; j < sp->size; ++j) { | ||
| 153 | - result += "null "; | ||
| 154 | - } | ||
| 155 | - } else { | ||
| 156 | - for (auto const& item: elements) { | ||
| 157 | - auto og = item->resolved_object()->getObjGen(); | ||
| 158 | - result += og.isIndirect() ? og.unparse(' ') + " R " : item->unparse() + " "; | ||
| 159 | - } | ||
| 160 | - } | ||
| 161 | - result += "]"; | ||
| 162 | - return result; | ||
| 163 | -} | ||
| 164 | - | ||
| 165 | -void | ||
| 166 | -QPDF_Array::writeJSON(int json_version, JSON::Writer& p) | ||
| 167 | -{ | ||
| 168 | - p.writeStart('['); | ||
| 169 | - if (sp) { | ||
| 170 | - int next = 0; | ||
| 171 | - for (auto& item: sp->elements) { | ||
| 172 | - int key = item.first; | ||
| 173 | - for (int j = next; j < key; ++j) { | ||
| 174 | - p.writeNext() << "null"; | ||
| 175 | - } | ||
| 176 | - p.writeNext(); | ||
| 177 | - auto og = item.second->getObjGen(); | ||
| 178 | - if (og.isIndirect()) { | ||
| 179 | - p << "\"" << og.unparse(' ') << " R\""; | ||
| 180 | - } else { | ||
| 181 | - item.second->writeJSON(json_version, p); | ||
| 182 | - } | ||
| 183 | - next = ++key; | ||
| 184 | - } | ||
| 185 | - for (int j = next; j < sp->size; ++j) { | ||
| 186 | - p.writeNext() << "null"; | ||
| 187 | - } | ||
| 188 | - } else { | ||
| 189 | - for (auto const& item: elements) { | ||
| 190 | - p.writeNext(); | ||
| 191 | - auto og = item->getObjGen(); | ||
| 192 | - if (og.isIndirect()) { | ||
| 193 | - p << "\"" << og.unparse(' ') << " R\""; | ||
| 194 | - } else { | ||
| 195 | - item->writeJSON(json_version, p); | ||
| 196 | - } | ||
| 197 | - } | ||
| 198 | - } | ||
| 199 | - p.writeEnd(']'); | ||
| 200 | -} | ||
| 201 | - | ||
| 202 | QPDF_Array* | 59 | QPDF_Array* |
| 203 | Array::array() const | 60 | Array::array() const |
| 204 | { | 61 | { |
libqpdf/QPDF_Bool.cc deleted
| 1 | -#include <qpdf/QPDF_Bool.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | - | ||
| 5 | -QPDF_Bool::QPDF_Bool(bool val) : | ||
| 6 | - QPDFValue(::ot_boolean), | ||
| 7 | - val(val) | ||
| 8 | -{ | ||
| 9 | -} | ||
| 10 | - | ||
| 11 | -std::shared_ptr<QPDFObject> | ||
| 12 | -QPDF_Bool::create(bool value) | ||
| 13 | -{ | ||
| 14 | - return do_create(new QPDF_Bool(value)); | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -std::shared_ptr<QPDFObject> | ||
| 18 | -QPDF_Bool::copy(bool shallow) | ||
| 19 | -{ | ||
| 20 | - return create(val); | ||
| 21 | -} | ||
| 22 | - | ||
| 23 | -std::string | ||
| 24 | -QPDF_Bool::unparse() | ||
| 25 | -{ | ||
| 26 | - return (val ? "true" : "false"); | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -void | ||
| 30 | -QPDF_Bool::writeJSON(int json_version, JSON::Writer& p) | ||
| 31 | -{ | ||
| 32 | - p << val; | ||
| 33 | -} | ||
| 34 | - | ||
| 35 | -bool | ||
| 36 | -QPDF_Bool::getVal() const | ||
| 37 | -{ | ||
| 38 | - return this->val; | ||
| 39 | -} |
libqpdf/QPDF_Destroyed.cc deleted
| 1 | -#include <qpdf/QPDF_Destroyed.hh> | ||
| 2 | - | ||
| 3 | -#include <stdexcept> | ||
| 4 | - | ||
| 5 | -QPDF_Destroyed::QPDF_Destroyed() : | ||
| 6 | - QPDFValue(::ot_destroyed) | ||
| 7 | -{ | ||
| 8 | -} | ||
| 9 | - | ||
| 10 | -std::shared_ptr<QPDFValue> | ||
| 11 | -QPDF_Destroyed::getInstance() | ||
| 12 | -{ | ||
| 13 | - static std::shared_ptr<QPDFValue> instance(new QPDF_Destroyed()); | ||
| 14 | - return instance; | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -std::shared_ptr<QPDFObject> | ||
| 18 | -QPDF_Destroyed::copy(bool shallow) | ||
| 19 | -{ | ||
| 20 | - throw std::logic_error("attempted to shallow copy QPDFObjectHandle from destroyed QPDF"); | ||
| 21 | - return nullptr; | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -std::string | ||
| 25 | -QPDF_Destroyed::unparse() | ||
| 26 | -{ | ||
| 27 | - throw std::logic_error("attempted to unparse a QPDFObjectHandle from a destroyed QPDF"); | ||
| 28 | - return ""; | ||
| 29 | -} | ||
| 30 | - | ||
| 31 | -void | ||
| 32 | -QPDF_Destroyed::writeJSON(int json_version, JSON::Writer& p) | ||
| 33 | -{ | ||
| 34 | - throw std::logic_error("attempted to get JSON from a QPDFObjectHandle from a destroyed QPDF"); | ||
| 35 | -} | ||
| 36 | \ No newline at end of file | 0 | \ No newline at end of file |
libqpdf/QPDF_Dictionary.cc
| 1 | -#include <qpdf/QPDF_Dictionary.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | #include <qpdf/QPDFObjectHandle_private.hh> | 1 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 2 | + | ||
| 5 | #include <qpdf/QPDFObject_private.hh> | 3 | #include <qpdf/QPDFObject_private.hh> |
| 6 | -#include <qpdf/QPDF_Name.hh> | ||
| 7 | #include <qpdf/QTC.hh> | 4 | #include <qpdf/QTC.hh> |
| 8 | -#include <qpdf/QUtil.hh> | ||
| 9 | 5 | ||
| 10 | using namespace std::literals; | 6 | using namespace std::literals; |
| 11 | using namespace qpdf; | 7 | using namespace qpdf; |
| 12 | 8 | ||
| 13 | -QPDF_Dictionary::QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items) : | ||
| 14 | - QPDFValue(::ot_dictionary), | ||
| 15 | - items(items) | ||
| 16 | -{ | ||
| 17 | -} | ||
| 18 | - | ||
| 19 | -QPDF_Dictionary::QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items) : | ||
| 20 | - QPDFValue(::ot_dictionary), | ||
| 21 | - items(items) | ||
| 22 | -{ | ||
| 23 | -} | ||
| 24 | - | ||
| 25 | -std::shared_ptr<QPDFObject> | ||
| 26 | -QPDF_Dictionary::create(std::map<std::string, QPDFObjectHandle> const& items) | ||
| 27 | -{ | ||
| 28 | - return do_create(new QPDF_Dictionary(items)); | ||
| 29 | -} | ||
| 30 | - | ||
| 31 | -std::shared_ptr<QPDFObject> | ||
| 32 | -QPDF_Dictionary::create(std::map<std::string, QPDFObjectHandle>&& items) | ||
| 33 | -{ | ||
| 34 | - return do_create(new QPDF_Dictionary(items)); | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | -std::shared_ptr<QPDFObject> | ||
| 38 | -QPDF_Dictionary::copy(bool shallow) | ||
| 39 | -{ | ||
| 40 | - if (shallow) { | ||
| 41 | - return create(items); | ||
| 42 | - } else { | ||
| 43 | - std::map<std::string, QPDFObjectHandle> new_items; | ||
| 44 | - for (auto const& item: this->items) { | ||
| 45 | - auto value = item.second; | ||
| 46 | - new_items[item.first] = value.isIndirect() ? value : value.shallowCopy(); | ||
| 47 | - } | ||
| 48 | - return create(new_items); | ||
| 49 | - } | ||
| 50 | -} | ||
| 51 | - | ||
| 52 | -void | ||
| 53 | -QPDF_Dictionary::disconnect() | ||
| 54 | -{ | ||
| 55 | - for (auto& iter: this->items) { | ||
| 56 | - QPDFObjectHandle::DisconnectAccess::disconnect(iter.second); | ||
| 57 | - } | ||
| 58 | -} | ||
| 59 | - | ||
| 60 | -std::string | ||
| 61 | -QPDF_Dictionary::unparse() | ||
| 62 | -{ | ||
| 63 | - std::string result = "<< "; | ||
| 64 | - for (auto& iter: this->items) { | ||
| 65 | - if (!iter.second.isNull()) { | ||
| 66 | - result += Name::normalize(iter.first) + " " + iter.second.unparse() + " "; | ||
| 67 | - } | ||
| 68 | - } | ||
| 69 | - result += ">>"; | ||
| 70 | - return result; | ||
| 71 | -} | ||
| 72 | - | ||
| 73 | -void | ||
| 74 | -QPDF_Dictionary::writeJSON(int json_version, JSON::Writer& p) | ||
| 75 | -{ | ||
| 76 | - p.writeStart('{'); | ||
| 77 | - for (auto& iter: this->items) { | ||
| 78 | - if (!iter.second.isNull()) { | ||
| 79 | - p.writeNext(); | ||
| 80 | - if (json_version == 1) { | ||
| 81 | - p << "\"" << JSON::Writer::encode_string(Name::normalize(iter.first)) << "\": "; | ||
| 82 | - } else if (auto res = Name::analyzeJSONEncoding(iter.first); res.first) { | ||
| 83 | - if (res.second) { | ||
| 84 | - p << "\"" << iter.first << "\": "; | ||
| 85 | - } else { | ||
| 86 | - p << "\"" << JSON::Writer::encode_string(iter.first) << "\": "; | ||
| 87 | - } | ||
| 88 | - } else { | ||
| 89 | - p << "\"n:" << JSON::Writer::encode_string(Name::normalize(iter.first)) << "\": "; | ||
| 90 | - } | ||
| 91 | - iter.second.writeJSON(json_version, p); | ||
| 92 | - } | ||
| 93 | - } | ||
| 94 | - p.writeEnd('}'); | ||
| 95 | -} | ||
| 96 | - | ||
| 97 | QPDF_Dictionary* | 9 | QPDF_Dictionary* |
| 98 | BaseDictionary::dict() const | 10 | BaseDictionary::dict() const |
| 99 | { | 11 | { |
libqpdf/QPDF_InlineImage.cc deleted
| 1 | -#include <qpdf/QPDF_InlineImage.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | - | ||
| 5 | -QPDF_InlineImage::QPDF_InlineImage(std::string const& val) : | ||
| 6 | - QPDFValue(::ot_inlineimage), | ||
| 7 | - val(val) | ||
| 8 | -{ | ||
| 9 | -} | ||
| 10 | - | ||
| 11 | -std::shared_ptr<QPDFObject> | ||
| 12 | -QPDF_InlineImage::create(std::string const& val) | ||
| 13 | -{ | ||
| 14 | - return do_create(new QPDF_InlineImage(val)); | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -std::shared_ptr<QPDFObject> | ||
| 18 | -QPDF_InlineImage::copy(bool shallow) | ||
| 19 | -{ | ||
| 20 | - return create(val); | ||
| 21 | -} | ||
| 22 | - | ||
| 23 | -std::string | ||
| 24 | -QPDF_InlineImage::unparse() | ||
| 25 | -{ | ||
| 26 | - return this->val; | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -void | ||
| 30 | -QPDF_InlineImage::writeJSON(int json_version, JSON::Writer& p) | ||
| 31 | -{ | ||
| 32 | - p << "null"; | ||
| 33 | -} |
libqpdf/QPDF_Integer.cc deleted
| 1 | -#include <qpdf/QPDF_Integer.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | -#include <qpdf/QUtil.hh> | ||
| 5 | - | ||
| 6 | -QPDF_Integer::QPDF_Integer(long long val) : | ||
| 7 | - QPDFValue(::ot_integer), | ||
| 8 | - val(val) | ||
| 9 | -{ | ||
| 10 | -} | ||
| 11 | - | ||
| 12 | -std::shared_ptr<QPDFObject> | ||
| 13 | -QPDF_Integer::create(long long value) | ||
| 14 | -{ | ||
| 15 | - return do_create(new QPDF_Integer(value)); | ||
| 16 | -} | ||
| 17 | - | ||
| 18 | -std::shared_ptr<QPDFObject> | ||
| 19 | -QPDF_Integer::copy(bool shallow) | ||
| 20 | -{ | ||
| 21 | - return create(val); | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -std::string | ||
| 25 | -QPDF_Integer::unparse() | ||
| 26 | -{ | ||
| 27 | - return std::to_string(this->val); | ||
| 28 | -} | ||
| 29 | - | ||
| 30 | -void | ||
| 31 | -QPDF_Integer::writeJSON(int json_version, JSON::Writer& p) | ||
| 32 | -{ | ||
| 33 | - p << std::to_string(this->val); | ||
| 34 | -} | ||
| 35 | - | ||
| 36 | -long long | ||
| 37 | -QPDF_Integer::getVal() const | ||
| 38 | -{ | ||
| 39 | - return this->val; | ||
| 40 | -} |
libqpdf/QPDF_Name.cc
| 1 | -#include <qpdf/QPDF_Name.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | -#include <qpdf/QPDFObjectHandle_private.hh> | ||
| 5 | -#include <qpdf/QUtil.hh> | ||
| 6 | - | ||
| 7 | -using namespace qpdf; | ||
| 8 | - | ||
| 9 | -QPDF_Name::QPDF_Name(std::string const& name) : | ||
| 10 | - QPDFValue(::ot_name), | ||
| 11 | - name(name) | ||
| 12 | -{ | ||
| 13 | -} | ||
| 14 | - | ||
| 15 | -std::shared_ptr<QPDFObject> | ||
| 16 | -QPDF_Name::create(std::string const& name) | ||
| 17 | -{ | ||
| 18 | - return do_create(new QPDF_Name(name)); | ||
| 19 | -} | ||
| 20 | - | ||
| 21 | -std::shared_ptr<QPDFObject> | ||
| 22 | -QPDF_Name::copy(bool shallow) | ||
| 23 | -{ | ||
| 24 | - return create(name); | ||
| 25 | -} | ||
| 26 | - | ||
| 27 | -std::string | ||
| 28 | -Name::normalize(std::string const& name) | ||
| 29 | -{ | ||
| 30 | - if (name.empty()) { | ||
| 31 | - return name; | ||
| 32 | - } | ||
| 33 | - std::string result; | ||
| 34 | - result += name.at(0); | ||
| 35 | - for (size_t i = 1; i < name.length(); ++i) { | ||
| 36 | - char ch = name.at(i); | ||
| 37 | - // Don't use locale/ctype here; follow PDF spec guidelines. | ||
| 38 | - if (ch == '\0') { | ||
| 39 | - // QPDFTokenizer embeds a null character to encode an invalid #. | ||
| 40 | - result += "#"; | ||
| 41 | - } else if ( | ||
| 42 | - ch < 33 || ch == '#' || ch == '/' || ch == '(' || ch == ')' || ch == '{' || ch == '}' || | ||
| 43 | - ch == '<' || ch == '>' || ch == '[' || ch == ']' || ch == '%' || ch > 126) { | ||
| 44 | - result += QUtil::hex_encode_char(ch); | ||
| 45 | - } else { | ||
| 46 | - result += ch; | ||
| 47 | - } | ||
| 48 | - } | ||
| 49 | - return result; | ||
| 50 | -} | ||
| 51 | - | ||
| 52 | -std::string | ||
| 53 | -QPDF_Name::unparse() | ||
| 54 | -{ | ||
| 55 | - return Name::normalize(name); | ||
| 56 | -} | ||
| 57 | - | ||
| 58 | -std::pair<bool, bool> | ||
| 59 | -Name::analyzeJSONEncoding(const std::string& name) | ||
| 60 | -{ | ||
| 61 | - int tail = 0; // Number of continuation characters expected. | ||
| 62 | - bool tail2 = false; // Potential overlong 3 octet utf-8. | ||
| 63 | - bool tail3 = false; // potential overlong 4 octet | ||
| 64 | - bool needs_escaping = false; | ||
| 65 | - for (auto const& it: name) { | ||
| 66 | - auto c = static_cast<unsigned char>(it); | ||
| 67 | - if (tail) { | ||
| 68 | - if ((c & 0xc0) != 0x80) { | ||
| 69 | - return {false, false}; | ||
| 70 | - } | ||
| 71 | - if (tail2) { | ||
| 72 | - if ((c & 0xe0) == 0x80) { | ||
| 73 | - return {false, false}; | ||
| 74 | - } | ||
| 75 | - tail2 = false; | ||
| 76 | - } else if (tail3) { | ||
| 77 | - if ((c & 0xf0) == 0x80) { | ||
| 78 | - return {false, false}; | ||
| 79 | - } | ||
| 80 | - tail3 = false; | ||
| 81 | - } | ||
| 82 | - tail--; | ||
| 83 | - } else if (c < 0x80) { | ||
| 84 | - if (!needs_escaping) { | ||
| 85 | - needs_escaping = !((c > 34 && c != '\\') || c == ' ' || c == 33); | ||
| 86 | - } | ||
| 87 | - } else if ((c & 0xe0) == 0xc0) { | ||
| 88 | - if ((c & 0xfe) == 0xc0) { | ||
| 89 | - return {false, false}; | ||
| 90 | - } | ||
| 91 | - tail = 1; | ||
| 92 | - } else if ((c & 0xf0) == 0xe0) { | ||
| 93 | - tail2 = (c == 0xe0); | ||
| 94 | - tail = 2; | ||
| 95 | - } else if ((c & 0xf8) == 0xf0) { | ||
| 96 | - tail3 = (c == 0xf0); | ||
| 97 | - tail = 3; | ||
| 98 | - } else { | ||
| 99 | - return {false, false}; | ||
| 100 | - } | ||
| 101 | - } | ||
| 102 | - return {tail == 0, !needs_escaping}; | ||
| 103 | -} | ||
| 104 | - | ||
| 105 | -void | ||
| 106 | -QPDF_Name::writeJSON(int json_version, JSON::Writer& p) | ||
| 107 | -{ | ||
| 108 | - // For performance reasons this code is duplicated in QPDF_Dictionary::writeJSON. When updating | ||
| 109 | - // this method make sure QPDF_Dictionary is also update. | ||
| 110 | - if (json_version == 1) { | ||
| 111 | - p << "\"" << JSON::Writer::encode_string(Name::normalize(name)) << "\""; | ||
| 112 | - } else { | ||
| 113 | - if (auto res = Name::analyzeJSONEncoding(name); res.first) { | ||
| 114 | - if (res.second) { | ||
| 115 | - p << "\"" << name << "\""; | ||
| 116 | - } else { | ||
| 117 | - p << "\"" << JSON::Writer::encode_string(name) << "\""; | ||
| 118 | - } | ||
| 119 | - } else { | ||
| 120 | - p << "\"n:" << JSON::Writer::encode_string(Name::normalize(name)) << "\""; | ||
| 121 | - } | ||
| 122 | - } | ||
| 123 | -} |
libqpdf/QPDF_Null.cc deleted
| 1 | -#include <qpdf/QPDF_Null.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | -#include <qpdf/QPDFObject_private.hh> | ||
| 5 | - | ||
| 6 | -QPDF_Null::QPDF_Null(QPDF* qpdf, QPDFObjGen og) : | ||
| 7 | - QPDFValue(::ot_null, qpdf, og) | ||
| 8 | -{ | ||
| 9 | -} | ||
| 10 | - | ||
| 11 | -std::shared_ptr<QPDFObject> | ||
| 12 | -QPDF_Null::create(QPDF* qpdf, QPDFObjGen og) | ||
| 13 | -{ | ||
| 14 | - return do_create(new QPDF_Null(qpdf, og)); | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -std::shared_ptr<QPDFObject> | ||
| 18 | -QPDF_Null::create( | ||
| 19 | - std::shared_ptr<QPDFObject> parent, std::string_view const& static_descr, std::string var_descr) | ||
| 20 | -{ | ||
| 21 | - auto n = do_create(new QPDF_Null()); | ||
| 22 | - n->setChildDescription(parent, static_descr, var_descr); | ||
| 23 | - return n; | ||
| 24 | -} | ||
| 25 | - | ||
| 26 | -std::shared_ptr<QPDFObject> | ||
| 27 | -QPDF_Null::create( | ||
| 28 | - std::shared_ptr<QPDFValue> parent, std::string_view const& static_descr, std::string var_descr) | ||
| 29 | -{ | ||
| 30 | - auto n = do_create(new QPDF_Null()); | ||
| 31 | - n->setChildDescription(parent, static_descr, var_descr); | ||
| 32 | - return n; | ||
| 33 | -} | ||
| 34 | - | ||
| 35 | -std::shared_ptr<QPDFObject> | ||
| 36 | -QPDF_Null::copy(bool shallow) | ||
| 37 | -{ | ||
| 38 | - return create(); | ||
| 39 | -} | ||
| 40 | - | ||
| 41 | -std::string | ||
| 42 | -QPDF_Null::unparse() | ||
| 43 | -{ | ||
| 44 | - return "null"; | ||
| 45 | -} | ||
| 46 | - | ||
| 47 | -void | ||
| 48 | -QPDF_Null::writeJSON(int json_version, JSON::Writer& p) | ||
| 49 | -{ | ||
| 50 | - p << "null"; | ||
| 51 | -} |
libqpdf/QPDF_Operator.cc deleted
| 1 | -#include <qpdf/QPDF_Operator.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | - | ||
| 5 | -QPDF_Operator::QPDF_Operator(std::string const& val) : | ||
| 6 | - QPDFValue(::ot_operator), | ||
| 7 | - val(val) | ||
| 8 | -{ | ||
| 9 | -} | ||
| 10 | - | ||
| 11 | -std::shared_ptr<QPDFObject> | ||
| 12 | -QPDF_Operator::create(std::string const& val) | ||
| 13 | -{ | ||
| 14 | - return do_create(new QPDF_Operator(val)); | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -std::shared_ptr<QPDFObject> | ||
| 18 | -QPDF_Operator::copy(bool shallow) | ||
| 19 | -{ | ||
| 20 | - return create(val); | ||
| 21 | -} | ||
| 22 | - | ||
| 23 | -std::string | ||
| 24 | -QPDF_Operator::unparse() | ||
| 25 | -{ | ||
| 26 | - return val; | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -void | ||
| 30 | -QPDF_Operator::writeJSON(int json_version, JSON::Writer& p) | ||
| 31 | -{ | ||
| 32 | - p << "null"; | ||
| 33 | -} |
libqpdf/QPDF_Real.cc deleted
| 1 | -#include <qpdf/QPDF_Real.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/JSON_writer.hh> | ||
| 4 | -#include <qpdf/QUtil.hh> | ||
| 5 | - | ||
| 6 | -QPDF_Real::QPDF_Real(std::string const& val) : | ||
| 7 | - QPDFValue(::ot_real), | ||
| 8 | - val(val) | ||
| 9 | -{ | ||
| 10 | -} | ||
| 11 | - | ||
| 12 | -QPDF_Real::QPDF_Real(double value, int decimal_places, bool trim_trailing_zeroes) : | ||
| 13 | - QPDFValue(::ot_real), | ||
| 14 | - val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes)) | ||
| 15 | -{ | ||
| 16 | -} | ||
| 17 | - | ||
| 18 | -std::shared_ptr<QPDFObject> | ||
| 19 | -QPDF_Real::create(std::string const& val) | ||
| 20 | -{ | ||
| 21 | - return do_create(new QPDF_Real(val)); | ||
| 22 | -} | ||
| 23 | - | ||
| 24 | -std::shared_ptr<QPDFObject> | ||
| 25 | -QPDF_Real::create(double value, int decimal_places, bool trim_trailing_zeroes) | ||
| 26 | -{ | ||
| 27 | - return do_create(new QPDF_Real(value, decimal_places, trim_trailing_zeroes)); | ||
| 28 | -} | ||
| 29 | - | ||
| 30 | -std::shared_ptr<QPDFObject> | ||
| 31 | -QPDF_Real::copy(bool shallow) | ||
| 32 | -{ | ||
| 33 | - return create(val); | ||
| 34 | -} | ||
| 35 | - | ||
| 36 | -std::string | ||
| 37 | -QPDF_Real::unparse() | ||
| 38 | -{ | ||
| 39 | - return this->val; | ||
| 40 | -} | ||
| 41 | - | ||
| 42 | -void | ||
| 43 | -QPDF_Real::writeJSON(int json_version, JSON::Writer& p) | ||
| 44 | -{ | ||
| 45 | - if (this->val.length() == 0) { | ||
| 46 | - // Can't really happen... | ||
| 47 | - p << "0"; | ||
| 48 | - } else if (this->val.at(0) == '.') { | ||
| 49 | - p << "0" << this->val; | ||
| 50 | - } else if (this->val.length() >= 2 && this->val.at(0) == '-' && this->val.at(1) == '.') { | ||
| 51 | - p << "-0." << this->val.substr(2); | ||
| 52 | - } else { | ||
| 53 | - p << this->val; | ||
| 54 | - } | ||
| 55 | - if (val.back() == '.') { | ||
| 56 | - p << "0"; | ||
| 57 | - } | ||
| 58 | -} |
libqpdf/QPDF_Reserved.cc deleted
| 1 | -#include <qpdf/QPDF_Reserved.hh> | ||
| 2 | - | ||
| 3 | -#include <stdexcept> | ||
| 4 | - | ||
| 5 | -QPDF_Reserved::QPDF_Reserved() : | ||
| 6 | - QPDFValue(::ot_reserved) | ||
| 7 | -{ | ||
| 8 | -} | ||
| 9 | - | ||
| 10 | -std::shared_ptr<QPDFObject> | ||
| 11 | -QPDF_Reserved::create() | ||
| 12 | -{ | ||
| 13 | - return do_create(new QPDF_Reserved()); | ||
| 14 | -} | ||
| 15 | - | ||
| 16 | -std::shared_ptr<QPDFObject> | ||
| 17 | -QPDF_Reserved::copy(bool shallow) | ||
| 18 | -{ | ||
| 19 | - return create(); | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | -std::string | ||
| 23 | -QPDF_Reserved::unparse() | ||
| 24 | -{ | ||
| 25 | - throw std::logic_error("QPDFObjectHandle: attempting to unparse a reserved object"); | ||
| 26 | - return ""; | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -void | ||
| 30 | -QPDF_Reserved::writeJSON(int json_version, JSON::Writer& p) | ||
| 31 | -{ | ||
| 32 | - throw std::logic_error("QPDFObjectHandle: attempting to get JSON from a reserved object"); | ||
| 33 | -} |
libqpdf/QPDF_Stream.cc
| 1 | -#include <qpdf/QPDF_Stream.hh> | 1 | +#include <qpdf/QPDFObjectHandle_private.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/ContentNormalizer.hh> | 3 | #include <qpdf/ContentNormalizer.hh> |
| 4 | #include <qpdf/JSON_writer.hh> | 4 | #include <qpdf/JSON_writer.hh> |
| @@ -12,7 +12,6 @@ | @@ -12,7 +12,6 @@ | ||
| 12 | #include <qpdf/QIntC.hh> | 12 | #include <qpdf/QIntC.hh> |
| 13 | #include <qpdf/QPDF.hh> | 13 | #include <qpdf/QPDF.hh> |
| 14 | #include <qpdf/QPDFExc.hh> | 14 | #include <qpdf/QPDFExc.hh> |
| 15 | -#include <qpdf/QPDFObjectHandle_private.hh> | ||
| 16 | #include <qpdf/QTC.hh> | 15 | #include <qpdf/QTC.hh> |
| 17 | #include <qpdf/QUtil.hh> | 16 | #include <qpdf/QUtil.hh> |
| 18 | #include <qpdf/SF_ASCII85Decode.hh> | 17 | #include <qpdf/SF_ASCII85Decode.hh> |
| @@ -105,34 +104,14 @@ std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>> Stream | @@ -105,34 +104,14 @@ std::map<std::string, std::function<std::shared_ptr<QPDFStreamFilter>()>> Stream | ||
| 105 | {"/ASCIIHexDecode", SF_ASCIIHexDecode::factory}, | 104 | {"/ASCIIHexDecode", SF_ASCIIHexDecode::factory}, |
| 106 | }; | 105 | }; |
| 107 | 106 | ||
| 108 | -QPDF_Stream::QPDF_Stream( | ||
| 109 | - QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) : | ||
| 110 | - QPDFValue(::ot_stream, qpdf, og), | ||
| 111 | - filter_on_write(true), | ||
| 112 | - stream_dict(stream_dict), | ||
| 113 | - length(length) | ||
| 114 | -{ | ||
| 115 | - if (!stream_dict.isDictionary()) { | ||
| 116 | - throw std::logic_error( | ||
| 117 | - "stream object instantiated with non-dictionary object for dictionary"); | ||
| 118 | - } | ||
| 119 | - auto descr = std::make_shared<QPDFValue::Description>( | ||
| 120 | - qpdf->getFilename() + ", stream object " + og.unparse(' ')); | ||
| 121 | - setDescription(qpdf, descr, offset); | ||
| 122 | -} | ||
| 123 | - | ||
| 124 | -std::shared_ptr<QPDFObject> | ||
| 125 | -QPDF_Stream::create( | ||
| 126 | - QPDF* qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) | 107 | +Stream::Stream( |
| 108 | + QPDF& qpdf, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length) : | ||
| 109 | + BaseHandle(QPDFObject::create<QPDF_Stream>(&qpdf, og, std::move(stream_dict), length)) | ||
| 127 | { | 110 | { |
| 128 | - return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length)); | ||
| 129 | -} | ||
| 130 | - | ||
| 131 | -std::shared_ptr<QPDFObject> | ||
| 132 | -QPDF_Stream::copy(bool shallow) | ||
| 133 | -{ | ||
| 134 | - QTC::TC("qpdf", "QPDF_Stream ERR shallow copy stream"); | ||
| 135 | - throw std::runtime_error("stream objects cannot be cloned"); | 111 | + auto descr = std::make_shared<QPDFObject::Description>( |
| 112 | + qpdf.getFilename() + ", stream object " + og.unparse(' ')); | ||
| 113 | + obj->setDescription(&qpdf, descr, offset); | ||
| 114 | + setDictDescription(); | ||
| 136 | } | 115 | } |
| 137 | 116 | ||
| 138 | void | 117 | void |
| @@ -142,26 +121,6 @@ Stream::registerStreamFilter( | @@ -142,26 +121,6 @@ Stream::registerStreamFilter( | ||
| 142 | filter_factories[filter_name] = factory; | 121 | filter_factories[filter_name] = factory; |
| 143 | } | 122 | } |
| 144 | 123 | ||
| 145 | -void | ||
| 146 | -QPDF_Stream::disconnect() | ||
| 147 | -{ | ||
| 148 | - this->stream_provider = nullptr; | ||
| 149 | - QPDFObjectHandle::DisconnectAccess::disconnect(this->stream_dict); | ||
| 150 | -} | ||
| 151 | - | ||
| 152 | -std::string | ||
| 153 | -QPDF_Stream::unparse() | ||
| 154 | -{ | ||
| 155 | - // Unparse stream objects as indirect references | ||
| 156 | - return og.unparse(' ') + " R"; | ||
| 157 | -} | ||
| 158 | - | ||
| 159 | -void | ||
| 160 | -QPDF_Stream::writeJSON(int json_version, JSON::Writer& jw) | ||
| 161 | -{ | ||
| 162 | - stream_dict.writeJSON(json_version, jw); | ||
| 163 | -} | ||
| 164 | - | ||
| 165 | JSON | 124 | JSON |
| 166 | Stream::getStreamJSON( | 125 | Stream::getStreamJSON( |
| 167 | int json_version, | 126 | int json_version, |
| @@ -278,34 +237,27 @@ Stream::writeStreamJSON( | @@ -278,34 +237,27 @@ Stream::writeStreamJSON( | ||
| 278 | } | 237 | } |
| 279 | 238 | ||
| 280 | void | 239 | void |
| 281 | -QPDF_Stream::setDescription( | ||
| 282 | - QPDF* qpdf, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) | 240 | +qpdf::Stream::setDictDescription() |
| 283 | { | 241 | { |
| 284 | - this->QPDFValue::setDescription(qpdf, description, offset); | ||
| 285 | - setDictDescription(); | ||
| 286 | -} | ||
| 287 | - | ||
| 288 | -void | ||
| 289 | -QPDF_Stream::setDictDescription() | ||
| 290 | -{ | ||
| 291 | - if (!this->stream_dict.hasObjectDescription()) { | ||
| 292 | - this->stream_dict.setObjectDescription(qpdf, getDescription() + " -> stream dictionary"); | 242 | + auto s = stream(); |
| 243 | + if (!s->stream_dict.hasObjectDescription()) { | ||
| 244 | + s->stream_dict.setObjectDescription( | ||
| 245 | + obj->getQPDF(), obj->getDescription() + " -> stream dictionary"); | ||
| 293 | } | 246 | } |
| 294 | } | 247 | } |
| 295 | 248 | ||
| 296 | std::shared_ptr<Buffer> | 249 | std::shared_ptr<Buffer> |
| 297 | Stream::getStreamData(qpdf_stream_decode_level_e decode_level) | 250 | Stream::getStreamData(qpdf_stream_decode_level_e decode_level) |
| 298 | { | 251 | { |
| 299 | - auto s = stream(); | ||
| 300 | Pl_Buffer buf("stream data buffer"); | 252 | Pl_Buffer buf("stream data buffer"); |
| 301 | bool filtered; | 253 | bool filtered; |
| 302 | pipeStreamData(&buf, &filtered, 0, decode_level, false, false); | 254 | pipeStreamData(&buf, &filtered, 0, decode_level, false, false); |
| 303 | if (!filtered) { | 255 | if (!filtered) { |
| 304 | throw QPDFExc( | 256 | throw QPDFExc( |
| 305 | qpdf_e_unsupported, | 257 | qpdf_e_unsupported, |
| 306 | - s->qpdf->getFilename(), | 258 | + obj->getQPDF()->getFilename(), |
| 307 | "", | 259 | "", |
| 308 | - s->parsed_offset, | 260 | + obj->getParsedOffset(), |
| 309 | "getStreamData called on unfilterable stream"); | 261 | "getStreamData called on unfilterable stream"); |
| 310 | } | 262 | } |
| 311 | QTC::TC("qpdf", "QPDF_Stream getStreamData"); | 263 | QTC::TC("qpdf", "QPDF_Stream getStreamData"); |
| @@ -315,14 +267,13 @@ Stream::getStreamData(qpdf_stream_decode_level_e decode_level) | @@ -315,14 +267,13 @@ Stream::getStreamData(qpdf_stream_decode_level_e decode_level) | ||
| 315 | std::shared_ptr<Buffer> | 267 | std::shared_ptr<Buffer> |
| 316 | Stream::getRawStreamData() | 268 | Stream::getRawStreamData() |
| 317 | { | 269 | { |
| 318 | - auto s = stream(); | ||
| 319 | Pl_Buffer buf("stream data buffer"); | 270 | Pl_Buffer buf("stream data buffer"); |
| 320 | if (!pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false)) { | 271 | if (!pipeStreamData(&buf, nullptr, 0, qpdf_dl_none, false, false)) { |
| 321 | throw QPDFExc( | 272 | throw QPDFExc( |
| 322 | qpdf_e_unsupported, | 273 | qpdf_e_unsupported, |
| 323 | - s->qpdf->getFilename(), | 274 | + obj->getQPDF()->getFilename(), |
| 324 | "", | 275 | "", |
| 325 | - s->parsed_offset, | 276 | + obj->getParsedOffset(), |
| 326 | "error getting raw stream data"); | 277 | "error getting raw stream data"); |
| 327 | } | 278 | } |
| 328 | QTC::TC("qpdf", "QPDF_Stream getRawStreamData"); | 279 | QTC::TC("qpdf", "QPDF_Stream getRawStreamData"); |
| @@ -532,12 +483,12 @@ Stream::pipeStreamData( | @@ -532,12 +483,12 @@ Stream::pipeStreamData( | ||
| 532 | Pl_Count count("stream provider count", pipeline); | 483 | Pl_Count count("stream provider count", pipeline); |
| 533 | if (s->stream_provider->supportsRetry()) { | 484 | if (s->stream_provider->supportsRetry()) { |
| 534 | if (!s->stream_provider->provideStreamData( | 485 | if (!s->stream_provider->provideStreamData( |
| 535 | - s->og, &count, suppress_warnings, will_retry)) { | 486 | + obj->getObjGen(), &count, suppress_warnings, will_retry)) { |
| 536 | filter = false; | 487 | filter = false; |
| 537 | success = false; | 488 | success = false; |
| 538 | } | 489 | } |
| 539 | } else { | 490 | } else { |
| 540 | - s->stream_provider->provideStreamData(s->og, &count); | 491 | + s->stream_provider->provideStreamData(obj->getObjGen(), &count); |
| 541 | } | 492 | } |
| 542 | qpdf_offset_t actual_length = count.getCount(); | 493 | qpdf_offset_t actual_length = count.getCount(); |
| 543 | qpdf_offset_t desired_length = 0; | 494 | qpdf_offset_t desired_length = 0; |
| @@ -550,7 +501,7 @@ Stream::pipeStreamData( | @@ -550,7 +501,7 @@ Stream::pipeStreamData( | ||
| 550 | // This would be caused by programmer error on the part of a library user, not by | 501 | // This would be caused by programmer error on the part of a library user, not by |
| 551 | // invalid input data. | 502 | // invalid input data. |
| 552 | throw std::runtime_error( | 503 | throw std::runtime_error( |
| 553 | - "stream data provider for " + s->og.unparse(' ') + " provided " + | 504 | + "stream data provider for " + obj->getObjGen().unparse(' ') + " provided " + |
| 554 | std::to_string(actual_length) + " bytes instead of expected " + | 505 | std::to_string(actual_length) + " bytes instead of expected " + |
| 555 | std::to_string(desired_length) + " bytes"); | 506 | std::to_string(desired_length) + " bytes"); |
| 556 | } | 507 | } |
| @@ -558,15 +509,15 @@ Stream::pipeStreamData( | @@ -558,15 +509,15 @@ Stream::pipeStreamData( | ||
| 558 | QTC::TC("qpdf", "QPDF_Stream provider length not provided"); | 509 | QTC::TC("qpdf", "QPDF_Stream provider length not provided"); |
| 559 | s->stream_dict.replaceKey("/Length", QPDFObjectHandle::newInteger(actual_length)); | 510 | s->stream_dict.replaceKey("/Length", QPDFObjectHandle::newInteger(actual_length)); |
| 560 | } | 511 | } |
| 561 | - } else if (s->parsed_offset == 0) { | 512 | + } else if (obj->getParsedOffset() == 0) { |
| 562 | QTC::TC("qpdf", "QPDF_Stream pipe no stream data"); | 513 | QTC::TC("qpdf", "QPDF_Stream pipe no stream data"); |
| 563 | throw std::logic_error("pipeStreamData called for stream with no data"); | 514 | throw std::logic_error("pipeStreamData called for stream with no data"); |
| 564 | } else { | 515 | } else { |
| 565 | QTC::TC("qpdf", "QPDF_Stream pipe original stream data"); | 516 | QTC::TC("qpdf", "QPDF_Stream pipe original stream data"); |
| 566 | if (!QPDF::Pipe::pipeStreamData( | 517 | if (!QPDF::Pipe::pipeStreamData( |
| 567 | - s->qpdf, | ||
| 568 | - s->og, | ||
| 569 | - s->parsed_offset, | 518 | + obj->getQPDF(), |
| 519 | + obj->getObjGen(), | ||
| 520 | + obj->getParsedOffset(), | ||
| 570 | s->length, | 521 | s->length, |
| 571 | s->stream_dict, | 522 | s->stream_dict, |
| 572 | pipeline, | 523 | pipeline, |
| @@ -642,8 +593,7 @@ Stream::replaceFilterData( | @@ -642,8 +593,7 @@ Stream::replaceFilterData( | ||
| 642 | void | 593 | void |
| 643 | Stream::warn(std::string const& message) | 594 | Stream::warn(std::string const& message) |
| 644 | { | 595 | { |
| 645 | - auto s = stream(); | ||
| 646 | - s->qpdf->warn(qpdf_e_damaged_pdf, "", s->parsed_offset, message); | 596 | + obj->getQPDF()->warn(qpdf_e_damaged_pdf, "", obj->getParsedOffset(), message); |
| 647 | } | 597 | } |
| 648 | 598 | ||
| 649 | QPDFObjectHandle | 599 | QPDFObjectHandle |
libqpdf/QPDF_String.cc
| 1 | -#include <qpdf/QPDF_String.hh> | 1 | +#include <qpdf/QPDFObject_private.hh> |
| 2 | 2 | ||
| 3 | -#include <qpdf/JSON_writer.hh> | 3 | +#include <qpdf/QPDFObjectHandle_private.hh> |
| 4 | #include <qpdf/QUtil.hh> | 4 | #include <qpdf/QUtil.hh> |
| 5 | 5 | ||
| 6 | // DO NOT USE ctype -- it is locale dependent for some things, and it's not worth the risk of | 6 | // DO NOT USE ctype -- it is locale dependent for some things, and it's not worth the risk of |
| @@ -12,18 +12,6 @@ is_iso_latin1_printable(char ch) | @@ -12,18 +12,6 @@ is_iso_latin1_printable(char ch) | ||
| 12 | return (((ch >= 32) && (ch <= 126)) || (static_cast<unsigned char>(ch) >= 160)); | 12 | return (((ch >= 32) && (ch <= 126)) || (static_cast<unsigned char>(ch) >= 160)); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | -QPDF_String::QPDF_String(std::string const& val) : | ||
| 16 | - QPDFValue(::ot_string), | ||
| 17 | - val(val) | ||
| 18 | -{ | ||
| 19 | -} | ||
| 20 | - | ||
| 21 | -std::shared_ptr<QPDFObject> | ||
| 22 | -QPDF_String::create(std::string const& val) | ||
| 23 | -{ | ||
| 24 | - return do_create(new QPDF_String(val)); | ||
| 25 | -} | ||
| 26 | - | ||
| 27 | std::shared_ptr<QPDFObject> | 15 | std::shared_ptr<QPDFObject> |
| 28 | QPDF_String::create_utf16(std::string const& utf8_val) | 16 | QPDF_String::create_utf16(std::string const& utf8_val) |
| 29 | { | 17 | { |
| @@ -31,19 +19,7 @@ QPDF_String::create_utf16(std::string const& utf8_val) | @@ -31,19 +19,7 @@ QPDF_String::create_utf16(std::string const& utf8_val) | ||
| 31 | if (!QUtil::utf8_to_pdf_doc(utf8_val, result, '?')) { | 19 | if (!QUtil::utf8_to_pdf_doc(utf8_val, result, '?')) { |
| 32 | result = QUtil::utf8_to_utf16(utf8_val); | 20 | result = QUtil::utf8_to_utf16(utf8_val); |
| 33 | } | 21 | } |
| 34 | - return do_create(new QPDF_String(result)); | ||
| 35 | -} | ||
| 36 | - | ||
| 37 | -std::shared_ptr<QPDFObject> | ||
| 38 | -QPDF_String::copy(bool shallow) | ||
| 39 | -{ | ||
| 40 | - return create(val); | ||
| 41 | -} | ||
| 42 | - | ||
| 43 | -std::string | ||
| 44 | -QPDF_String::unparse() | ||
| 45 | -{ | ||
| 46 | - return unparse(false); | 22 | + return QPDFObject::create<QPDF_String>(result); |
| 47 | } | 23 | } |
| 48 | 24 | ||
| 49 | void | 25 | void |
libqpdf/QPDF_Unresolved.cc deleted
| 1 | -#include <qpdf/QPDF_Unresolved.hh> | ||
| 2 | - | ||
| 3 | -#include <qpdf/QPDF.hh> | ||
| 4 | -#include <qpdf/QPDFObject_private.hh> | ||
| 5 | - | ||
| 6 | -QPDF_Unresolved::QPDF_Unresolved(QPDF* qpdf, QPDFObjGen og) : | ||
| 7 | - QPDFValue(::ot_unresolved, qpdf, og) | ||
| 8 | -{ | ||
| 9 | -} | ||
| 10 | - | ||
| 11 | -std::shared_ptr<QPDFObject> | ||
| 12 | -QPDF_Unresolved::create(QPDF* qpdf, QPDFObjGen og) | ||
| 13 | -{ | ||
| 14 | - return do_create(new QPDF_Unresolved(qpdf, og)); | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -std::shared_ptr<QPDFObject> | ||
| 18 | -QPDF_Unresolved::copy(bool shallow) | ||
| 19 | -{ | ||
| 20 | - return QPDF::Resolver::resolved(qpdf, og)->copy(shallow); | ||
| 21 | -} | ||
| 22 | - | ||
| 23 | -std::string | ||
| 24 | -QPDF_Unresolved::unparse() | ||
| 25 | -{ | ||
| 26 | - return QPDF::Resolver::resolved(qpdf, og)->unparse(); | ||
| 27 | -} | ||
| 28 | - | ||
| 29 | -void | ||
| 30 | -QPDF_Unresolved::writeJSON(int json_version, JSON::Writer& p) | ||
| 31 | -{ | ||
| 32 | - QPDF::Resolver::resolved(qpdf, og)->writeJSON(json_version, p); | ||
| 33 | -} | ||
| 34 | - | ||
| 35 | -std::string | ||
| 36 | -QPDF_Unresolved::getStringValue() const | ||
| 37 | -{ | ||
| 38 | - return QPDF::Resolver::resolved(qpdf, og)->getStringValue(); | ||
| 39 | -} |
libqpdf/QPDF_json.cc
| @@ -7,9 +7,6 @@ | @@ -7,9 +7,6 @@ | ||
| 7 | #include <qpdf/QIntC.hh> | 7 | #include <qpdf/QIntC.hh> |
| 8 | #include <qpdf/QPDFObjectHandle_private.hh> | 8 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 9 | #include <qpdf/QPDFObject_private.hh> | 9 | #include <qpdf/QPDFObject_private.hh> |
| 10 | -#include <qpdf/QPDFValue.hh> | ||
| 11 | -#include <qpdf/QPDF_Null.hh> | ||
| 12 | -#include <qpdf/QPDF_Stream.hh> | ||
| 13 | #include <qpdf/QTC.hh> | 10 | #include <qpdf/QTC.hh> |
| 14 | #include <qpdf/QUtil.hh> | 11 | #include <qpdf/QUtil.hh> |
| 15 | #include <algorithm> | 12 | #include <algorithm> |
| @@ -239,8 +236,8 @@ class QPDF::JSONReactor: public JSON::Reactor | @@ -239,8 +236,8 @@ class QPDF::JSONReactor: public JSON::Reactor | ||
| 239 | is(is), | 236 | is(is), |
| 240 | must_be_complete(must_be_complete), | 237 | must_be_complete(must_be_complete), |
| 241 | descr( | 238 | descr( |
| 242 | - std::make_shared<QPDFValue::Description>( | ||
| 243 | - QPDFValue::JSON_Descr(std::make_shared<std::string>(is->getName()), ""))) | 239 | + std::make_shared<QPDFObject::Description>( |
| 240 | + QPDFObject::JSON_Descr(std::make_shared<std::string>(is->getName()), ""))) | ||
| 244 | { | 241 | { |
| 245 | } | 242 | } |
| 246 | ~JSONReactor() override = default; | 243 | ~JSONReactor() override = default; |
| @@ -287,7 +284,7 @@ class QPDF::JSONReactor: public JSON::Reactor | @@ -287,7 +284,7 @@ class QPDF::JSONReactor: public JSON::Reactor | ||
| 287 | QPDF& pdf; | 284 | QPDF& pdf; |
| 288 | std::shared_ptr<InputSource> is; | 285 | std::shared_ptr<InputSource> is; |
| 289 | bool must_be_complete{true}; | 286 | bool must_be_complete{true}; |
| 290 | - std::shared_ptr<QPDFValue::Description> descr; | 287 | + std::shared_ptr<QPDFObject::Description> descr; |
| 291 | bool errors{false}; | 288 | bool errors{false}; |
| 292 | bool saw_qpdf{false}; | 289 | bool saw_qpdf{false}; |
| 293 | bool saw_qpdf_meta{false}; | 290 | bool saw_qpdf_meta{false}; |
| @@ -577,8 +574,8 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) | @@ -577,8 +574,8 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) | ||
| 577 | } else { | 574 | } else { |
| 578 | this_stream_needs_data = true; | 575 | this_stream_needs_data = true; |
| 579 | replaceObject( | 576 | replaceObject( |
| 580 | - QPDF_Stream::create( | ||
| 581 | - &pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0), | 577 | + qpdf::Stream( |
| 578 | + pdf, tos.object.getObjGen(), QPDFObjectHandle::newDictionary(), 0, 0), | ||
| 582 | value); | 579 | value); |
| 583 | } | 580 | } |
| 584 | next_obj = tos.object; | 581 | next_obj = tos.object; |
| @@ -707,10 +704,10 @@ QPDF::JSONReactor::arrayItem(JSON const& value) | @@ -707,10 +704,10 @@ QPDF::JSONReactor::arrayItem(JSON const& value) | ||
| 707 | void | 704 | void |
| 708 | QPDF::JSONReactor::setObjectDescription(QPDFObjectHandle& oh, JSON const& value) | 705 | QPDF::JSONReactor::setObjectDescription(QPDFObjectHandle& oh, JSON const& value) |
| 709 | { | 706 | { |
| 710 | - auto j_descr = std::get<QPDFValue::JSON_Descr>(*descr); | 707 | + auto j_descr = std::get<QPDFObject::JSON_Descr>(*descr); |
| 711 | if (j_descr.object != cur_object) { | 708 | if (j_descr.object != cur_object) { |
| 712 | - descr = std::make_shared<QPDFValue::Description>( | ||
| 713 | - QPDFValue::JSON_Descr(j_descr.input, cur_object)); | 709 | + descr = std::make_shared<QPDFObject::Description>( |
| 710 | + QPDFObject::JSON_Descr(j_descr.input, cur_object)); | ||
| 714 | } | 711 | } |
| 715 | 712 | ||
| 716 | oh.getObjectPtr()->setDescription(&pdf, descr, value.getStart()); | 713 | oh.getObjectPtr()->setDescription(&pdf, descr, value.getStart()); |
libqpdf/QPDF_optimization.cc
| @@ -5,9 +5,8 @@ | @@ -5,9 +5,8 @@ | ||
| 5 | #include <qpdf/QPDF.hh> | 5 | #include <qpdf/QPDF.hh> |
| 6 | 6 | ||
| 7 | #include <qpdf/QPDFExc.hh> | 7 | #include <qpdf/QPDFExc.hh> |
| 8 | +#include <qpdf/QPDFObjectHandle_private.hh> | ||
| 8 | #include <qpdf/QPDFWriter_private.hh> | 9 | #include <qpdf/QPDFWriter_private.hh> |
| 9 | -#include <qpdf/QPDF_Array.hh> | ||
| 10 | -#include <qpdf/QPDF_Dictionary.hh> | ||
| 11 | #include <qpdf/QTC.hh> | 10 | #include <qpdf/QTC.hh> |
| 12 | 11 | ||
| 13 | QPDF::ObjUser::ObjUser() : | 12 | QPDF::ObjUser::ObjUser() : |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| @@ -4,9 +4,7 @@ | @@ -4,9 +4,7 @@ | ||
| 4 | #include <qpdf/QPDFObjectHandle.hh> | 4 | #include <qpdf/QPDFObjectHandle.hh> |
| 5 | 5 | ||
| 6 | #include <qpdf/QPDFObject_private.hh> | 6 | #include <qpdf/QPDFObject_private.hh> |
| 7 | -#include <qpdf/QPDF_Array.hh> | ||
| 8 | -#include <qpdf/QPDF_Dictionary.hh> | ||
| 9 | -#include <qpdf/QPDF_Stream.hh> | 7 | +#include <qpdf/QUtil.hh> |
| 10 | 8 | ||
| 11 | namespace qpdf | 9 | namespace qpdf |
| 12 | { | 10 | { |
| @@ -106,6 +104,13 @@ namespace qpdf | @@ -106,6 +104,13 @@ namespace qpdf | ||
| 106 | { | 104 | { |
| 107 | } | 105 | } |
| 108 | 106 | ||
| 107 | + Stream( | ||
| 108 | + QPDF& qpdf, | ||
| 109 | + QPDFObjGen og, | ||
| 110 | + QPDFObjectHandle stream_dict, | ||
| 111 | + qpdf_offset_t offset, | ||
| 112 | + size_t length); | ||
| 113 | + | ||
| 109 | QPDFObjectHandle | 114 | QPDFObjectHandle |
| 110 | getDict() const | 115 | getDict() const |
| 111 | { | 116 | { |
| @@ -186,20 +191,22 @@ namespace qpdf | @@ -186,20 +191,22 @@ namespace qpdf | ||
| 186 | { | 191 | { |
| 187 | auto s = stream(); | 192 | auto s = stream(); |
| 188 | s->stream_dict = new_dict; | 193 | s->stream_dict = new_dict; |
| 189 | - s->setDictDescription(); | 194 | + setDictDescription(); |
| 190 | } | 195 | } |
| 191 | 196 | ||
| 197 | + void setDictDescription(); | ||
| 198 | + | ||
| 192 | static void registerStreamFilter( | 199 | static void registerStreamFilter( |
| 193 | std::string const& filter_name, | 200 | std::string const& filter_name, |
| 194 | std::function<std::shared_ptr<QPDFStreamFilter>()> factory); | 201 | std::function<std::shared_ptr<QPDFStreamFilter>()> factory); |
| 195 | 202 | ||
| 196 | private: | 203 | private: |
| 197 | - QPDF_Stream* | 204 | + QPDF_Stream::Members* |
| 198 | stream() const | 205 | stream() const |
| 199 | { | 206 | { |
| 200 | if (obj) { | 207 | if (obj) { |
| 201 | if (auto s = obj->as<QPDF_Stream>()) { | 208 | if (auto s = obj->as<QPDF_Stream>()) { |
| 202 | - return s; | 209 | + return s->m.get(); |
| 203 | } | 210 | } |
| 204 | } | 211 | } |
| 205 | throw std::runtime_error("operation for stream attempted on object of type dictionary"); | 212 | throw std::runtime_error("operation for stream attempted on object of type dictionary"); |
| @@ -227,6 +234,32 @@ namespace qpdf | @@ -227,6 +234,32 @@ namespace qpdf | ||
| 227 | 234 | ||
| 228 | } // namespace qpdf | 235 | } // namespace qpdf |
| 229 | 236 | ||
| 237 | +inline QPDF_Dictionary::QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items) : | ||
| 238 | + items(std::move(items)) | ||
| 239 | +{ | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +inline std::shared_ptr<QPDFObject> | ||
| 243 | +QPDF_Null::create( | ||
| 244 | + std::shared_ptr<QPDFObject> parent, std::string_view const& static_descr, std::string var_descr) | ||
| 245 | +{ | ||
| 246 | + auto n = QPDFObject::create<QPDF_Null>(); | ||
| 247 | + n->setChildDescription(parent->getQPDF(), parent, static_descr, var_descr); | ||
| 248 | + return n; | ||
| 249 | +} | ||
| 250 | + | ||
| 251 | +inline QPDF_Real::QPDF_Real(double value, int decimal_places, bool trim_trailing_zeroes) : | ||
| 252 | + val(QUtil::double_to_string(value, decimal_places, trim_trailing_zeroes)) | ||
| 253 | +{ | ||
| 254 | +} | ||
| 255 | + | ||
| 256 | +template <typename T, typename... Args> | ||
| 257 | +inline std::shared_ptr<QPDFObject> | ||
| 258 | +QPDFObject::create(Args&&... args) | ||
| 259 | +{ | ||
| 260 | + return std::make_shared<QPDFObject>(std::forward<T>(T(std::forward<Args>(args)...))); | ||
| 261 | +} | ||
| 262 | + | ||
| 230 | inline qpdf::Array | 263 | inline qpdf::Array |
| 231 | QPDFObjectHandle::as_array(qpdf::typed options) const | 264 | QPDFObjectHandle::as_array(qpdf::typed options) const |
| 232 | { | 265 | { |
libqpdf/qpdf/QPDFObject_private.hh
| @@ -6,182 +6,508 @@ | @@ -6,182 +6,508 @@ | ||
| 6 | 6 | ||
| 7 | #include <qpdf/Constants.h> | 7 | #include <qpdf/Constants.h> |
| 8 | #include <qpdf/JSON.hh> | 8 | #include <qpdf/JSON.hh> |
| 9 | +#include <qpdf/JSON_writer.hh> | ||
| 9 | #include <qpdf/QPDF.hh> | 10 | #include <qpdf/QPDF.hh> |
| 10 | -#include <qpdf/QPDFValue.hh> | 11 | +#include <qpdf/QPDFObjGen.hh> |
| 11 | #include <qpdf/Types.h> | 12 | #include <qpdf/Types.h> |
| 12 | 13 | ||
| 14 | +#include <map> | ||
| 15 | +#include <memory> | ||
| 13 | #include <string> | 16 | #include <string> |
| 14 | #include <string_view> | 17 | #include <string_view> |
| 18 | +#include <variant> | ||
| 19 | +#include <vector> | ||
| 15 | 20 | ||
| 16 | -class QPDF; | 21 | +class QPDFObject; |
| 17 | class QPDFObjectHandle; | 22 | class QPDFObjectHandle; |
| 18 | 23 | ||
| 19 | -class QPDFObject | 24 | +namespace qpdf |
| 25 | +{ | ||
| 26 | + class Array; | ||
| 27 | + class BaseDictionary; | ||
| 28 | + class Dictionary; | ||
| 29 | + class Stream; | ||
| 30 | +} // namespace qpdf | ||
| 31 | + | ||
| 32 | +class QPDF_Array final | ||
| 20 | { | 33 | { |
| 21 | - friend class QPDFValue; | 34 | + private: |
| 35 | + struct Sparse | ||
| 36 | + { | ||
| 37 | + int size{0}; | ||
| 38 | + std::map<int, std::shared_ptr<QPDFObject>> elements; | ||
| 39 | + }; | ||
| 22 | 40 | ||
| 23 | public: | 41 | public: |
| 24 | - QPDFObject() = default; | 42 | + QPDF_Array() = default; |
| 43 | + QPDF_Array(QPDF_Array const& other) : | ||
| 44 | + sp(other.sp ? std::make_unique<Sparse>(*other.sp) : nullptr) | ||
| 45 | + { | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + QPDF_Array(QPDF_Array&&) = default; | ||
| 49 | + QPDF_Array& operator=(QPDF_Array&&) = default; | ||
| 50 | + | ||
| 51 | + private: | ||
| 52 | + friend class QPDFObject; | ||
| 53 | + friend class qpdf::Array; | ||
| 54 | + QPDF_Array(std::vector<QPDFObjectHandle> const& items); | ||
| 55 | + QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse); | ||
| 25 | 56 | ||
| 26 | - std::shared_ptr<QPDFObject> | ||
| 27 | - copy(bool shallow = false) | 57 | + int |
| 58 | + size() const | ||
| 28 | { | 59 | { |
| 29 | - return value->copy(shallow); | 60 | + return sp ? sp->size : int(elements.size()); |
| 30 | } | 61 | } |
| 31 | - std::string | ||
| 32 | - unparse() | 62 | + void setFromVector(std::vector<QPDFObjectHandle> const& items); |
| 63 | + void checkOwnership(QPDFObjectHandle const& item) const; | ||
| 64 | + | ||
| 65 | + std::unique_ptr<Sparse> sp; | ||
| 66 | + std::vector<std::shared_ptr<QPDFObject>> elements; | ||
| 67 | +}; | ||
| 68 | + | ||
| 69 | +class QPDF_Bool final | ||
| 70 | +{ | ||
| 71 | + friend class QPDFObject; | ||
| 72 | + friend class QPDFObjectHandle; | ||
| 73 | + | ||
| 74 | + explicit QPDF_Bool(bool val) : | ||
| 75 | + val(val) | ||
| 33 | { | 76 | { |
| 34 | - return value->unparse(); | ||
| 35 | } | 77 | } |
| 36 | - void | ||
| 37 | - writeJSON(int json_version, JSON::Writer& p) | 78 | + bool val; |
| 79 | +}; | ||
| 80 | + | ||
| 81 | +class QPDF_Destroyed final | ||
| 82 | +{ | ||
| 83 | +}; | ||
| 84 | + | ||
| 85 | +class QPDF_Dictionary final | ||
| 86 | +{ | ||
| 87 | + friend class QPDFObject; | ||
| 88 | + friend class qpdf::BaseDictionary; | ||
| 89 | + | ||
| 90 | + QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items) : | ||
| 91 | + items(items) | ||
| 38 | { | 92 | { |
| 39 | - return value->writeJSON(json_version, p); | ||
| 40 | } | 93 | } |
| 41 | - std::string | ||
| 42 | - getStringValue() const | 94 | + inline QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items); |
| 95 | + | ||
| 96 | + std::map<std::string, QPDFObjectHandle> items; | ||
| 97 | +}; | ||
| 98 | + | ||
| 99 | +class QPDF_InlineImage final | ||
| 100 | +{ | ||
| 101 | + friend class QPDFObject; | ||
| 102 | + | ||
| 103 | + explicit QPDF_InlineImage(std::string val) : | ||
| 104 | + val(std::move(val)) | ||
| 105 | + { | ||
| 106 | + } | ||
| 107 | + std::string val; | ||
| 108 | +}; | ||
| 109 | + | ||
| 110 | +class QPDF_Integer final | ||
| 111 | +{ | ||
| 112 | + friend class QPDFObject; | ||
| 113 | + friend class QPDFObjectHandle; | ||
| 114 | + | ||
| 115 | + QPDF_Integer(long long val) : | ||
| 116 | + val(val) | ||
| 117 | + { | ||
| 118 | + } | ||
| 119 | + long long val; | ||
| 120 | +}; | ||
| 121 | + | ||
| 122 | +class QPDF_Name final | ||
| 123 | +{ | ||
| 124 | + friend class QPDFObject; | ||
| 125 | + | ||
| 126 | + explicit QPDF_Name(std::string name) : | ||
| 127 | + name(std::move(name)) | ||
| 128 | + { | ||
| 129 | + } | ||
| 130 | + std::string name; | ||
| 131 | +}; | ||
| 132 | + | ||
| 133 | +class QPDF_Null final | ||
| 134 | +{ | ||
| 135 | + friend class QPDFObject; | ||
| 136 | + | ||
| 137 | + public: | ||
| 138 | + static inline std::shared_ptr<QPDFObject> create( | ||
| 139 | + std::shared_ptr<QPDFObject> parent, | ||
| 140 | + std::string_view const& static_descr, | ||
| 141 | + std::string var_descr); | ||
| 142 | +}; | ||
| 143 | + | ||
| 144 | +class QPDF_Operator final | ||
| 145 | +{ | ||
| 146 | + friend class QPDFObject; | ||
| 147 | + | ||
| 148 | + QPDF_Operator(std::string val) : | ||
| 149 | + val(std::move(val)) | ||
| 150 | + { | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + std::string val; | ||
| 154 | +}; | ||
| 155 | + | ||
| 156 | +class QPDF_Real final | ||
| 157 | +{ | ||
| 158 | + friend class QPDFObject; | ||
| 159 | + | ||
| 160 | + QPDF_Real(std::string val) : | ||
| 161 | + val(std::move(val)) | ||
| 162 | + { | ||
| 163 | + } | ||
| 164 | + inline QPDF_Real(double value, int decimal_places, bool trim_trailing_zeroes); | ||
| 165 | + // Store reals as strings to avoid roundoff errors. | ||
| 166 | + std::string val; | ||
| 167 | +}; | ||
| 168 | + | ||
| 169 | +class QPDF_Reference | ||
| 170 | +{ | ||
| 171 | + // This is a minimal implementation to support QPDF::replaceObject. Once we support parsing of | ||
| 172 | + // objects that are an indirect reference we will need to support multiple levels of | ||
| 173 | + // indirection, including the possibility of circular references. | ||
| 174 | + friend class QPDFObject; | ||
| 175 | + | ||
| 176 | + QPDF_Reference(std::shared_ptr<QPDFObject> obj) : | ||
| 177 | + obj(std::move(obj)) | ||
| 178 | + { | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + std::shared_ptr<QPDFObject> obj; | ||
| 182 | +}; | ||
| 183 | + | ||
| 184 | +class QPDF_Reserved final | ||
| 185 | +{ | ||
| 186 | +}; | ||
| 187 | + | ||
| 188 | +class QPDF_Stream final | ||
| 189 | +{ | ||
| 190 | + class Members | ||
| 191 | + { | ||
| 192 | + friend class QPDF_Stream; | ||
| 193 | + friend class QPDFObject; | ||
| 194 | + friend class qpdf::Stream; | ||
| 195 | + | ||
| 196 | + public: | ||
| 197 | + Members(QPDFObjectHandle stream_dict, size_t length) : | ||
| 198 | + stream_dict(std::move(stream_dict)), | ||
| 199 | + length(length) | ||
| 200 | + { | ||
| 201 | + } | ||
| 202 | + | ||
| 203 | + private: | ||
| 204 | + void replaceFilterData( | ||
| 205 | + QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms, size_t length); | ||
| 206 | + | ||
| 207 | + bool filter_on_write{true}; | ||
| 208 | + QPDFObjectHandle stream_dict; | ||
| 209 | + size_t length{0}; | ||
| 210 | + std::shared_ptr<Buffer> stream_data; | ||
| 211 | + std::shared_ptr<QPDFObjectHandle::StreamDataProvider> stream_provider; | ||
| 212 | + std::vector<std::shared_ptr<QPDFObjectHandle::TokenFilter>> token_filters; | ||
| 213 | + }; | ||
| 214 | + | ||
| 215 | + friend class QPDFObject; | ||
| 216 | + friend class qpdf::Stream; | ||
| 217 | + | ||
| 218 | + QPDF_Stream(QPDFObjectHandle stream_dict, size_t length) : | ||
| 219 | + m(std::make_unique<Members>(stream_dict, length)) | ||
| 220 | + { | ||
| 221 | + if (!stream_dict.isDictionary()) { | ||
| 222 | + throw std::logic_error( | ||
| 223 | + "stream object instantiated with non-dictionary object for dictionary"); | ||
| 224 | + } | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + std::unique_ptr<Members> m; | ||
| 228 | +}; | ||
| 229 | + | ||
| 230 | +// QPDF_Strings may included embedded null characters. | ||
| 231 | +class QPDF_String final | ||
| 232 | +{ | ||
| 233 | + friend class QPDFObject; | ||
| 234 | + friend class QPDFWriter; | ||
| 235 | + | ||
| 236 | + public: | ||
| 237 | + static std::shared_ptr<QPDFObject> create_utf16(std::string const& utf8_val); | ||
| 238 | + std::string unparse(bool force_binary = false); | ||
| 239 | + void writeJSON(int json_version, JSON::Writer& p); | ||
| 240 | + std::string getUTF8Val() const; | ||
| 241 | + | ||
| 242 | + private: | ||
| 243 | + QPDF_String(std::string val) : | ||
| 244 | + val(std::move(val)) | ||
| 43 | { | 245 | { |
| 44 | - return value->getStringValue(); | ||
| 45 | } | 246 | } |
| 247 | + bool useHexString() const; | ||
| 248 | + std::string val; | ||
| 249 | +}; | ||
| 250 | + | ||
| 251 | +class QPDF_Unresolved final | ||
| 252 | +{ | ||
| 253 | +}; | ||
| 254 | + | ||
| 255 | +class QPDFObject | ||
| 256 | +{ | ||
| 257 | + public: | ||
| 258 | + template <typename T> | ||
| 259 | + QPDFObject(T&& value) : | ||
| 260 | + value(std::forward<T>(value)) | ||
| 261 | + { | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + template <typename T> | ||
| 265 | + QPDFObject(QPDF* qpdf, QPDFObjGen og, T&& value) : | ||
| 266 | + value(std::forward<T>(value)), | ||
| 267 | + qpdf(qpdf), | ||
| 268 | + og(og) | ||
| 269 | + { | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + template <typename T, typename... Args> | ||
| 273 | + inline static std::shared_ptr<QPDFObject> create(Args&&... args); | ||
| 274 | + | ||
| 275 | + template <typename T, typename... Args> | ||
| 276 | + inline static std::shared_ptr<QPDFObject> | ||
| 277 | + create(QPDF* qpdf, QPDFObjGen og, Args&&... args) | ||
| 278 | + { | ||
| 279 | + return std::make_shared<QPDFObject>( | ||
| 280 | + qpdf, og, std::forward<T>(T(std::forward<Args>(args)...))); | ||
| 281 | + } | ||
| 282 | + | ||
| 283 | + std::shared_ptr<QPDFObject> copy(bool shallow = false); | ||
| 284 | + std::string unparse(); | ||
| 285 | + void write_json(int json_version, JSON::Writer& p); | ||
| 286 | + void disconnect(); | ||
| 287 | + std::string getStringValue() const; | ||
| 288 | + | ||
| 46 | // Return a unique type code for the resolved object | 289 | // Return a unique type code for the resolved object |
| 47 | qpdf_object_type_e | 290 | qpdf_object_type_e |
| 48 | getResolvedTypeCode() const | 291 | getResolvedTypeCode() const |
| 49 | { | 292 | { |
| 50 | - auto tc = value->type_code; | ||
| 51 | - return tc == ::ot_unresolved | ||
| 52 | - ? QPDF::Resolver::resolved(value->qpdf, value->og)->value->type_code | ||
| 53 | - : tc; | 293 | + if (getTypeCode() == ::ot_unresolved) { |
| 294 | + return QPDF::Resolver::resolved(qpdf, og)->getTypeCode(); | ||
| 295 | + } | ||
| 296 | + if (getTypeCode() == ::ot_reference) { | ||
| 297 | + return std::get<QPDF_Reference>(value).obj->getResolvedTypeCode(); | ||
| 298 | + } | ||
| 299 | + return getTypeCode(); | ||
| 54 | } | 300 | } |
| 55 | // Return a unique type code for the object | 301 | // Return a unique type code for the object |
| 56 | qpdf_object_type_e | 302 | qpdf_object_type_e |
| 57 | - getTypeCode() const noexcept | 303 | + getTypeCode() const |
| 58 | { | 304 | { |
| 59 | - return value->type_code; | 305 | + return static_cast<qpdf_object_type_e>(value.index()); |
| 60 | } | 306 | } |
| 61 | 307 | ||
| 62 | QPDF* | 308 | QPDF* |
| 63 | getQPDF() const | 309 | getQPDF() const |
| 64 | { | 310 | { |
| 65 | - return value->qpdf; | 311 | + return qpdf; |
| 66 | } | 312 | } |
| 67 | QPDFObjGen | 313 | QPDFObjGen |
| 68 | getObjGen() const | 314 | getObjGen() const |
| 69 | { | 315 | { |
| 70 | - return value->og; | 316 | + return og; |
| 71 | } | 317 | } |
| 72 | void | 318 | void |
| 73 | - setDescription( | ||
| 74 | - QPDF* qpdf, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset = -1) | 319 | + assign_null() |
| 75 | { | 320 | { |
| 76 | - return value->setDescription(qpdf, description, offset); | 321 | + value = QPDF_Null(); |
| 322 | + qpdf = nullptr; | ||
| 323 | + og = QPDFObjGen(); | ||
| 324 | + object_description = nullptr; | ||
| 325 | + parsed_offset = -1; | ||
| 77 | } | 326 | } |
| 78 | void | 327 | void |
| 79 | - setChildDescription( | ||
| 80 | - std::shared_ptr<QPDFObject> parent, | ||
| 81 | - std::string_view const& static_descr, | ||
| 82 | - std::string var_descr) | 328 | + move_to(std::shared_ptr<QPDFObject>& o, bool destroy) |
| 83 | { | 329 | { |
| 84 | - auto qpdf = parent ? parent->value->qpdf : nullptr; | ||
| 85 | - value->setChildDescription(qpdf, parent->value, static_descr, var_descr); | 330 | + o->value = std::move(value); |
| 331 | + o->qpdf = qpdf; | ||
| 332 | + o->og = og; | ||
| 333 | + o->object_description = object_description; | ||
| 334 | + o->parsed_offset = parsed_offset; | ||
| 335 | + if (!destroy) { | ||
| 336 | + value = QPDF_Reference(o); | ||
| 337 | + } | ||
| 86 | } | 338 | } |
| 87 | void | 339 | void |
| 88 | - setChildDescription( | ||
| 89 | - std::shared_ptr<QPDFValue> parent, | ||
| 90 | - std::string_view const& static_descr, | ||
| 91 | - std::string var_descr) | 340 | + swapWith(std::shared_ptr<QPDFObject> o) |
| 92 | { | 341 | { |
| 93 | - auto qpdf = parent ? parent->qpdf : nullptr; | ||
| 94 | - value->setChildDescription(qpdf, parent, static_descr, var_descr); | 342 | + std::swap(value, o->value); |
| 343 | + std::swap(qpdf, o->qpdf); | ||
| 344 | + std::swap(object_description, o->object_description); | ||
| 345 | + std::swap(parsed_offset, o->parsed_offset); | ||
| 95 | } | 346 | } |
| 96 | - bool | ||
| 97 | - getDescription(QPDF*& qpdf, std::string& description) | 347 | + |
| 348 | + void | ||
| 349 | + setObjGen(QPDF* a_qpdf, QPDFObjGen a_og) | ||
| 98 | { | 350 | { |
| 99 | - qpdf = value->qpdf; | ||
| 100 | - description = value->getDescription(); | ||
| 101 | - return qpdf != nullptr; | 351 | + qpdf = a_qpdf; |
| 352 | + og = a_og; | ||
| 102 | } | 353 | } |
| 103 | - bool | ||
| 104 | - hasDescription() | 354 | + // Mark an object as destroyed. Used by QPDF's destructor for its indirect objects. |
| 355 | + void | ||
| 356 | + destroy() | ||
| 105 | { | 357 | { |
| 106 | - return value->hasDescription(); | 358 | + value = QPDF_Destroyed(); |
| 107 | } | 359 | } |
| 108 | - void | ||
| 109 | - setParsedOffset(qpdf_offset_t offset) | 360 | + |
| 361 | + bool | ||
| 362 | + isUnresolved() const | ||
| 110 | { | 363 | { |
| 111 | - value->setParsedOffset(offset); | 364 | + return getTypeCode() == ::ot_unresolved; |
| 112 | } | 365 | } |
| 113 | - qpdf_offset_t | ||
| 114 | - getParsedOffset() | 366 | + const QPDFObject* |
| 367 | + resolved_object() const | ||
| 115 | { | 368 | { |
| 116 | - return value->getParsedOffset(); | 369 | + return isUnresolved() ? QPDF::Resolver::resolved(qpdf, og) : this; |
| 117 | } | 370 | } |
| 371 | + | ||
| 372 | + struct JSON_Descr | ||
| 373 | + { | ||
| 374 | + JSON_Descr(std::shared_ptr<std::string> input, std::string const& object) : | ||
| 375 | + input(input), | ||
| 376 | + object(object) | ||
| 377 | + { | ||
| 378 | + } | ||
| 379 | + | ||
| 380 | + std::shared_ptr<std::string> input; | ||
| 381 | + std::string object; | ||
| 382 | + }; | ||
| 383 | + | ||
| 384 | + struct ChildDescr | ||
| 385 | + { | ||
| 386 | + ChildDescr( | ||
| 387 | + std::shared_ptr<QPDFObject> parent, | ||
| 388 | + std::string_view const& static_descr, | ||
| 389 | + std::string var_descr) : | ||
| 390 | + parent(parent), | ||
| 391 | + static_descr(static_descr), | ||
| 392 | + var_descr(var_descr) | ||
| 393 | + { | ||
| 394 | + } | ||
| 395 | + | ||
| 396 | + std::weak_ptr<QPDFObject> parent; | ||
| 397 | + std::string_view const& static_descr; | ||
| 398 | + std::string var_descr; | ||
| 399 | + }; | ||
| 400 | + | ||
| 401 | + using Description = std::variant<std::string, JSON_Descr, ChildDescr>; | ||
| 402 | + | ||
| 118 | void | 403 | void |
| 119 | - assign(std::shared_ptr<QPDFObject> o) | 404 | + setDescription( |
| 405 | + QPDF* qpdf_p, std::shared_ptr<Description>& description, qpdf_offset_t offset = -1) | ||
| 120 | { | 406 | { |
| 121 | - value = o->value; | 407 | + qpdf = qpdf_p; |
| 408 | + object_description = description; | ||
| 409 | + setParsedOffset(offset); | ||
| 122 | } | 410 | } |
| 123 | void | 411 | void |
| 124 | - swapWith(std::shared_ptr<QPDFObject> o) | 412 | + setDefaultDescription(QPDF* a_qpdf, QPDFObjGen const& a_og) |
| 125 | { | 413 | { |
| 126 | - auto v = value; | ||
| 127 | - value = o->value; | ||
| 128 | - o->value = v; | ||
| 129 | - auto og = value->og; | ||
| 130 | - value->og = o->value->og; | ||
| 131 | - o->value->og = og; | 414 | + qpdf = a_qpdf; |
| 415 | + og = a_og; | ||
| 132 | } | 416 | } |
| 133 | - | ||
| 134 | void | 417 | void |
| 135 | - setDefaultDescription(QPDF* qpdf, QPDFObjGen og) | 418 | + setChildDescription( |
| 419 | + QPDF* a_qpdf, | ||
| 420 | + std::shared_ptr<QPDFObject> parent, | ||
| 421 | + std::string_view const& static_descr, | ||
| 422 | + std::string var_descr) | ||
| 136 | { | 423 | { |
| 137 | - // Intended for use by the QPDF class | ||
| 138 | - value->setDefaultDescription(qpdf, og); | 424 | + object_description = |
| 425 | + std::make_shared<Description>(ChildDescr(parent, static_descr, var_descr)); | ||
| 426 | + qpdf = a_qpdf; | ||
| 139 | } | 427 | } |
| 140 | - void | ||
| 141 | - setObjGen(QPDF* qpdf, QPDFObjGen og) | 428 | + std::string getDescription(); |
| 429 | + bool | ||
| 430 | + hasDescription() | ||
| 142 | { | 431 | { |
| 143 | - value->qpdf = qpdf; | ||
| 144 | - value->og = og; | 432 | + return object_description || og.isIndirect(); |
| 145 | } | 433 | } |
| 146 | void | 434 | void |
| 147 | - disconnect() | 435 | + setParsedOffset(qpdf_offset_t offset) |
| 148 | { | 436 | { |
| 149 | - // Disconnect an object from its owning QPDF. This is called by QPDF's destructor. | ||
| 150 | - value->disconnect(); | ||
| 151 | - value->qpdf = nullptr; | ||
| 152 | - value->og = QPDFObjGen(); | 437 | + if (parsed_offset < 0) { |
| 438 | + parsed_offset = offset; | ||
| 439 | + } | ||
| 153 | } | 440 | } |
| 154 | - // Mark an object as destroyed. Used by QPDF's destructor for its indirect objects. | ||
| 155 | - void destroy(); | ||
| 156 | - | ||
| 157 | bool | 441 | bool |
| 158 | - isUnresolved() const | 442 | + getDescription(QPDF*& a_qpdf, std::string& description) |
| 159 | { | 443 | { |
| 160 | - return value->type_code == ::ot_unresolved; | 444 | + a_qpdf = qpdf; |
| 445 | + description = getDescription(); | ||
| 446 | + return qpdf != nullptr; | ||
| 161 | } | 447 | } |
| 162 | - const QPDFObject* | ||
| 163 | - resolved_object() const | 448 | + qpdf_offset_t |
| 449 | + getParsedOffset() | ||
| 164 | { | 450 | { |
| 165 | - return isUnresolved() ? QPDF::Resolver::resolved(value->qpdf, value->og) : this; | 451 | + return parsed_offset; |
| 452 | + } | ||
| 453 | + QPDF* | ||
| 454 | + getQPDF() | ||
| 455 | + { | ||
| 456 | + return qpdf; | ||
| 457 | + } | ||
| 458 | + QPDFObjGen | ||
| 459 | + getObjGen() | ||
| 460 | + { | ||
| 461 | + return og; | ||
| 166 | } | 462 | } |
| 167 | 463 | ||
| 168 | template <typename T> | 464 | template <typename T> |
| 169 | T* | 465 | T* |
| 170 | - as() const | ||
| 171 | - { | ||
| 172 | - if (auto result = dynamic_cast<T*>(value.get())) { | ||
| 173 | - return result; | ||
| 174 | - } else { | ||
| 175 | - return isUnresolved() | ||
| 176 | - ? dynamic_cast<T*>(QPDF::Resolver::resolved(value->qpdf, value->og)->value.get()) | ||
| 177 | - : nullptr; | 466 | + as() |
| 467 | + { | ||
| 468 | + if (std::holds_alternative<T>(value)) { | ||
| 469 | + return &std::get<T>(value); | ||
| 178 | } | 470 | } |
| 471 | + if (std::holds_alternative<QPDF_Unresolved>(value)) { | ||
| 472 | + return QPDF::Resolver::resolved(qpdf, og)->as<T>(); | ||
| 473 | + } | ||
| 474 | + if (std::holds_alternative<QPDF_Reference>(value)) { | ||
| 475 | + // see comment in QPDF_Reference. | ||
| 476 | + return std::get<QPDF_Reference>(value).obj->as<T>(); | ||
| 477 | + } | ||
| 478 | + return nullptr; | ||
| 179 | } | 479 | } |
| 180 | 480 | ||
| 181 | private: | 481 | private: |
| 482 | + friend class QPDF_Stream; | ||
| 483 | + typedef std::variant< | ||
| 484 | + std::monostate, | ||
| 485 | + QPDF_Reserved, | ||
| 486 | + QPDF_Null, | ||
| 487 | + QPDF_Bool, | ||
| 488 | + QPDF_Integer, | ||
| 489 | + QPDF_Real, | ||
| 490 | + QPDF_String, | ||
| 491 | + QPDF_Name, | ||
| 492 | + QPDF_Array, | ||
| 493 | + QPDF_Dictionary, | ||
| 494 | + QPDF_Stream, | ||
| 495 | + QPDF_Operator, | ||
| 496 | + QPDF_InlineImage, | ||
| 497 | + QPDF_Unresolved, | ||
| 498 | + QPDF_Destroyed, | ||
| 499 | + QPDF_Reference> | ||
| 500 | + Value; | ||
| 501 | + Value value; | ||
| 502 | + | ||
| 182 | QPDFObject(QPDFObject const&) = delete; | 503 | QPDFObject(QPDFObject const&) = delete; |
| 183 | QPDFObject& operator=(QPDFObject const&) = delete; | 504 | QPDFObject& operator=(QPDFObject const&) = delete; |
| 184 | - std::shared_ptr<QPDFValue> value; | 505 | + |
| 506 | + std::shared_ptr<Description> object_description; | ||
| 507 | + | ||
| 508 | + QPDF* qpdf{nullptr}; | ||
| 509 | + QPDFObjGen og{}; | ||
| 510 | + qpdf_offset_t parsed_offset{-1}; | ||
| 185 | }; | 511 | }; |
| 186 | 512 | ||
| 187 | #endif // QPDFOBJECT_HH | 513 | #endif // QPDFOBJECT_HH |
libqpdf/qpdf/QPDFParser.hh
| 1 | #ifndef QPDFPARSER_HH | 1 | #ifndef QPDFPARSER_HH |
| 2 | #define QPDFPARSER_HH | 2 | #define QPDFPARSER_HH |
| 3 | 3 | ||
| 4 | -#include <qpdf/QPDFObjectHandle.hh> | ||
| 5 | -#include <qpdf/QPDFValue.hh> | 4 | +#include <qpdf/QPDFObjectHandle_private.hh> |
| 5 | +#include <qpdf/QPDFObject_private.hh> | ||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <string> | 8 | #include <string> |
| @@ -24,7 +24,7 @@ class QPDFParser | @@ -24,7 +24,7 @@ class QPDFParser | ||
| 24 | decrypter(decrypter), | 24 | decrypter(decrypter), |
| 25 | context(context), | 25 | context(context), |
| 26 | description( | 26 | description( |
| 27 | - std::make_shared<QPDFValue::Description>( | 27 | + std::make_shared<QPDFObject::Description>( |
| 28 | std::string(input.getName() + ", " + object_description + " at offset $PO"))), | 28 | std::string(input.getName() + ", " + object_description + " at offset $PO"))), |
| 29 | parse_pdf(parse_pdf) | 29 | parse_pdf(parse_pdf) |
| 30 | { | 30 | { |
| @@ -78,7 +78,7 @@ class QPDFParser | @@ -78,7 +78,7 @@ class QPDFParser | ||
| 78 | QPDFTokenizer& tokenizer; | 78 | QPDFTokenizer& tokenizer; |
| 79 | QPDFObjectHandle::StringDecrypter* decrypter; | 79 | QPDFObjectHandle::StringDecrypter* decrypter; |
| 80 | QPDF* context; | 80 | QPDF* context; |
| 81 | - std::shared_ptr<QPDFValue::Description> description; | 81 | + std::shared_ptr<QPDFObject::Description> description; |
| 82 | bool parse_pdf; | 82 | bool parse_pdf; |
| 83 | 83 | ||
| 84 | std::vector<StackFrame> stack; | 84 | std::vector<StackFrame> stack; |
libqpdf/qpdf/QPDFValue.hh deleted
| 1 | -#ifndef QPDFVALUE_HH | ||
| 2 | -#define QPDFVALUE_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/Constants.h> | ||
| 5 | -#include <qpdf/DLL.h> | ||
| 6 | -#include <qpdf/JSON.hh> | ||
| 7 | -#include <qpdf/QPDFObjGen.hh> | ||
| 8 | -#include <qpdf/Types.h> | ||
| 9 | - | ||
| 10 | -#include <string> | ||
| 11 | -#include <string_view> | ||
| 12 | -#include <variant> | ||
| 13 | - | ||
| 14 | -class QPDF; | ||
| 15 | -class QPDFObjectHandle; | ||
| 16 | -class QPDFObject; | ||
| 17 | - | ||
| 18 | -class QPDFValue: public std::enable_shared_from_this<QPDFValue> | ||
| 19 | -{ | ||
| 20 | - friend class QPDFObject; | ||
| 21 | - | ||
| 22 | - public: | ||
| 23 | - virtual ~QPDFValue() = default; | ||
| 24 | - | ||
| 25 | - virtual std::shared_ptr<QPDFObject> copy(bool shallow = false) = 0; | ||
| 26 | - virtual std::string unparse() = 0; | ||
| 27 | - virtual void writeJSON(int json_version, JSON::Writer& p) = 0; | ||
| 28 | - | ||
| 29 | - struct JSON_Descr | ||
| 30 | - { | ||
| 31 | - JSON_Descr(std::shared_ptr<std::string> input, std::string const& object) : | ||
| 32 | - input(input), | ||
| 33 | - object(object) | ||
| 34 | - { | ||
| 35 | - } | ||
| 36 | - | ||
| 37 | - std::shared_ptr<std::string> input; | ||
| 38 | - std::string object; | ||
| 39 | - }; | ||
| 40 | - | ||
| 41 | - struct ChildDescr | ||
| 42 | - { | ||
| 43 | - ChildDescr( | ||
| 44 | - std::shared_ptr<QPDFValue> parent, | ||
| 45 | - std::string_view const& static_descr, | ||
| 46 | - std::string var_descr) : | ||
| 47 | - parent(parent), | ||
| 48 | - static_descr(static_descr), | ||
| 49 | - var_descr(var_descr) | ||
| 50 | - { | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - std::weak_ptr<QPDFValue> parent; | ||
| 54 | - std::string_view const& static_descr; | ||
| 55 | - std::string var_descr; | ||
| 56 | - }; | ||
| 57 | - | ||
| 58 | - using Description = std::variant<std::string, JSON_Descr, ChildDescr>; | ||
| 59 | - | ||
| 60 | - virtual void | ||
| 61 | - setDescription(QPDF* qpdf_p, std::shared_ptr<Description>& description, qpdf_offset_t offset) | ||
| 62 | - { | ||
| 63 | - qpdf = qpdf_p; | ||
| 64 | - object_description = description; | ||
| 65 | - setParsedOffset(offset); | ||
| 66 | - } | ||
| 67 | - void | ||
| 68 | - setDefaultDescription(QPDF* a_qpdf, QPDFObjGen a_og) | ||
| 69 | - { | ||
| 70 | - qpdf = a_qpdf; | ||
| 71 | - og = a_og; | ||
| 72 | - } | ||
| 73 | - void | ||
| 74 | - setChildDescription( | ||
| 75 | - QPDF* a_qpdf, | ||
| 76 | - std::shared_ptr<QPDFValue> parent, | ||
| 77 | - std::string_view const& static_descr, | ||
| 78 | - std::string var_descr) | ||
| 79 | - { | ||
| 80 | - object_description = | ||
| 81 | - std::make_shared<Description>(ChildDescr(parent, static_descr, var_descr)); | ||
| 82 | - qpdf = a_qpdf; | ||
| 83 | - } | ||
| 84 | - std::string getDescription(); | ||
| 85 | - bool | ||
| 86 | - hasDescription() | ||
| 87 | - { | ||
| 88 | - return object_description || og.isIndirect(); | ||
| 89 | - } | ||
| 90 | - void | ||
| 91 | - setParsedOffset(qpdf_offset_t offset) | ||
| 92 | - { | ||
| 93 | - if (parsed_offset < 0) { | ||
| 94 | - parsed_offset = offset; | ||
| 95 | - } | ||
| 96 | - } | ||
| 97 | - qpdf_offset_t | ||
| 98 | - getParsedOffset() | ||
| 99 | - { | ||
| 100 | - return parsed_offset; | ||
| 101 | - } | ||
| 102 | - QPDF* | ||
| 103 | - getQPDF() | ||
| 104 | - { | ||
| 105 | - return qpdf; | ||
| 106 | - } | ||
| 107 | - QPDFObjGen | ||
| 108 | - getObjGen() | ||
| 109 | - { | ||
| 110 | - return og; | ||
| 111 | - } | ||
| 112 | - virtual void | ||
| 113 | - disconnect() | ||
| 114 | - { | ||
| 115 | - } | ||
| 116 | - virtual std::string | ||
| 117 | - getStringValue() const | ||
| 118 | - { | ||
| 119 | - return ""; | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | - protected: | ||
| 123 | - QPDFValue() = default; | ||
| 124 | - | ||
| 125 | - QPDFValue(qpdf_object_type_e type_code) : | ||
| 126 | - type_code(type_code) | ||
| 127 | - { | ||
| 128 | - } | ||
| 129 | - QPDFValue(qpdf_object_type_e type_code, QPDF* qpdf, QPDFObjGen og) : | ||
| 130 | - type_code(type_code), | ||
| 131 | - qpdf(qpdf), | ||
| 132 | - og(og) | ||
| 133 | - { | ||
| 134 | - } | ||
| 135 | - | ||
| 136 | - static std::shared_ptr<QPDFObject> do_create(QPDFValue*); | ||
| 137 | - | ||
| 138 | - private: | ||
| 139 | - QPDFValue(QPDFValue const&) = delete; | ||
| 140 | - QPDFValue& operator=(QPDFValue const&) = delete; | ||
| 141 | - std::shared_ptr<Description> object_description; | ||
| 142 | - | ||
| 143 | - const qpdf_object_type_e type_code{::ot_uninitialized}; | ||
| 144 | - | ||
| 145 | - protected: | ||
| 146 | - QPDF* qpdf{nullptr}; | ||
| 147 | - QPDFObjGen og{}; | ||
| 148 | - qpdf_offset_t parsed_offset{-1}; | ||
| 149 | -}; | ||
| 150 | - | ||
| 151 | -#endif // QPDFVALUE_HH |
libqpdf/qpdf/QPDF_Array.hh deleted
| 1 | -#ifndef QPDF_ARRAY_HH | ||
| 2 | -#define QPDF_ARRAY_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFObjectHandle.hh> | ||
| 5 | -#include <qpdf/QPDFObject_private.hh> | ||
| 6 | -#include <qpdf/QPDFValue.hh> | ||
| 7 | - | ||
| 8 | -#include <map> | ||
| 9 | -#include <vector> | ||
| 10 | - | ||
| 11 | -class QPDF_Array: public QPDFValue | ||
| 12 | -{ | ||
| 13 | - private: | ||
| 14 | - struct Sparse | ||
| 15 | - { | ||
| 16 | - int size{0}; | ||
| 17 | - std::map<int, std::shared_ptr<QPDFObject>> elements; | ||
| 18 | - }; | ||
| 19 | - | ||
| 20 | - public: | ||
| 21 | - ~QPDF_Array() override = default; | ||
| 22 | - static std::shared_ptr<QPDFObject> create(std::vector<QPDFObjectHandle> const& items); | ||
| 23 | - static std::shared_ptr<QPDFObject> | ||
| 24 | - create(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse); | ||
| 25 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 26 | - std::string unparse() override; | ||
| 27 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 28 | - void disconnect() override; | ||
| 29 | - | ||
| 30 | - private: | ||
| 31 | - friend class qpdf::Array; | ||
| 32 | - QPDF_Array(); | ||
| 33 | - QPDF_Array(QPDF_Array const&); | ||
| 34 | - QPDF_Array(std::vector<QPDFObjectHandle> const& items); | ||
| 35 | - QPDF_Array(std::vector<std::shared_ptr<QPDFObject>>&& items, bool sparse); | ||
| 36 | - | ||
| 37 | - int | ||
| 38 | - size() const | ||
| 39 | - { | ||
| 40 | - return sp ? sp->size : int(elements.size()); | ||
| 41 | - } | ||
| 42 | - void setFromVector(std::vector<QPDFObjectHandle> const& items); | ||
| 43 | - | ||
| 44 | - void checkOwnership(QPDFObjectHandle const& item) const; | ||
| 45 | - | ||
| 46 | - std::unique_ptr<Sparse> sp; | ||
| 47 | - std::vector<std::shared_ptr<QPDFObject>> elements; | ||
| 48 | -}; | ||
| 49 | - | ||
| 50 | -#endif // QPDF_ARRAY_HH |
libqpdf/qpdf/QPDF_Bool.hh deleted
| 1 | -#ifndef QPDF_BOOL_HH | ||
| 2 | -#define QPDF_BOOL_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Bool: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Bool() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(bool val); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - | ||
| 15 | - bool getVal() const; | ||
| 16 | - | ||
| 17 | - private: | ||
| 18 | - QPDF_Bool(bool val); | ||
| 19 | - bool val; | ||
| 20 | -}; | ||
| 21 | - | ||
| 22 | -#endif // QPDF_BOOL_HH |
libqpdf/qpdf/QPDF_Destroyed.hh deleted
| 1 | -#ifndef QPDF_DESTROYED_HH | ||
| 2 | -#define QPDF_DESTROYED_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Destroyed: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Destroyed() override = default; | ||
| 10 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 11 | - std::string unparse() override; | ||
| 12 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 13 | - static std::shared_ptr<QPDFValue> getInstance(); | ||
| 14 | - | ||
| 15 | - private: | ||
| 16 | - QPDF_Destroyed(); | ||
| 17 | -}; | ||
| 18 | - | ||
| 19 | -#endif // QPDF_DESTROYED_HH |
libqpdf/qpdf/QPDF_Dictionary.hh deleted
| 1 | -#ifndef QPDF_DICTIONARY_HH | ||
| 2 | -#define QPDF_DICTIONARY_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -#include <map> | ||
| 7 | -#include <set> | ||
| 8 | - | ||
| 9 | -#include <qpdf/QPDFExc.hh> | ||
| 10 | -#include <qpdf/QPDFObjectHandle.hh> | ||
| 11 | -#include <qpdf/QPDFObject_private.hh> | ||
| 12 | -#include <qpdf/QPDF_Null.hh> | ||
| 13 | - | ||
| 14 | -class QPDF_Dictionary: public QPDFValue | ||
| 15 | -{ | ||
| 16 | - public: | ||
| 17 | - ~QPDF_Dictionary() override = default; | ||
| 18 | - static std::shared_ptr<QPDFObject> create(std::map<std::string, QPDFObjectHandle> const& items); | ||
| 19 | - static std::shared_ptr<QPDFObject> create(std::map<std::string, QPDFObjectHandle>&& items); | ||
| 20 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 21 | - std::string unparse() override; | ||
| 22 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 23 | - void disconnect() override; | ||
| 24 | - | ||
| 25 | - private: | ||
| 26 | - friend class qpdf::BaseDictionary; | ||
| 27 | - | ||
| 28 | - QPDF_Dictionary(std::map<std::string, QPDFObjectHandle> const& items); | ||
| 29 | - QPDF_Dictionary(std::map<std::string, QPDFObjectHandle>&& items); | ||
| 30 | - | ||
| 31 | - std::map<std::string, QPDFObjectHandle> items; | ||
| 32 | -}; | ||
| 33 | - | ||
| 34 | -#endif // QPDF_DICTIONARY_HH |
libqpdf/qpdf/QPDF_InlineImage.hh deleted
| 1 | -#ifndef QPDF_INLINEIMAGE_HH | ||
| 2 | -#define QPDF_INLINEIMAGE_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_InlineImage: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_InlineImage() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(std::string const& val); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - std::string | ||
| 15 | - getStringValue() const override | ||
| 16 | - { | ||
| 17 | - return val; | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | - private: | ||
| 21 | - QPDF_InlineImage(std::string const& val); | ||
| 22 | - std::string val; | ||
| 23 | -}; | ||
| 24 | - | ||
| 25 | -#endif // QPDF_INLINEIMAGE_HH |
libqpdf/qpdf/QPDF_Integer.hh deleted
| 1 | -#ifndef QPDF_INTEGER_HH | ||
| 2 | -#define QPDF_INTEGER_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Integer: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Integer() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(long long value); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - long long getVal() const; | ||
| 15 | - | ||
| 16 | - private: | ||
| 17 | - QPDF_Integer(long long val); | ||
| 18 | - long long val; | ||
| 19 | -}; | ||
| 20 | - | ||
| 21 | -#endif // QPDF_INTEGER_HH |
libqpdf/qpdf/QPDF_Name.hh
| 1 | -#ifndef QPDF_NAME_HH | ||
| 2 | -#define QPDF_NAME_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Name: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Name() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(std::string const& name); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - std::string | ||
| 15 | - getStringValue() const override | ||
| 16 | - { | ||
| 17 | - return name; | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | - private: | ||
| 21 | - QPDF_Name(std::string const& name); | ||
| 22 | - std::string name; | ||
| 23 | -}; | ||
| 24 | - | ||
| 25 | -#endif // QPDF_NAME_HH |
libqpdf/qpdf/QPDF_Null.hh deleted
| 1 | -#ifndef QPDF_NULL_HH | ||
| 2 | -#define QPDF_NULL_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Null: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Null() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen()); | ||
| 11 | - static std::shared_ptr<QPDFObject> create( | ||
| 12 | - std::shared_ptr<QPDFObject> parent, | ||
| 13 | - std::string_view const& static_descr, | ||
| 14 | - std::string var_descr); | ||
| 15 | - static std::shared_ptr<QPDFObject> create( | ||
| 16 | - std::shared_ptr<QPDFValue> parent, | ||
| 17 | - std::string_view const& static_descr, | ||
| 18 | - std::string var_descr); | ||
| 19 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 20 | - std::string unparse() override; | ||
| 21 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 22 | - | ||
| 23 | - private: | ||
| 24 | - QPDF_Null(QPDF* qpdf = nullptr, QPDFObjGen og = QPDFObjGen()); | ||
| 25 | -}; | ||
| 26 | - | ||
| 27 | -#endif // QPDF_NULL_HH |
libqpdf/qpdf/QPDF_Operator.hh deleted
| 1 | -#ifndef QPDF_OPERATOR_HH | ||
| 2 | -#define QPDF_OPERATOR_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Operator: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Operator() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(std::string const& val); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - std::string | ||
| 15 | - getStringValue() const override | ||
| 16 | - { | ||
| 17 | - return val; | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | - private: | ||
| 21 | - QPDF_Operator(std::string const& val); | ||
| 22 | - std::string val; | ||
| 23 | -}; | ||
| 24 | - | ||
| 25 | -#endif // QPDF_OPERATOR_HH |
libqpdf/qpdf/QPDF_Real.hh deleted
| 1 | -#ifndef QPDF_REAL_HH | ||
| 2 | -#define QPDF_REAL_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Real: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Real() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(std::string const& val); | ||
| 11 | - static std::shared_ptr<QPDFObject> | ||
| 12 | - create(double value, int decimal_places, bool trim_trailing_zeroes); | ||
| 13 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 14 | - std::string unparse() override; | ||
| 15 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 16 | - std::string | ||
| 17 | - getStringValue() const override | ||
| 18 | - { | ||
| 19 | - return val; | ||
| 20 | - } | ||
| 21 | - | ||
| 22 | - private: | ||
| 23 | - QPDF_Real(std::string const& val); | ||
| 24 | - QPDF_Real(double value, int decimal_places, bool trim_trailing_zeroes); | ||
| 25 | - // Store reals as strings to avoid roundoff errors. | ||
| 26 | - std::string val; | ||
| 27 | -}; | ||
| 28 | - | ||
| 29 | -#endif // QPDF_REAL_HH |
libqpdf/qpdf/QPDF_Reserved.hh deleted
| 1 | -#ifndef QPDF_RESERVED_HH | ||
| 2 | -#define QPDF_RESERVED_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Reserved: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Reserved() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - | ||
| 15 | - private: | ||
| 16 | - QPDF_Reserved(); | ||
| 17 | -}; | ||
| 18 | - | ||
| 19 | -#endif // QPDF_RESERVED_HH |
libqpdf/qpdf/QPDF_Stream.hh deleted
| 1 | -#ifndef QPDF_STREAM_HH | ||
| 2 | -#define QPDF_STREAM_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/Types.h> | ||
| 5 | - | ||
| 6 | -#include <qpdf/QPDFObjectHandle.hh> | ||
| 7 | -#include <qpdf/QPDFObject_private.hh> | ||
| 8 | -#include <qpdf/QPDFStreamFilter.hh> | ||
| 9 | -#include <qpdf/QPDFValue.hh> | ||
| 10 | - | ||
| 11 | -#include <functional> | ||
| 12 | -#include <memory> | ||
| 13 | - | ||
| 14 | -class Pipeline; | ||
| 15 | -class QPDF; | ||
| 16 | - | ||
| 17 | -class QPDF_Stream final: public QPDFValue | ||
| 18 | -{ | ||
| 19 | - public: | ||
| 20 | - ~QPDF_Stream() final = default; | ||
| 21 | - static std::shared_ptr<QPDFObject> | ||
| 22 | - create(QPDF*, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length); | ||
| 23 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) final; | ||
| 24 | - std::string unparse() final; | ||
| 25 | - void writeJSON(int json_version, JSON::Writer& p) final; | ||
| 26 | - void setDescription( | ||
| 27 | - QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) final; | ||
| 28 | - void disconnect() final; | ||
| 29 | - | ||
| 30 | - private: | ||
| 31 | - friend class qpdf::Stream; | ||
| 32 | - | ||
| 33 | - QPDF_Stream( | ||
| 34 | - QPDF*, QPDFObjGen og, QPDFObjectHandle stream_dict, qpdf_offset_t offset, size_t length); | ||
| 35 | - | ||
| 36 | - void replaceFilterData( | ||
| 37 | - QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms, size_t length); | ||
| 38 | - void setDictDescription(); | ||
| 39 | - | ||
| 40 | - bool filter_on_write; | ||
| 41 | - QPDFObjectHandle stream_dict; | ||
| 42 | - size_t length; | ||
| 43 | - std::shared_ptr<Buffer> stream_data; | ||
| 44 | - std::shared_ptr<QPDFObjectHandle::StreamDataProvider> stream_provider; | ||
| 45 | - std::vector<std::shared_ptr<QPDFObjectHandle::TokenFilter>> token_filters; | ||
| 46 | -}; | ||
| 47 | - | ||
| 48 | -#endif // QPDF_STREAM_HH |
libqpdf/qpdf/QPDF_String.hh deleted
| 1 | -#ifndef QPDF_STRING_HH | ||
| 2 | -#define QPDF_STRING_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -// QPDF_Strings may included embedded null characters. | ||
| 7 | - | ||
| 8 | -class QPDF_String: public QPDFValue | ||
| 9 | -{ | ||
| 10 | - friend class QPDFWriter; | ||
| 11 | - | ||
| 12 | - public: | ||
| 13 | - ~QPDF_String() override = default; | ||
| 14 | - static std::shared_ptr<QPDFObject> create(std::string const& val); | ||
| 15 | - static std::shared_ptr<QPDFObject> create_utf16(std::string const& utf8_val); | ||
| 16 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 17 | - std::string unparse() override; | ||
| 18 | - std::string unparse(bool force_binary); | ||
| 19 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 20 | - std::string getUTF8Val() const; | ||
| 21 | - std::string | ||
| 22 | - getStringValue() const override | ||
| 23 | - { | ||
| 24 | - return val; | ||
| 25 | - } | ||
| 26 | - | ||
| 27 | - private: | ||
| 28 | - QPDF_String(std::string const& val); | ||
| 29 | - bool useHexString() const; | ||
| 30 | - std::string val; | ||
| 31 | -}; | ||
| 32 | - | ||
| 33 | -#endif // QPDF_STRING_HH |
libqpdf/qpdf/QPDF_Unresolved.hh deleted
| 1 | -#ifndef QPDF_UNRESOLVED_HH | ||
| 2 | -#define QPDF_UNRESOLVED_HH | ||
| 3 | - | ||
| 4 | -#include <qpdf/QPDFValue.hh> | ||
| 5 | - | ||
| 6 | -class QPDF_Unresolved: public QPDFValue | ||
| 7 | -{ | ||
| 8 | - public: | ||
| 9 | - ~QPDF_Unresolved() override = default; | ||
| 10 | - static std::shared_ptr<QPDFObject> create(QPDF* qpdf, QPDFObjGen og); | ||
| 11 | - std::shared_ptr<QPDFObject> copy(bool shallow = false) override; | ||
| 12 | - std::string unparse() override; | ||
| 13 | - void writeJSON(int json_version, JSON::Writer& p) override; | ||
| 14 | - std::string getStringValue() const override; | ||
| 15 | - | ||
| 16 | - private: | ||
| 17 | - QPDF_Unresolved(QPDF* qpdf, QPDFObjGen og); | ||
| 18 | -}; | ||
| 19 | - | ||
| 20 | -#endif // QPDF_UNRESOLVED_HH |
libtests/sparse_array.cc
| @@ -3,14 +3,13 @@ | @@ -3,14 +3,13 @@ | ||
| 3 | #include <qpdf/QPDF.hh> | 3 | #include <qpdf/QPDF.hh> |
| 4 | #include <qpdf/QPDFObjectHandle_private.hh> | 4 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 5 | #include <qpdf/QPDFObject_private.hh> | 5 | #include <qpdf/QPDFObject_private.hh> |
| 6 | -#include <qpdf/QPDF_Array.hh> | ||
| 7 | 6 | ||
| 8 | #include <iostream> | 7 | #include <iostream> |
| 9 | 8 | ||
| 10 | int | 9 | int |
| 11 | main() | 10 | main() |
| 12 | { | 11 | { |
| 13 | - auto obj = QPDF_Array::create({}, true); | 12 | + auto obj = QPDFObject::create<QPDF_Array>(std::vector<std::shared_ptr<QPDFObject>>(), true); |
| 14 | auto a = qpdf::Array(obj); | 13 | auto a = qpdf::Array(obj); |
| 15 | 14 | ||
| 16 | assert(a.size() == 0); | 15 | assert(a.size() == 0); |
| @@ -88,7 +87,8 @@ main() | @@ -88,7 +87,8 @@ main() | ||
| 88 | QPDF pdf; | 87 | QPDF pdf; |
| 89 | pdf.emptyPDF(); | 88 | pdf.emptyPDF(); |
| 90 | 89 | ||
| 91 | - obj = QPDF_Array::create({10, "null"_qpdf.getObj()}, true); | 90 | + obj = QPDFObject::create<QPDF_Array>( |
| 91 | + std::vector<std::shared_ptr<QPDFObject>>{10, "null"_qpdf.getObj()}, true); | ||
| 92 | auto b = qpdf::Array(obj); | 92 | auto b = qpdf::Array(obj); |
| 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); |