Commit b48a0ff0e8e1861884b2dac62d98d39f8e194086

Authored by Jay Berkenbilt
1 parent 8cf7f2bf

Add qpdf_empty_pdf to C API

ChangeLog
1 2022-02-05 Jay Berkenbilt <ejb@ql.org> 1 2022-02-05 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Expose QPDF::emptyPDF to the C API as qpdf_empty_pdf()
  4 +
3 * Add comments letting people know that the version string 5 * Add comments letting people know that the version string
4 returned by QPDF::QPDFVersion and qpdf_get_qpdf_version is static. 6 returned by QPDF::QPDFVersion and qpdf_get_qpdf_version is static.
5 7
1 10.6 1 10.6
2 ==== 2 ====
3 3
4 -* Expose emptyPDF to the C API. Ensure that qpdf_get_qpdf_version is  
5 - always static.  
6 -  
7 * Consider doing one big commit to reformat the entire codebase using 4 * Consider doing one big commit to reformat the entire codebase using
8 clang-format or a similar tool. Consider using blame.ignoreRevsFile 5 clang-format or a similar tool. Consider using blame.ignoreRevsFile
9 or similar (or otherwise study git blame to see how to minimize the 6 or similar (or otherwise study git blame to see how to minimize the
include/qpdf/qpdf-c.h
@@ -178,9 +178,9 @@ extern &quot;C&quot; { @@ -178,9 +178,9 @@ extern &quot;C&quot; {
178 char const* qpdf_get_qpdf_version(); 178 char const* qpdf_get_qpdf_version();
179 179
180 /* Returns dynamically allocated qpdf_data pointer; must be freed 180 /* Returns dynamically allocated qpdf_data pointer; must be freed
181 - * by calling qpdf_cleanup. You must call qpdf_read or one of the  
182 - * other qpdf_read_* functions before calling any function that  
183 - * would need to operate on the PDF file. 181 + * by calling qpdf_cleanup. You must call qpdf_read, one of the
  182 + * other qpdf_read_* functions, or qpdf_empty_pdf before calling
  183 + * any function that would need to operate on the PDF file.
184 */ 184 */
185 QPDF_DLL 185 QPDF_DLL
186 qpdf_data qpdf_init(); 186 qpdf_data qpdf_init();
@@ -289,6 +289,13 @@ extern &quot;C&quot; { @@ -289,6 +289,13 @@ extern &quot;C&quot; {
289 unsigned long long size, 289 unsigned long long size,
290 char const* password); 290 char const* password);
291 291
  292 + /* Calling qpdf_empty_pdf initializes this qpdf object with an
  293 + * empty PDF, making it possible to create a PDF from scratch
  294 + * using the C API. Added in 10.6.
  295 + */
  296 + QPDF_DLL
  297 + QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf);
  298 +
292 /* Read functions below must be called after qpdf_read or 299 /* Read functions below must be called after qpdf_read or
293 * qpdf_read_memory. */ 300 * qpdf_read_memory. */
294 301
libqpdf/qpdf-c.cc
@@ -356,6 +356,14 @@ QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf, @@ -356,6 +356,14 @@ QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf,
356 return status; 356 return status;
357 } 357 }
358 358
  359 +QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf)
  360 +{
  361 + qpdf->filename = "empty PDF";
  362 + qpdf->qpdf->emptyPDF();
  363 + QTC::TC("qpdf", "qpdf-c called qpdf_empty_pdf");
  364 + return QPDF_SUCCESS;
  365 +}
  366 +
