From 52d6f7fc8bf76e83b1d469f7de36259df4df87f2 Mon Sep 17 00:00:00 2001 From: Gerd von Egidy Date: Tue, 9 Mar 2010 18:43:18 +0100 Subject: [PATCH] first working version of tmpfstream. Still in need of some polishing --- configure.in | 1 + libi2ncommon.pc.in | 4 +- m4/ax_boost_iostreams.m4 | 113 ++++++++++++++++++++++++++++++++++++++++++++++ src/Makefile.am | 10 ++-- src/tmpfstream.cpp | 79 ++++++++++++++++++++++++++++++++ src/tmpfstream.hpp | 99 ++++++++++++++++++++++++++++++++++++++++ test/Makefile.am | 2 +- test/test_tmpfstream.cpp | 66 +++++++++++++++++++++++++++ 8 files changed, 366 insertions(+), 8 deletions(-) create mode 100644 m4/ax_boost_iostreams.m4 create mode 100644 src/tmpfstream.cpp create mode 100644 src/tmpfstream.hpp create mode 100644 test/test_tmpfstream.cpp diff --git a/configure.in b/configure.in index 2a58ac2..a1f20c4 100644 --- a/configure.in +++ b/configure.in @@ -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) diff --git a/libi2ncommon.pc.in b/libi2ncommon.pc.in index 76dc3f8..10fc0b8 100644 --- a/libi2ncommon.pc.in +++ b/libi2ncommon.pc.in @@ -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 index 0000000..d8969e9 --- /dev/null +++ b/m4/ax_boost_iostreams.m4 @@ -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 . +# +# This macro calls: +# +# AC_SUBST(BOOST_IOSTREAMS_LIB) +# +# And sets: +# +# HAVE_BOOST_IOSTREAMS +# +# LICENSE +# +# Copyright (c) 2008 Thomas Porschberg +# +# 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 + @%:@include + ]], + [[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 +]) diff --git a/src/Makefile.am b/src/Makefile.am index c71d02c..a0c54a7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 0000000..e4dc459 --- /dev/null +++ b/src/tmpfstream.cpp @@ -0,0 +1,79 @@ +/** @file + * @brief fstream which creates files with mkstemp. + * + * @author Gerd v. Egidy + * + * @copyright © Copyright 2010 by Intra2net AG + * @license commercial + * + * info@intra2net.com + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tmpfstream.hpp" +#include "filefunc.hxx" + +using namespace std; + +namespace I2n +{ +/* +template< typename Device, typename Tr, typename Alloc > +bool tmpfstream::open(const std::string& tmpnametemplate, + std::ios_base::open_mode mode, + int buffer_size, int pback_size) +{ + if (tmpfstream::is_open()) + tmpfstream::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::open(Device(fd,true)); + + return tmpfstream::is_open(); +} + +template< typename Device, typename Tr, typename Alloc > +bool tmpfstream::set_file_mode(int mode) +{ + +} + +template< typename Device, typename Tr, typename Alloc > +bool tmpfstream::unlink() +{ + if (!get_tmp_filename().empty()) + unlink(get_tmp_filename()); + else + return false; +} +template< typename Device, typename Tr, typename Alloc > +bool tmpfstream::move_to(const std::string& targetpath, bool overwrite) +{ + +} +*/ + + +} diff --git a/src/tmpfstream.hpp b/src/tmpfstream.hpp new file mode 100644 index 0000000..961e4ae --- /dev/null +++ b/src/tmpfstream.hpp @@ -0,0 +1,99 @@ +/** @file + * @brief fstream which creates files with mkstemp. + * + * @author Gerd v. Egidy + * + * @copyright © Copyright 2010 by Intra2net AG + * @license commercial + * + * info@intra2net.com + * + */ + +#ifndef __I2N_TMPFSTREAM_HPP__ +#define __I2N_TMPFSTREAM_HPP__ + +#include + +#include +#include +#include +#include + +#include "filefunc.hxx" + + +namespace I2n +{ + +template< typename Device, + typename Tr = + BOOST_IOSTREAMS_CHAR_TRAITS( + BOOST_DEDUCED_TYPENAME boost::iostreams::char_type_of::type + ), + typename Alloc = + std::allocator< + BOOST_DEDUCED_TYPENAME boost::iostreams::char_type_of::type + > > +class tmpfstream : public boost::iostreams::stream +{ +private: + std::string filename; + +public: + tmpfstream() + : boost::iostreams::stream() + { } + + 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() + { + 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::is_open()) + tmpfstream::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::open(Device(fd,true)); + + return tmpfstream::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 diff --git a/test/Makefile.am b/test/Makefile.am index b1319ff..6cf2587 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 index 0000000..b29b422 --- /dev/null +++ b/test/test_tmpfstream.cpp @@ -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 + +#include +#include +#include + +#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 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() -- 1.7.1