first working version of tmpfstream. Still in need of some polishing
authorGerd von Egidy <gerd.von.egidy@intra2net.com>
Tue, 9 Mar 2010 17:43:18 +0000 (18:43 +0100)
committerGerd von Egidy <gerd.von.egidy@intra2net.com>
Tue, 9 Mar 2010 17:44:40 +0000 (18:44 +0100)
configure.in
libi2ncommon.pc.in
m4/ax_boost_iostreams.m4 [new file with mode: 0644]
src/Makefile.am
src/tmpfstream.cpp [new file with mode: 0644]
src/tmpfstream.hpp [new file with mode: 0644]
test/Makefile.am
test/test_tmpfstream.cpp [new file with mode: 0644]

index 2a58ac2..a1f20c4 100644 (file)
@@ -45,6 +45,7 @@ AM_CONDITIONAL(HAVE_DOXYGEN, test -n $DOXYGEN)
 
 AX_BOOST_BASE([1.34])
 AX_BOOST_UNIT_TEST_FRAMEWORK
+AX_BOOST_IOSTREAMS
 
 AC_OUTPUT(Doxyfile Makefile doc/Makefile doc/Doxyfile configlib/Makefile xmllib/Makefile utils/Makefile src/Makefile \
        test/Makefile libi2ncommon.pc libi2ncommon_config.pc libi2ncommon_xml.pc libi2ncommon_utils.pc)
index 76dc3f8..10fc0b8 100644 (file)
@@ -7,5 +7,5 @@ Name: libi2ncommon
 Description: library with functions common in Intra2net programs
 Requires: libgettext libi2ncommon_utils
 Version: @VERSION@
