2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-01 01:40:51 +00:00

Add new method QPDF_Stream::writeStreamJSON

(Replacing the temporary implementation from the last commit.)
This commit is contained in:
m-holger 2024-02-15 12:33:31 +00:00
parent 920e929864
commit b15d0bf6e1
2 changed files with 69 additions and 50 deletions

View File

@ -178,9 +178,9 @@ QPDF_Stream::unparse()
} }
void void
QPDF_Stream::writeJSON(int json_version, JSON::Writer& p) QPDF_Stream::writeJSON(int json_version, JSON::Writer& jw)
{ {
stream_dict.writeJSON(json_version, p); stream_dict.writeJSON(json_version, jw);
} }
JSON JSON
@ -233,21 +233,27 @@ QPDF_Stream::writeStreamJSON(
break; break;
} }
auto dict = this->stream_dict; jw.writeStart('{');
JSON result = JSON::makeDictionary();
if (json_data != qpdf_sj_none) { if (json_data == qpdf_sj_none) {
jw.writeNext();
jw << R"("dict": )";
stream_dict.writeJSON(json_version, jw);
jw.writeEnd('}');
return decode_level;
}
Pl_Discard discard; Pl_Discard discard;
Pl_Buffer buf_pl{"stream data"}; Pl_Buffer buf_pl{"stream data"};
// buf_pl contains valid data and is ready for retrieval of the data. Pipeline* data_pipeline = &buf_pl;
if (no_data_key && json_data == qpdf_sj_inline) {
data_pipeline = &discard;
}
// pipeStreamData produced valid data.
bool buf_pl_ready = false; bool buf_pl_ready = false;
bool filtered = false; bool filtered = false;
bool filter = (decode_level != qpdf_dl_none); bool filter = (decode_level != qpdf_dl_none);
for (int attempt = 1; attempt <= 2; ++attempt) { for (int attempt = 1; attempt <= 2; ++attempt) {
Pipeline* data_pipeline = &discard;
if (json_data == qpdf_sj_file) {
// We need to capture the data to write
data_pipeline = &buf_pl;
}
bool succeeded = bool succeeded =
pipeStreamData(data_pipeline, &filtered, 0, decode_level, false, (attempt == 1)); pipeStreamData(data_pipeline, &filtered, 0, decode_level, false, (attempt == 1));
if (!succeeded || (filter && !filtered)) { if (!succeeded || (filter && !filtered)) {
@ -264,27 +270,28 @@ QPDF_Stream::writeStreamJSON(
throw std::logic_error("QPDF_Stream: failed to get stream data"); throw std::logic_error("QPDF_Stream: failed to get stream data");
} }
// We can use unsafeShallowCopy because we are only touching top-level keys. // We can use unsafeShallowCopy because we are only touching top-level keys.
dict = this->stream_dict.unsafeShallowCopy(); auto dict = stream_dict.unsafeShallowCopy();
dict.removeKey("/Length"); dict.removeKey("/Length");
if (filter && filtered) { if (filter && filtered) {
dict.removeKey("/Filter"); dict.removeKey("/Filter");
dict.removeKey("/DecodeParms"); dict.removeKey("/DecodeParms");
} }
if (json_data == qpdf_sj_file) { if (json_data == qpdf_sj_file) {
result.addDictionaryMember("datafile", JSON::makeString(data_filename)); jw.writeNext() << R"("datafile": ")" << JSON::Writer::encode_string(data_filename) << "\"";
p->writeString(buf_pl.getString()); p->writeString(buf_pl.getString());
} else if (json_data == qpdf_sj_inline) { } else if (json_data == qpdf_sj_inline) {
if (!no_data_key) { if (!no_data_key) {
result.addDictionaryMember( jw.writeNext() << R"("data": ")";
"data", JSON::makeBlob(StreamBlobProvider(this, decode_level))); jw.writeBase64(buf_pl.getString()) << "\"";
} }
} else { } else {
throw std::logic_error("QPDF_Stream: unexpected value of json_data"); throw std::logic_error("QPDF_Stream::writeStreamJSON : unexpected value of json_data");
} }
}
result.addDictionaryMember("dict", dict.getJSON(json_version)); jw.writeNext() << R"("dict": )";
jw << std::move(result); dict.writeJSON(json_version, jw);
jw.writeEnd('}');
return decode_level; return decode_level;
} }

View File

@ -3,6 +3,8 @@
#include <qpdf/JSON.hh> #include <qpdf/JSON.hh>
#include <qpdf/Pipeline.hh> #include <qpdf/Pipeline.hh>
#include <qpdf/Pl_Base64.hh>
#include <qpdf/Pl_Concatenate.hh>
#include <string_view> #include <string_view>
@ -27,6 +29,16 @@ class JSON::Writer
return *this; return *this;
} }
Writer&
writeBase64(std::string_view sv)
{
Pl_Concatenate cat{"writer concat", p};
Pl_Base64 base{"writer base64", &cat, Pl_Base64::a_encode};
base.write(reinterpret_cast<unsigned char const*>(sv.data()), sv.size());
base.finish();
return *this;
}
Writer& Writer&
writeNext() writeNext()
{ {