libi2ncommon: (reinhard) added containerfunc and some unit tests.
authorReinhard Pfau <reinhard.pfau@intra2net.com>
Mon, 7 Apr 2008 15:25:09 +0000 (15:25 +0000)
committerReinhard Pfau <reinhard.pfau@intra2net.com>
Mon, 7 Apr 2008 15:25:09 +0000 (15:25 +0000)
src/Makefile.am
src/containerfunc.cpp [new file with mode: 0644]
src/containerfunc.hpp [new file with mode: 0644]
src/containerfunc.hxx [new file with mode: 0644]
test/Makefile.am
test/stringfunc.cpp
test/test_containerfunc.cpp [new file with mode: 0644]

index 1ddd7c8..3dd6b92 100644 (file)
@@ -4,11 +4,16 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu
 
 # the library search path.
 lib_LTLIBRARIES = libi2ncommon.la
-include_HEADERS = userfunc.hxx daemonfunc.hxx pidfile.hxx logread.hxx insocketstream.hxx oftmpstream.hxx pipestream.hxx filefunc.hxx stringfunc.hxx timefunc.hxx ipfunc.hxx ip_type.hxx
-libi2ncommon_la_SOURCES = userfunc.cpp daemonfunc.cpp pidfile.cpp logread.cpp oftmpstream.cpp ipfunc.cpp timefunc.cpp filefunc.cpp stringfunc.cpp
+include_HEADERS = containerfunc.hpp daemonfunc.hxx filefunc.hxx \
+       insocketstream.hxx ip_type.hxx ipfunc.hxx logread.hxx oftmpstream.hxx pidfile.hxx \
+       pipestream.hxx stringfunc.hxx timefunc.hxx userfunc.hxx
+libi2ncommon_la_SOURCES = containerfunc.cpp daemonfunc.cpp filefunc.cpp \
+       ipfunc.cpp logread.cpp oftmpstream.cpp pidfile.cpp stringfunc.cpp timefunc.cpp \
+       userfunc.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
 #  example, the version is 2.1.2. (3:2:1)
 
 libi2ncommon_la_LIBADD = @LIBGETTEXT_LIBS@ @LIBICONV_LIBS@
