glib: Add poppler_document_new_from_bytes

This allows creating a PopplerDocument from data stored in a
GBytes.

This is better than poppler_document_new_from_data() since the
document will keep a reference to the data, instead of having
to make sure manually that the data stays around as long as the
document exists. Also poppler_document_new_from_data() is buggy
in that it uses int for the data size instead of gsize.

https://gitlab.freedesktop.org/poppler/poppler/issues/771
diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc
index 6b424aa..843be83 100644
--- a/glib/poppler-document.cc
+++ b/glib/poppler-document.cc
@@ -24,6 +24,8 @@
 #include <string.h>
 
 #ifndef __GI_SCANNER__
+#include <memory>
+
 #include <splash/SplashBitmap.h>
 #include <DateInfo.h>
 #include <GlobalParams.h>
@@ -234,6 +236,9 @@
  * Creates a new #PopplerDocument.  If %NULL is returned, then @error will be
  * set. Possible errors include those in the #POPPLER_ERROR and #G_FILE_ERROR
  * domains.
+ *
+ * Note that @data must remain valid for as long as the returned document exists.
+ * Prefer using poppler_document_new_from_bytes().
  * 
  * Return value: A newly created #PopplerDocument, or %NULL
  **/
@@ -261,6 +266,60 @@
   return _poppler_document_new_from_pdfdoc (newDoc, error);
 }
 
+class BytesStream : public MemStream
+{
+  std::unique_ptr<GBytes, decltype(&g_bytes_unref)> m_bytes;
+
+public:
+  BytesStream(GBytes *bytes, Object &&dictA)
+    : MemStream(static_cast<const char*>(g_bytes_get_data(bytes, nullptr)),
+		0, g_bytes_get_size(bytes), std::move(dictA)),
+      m_bytes{g_bytes_ref(bytes), &g_bytes_unref}
+  { }
+};
+
+/**
+ * poppler_document_new_from_bytes:
+ * @bytes: a #GBytes
+ * @password: (allow-none): password to unlock the file with, or %NULL
+ * @error: (allow-none): Return location for an error, or %NULL
+ *
+ * Creates a new #PopplerDocument from @bytes. The returned document
+ * will hold a reference to @bytes.
+ *
+ * On error,  %NULL is returned, with @error set. Possible errors include
+ * those in the #POPPLER_ERROR and #G_FILE_ERROR domains.
+ *
+ * Return value: (transfer full): a newly created #PopplerDocument, or %NULL
+ *
+ * Since: 0.82
+ **/
+PopplerDocument *
+poppler_document_new_from_bytes (GBytes      *bytes,
+				 const char  *password,
+				 GError     **error)
+{
+  PDFDoc *newDoc;
+  BytesStream *str;
+  GooString *password_g;
+
+  g_return_val_if_fail(bytes != nullptr, nullptr);
+  g_return_val_if_fail(error == nullptr || *error == nullptr, nullptr);
+
+  if (!globalParams) {
+    globalParams = new GlobalParams();
+  }
+
+  // create stream
+  str = new BytesStream(bytes, Object(objNull));
+
+  password_g = poppler_password_to_latin1(password);
+  newDoc = new PDFDoc(str, password_g, password_g);
+  delete password_g;
+
+  return _poppler_document_new_from_pdfdoc (newDoc, error);
+}
+
 static inline gboolean
 stream_is_memory_buffer_or_local_file (GInputStream *stream)
 {
diff --git a/glib/poppler-document.h b/glib/poppler-document.h
index 9d8b705..98dae9a 100644
--- a/glib/poppler-document.h
+++ b/glib/poppler-document.h
@@ -298,6 +298,10 @@
 							    const char      *password,
 							    GError         **error);
 POPPLER_PUBLIC
+PopplerDocument   *poppler_document_new_from_bytes         (GBytes          *bytes,
+							    const char      *password,
+							    GError         **error);
+POPPLER_PUBLIC
 PopplerDocument   *poppler_document_new_from_stream        (GInputStream    *stream,
                                                             goffset          length,
                                                             const char      *password,
diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt
index 66c57f2..75bf3b0 100644
--- a/glib/reference/poppler-sections.txt
+++ b/glib/reference/poppler-sections.txt
@@ -184,6 +184,7 @@
 poppler_document_get_title
 poppler_document_has_attachments
 poppler_document_is_linearized
+poppler_document_new_from_bytes
 poppler_document_new_from_data
 poppler_document_new_from_file
 poppler_document_new_from_gfile