Commit fee7489ee4c90c6dbd11e57ecc8e888c8f038716

Authored by Jay Berkenbilt
1 parent 8c4ad6b9

Add Pl_Buffer::getMallocBuffer

ChangeLog
  1 +2021-12-17 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Add Pl_Buffer::getMallocBuffer() to initialize a buffer with
  4 + malloc in support of the C API
  5 +
1 2021-12-16 Jay Berkenbilt <ejb@ql.org> 6 2021-12-16 Jay Berkenbilt <ejb@ql.org>
2 7
3 * Add several functions to the C API for working with pages. C 8 * Add several functions to the C API for working with pages. C
include/qpdf/Pl_Buffer.hh
@@ -55,6 +55,15 @@ class Pl_Buffer: public Pipeline @@ -55,6 +55,15 @@ class Pl_Buffer: public Pipeline
55 QPDF_DLL 55 QPDF_DLL
56 Buffer* getBuffer(); 56 Buffer* getBuffer();
57 57
  58 + // getMallocBuffer behaves in the same was as getBuffer except the
  59 + // buffer is allocated with malloc(), making it suitable for use
  60 + // when calling from other languages. If there is no data, *buf is
  61 + // set to a null pointer and *len is set to 0. Otherwise, *buf is
  62 + // a buffer of size *len allocated with malloc(). It is the
  63 + // caller's responsibility to call free() on the buffer.
  64 + QPDF_DLL
  65 + void getMallocBuffer(unsigned char **buf, size_t* len);
  66 +
58 private: 67 private:
59 class Members 68 class Members
60 { 69 {
libqpdf/Pl_Buffer.cc
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 #include <algorithm> 3 #include <algorithm>
4 #include <assert.h> 4 #include <assert.h>
5 #include <string.h> 5 #include <string.h>
  6 +#include <stdlib.h>
6 7
7 Pl_Buffer::Members::Members() : 8 Pl_Buffer::Members::Members() :
8 ready(true), 9 ready(true),
@@ -80,3 +81,25 @@ Pl_Buffer::getBuffer() @@ -80,3 +81,25 @@ Pl_Buffer::getBuffer()
80 this->m = new Members(); 81 this->m = new Members();
81 return b; 82 return b;
82 } 83 }
  84 +
  85 +void
  86 +Pl_Buffer::getMallocBuffer(unsigned char **buf, size_t* len)
  87 +{
  88 + if (! this->m->ready)
  89 + {
  90 + throw std::logic_error(
  91 + "Pl_Buffer::getMallocBuffer() called when not ready");
  92 + }
  93 +
  94 + *len = this->m->total_size;
  95 + if (this->m->total_size > 0)
  96 + {
  97 + *buf = reinterpret_cast<unsigned char*>(malloc(this->m->total_size));
  98 + memcpy(*buf, this->m->data->getBuffer(), this->m->total_size);
  99 + }
  100 + else
  101 + {
  102 + *buf = nullptr;
  103 + }
  104 + this->m = new Members();
  105 +}
libtests/buffer.cc
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 #include <stdexcept> 6 #include <stdexcept>
7 #include <iostream> 7 #include <iostream>
8 #include <cassert> 8 #include <cassert>
  9 +#include <cstring>
9 10
10 static unsigned char* uc(char const* s) 11 static unsigned char* uc(char const* s)
11 { 12 {
@@ -98,6 +99,31 @@ int main() @@ -98,6 +99,31 @@ int main()
98 b = bp3.getBuffer(); 99 b = bp3.getBuffer();
99 std::cout << "size: " << b->getSize() << std::endl; 100 std::cout << "size: " << b->getSize() << std::endl;
100 delete b; 101 delete b;
  102 +
  103 + // Malloc buffer should behave similarly.
  104 + Pl_Buffer bp4("bp4");
  105 + bp4.write(uc("asdf"), 4);
  106 + unsigned char* mbuf;
  107 + size_t len;
  108 + try
  109 + {
  110 + bp4.getMallocBuffer(&mbuf, &len);
  111 + assert(false);
  112 + }
  113 + catch (std::logic_error& e)
  114 + {
  115 + std::cout << "malloc buffer logic error: " << e.what() << std::endl;
  116 + }
  117 + bp4.finish();
  118 + bp4.getMallocBuffer(&mbuf, &len);
  119 + assert(len == 4);
  120 + assert(memcmp(mbuf, uc("asdf"), 4) == 0);
  121 + free(mbuf);
  122 + bp4.write(uc(""), 0);
  123 + bp4.finish();
  124 + bp4.getMallocBuffer(&mbuf, &len);
  125 + assert(mbuf == nullptr);
  126 + assert(len == 0);
101 } 127 }
102 catch (std::exception& e) 128 catch (std::exception& e)
103 { 129 {
libtests/qtest/buffer/buffer.out
@@ -11,4 +11,5 @@ data: mooquack @@ -11,4 +11,5 @@ data: mooquack
11 size: 0 11 size: 0
12 size: 0 12 size: 0
13 size: 0 13 size: 0
  14 +malloc buffer logic error: Pl_Buffer::getMallocBuffer() called when not ready
14 done 15 done
manual/index.rst
@@ -3622,10 +3622,14 @@ For a detailed list of changes, please see the file @@ -3622,10 +3622,14 @@ For a detailed list of changes, please see the file
3622 object is not of the expected type. These warnings now have an 3622 object is not of the expected type. These warnings now have an
3623 error code of ``qpdf_e_object`` instead of 3623 error code of ``qpdf_e_object`` instead of
3624 ``qpdf_e_damaged_pdf``. Also, comments have been added to 3624 ``qpdf_e_damaged_pdf``. Also, comments have been added to
3625 - :file:`QPDFObjectHandle.hh` to explain in  
3626 - more detail what the behavior is. See :ref:`ref.object-accessors` for a more in-depth 3625 + :file:`QPDFObjectHandle.hh` to explain in more detail what the
  3626 + behavior is. See :ref:`ref.object-accessors` for a more in-depth
3627 discussion. 3627 discussion.
3628 3628
  3629 + - Add ``Pl_Buffer::getMallocBuffer()`` to initialize a buffer
  3630 + allocated with ``malloc()`` for better cross-language
  3631 + interoperability.
  3632 +
3629 - C API Enhancements 3633 - C API Enhancements
3630 3634
3631 - Overhaul error handling for the object handle functions 3635 - Overhaul error handling for the object handle functions