$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: steven_at_[hidden]
Date: 2007-11-19 10:38:29
Author: steven_watanabe
Date: 2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
New Revision: 41228
URL: http://svn.boost.org/trac/boost/changeset/41228
Log:
Initial import
Added:
   sandbox/switch/
   sandbox/switch/boost/
   sandbox/switch/boost/switch.hpp   (contents, props changed)
   sandbox/switch/libs/
   sandbox/switch/libs/switch/
   sandbox/switch/libs/switch/boost.png   (contents, props changed)
   sandbox/switch/libs/switch/doc/
   sandbox/switch/libs/switch/doc/Jamfile.v2   (contents, props changed)
   sandbox/switch/libs/switch/doc/switch.qbk   (contents, props changed)
   sandbox/switch/libs/switch/test/
   sandbox/switch/libs/switch/test/Jamfile.v2   (contents, props changed)
   sandbox/switch/libs/switch/test/test_switch.cpp   (contents, props changed)
Added: sandbox/switch/boost/switch.hpp
==============================================================================
--- (empty file)
+++ sandbox/switch/boost/switch.hpp	2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,129 @@
+// switch.hpp
+//
+// Copyright (c) 2006-2007
+// Steven Watanabe
+//
+// Distriuted under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost/org/LICENSE_1_0.txt)
+
+#ifndef BOOST_SWITCH_HPP_INCLUDED
+#define BOOST_SWITCH_HPP_INCLUDED
+
+#include <stdexcept>
+#include <string>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/preprocessor/config/limits.hpp>
+#include <boost/preprocessor/repetition/repeat.hpp>
+#include <boost/preprocessor/iteration/local.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/at.hpp>
+
+#ifndef BOOST_SWITCH_LIMIT
+    #define BOOST_SWITCH_LIMIT 50
+#endif
+
+#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_REPEAT
+    #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit
+#endif
+#if BOOST_SWITCH_LIMIT > BOOST_PP_LIMIT_ITERATION
+    #error BOOST_SWITCH_LIMIT exceeds Boost.Preprocessor limit
+#endif
+
+namespace boost {
+
+class bad_switch : public std::runtime_error {
+public:
+    template<class Int>
+    explicit bad_switch(Int v) :
+        std::runtime_error(
+            "boost::switch_ default case called -- none provided. value is: " +
+            boost::lexical_cast<std::string>(v)) {}
+};
+
+namespace switch_detail {
+
+// Avoid the need to create all the specializations of switch_impl
+// twice. Just pass this to switch_impl<N>::apply(...) when no
+// default is supplied.
+
+template<class R>
+R forced_return(R* r = 0) {
+    return(*r);
+}
+
+// Thanks to Stjepan Rajko for catching this.
+template<>
+void forced_return<void>(void*) {}
+
+template<class R>
+struct throw_exception {
+    template<class Int>
+    R operator()(Int i) const {
+        boost::throw_exception(bad_switch(i));
+        return(switch_detail::forced_return<R>());
+    }
+};
+
+// N is the number of cases not including the default
+template<int N>
+struct switch_impl;
+
+// specialize for 0 separately to avoid warnings
+template<>
+struct switch_impl<0> {
+    template<class V, class Int, class F, class Default>
+    static typename F::result_type
+    apply(Int i, F, Default d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+        return(d(i));
+    }
+};
+
+#define BOOST_SWITCH_CASE(z, n, data)                   \
+    case boost::mpl::at_c<data, n>::type::value: {      \
+        typename boost::mpl::at_c<data, n>::type arg;   \
+        return(f(arg));                                 \
+    }
+
+#define BOOST_SWITCH_IMPL(z, n, data)                                   \
+    template<>                                                          \
+    struct switch_impl<n> {                                             \
+        template<class V, class I, class F, class D>                    \
+        static typename F::result_type                                  \
+        apply(I i, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {   \
+            switch(i) {                                                 \
+                BOOST_PP_REPEAT_##z(n, BOOST_SWITCH_CASE, V)            \
+                default: return(d(i));                                  \
+            }                                                           \
+        }                                                               \
+    };
+
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_SWITCH_LIMIT)
+#define BOOST_PP_LOCAL_MACRO(n) BOOST_SWITCH_IMPL(1, n, ~)
+#include BOOST_PP_LOCAL_ITERATE()
+
+#undef BOOST_SWITCH_IMPL
+#undef BOOST_SWITCH_CASE
+
+}
+
+template<class V, class N, class F>
+inline typename F::result_type
+switch_(N n, F f BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+    typedef switch_detail::switch_impl<boost::mpl::size<V>::value> impl;
+    switch_detail::throw_exception<typename F::result_type> default_;
+    return(impl::template apply<V>(n, f, default_));
+}
+
+template<class V, class N, class F, class D>
+inline typename F::result_type
+switch_(N n, F f, D d BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(V)) {
+    typedef switch_detail::switch_impl<boost::mpl::size<V>::value> impl;
+    return(impl::template apply<V>(n, f, d));
+}
+
+}
+
+#endif
Added: sandbox/switch/libs/switch/boost.png
==============================================================================
Binary file. No diff available.
Added: sandbox/switch/libs/switch/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/doc/Jamfile.v2	2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,14 @@
+# Switch documentation Jamfile
+#
+# Copyright (c) 2007
+# Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+using quickbook ;
+
+xml switch_ : switch.qbk ;
+
+boostbook standalone : switch_ ;
Added: sandbox/switch/libs/switch/doc/switch.qbk
 Added: sandbox/switch/libs/switch/test/Jamfile.v2
 Added: sandbox/switch/libs/switch/test/test_switch.cpp
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/doc/switch.qbk	2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,109 @@
+[library Boost.Switch
+  [version 1.0]
+  [authors [Watanabe, Steven]]
+  [copyright 2007 Steven Watanabe]
+  [license
+      Distributed under the Boost Software License, Version 1.0.
+      (See accompanying file LICENSE_1_0.txt or copy at
+      <ulink href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)
+  ]
+  [purpose generates a switch statement]
+]
+
+[section:introduction Introduction]
+
+The built in C/C++ switch statement is very efficient.
+Unfortunately, unlike a chained if/else construct there
+is no easy way to use it when the number of cases depends
+on a template parameter.
+
+[endsect]
+
+[section:switch_ switch_]
+
+    namespace boost {
+
+    template<class Cases, class Int, class F>
+    typename F::result_type switch_(Int n, F f);
+
+    template<class Cases, class Int, class F, class Default>
+    typename F::result_type switch_(Int n, F f, Default default_);
+
+    }
+
+[*Header]
+
+    #include <boost/switch.hpp>
+
+[variablelist Parameters
+    [[[^Cases]][MPL Forward Sequence of integer constants]]
+    [[[^n]][Integer]]
+    [[[^f]][Function object]]
+    [[[^default_]][Function object]]
+]
+
+Generates a switch statement. If the value of one
+of the elements of `Cases` is equal to `n`, then this function
+will call `f` with a parameter of that type.  Otherwise
+it will pass `n` to `default_` or throw an exception depending
+on whether `default_` was specified.  For example
+
+    template<class FusionSequence>
+    struct print_nth_function {
+        typedef void result_type;
+        template<class Case>
+        void operator()(Case) const {
+            std::cout << fusion::at<Case>(sequence) << std::endl;
+        }
+        print_nth(const FusionSequence& s) : sequence(s) {}
+        const FusionSequence& sequence;
+    };
+
+    struct throw_out_of_range {
+        template<class Int>
+        void operator()(Int) const {
+            throw(std::out_of_range());
+        }
+    };
+
+    template<class FusionSequence>
+    void print_nth(const FusionSequence& s, std::size_t n) {
+        typedef typename fusion::result_of::size<FusionSequence>::type size;
+        typedef mpl::range_c<std::size_t, 0, size::value> range;
+        switch_<range>(n, print_nth_function(s), throw_out_of_range());
+    }
+
+prints the nth element of a fusion sequence.
+
+[endsect]
+
+[section:bad_switch bad_switch]
+
+    namespace boost {
+
+    class bad_switch : public std::runtime_error {};
+
+    }
+
+[*Header]
+
+    #include <boost/switch.hpp>
+
+Thrown when the default case is executed
+and no default was provided.
+
+[endsect]
+
+[section:BOOST_SWITCH_LIMIT BOOST_SWITCH_LIMIT]
+
+    #define BOOST_SWITCH_LIMIT 50
+
+[*Header]
+
+    #include <boost/switch.hpp>
+
+Specifies the maximum number of cases supported.
+The default value of 50 can be overridden as long
+as it is the same in every translation unit.
+
+[endsect]
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/test/Jamfile.v2	2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,22 @@
+# Switch
+#
+# Copyright (c) 2007
+# Steven Watanabe
+#
+# Distributed under the Boost Software License, Version 1.0. (See
+# accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt
+
+import testing ;
+
+project switch_test : :
+    requirements <include>../../.. <warnings>all
+;
+
+
+{
+  test-suite switch_:
+   :
+    [ run test_switch.cpp $(BOOST_ROOT)/libs/test/build//boost_unit_test_framework : : : : ]
+   ;
+}
==============================================================================
--- (empty file)
+++ sandbox/switch/libs/switch/test/test_switch.cpp	2007-11-19 10:38:28 EST (Mon, 19 Nov 2007)
@@ -0,0 +1,113 @@
+// test_switch.cpp
+//
+// Copyright (c) 2007
+// Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_AUTO_TEST_MAIN
+
+#include <boost/switch.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/vector_c.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/test/auto_unit_test.hpp>
+
+namespace {
+    typedef boost::mpl::vector_c<int, 0, 2, 1, 4, 5, 6, 3> values;
+    struct f {
+        typedef int result_type;
+        template<class Index>
+        int operator()(Index) {
+            return(boost::mpl::at<values, Index>::type::value);
+        }
+    };
+    int default_(int i) {
+        return(i);
+    }
+    typedef boost::mpl::range_c<int, 0, 0> empty_range;
+    typedef boost::mpl::vector_c<int, 1, 0, 5> non_sequential_range;
+    typedef boost::mpl::range_c<int, 0, 7> test_range;
+
+    struct limit_test {
+        typedef int result_type;
+        template<class Index>
+        int operator()(Index) {
+            return(-Index::value);
+        }
+    };
+    typedef boost::mpl::range_c<int, 0, BOOST_SWITCH_LIMIT> limit_range;
+    const int limit_value = BOOST_SWITCH_LIMIT - 1;
+
+    struct void_return {
+        typedef void result_type;
+        template<class Index>
+        void operator()(Index) {
+            // Do Nothing.
+        }
+    };
+}
+
+BOOST_AUTO_TEST_CASE(without_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<test_range>(5, f())), 6);
+    BOOST_CHECK_EQUAL((boost::switch_<test_range>(1, f())), 2);
+
+    BOOST_CHECK_THROW((boost::switch_<test_range>(-1, f())), boost::bad_switch);
+    BOOST_CHECK_THROW((boost::switch_<test_range>(7, f())), boost::bad_switch);
+}
+
+BOOST_AUTO_TEST_CASE(with_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<test_range>(5, f(), &default_)), 6);
+    BOOST_CHECK_EQUAL((boost::switch_<test_range>(1, f(), &default_)), 2);
+
+    BOOST_CHECK_EQUAL((boost::switch_<test_range>(-1, f(), &default_)), -1);
+    BOOST_CHECK_EQUAL((boost::switch_<test_range>(7, f(), &default_)), 7);
+}
+
+BOOST_AUTO_TEST_CASE(non_sequential_without_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(5, f())), 6);
+    BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(1, f())), 2);
+
+    BOOST_CHECK_THROW((boost::switch_<non_sequential_range>(-1, f())), boost::bad_switch);
+    BOOST_CHECK_THROW((boost::switch_<non_sequential_range>(7, f())), boost::bad_switch);
+}
+
+BOOST_AUTO_TEST_CASE(non_sequential_with_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(5, f(), &default_)), 6);
+    BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(1, f(), &default_)), 2);
+
+    BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(-1, f(), &default_)), -1);
+    BOOST_CHECK_EQUAL((boost::switch_<non_sequential_range>(7, f(), &default_)), 7);
+}
+
+BOOST_AUTO_TEST_CASE(zero_params_without_default) {
+    BOOST_CHECK_THROW((boost::switch_<empty_range>(5, f())), boost::bad_switch);
+    BOOST_CHECK_THROW((boost::switch_<empty_range>(1, f())), boost::bad_switch);
+    BOOST_CHECK_THROW((boost::switch_<empty_range>(0, f())), boost::bad_switch);
+
+    BOOST_CHECK_THROW((boost::switch_<empty_range>(-1, f())), boost::bad_switch);
+    BOOST_CHECK_THROW((boost::switch_<empty_range>(7, f())), boost::bad_switch);
+}
+
+BOOST_AUTO_TEST_CASE(zero_params_with_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<empty_range>(5, f(), &default_)), 5);
+    BOOST_CHECK_EQUAL((boost::switch_<empty_range>(1, f(), &default_)), 1);
+    BOOST_CHECK_EQUAL((boost::switch_<empty_range>(0, f(), &default_)), 0);
+
+    BOOST_CHECK_EQUAL((boost::switch_<empty_range>(-1, f(), &default_)), -1);
+    BOOST_CHECK_EQUAL((boost::switch_<empty_range>(7, f(), &default_)), 7);
+}
+
+BOOST_AUTO_TEST_CASE(limit_without_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<limit_range>(limit_value, limit_test())), -limit_value);
+}
+
+BOOST_AUTO_TEST_CASE(limit_with_default) {
+    BOOST_CHECK_EQUAL((boost::switch_<limit_range>(limit_value, limit_test(), &default_)), -limit_value);
+}
+
+BOOST_AUTO_TEST_CASE(test_void) {
+    boost::switch_<test_range>(0, void_return());
+}
 
$include_dir="/home/hyper-archives/boost-commit/include";
include("$include_dir/msg-footer.inc");
?>