+_SOURCES = containerfunc.hxx
diff --git a/src/containerfunc.cpp b/src/containerfunc.cpp
new file mode 100644 (file)
index 0000000..4e09116
--- /dev/null
@@ -0,0 +1,8 @@
+/** @file
+ *
+ * (c) Copyright 2007-2008 by Intra2net AG
+ * 
+ * info@intra2net.com
+ */
+
+#include "containerfunc.hpp"
diff --git a/src/containerfunc.hpp b/src/containerfunc.hpp
new file mode 100644 (file)
index 0000000..7c7b459
--- /dev/null
@@ -0,0 +1,408 @@
+/** @file
+ * @brief some helper for handling (STL) data structures.
+ *
+ * @author Reinhard Pfau \<Reinhard.Pfau@intra2net.com\>
+ *
+ * (c) Copyright 2007-2008 by Intra2net AG
+ * 
+ * info@intra2net.com
+ */
+
+#ifndef _I2N_CONTAINERFUNC_HPP_
+#define _I2N_CONTAINERFUNC_HPP_
+
+#include <map>
+#include <list>
+#include <set>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+
+namespace I2n {
+
+
+/**
+ * convenience class to insert key-value pairs into a map.
+ */
+template<typename K, typename V>
+class MapFiller
+{
+        std::map<K,V> & MapRef;
+    
+    public:
+        MapFiller( std::map<K,V> & map_ref)
+        : MapRef(map_ref)
+        {
+        }
+        
+        MapFiller& operator () (const K& key, const V& value)
+        {
+            MapRef[key]= value;
+            return *this;
+        }
+        
+}; // eo class MapFiller
+
+
+/**
+ * convenience class to fill values into a container (using push_back).
+ */
+template<typename T, template <typename> class C= std::list >
+class PushBackFiller
+{
+        C<T> &CRef;
+    public:
+        PushBackFiller( C<T> & c )
+        : CRef(c)
+        {}
+        
+        PushBackFiller& operator () (const T& value)
+        {
+            CRef.push_back(value);
+            return *this;
+        } // eo operator ()
+        
+}; // eo class PushBackFiller
+
+
+template< typename T, template <typename> class C >
+PushBackFiller< T, C > get_push_back_filler( C< T >& c)
+{
+    return PushBackFiller< T, C >(c);
+} // eo get_push_back_filler(C< T >&)
+
+
+/**
+ * convenience class for transient construction of a container including values.
+ */
+template<typename T, template<typename> class C= std::list >
+class TransientPushBackFiller
+{
+        C< T > MyC;
+    public:
+        typedef C< T > CType;
+    
+        TransientPushBackFiller()
+        {}
+        
+        TransientPushBackFiller& operator () (const T& value)
+        {
+            MyC.push_back(value);
+            return *this;
+        } // eo operator ()
+        
+        operator CType () const { return MyC; }
+}; // eo class TransientPushBackFiller
+
+
+/**
+ * convenience class for transient construction of a map including values.
+ */
+template<typename K, typename V>
+class TransientMapFiller
+{
+        std::map<K,V> Map;
+    
+    public:
+        typedef std::map< K, V > CType;
+    
+    
+        TransientMapFiller( )
+        {
+        }
+        
+        TransientMapFiller& operator () (const K& key, const V& value)
+        {
+            Map[key]= value;
+            return *this;
+        }
+        
+        operator CType () const { return Map; }
+}; // eo class MapFiller
+
+
+
+
+/**
+ * returns the keys of a map as a list.
+ * @param the_map the map.
+ * @param the_keys the list where the keys are added to.
+ * @return @a true.
+ */
+template< typename K, typename V >
+bool get_key_list( const std::map< K, V >& the_map, std::list< K >& the_keys )
+{
+    for(typename std::map< K, V >::const_iterator it= the_map.begin();
+        it != the_map.end();
+        ++it )
+    {
+        the_keys.push_back( it->first );
+    }
+    return true;
+}  // eo get_key_list(const std::map< K,V >, std::list< K >&)
+
+
+/**
+ * returns the keys of a map as a list.
+ * @param the_map the map.
+ * @return the list of keys.
+ */
+template< typename K, typename V >
+std::list< K > get_key_list( const std::map< K, V>& the_map)
+{
+    std::list< K > result;
+    get_key_list(the_map, result);
+    return result;
+} // eo get_key_list(const std::map< K,V >)
+
+
+/**
+ * returns the keys of a map as a set.
+ * @param the_map the map.
+ * @param the_keys the set where the keys are added to.
+ * @return @a true.
+ */
+template< typename K, typename V >
+bool get_key_set( const std::map< K, V >& the_map, std::set< K >& the_keys )
+{
+    for(typename std::map< K, V >::const_iterator it= the_map.begin();
+        it != the_map.end();
+        ++it )
+    {
+        the_keys.insert( it->first );
+    }
+    return true;
+}  // eo get_key_set(const std::map< K,V >, std::set< K >&)
+
+
+/**
+ * returns the keys of a map as a set.
+ * @param the_map the map.
+ * @return the set of keys.
+ */
+template< typename K, typename V >
+std::list< K > get_key_set( const std::map< K, V>& the_map)
+{
+    std::set< K > result;
+    get_key_set(the_map, result);
+    return result;
+} // eo get_key_set(const std::map< K,V >)
+
+
+/**
+ * functor version of new().
+ * can be used for deferred instantiation of objects.
+ */
+template<
+    typename T
+>
+struct New
+{
+    typedef T* result_type;
+    
+    result_type operator() () 
+    {
+        return new T;
+    }
+    
+    template<typename Arg1>
+    result_type operator() (Arg1 arg1)
+    {
+        return new T(arg1);
+    }
+    
+    template<typename Arg1, typename Arg2>
+    result_type operator() (Arg1 arg1,Arg2 arg2)
+    {
+        return new T(arg1,arg2);
+    }
+    
+    template<typename Arg1, typename Arg2, typename Arg3>
+    result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3)
+    {
+        return new T(arg1,arg2,arg3);
+    }
+    
+    template<typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+    result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4)
+    {
+        return new T(arg1,arg2,arg3,arg4);
+    }
+    
+    template<typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+    result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5)
+    {
+        return new T(arg1,arg2,arg3,arg4,arg5);
+    }
+    
+}; // eo struct New
+
+
+
+
+/**
+ * functor version of boost::shared_ptr = new().
+ * can be used for deferred instantiation of objects.
+ */
+template<
+    typename T
+>
+struct SharedPtrNew
+{
+    typedef boost::shared_ptr<T> result_type;
+    
+    result_type operator() () 
+    {
+        return result_type(new T);
+    }
+    
+    template<typename Arg1>
+    result_type operator() (Arg1 arg1)
+    {
+        return result_type(new T(arg1));
+    }
+    
+    template<typename Arg1, typename Arg2>
+    result_type operator() (Arg1 arg1,Arg2 arg2)
+    {
+        return result_type(new T(arg1,arg2));
+    }
+    
+    template<typename Arg1, typename Arg2, typename Arg3>
+    result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3)
+    {
+        return result_type(new T(arg1,arg2,arg3));
+    }
+    
+    template<typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+    result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4)
+    {
+        return result_type(new T(arg1,arg2,arg3,arg4));
+    }
+    
+    template<typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
+    result_type operator() (Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4,Arg5 arg5)
+    {
+        return result_type(new T(arg1,arg2,arg3,arg4,arg5));
+    }
+    
+}; // eo struct SharedPtrNew
+
+
+
+/*
+** classes holding a shared or weak pointer.
+** designed to be used as policy classes...
+** (but may be used for other purposes, too)
+*/
+
+template<
+    class X
+>
+class SharedOwnership
+{
+    public:
+    
+        SharedOwnership( boost::shared_ptr< X > ptr)
+        : StoredPtr(ptr)
+        {}
+        
+        
+        boost::shared_ptr< X > get_ptr() const { return StoredPtr; }
+    
+    public:
+    
+        boost::shared_ptr< X > StoredPtr;
+}; // eo class SharedOwnership
+
+
+
+template<
+    class X
+>
+class WeakOwnership
+{
+    public:
+    
+        WeakOwnership( boost::shared_ptr< X > ptr)
+        : StoredPtr(ptr)
+        {}
+        
+        
+        boost::shared_ptr< X > get_ptr() const { return StoredPtr.lock(); }
+    
+    public:
+    
+        boost::weak_ptr< X > StoredPtr;
+}; // eo class WeakOwnership
+
+
+
+/*
+** NoOperation
+** ===========
+*/
+
+
+/**
+ * @brief the ultimate class for doing nothing :-)
+ *
+ * Even it sounds odd to have a functor class which is doing nothing it makes
+ * sense to use this class in some situations.
+ *
+ * One example is the usage as Deleter for shared pointers which "own" a pointer to
+ * a static object (i.e. it is not allowed to be really deleted...). Using this class
+ * as Deleter in these pointers enables us to use interfaces which expect a shared pointer
+ * even if we want(/must) to pass pointers to static objects.
+ */
+struct NoOperation
+{
+    NoOperation() {};
+    
+    template<
+        typename Arg1
+    >
+    NoOperation(Arg1) {}
+    
+    
+    template<
+        typename Arg1, typename Arg2
+    >
+    NoOperation(Arg1, Arg2) {}
+    
+    
+    template<
+        typename Arg1, typename Arg2, typename Arg3
+    >
+    NoOperation(Arg1, Arg2, Arg3) {}
+    
+    
+    void operator() () const {}
+    
+    
+    template<
+        typename Arg1
+    >
+    void operator() (Arg1) const {}
+    
+    
+    template<
+        typename Arg1, typename Arg2
+    >
+    void operator() (Arg1, Arg2) const {}
+    
+    
+    template<
+        typename Arg1, typename Arg2, typename Arg3
+    >
+    void operator() (Arg1, Arg2, Arg3) const {}
+    
+    
+    
+}; // eo struct NoOperation
+
+
+
+} // eo namespace I2n
+
+#endif
diff --git a/src/containerfunc.hxx b/src/containerfunc.hxx
new file mode 100644 (file)
index 0000000..5b1314b
--- /dev/null
@@ -0,0 +1,3 @@
+// for those who are used to .hxx files...
+
+#include "containerfunc.hpp"
\ No newline at end of file
index 4aa118b..ac4c0b3 100644 (file)
@@ -1,7 +1,7 @@
 INCLUDES = -I$(top_srcdir)/src @CPPUNIT_CFLAGS@
 METASOURCES = AUTO
 check_PROGRAMS =  test