-Libs: -L${libdir} -li2ncommon -li2ncommon_utils
-Cflags: -I${includedir}
+Libs: -L${libdir} -li2ncommon -li2ncommon_utils  @BOOST_LDFLAGS@ @BOOST_IOSTREAMS_LIB@
+Cflags: -I${includedir} @BOOST_CPPFLAGS@
diff --git a/m4/ax_boost_iostreams.m4 b/m4/ax_boost_iostreams.m4
new file mode 100644 (file)
index 0000000..d8969e9
--- /dev/null
@@ -0,0 +1,113 @@
+# ===========================================================================
+#    http://www.gnu.org/software/autoconf-archive/ax_boost_iostreams.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_BOOST_IOSTREAMS
+#
+# DESCRIPTION
+#
+#   Test for IOStreams library from the Boost C++ libraries. The macro
+#   requires a preceding call to AX_BOOST_BASE. Further documentation is
+#   available at <http://randspringer.de/boost/index.html>.
+#
+#   This macro calls:
+#
+#     AC_SUBST(BOOST_IOSTREAMS_LIB)
+#
+#   And sets:
+#
+#     HAVE_BOOST_IOSTREAMS
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 11
+
+AC_DEFUN([AX_BOOST_IOSTREAMS],
+[
+       AC_ARG_WITH([boost-iostreams],
+       AS_HELP_STRING([--with-boost-iostreams@<:@=special-lib@:>@],
+                   [use the IOStreams library from boost - it is possible to specify a certain library for the linker
+                        e.g. --with-boost-iostreams=boost_iostreams-gcc-mt-d-1_33_1 ]),
+        [
+        if test "$withval" = "no"; then
+                       want_boost="no"
+        elif test "$withval" = "yes"; then
+            want_boost="yes"
+            ax_boost_user_iostreams_lib=""
+        else
+                   want_boost="yes"
+               ax_boost_user_iostreams_lib="$withval"
+               fi
+        ],
+        [want_boost="yes"]
+       )
+
+       if test "x$want_boost" = "xyes"; then
+        AC_REQUIRE([AC_PROG_CC])
+               CPPFLAGS_SAVED="$CPPFLAGS"
+               CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
+               export CPPFLAGS
+
+               LDFLAGS_SAVED="$LDFLAGS"
+               LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
+               export LDFLAGS
+
+        AC_CACHE_CHECK(whether the Boost::IOStreams library is available,
+                                          ax_cv_boost_iostreams,
+        [AC_LANG_PUSH([C++])
+                AC_COMPILE_IFELSE(AC_LANG_PROGRAM([[@%:@include <boost/iostreams/filtering_stream.hpp>
+                                                                                        @%:@include <boost/range/iterator_range.hpp>
+                                                                                       ]],
+                                  [[std::string  input = "Hello World!";
+                                                                        namespace io = boost::iostreams;
+                                                                        io::filtering_istream  in(boost::make_iterator_range(input));
+                                                                        return 0;
+                                   ]]),
+                             ax_cv_boost_iostreams=yes, ax_cv_boost_iostreams=no)
+         AC_LANG_POP([C++])
+               ])
+               if test "x$ax_cv_boost_iostreams" = "xyes"; then
+                       AC_DEFINE(HAVE_BOOST_IOSTREAMS,,[define if the Boost::IOStreams library is available])
+            BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
+            if test "x$ax_boost_user_iostreams_lib" = "x"; then
+                for libextension in `ls $BOOSTLIBDIR/libboost_iostreams*.{so,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_iostreams.*\)\.so.*$;\1;' -e 's;^lib\(boost_iostreams.*\)\.a*$;\1;'` ; do
+                     ax_lib=${libextension}
+                                   AC_CHECK_LIB($ax_lib, exit,
+                                 [BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break],
+                                 [link_iostreams="no"])
+                               done
+                if test "x$link_iostreams" != "xyes"; then
+                for libextension in `ls $BOOSTLIBDIR/boost_iostreams*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_iostreams.*\)\.dll.*$;\1;' -e 's;^\(boost_iostreams.*\)\.a*$;\1;'` ; do
+                     ax_lib=${libextension}
+                                   AC_CHECK_LIB($ax_lib, exit,
+                                 [BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break],
+                                 [link_iostreams="no"])
+                               done
+                fi
+
+            else
+               for ax_lib in $ax_boost_user_iostreams_lib boost_iostreams-$ax_boost_user_iostreams_lib; do
+                                     AC_CHECK_LIB($ax_lib, main,
+                                   [BOOST_IOSTREAMS_LIB="-l$ax_lib"; AC_SUBST(BOOST_IOSTREAMS_LIB) link_iostreams="yes"; break],
+                                   [link_iostreams="no"])
+                  done
+
+            fi
+                       if test "x$link_iostreams" != "xyes"; then
+                               AC_MSG_ERROR(Could not link against $ax_lib !)
+                       fi
+               fi
+
+               CPPFLAGS="$CPPFLAGS_SAVED"
+       LDFLAGS="$LDFLAGS_SAVED"
+       fi
+])
index c71d02c..a0c54a7 100644 (file)
@@ -10,10 +10,10 @@ include_HEADERS = week.hpp cron.hpp daemonfunc.hpp filefunc.hxx \
        pointer_func.hpp source_track_basics.hpp stringfunc.hxx timefunc.hxx \
        tracefunc.hpp userfunc.hpp exception.hxx
        
-libi2ncommon_la_SOURCES = week.cpp cron.cpp daemonfunc.cpp \
-       filefunc.cpp i2n_configfile.cpp ipfunc.cpp logfunc.cpp logread.cpp oftmpstream.cpp \
-       pidfile.cpp pointer_func.cpp source_track_basics.cpp stringfunc.cpp \
-       timefunc.cpp tracefunc.cpp userfunc.cpp
+libi2ncommon_la_SOURCES = cron.cpp daemonfunc.cpp filefunc.cpp \
+       i2n_configfile.cpp ipfunc.cpp logfunc.cpp logread.cpp oftmpstream.cpp pidfile.cpp \
+       pointer_func.cpp source_track_basics.cpp stringfunc.cpp timefunc.cpp tmpfstream.cpp \
+       tracefunc.cpp userfunc.cpp week.cpp
 
 # Note:  If you specify a:b:c as the version in the next line,
 #  the library that is made has version (a-c).c.b.  In this
@@ -21,4 +21,4 @@ libi2ncommon_la_SOURCES = week.cpp cron.cpp daemonfunc.cpp \
 
 libi2ncommon_la_LDFLAGS = -version-info @LIBI2NCOMMON_LIB_VERSION@ @BOOST_LDFLAGS@
 
