[glibmm] Add tests/giomm_stream_vfuncs



commit 4aff300e67f0ec088297e6301d9fa2313acee565
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Mon Nov 21 16:27:27 2016 +0100

    Add tests/giomm_stream_vfuncs
    
    * tests/Makefile.am: Add giomm_stream_vfuncs.
    * tests/giomm_stream_vfuncs/main.cc: New file.
    An updated version of a patch by Krzysztof KosiƄski <tweenk pl gmail com>
    Bug #572471

 tests/Makefile.am                 |    4 +
 tests/giomm_stream_vfuncs/main.cc |  170 +++++++++++++++++++++++++++++++++++++
 2 files changed, 174 insertions(+), 0 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0db1869..bbe85ae 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,6 +22,7 @@ check_PROGRAMS =                              \
        giomm_ioerror_and_iodbuserror/test      \
        giomm_memoryinputstream/test                    \
        giomm_simple/test                       \
+  giomm_stream_vfuncs/test \
        giomm_asyncresult_sourceobject/test     \
        giomm_tls_client/test                   \
        giomm_listmodel/test \
@@ -78,6 +79,9 @@ giomm_memoryinputstream_test_LDADD   = $(giomm_ldadd)
 giomm_simple_test_SOURCES  = giomm_simple/main.cc
 giomm_simple_test_LDADD    = $(giomm_ldadd)
 
+giomm_stream_vfuncs_test_SOURCES = giomm_stream_vfuncs/main.cc
+giomm_stream_vfuncs_test_LDADD   = $(giomm_ldadd)
+
 giomm_asyncresult_sourceobject_test_SOURCES  = giomm_asyncresult_sourceobject/main.cc
 giomm_asyncresult_sourceobject_test_LDADD    = $(giomm_ldadd)
 
diff --git a/tests/giomm_stream_vfuncs/main.cc b/tests/giomm_stream_vfuncs/main.cc
new file mode 100644
index 0000000..f70a1fa
--- /dev/null
+++ b/tests/giomm_stream_vfuncs/main.cc
@@ -0,0 +1,170 @@
+/* Copyright (C) 2016 The giomm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <giomm.h>
+#include <iostream>
+#include <string>
+#include <cstdlib>
+
+// A simple custom stream that base64 encodes data.
+// Do not copy it to your code, because it's very slow.
+class Base64OutputStream : public Gio::FilterOutputStream
+{
+public:
+  unsigned get_column_width() const { return column_width; }
+  void set_column_width(unsigned cw) { column_width = cw; }
+  static Glib::RefPtr<Base64OutputStream> create(const Glib::RefPtr<OutputStream>& base_stream)
+  {
+    return Glib::RefPtr<Base64OutputStream>(new Base64OutputStream(base_stream));
+  }
+
+protected:
+  Base64OutputStream(const Glib::RefPtr<Gio::OutputStream>& base_stream)
+    : Gio::FilterOutputStream(base_stream), column(0), bit_count(0), bit_buffer(0), column_width(72) {}
+
+  gssize write_vfunc(const void* buffer, gsize count, const Glib::RefPtr<Gio::Cancellable>& cancellable) 
override
+  {
+    char const *byte = (char const *) buffer;
+    for (unsigned i = 0; i < count; ++i, ++byte)
+    {
+      // kindergarten implementation, because the object is not performance :)
+      bit_buffer <<= 8;
+      bit_buffer |= (*byte & 0xff);
+      bit_count += 8;
+
+      if (bit_count == 24)
+      {
+        clear_pending(); // TODO why is this necessary to avoid an outstanding op. exception?
+        flush(cancellable);
+        set_pending();
+        bit_count = 0;
+      }
+
+      if (cancellable && cancellable->is_cancelled())
+        throw Gio::Error(Gio::Error::CANCELLED, "Operation cancelled");
+    }
+    return count;
+  }
+
+  bool flush_vfunc(const Glib::RefPtr<Gio::Cancellable>& cancellable) override
+  {
+    if (bit_count != 24)
+      return true;
+    char to_write[5];
+    gsize len = 4;
+
+    for (unsigned i=0; i<4; ++i)
+    {
+      unsigned index = (bit_buffer & (0x3f<<(i*6))) >> (i*6);
+      to_write[3-i] = base64_encode_str[index];
+    }
+    column += 4;
+    // Yes, I know this is completely wrong.
+    if (column >= column_width)
+    {
+      column = 0;
+      to_write[4] = '\n';
+      ++len;
+    }
+
+    get_base_stream()->write(&to_write, len, cancellable);
+
+    bit_count = 0;
+    bit_buffer = 0;
+
+    return true;
+  }
+
+  bool close_vfunc(const Glib::RefPtr<Gio::Cancellable>& cancellable) override
+  {
+    char to_write[5] = "====";
+    //get any last bytes (1 or 2) out of the buffer
+    switch (bit_count)
+    {
+    case 16:
+      bit_buffer <<= 2;  //pad to make 18 bits
+      to_write[0] = base64_encode_str[(bit_buffer & (0x3f << 12)) >> 12];
+      to_write[1] = base64_encode_str[(bit_buffer & (0x3f << 6)) >> 6];
+      to_write[2] = base64_encode_str[bit_buffer & 0x3f];
+      break;
+
+    case 8:
+      bit_buffer <<= 4; //pad to make 12 bits
+      to_write[0] = base64_encode_str[(bit_buffer & (0x3f << 6)) >> 6];
+      to_write[1] = base64_encode_str[bit_buffer & 0x3f];
+      break;
+    }
+
+    if (bit_count > 0)
+    {
+      get_base_stream()->write(&to_write, 5, cancellable);
+    }
+    else
+    {
+      // null terminate output
+      get_base_stream()->write("", 1, cancellable);
+    }
+    if (get_close_base_stream())
+      get_base_stream()->close(cancellable);
+
+    return true;
+  }
+
+private:
+  static char const *const base64_encode_str;
+  unsigned column;
+  unsigned bit_count;
+  unsigned bit_buffer;
+  unsigned column_width;
+};
+
+char const *const Base64OutputStream::base64_encode_str = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+int main(int, char**)
+{
+  Glib::init();
+  Gio::init();
+
+  try
+  {
+    char result[256];
+    Glib::RefPtr<Gio::MemoryOutputStream> memory_chunk = Gio::MemoryOutputStream::create(result, 256, 
nullptr, nullptr);
+    Glib::RefPtr<Base64OutputStream> base64 = Base64OutputStream::create(memory_chunk);
+
+    std::string data = "Custom GIO streams are cool!";
+
+    base64->set_close_base_stream(true);
+    base64->write(data);
+    base64->close();
+
+    const std::string base64_should_be("Q3VzdG9tIEdJTyBzdHJlYW1zIGFyZSBjb29sIQ==");
+    std::cout << "Original data:       " << data << std::endl;
+    std::cout << "base64-encoded data: " << result << std::endl;
+    std::cout << "base64 should be:    " << base64_should_be << std::endl;
+    if (base64_should_be != result)
+    {
+      std::cout << "Not correct!" << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+  catch (Gio::Error e)
+  {
+    std::cout << "Gio error: " << e.what() << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  return EXIT_SUCCESS;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]