aboutsummaryrefslogtreecommitdiff
path: root/cutl
diff options
context:
space:
mode:
Diffstat (limited to 'cutl')
-rw-r--r--cutl/compiler/context.cxx23
-rw-r--r--cutl/compiler/context.hxx70
-rw-r--r--cutl/compiler/context.txx85
-rw-r--r--cutl/compiler/traversal.hxx155
-rw-r--r--cutl/compiler/traversal.txx145
-rw-r--r--cutl/compiler/type-id.hxx47
-rw-r--r--cutl/compiler/type-id.ixx45
-rw-r--r--cutl/compiler/type-id.txx18
-rw-r--r--cutl/compiler/type-info.cxx31
-rw-r--r--cutl/compiler/type-info.hxx109
-rw-r--r--cutl/compiler/type-info.ixx96
-rw-r--r--cutl/container/any.hxx133
-rw-r--r--cutl/container/graph.hxx157
-rw-r--r--cutl/container/graph.txx315
-rw-r--r--cutl/container/pointer-iterator.hxx127
-rw-r--r--cutl/makefile47
-rw-r--r--cutl/meta/answer.hxx25
-rw-r--r--cutl/meta/class-p.hxx27
-rw-r--r--cutl/meta/polymorphic-p.hxx51
-rw-r--r--cutl/meta/remove-c.hxx27
-rw-r--r--cutl/meta/remove-cv.hxx24
-rw-r--r--cutl/meta/remove-p.hxx27
-rw-r--r--cutl/meta/remove-v.hxx27
-rw-r--r--cutl/shared-ptr.hxx135
-rw-r--r--cutl/shared-ptr/base.cxx63
-rw-r--r--cutl/shared-ptr/base.hxx90
-rw-r--r--cutl/shared-ptr/base.ixx79
-rw-r--r--cutl/shared-ptr/base.txx174
-rw-r--r--cutl/static-ptr.hxx75
29 files changed, 2427 insertions, 0 deletions
diff --git a/cutl/compiler/context.cxx b/cutl/compiler/context.cxx
new file mode 100644
index 0000000..da31d6e
--- /dev/null
+++ b/cutl/compiler/context.cxx
@@ -0,0 +1,23 @@
+// file : cutl/compiler/context.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/context.hxx>
+
+namespace cutl
+{
+ namespace compiler
+ {
+ void context::
+ remove (char const* key)
+ {
+ map::iterator i (map_.find (key));
+
+ if (i == map_.end ())
+ throw no_entry ();
+
+ map_.erase (i);
+ }
+ }
+}
diff --git a/cutl/compiler/context.hxx b/cutl/compiler/context.hxx
new file mode 100644
index 0000000..4bae010
--- /dev/null
+++ b/cutl/compiler/context.hxx
@@ -0,0 +1,70 @@
+// file : cutl/compiler/context.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_COMPILER_CONTEXT_HXX
+#define CUTL_COMPILER_CONTEXT_HXX
+
+#include <map>
+#include <string>
+#include <cstddef> // std::size_t
+
+#include <cutl/container/any.hxx>
+
+namespace cutl
+{
+ namespace compiler
+ {
+ class context
+ {
+ public:
+ struct no_entry {};
+ struct typing {};
+
+ public:
+ context () {}
+
+ private:
+ context (context const&);
+
+ context&
+ operator= (context const&);
+
+ public:
+ std::size_t
+ count (char const* key) const
+ {
+ return map_.count (key);
+ }
+
+ template <typename X>
+ X&
+ get (char const* key);
+
+ template <typename X>
+ X const&
+ get (char const* key) const;
+
+ template <typename X>
+ X const&
+ get (char const* key, X const& default_value) const;
+
+ template <typename X>
+ void
+ set (char const* key, X const& value);
+
+ void
+ remove (char const* key);
+
+ private:
+ typedef std::map<std::string, container::any> map;
+
+ map map_;
+ };
+ }
+}
+
+#include <cutl/compiler/context.txx>
+
+#endif // CUTL_COMPILER_CONTEXT_HXX
diff --git a/cutl/compiler/context.txx b/cutl/compiler/context.txx
new file mode 100644
index 0000000..55a24f7
--- /dev/null
+++ b/cutl/compiler/context.txx
@@ -0,0 +1,85 @@
+// file : cutl/compiler/context.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace compiler
+ {
+ template <typename X>
+ X& context::
+ get (char const* key)
+ {
+ map::iterator i (map_.find (key));
+
+ if (i == map_.end ())
+ throw no_entry ();
+
+ try
+ {
+ return i->second.value<X> ();
+ }
+ catch (container::any::typing const&)
+ {
+ throw typing ();
+ }
+ }
+
+ template <typename X>
+ X const& context::
+ get (char const* key) const
+ {
+ map::const_iterator i (map_.find (key));
+
+ if (i == map_.end ())
+ throw no_entry ();
+
+ try
+ {
+ return i->second.value<X> ();
+ }
+ catch (container::any::typing const&)
+ {
+ throw typing ();
+ }
+ }
+
+ template <typename X>
+ X const& context::
+ get (char const* key, X const& default_value) const
+ {
+ map::const_iterator i (map_.find (key));
+
+ if (i == map_.end ())
+ return default_value;
+
+ try
+ {
+ return i->second.value<X> ();
+ }
+ catch (container::any::typing const&)
+ {
+ throw typing ();
+ }
+ }
+
+ template <typename X>
+ void context::
+ set (char const* key, X const& value)
+ {
+ try
+ {
+ std::pair<map::iterator, bool> r (
+ map_.insert (map::value_type (key, value)));
+
+ if (!r.second)
+ r.first->second.value<X> () = value;
+ }
+ catch (container::any::typing const&)
+ {
+ throw typing ();
+ }
+ }
+ }
+}
diff --git a/cutl/compiler/traversal.hxx b/cutl/compiler/traversal.hxx
new file mode 100644
index 0000000..ad677b0
--- /dev/null
+++ b/cutl/compiler/traversal.hxx
@@ -0,0 +1,155 @@
+// file : cutl/compiler/traversal.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_COMPILER_TRAVERSAL_HXX
+#define CUTL_COMPILER_TRAVERSAL_HXX
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include <cutl/compiler/type-info.hxx>
+
+namespace cutl
+{
+ namespace compiler
+ {
+ //
+ //
+ template<typename B>
+ class traverser
+ {
+ public:
+ virtual
+ ~traverser ();
+
+ virtual void
+ trampoline (B&) = 0;
+ };
+
+ //
+ //
+ template<typename B>
+ class traverser_map
+ {
+ public:
+ typedef std::vector<traverser<B>*> traversers;
+ typedef std::map<type_id, traversers> map_type;
+ typedef typename map_type::const_iterator iterator;
+
+ iterator
+ begin () const
+ {
+ return map_.begin ();
+ }
+
+ iterator
+ end () const
+ {
+ return map_.end ();
+ }
+
+ void
+ add (type_id const& id, traverser<B>& t)
+ {
+ traversers& travs (map_[id]);
+ travs.push_back (&t);
+ }
+
+ protected:
+ map_type map_;
+ };
+
+ //
+ //
+ template <typename X, typename B>
+ class traverser_impl: public traverser<B>,
+ public virtual traverser_map<B>
+ {
+ public:
+ typedef X type;
+
+ traverser_impl ()
+ {
+ add (typeid (type), *this);
+ }
+
+ virtual void
+ traverse (type&) = 0;
+
+ public:
+ virtual void
+ trampoline (B&);
+ };
+
+ //
+ //
+ template <typename B>
+ class dispatcher: public virtual traverser_map<B>
+ {
+ public:
+ virtual
+ ~dispatcher ();
+
+ void
+ traverser (traverser_map<B>&);
+
+ virtual void
+ dispatch (B&);
+
+ public:
+ template <typename I, typename X>
+ static void
+ iterate_and_dispatch (I begin, I end, dispatcher<X>& d)
+ {
+ for (; begin != end; ++begin)
+ {
+ d.dispatch (*begin);
+ }
+ }
+
+ template <typename T, typename A, typename I, typename X>
+ static void
+ iterate_and_dispatch (I begin,
+ I end,
+ dispatcher<X>& d,
+ T& t,
+ void (T::*next)(A&),
+ A& a)
+ {
+ for (; begin != end;)
+ {
+ d.dispatch (*begin);
+
+ if (++begin != end && next != 0)
+ (t.*next) (a);
+ }
+ }
+
+ private:
+ struct comparator
+ {
+ bool
+ operator () (type_info const& a, type_info const& b) const
+ {
+ return a.type_id () < b.type_id ();
+ }
+ };
+
+ typedef std::map<type_info, std::size_t, comparator> level_map;
+ typedef std::set<type_info, comparator> type_info_set;
+
+ static std::size_t
+ compute_levels (type_info const&, std::size_t current, level_map&);
+
+ static void
+ flatten_tree (type_info const&, type_info_set&);
+ };
+ }
+}
+
+#include <cutl/compiler/traversal.txx>
+
+#endif // CUTL_COMPILER_TRAVERSAL_HXX
diff --git a/cutl/compiler/traversal.txx b/cutl/compiler/traversal.txx
new file mode 100644
index 0000000..315d11b
--- /dev/null
+++ b/cutl/compiler/traversal.txx
@@ -0,0 +1,145 @@
+// file : cutl/compiler/traversal.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace compiler
+ {
+ // traverser
+ //
+ template<typename B>
+ traverser<B>::
+ ~traverser ()
+ {
+ }
+
+ // traverser_impl
+ //
+
+ template <typename X, typename B>
+ void traverser_impl<X, B>::
+ trampoline (B& x)
+ {
+ this->traverse (dynamic_cast<type&> (x));
+ }
+
+ // dispatcher
+ //
+
+ template <typename B>
+ dispatcher<B>::
+ ~dispatcher ()
+ {
+ }
+
+ template <typename B>
+ void dispatcher<B>::
+ traverser (traverser_map<B>& m)
+ {
+ // Copy entries from m to our map.
+ //
+ for (typename traverser_map<B>::iterator
+ i (m.begin ()), e (m.end ()); i != e; ++i)
+ {
+ typename traverser_map<B>::traversers& travs (this->map_[i->first]);
+
+ for (typename traverser_map<B>::traversers::const_iterator
+ t (i->second.begin ()), e (i->second.end ()); t != e; ++t)
+ {
+ travs.push_back (*t);
+ }
+ }
+ }
+
+ template <typename B>
+ void dispatcher<B>::
+ dispatch (B& x)
+ {
+ using std::size_t;
+
+ level_map levels;
+ type_info const& ti (lookup (x));
+ size_t max (compute_levels (ti, 0, levels));
+
+ // cerr << "starting dispatch process for " << ti.type_id ().name ()
+ // << " with " << max << " levels" << endl;
+
+ for (size_t l (0); l < max + 1; ++l)
+ {
+ type_info_set dispatched;
+
+ for (typename level_map::const_iterator
+ i (levels.begin ()), e (levels.end ()); i != e; ++i)
+ {
+ if (i->second == l)
+ {
+ typename traverser_map<B>::map_type::const_iterator v (
+ this->map_.find (i->first.type_id ()));
+
+ if (v != this->map_.end ())
+ {
+ // cerr << "dispatching traversers for " << ti.type_id ().name ()
+ // << " as " << i->first.type_id ().name () << endl;
+
+ typename traverser_map<B>::traversers const& travs (v->second);
+
+ for (typename traverser_map<B>::traversers::const_iterator
+ ti (travs.begin ()), te (travs.end ()); ti != te; ++ti)
+ {
+ (*ti)->trampoline (x);
+ }
+
+ flatten_tree (i->first, dispatched);
+ }
+ }
+ }
+
+ // Remove traversed types from the level map.
+ //
+ for (typename type_info_set::const_iterator i (dispatched.begin ());
+ i != dispatched.end (); ++i)
+ {
+ levels.erase (*i);
+ }
+ }
+ }
+
+ template <typename B>
+ std::size_t dispatcher<B>::
+ compute_levels (type_info const& ti, std::size_t cur, level_map& map)
+ {
+ using std::size_t;
+
+ size_t ret (cur);
+
+ if (map.find (ti) == map.end () || map[ti] < cur)
+ map[ti] = cur;
+
+ for (type_info::base_iterator i (ti.begin_base ());
+ i != ti.end_base (); ++i)
+ {
+ size_t tmp (compute_levels (i->type_info (), cur + 1, map));
+
+ if (tmp > ret)
+ ret = tmp;
+ }
+
+ return ret;
+ }
+
+ template <typename B>
+ void dispatcher<B>::
+ flatten_tree (type_info const& ti, type_info_set& set)
+ {
+ set.insert (ti);
+
+ for (type_info::base_iterator i (ti.begin_base ());
+ i != ti.end_base (); ++i)
+ {
+ flatten_tree (i->type_info (), set);
+ }
+ }
+ }
+}
diff --git a/cutl/compiler/type-id.hxx b/cutl/compiler/type-id.hxx
new file mode 100644
index 0000000..7731f6d
--- /dev/null
+++ b/cutl/compiler/type-id.hxx
@@ -0,0 +1,47 @@
+// file : cutl/compiler/type-id.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_COMPILER_TYPE_ID_HXX
+#define CUTL_COMPILER_TYPE_ID_HXX
+
+#include <typeinfo> // std::type_info
+
+namespace cutl
+{
+ namespace compiler
+ {
+ class type_id
+ {
+ public:
+ template<typename X>
+ type_id (X const volatile&);
+
+ type_id (std::type_info const&);
+
+ public:
+ char const*
+ name () const;
+
+ friend bool
+ operator== (type_id const&, type_id const&);
+
+ friend bool
+ operator!= (type_id const&, type_id const&);
+
+ friend bool
+ operator< (type_id const&, type_id const&);
+
+ private:
+ std::type_info const* ti_;
+ };
+
+ typedef type_id type_id_t;
+ }
+}
+
+#include <cutl/compiler/type-id.ixx>
+#include <cutl/compiler/type-id.txx>
+
+#endif // CUTL_COMPILER_TYPE_ID_HXX
diff --git a/cutl/compiler/type-id.ixx b/cutl/compiler/type-id.ixx
new file mode 100644
index 0000000..4092d6d
--- /dev/null
+++ b/cutl/compiler/type-id.ixx
@@ -0,0 +1,45 @@
+// file : cutl/compiler/type-id.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace compiler
+ {
+ inline
+ type_id::
+ type_id (std::type_info const& ti)
+ : ti_ (&ti)
+ {
+ }
+
+ inline
+ char const* type_id::
+ name () const
+ {
+ return ti_->name ();
+ }
+
+ inline
+ bool
+ operator== (type_id const& x, type_id const& y)
+ {
+ return *x.ti_ == *y.ti_;
+ }
+
+ inline
+ bool
+ operator!= (type_id const& x, type_id const& y)
+ {
+ return *x.ti_ != *y.ti_;
+ }
+
+ inline
+ bool
+ operator< (type_id const& x, type_id const& y)
+ {
+ return x.ti_->before (*y.ti_);
+ }
+ }
+}
diff --git a/cutl/compiler/type-id.txx b/cutl/compiler/type-id.txx
new file mode 100644
index 0000000..9fee905
--- /dev/null
+++ b/cutl/compiler/type-id.txx
@@ -0,0 +1,18 @@
+// file : cutl/compiler/type-id.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace compiler
+ {
+ template <typename X>
+ inline
+ type_id::
+ type_id (X const volatile& x)
+ : ti_ (&typeid (x))
+ {
+ }
+ }
+}
diff --git a/cutl/compiler/type-info.cxx b/cutl/compiler/type-info.cxx
new file mode 100644
index 0000000..4be7177
--- /dev/null
+++ b/cutl/compiler/type-info.cxx
@@ -0,0 +1,31 @@
+// file : cutl/compiler/type-info.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/compiler/type-info.hxx>
+
+namespace cutl
+{
+ namespace compiler
+ {
+ using namespace bits;
+
+ type_info const&
+ lookup (type_id const& tid)
+ {
+ type_info_map::const_iterator i (type_info_map_->find (tid));
+
+ if (i == type_info_map_->end ())
+ throw no_type_info ();
+
+ return i->second;
+ }
+
+ void
+ insert (type_info const& ti)
+ {
+ type_info_map_->insert (type_info_map::value_type (ti.type_id (), ti));
+ }
+ }
+}
diff --git a/cutl/compiler/type-info.hxx b/cutl/compiler/type-info.hxx
new file mode 100644
index 0000000..f970067
--- /dev/null
+++ b/cutl/compiler/type-info.hxx
@@ -0,0 +1,109 @@
+// file : cutl/compiler/type-info.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_COMPILER_TYPE_INFO_HXX
+#define CUTL_COMPILER_TYPE_INFO_HXX
+
+#include <map>
+#include <vector>
+#include <typeinfo> // std::type_info
+
+#include <cutl/static-ptr.hxx>
+#include <cutl/compiler/type-id.hxx>
+
+namespace cutl
+{
+ namespace compiler
+ {
+ //
+ //
+ class type_info;
+ typedef type_info type_info_t;
+
+
+ //
+ //
+ class base_info
+ {
+ public:
+ base_info (type_id const&);
+
+ public:
+ type_info_t const&
+ type_info () const;
+
+ private:
+ type_id type_id_;
+ mutable type_info_t const* type_info_;
+ };
+
+ typedef base_info base_info_t;
+
+
+ //
+ //
+ class type_info
+ {
+ typedef std::vector<base_info> bases;
+
+ public:
+ typedef
+ bases::const_iterator
+ base_iterator;
+
+ public:
+ type_info (type_id_t const&);
+
+ type_id_t
+ type_id () const;
+
+ base_iterator
+ begin_base () const;
+
+ base_iterator
+ end_base () const;
+
+ void
+ add_base (type_id_t const&);
+
+ private:
+ type_id_t type_id_;
+ bases bases_;
+ };
+
+
+ //
+ //
+ class no_type_info {};
+
+ type_info const&
+ lookup (type_id const&);
+
+ type_info const&
+ lookup (std::type_info const&);
+
+ template <typename X>
+ type_info const&
+ lookup (X const volatile&);
+
+ template<typename X>
+ type_info const&
+ lookup ();
+
+ void
+ insert (type_info const&);
+
+ namespace bits
+ {
+ struct default_type_info_id {};
+ typedef std::map<type_id, type_info> type_info_map;
+ static static_ptr<type_info_map, default_type_info_id> type_info_map_;
+ }
+ }
+}
+
+#include <cutl/compiler/type-info.ixx>
+
+#endif // CUTL_COMPILER_TYPE_INFO_HXX
diff --git a/cutl/compiler/type-info.ixx b/cutl/compiler/type-info.ixx
new file mode 100644
index 0000000..3f1bb86
--- /dev/null
+++ b/cutl/compiler/type-info.ixx
@@ -0,0 +1,96 @@
+// file : cutl/compiler/type-info.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace compiler
+ {
+ // base_info
+ //
+
+ inline
+ base_info::
+ base_info (type_id const& type_id)
+ : type_id_ (type_id), type_info_ (0)
+ {
+ }
+
+ inline
+ type_info_t const& base_info::
+ type_info () const
+ {
+ // We need to do delayed lookup because of the unpredictable
+ // order in which type information may be added.
+ //
+ // @@ MT-unsafe
+ //
+ if (type_info_ == 0)
+ type_info_ = &(lookup (type_id_));
+
+ return *type_info_;
+ }
+
+ // type_info
+ //
+
+ inline
+ type_info::
+ type_info (type_id_t const& tid)
+ : type_id_ (tid)
+ {
+ }
+
+ inline
+ type_id_t type_info::
+ type_id () const
+ {
+ return type_id_;
+ }
+
+ inline
+ type_info::base_iterator type_info::
+ begin_base () const
+ {
+ return bases_.begin ();
+ }
+
+
+ inline
+ type_info::base_iterator type_info::
+ end_base () const
+ {
+ return bases_.end ();
+ }
+
+ inline
+ void type_info::
+ add_base (type_id_t const& tid)
+ {
+ bases_.push_back (base_info (tid));
+ }
+
+ //
+ //
+ inline type_info const&
+ lookup (std::type_info const& tid)
+ {
+ return lookup (type_id (tid));
+ }
+
+ template <typename X>
+ inline type_info const&
+ lookup (X const volatile& x)
+ {
+ return lookup (typeid (x));
+ }
+
+ template<typename X>
+ inline type_info const&
+ lookup ()
+ {
+ return lookup (typeid (X));
+ }
+ }
+}
diff --git a/cutl/container/any.hxx b/cutl/container/any.hxx
new file mode 100644
index 0000000..0c89a38
--- /dev/null
+++ b/cutl/container/any.hxx
@@ -0,0 +1,133 @@
+// file : cutl/container/any.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_CONTAINER_ANY_HXX
+#define CUTL_CONTAINER_ANY_HXX
+
+#include <memory> // std::auto_ptr
+#include <typeinfo> // std::type_info
+
+namespace cutl
+{
+ namespace container
+ {
+ class any
+ {
+ public:
+ struct typing {};
+
+ public:
+ template <typename X>
+ any (X const& x)
+ : holder_ (new holder_impl<X> (x))
+ {
+ }
+
+ any (any const& x)
+ : holder_ (x.holder_->clone ())
+ {
+ }
+
+ template <typename X>
+ any&
+ operator= (X const& x)
+ {
+ holder_.reset (new holder_impl<X> (x));
+ return *this;
+ }
+
+ any&
+ operator= (any const& x)
+ {
+ holder_.reset (x.holder_->clone ());
+ return *this;
+ }
+
+ public:
+ template <typename X>
+ X&
+ value ()
+ {
+ if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
+ return p->value ();
+ else
+ throw typing ();
+ }
+
+ template <typename X>
+ X const&
+ value () const
+ {
+ if (holder_impl<X>* p = dynamic_cast<holder_impl<X>*> (holder_.get ()))
+ return p->value ();
+ else
+ throw typing ();
+ }
+
+ public:
+ std::type_info const&
+ type_info () const
+ {
+ return holder_->type_info ();
+ }
+
+ private:
+ class holder
+ {
+ public:
+ virtual
+ ~holder () {}
+
+ virtual holder*
+ clone () const = 0;
+
+ virtual std::type_info&
+ type_info () const = 0;
+ };
+
+ template <typename X>
+ class holder_impl: public holder
+ {
+ public:
+ holder_impl (X const& x)
+ : x_ (x)
+ {
+ }
+
+ virtual holder_impl*
+ clone () const
+ {
+ return new holder_impl (x_);
+ }
+
+ virtual std::type_info&
+ type_info () const
+ {
+ return typeid (x_);
+ }
+
+ X const&
+ value () const
+ {
+ return x_;
+ }
+
+ X&
+ value ()
+ {
+ return x_;
+ }
+
+ private:
+ X x_;
+ };
+
+ private:
+ std::auto_ptr<holder> holder_;
+ };
+ }
+}
+
+#endif // CUTL_CONTAINER_ANY_HXX
diff --git a/cutl/container/graph.hxx b/cutl/container/graph.hxx
new file mode 100644
index 0000000..9d1c716
--- /dev/null
+++ b/cutl/container/graph.hxx
@@ -0,0 +1,157 @@
+// file : cutl/container/graph.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_CONTAINER_GRAPH_HXX
+#define CUTL_CONTAINER_GRAPH_HXX
+
+#include <map>
+#include <cutl/shared-ptr.hxx>
+
+namespace cutl
+{
+ namespace container
+ {
+ template <typename N, typename E>
+ class graph
+ {
+ public:
+ typedef N node_base;
+ typedef E edge_base;
+
+ struct no_edge {};
+
+ public:
+ template <typename T>
+ T&
+ new_node ();
+
+ template <typename T, typename A0>
+ T&
+ new_node (A0 const&);
+
+ template <typename T, typename A0, typename A1>
+ T&
+ new_node (A0 const&, A1 const&);
+
+ template <typename T, typename A0, typename A1, typename A2>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&, A8 const&);
+
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8, typename A9>
+ T&
+ new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&,
+ A5 const&, A6 const&, A7 const&, A8 const&, A9 const&);
+
+ // template <typename T>
+ // void
+ // delete_node (T& node);
+
+ public:
+ template <typename T, typename L, typename R>
+ T&
+ new_edge (L&, R&);
+
+ template <typename T, typename L, typename R,
+ typename A0>
+ T&
+ new_edge (L&, R&, A0 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&,
+ A4 const&);
+
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4, typename A5>
+ T&
+ new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&,
+ A4 const&, A5 const&);
+
+ public:
+ template <typename T, typename L, typename R>
+ void
+ delete_edge (L&, R&, T& edge);
+
+ public:
+ graph () {}
+
+ private:
+ graph (graph const&);
+
+ graph&
+ operator= (graph const&);
+
+ protected:
+ typedef shared_ptr<node_base> node_ptr;
+ typedef shared_ptr<edge_base> edge_ptr;
+
+ typedef std::map<node_base*, node_ptr> nodes;
+ typedef std::map<edge_base*, edge_ptr> edges;
+
+ nodes nodes_;
+ edges edges_;
+ };
+ }
+}
+
+#include <cutl/container/graph.txx>
+
+#endif // CUTL_CONTAINER_GRAPH_HXX
diff --git a/cutl/container/graph.txx b/cutl/container/graph.txx
new file mode 100644
index 0000000..534b0ac
--- /dev/null
+++ b/cutl/container/graph.txx
@@ -0,0 +1,315 @@
+// file : cutl/container/graph.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ namespace container
+ {
+
+ // Nodes.
+ //
+
+ template <typename N, typename E>
+ template <typename T>
+ T& graph<N, E>::
+ new_node ()
+ {
+ shared_ptr<T> node (new (shared) T);
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0>
+ T& graph<N, E>::
+ new_node (A0 const& a0)
+ {
+ shared_ptr<T> node (new (shared) T (a0));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4, a5));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4, a5, a6));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7)
+ {
+ shared_ptr<T> node (new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7,
+ A8 const& a8)
+ {
+ shared_ptr<T> node (
+ new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7, a8));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename A0, typename A1, typename A2,
+ typename A3, typename A4, typename A5, typename A6,
+ typename A7, typename A8, typename A9>
+ T& graph<N, E>::
+ new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3,
+ A4 const& a4, A5 const& a5, A6 const& a6, A7 const& a7,
+ A8 const& a8, A9 const& a9)
+ {
+ shared_ptr<T> node (
+ new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9));
+ nodes_[node.get ()] = node;
+
+ return *node;
+ }
+
+
+ // Edges.
+ //
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R>
+ T& graph<N, E>::
+ new_edge (L& l, R& r)
+ {
+ shared_ptr<T> edge (new (shared) T);
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0)
+ {
+ shared_ptr<T> edge (new (shared) T (a0));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2, a3));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3, A4 const& a4)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2, a3, a4));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R,
+ typename A0, typename A1, typename A2, typename A3,
+ typename A4, typename A5>
+ T& graph<N, E>::
+ new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2,
+ A3 const& a3, A4 const& a4, A5 const& a5)
+ {
+ shared_ptr<T> edge (new (shared) T (a0, a1, a2, a3, a4, a5));
+ edges_[edge.get ()] = edge;
+
+ edge->set_left_node (l);
+ edge->set_right_node (r);
+
+ l.add_edge_left (*edge);
+ r.add_edge_right (*edge);
+
+ return *edge;
+ }
+
+
+ template <typename N, typename E>
+ template <typename T, typename L, typename R>
+ void graph<N, E>::
+ delete_edge (L& l, R& r, T& edge)
+ {
+ typename edges::iterator i (edges_.find (&edge));
+
+ if (i == edges_.end () ||
+ nodes_.find (&l) == nodes_.end () ||
+ nodes_.find (&r) == nodes_.end ())
+ throw no_edge ();
+
+ r.remove_edge_right (edge);
+ l.remove_edge_left (edge);
+
+ edge.clear_right_node (r);
+ edge.clear_left_node (l);
+
+ edges_.erase (i);
+ }
+ }
+}
diff --git a/cutl/container/pointer-iterator.hxx b/cutl/container/pointer-iterator.hxx
new file mode 100644
index 0000000..cc94151
--- /dev/null
+++ b/cutl/container/pointer-iterator.hxx
@@ -0,0 +1,127 @@
+// file : cutl/container/pointer-iterator.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_CONTAINER_POINTER_ITERATOR_HXX
+#define CUTL_CONTAINER_POINTER_ITERATOR_HXX
+
+#include <iterator> // std::iterator_traits
+
+#include <cutl/meta/remove-p.hxx>
+
+namespace cutl
+{
+ namespace container
+ {
+ template <typename I>
+ class pointer_iterator
+ {
+ public:
+ typedef
+ typename meta::remove_p<typename std::iterator_traits<I>::value_type>::r
+ value_type;
+
+ typedef
+ typename std::iterator_traits<I>::iterator_category
+ iterator_category;
+
+ typedef
+ typename std::iterator_traits<I>::difference_type
+ difference_type;
+
+ typedef value_type& reference;
+ typedef value_type* pointer;
+ typedef I base_iterator;
+
+ public:
+ pointer_iterator ()
+ : i_ () // I can be of a pointer type.
+ {
+ }
+
+ pointer_iterator (I const& i)
+ : i_ (i)
+ {
+ }
+
+ public:
+ reference
+ operator* () const
+ {
+ return **i_;
+ }
+
+ pointer
+ operator-> () const
+ {
+ return *i_;
+ }
+
+ I const&
+ base () const
+ {
+ return i_;
+ }
+
+ public:
+ // Forward iterator requirements.
+ //
+ pointer_iterator&
+ operator++ ()
+ {
+ ++i_;
+ return *this;
+ }
+
+ pointer_iterator
+ operator++ (int)
+ {
+ pointer_iterator r (*this);
+ ++i_;
+ return r;
+ }
+
+ pointer_iterator&
+ operator-- ()
+ {
+ --i_;
+ return *this;
+ }
+
+ pointer_iterator
+ operator-- (int)
+ {
+ pointer_iterator r (*this);
+ --i_;
+ return r;
+ }
+
+ private:
+ I i_;
+ };
+
+ template <typename I>
+ inline bool
+ operator== (pointer_iterator<I> const& a, pointer_iterator<I> const& b)
+ {
+ return a.base () == b.base ();
+ }
+
+ template <typename I>
+ inline bool
+ operator!= (pointer_iterator<I> const& a, pointer_iterator<I> const& b)
+ {
+ return a.base () != b.base ();
+ }
+
+ template <typename I>
+ inline typename pointer_iterator<I>::difference_type
+ operator- (pointer_iterator<I> const& a, pointer_iterator<I> const& b)
+ {
+ return a.base () - b.base ();
+ }
+ }
+}
+
+#endif // CUTL_CONTAINER_POINTER_ITERATOR_HXX
diff --git a/cutl/makefile b/cutl/makefile
new file mode 100644
index 0000000..b27f090
--- /dev/null
+++ b/cutl/makefile
@@ -0,0 +1,47 @@
+# file : cutl/makefile
+# author : Boris Kolpackov <boris@codesynthesis.com>
+# copyright : Copyright (c) 2009 Code Synthesis Tools CC
+# license : MIT; see accompanying LICENSE file
+
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+cxx_tun := shared-ptr/base.cxx
+cxx_tun += compiler/context.cxx compiler/type-info.cxx
+
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+cutl.l := $(out_base)/cutl.l
+cutl.l.cpp-options := $(out_base)/cutl.l.cpp-options
+
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(cutl.l): $(cxx_obj)
+
+$(cxx_obj) $(cxx_od): $(cutl.l.cpp-options)
+$(cutl.l.cpp-options): value := -I$(src_root)
+
+$(call include-dep,$(cxx_od))
+
+
+# Convenience alias for default target.
+#
+$(out_base)/: $(cutl.l)
+
+
+# Clean.
+#
+$(clean): $(cutl.l).o.clean \
+ $(cutl.l.cpp-options).clean \
+ $(addsuffix .cxx.clean,$(cxx_obj)) \
+ $(addsuffix .cxx.clean,$(cxx_od))
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-l.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+$(call include,$(bld_root)/cxx/cxx-d.make)
diff --git a/cutl/meta/answer.hxx b/cutl/meta/answer.hxx
new file mode 100644
index 0000000..f476dd7
--- /dev/null
+++ b/cutl/meta/answer.hxx
@@ -0,0 +1,25 @@
+// file : cutl/meta/answer.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_ANSWER_HXX
+#define CUTL_META_ANSWER_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ struct yes
+ {
+ char filling;
+ };
+
+ struct no
+ {
+ char filling[2];
+ };
+ }
+}
+
+#endif // CUTL_META_ANSWER_HXX
diff --git a/cutl/meta/class-p.hxx b/cutl/meta/class-p.hxx
new file mode 100644
index 0000000..79e8469
--- /dev/null
+++ b/cutl/meta/class-p.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/class-p.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_CLASS_HXX
+#define CUTL_META_CLASS_HXX
+
+#include <cutl/meta/answer.hxx>
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct class_p
+ {
+ template <typename Y> static no test (...);
+ template <typename Y> static yes test (void* Y::*);
+
+ static bool const r = sizeof (
+ class_p<X>::template test<X> (0)) == sizeof (yes);
+ };
+ }
+}
+
+#endif // CUTL_META_CLASS_HXX
diff --git a/cutl/meta/polymorphic-p.hxx b/cutl/meta/polymorphic-p.hxx
new file mode 100644
index 0000000..35723e3
--- /dev/null
+++ b/cutl/meta/polymorphic-p.hxx
@@ -0,0 +1,51 @@
+// file : cutl/meta/polymorphic-p.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_POLYMORPHIC_HXX
+#define CUTL_META_POLYMORPHIC_HXX
+
+#include <cutl/meta/class-p.hxx>
+#include <cutl/meta/remove-cv.hxx>
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename CVX>
+ struct polymorphic_p
+ {
+ typedef typename remove_cv<CVX>::r X;
+
+ template <typename Y, bool C>
+ struct impl
+ {
+ static const bool r = false;
+ };
+
+ template <typename Y>
+ struct impl<Y, true>
+ {
+ struct t1: Y
+ {
+ t1 ();
+ };
+
+ struct t2: Y
+ {
+ t2 ();
+
+ virtual
+ ~t2 () throw ();
+ };
+
+ static const bool r = sizeof (t1) == sizeof (t2);
+ };
+
+ static const bool r = impl<X, class_p<X>::r>::r;
+ };
+ }
+}
+
+#endif // CUTL_META_POLYMORPHIC_HXX
diff --git a/cutl/meta/remove-c.hxx b/cutl/meta/remove-c.hxx
new file mode 100644
index 0000000..be7b8a6
--- /dev/null
+++ b/cutl/meta/remove-c.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/remove-c.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_C_HXX
+#define CUTL_META_REMOVE_C_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_c
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct remove_c<X const>
+ {
+ typedef X r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_C_HXX
diff --git a/cutl/meta/remove-cv.hxx b/cutl/meta/remove-cv.hxx
new file mode 100644
index 0000000..5a7de7a
--- /dev/null
+++ b/cutl/meta/remove-cv.hxx
@@ -0,0 +1,24 @@
+// file : cutl/meta/remove-cv.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_CV_HXX
+#define CUTL_META_REMOVE_CV_HXX
+
+#include <cutl/meta/remove-c.hxx>
+#include <cutl/meta/remove-v.hxx>
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_cv
+ {
+ typedef typename remove_v<typename remove_c<X>::r>::r r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_CV_HXX
diff --git a/cutl/meta/remove-p.hxx b/cutl/meta/remove-p.hxx
new file mode 100644
index 0000000..56c4517
--- /dev/null
+++ b/cutl/meta/remove-p.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/remove-p.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_P_HXX
+#define CUTL_META_REMOVE_P_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_p
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct remove_p<X*>
+ {
+ typedef X r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_P_HXX
diff --git a/cutl/meta/remove-v.hxx b/cutl/meta/remove-v.hxx
new file mode 100644
index 0000000..9f2ae46
--- /dev/null
+++ b/cutl/meta/remove-v.hxx
@@ -0,0 +1,27 @@
+// file : cutl/meta/remove-v.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_META_REMOVE_V_HXX
+#define CUTL_META_REMOVE_V_HXX
+
+namespace cutl
+{
+ namespace meta
+ {
+ template <typename X>
+ struct remove_v
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct remove_v<X volatile>
+ {
+ typedef X r;
+ };
+ }
+}
+
+#endif // CUTL_META_REMOVE_V_HXX
diff --git a/cutl/shared-ptr.hxx b/cutl/shared-ptr.hxx
new file mode 100644
index 0000000..d94bf97
--- /dev/null
+++ b/cutl/shared-ptr.hxx
@@ -0,0 +1,135 @@
+// file : cutl/shared-ptr.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_SHARED_PTR_HXX
+#define CUTL_SHARED_PTR_HXX
+
+#include <cutl/shared-ptr/base.hxx>
+
+namespace cutl
+{
+ template <typename X>
+ class shared_ptr: bits::counter_ops<typename bits::counter_type<X>::r, X>
+ {
+ typedef bits::counter_ops<typename bits::counter_type<X>::r, X> base;
+
+ public:
+ ~shared_ptr ()
+ {
+ if (x_ != 0)
+ base::dec (x_);
+ }
+
+ explicit
+ shared_ptr (X* x = 0)
+ : base (x), x_ (x)
+ {
+ }
+
+ shared_ptr (shared_ptr const& x)
+ : base (x), x_ (x.x_)
+ {
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ template <typename Y>
+ shared_ptr (shared_ptr<Y> const& x)
+ : base (x), x_ (x.x_)
+ {
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ shared_ptr&
+ operator= (shared_ptr const& x)
+ {
+ if (x_ != x.x_)
+ {
+ if (x_ != 0)
+ base::dec (x_);
+
+ static_cast<base&> (*this) = x;
+ x_ = x.x_;
+
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ return *this;
+ }
+
+ template <typename Y>
+ shared_ptr&
+ operator= (shared_ptr<Y> const& x)
+ {
+ if (x_ != x.x_)
+ {
+ if (x_ != 0)
+ base::dec (x_);
+
+ static_cast<base&> (*this) = x;
+ x_ = x.x_;
+
+ if (x_ != 0)
+ base::inc (x_);
+ }
+
+ return *this;
+ }
+
+ public:
+ X*
+ operator-> () const
+ {
+ return x_;
+ }
+
+ X&
+ operator* () const
+ {
+ return *x_;
+ }
+
+ // Conversion to bool.
+ //
+ typedef void (shared_ptr::*boolean_convertible)();
+ void true_value () {};
+
+ operator boolean_convertible () const
+ {
+ return x_ ? &shared_ptr<X>::true_value : 0;
+ }
+
+ public:
+ X*
+ get () const
+ {
+ return x_;
+ }
+
+ X*
+ release ()
+ {
+ X* r (x_);
+ x_ = 0;
+ return r;
+ }
+
+ std::size_t
+ count () const
+ {
+ return x_ != 0 ? base::count (x_) : 0;
+ }
+
+ private:
+ template <typename>
+ friend class shared_ptr;
+
+ X* x_;
+ };
+}
+
+#endif // CUTL_SHARED_PTR_HXX
diff --git a/cutl/shared-ptr/base.cxx b/cutl/shared-ptr/base.cxx
new file mode 100644
index 0000000..a74ed15
--- /dev/null
+++ b/cutl/shared-ptr/base.cxx
@@ -0,0 +1,63 @@
+// file : cutl/shared-ptr/base.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/shared-ptr/base.hxx>
+
+using std::size_t;
+
+//
+//
+cutl::share shared = cutl::share (1);
+cutl::share exclusive = cutl::share (2);
+
+//
+//
+namespace cutl
+{
+ char const* not_shared::
+ what () const throw ()
+ {
+ return "object is not shared";
+ }
+}
+
+//
+//
+void*
+operator new (size_t n, cutl::share s) throw (std::bad_alloc)
+{
+ if (s == shared)
+ {
+ // Here we need to make sure we don't break the alignment of the
+ // returned block. For that we need to know the maximum alignment
+ // of this platform. Twice the pointer size is a good guess for
+ // most platforms.
+ //
+ size_t* p = static_cast<size_t*> (operator new (n + 2 * sizeof (size_t)));
+ *p++ = 1; // Initial count.
+ *p++ = 0xDEADBEEF; // Signature.
+ return p;
+ }
+ else
+ return operator new (n);
+
+}
+
+void
+operator delete (void* p, cutl::share s) throw ()
+{
+ // This version of operator delete is only called when the c-tor
+ // fails. In this case there is no object and we can just free the
+ // memory.
+ //
+ if (s == shared)
+ {
+ size_t* sp = static_cast<size_t*> (p);
+ sp -= 2;
+ operator delete (sp);
+ }
+ else
+ operator delete (p);
+}
diff --git a/cutl/shared-ptr/base.hxx b/cutl/shared-ptr/base.hxx
new file mode 100644
index 0000000..bb297cb
--- /dev/null
+++ b/cutl/shared-ptr/base.hxx
@@ -0,0 +1,90 @@
+// file : cutl/shared-ptr/base.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_SHARED_PTR_BASE_HXX
+#define CUTL_SHARED_PTR_BASE_HXX
+
+#include <new>
+#include <cstddef> // std::size_t
+#include <exception> // std::exception
+
+namespace cutl
+{
+ struct share
+ {
+ explicit
+ share (char id);
+
+ bool
+ operator== (share) const;
+
+ private:
+ char id_;
+ };
+}
+
+extern cutl::share shared;
+extern cutl::share exclusive;
+
+void*
+operator new (std::size_t, cutl::share) throw (std::bad_alloc);
+
+void
+operator delete (void*, cutl::share) throw ();
+
+namespace cutl
+{
+ struct not_shared: std::exception
+ {
+ virtual char const*
+ what () const throw ();
+ };
+
+ struct shared_base
+ {
+ shared_base ();
+ shared_base (shared_base const&);
+ shared_base&
+ operator= (shared_base const&);
+
+ void
+ _inc_ref ();
+
+ bool
+ _dec_ref ();
+
+ std::size_t
+ _ref_count () const;
+
+ void*
+ operator new (std::size_t, share) throw (std::bad_alloc);
+
+ void
+ operator delete (void*, share) throw ();
+
+ void
+ operator delete (void*) throw ();
+
+ protected:
+ std::size_t counter_;
+ };
+
+ template <typename X>
+ inline X*
+ inc_ref (X*);
+
+ template <typename X>
+ inline void
+ dec_ref (X*);
+
+ template <typename X>
+ inline std::size_t
+ ref_count (X const*);
+}
+
+#include <cutl/shared-ptr/base.ixx>
+#include <cutl/shared-ptr/base.txx>
+
+#endif // CUTL_SHARED_PTR_BASE_HXX
diff --git a/cutl/shared-ptr/base.ixx b/cutl/shared-ptr/base.ixx
new file mode 100644
index 0000000..928e439
--- /dev/null
+++ b/cutl/shared-ptr/base.ixx
@@ -0,0 +1,79 @@
+// file : cutl/shared-ptr/base.ixx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+namespace cutl
+{
+ // share
+ //
+
+ inline share::
+ share (char id)
+ : id_ (id)
+ {
+ }
+
+ inline bool share::
+ operator== (share x) const
+ {
+ return id_ == x.id_;
+ }
+
+ // shared_base
+ //
+
+ inline shared_base::
+ shared_base ()
+ : counter_ (1)
+ {
+ }
+
+ inline shared_base::
+ shared_base (shared_base const&)
+ : counter_ (1)
+ {
+ }
+
+ inline shared_base& shared_base::
+ operator= (shared_base const&)
+ {
+ return *this;
+ }
+
+ inline void shared_base::
+ _inc_ref ()
+ {
+ counter_++;
+ }
+
+ inline bool shared_base::
+ _dec_ref ()
+ {
+ return --counter_ == 0;
+ }
+
+ inline std::size_t shared_base::
+ _ref_count () const
+ {
+ return counter_;
+ }
+
+ inline void* shared_base::
+ operator new (std::size_t n, share) throw (std::bad_alloc)
+ {
+ return ::operator new (n);
+ }
+
+ inline void shared_base::
+ operator delete (void* p, share) throw ()
+ {
+ ::operator delete (p);
+ }
+
+ inline void shared_base::
+ operator delete (void* p) throw ()
+ {
+ ::operator delete (p);
+ }
+}
diff --git a/cutl/shared-ptr/base.txx b/cutl/shared-ptr/base.txx
new file mode 100644
index 0000000..168fb52
--- /dev/null
+++ b/cutl/shared-ptr/base.txx
@@ -0,0 +1,174 @@
+// file : cutl/shared-ptr/base.txx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#include <cutl/meta/answer.hxx>
+#include <cutl/meta/polymorphic-p.hxx>
+
+namespace cutl
+{
+ namespace bits
+ {
+ // Support for locating the counter in the memory block.
+ //
+ template <typename X, bool poly = meta::polymorphic_p<X>::r>
+ struct locator;
+
+ template <typename X>
+ struct locator<X, false>
+ {
+ static std::size_t*
+ counter (X* x)
+ {
+ std::size_t* p (reinterpret_cast<std::size_t*> (x));
+
+ if (*(--p) != 0xDEADBEEF)
+ throw not_shared ();
+
+ return --p;
+ }
+ };
+
+ template <typename X>
+ struct locator<X, true>
+ {
+ static std::size_t*
+ counter (X* x)
+ {
+ std::size_t* p (
+ static_cast<std::size_t*> (
+ dynamic_cast<void*> (x)));
+
+ if (*(--p) != 0xDEADBEEF)
+ throw not_shared ();
+
+ return --p;
+ }
+ };
+
+ template <typename X>
+ std::size_t*
+ counter (X const* p)
+ {
+ return bits::locator<X>::counter (const_cast<X*> (p));
+ }
+
+ // Counter type and operations.
+ //
+ meta::no test (...);
+ meta::yes test (shared_base*);
+
+ template <typename X,
+ std::size_t A = sizeof (test (reinterpret_cast<X*> (0)))>
+ struct counter_type;
+
+ template <typename X>
+ struct counter_type<X, sizeof (meta::no)>
+ {
+ typedef X r;
+ };
+
+ template <typename X>
+ struct counter_type<X, sizeof (meta::yes)>
+ {
+ typedef shared_base r;
+ };
+
+ template <typename X, typename Y>
+ struct counter_ops;
+
+ template <typename X>
+ struct counter_ops<X, X>
+ {
+ counter_ops (X const* p) : counter_ (p ? bits::counter (p) : 0) {}
+ counter_ops (counter_ops const& x) : counter_ (x.counter_) {}
+
+ template <typename Y>
+ counter_ops (counter_ops<Y, Y> const& x) : counter_ (x.counter_) {}
+
+ counter_ops&
+ operator= (counter_ops const& x)
+ {
+ counter_ = x.counter_;
+ return *this;
+ }
+
+ template <typename Y>
+ counter_ops&
+ operator= (counter_ops<Y, Y> const& x)
+ {
+ counter_ = x.counter_;
+ return *this;
+ }
+
+ void
+ inc (X*)
+ {
+ (*counter_)++;
+ }
+
+ void
+ dec (X* p)
+ {
+ if (--(*counter_) == 0)
+ {
+ p->~X ();
+ operator delete (counter_); // Counter is the top of the memory block.
+ }
+ }
+
+ std::size_t
+ count (X const*) const
+ {
+ return *counter_;
+ }
+
+ std::size_t* counter_;
+ };
+
+ template <typename Y>
+ struct counter_ops<shared_base, Y>
+ {
+ counter_ops (Y const*) {}
+
+ void
+ inc (shared_base* p) {p->_inc_ref ();}
+
+ void
+ dec (Y* p)
+ {
+ if (static_cast<shared_base*> (p)->_dec_ref ())
+ delete p;
+ }
+
+ std::size_t
+ count (shared_base const* p) const {return p->_ref_count ();}
+ };
+ }
+
+ template <typename X>
+ inline X*
+ inc_ref (X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ c.inc (p);
+ return p;
+ }
+
+ template <typename X>
+ inline void
+ dec_ref (X* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ c.dec (p);
+ }
+
+ template <typename X>
+ inline std::size_t
+ ref_count (X const* p)
+ {
+ bits::counter_ops<typename bits::counter_type<X>::r, X> c (p);
+ return c.count (p);
+ }
+}
diff --git a/cutl/static-ptr.hxx b/cutl/static-ptr.hxx
new file mode 100644
index 0000000..12ecc1c
--- /dev/null
+++ b/cutl/static-ptr.hxx
@@ -0,0 +1,75 @@
+// file : cutl/static-ptr.hxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009 Code Synthesis Tools CC
+// license : MIT; see accompanying LICENSE file
+
+#ifndef CUTL_STATIC_PTR_HXX
+#define CUTL_STATIC_PTR_HXX
+
+#include <cstddef> // std::size_t
+
+namespace cutl
+{
+ // This class template implements Jerry Schwarz's static
+ // initialization technique commonly found in iostream
+ // implementations.
+ //
+ // The second template argument is used to make sure the
+ // instantiation of static_ptr is unique.
+ //
+ template <typename X, typename ID>
+ class static_ptr
+ {
+ public:
+ static_ptr ()
+ {
+ if (count_ == 0)
+ x_ = new X;
+
+ ++count_;
+ }
+
+ ~static_ptr ()
+ {
+ if (--count_ == 0)
+ delete x_;
+ }
+
+ private:
+ static_ptr (static_ptr const&);
+
+ static_ptr&
+ operator= (static_ptr const&);
+
+ public:
+ X*
+ operator-> () const
+ {
+ return x_;
+ }
+
+ X&
+ operator* () const
+ {
+ return *x_;
+ }
+
+ X*
+ get () const
+ {
+ return x_;
+ }
+
+ private:
+ static X* x_;
+ static std::size_t count_;
+ };
+
+ template <typename X, typename ID>
+ X* static_ptr<X, ID>::x_ = 0;
+
+ template <typename X, typename ID>
+ std::size_t static_ptr<X, ID>::count_ = 0;
+}
+
+#endif // CUTL_STATIC_PTR_HXX