-libi2ncommon_la_LIBADD =  @LIBGETTEXT_LIBS@ @LIBICONV_LIBS@
+libi2ncommon_la_LIBADD =  @LIBGETTEXT_LIBS@ @LIBICONV_LIBS@ @BOOST_IOSTREAMS_LIB@
diff --git a/src/tmpfstream.cpp b/src/tmpfstream.cpp
new file mode 100644 (file)
index 0000000..e4dc459
--- /dev/null
@@ -0,0 +1,79 @@
+/** @file
+ * @brief fstream which creates files with mkstemp.
+ *
+ * @author Gerd v. Egidy
+ *
+ * @copyright &copy; Copyright 2010 by Intra2net AG
+ * @license commercial
+ *
+ * info@intra2net.com
+ *
+ */
+
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "tmpfstream.hpp"
+#include "filefunc.hxx"
+
+using namespace std;
+
+namespace I2n
+{
+/*
+template< typename Device, typename Tr, typename Alloc >
+bool tmpfstream<Device,Tr,Alloc>::open(const std::string& tmpnametemplate, 
+        std::ios_base::open_mode mode,
+        int buffer_size, int pback_size)
+{
+    if (tmpfstream<Device,Tr,Alloc>::is_open())
+        tmpfstream<Device,Tr,Alloc>::close();
+
+    char* chbuf=new char[tmpnametemplate.size()+1];
+    tmpnametemplate.copy(chbuf,tmpnametemplate.size()+1);
+    chbuf[tmpnametemplate.size()]=0;
+
+    // TODO: flags handling
+
+    int fd=mkstemp(chbuf);
+    filename=chbuf;
+    delete[] chbuf;
+
+    if (fd==-1)
+        return false;
+
+    boost::iostreams::stream<Device,Tr,Alloc>::open(Device(fd,true));
+
+    return tmpfstream<Device,Tr,Alloc>::is_open();
+}
+
+template< typename Device, typename Tr, typename Alloc >
+bool tmpfstream<Device,Tr,Alloc>::set_file_mode(int mode)
+{
+
+}
+
+template< typename Device, typename Tr, typename Alloc >
+bool tmpfstream<Device,Tr,Alloc>::unlink()
+{
+    if (!get_tmp_filename().empty())
+        unlink(get_tmp_filename());
+    else
+        return false;
+}
+template< typename Device, typename Tr, typename Alloc >
+bool tmpfstream<Device,Tr,Alloc>::move_to(const std::string& targetpath, bool overwrite)
+{
+
+}
+*/
+
+
+}
diff --git a/src/tmpfstream.hpp b/src/tmpfstream.hpp
new file mode 100644 (file)
index 0000000..961e4ae
--- /dev/null
@@ -0,0 +1,99 @@
+/** @file
+ * @brief fstream which creates files with mkstemp.
+ *
+ * @author Gerd v. Egidy
+ *
+ * @copyright &copy; Copyright 2010 by Intra2net AG
+ * @license commercial
+ *
+ * info@intra2net.com
+ *
+ */
+
+#ifndef __I2N_TMPFSTREAM_HPP__
+#define __I2N_TMPFSTREAM_HPP__
+
+#include <string>
+
+#include <boost/iostreams/detail/char_traits.hpp>
+#include <boost/config.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+
+#include "filefunc.hxx"
+
+
+namespace I2n
+{
+
+template< typename Device,
+          typename Tr =
+              BOOST_IOSTREAMS_CHAR_TRAITS(
+                  BOOST_DEDUCED_TYPENAME  boost::iostreams::char_type_of<Device>::type
+              ),
+          typename Alloc =
+              std::allocator<
+                  BOOST_DEDUCED_TYPENAME  boost::iostreams::char_type_of<Device>::type
+              > >
+class tmpfstream : public boost::iostreams::stream<Device, Tr, Alloc>
+{
+private:
+    std::string filename;
+
+public:
+    tmpfstream()
+        : boost::iostreams::stream<Device, Tr, Alloc>()
+        { }
+
+    tmpfstream(const std::string& tmpnametemplate, 
+               std::ios_base::open_mode mode = std::ios_base::out,
+               int buffer_size = -1 , int pback_size = -1)
+        : boost::iostreams::stream<Device, Tr, Alloc>()
+    {
+        open(tmpnametemplate,mode,buffer_size,pback_size);
+    }
+
+    bool open(const std::string& tmpnametemplate, 
+               std::ios_base::open_mode mode = std::ios_base::out,
+               int buffer_size = -1 , int pback_size = -1)
+    {
+        if (tmpfstream<Device,Tr,Alloc>::is_open())
+            tmpfstream<Device,Tr,Alloc>::close();
+
+        char* chbuf=new char[tmpnametemplate.size()+1];
+        tmpnametemplate.copy(chbuf,tmpnametemplate.size()+1);
+        chbuf[tmpnametemplate.size()]=0;
+
+        // TODO: flags handling
+
+        int fd=mkstemp(chbuf);
+        filename=chbuf;
+        delete[] chbuf;
+
+        if (fd==-1)
+            return false;
+
+        boost::iostreams::stream<Device,Tr,Alloc>::open(Device(fd,true));
+
+        return tmpfstream<Device,Tr,Alloc>::is_open();
+    }
+
+    std::string get_tmp_filename()
+        { return filename; }
+
+    bool set_file_mode(int mode);
+
+    bool unlink()
+    {
+        if (!get_tmp_filename().empty())
+            return I2n::unlink(get_tmp_filename());
+        else
+            return false;
+    }
+
+    bool move_to(const std::string& targetpath, bool overwrite);
+};
+
+}
+
+#endif
index b1319ff..6cf2587 100644 (file)
@@ -3,7 +3,7 @@ METASOURCES = AUTO
 check_PROGRAMS =  test
 test_SOURCES = ip_range.cpp stringfunc.cpp test_containerfunc.cpp \
        test_cron_interval.cpp test_cron_point.cpp test_filefunc.cpp test_global_config.cpp \
