aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-12-17 13:33:42 +0100
committerJay Berkenbilt <ejb@ql.org>2021-12-17 18:38:52 +0100
commitfee7489ee4c90c6dbd11e57ecc8e888c8f038716 (patch)
tree9a1872d7e52b2db3ec2cb44109a3a3918927621d
parent8c4ad6b946a762fd57443a3647e0cc620ad6eae4 (diff)
downloadqpdf-fee7489ee4c90c6dbd11e57ecc8e888c8f038716.tar.zst
Add Pl_Buffer::getMallocBuffer
-rw-r--r--ChangeLog5
-rw-r--r--include/qpdf/Pl_Buffer.hh9
-rw-r--r--libqpdf/Pl_Buffer.cc23
-rw-r--r--libtests/buffer.cc26
-rw-r--r--libtests/qtest/buffer/buffer.out1
-rw-r--r--manual/index.rst8
6 files changed, 70 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 16cfd204..60e3c0c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2021-12-17 Jay Berkenbilt <ejb@ql.org>
+
+ * Add Pl_Buffer::getMallocBuffer() to initialize a buffer with
+ malloc in support of the C API
+
2021-12-16 Jay Berkenbilt <ejb@ql.org>
* Add several functions to the C API for working with pages. C
diff --git a/include/qpdf/Pl_Buffer.hh b/include/qpdf/Pl_Buffer.hh
index 07bc2372..8c402cd4 100644
--- a/include/qpdf/Pl_Buffer.hh
+++ b/include/qpdf/Pl_Buffer.hh
@@ -55,6 +55,15 @@ class Pl_Buffer: public Pipeline
QPDF_DLL
Buffer* getBuffer();
+ // getMallocBuffer behaves in the same was as getBuffer except the
+ // buffer is allocated with malloc(), making it suitable for use
+ // when calling from other languages. If there is no data, *buf is
+ // set to a null pointer and *len is set to 0. Otherwise, *buf is
+ // a buffer of size *len allocated with malloc(). It is the
+ // caller's responsibility to call free() on the buffer.
+ QPDF_DLL
+ void getMallocBuffer(unsigned char **buf, size_t* len);
+
private:
class Members
{
diff --git a/libqpdf/Pl_Buffer.cc b/libqpdf/Pl_Buffer.cc
index 70d906ea..0743de75 100644
--- a/libqpdf/Pl_Buffer.cc
+++ b/libqpdf/Pl_Buffer.cc
@@ -3,6 +3,7 @@
#include <algorithm>
#include <assert.h>
#include <string.h>
+#include <stdlib.h>
Pl_Buffer::Members::Members() :
ready(true),
@@ -80,3 +81,25 @@ Pl_Buffer::getBuffer()
this->m = new Members();
return b;
}
+
+void
+Pl_Buffer::getMallocBuffer(unsigned char **buf, size_t* len)
+{
+ if (! this->m->ready)
+ {
+ throw std::logic_error(
+ "Pl_Buffer::getMallocBuffer() called when not ready");
+ }
+
+ *len = this->m->total_size;
+ if (this->m->total_size > 0)
+ {
+ *buf = reinterpret_cast<unsigned char*>(malloc(this->m->total_size));
+ memcpy(*buf, this->m->data->getBuffer(), this->m->total_size);
+ }
+ else
+ {
+ *buf = nullptr;
+ }
+ this->m = new Members();
+}
diff --git a/libtests/buffer.cc b/libtests/buffer.cc
index bd28746f..23d82e7b 100644
--- a/libtests/buffer.cc
+++ b/libtests/buffer.cc
@@ -6,6 +6,7 @@
#include <stdexcept>
#include <iostream>
#include <cassert>
+#include <cstring>
static unsigned char* uc(char const* s)
{
@@ -98,6 +99,31 @@ int main()
b = bp3.getBuffer();
std::cout << "size: " << b->getSize() << std::endl;
delete b;
+
+ // Malloc buffer should behave similarly.
+ Pl_Buffer bp4("bp4");
+ bp4.write(uc("asdf"), 4);
+ unsigned char* mbuf;
+ size_t len;
+ try
+ {
+ bp4.getMallocBuffer(&mbuf, &len);
+ assert(false);
+ }
+ catch (std::logic_error& e)
+ {
+ std::cout << "malloc buffer logic error: " << e.what() << std::endl;
+ }
+ bp4.finish();
+ bp4.getMallocBuffer(&mbuf, &len);
+ assert(len == 4);
+ assert(memcmp(mbuf, uc("asdf"), 4) == 0);
+ free(mbuf);
+ bp4.write(uc(""), 0);
+ bp4.finish();
+ bp4.getMallocBuffer(&mbuf, &len);
+ assert(mbuf == nullptr);
+ assert(len == 0);
}
catch (std::exception& e)
{
diff --git a/libtests/qtest/buffer/buffer.out b/libtests/qtest/buffer/buffer.out
index e1e404b1..4143e58f 100644
--- a/libtests/qtest/buffer/buffer.out
+++ b/libtests/qtest/buffer/buffer.out
@@ -11,4 +11,5 @@ data: mooquack
size: 0
size: 0
size: 0
+malloc buffer logic error: Pl_Buffer::getMallocBuffer() called when not ready
done
diff --git a/manual/index.rst b/manual/index.rst
index 155d64b0..a77fae29 100644
--- a/manual/index.rst
+++ b/manual/index.rst
@@ -3622,10 +3622,14 @@ For a detailed list of changes, please see the file
object is not of the expected type. These warnings now have an
error code of ``qpdf_e_object`` instead of
``qpdf_e_damaged_pdf``. Also, comments have been added to
- :file:`QPDFObjectHandle.hh` to explain in
- more detail what the behavior is. See :ref:`ref.object-accessors` for a more in-depth
+ :file:`QPDFObjectHandle.hh` to explain in more detail what the
+ behavior is. See :ref:`ref.object-accessors` for a more in-depth
discussion.
+ - Add ``Pl_Buffer::getMallocBuffer()`` to initialize a buffer
+ allocated with ``malloc()`` for better cross-language
+ interoperability.
+
- C API Enhancements
- Overhaul error handling for the object handle functions