diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | cSpell.json | 1 | ||||
-rw-r--r-- | include/qpdf/JSON.hh | 14 | ||||
-rw-r--r-- | libqpdf/JSON.cc | 24 | ||||
-rw-r--r-- | libtests/json.cc | 14 |
6 files changed, 57 insertions, 5 deletions
@@ -1,5 +1,9 @@ 2022-05-04 Jay Berkenbilt <ejb@ql.org> + * JSON: add a new "blob" type that takes a function to write data + into. The blob is serialized as a base64-encoded representation of + whatever is written to the function. + * FileInputSource has new constructors that eliminate the need to call setFilename or setFile in most cases. @@ -51,11 +51,6 @@ library, when context is available, to have a pipeline rather than a FILE* or std::ostream. This makes it possible for people to capture output more flexibly. -Have a json blob defined by a function that takes a pipeline and -writes data to the pipeline. It's writer should create a Pl_Base64 -> -Pl_Concatenate in front of the pipeline passed to write and call the -function with that. - For json output, do not unparse to string. Use the writers instead. Write incrementally. This changes ordering only, but we should be able manually update the test output for those cases. Objects should be diff --git a/cSpell.json b/cSpell.json index cba39d9a..1cc0363e 100644 --- a/cSpell.json +++ b/cSpell.json @@ -199,6 +199,7 @@ "itemizedlist", "jarr", "jbig", + "jblob", "jdimension", "jdouble", "jerr", diff --git a/include/qpdf/JSON.hh b/include/qpdf/JSON.hh index 435c2362..4f4162fc 100644 --- a/include/qpdf/JSON.hh +++ b/include/qpdf/JSON.hh @@ -122,6 +122,13 @@ class JSON QPDF_DLL static JSON makeNull(); + // A blob serializes as a string. The function will be called by + // JSON with a pipeline and should write binary data to the + // pipeline but not call finish(). JSON will call finish() at the + // right time. + QPDF_DLL + static JSON makeBlob(std::function<void(Pipeline*)>); + QPDF_DLL bool isArray() const; @@ -323,6 +330,13 @@ class JSON virtual ~JSON_null() = default; virtual void write(Pipeline*, size_t depth) const; }; + struct JSON_blob: public JSON_value + { + JSON_blob(std::function<void(Pipeline*)> fn); + virtual ~JSON_blob() = default; + virtual void write(Pipeline*, size_t depth) const; + std::function<void(Pipeline*)> fn; + }; JSON(std::shared_ptr<JSON_value>); diff --git a/libqpdf/JSON.cc b/libqpdf/JSON.cc index 71ea33d7..8549b7ed 100644 --- a/libqpdf/JSON.cc +++ b/libqpdf/JSON.cc @@ -1,6 +1,8 @@ #include <qpdf/JSON.hh> #include <qpdf/BufferInputSource.hh> +#include <qpdf/Pl_Base64.hh> +#include <qpdf/Pl_Concatenate.hh> #include <qpdf/Pl_String.hh> #include <qpdf/QTC.hh> #include <qpdf/QUtil.hh> @@ -168,6 +170,22 @@ JSON::JSON_null::write(Pipeline* p, size_t) const *p << "null"; } +JSON::JSON_blob::JSON_blob(std::function<void(Pipeline*)> fn) : + fn(fn) +{ +} + +void +JSON::JSON_blob::write(Pipeline* p, size_t) const +{ + *p << "\""; + Pl_Concatenate cat("blob concatenate", p); + Pl_Base64 base64("blob base64", &cat, Pl_Base64::a_encode); + fn(&base64); + base64.finish(); + *p << "\""; +} + void JSON::write(Pipeline* p, size_t depth) const { @@ -306,6 +324,12 @@ JSON::makeNull() return JSON(std::make_shared<JSON_null>()); } +JSON +JSON::makeBlob(std::function<void(Pipeline*)> fn) +{ + return JSON(std::make_shared<JSON_blob>(fn)); +} + bool JSON::isArray() const { diff --git a/libtests/json.cc b/libtests/json.cc index 3844222f..b386e6eb 100644 --- a/libtests/json.cc +++ b/libtests/json.cc @@ -1,6 +1,7 @@ #include <qpdf/assert_test.h> #include <qpdf/JSON.hh> +#include <qpdf/Pipeline.hh> #include <qpdf/QPDFObjectHandle.hh> #include <iostream> @@ -113,6 +114,19 @@ test_main() {"c", "[\n true\n]"}, }; assert(dvalue == xdvalue); + auto blob_data = [](Pipeline* p) { + *p << "\x01\x02\x03\x04\x05\xff\xfe\xfd\xfc\xfb"; + }; + JSON jblob = JSON::makeDictionary(); + jblob.addDictionaryMember("normal", JSON::parse(R"("string")")); + jblob.addDictionaryMember("blob", JSON::makeBlob(blob_data)); + // cSpell:ignore AQIDBAX + check( + jblob, + "{\n" + " \"blob\": \"AQIDBAX//v38+w==\",\n" + " \"normal\": \"string\"\n" + "}"); } static void |