359 char const* qpdf_get_pdf_version(qpdf_data qpdf) 367 char const* qpdf_get_pdf_version(qpdf_data qpdf)
360 { 368 {
361 QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_version"); 369 QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_version");
qpdf/qpdf-ctest.c
@@ -1242,6 +1242,19 @@ static void test40(char const* infile, @@ -1242,6 +1242,19 @@ static void test40(char const* infile,
1242 report_errors(); 1242 report_errors();
1243 } 1243 }
1244 1244
  1245 +static void test41(char const* infile,
  1246 + char const* password,
  1247 + char const* outfile,
  1248 + char const* xarg)
  1249 +{
  1250 + /* Empty PDF -- infile is ignored*/
  1251 + assert(qpdf_empty_pdf(qpdf) == 0);
  1252 + qpdf_init_write(qpdf, outfile);
  1253 + qpdf_set_static_ID(qpdf, QPDF_TRUE);
  1254 + qpdf_write(qpdf);
  1255 + report_errors();
  1256 +}
  1257 +
1245 int main(int argc, char* argv[]) 1258 int main(int argc, char* argv[])
1246 { 1259 {
1247 char* p = 0; 1260 char* p = 0;
@@ -1322,6 +1335,7 @@ int main(int argc, char* argv[]) @@ -1322,6 +1335,7 @@ int main(int argc, char* argv[])
1322 (n == 38) ? test38 : 1335 (n == 38) ? test38 :
1323 (n == 39) ? test39 : 1336 (n == 39) ? test39 :
1324 (n == 40) ? test40 : 1337 (n == 40) ? test40 :
  1338 + (n == 41) ? test41 :
1325 0); 1339 0);
1326 1340
1327 if (fn == 0) 1341 if (fn == 0)
qpdf/qpdf.testcov
@@ -639,3 +639,4 @@ QPDFJob json encrypt no key length 0 @@ -639,3 +639,4 @@ QPDFJob json encrypt no key length 0
639 QPDFJob json encrypt duplicate key length 0 639 QPDFJob json encrypt duplicate key length 0
640 QPDFJob json encrypt missing password 0 640 QPDFJob json encrypt missing password 0
641 QPDFJob json pages no file 0 641 QPDFJob json pages no file 0
  642 +qpdf-c called qpdf_empty_pdf 0
qpdf/qtest/qpdf.test
@@ -3553,7 +3553,7 @@ my @capi = ( @@ -3553,7 +3553,7 @@ my @capi = (
3553 [8, 'no original object ids'], 3553 [8, 'no original object ids'],
3554 [9, 'uncompressed streams'], 3554 [9, 'uncompressed streams'],
3555 ); 3555 );
3556 -$n_tests += (2 * @capi) + 3; 3556 +$n_tests += (2 * @capi) + 5;
3557 foreach my $d (@capi) 3557 foreach my $d (@capi)
3558 { 3558 {
3559 my ($n, $description) = @$d; 3559 my ($n, $description) = @$d;
@@ -3590,6 +3590,14 @@ $td-&gt;runtest(&quot;write damaged&quot;, @@ -3590,6 +3590,14 @@ $td-&gt;runtest(&quot;write damaged&quot;,
3590 $td->EXIT_STATUS => 0}, 3590 $td->EXIT_STATUS => 0},
3591 $td->NORMALIZE_NEWLINES); 3591 $td->NORMALIZE_NEWLINES);
3592 3592
  3593 +$td->runtest("empty PDF",
  3594 + {$td->COMMAND => "qpdf-ctest 41 - '' a.pdf"},
  3595 + {$td->STRING => "C test 41 done\n", $td->EXIT_STATUS => 0},
  3596 + $td->NORMALIZE_NEWLINES);
  3597 +$td->runtest("check output",
  3598 + {$td->FILE => "a.pdf"},
  3599 + {$td->FILE => "c-empty.pdf"});
  3600 +
3593 show_ntests(); 3601 show_ntests();
3594 # ---------- 3602 # ----------
3595 $td->notify("--- Deterministic ID Tests ---"); 3603 $td->notify("--- Deterministic ID Tests ---");
qpdf/qtest/qpdf/c-empty.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /Pages 2 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /Count 0 /Kids [ ] /Type /Pages >>
  8 +endobj
  9 +xref
  10 +0 3
  11 +0000000000 65535 f
  12 +0000000015 00000 n
  13 +0000000064 00000 n
  14 +trailer << /Root 1 0 R /Size 3 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
  15 +startxref
  16 +117
  17 +%%EOF