-       test_logging.cpp test_pidfile.cpp test_timefunc.cpp
+       test_logging.cpp test_pidfile.cpp test_timefunc.cpp test_tmpfstream.cpp
 test_LDADD = $(top_builddir)/src/libi2ncommon.la $(top_builddir)/utils/libi2ncommon_utils.la \
        $(top_builddir)/configlib/libi2ncommon_config.la @BOOST_UNIT_TEST_FRAMEWORK_LIB@
 
diff --git a/test/test_tmpfstream.cpp b/test/test_tmpfstream.cpp
new file mode 100644 (file)
index 0000000..b29b422
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file
+ *
+ * tests for the module tmpfstream
+ *
+ * (c) Copyright 2010 by Intra2net AG
+ *
+ * info@intra2net.com
+ */
+
+//#define NOISEDEBUG
+
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+#include <filefunc.hxx>
+#include <tmpfstream.hpp>
+
+#ifdef NOISEDEBUG
+#define DOUT(msg) std::cout << msg << std::endl
+#else
+#define DOUT(msg) do {} while (0)
+#endif
+
+using namespace std;
+using namespace I2n;
+
+namespace bio = boost::iostreams;
+
+BOOST_AUTO_TEST_SUITE(TestTmpfstream)
+
+BOOST_AUTO_TEST_CASE(Tmpfstream)
+{
+    tmpfstream<bio::file_descriptor_sink> tmpf("./tmp.XXXXXX");
+
+    BOOST_CHECK_EQUAL( true, tmpf.is_open() );
+    BOOST_CHECK_EQUAL( false, tmpf.get_tmp_filename().empty() );
+
+    Stat stat(tmpf.get_tmp_filename());
+
+    DOUT("filename : " << tmpf.get_tmp_filename());
+
+    BOOST_CHECK_EQUAL( true, (bool)stat );
+    BOOST_CHECK_EQUAL( true, stat.is_regular_file() );
+
+    tmpf << "hello world" << endl;
+
+    tmpf.close();
+    BOOST_CHECK_EQUAL( false, tmpf.is_open() );
+
+    Stat stat2(tmpf.get_tmp_filename());
+
+    DOUT("stated path: " << stat2.path());
+    DOUT("filesize: " << stat2.size());
+
+    BOOST_CHECK_EQUAL( true, stat2.size() > 0 );
+
+    BOOST_CHECK_EQUAL( true, tmpf.unlink() );
+
+    Stat stat3(tmpf.get_tmp_filename());
+    BOOST_CHECK_EQUAL( false, (bool)stat3 );
+
+} 
+
+
+BOOST_AUTO_TEST_SUITE_END()