From cb9ea47e7825b5073d4d645afb94f6326cb7cf4d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 6 Sep 2009 12:52:53 +0200 Subject: Start the libcutl repository --- INSTALL | 28 +++ LICENSE | 21 ++ NEWS | 3 + README | 12 + TODO | 2 + build/bootstrap.make | 51 +++++ build/export/libcutl/stub.make | 10 + build/import/libcutl/LICENSE | 1 + build/import/libcutl/configuration-rules.make | 15 ++ build/import/libcutl/configure | 55 +++++ build/import/libcutl/stub.make | 30 +++ cutl/compiler/context.cxx | 23 ++ cutl/compiler/context.hxx | 70 ++++++ cutl/compiler/context.txx | 85 +++++++ cutl/compiler/traversal.hxx | 155 +++++++++++++ cutl/compiler/traversal.txx | 145 ++++++++++++ cutl/compiler/type-id.hxx | 47 ++++ cutl/compiler/type-id.ixx | 45 ++++ cutl/compiler/type-id.txx | 18 ++ cutl/compiler/type-info.cxx | 31 +++ cutl/compiler/type-info.hxx | 109 +++++++++ cutl/compiler/type-info.ixx | 96 ++++++++ cutl/container/any.hxx | 133 +++++++++++ cutl/container/graph.hxx | 157 +++++++++++++ cutl/container/graph.txx | 315 ++++++++++++++++++++++++++ cutl/container/pointer-iterator.hxx | 127 +++++++++++ cutl/makefile | 47 ++++ cutl/meta/answer.hxx | 25 ++ cutl/meta/class-p.hxx | 27 +++ cutl/meta/polymorphic-p.hxx | 51 +++++ cutl/meta/remove-c.hxx | 27 +++ cutl/meta/remove-cv.hxx | 24 ++ cutl/meta/remove-p.hxx | 27 +++ cutl/meta/remove-v.hxx | 27 +++ cutl/shared-ptr.hxx | 135 +++++++++++ cutl/shared-ptr/base.cxx | 63 ++++++ cutl/shared-ptr/base.hxx | 90 ++++++++ cutl/shared-ptr/base.ixx | 79 +++++++ cutl/shared-ptr/base.txx | 174 ++++++++++++++ cutl/static-ptr.hxx | 75 ++++++ doc/components.txt | 6 + makefile | 42 ++++ tests/compiler/makefile | 18 ++ tests/compiler/traversal/driver.cxx | 135 +++++++++++ tests/compiler/traversal/makefile | 71 ++++++ tests/compiler/traversal/output.std | 16 ++ tests/makefile | 18 ++ tests/shared-ptr/driver.cxx | 186 +++++++++++++++ tests/shared-ptr/makefile | 70 ++++++ version | 1 + 50 files changed, 3218 insertions(+) create mode 100644 INSTALL create mode 100644 LICENSE create mode 100644 NEWS create mode 100644 README create mode 100644 TODO create mode 100644 build/bootstrap.make create mode 100644 build/export/libcutl/stub.make create mode 120000 build/import/libcutl/LICENSE create mode 100644 build/import/libcutl/configuration-rules.make create mode 100755 build/import/libcutl/configure create mode 100644 build/import/libcutl/stub.make create mode 100644 cutl/compiler/context.cxx create mode 100644 cutl/compiler/context.hxx create mode 100644 cutl/compiler/context.txx create mode 100644 cutl/compiler/traversal.hxx create mode 100644 cutl/compiler/traversal.txx create mode 100644 cutl/compiler/type-id.hxx create mode 100644 cutl/compiler/type-id.ixx create mode 100644 cutl/compiler/type-id.txx create mode 100644 cutl/compiler/type-info.cxx create mode 100644 cutl/compiler/type-info.hxx create mode 100644 cutl/compiler/type-info.ixx create mode 100644 cutl/container/any.hxx create mode 100644 cutl/container/graph.hxx create mode 100644 cutl/container/graph.txx create mode 100644 cutl/container/pointer-iterator.hxx create mode 100644 cutl/makefile create mode 100644 cutl/meta/answer.hxx create mode 100644 cutl/meta/class-p.hxx create mode 100644 cutl/meta/polymorphic-p.hxx create mode 100644 cutl/meta/remove-c.hxx create mode 100644 cutl/meta/remove-cv.hxx create mode 100644 cutl/meta/remove-p.hxx create mode 100644 cutl/meta/remove-v.hxx create mode 100644 cutl/shared-ptr.hxx create mode 100644 cutl/shared-ptr/base.cxx create mode 100644 cutl/shared-ptr/base.hxx create mode 100644 cutl/shared-ptr/base.ixx create mode 100644 cutl/shared-ptr/base.txx create mode 100644 cutl/static-ptr.hxx create mode 100644 doc/components.txt create mode 100644 makefile create mode 100644 tests/compiler/makefile create mode 100644 tests/compiler/traversal/driver.cxx create mode 100644 tests/compiler/traversal/makefile create mode 100644 tests/compiler/traversal/output.std create mode 100644 tests/makefile create mode 100644 tests/shared-ptr/driver.cxx create mode 100644 tests/shared-ptr/makefile create mode 100644 version diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..d7ed7e2 --- /dev/null +++ b/INSTALL @@ -0,0 +1,28 @@ +UNIX +---- + +Building on UNIX-like operating systems requires GNU make 3.81 or later. +Most recent GNU/Linux distributions should already have this version +installed. To check the GNU make version run make (or gmake) with the +--version option. + +Unless you are using the libcutl+dep package, you will also need to +install the following dependencies: + + build >= 0.3.4 http://kolpackov.net/projects/build/ + +The libcutl+dep package comes with the necessary dependencies bundled. + +To build the library, tests, and examples simply run make in the root +directory of the package. To run the automated tests, run 'make test'. +To clean the object file, executables, etc., run 'make clean'. To de- +configure the package (that is, remove configuration files in addition +to objects, executables, etc.), run 'make disfigure'. + + +Windows +------- + +Project and solution files for Visual C++ will be provided in the future. +For now, you can create an empty library project and add all the source +files in the cutl/ directory to it. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5306eea --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) Code Synthesis Tools CC, 2009. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..a4e1bbf --- /dev/null +++ b/NEWS @@ -0,0 +1,3 @@ +Version 1.0.0 + + * First public release. diff --git a/README b/README new file mode 100644 index 0000000..d18c36e --- /dev/null +++ b/README @@ -0,0 +1,12 @@ +libcutl is a C++ utility library. It contains a collection of generic and +fairly independent components. See doc/components.txt for an overview. + +See the NEWS file for the user-visible changes from the previous release. + +See the LICENSE file for distribution conditions. + +See the INSTALL file for prerequisites and installation instructions. + +See the doc/ directory for documentation. + +Send questions, bug reports, or any other feedback to boris@codesynthesis.com diff --git a/TODO b/TODO new file mode 100644 index 0000000..25de54b --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +@@ Common exception class (print typeid(*this).name () in what()). +@@ Add memprof? diff --git a/build/bootstrap.make b/build/bootstrap.make new file mode 100644 index 0000000..7720553 --- /dev/null +++ b/build/bootstrap.make @@ -0,0 +1,51 @@ +# file : build/bootstrap.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +project_name := libcutl + +# First try to include the bundled bootstrap.make if it exist. If that +# fails, let make search for the external bootstrap.make. +# +build := build-0.3 + +-include $(dir $(lastword $(MAKEFILE_LIST)))../../$(build)/bootstrap.make + +ifeq ($(patsubst %build/bootstrap.make,,$(lastword $(MAKEFILE_LIST))),) +include $(build)/bootstrap.make +endif + + +# Aliases +# +.PHONY: $(out_base)/ \ + $(out_base)/.test \ + $(out_base)/.install \ + $(out_base)/.dist \ + $(out_base)/.clean + +ifdef %interactive% + +.PHONY: test install dist clean + +test: $(out_base)/.test +install: $(out_base)/.install +dist: $(out_base)/.dist +clean: $(out_base)/.clean + +ifneq ($(filter $(.DEFAULT_GOAL),test install dist clean),) +.DEFAULT_GOAL := +endif + +endif + +# Don't include dependency info for certain targets. +# +define include-dep +$(call -include,$1) +endef + +ifneq ($(filter $(MAKECMDGOALS),clean disfigure),) +include-dep = +endif diff --git a/build/export/libcutl/stub.make b/build/export/libcutl/stub.make new file mode 100644 index 0000000..165d5e0 --- /dev/null +++ b/build/export/libcutl/stub.make @@ -0,0 +1,10 @@ +# file : build/export/libcutl/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +$(call include-once,$(src_root)/cutl/makefile,$(out_root)) + +$(call export,\ + l: $(out_root)/cutl/cutl.l,\ + cpp-options: $(out_root)/cutl/cutl.l.cpp-options) diff --git a/build/import/libcutl/LICENSE b/build/import/libcutl/LICENSE new file mode 120000 index 0000000..5853aae --- /dev/null +++ b/build/import/libcutl/LICENSE @@ -0,0 +1 @@ +../../../LICENSE \ No newline at end of file diff --git a/build/import/libcutl/configuration-rules.make b/build/import/libcutl/configuration-rules.make new file mode 100644 index 0000000..e2fefb7 --- /dev/null +++ b/build/import/libcutl/configuration-rules.make @@ -0,0 +1,15 @@ +# file : build/import/libcutl/configuration-rules.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +$(dcf_root)/import/libcutl/configuration-dynamic.make: | $(dcf_root)/import/libcutl/. + $(call message,,$(scf_root)/import/libcutl/configure $@) + +ifndef %foreign% + +disfigure:: + $(call message,rm $(dcf_root)/import/libcutl/configuration-dynamic.make,\ +rm -f $(dcf_root)/import/libcutl/configuration-dynamic.make) + +endif diff --git a/build/import/libcutl/configure b/build/import/libcutl/configure new file mode 100755 index 0000000..b06e6f5 --- /dev/null +++ b/build/import/libcutl/configure @@ -0,0 +1,55 @@ +#! /usr/bin/env bash + +# file : build/import/libcutl/configure +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + + +# $1 - out file +# +# bld_root - build root +# project_name - project name +# + +source $bld_root/dialog.bash + + +$echo +$echo "Configuring external dependency on 'libcutl' for '$project_name'." +$echo + +$echo +$echo "Would you like to configure dependency on the installed " +$echo "version of 'libcutl' as opposed to the development build?" +$echo + +installed=`read_y_n y` + +path= + +if [ "$installed" = "n" ]; then + +$echo +$echo "Please enter the src_root for 'libcutl'." +$echo + +src_root=`read_path --directory --exist` + +$echo +$echo "Please enter the out_root for 'libcutl'." +$echo + +out_root=`read_path --directory $src_root` + +fi + +echo libcutl_installed := $installed >$1 + +if [ "$installed" = "n" ]; then + +echo src_root := $src_root >>$1 +echo scf_root := \$\(src_root\)/build >>$1 +echo out_root := $out_root >>$1 + +fi diff --git a/build/import/libcutl/stub.make b/build/import/libcutl/stub.make new file mode 100644 index 0000000..15fa9dd --- /dev/null +++ b/build/import/libcutl/stub.make @@ -0,0 +1,30 @@ +# file : build/import/libcutl/stub.make +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +$(call include-once,$(scf_root)/import/libcutl/configuration-rules.make,$(dcf_root)) + +libcutl_installed := + +$(call -include,$(dcf_root)/import/libcutl/configuration-dynamic.make) + +ifdef libcutl_installed + +ifeq ($(libcutl_installed),y) + +$(call export,l: -lcutl,cpp-options: ) + +else + +# Include export stub. +# +$(call include,$(scf_root)/export/libcutl/stub.make) + +endif + +else + +.NOTPARALLEL: + +endif 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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include + +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 +// 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 +#include +#include // std::size_t + +#include + +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 + X& + get (char const* key); + + template + X const& + get (char const* key) const; + + template + X const& + get (char const* key, X const& default_value) const; + + template + void + set (char const* key, X const& value); + + void + remove (char const* key); + + private: + typedef std::map map; + + map map_; + }; + } +} + +#include + +#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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + template + X& context:: + get (char const* key) + { + map::iterator i (map_.find (key)); + + if (i == map_.end ()) + throw no_entry (); + + try + { + return i->second.value (); + } + catch (container::any::typing const&) + { + throw typing (); + } + } + + template + 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 (); + } + catch (container::any::typing const&) + { + throw typing (); + } + } + + template + 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 (); + } + catch (container::any::typing const&) + { + throw typing (); + } + } + + template + void context:: + set (char const* key, X const& value) + { + try + { + std::pair r ( + map_.insert (map::value_type (key, value))); + + if (!r.second) + r.first->second.value () = 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 +// 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 +#include +#include + +#include + +namespace cutl +{ + namespace compiler + { + // + // + template + class traverser + { + public: + virtual + ~traverser (); + + virtual void + trampoline (B&) = 0; + }; + + // + // + template + class traverser_map + { + public: + typedef std::vector*> traversers; + typedef std::map 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& t) + { + traversers& travs (map_[id]); + travs.push_back (&t); + } + + protected: + map_type map_; + }; + + // + // + template + class traverser_impl: public traverser, + public virtual traverser_map + { + public: + typedef X type; + + traverser_impl () + { + add (typeid (type), *this); + } + + virtual void + traverse (type&) = 0; + + public: + virtual void + trampoline (B&); + }; + + // + // + template + class dispatcher: public virtual traverser_map + { + public: + virtual + ~dispatcher (); + + void + traverser (traverser_map&); + + virtual void + dispatch (B&); + + public: + template + static void + iterate_and_dispatch (I begin, I end, dispatcher& d) + { + for (; begin != end; ++begin) + { + d.dispatch (*begin); + } + } + + template + static void + iterate_and_dispatch (I begin, + I end, + dispatcher& 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 level_map; + typedef std::set 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 + +#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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + // traverser + // + template + traverser:: + ~traverser () + { + } + + // traverser_impl + // + + template + void traverser_impl:: + trampoline (B& x) + { + this->traverse (dynamic_cast (x)); + } + + // dispatcher + // + + template + dispatcher:: + ~dispatcher () + { + } + + template + void dispatcher:: + traverser (traverser_map& m) + { + // Copy entries from m to our map. + // + for (typename traverser_map::iterator + i (m.begin ()), e (m.end ()); i != e; ++i) + { + typename traverser_map::traversers& travs (this->map_[i->first]); + + for (typename traverser_map::traversers::const_iterator + t (i->second.begin ()), e (i->second.end ()); t != e; ++t) + { + travs.push_back (*t); + } + } + } + + template + void dispatcher:: + 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::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::traversers const& travs (v->second); + + for (typename traverser_map::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 + std::size_t dispatcher:: + 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 + void dispatcher:: + 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 +// 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 // std::type_info + +namespace cutl +{ + namespace compiler + { + class type_id + { + public: + template + 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 +#include + +#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 +// 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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace compiler + { + template + 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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include + +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 +// 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 +#include +#include // std::type_info + +#include +#include + +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 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 + type_info const& + lookup (X const volatile&); + + template + type_info const& + lookup (); + + void + insert (type_info const&); + + namespace bits + { + struct default_type_info_id {}; + typedef std::map type_info_map; + static static_ptr type_info_map_; + } + } +} + +#include + +#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 +// 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 + inline type_info const& + lookup (X const volatile& x) + { + return lookup (typeid (x)); + } + + template + 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 +// 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 // std::auto_ptr +#include // std::type_info + +namespace cutl +{ + namespace container + { + class any + { + public: + struct typing {}; + + public: + template + any (X const& x) + : holder_ (new holder_impl (x)) + { + } + + any (any const& x) + : holder_ (x.holder_->clone ()) + { + } + + template + any& + operator= (X const& x) + { + holder_.reset (new holder_impl (x)); + return *this; + } + + any& + operator= (any const& x) + { + holder_.reset (x.holder_->clone ()); + return *this; + } + + public: + template + X& + value () + { + if (holder_impl* p = dynamic_cast*> (holder_.get ())) + return p->value (); + else + throw typing (); + } + + template + X const& + value () const + { + if (holder_impl* p = dynamic_cast*> (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 + 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_; + }; + } +} + +#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 +// 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 +#include + +namespace cutl +{ + namespace container + { + template + class graph + { + public: + typedef N node_base; + typedef E edge_base; + + struct no_edge {}; + + public: + template + T& + new_node (); + + template + T& + new_node (A0 const&); + + template + T& + new_node (A0 const&, A1 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&, A8 const&); + + template + T& + new_node (A0 const&, A1 const&, A2 const&, A3 const&, A4 const&, + A5 const&, A6 const&, A7 const&, A8 const&, A9 const&); + + // template + // void + // delete_node (T& node); + + public: + template + T& + new_edge (L&, R&); + + template + T& + new_edge (L&, R&, A0 const&); + + template + T& + new_edge (L&, R&, A0 const&, A1 const&); + + template + T& + new_edge (L&, R&, A0 const&, A1 const&, A2 const&); + + template + T& + new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&); + + template + T& + new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&, + A4 const&); + + template + T& + new_edge (L&, R&, A0 const&, A1 const&, A2 const&, A3 const&, + A4 const&, A5 const&); + + public: + template + void + delete_edge (L&, R&, T& edge); + + public: + graph () {} + + private: + graph (graph const&); + + graph& + operator= (graph const&); + + protected: + typedef shared_ptr node_ptr; + typedef shared_ptr edge_ptr; + + typedef std::map nodes; + typedef std::map edges; + + nodes nodes_; + edges edges_; + }; + } +} + +#include + +#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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +namespace cutl +{ + namespace container + { + + // Nodes. + // + + template + template + T& graph:: + new_node () + { + shared_ptr node (new (shared) T); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& graph:: + new_node (A0 const& a0) + { + shared_ptr node (new (shared) T (a0)); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& graph:: + new_node (A0 const& a0, A1 const& a1) + { + shared_ptr node (new (shared) T (a0, a1)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2) + { + shared_ptr node (new (shared) T (a0, a1, a2)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) + { + shared_ptr node (new (shared) T (a0, a1, a2, a3)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4) + { + shared_ptr node (new (shared) T (a0, a1, a2, a3, a4)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& graph:: + new_node (A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3, + A4 const& a4, A5 const& a5) + { + shared_ptr node (new (shared) T (a0, a1, a2, a3, a4, a5)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& graph:: + 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 node (new (shared) T (a0, a1, a2, a3, a4, a5, a6)); + nodes_[node.get ()] = node; + + return *node; + } + + template + template + T& graph:: + 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 node (new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7)); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& graph:: + 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 node ( + new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7, a8)); + nodes_[node.get ()] = node; + + return *node; + } + + + template + template + T& graph:: + 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 node ( + new (shared) T (a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); + nodes_[node.get ()] = node; + + return *node; + } + + + // Edges. + // + + template + template + T& graph:: + new_edge (L& l, R& r) + { + shared_ptr 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 + template + T& graph:: + new_edge (L& l, R& r, A0 const& a0) + { + shared_ptr 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 + template + T& graph:: + new_edge (L& l, R& r, A0 const& a0, A1 const& a1) + { + shared_ptr 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 + template + T& graph:: + new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2) + { + shared_ptr 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 + template + T& graph:: + new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3) + { + shared_ptr 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 + template + T& graph:: + new_edge (L& l, R& r, A0 const& a0, A1 const& a1, A2 const& a2, + A3 const& a3, A4 const& a4) + { + shared_ptr 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 + template + T& graph:: + 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 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 + template + void graph:: + 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 +// 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 // std::iterator_traits + +#include + +namespace cutl +{ + namespace container + { + template + class pointer_iterator + { + public: + typedef + typename meta::remove_p::value_type>::r + value_type; + + typedef + typename std::iterator_traits::iterator_category + iterator_category; + + typedef + typename std::iterator_traits::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 + inline bool + operator== (pointer_iterator const& a, pointer_iterator const& b) + { + return a.base () == b.base (); + } + + template + inline bool + operator!= (pointer_iterator const& a, pointer_iterator const& b) + { + return a.base () != b.base (); + } + + template + inline typename pointer_iterator::difference_type + operator- (pointer_iterator const& a, pointer_iterator 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 +# 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 +// 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 +// 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 + +namespace cutl +{ + namespace meta + { + template + struct class_p + { + template static no test (...); + template static yes test (void* Y::*); + + static bool const r = sizeof ( + class_p::template test (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 +// 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 +#include + +namespace cutl +{ + namespace meta + { + template + struct polymorphic_p + { + typedef typename remove_cv::r X; + + template + struct impl + { + static const bool r = false; + }; + + template + struct impl + { + struct t1: Y + { + t1 (); + }; + + struct t2: Y + { + t2 (); + + virtual + ~t2 () throw (); + }; + + static const bool r = sizeof (t1) == sizeof (t2); + }; + + static const bool r = impl::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 +// 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 + struct remove_c + { + typedef X r; + }; + + template + struct remove_c + { + 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 +// 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 +#include + +namespace cutl +{ + namespace meta + { + template + struct remove_cv + { + typedef typename remove_v::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 +// 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 + struct remove_p + { + typedef X r; + }; + + template + struct remove_p + { + 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 +// 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 + struct remove_v + { + typedef X r; + }; + + template + struct remove_v + { + 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 +// 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 + +namespace cutl +{ + template + class shared_ptr: bits::counter_ops::r, X> + { + typedef bits::counter_ops::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 + shared_ptr (shared_ptr 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 (*this) = x; + x_ = x.x_; + + if (x_ != 0) + base::inc (x_); + } + + return *this; + } + + template + shared_ptr& + operator= (shared_ptr const& x) + { + if (x_ != x.x_) + { + if (x_ != 0) + base::dec (x_); + + static_cast (*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::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 + 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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include + +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 (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 (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 +// 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 +#include // std::size_t +#include // 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 + inline X* + inc_ref (X*); + + template + inline void + dec_ref (X*); + + template + inline std::size_t + ref_count (X const*); +} + +#include +#include + +#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 +// 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 +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include +#include + +namespace cutl +{ + namespace bits + { + // Support for locating the counter in the memory block. + // + template ::r> + struct locator; + + template + struct locator + { + static std::size_t* + counter (X* x) + { + std::size_t* p (reinterpret_cast (x)); + + if (*(--p) != 0xDEADBEEF) + throw not_shared (); + + return --p; + } + }; + + template + struct locator + { + static std::size_t* + counter (X* x) + { + std::size_t* p ( + static_cast ( + dynamic_cast (x))); + + if (*(--p) != 0xDEADBEEF) + throw not_shared (); + + return --p; + } + }; + + template + std::size_t* + counter (X const* p) + { + return bits::locator::counter (const_cast (p)); + } + + // Counter type and operations. + // + meta::no test (...); + meta::yes test (shared_base*); + + template (0)))> + struct counter_type; + + template + struct counter_type + { + typedef X r; + }; + + template + struct counter_type + { + typedef shared_base r; + }; + + template + struct counter_ops; + + template + struct counter_ops + { + counter_ops (X const* p) : counter_ (p ? bits::counter (p) : 0) {} + counter_ops (counter_ops const& x) : counter_ (x.counter_) {} + + template + counter_ops (counter_ops const& x) : counter_ (x.counter_) {} + + counter_ops& + operator= (counter_ops const& x) + { + counter_ = x.counter_; + return *this; + } + + template + counter_ops& + operator= (counter_ops 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 + struct counter_ops + { + counter_ops (Y const*) {} + + void + inc (shared_base* p) {p->_inc_ref ();} + + void + dec (Y* p) + { + if (static_cast (p)->_dec_ref ()) + delete p; + } + + std::size_t + count (shared_base const* p) const {return p->_ref_count ();} + }; + } + + template + inline X* + inc_ref (X* p) + { + bits::counter_ops::r, X> c (p); + c.inc (p); + return p; + } + + template + inline void + dec_ref (X* p) + { + bits::counter_ops::r, X> c (p); + c.dec (p); + } + + template + inline std::size_t + ref_count (X const* p) + { + bits::counter_ops::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 +// 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 // 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 + 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 + X* static_ptr::x_ = 0; + + template + std::size_t static_ptr::count_ = 0; +} + +#endif // CUTL_STATIC_PTR_HXX diff --git a/doc/components.txt b/doc/components.txt new file mode 100644 index 0000000..cdb1920 --- /dev/null +++ b/doc/components.txt @@ -0,0 +1,6 @@ +Components + + core: meta/ shared-ptr/ shared-ptr.hxx + container: container/ + compiler: compiler/ + diff --git a/makefile b/makefile new file mode 100644 index 0000000..5d90ad8 --- /dev/null +++ b/makefile @@ -0,0 +1,42 @@ +# file : makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make + +default := $(out_base)/ +test := $(out_base)/.test +install := $(out_base)/.install +dist := $(out_base)/.dist +clean := $(out_base)/.clean + +# Build. +# +$(default): $(out_base)/cutl/ $(out_base)/tests/ + +# Test. +# +$(test): $(out_base)/tests/.test + +# Install. +# +$(install): $(out_base)/cutl/.install \ + $(out_base)/doc/.install + $(call install-data,$(src_base)/LICENSE,$(install_doc_dir)/libcutl/LICENSE) + $(call install-data,$(src_base)/NEWS,$(install_doc_dir)/libcutl/NEWS) + $(call install-data,$(src_base)/README,$(install_doc_dir)/libcutl/README) + +# Dist. +# + +# @@ TODO + +# Clean. +# +$(clean): $(out_base)/cutl/.clean $(out_base)/tests/.clean + +$(call include,$(bld_root)/install.make) + +$(call import,$(src_base)/cutl/makefile) +$(call import,$(src_base)/tests/makefile) diff --git a/tests/compiler/makefile b/tests/compiler/makefile new file mode 100644 index 0000000..5a63fc8 --- /dev/null +++ b/tests/compiler/makefile @@ -0,0 +1,18 @@ +# file : tests/compiler/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +tests := traversal + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/compiler/traversal/driver.cxx b/tests/compiler/traversal/driver.cxx new file mode 100644 index 0000000..8d49b6f --- /dev/null +++ b/tests/compiler/traversal/driver.cxx @@ -0,0 +1,135 @@ +// file : tests/compiler/traversal/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include +#include + +#include + +#include +#include + +using namespace std; +using namespace cutl; + +// Data types. +// +struct base +{ + virtual ~base () {} +}; + +struct derived1: base {}; +struct derived2: base {}; + +typedef vector > objects; + +struct init +{ + init () + { + using compiler::type_info; + + { + type_info ti (typeid (base)); + insert (ti); + } + + { + type_info ti (typeid (derived1)); + ti.add_base (typeid (base)); + insert (ti); + } + + { + type_info ti (typeid (derived2)); + ti.add_base (typeid (base)); + insert (ti); + } + } +} init_; + +// Traversers. +// +template +struct traverser: compiler::traverser_impl, + virtual compiler::dispatcher +{ +}; + +typedef traverser base_trav; +typedef traverser derived1_trav; +typedef traverser derived2_trav; + +struct base_impl: base_trav +{ + virtual void + traverse (type&) + { + cout << "base_impl: base" << endl; + } +}; + +struct derived1_impl: derived1_trav +{ + virtual void + traverse (type&) + { + cout << "derived1_impl: derived1" << endl; + } +}; + +struct combined_impl: derived1_trav, derived2_trav +{ + virtual void + traverse (derived1&) + { + cout << "combined_impl: derived1" << endl; + } + + virtual void + traverse (derived2&) + { + cout << "combined_impl: derived2" << endl; + } +}; + +int +main () +{ + objects o; + o.push_back (shared_ptr (new (shared) base)); + o.push_back (shared_ptr (new (shared) derived1)); + o.push_back (shared_ptr (new (shared) derived2)); + + base_impl base; + derived1_impl derived1; + combined_impl combined; + + for (objects::iterator i (o.begin ()); i != o.end (); ++i) + base.dispatch (**i); + + cout << endl; + + for (objects::iterator i (o.begin ()); i != o.end (); ++i) + derived1.dispatch (**i); + + cout << endl; + + for (objects::iterator i (o.begin ()); i != o.end (); ++i) + combined.dispatch (**i); + + cout << endl; + + base.traverser (derived1); + for (objects::iterator i (o.begin ()); i != o.end (); ++i) + base.dispatch (**i); + + cout << endl; + + derived1.traverser (combined); + for (objects::iterator i (o.begin ()); i != o.end (); ++i) + derived1.dispatch (**i); +} diff --git a/tests/compiler/traversal/makefile b/tests/compiler/traversal/makefile new file mode 100644 index 0000000..bb5513a --- /dev/null +++ b/tests/compiler/traversal/makefile @@ -0,0 +1,71 @@ +# file : tests/compiler/traversal/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../../build/bootstrap.make + +cxx_tun := driver.cxx + +# +# +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cutl.l := $(out_root)/cutl/cutl.l +cutl.l.cpp-options := $(out_root)/cutl/cutl.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(cxx_obj) $(cutl.l) +$(cxx_obj) $(cxx_od): $(cutl.l.cpp-options) + + +$(call include-dep,$(cxx_od)) + + +# Alias for default target. +# +$(out_base)/: $(driver) + + +# Test. +# +$(test): driver := $(driver) +$(test): $(driver) $(src_base)/output.std + $(call message,test $$1,$$1 | diff -u $(src_base)/output.std -,$(driver)) + + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cutl/makefile) diff --git a/tests/compiler/traversal/output.std b/tests/compiler/traversal/output.std new file mode 100644 index 0000000..095739c --- /dev/null +++ b/tests/compiler/traversal/output.std @@ -0,0 +1,16 @@ +base_impl: base +base_impl: base +base_impl: base + +derived1_impl: derived1 + +combined_impl: derived1 +combined_impl: derived2 + +base_impl: base +derived1_impl: derived1 +base_impl: base + +derived1_impl: derived1 +combined_impl: derived1 +combined_impl: derived2 diff --git a/tests/makefile b/tests/makefile new file mode 100644 index 0000000..ffbd8bd --- /dev/null +++ b/tests/makefile @@ -0,0 +1,18 @@ +# file : tests/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make + +tests := compiler shared-ptr + +default := $(out_base)/ +test := $(out_base)/.test +clean := $(out_base)/.clean + +$(default): $(addprefix $(out_base)/,$(addsuffix /,$(tests))) +$(test): $(addprefix $(out_base)/,$(addsuffix /.test,$(tests))) +$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(tests))) + +$(foreach t,$(tests),$(call import,$(src_base)/$t/makefile)) diff --git a/tests/shared-ptr/driver.cxx b/tests/shared-ptr/driver.cxx new file mode 100644 index 0000000..c32192e --- /dev/null +++ b/tests/shared-ptr/driver.cxx @@ -0,0 +1,186 @@ +// file : tests/shared-ptr/driver.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2009 Code Synthesis Tools CC +// license : MIT; see accompanying LICENSE file + +#include +#include + +#include + +using namespace cutl; + +struct type +{ + type (int x, char const* y) : x_ (x), y_ (y) {} + + int x_; + std::string y_; +}; + +struct base1 +{ + virtual + ~base1 () {} + base1 (int x) : x_ (x) {} + + int x_; +}; + +struct base2 +{ + virtual + ~base2 () {} + base2 (char const* y) : y_ (y) {} + + std::string y_; +}; + +struct derived: base1, base2 +{ + derived (int x, char const* y) : base1 (x), base2 (y) {} +}; + +struct shared_type: shared_base +{ + shared_type (int x, char const* y) + : x_ (x), y_ (y) + { + assert (ref_count (this) == 1); + } + + int x_; + std::string y_; +}; + +int +main () +{ + // + // inc_ref, dec_ref, ref_count + // + + // Non-polymorphic type. + // + { + type* x (new (shared) type (5, "foo")); + assert (ref_count (x) == 1); + inc_ref (x); + assert (ref_count (x) == 2); + dec_ref (x); + assert (ref_count (x) == 1); + dec_ref (x); + } + + // Polymorphic type. + // + { + base2* x (new (shared) derived (5, "foo")); + assert (ref_count (x) == 1); + inc_ref (x); + assert (ref_count (x) == 2); + dec_ref (x); + assert (ref_count (x) == 1); + dec_ref (x); + } + + // Shared type. + // + { + shared_type* x (new (shared) shared_type (5, "foo")); + assert (ref_count (x) == 1); + inc_ref (x); + assert (ref_count (x) == 2); + dec_ref (x); + assert (ref_count (x) == 1); + dec_ref (x); + } + + // Error handling (this theoretically can segfault). + // + { + type* x (new type (5, "foo")); + + try + { + inc_ref (x); + assert (false); + } + catch (not_shared const&) + { + } + + delete x; + } + + // + // shared_ptr + // + + // Non-polymorphic type. + // + { + shared_ptr x (new (shared) type (5, "foo")); + assert (x.count () == 1); + assert (x); + assert (x->x_ == 5); + assert ((*x).y_ == "foo"); + { + shared_ptr y (x); + assert (y.count () == 2); + } + { + shared_ptr y; + y = x; + assert (y.count () == 2); + } + assert (x.count () == 1); + shared_ptr y (x.release ()); + assert (y.count () == 1); + } + + // Polymorphic type. + // + { + shared_ptr x (new (shared) derived (5, "foo")); + assert (x.count () == 1); + { + shared_ptr y (x); + assert (y.count () == 2); + assert (y->y_ == "foo"); + } + { + shared_ptr y; + y = x; + assert (y.count () == 2); + } + assert (x.count () == 1); + } + + // Non-polymorphic type. + // + { + shared_ptr x (new (shared) shared_type (5, "foo")); + assert (x.count () == 1); + assert (x); + assert (x->x_ == 5); + assert ((*x).y_ == "foo"); + assert (x->_ref_count () == 1); + x->_inc_ref (); + assert (x.count () == 2); + x->_dec_ref (); + assert (x.count () == 1); + { + shared_ptr y (x); + assert (y.count () == 2); + } + { + shared_ptr y; + y = x; + assert (y.count () == 2); + } + assert (x.count () == 1); + shared_ptr y (x.release ()); + assert (y.count () == 1); + } +} diff --git a/tests/shared-ptr/makefile b/tests/shared-ptr/makefile new file mode 100644 index 0000000..43e9b53 --- /dev/null +++ b/tests/shared-ptr/makefile @@ -0,0 +1,70 @@ +# file : tests/shared-ptr/makefile +# author : Boris Kolpackov +# copyright : Copyright (c) 2009 Code Synthesis Tools CC +# license : MIT; see accompanying LICENSE file + +include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make + +cxx_tun := driver.cxx + +# +# +cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) +cxx_od := $(cxx_obj:.o=.o.d) + +cutl.l := $(out_root)/cutl/cutl.l +cutl.l.cpp-options := $(out_root)/cutl/cutl.l.cpp-options + +driver := $(out_base)/driver +test := $(out_base)/.test +clean := $(out_base)/.clean + +# Build. +# +$(driver): $(cxx_obj) $(cutl.l) +$(cxx_obj) $(cxx_od): $(cutl.l.cpp-options) + + +$(call include-dep,$(cxx_od)) + + +# Alias for default target. +# +$(out_base)/: $(driver) + + +# Test. +# +$(test): $(driver) + $(call message,test $<,$<) + + +# Clean. +# +$(clean): \ + $(driver).o.clean \ + $(addsuffix .cxx.clean,$(cxx_obj)) \ + $(addsuffix .cxx.clean,$(cxx_od)) + + +# Generated .gitignore. +# +ifeq ($(out_base),$(src_base)) +$(driver): | $(out_base)/.gitignore + +$(out_base)/.gitignore: files := driver +$(clean): $(out_base)/.gitignore.clean + +$(call include,$(bld_root)/git/gitignore.make) +endif + + +# How to. +# +$(call include,$(bld_root)/cxx/o-e.make) +$(call include,$(bld_root)/cxx/cxx-o.make) +$(call include,$(bld_root)/cxx/cxx-d.make) + +# Dependencies. +# +$(call import,$(src_root)/cutl/makefile) diff --git a/version b/version new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/version @@ -0,0 +1 @@ +1.0.0 -- cgit v1.1