mirror of
https://github.com/qpdf/qpdf.git
synced 2025-02-07 06:08:26 +00:00
Add new writeJSON methods
Create an alternative to getJSON to allow an object handle to be written as JSON without the overhead of creating a JSON object.
This commit is contained in:
parent
9e90007a4a
commit
e2737ab646
@ -1353,6 +1353,8 @@ class QPDFObjectHandle
|
||||
return obj.get();
|
||||
}
|
||||
|
||||
void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false);
|
||||
|
||||
private:
|
||||
QPDF_Array* asArray();
|
||||
QPDF_Bool* asBool();
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <qpdf/BufferInputSource.hh>
|
||||
#include <qpdf/Pl_Buffer.hh>
|
||||
#include <qpdf/Pl_QPDFTokenizer.hh>
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFExc.hh>
|
||||
#include <qpdf/QPDFLogger.hh>
|
||||
@ -1621,6 +1622,18 @@ QPDFObjectHandle::getJSON(int json_version, bool dereference_indirect)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDFObjectHandle::writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect)
|
||||
{
|
||||
if (!dereference_indirect && isIndirect()) {
|
||||
p << "\"" << getObjGen().unparse(' ') << " R\"";
|
||||
} else if (!dereference()) {
|
||||
throw std::logic_error("attempted to dereference an uninitialized QPDFObjectHandle");
|
||||
} else {
|
||||
obj->writeJSON(json_version, p);
|
||||
}
|
||||
}
|
||||
|
||||
JSON
|
||||
QPDFObjectHandle::getStreamJSON(
|
||||
int json_version,
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_Array.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/QPDFObject_private.hh>
|
||||
#include <qpdf/QTC.hh>
|
||||
@ -180,6 +181,43 @@ QPDF_Array::getJSON(int json_version)
|
||||
return j_array;
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Array::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p.writeStart('[');
|
||||
if (sp) {
|
||||
int next = 0;
|
||||
for (auto& item: sp->elements) {
|
||||
int key = item.first;
|
||||
for (int j = next; j < key; ++j) {
|
||||
p.writeNext() << "null";
|
||||
}
|
||||
p.writeNext();
|
||||
auto og = item.second->getObjGen();
|
||||
if (og.isIndirect()) {
|
||||
p << "\"" << og.unparse(' ') << " R\"";
|
||||
} else {
|
||||
item.second->writeJSON(json_version, p);
|
||||
}
|
||||
next = ++key;
|
||||
}
|
||||
for (int j = next; j < sp->size; ++j) {
|
||||
p.writeNext() << "null";
|
||||
}
|
||||
} else {
|
||||
for (auto const& item: elements) {
|
||||
p.writeNext();
|
||||
auto og = item->getObjGen();
|
||||
if (og.isIndirect()) {
|
||||
p << "\"" << og.unparse(' ') << " R\"";
|
||||
} else {
|
||||
item->writeJSON(json_version, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
p.writeEnd(']');
|
||||
}
|
||||
|
||||
QPDFObjectHandle
|
||||
QPDF_Array::at(int n) const noexcept
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <qpdf/QPDF_Bool.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
|
||||
QPDF_Bool::QPDF_Bool(bool val) :
|
||||
QPDFValue(::ot_boolean, "boolean"),
|
||||
val(val)
|
||||
@ -30,6 +32,12 @@ QPDF_Bool::getJSON(int json_version)
|
||||
return JSON::makeBool(this->val);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Bool::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p << val;
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF_Bool::getVal() const
|
||||
{
|
||||
|
@ -34,3 +34,9 @@ QPDF_Destroyed::getJSON(int json_version)
|
||||
throw std::logic_error("attempted to get JSON from a QPDFObjectHandle from a destroyed QPDF");
|
||||
return JSON::makeNull();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Destroyed::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
throw std::logic_error("attempted to get JSON from a QPDFObjectHandle from a destroyed QPDF");
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_Dictionary.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QPDFObject_private.hh>
|
||||
#include <qpdf/QPDF_Name.hh>
|
||||
#include <qpdf/QPDF_Null.hh>
|
||||
@ -91,6 +92,33 @@ QPDF_Dictionary::getJSON(int json_version)
|
||||
return j;
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Dictionary::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p.writeStart('{');
|
||||
for (auto& iter: this->items) {
|
||||
if (!iter.second.isNull()) {
|
||||
p.writeNext();
|
||||
if (json_version == 1) {
|
||||
p << "\"" << JSON::Writer::encode_string(QPDF_Name::normalizeName(iter.first)) << "\": ";
|
||||
} else {
|
||||
bool has_8bit_chars;
|
||||
bool is_valid_utf8;
|
||||
bool is_utf16;
|
||||
QUtil::analyze_encoding(iter.first, has_8bit_chars, is_valid_utf8, is_utf16);
|
||||
if (!has_8bit_chars || is_valid_utf8) {
|
||||
p << "\"" << JSON::Writer::encode_string(iter.first) << "\": ";
|
||||
} else {
|
||||
p << "\"n:" << JSON::Writer::encode_string(QPDF_Name::normalizeName(iter.first))
|
||||
<< "\": ";
|
||||
}
|
||||
}
|
||||
iter.second.writeJSON(json_version, p);
|
||||
}
|
||||
}
|
||||
p.writeEnd('}');
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF_Dictionary::hasKey(std::string const& key)
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <qpdf/QPDF_InlineImage.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
|
||||
QPDF_InlineImage::QPDF_InlineImage(std::string const& val) :
|
||||
QPDFValue(::ot_inlineimage, "inline-image"),
|
||||
val(val)
|
||||
@ -29,3 +31,9 @@ QPDF_InlineImage::getJSON(int json_version)
|
||||
{
|
||||
return JSON::makeNull();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_InlineImage::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p << "null";
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_Integer.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
QPDF_Integer::QPDF_Integer(long long val) :
|
||||
@ -32,6 +33,12 @@ QPDF_Integer::getJSON(int json_version)
|
||||
return JSON::makeInt(this->val);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Integer::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p << std::to_string(this->val);
|
||||
}
|
||||
|
||||
long long
|
||||
QPDF_Integer::getVal() const
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_Name.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
QPDF_Name::QPDF_Name(std::string const& name) :
|
||||
@ -68,3 +69,21 @@ QPDF_Name::getJSON(int json_version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Name::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
if (json_version == 1) {
|
||||
p << "\"" << JSON::Writer::encode_string(normalizeName(name)) << "\"";
|
||||
} else {
|
||||
bool has_8bit_chars;
|
||||
bool is_valid_utf8;
|
||||
bool is_utf16;
|
||||
QUtil::analyze_encoding(this->name, has_8bit_chars, is_valid_utf8, is_utf16);
|
||||
if (!has_8bit_chars || is_valid_utf8) {
|
||||
p << "\"" << JSON::Writer::encode_string(name) << "\"";
|
||||
} else {
|
||||
p << "\"n:" << JSON::Writer::encode_string(normalizeName(name)) << "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_Null.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QPDFObject_private.hh>
|
||||
|
||||
QPDF_Null::QPDF_Null() :
|
||||
@ -49,3 +50,9 @@ QPDF_Null::getJSON(int json_version)
|
||||
// If this is updated, QPDF_Array::getJSON must also be updated.
|
||||
return JSON::makeNull();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Null::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p << "null";
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <qpdf/QPDF_Operator.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
|
||||
QPDF_Operator::QPDF_Operator(std::string const& val) :
|
||||
QPDFValue(::ot_operator, "operator"),
|
||||
val(val)
|
||||
@ -29,3 +31,9 @@ QPDF_Operator::getJSON(int json_version)
|
||||
{
|
||||
return JSON::makeNull();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Operator::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
p << "null";
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_Real.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
QPDF_Real::QPDF_Real(std::string const& val) :
|
||||
@ -56,3 +57,18 @@ QPDF_Real::getJSON(int json_version)
|
||||
}
|
||||
return JSON::makeNumber(result);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Real::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
if (this->val.length() == 0) {
|
||||
// Can't really happen...
|
||||
p << "0";
|
||||
} else if (this->val.at(0) == '.') {
|
||||
p << "0" << this->val;
|
||||
} else if (this->val.length() >= 2 && this->val.at(0) == '-' && this->val.at(1) == '.') {
|
||||
p << "-0." << this->val.substr(2);
|
||||
} else {
|
||||
p << this->val;
|
||||
}
|
||||
}
|
||||
|
@ -32,3 +32,9 @@ QPDF_Reserved::getJSON(int json_version)
|
||||
throw std::logic_error("QPDFObjectHandle: attempting to get JSON from a reserved object");
|
||||
return JSON::makeNull();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Reserved::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
throw std::logic_error("QPDFObjectHandle: attempting to get JSON from a reserved object");
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <qpdf/QPDF_Stream.hh>
|
||||
|
||||
#include <qpdf/ContentNormalizer.hh>
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/Pipeline.hh>
|
||||
#include <qpdf/Pl_Base64.hh>
|
||||
#include <qpdf/Pl_Buffer.hh>
|
||||
@ -185,6 +186,12 @@ QPDF_Stream::getJSON(int json_version)
|
||||
return getStreamJSON(json_version, qpdf_sj_none, qpdf_dl_none, nullptr, "");
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Stream::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
stream_dict.writeJSON(json_version, p);
|
||||
}
|
||||
|
||||
JSON
|
||||
QPDF_Stream::getStreamJSON(
|
||||
int json_version,
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <qpdf/QPDF_String.hh>
|
||||
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
// DO NOT USE ctype -- it is locale dependent for some things, and it's not worth the risk of
|
||||
@ -74,6 +75,30 @@ QPDF_String::getJSON(int json_version)
|
||||
return JSON::makeString(result);
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_String::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
auto candidate = getUTF8Val();
|
||||
if (json_version == 1) {
|
||||
|
||||
p << "\"" << JSON::Writer::encode_string(candidate) << "\"";
|
||||
} else {
|
||||
// See if we can unambiguously represent as Unicode.
|
||||
if (QUtil::is_utf16(this->val) || QUtil::is_explicit_utf8(this->val)) {
|
||||
p << "\"u:" << JSON::Writer::encode_string(candidate) <<"\"";
|
||||
return;
|
||||
} else if (!useHexString()) {
|
||||
std::string test;
|
||||
if (QUtil::utf8_to_pdf_doc(candidate, test, '?') && (test == this->val)) {
|
||||
// This is a PDF-doc string that can be losslessly encoded as Unicode.
|
||||
p << "\"u:" << JSON::Writer::encode_string(candidate) <<"\"";
|
||||
return;
|
||||
}
|
||||
}
|
||||
p << "\"b:" << QUtil::hex_encode(val) <<"\"";
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
QPDF_String::useHexString() const
|
||||
{
|
||||
|
@ -33,3 +33,9 @@ QPDF_Unresolved::getJSON(int json_version)
|
||||
throw std::logic_error("attempted to get JSON from an unresolved QPDFObjectHandle");
|
||||
return JSON::makeNull();
|
||||
}
|
||||
|
||||
void
|
||||
QPDF_Unresolved::writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
throw std::logic_error("attempted to get JSON from an unresolved QPDFObjectHandle");
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <qpdf/QPDF.hh>
|
||||
|
||||
#include <qpdf/FileInputSource.hh>
|
||||
#include <qpdf/JSON_writer.hh>
|
||||
#include <qpdf/Pl_Base64.hh>
|
||||
#include <qpdf/Pl_StdioFile.hh>
|
||||
#include <qpdf/QIntC.hh>
|
||||
@ -864,9 +865,15 @@ void
|
||||
QPDF::writeJSONObject(
|
||||
int version, Pipeline* p, bool& first, std::string const& key, QPDFObjectHandle& obj)
|
||||
{
|
||||
auto j = JSON::makeDictionary();
|
||||
j.addDictionaryMember("value", obj.getJSON(version, true));
|
||||
JSON::writeDictionaryItem(p, first, key, j, 3);
|
||||
if (first) {
|
||||
*p << "\n \"" << key << "\": {\n \"value\": ";
|
||||
first = false;
|
||||
} else {
|
||||
*p << ",\n \"" << key << "\": {\n \"value\": ";
|
||||
}
|
||||
auto w = JSON::Writer(p, 4);
|
||||
obj.writeJSON(version, w, true);
|
||||
*p << "\n }";
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -38,6 +38,11 @@ class QPDFObject
|
||||
{
|
||||
return value->getJSON(json_version);
|
||||
}
|
||||
void
|
||||
writeJSON(int json_version, JSON::Writer& p)
|
||||
{
|
||||
return value->writeJSON(json_version, p);
|
||||
}
|
||||
std::string
|
||||
getStringValue() const
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ class QPDFValue: public std::enable_shared_from_this<QPDFValue>
|
||||
virtual std::shared_ptr<QPDFObject> copy(bool shallow = false) = 0;
|
||||
virtual std::string unparse() = 0;
|
||||
virtual JSON getJSON(int json_version) = 0;
|
||||
virtual void writeJSON(int json_version, JSON::Writer& p) = 0;
|
||||
|
||||
struct JSON_Descr
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ class QPDF_Array: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
void disconnect() override;
|
||||
|
||||
int
|
||||
|
@ -11,6 +11,8 @@ class QPDF_Bool: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
|
||||
bool getVal() const;
|
||||
|
||||
private:
|
||||
|
@ -10,6 +10,7 @@ class QPDF_Destroyed: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
static std::shared_ptr<QPDFValue> getInstance();
|
||||
|
||||
private:
|
||||
|
@ -17,6 +17,7 @@ class QPDF_Dictionary: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
void disconnect() override;
|
||||
|
||||
// hasKey() and getKeys() treat keys with null values as if they aren't there. getKey() returns
|
||||
|
@ -11,6 +11,7 @@ class QPDF_InlineImage: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
std::string
|
||||
getStringValue() const override
|
||||
{
|
||||
|
@ -11,6 +11,7 @@ class QPDF_Integer: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
long long getVal() const;
|
||||
|
||||
private:
|
||||
|
@ -11,6 +11,7 @@ class QPDF_Name: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
|
||||
// Put # into strings with characters unsuitable for name token
|
||||
static std::string normalizeName(std::string const& name);
|
||||
|
@ -19,6 +19,7 @@ class QPDF_Null: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
|
||||
private:
|
||||
QPDF_Null();
|
||||
|
@ -11,6 +11,7 @@ class QPDF_Operator: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
std::string
|
||||
getStringValue() const override
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ class QPDF_Real: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
std::string
|
||||
getStringValue() const override
|
||||
{
|
||||
|
@ -11,6 +11,7 @@ class QPDF_Reserved: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
|
||||
private:
|
||||
QPDF_Reserved();
|
||||
|
@ -26,6 +26,7 @@ class QPDF_Stream: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
void setDescription(
|
||||
QPDF*, std::shared_ptr<QPDFValue::Description>& description, qpdf_offset_t offset) override;
|
||||
void disconnect() override;
|
||||
|
@ -17,6 +17,7 @@ class QPDF_String: public QPDFValue
|
||||
std::string unparse() override;
|
||||
std::string unparse(bool force_binary);
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
std::string getUTF8Val() const;
|
||||
std::string
|
||||
getStringValue() const override
|
||||
|
@ -11,6 +11,7 @@ class QPDF_Unresolved: public QPDFValue
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) override;
|
||||
std::string unparse() override;
|
||||
JSON getJSON(int json_version) override;
|
||||
void writeJSON(int json_version, JSON::Writer& p) override;
|
||||
|
||||
private:
|
||||
QPDF_Unresolved(QPDF* qpdf, QPDFObjGen const& og);
|
||||
|
Loading…
x
Reference in New Issue
Block a user