-test_SOURCES =  stringfunc.cpp ip_range.cpp test.cpp
+test_SOURCES = ip_range.cpp stringfunc.cpp test.cpp test_containerfunc.cpp
 test_LDADD = $(top_builddir)/src/libi2ncommon.la @CPPUNIT_LIBS@
 
 TESTS = test
index c2a1c96..043c58f 100644 (file)
 #include <cppunit/extensions/HelperMacros.h>
 
 #include <stringfunc.hxx>
+#include <containerfunc.hpp>
 
 using namespace std;
 using namespace CppUnit;
+using namespace I2n;
 
 class stringfunc : public TestFixture
 {
@@ -37,8 +39,28 @@ class stringfunc : public TestFixture
     CPPUNIT_TEST(imaputf7_to_utf8);
     CPPUNIT_TEST(utf8_to_imaputf7);
 
+    
+    CPPUNIT_TEST(TestTrim);
+    CPPUNIT_TEST(TestChomp);
+    CPPUNIT_TEST(TestSuffixFuncs);
+    CPPUNIT_TEST(TestPrefixFuncs);
+    CPPUNIT_TEST(TestLowerUpperFuncs);
+    
+    CPPUNIT_TEST(PairSplit1);
+    CPPUNIT_TEST(SplitString1);
+    CPPUNIT_TEST(SplitString2);
+    CPPUNIT_TEST(JoinString1);
+    
+    CPPUNIT_TEST(ConversionStringInt);
+    
+    CPPUNIT_TEST(HexConversion);
+    
+
     CPPUNIT_TEST_SUITE_END();
 
+    protected:
+      typedef std::list< std::string > StringList;
+
     public:
         void smart_html_entites1()
         {
@@ -132,6 +154,306 @@ class stringfunc : public TestFixture
             string output = utf8_to_utf7imap("Späm");
             CPPUNIT_ASSERT_EQUAL(string("Sp&AOQ-m"), output);
         }
+
+      /*
+      **
+      */
+
+        void TestTrim()
+        {
+            std::string s("s1");
+            trim_mod(s);
+            CPPUNIT_ASSERT_EQUAL( std::string("s1"), s );
+            
+            s="  s2";
+            trim_mod(s);
+            CPPUNIT_ASSERT_EQUAL( std::string("s2"), s );
+            
+            s="s3   ";
+            trim_mod(s);
+            CPPUNIT_ASSERT_EQUAL( std::string("s3"), s );
+            
+            s="::s4:s4::++--aa";
+            trim_mod(s,":+-a");
+            CPPUNIT_ASSERT_EQUAL( std::string("s4:s4"), s);
+            
+            /* non modifying version */
+            
+            s= "s1";
+            CPPUNIT_ASSERT_EQUAL( std::string("s1"), trim(s) );
+            
+            s="  s2";
+            CPPUNIT_ASSERT_EQUAL( std::string("s2"), trim(s) );
+            CPPUNIT_ASSERT_EQUAL( std::string("  s2"), s );
+            
+            s="s3   ";
+            CPPUNIT_ASSERT_EQUAL( std::string("s3"), trim(s) );
+            CPPUNIT_ASSERT_EQUAL( std::string("s3   "), s );
+            
+            s="::s4:s4::++--aa";
+            CPPUNIT_ASSERT_EQUAL( std::string("s4:s4"), trim(s,":+-a") );
+        } // eo TestTrim()
+        
+        
+        
+        void TestChomp()
+        {
+            std::string s("s1");
+            
+            chomp_mod(s);
+            CPPUNIT_ASSERT_EQUAL( std::string("s1"), s );
+            
+            s="s2\n";
+            chomp_mod(s);
+            CPPUNIT_ASSERT_EQUAL( std::string("s2"), s );
+            
+            s="s3:";
+            chomp_mod(s,":");
+            CPPUNIT_ASSERT_EQUAL( std::string("s3"), s );
+            
+            s=":s4::";
+            chomp_mod(s,"s:");
+            CPPUNIT_ASSERT_EQUAL( std::string(":s4:"), s);
+            
+            /* non modifiying versions */
+            s= "s1";
+            
+            CPPUNIT_ASSERT_EQUAL( std::string("s1"), chomp(s) );
+            
+            s="s2\n";
+            CPPUNIT_ASSERT_EQUAL( std::string("s2"), chomp(s) );
+            CPPUNIT_ASSERT_EQUAL( std::string("s2\n"), s);
+            
+            s="s3:";
+            CPPUNIT_ASSERT_EQUAL( std::string("s3"), chomp(s,":") );
+            CPPUNIT_ASSERT_EQUAL( std::string("s3:"), s);
+            
+            s=":s4::";
+            CPPUNIT_ASSERT_EQUAL( std::string(":s4:"), chomp(s,"s:") );
+            CPPUNIT_ASSERT_EQUAL( std::string(":s4::"), s);
+        } // eo TestChomp()
+        
+        
+        
+        void TestSuffixFuncs()
+        {
+            std::string s1("12.cpp");
+            
+            CPPUNIT_ASSERT_EQUAL( true, has_suffix(s1,".cpp") );
+            CPPUNIT_ASSERT_EQUAL( true, has_suffix(s1,"pp") );
+            CPPUNIT_ASSERT_EQUAL( false, has_suffix(s1,"hpp") );
+            CPPUNIT_ASSERT_EQUAL( false, has_suffix(s1,"cp") );
+            CPPUNIT_ASSERT_EQUAL( false, has_suffix(s1,"") );
+            
+            std::string s1c1= remove_suffix(s1,".cpp");
+            CPPUNIT_ASSERT_EQUAL( std::string("12"), s1c1 );
+            
+            std::string s1c2= remove_suffix(s1,"p");
+            CPPUNIT_ASSERT_EQUAL( std::string("12.cp"), s1c2 );
+            
+            std::string s1c3= remove_suffix(s1,"cp");
+            CPPUNIT_ASSERT_EQUAL( std::string("12.cpp"), s1c3 );
+            
+            std::string s2(".cpp");
+            CPPUNIT_ASSERT_EQUAL( true, has_suffix(s2,".cpp") );
+            
+            std::string s2c1= remove_suffix(s2,".cpp");
+            CPPUNIT_ASSERT_EQUAL( std::string(""), s2c1 );
+            
+        } // eo TestSuffixFuncs()
+        
+        
+        
+        void TestPrefixFuncs()
+        {
+            std::string s1("12.cpp");
+            
+            CPPUNIT_ASSERT_EQUAL( true, has_prefix(s1,"12") );
+            CPPUNIT_ASSERT_EQUAL( true, has_prefix(s1, "1") );
+            CPPUNIT_ASSERT_EQUAL( false, has_prefix(s1, "2") );
+            CPPUNIT_ASSERT_EQUAL( false, has_prefix(s1, "") );
+            
+            std::string s1c1= remove_prefix(s1, "12");
+            CPPUNIT_ASSERT_EQUAL( std::string(".cpp"), s1c1);
+        } // eo TestPrefixFuncs()
+        
+        
+        
+        void TestLowerUpperFuncs()
+        {
+            std::string u1("CASE CONVERSION TEST..");
+            std::string l1("case conversion test..");
+            
+            std::string test1(l1);
+            
+            to_upper_mod(test1);
+            CPPUNIT_ASSERT_EQUAL( u1, test1 );
+            
+            to_lower_mod(test1);
+            CPPUNIT_ASSERT_EQUAL( l1, test1 );
+            
+            
+            CPPUNIT_ASSERT_EQUAL( u1, to_upper(l1) );
+            CPPUNIT_ASSERT_EQUAL( l1, to_lower(u1) );
+        } // eo TestLowerUpper
+        
+        
+        
+        void PairSplit1()
+        {
+            StringList str_list;
+            get_push_back_filler(str_list)
+                ("a=11")("a= 11")("a =11 ")("a =  11 ")("  a    =    11   ")
+            ;
+            CPPUNIT_ASSERT_EQUAL( 5u, str_list.size() );
+            for(StringList::iterator it= str_list.begin();
+                it != str_list.end();
+                ++it)
+            {
+                std::string key, value;
+                bool res= pair_split( *it, key, value);
+                
+                CPPUNIT_ASSERT_EQUAL( true , res );
+                CPPUNIT_ASSERT_EQUAL( std::string("a"), key );
+                CPPUNIT_ASSERT_EQUAL( std::string("11"), value );
+            }
+            
+            std::string key, value;
+            bool res;
+            
+            res= pair_split(" 1 : 2 ", key, value, ':');
+            CPPUNIT_ASSERT_EQUAL( true, res );
+            CPPUNIT_ASSERT_EQUAL( std::string("1"), key);
+            CPPUNIT_ASSERT_EQUAL( std::string("2"), value);
+        } // eo PairSplit1
+        
+        
+        
+        void SplitString1()
+        {
+            std::string block(
+                "Zeile 1\n"
+                "++Zeile-2--\n"
+                "Zeile 3\n"
+                "\n"
+                "Zeile 5\n"
+            );
+            
+            StringList list1;
+            
+            split_string(block, list1, "\n");
+            // since the blocks ends with \n we should have 6 lines (the last one empty):
+            CPPUNIT_ASSERT_EQUAL( 6u, list1.size() );
+            CPPUNIT_ASSERT_EQUAL( std::string(), list1.back() );
+            CPPUNIT_ASSERT_EQUAL( std::string("Zeile 1"), list1.front() );
+            
+            StringList list2;
+            
+            split_string(block, list2, "\n", true);
+            
+            // now we omitted empty lines, now we should have only 4 lines left:
+            CPPUNIT_ASSERT_EQUAL( 4u, list2.size() );
+            CPPUNIT_ASSERT_EQUAL( std::string("Zeile 5"), list2.back() );
+            CPPUNIT_ASSERT_EQUAL( std::string("Zeile 1"), list2.front() );
+            
+            list2= split_string(block, "\n", true, "+-");
+            
+            // again, we omitted empty lines, but also trimmed away leading and trailing "+" and "-"
+            CPPUNIT_ASSERT_EQUAL( 4u, list2.size() );
+            CPPUNIT_ASSERT_EQUAL( std::string("Zeile 5"), list2.back() );
+            CPPUNIT_ASSERT_EQUAL( std::string("Zeile 1"), list2.front() );
+            CPPUNIT_ASSERT_EQUAL( std::string("Zeile-2"), *(++list2.begin()) );
+        } // eo SplitString1
+        
+        
+        
+        void SplitString2()
+        {
+            std::string line("172.16.0.0/16 dev eth0  scope link  src 172.16.1.111");
+            
+            StringList list1;
+            
+            split_string(line, list1, " ", true, Whitespaces);
+            
+            CPPUNIT_ASSERT_EQUAL( 7u, list1.size() );
+            
+        } // eo SplitString2
+        
+        
+        
+        void JoinString1()
+        {
+            std::list< std::string > parts;
+            get_push_back_filler(parts)("1")("2")("drei");
+            
+            std::string joined_string= join_string(parts,"/");
+            // we should have slashes between the strings:
+            CPPUNIT_ASSERT_EQUAL( std::string("1/2/drei") , joined_string );
+            
+            parts.push_back( std::string() );
+            joined_string= join_string(parts,"/");
+            // now we should have an additional trailing slash:
+            CPPUNIT_ASSERT_EQUAL( std::string("1/2/drei/") , joined_string );
+            
+            parts.push_front( std::string() );
+            joined_string= join_string(parts,"/");
+            // now we should have an additional leading slash:
+            CPPUNIT_ASSERT_EQUAL( std::string("/1/2/drei/") , joined_string );
+            
+        } // eo JoinString1
+        
+        
+        
+        void ConversionStringInt()
+        {
+            std::string s1("24");
+            std::string s1x("25x");
+            int i1=0;
+            bool res= false;
+            
+            i1= string_to<int>(s1);
+            CPPUNIT_ASSERT_EQUAL( 24, i1 );
+            i1= string_to<int>(s1x);
+            CPPUNIT_ASSERT_EQUAL( 25, i1 );
+            
+            res= string_to<int>(s1,i1);
+            CPPUNIT_ASSERT_EQUAL( true, res );
+            CPPUNIT_ASSERT_EQUAL( 24, i1 );
+            
+            res= string_to<int>(s1x,i1);
+            CPPUNIT_ASSERT_EQUAL( false, res );
+            
+            std::string ss1= to_string( 24 );
+            CPPUNIT_ASSERT_EQUAL( std::string("24"), ss1);
+            
+        } // eo ConversionStringInt()
+        
+        
+        
+        void HexConversion()
+        {
+            std::string hex1("49324E");
+            std::string bin1("I2N");
+            
+            CPPUNIT_ASSERT_EQUAL( hex1, convert_binary_to_hex(bin1,true) );
+            CPPUNIT_ASSERT_EQUAL( bin1, convert_hex_to_binary(hex1) );
+            CPPUNIT_ASSERT_EQUAL( to_lower(hex1), convert_binary_to_hex(bin1) );
+            
+            std::string hex2("0001");
+            std::string hex2a("00 01");
+            std::string hex2b("00:01");
+            std::string bin2("\0\1",2);
+            
+            CPPUNIT_ASSERT_EQUAL( hex2, convert_binary_to_hex(bin2) );
+            CPPUNIT_ASSERT_EQUAL( bin2, convert_hex_to_binary(hex2) );
+            CPPUNIT_ASSERT_EQUAL( bin2, convert_hex_to_binary(hex2a) );
+            CPPUNIT_ASSERT_EQUAL( bin2, convert_hex_to_binary(hex2b) );
+            
+            CPPUNIT_ASSERT_THROW( convert_hex_to_binary("01 kein hex"), std::runtime_error);
+        } // eo HexConversion()
+        
+        
+        
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(stringfunc);
diff --git a/test/test_containerfunc.cpp b/test/test_containerfunc.cpp
new file mode 100644 (file)
index 0000000..585df32
--- /dev/null
@@ -0,0 +1,123 @@
+/** @file
+ *
+ * tests for the module "containerfunc"
+ *
+ * (c) Copyright 2007-2008 by Intra2net AG
+ * 
+ * info@intra2net.com
+ */
+
+//#define NOISEDEBUG
+
+#include <string>
+#include <vector>
+#include <list>
+#include <algorithm>
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <containerfunc.hpp>
+
+
+
+using namespace I2n;
+
+using namespace CppUnit;
+
+namespace {
+
+
+} // eo namespace <anonymous>
+
+
+class TestContainerFunc : public TestFixture
+{
+    CPPUNIT_TEST_SUITE(TestContainerFunc);
+    
+    // data tools:
+    
+    CPPUNIT_TEST(FillStringVector);
+    CPPUNIT_TEST(RetrieveMapKeys);
+    
+    CPPUNIT_TEST_SUITE_END();
+    
+    protected:
+    
+
+    public:
+    
+        void setUp()
+        {
+        } // eo setUp
+        
+        
+        void tearDown()
+        {
+        } // eo tearDown
+        
+        
+        /*
+         * the tests:
+         */
+        
+        
+        
+        void FillStringVector()
+        {
+            std::vector< std::string > v;
+            CPPUNIT_ASSERT_EQUAL( true, v.empty() );
+            
+            get_push_back_filler(v)("1")("2")("drei");
+            
+            CPPUNIT_ASSERT_EQUAL( 3u, v.size() );
+            CPPUNIT_ASSERT_EQUAL( std::string("2"), v[1]);
+            CPPUNIT_ASSERT_EQUAL( std::string("drei"), v[2]);
+            CPPUNIT_ASSERT_EQUAL( std::string("1"), v[0]);
+            
+            get_push_back_filler(v)("i3")("i4");
+            
+            CPPUNIT_ASSERT_EQUAL( 5u, v.size() );
+            CPPUNIT_ASSERT_EQUAL( std::string("i4"), v[4]);
+            CPPUNIT_ASSERT_EQUAL( std::string("i3"), v[3]);
+        } // eo FillStringVector
+        
+        
+        
+        void RetrieveMapKeys()
+        {
+            std::map< int, std::string > map1;
+            std::list< int > key_list;
+            std::set< int > key_set;
+            
+            {
+                MapFiller< int, std::string > fill(map1);
+                fill
+                    (1, "one")
+                    (2, "two")
+                    (3, "three" )
+                    (4, "many..." )
+                ;
+            }
+            CPPUNIT_ASSERT_EQUAL( 4u, map1.size() );
+            
+            get_key_list(map1, key_list);
+            CPPUNIT_ASSERT_EQUAL( 4u, key_list.size() );
+            CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 1) != key_list.end() );
+            CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 2) != key_list.end() );
+            CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 3) != key_list.end() );
+            CPPUNIT_ASSERT( std::find(key_list.begin(), key_list.end(), 4) != key_list.end() );
+            
+            get_key_set(map1, key_set);
+            CPPUNIT_ASSERT_EQUAL( 4u, key_set.size() );
+            CPPUNIT_ASSERT( key_set.find(1) != key_set.end() );
+            CPPUNIT_ASSERT( key_set.find(2) != key_set.end() );
+            CPPUNIT_ASSERT( key_set.find(3) != key_set.end() );
+            CPPUNIT_ASSERT( key_set.find(4) != key_set.end() );
+        } // RetrieveMapKeys()
+        
+        
+}; // eo class TestContainerFunc
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TestContainerFunc);