diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2011-02-04 13:56:09 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2011-02-04 13:56:09 +0200 |
commit | f1c2a621ac2695dfe4a3bc71dbc9ce3079008d2f (patch) | |
tree | d0c45ecd5489cd1b4beb57fc5afda3263ad0d2b2 | |
parent | 6a07b88cdf6419440b19e7b7dbc9231519c32c62 (diff) |
Add support for smart-ptr, unordered, and date_time (basic)
25 files changed, 1768 insertions, 44 deletions
@@ -2,6 +2,7 @@ Prerequisites ============= - libodb http://www.codesynthesis.com/products/odb/ + - boost http://www.boost.org Building on UNIX @@ -21,19 +22,22 @@ To see the available configuration options run configure with --help: ./configure --help -The configure script expects the libodb headers and libraries to -be installed in a directory where the C++ compiler and linker will -search for them by default (normally /usr and /usr/local). If libodb -is installed in another directory, you can use the CPPFLAGS and -LDFLAGS configure variables to specify its location, for example: +The configure script expects the libodb and boost headers and libraries +to be installed in a directory where the C++ compiler and linker will +search for them by default (normally /usr and /usr/local). If these +libraries are installed in other directories, you can use the CPPFLAGS +and LDFLAGS configure variables to specify their locations, for example: ./configure CPPFLAGS=-I/opt/libodb/include LDFLAGS=-L/opt/libodb/lib -If libodb is not installed and you would like to use its build -directory instead, you can use the --with-libodb configure option -to specify its location, for example: +If these libraries are not installed and you would like to use their +build directories instead, you can use the --with-libodb, and +--with-boost configure options to specify their locations, for example: -./configure --with-libodb=/tmp/libodb +./configure --with-boost=/tmp/boost + +For the boost build directory the configure script expects to find the +boost libraries in the stage/lib/ subdirectory. As another example, the following configure command only builds shared libraries, uses the specified C++ compiler, and compiles with optimization @@ -60,10 +64,11 @@ Studio. If you would like to build libodb-boost with GCC either using Cygwin or MinGW, refer to the "Building on UNIX" section above. The standard Visual Studio project and solution files are used on this -platform. The provided project files expect the libodb header and import -library directories to be in the VC++ Directories Include and Library -search lists. See the INSTALL file in the libodb package for more -information on how to setup the VC++ Directories. +platform. The provided project files expect the libodb and boost header +and import library directories to be in the VC++ Directories Include and +Library search lists. For libodb, see the INSTALL file in the package +directory for more information on how to setup the VC++ Directories. For +boost, refer to the boost documentation. To build libodb-boost, unpack the source code archive and open the libodb-boost-vc<N>.sln file located in the libodb-boost package diff --git a/Makefile.am b/Makefile.am index 172c374..2d1198a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,5 +8,7 @@ dist_doc_DATA = __file__(docs) EXTRA_DIST = __file__(extra_dist) ACLOCAL_AMFLAGS = -I m4 +nobase_include_HEADERS = __path__(options) + pkgconfigdir = @pkgconfigdir@ pkgconfig_DATA= libodb-boost.pc diff --git a/configure.ac b/configure.ac index e2834da..0060d99 100644 --- a/configure.ac +++ b/configure.ac @@ -28,9 +28,14 @@ LT_OUTPUT # THREADS +# Check for boost. +# +LIBBOOST([],[AC_MSG_ERROR([boost is not found; consider using CPPFLAGS/LDFLAGS or --with-boost=DIR to specify its location])]) +LIBBOOST_SYSTEM + # Check for libodb. # -LIBODB([],[AC_MSG_ERROR([libodb is not found; consider using --with-libodb=DIR])]) +LIBODB([], [AC_MSG_ERROR([libodb is not found; consider using --with-libodb=DIR])]) # Define LIBODB_BOOST_STATIC_LIB if we are build static library on certain # platforms. diff --git a/m4/libboost.m4 b/m4/libboost.m4 new file mode 100644 index 0000000..6ce9d79 --- /dev/null +++ b/m4/libboost.m4 @@ -0,0 +1,186 @@ +dnl file : m4/libboost.m4 +dnl author : Boris Kolpackov <boris@codesynthesis.com> +dnl copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +dnl license : GNU GPL v2; see accompanying LICENSE file +dnl +dnl LIBBOOST([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +dnl +AC_DEFUN([LIBBOOST], [ +libboost_found=no + +AC_MSG_CHECKING([for boost base headers]) + +AC_ARG_WITH( + [boost], + [AC_HELP_STRING([--with-boost=DIR],[location of boost build directory])], + [libboost_dir=${withval}], + [libboost_dir=]) + +# If libboost_dir was given, add the necessary preprocessor and linker flags. +# +if test x"$libboost_dir" != x; then + save_CPPFLAGS="$CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + + AS_SET_CATFILE([abs_libboost_dir], [$ac_pwd], [$libboost_dir]) + + CPPFLAGS="$CPPFLAGS -I$abs_libboost_dir" + LDFLAGS="$LDFLAGS -L$abs_libboost_dir/stage/lib" +fi + +CXX_LIBTOOL_LINK_IFELSE( +AC_LANG_SOURCE([[ +#include <boost/version.hpp> + +#ifndef BOOST_VERSION +# error BOOST_VERSION not defined +#endif + +int +main () +{ +} +]]), +[ +libboost_found=yes +]) + +if test x"$libboost_found" = xno; then + if test x"$libboost_dir" != x; then + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + fi +fi + +if test x"$libboost_found" = xyes; then + AC_MSG_RESULT([yes]) + $1 +else + AC_MSG_RESULT([no]) + $2 +fi +])dnl +dnl +dnl LIBBOOST_HEADER_LIB(NAME, SOURCE, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +dnl +AC_DEFUN([LIBBOOST_HEADER_LIB], [ +libboost_$1_found=no + +AC_MSG_CHECKING([for boost $1 library]) +CXX_LIBTOOL_LINK_IFELSE([$2],[libboost_$1_found=yes]) + +if test x"$libboost_$1_found" = xyes; then + AC_MSG_RESULT([yes]) + [$3] +else + AC_MSG_RESULT([no]) + [$4] +fi +])dnl +dnl +dnl LIBBOOST_LIB(NAME, SOURCE, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +dnl +AC_DEFUN([LIBBOOST_LIB], [ +libboost_$1_found=no + +AC_MSG_CHECKING([for boost $1 library]) + +save_LIBS="$LIBS" +LIBS="-lboost_$1 $LIBS" + +CXX_LIBTOOL_LINK_IFELSE([$2],[libboost_$1_found=yes]) + +# Try to fall back on the -mt version for backwards-compatibility. +# +if test x"$libboost_$1_found" = xno; then + LIBS="-lboost_$1-mt $save_LIBS" + CXX_LIBTOOL_LINK_IFELSE([$2],[libboost_$1_found=yes]) +fi + +if test x"$libboost_$1_found" = xno; then + LIBS="$save_LIBS" +fi + +if test x"$libboost_$1_found" = xyes; then + AC_MSG_RESULT([yes]) + [$3] +else + AC_MSG_RESULT([no]) + [$4] +fi +])dnl +dnl +dnl LIBBOOST_SMART_PTR([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([LIBBOOST_SMART_PTR], [ +LIBBOOST_HEADER_LIB([smart_ptr], +AC_LANG_SOURCE([[ +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +int +main () +{ + boost::shared_ptr<int> sp (new int (10)); + boost::weak_ptr<int> wp (sp); +} +]]), +[$1], +[$2]) +])dnl +dnl +dnl LIBBOOST_UNORDERED([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([LIBBOOST_UNORDERED], [ +LIBBOOST_HEADER_LIB([unordered], +AC_LANG_SOURCE([[ +#include <boost/unordered_set.hpp> +#include <boost/unordered_map.hpp> + +int +main () +{ + boost::unordered_set<int> s; + boost::unordered_map<int, int> m; + + s.insert (1); + return m.find (1) != m.end (); +} +]]), +[$1], +[$2]) +])dnl +dnl +dnl LIBBOOST_SYSTEM([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([LIBBOOST_SYSTEM], [ +LIBBOOST_LIB([system], +AC_LANG_SOURCE([[ +int +main () +{ +} +]]), +[$1], +[$2]) +])dnl +dnl +dnl LIBBOOST_DATE_TIME([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([LIBBOOST_DATE_TIME], [ +LIBBOOST_LIB([date_time], +AC_LANG_SOURCE([[ +#include <boost/date_time/gregorian/gregorian.hpp> + +int +main () +{ + boost::gregorian::greg_month m (1); + const char* s (m.as_short_string ()); + return s == 0; +} +]]), +[$1], +[$2]) +])dnl @@ -15,13 +15,14 @@ $(default): $(addprefix $(out_base)/,$(addsuffix /,$(dirs))) $(dist): export dirs := $(dirs) $(dist): export docs := GPLv2 LICENSE README NEWS version +$(dist): export options := odb/boost.options $(dist): data_dist := INSTALL libodb-boost-vc9.sln libodb-boost-vc10.sln $(dist): exec_dist := bootstrap $(dist): export extra_dist := $(data_dist) $(exec_dist) $(dist): export version = $(shell cat $(src_root)/version) $(dist): $(addprefix $(out_base)/,$(addsuffix /.dist,$(dirs))) - $(call dist-data,$(docs) $(data_dist) libodb-boost.pc.in) + $(call dist-data,$(docs) $(options) $(data_dist) libodb-boost.pc.in) $(call dist-exec,$(exec_dist)) $(call dist-dir,m4) $(call meta-automake) diff --git a/odb/boost.options b/odb/boost.options new file mode 100644 index 0000000..bd77262 --- /dev/null +++ b/odb/boost.options @@ -0,0 +1,8 @@ +# file : odb/boost.options +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +--profile boost/smart-ptr +--profile boost/unordered +--profile boost/date-time diff --git a/odb/boost/Makefile.am b/odb/boost/Makefile.am index 55d7816..710f3b7 100644 --- a/odb/boost/Makefile.am +++ b/odb/boost/Makefile.am @@ -7,7 +7,7 @@ lib_LTLIBRARIES = libodb-boost.la libodb_boost_la_SOURCES = __path__(sources) odbboostincludedir = $(includedir)/odb/boost/ -nobase_odbboostinclude_HEADERS = __path__(headers) +nobase_odbboostinclude_HEADERS = __path__(headers) __path__(options) nobase_nodist_odbboostinclude_HEADERS = details/config.h EXTRA_DIST = __file__(extra_dist) diff --git a/odb/boost/date-time.options b/odb/boost/date-time.options new file mode 100644 index 0000000..d545a62 --- /dev/null +++ b/odb/boost/date-time.options @@ -0,0 +1,6 @@ +# file : odb/boost/date-time.options +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +--profile boost/date-time/gregorian diff --git a/odb/boost/date-time/exceptions.cxx b/odb/boost/date-time/exceptions.cxx new file mode 100644 index 0000000..abde353 --- /dev/null +++ b/odb/boost/date-time/exceptions.cxx @@ -0,0 +1,21 @@ +// file : odb/boost/date-time/exceptions.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <odb/boost/date-time/exceptions.hxx> + +namespace odb +{ + namespace boost + { + namespace date_time + { + const char* special_value:: + what () const throw () + { + return "unrepresentable date/time special value"; + } + } + } +} diff --git a/odb/boost/date-time/exceptions.hxx b/odb/boost/date-time/exceptions.hxx new file mode 100644 index 0000000..8fd58b8 --- /dev/null +++ b/odb/boost/date-time/exceptions.hxx @@ -0,0 +1,31 @@ +// file : odb/boost/date-time/exceptions.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_DATE_TIME_EXCEPTIONS_HXX +#define ODB_BOOST_DATE_TIME_EXCEPTIONS_HXX + +#include <odb/pre.hxx> + +#include <odb/boost/exception.hxx> +#include <odb/boost/details/export.hxx> + +namespace odb +{ + namespace boost + { + namespace date_time + { + struct LIBODB_BOOST_EXPORT special_value: odb::boost::exception + { + virtual const char* + what () const throw (); + }; + } + } +} + +#include <odb/post.hxx> + +#endif // ODB_BOOST_DATE_TIME_EXCEPTIONS_HXX diff --git a/odb/boost/date-time/gregorian.options b/odb/boost/date-time/gregorian.options new file mode 100644 index 0000000..f320005 --- /dev/null +++ b/odb/boost/date-time/gregorian.options @@ -0,0 +1,9 @@ +# file : odb/boost/date-time/gregorian.options +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +--profile boost/version + +--odb-epilogue '#include <odb/boost/date-time/mysql/gregorian-mapping.hxx>' +--hxx-prologue '#include <odb/boost/date-time/mysql/gregorian-traits.hxx>' diff --git a/odb/boost/date-time/mysql/gregorian-mapping.hxx b/odb/boost/date-time/mysql/gregorian-mapping.hxx new file mode 100644 index 0000000..add14ba --- /dev/null +++ b/odb/boost/date-time/mysql/gregorian-mapping.hxx @@ -0,0 +1,19 @@ +// file : odb/boost/date-time/mysql/gregorian-mapping.hxx +// author : Constantin Michael <constantin@codesynthesis.com> +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_DATE_TIME_MYSQL_GREGORIAN_MAPPING_HXX +#define ODB_BOOST_DATE_TIME_MYSQL_GREGORIAN_MAPPING_HXX + +#include <boost/date_time/gregorian/gregorian_types.hpp> + +// By default map boost::gregorian::date to MySQL DATE. We use the +// NULL value to represent not_a_date_time. In MYSQL "zero" date +// plays the special value role but this value is not treated as +// special by gregorian::date. +// +#pragma db value(boost::gregorian::date) type("DATE") + +#endif // ODB_BOOST_DATE_TIME_MYSQL_GREGORIAN_MAPPING_HXX diff --git a/odb/boost/date-time/mysql/gregorian-traits.hxx b/odb/boost/date-time/mysql/gregorian-traits.hxx new file mode 100644 index 0000000..d907aef --- /dev/null +++ b/odb/boost/date-time/mysql/gregorian-traits.hxx @@ -0,0 +1,64 @@ +// file : odb/boost/date-time/mysql/gregorian-traits.hxx +// author : Constantin Michael <constantin@codesynthesis.com> +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_DATE_TIME_MYSQL_GREGORIAN_TRAITS_HXX +#define ODB_BOOST_DATE_TIME_MYSQL_GREGORIAN_TRAITS_HXX + +#include <odb/pre.hxx> + +#include <boost/date_time/gregorian/gregorian_types.hpp> + +#include <odb/core.hxx> +#include <odb/mysql/traits.hxx> +#include <odb/boost/date-time/exceptions.hxx> + +namespace odb +{ + namespace mysql + { + template <> + class value_traits< ::boost::gregorian::date, MYSQL_TIME, id_date> + { + public: + typedef ::boost::gregorian::date date; + typedef date value_type; + typedef date query_type; + typedef MYSQL_TIME image_type; + + static void + set_value (date& v, const MYSQL_TIME& i, bool is_null) + { + if (is_null) + v = date (::boost::date_time::not_a_date_time); + else + v = date (i.year, i.month, i.day); + } + + static void + set_image (MYSQL_TIME& i, bool& is_null, const date& v) + { + if (v.is_special ()) + { + if (v.is_not_a_date ()) + is_null = true; + else + throw odb::boost::date_time::special_value (); + } + else + { + is_null = false; + i.year = v.year (); + i.month = v.month (); + i.day = v.day (); + } + } + }; + } +} + +#include <odb/post.hxx> + +#endif // ODB_BOOST_DATE_TIME_MYSQL_GREGORIAN_TRAITS_HXX diff --git a/odb/boost/exceptions.hxx b/odb/boost/exception.hxx index 5e5b18c..96eb5df 100644 --- a/odb/boost/exceptions.hxx +++ b/odb/boost/exception.hxx @@ -1,10 +1,10 @@ -// file : odb/boost/exceptions.hxx +// file : odb/boost/exception.hxx // author : Boris Kolpackov <boris@codesynthesis.com> // copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file -#ifndef ODB_BOOST_EXCEPTIONS_HXX -#define ODB_BOOST_EXCEPTIONS_HXX +#ifndef ODB_BOOST_EXCEPTION_HXX +#define ODB_BOOST_EXCEPTION_HXX #include <odb/pre.hxx> @@ -16,14 +16,14 @@ namespace odb { namespace boost { - struct LIBODB_BOOST_EXPORT dummy_exception: odb::exception + struct LIBODB_BOOST_EXPORT exception: odb::exception { virtual const char* - what () const throw (); + what () const throw () = 0; }; } } #include <odb/post.hxx> -#endif // ODB_BOOST_EXCEPTIONS_HXX +#endif // ODB_BOOST_EXCEPTION_HXX diff --git a/odb/boost/exceptions.cxx b/odb/boost/exceptions.cxx deleted file mode 100644 index 038efe4..0000000 --- a/odb/boost/exceptions.cxx +++ /dev/null @@ -1,20 +0,0 @@ -// file : odb/boost/exceptions.cxx -// author : Boris Kolpackov <boris@codesynthesis.com> -// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC -// license : GNU GPL v2; see accompanying LICENSE file - -#include <odb/boost/exceptions.hxx> - -using namespace std; - -namespace odb -{ - namespace boost - { - const char* dummy_exception:: - what () const throw () - { - return "dummy exception"; - } - } -} diff --git a/odb/boost/makefile b/odb/boost/makefile index 521fb62..d028a10 100644 --- a/odb/boost/makefile +++ b/odb/boost/makefile @@ -5,7 +5,7 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../../build/bootstrap.make -cxx := exceptions.cxx +cxx := date-time/exceptions.cxx cxx_tun := $(cxx) cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) @@ -54,13 +54,15 @@ $(out_base)/: $(odb_boost.l) $(dist): export sources := $(cxx) $(dist): export headers = $(subst $(src_base)/,,$(shell find $(src_base) \ -name '*.hxx' -o -name '*.ixx' -o -name '*.txx')) +$(dist): export options = $(subst $(src_base)/,,$(shell find $(src_base) \ +-name '*.options')) $(dist): export extra_dist := libodb-boost-vc9.vcproj \ libodb-boost-vc10.vcxproj libodb-boost-vc10.vcxproj.filters $(dist): export interface_version = $(shell sed -e \ 's/^\([0-9]*\.[0-9]*\).*/\1/' $(src_root)/version) $(dist): - $(call dist-data,$(sources) $(headers) details/config.h.in) + $(call dist-data,$(sources) $(headers) $(options) details/config.h.in) $(call meta-vc9proj,libodb-boost-vc9.vcproj) $(call meta-vc10proj,libodb-boost-vc10.vcxproj) $(call meta-automake) diff --git a/odb/boost/smart-ptr.options b/odb/boost/smart-ptr.options new file mode 100644 index 0000000..9e4e41b --- /dev/null +++ b/odb/boost/smart-ptr.options @@ -0,0 +1,16 @@ +# file : odb/boost/smart-ptr.options +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +--profile boost/version + +# Make boost::shared_ptr the default object pointer. +# +--hxx-prologue '#include <boost/shared_ptr.hpp>' +--default-pointer ::boost::shared_ptr + +# Include pointer traits. +# +--odb-epilogue '#include <odb/boost/smart-ptr/pointer-traits.hxx>' +--hxx-prologue '#include <odb/boost/smart-ptr/pointer-traits.hxx>' diff --git a/odb/boost/smart-ptr/lazy-pointer-traits.hxx b/odb/boost/smart-ptr/lazy-pointer-traits.hxx new file mode 100644 index 0000000..d7a9428 --- /dev/null +++ b/odb/boost/smart-ptr/lazy-pointer-traits.hxx @@ -0,0 +1,63 @@ +// file : odb/boost/smart-ptr/lazy-pointer-traits.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_SMART_PTR_LAZY_POINTER_TRAITS_HXX +#define ODB_BOOST_SMART_PTR_LAZY_POINTER_TRAITS_HXX + +#include <odb/pre.hxx> + +#include <odb/pointer-traits.hxx> +#include <odb/boost/smart-ptr/lazy-ptr.hxx> + +namespace odb +{ + template <typename T> + class pointer_traits<boost::lazy_shared_ptr<T> > + { + public: + static pointer_kind const kind = pk_shared; + static bool const lazy = true; + + typedef T element_type; + typedef boost::lazy_shared_ptr<element_type> pointer_type; + typedef ::boost::shared_ptr<element_type> eager_pointer_type; + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + template <class O /* = T */> + static typename object_traits<O>::id_type + object_id (const pointer_type& p) + { + return p.object_id<O> (); + } + }; + + template <typename T> + class pointer_traits<boost::lazy_weak_ptr<T> > + { + public: + static pointer_kind const kind = pk_weak; + static bool const lazy = true; + + typedef T element_type; + typedef boost::lazy_weak_ptr<element_type> pointer_type; + typedef boost::lazy_shared_ptr<element_type> strong_pointer_type; + typedef ::boost::weak_ptr<element_type> eager_pointer_type; + + static strong_pointer_type + lock (const pointer_type& p) + { + return p.lock (); + } + }; +} + +#include <odb/post.hxx> + +#endif // ODB_BOOST_SMART_PTR_LAZY_POINTER_TRAITS_HXX diff --git a/odb/boost/smart-ptr/lazy-ptr.hxx b/odb/boost/smart-ptr/lazy-ptr.hxx new file mode 100644 index 0000000..4dbf9bf --- /dev/null +++ b/odb/boost/smart-ptr/lazy-ptr.hxx @@ -0,0 +1,237 @@ +// file : odb/boost/smart-ptr/lazy-ptr.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_SMART_PTR_LAZY_PTR_HXX +#define ODB_BOOST_SMART_PTR_LAZY_PTR_HXX + +#include <odb/pre.hxx> + +#include <memory> // std::auto_ptr + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <odb/forward.hxx> // odb::database +#include <odb/traits.hxx> +#include <odb/lazy-ptr-impl.hxx> + +namespace odb +{ + namespace boost + { + template <class T> + class lazy_weak_ptr; + + // + // + template <class T> + class lazy_shared_ptr + { + // The standard shared_ptr interface. + // + public: + typedef T element_type; + + lazy_shared_ptr (); + template <class Y> explicit lazy_shared_ptr (Y*); + template <class Y, class D> lazy_shared_ptr (Y*, D); + template <class Y, class D, class A> lazy_shared_ptr (Y*, D, A); + + lazy_shared_ptr (const lazy_shared_ptr&); + template <class Y> lazy_shared_ptr (const lazy_shared_ptr<Y>&); + template <class Y> explicit lazy_shared_ptr (const lazy_weak_ptr<Y>&); + template <class Y> explicit lazy_shared_ptr (std::auto_ptr<Y>&); + + ~lazy_shared_ptr (); + + lazy_shared_ptr& operator= (const lazy_shared_ptr&); + template <class Y> lazy_shared_ptr& operator= (const lazy_shared_ptr<Y>&); + template <class Y> lazy_shared_ptr& operator= (std::auto_ptr<Y>&); + + void swap (lazy_shared_ptr&); + void reset (); + template <class Y> void reset (Y*); + template <class Y, class D> void reset (Y*, D); + template <class Y, class D, class A> void reset (Y*, D, A); + + T& operator* () const; + T* operator-> () const; + T* get () const; + + bool unique () const; + long use_count () const; + + typedef ::boost::shared_ptr<T> lazy_shared_ptr::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return (p_ || i_) ? &lazy_shared_ptr::p_ : 0; + } + + // Initialization/assignment from shared_ptr and weak_ptr. + // + public: + template <class Y> lazy_shared_ptr (const ::boost::shared_ptr<Y>&); + template <class Y> explicit lazy_shared_ptr (const ::boost::weak_ptr<Y>&); + + template <class Y> lazy_shared_ptr& operator= (const ::boost::shared_ptr<Y>&); + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + bool loaded () const; + ::boost::shared_ptr<T> load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + template <class ID> lazy_shared_ptr (database_type&, const ID&); + template <class Y> lazy_shared_ptr (database_type&, Y*); + template <class Y, class D> lazy_shared_ptr (database_type&, Y*, D); + template <class Y, class D, class A> lazy_shared_ptr (database_type&, Y*, D, A); + template <class Y> lazy_shared_ptr (database_type&, std::auto_ptr<Y>&); + template <class Y> lazy_shared_ptr (database_type&, const ::boost::shared_ptr<Y>&); + template <class Y> lazy_shared_ptr (database_type&, const ::boost::weak_ptr<Y>&); + + template <class ID> void reset (database_type&, const ID&); + template <class Y> void reset (database_type&, Y*); + template <class Y, class D> void reset (database_type&, Y*, D); + template <class Y, class D, class A> void reset (database_type&, Y*, D, A); + template <class Y> void reset (database_type&, const std::auto_ptr<Y>&); + template <class Y> void reset (database_type&, const ::boost::shared_ptr<Y>&); + + template <class O /* = T */> + typename object_traits<O>::id_type object_id () const; + + database_type& database () const; + + // Helpers. + // + public: + template <class Y> bool equal (const lazy_shared_ptr<Y>&) const; + + private: + template <class Y> friend class lazy_shared_ptr; + template <class Y> friend class lazy_weak_ptr; + + mutable ::boost::shared_ptr<T> p_; + mutable lazy_ptr_impl<T> i_; + }; + + // operator< and operator<< are not provided. + // + template<class T, class Y> + bool operator== (const lazy_shared_ptr<T>&, const lazy_shared_ptr<Y>&); + + template<class T, class Y> + bool operator!= (const lazy_shared_ptr<T>&, const lazy_shared_ptr<Y>&); + + template<class T> void swap (lazy_shared_ptr<T>&, lazy_shared_ptr<T>&); + + template<class D, class T> + D* get_deleter (const lazy_shared_ptr<T>&); + + // + // + template <class T> + class lazy_weak_ptr + { + // The standard weak_ptr interface. + // + public: + typedef T element_type; + + lazy_weak_ptr (); + template <class Y> lazy_weak_ptr (const lazy_shared_ptr<Y>&); + lazy_weak_ptr (const lazy_weak_ptr&); + template <class Y> lazy_weak_ptr (const lazy_weak_ptr<Y>&); + + ~lazy_weak_ptr (); + + lazy_weak_ptr& operator= (const lazy_weak_ptr&); + template <class Y> lazy_weak_ptr& operator= (const lazy_weak_ptr<Y>&); + template <class Y> lazy_weak_ptr& operator= (const lazy_shared_ptr<Y>&); + + void swap (lazy_weak_ptr<T>&); + void reset (); + + long use_count () const; + bool expired () const; + + lazy_shared_ptr<T> lock () const; + + // Initialization/assignment from shared_ptr and weak_ptr. + // + public: + template <class Y> lazy_weak_ptr (const ::boost::weak_ptr<Y>&); + template <class Y> lazy_weak_ptr (const ::boost::shared_ptr<Y>&); + + template <class Y> lazy_weak_ptr& operator= (const ::boost::weak_ptr<Y>&); + template <class Y> lazy_weak_ptr& operator= (const ::boost::shared_ptr<Y>&); + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + // expired() loaded() + // + // true true expired pointer to transient object + // false true valid pointer to persistent object + // true false expired pointer to persistent object + // false false valid pointer to transiend object + // + bool loaded () const; + + // Performs both lock and load. + // + ::boost::shared_ptr<T> load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + template <class ID> lazy_weak_ptr (database_type&, const ID&); + template <class Y> lazy_weak_ptr (database_type&, const ::boost::shared_ptr<Y>&); + template <class Y> lazy_weak_ptr (database_type&, const ::boost::weak_ptr<Y>&); + + template <class ID> void reset (database_type&, const ID&); + template <class Y> void reset (database_type&, const ::boost::shared_ptr<Y>&); + template <class Y> void reset (database_type&, const ::boost::weak_ptr<Y>&); + + // The object_id() function can only be called when the object is + // persistent, or: expired() XOR loaded() (can use != for XOR). + // + template <class O /* = T */> + typename object_traits<O>::id_type object_id () const; + + database_type& database () const; + + private: + template <class Y> friend class lazy_shared_ptr; + template <class Y> friend class lazy_weak_ptr; + + mutable ::boost::weak_ptr<T> p_; + mutable lazy_ptr_impl<T> i_; + }; + + // operator< is not provided. + // + template<class T> void swap (lazy_weak_ptr<T>&, lazy_weak_ptr<T>&); + } +} + +#include <odb/boost/smart-ptr/lazy-ptr.ixx> +#include <odb/boost/smart-ptr/lazy-ptr.txx> + +#include <odb/boost/smart-ptr/lazy-pointer-traits.hxx> + +#include <odb/post.hxx> + +#endif // ODB_BOOST_SMART_PTR_LAZY_PTR_HXX diff --git a/odb/boost/smart-ptr/lazy-ptr.ixx b/odb/boost/smart-ptr/lazy-ptr.ixx new file mode 100644 index 0000000..2522ab4 --- /dev/null +++ b/odb/boost/smart-ptr/lazy-ptr.ixx @@ -0,0 +1,649 @@ +// file : odb/boost/smart-ptr/lazy-ptr.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace boost + { + // + // lazy_shared_ptr + // + + template <class T> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr () {} + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (Y* p): p_ (p) {} + + template <class T> + template <class Y, class D> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (Y* p, D d): p_ (p, d) {} + + template <class T> + template <class Y, class D, class A> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (Y* p, D d, A a): p_ (p, d, a) {} + + template <class T> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (const lazy_shared_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {} + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (const lazy_weak_ptr<Y>& r): i_ (r.i_) + { + // If the pointer has expired but can be re-loaded, then don't throw. + // + p_ = r.lock (); + + if (!p_ && !i_) + throw ::boost::bad_weak_ptr (); + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (std::auto_ptr<Y>& r): p_ (r) {} + + template <class T> + inline lazy_shared_ptr<T>:: + ~lazy_shared_ptr () {} + + template <class T> + inline lazy_shared_ptr<T>& lazy_shared_ptr<T>:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>& lazy_shared_ptr<T>:: + operator= (const lazy_shared_ptr<Y>& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>& lazy_shared_ptr<T>:: + operator= (std::auto_ptr<Y>& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template <class T> + inline void lazy_shared_ptr<T>:: + swap (lazy_shared_ptr& b) + { + p_.swap (b.p_); + i_.swap (b.i_); + } + + template <class T> + inline void lazy_shared_ptr<T>:: + reset () + { + p_.reset (); + i_.reset (); + } + + template <class T> + template <class Y> + inline void lazy_shared_ptr<T>:: + reset (Y* p) + { + p_.reset (p); + i_.reset (); + } + + template <class T> + template <class Y, class D> + inline void lazy_shared_ptr<T>:: + reset (Y* p, D d) + { + p_.reset (p, d); + i_.reset (); + } + + template <class T> + template <class Y, class D, class A> + inline void lazy_shared_ptr<T>:: + reset (Y* p, D d, A a) + { + p_.reset (p, d, a); + i_.reset (); + } + + template <class T> + inline T& lazy_shared_ptr<T>:: + operator* () const + { + return *p_; + } + + template <class T> + inline T* lazy_shared_ptr<T>:: + operator-> () const + { + return p_.operator-> (); + } + + template <class T> + inline T* lazy_shared_ptr<T>:: + get () const + { + return p_.get (); + } + + template <class T> + inline bool lazy_shared_ptr<T>:: + unique () const + { + return p_.unique (); + } + + template <class T> + inline long lazy_shared_ptr<T>:: + use_count () const + { + return p_.use_count (); + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (const ::boost::shared_ptr<Y>& r): p_ (r) {} + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (const ::boost::weak_ptr<Y>& r): p_ (r) {} + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>& lazy_shared_ptr<T>:: + operator= (const ::boost::shared_ptr<Y>& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template <class T> + inline bool lazy_shared_ptr<T>:: + loaded () const + { + return p_ || !i_; + } + + template <class T> + inline ::boost::shared_ptr<T> lazy_shared_ptr<T>:: + load () const + { + if (!loaded ()) + p_ = i_.template load<T> (true); // Reset id. + + return p_; + } + + template <class T> + inline void lazy_shared_ptr<T>:: + unload () const + { + typedef typename object_traits<T>::object_type object_type; + + if (p_) + { + if (i_.database () != 0) + i_.reset_id (object_traits<object_type>::id (*p_)); + + p_.reset (); + } + } + + template <class T> + template <class ID> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, const ID& id): i_ (db, id) {} + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, Y* p) + : p_ (p) + { + if (p_) + i_.reset (db); + } + + template <class T> + template <class Y, class D> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, Y* p, D d) + : p_ (p, d) + { + if (p_) + i_.reset (db); + } + + template <class T> + template <class Y, class D, class A> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, Y* p, D d, A a) + : p_ (p, d, a) + { + if (p_) + i_.reset (db); + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, std::auto_ptr<Y>& r) + : p_ (r) + { + if (p_) + i_.reset (db); + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, const ::boost::shared_ptr<Y>& r) + : p_ (r) + { + if (p_) + i_.reset (db); + } + + template <class T> + template <class Y> + inline lazy_shared_ptr<T>:: + lazy_shared_ptr (database_type& db, const ::boost::weak_ptr<Y>& r) + : p_ (r) + { + if (p_) + i_.reset (db); + } + + template <class T> + template <class ID> + inline void lazy_shared_ptr<T>:: + reset (database_type& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template <class T> + template <class Y> + inline void lazy_shared_ptr<T>:: + reset (database_type& db, Y* p) + { + p_.reset (p); + + if (p_) + i_.reset (db); + else + i_.reset (); + } + + template <class T> + template <class Y, class D> + inline void lazy_shared_ptr<T>:: + reset (database_type& db, Y* p, D d) + { + p_.reset (p, d); + + if (p_) + i_.reset (db); + else + i_.reset (); + } + + template <class T> + template <class Y, class D, class A> + inline void lazy_shared_ptr<T>:: + reset (database_type& db, Y* p, D d, A a) + { + p_.reset (p, d, a); + + if (p_) + i_.reset (db); + else + i_.reset (); + } + + template <class T> + template <class Y> + inline void lazy_shared_ptr<T>:: + reset (database_type& db, const std::auto_ptr<Y>& r) + { + p_ = r; + + if (p_) + i_.reset (db); + else + i_.reset (); + } + + template <class T> + template <class Y> + inline void lazy_shared_ptr<T>:: + reset (database_type& db, const ::boost::shared_ptr<Y>& r) + { + p_ = r; + + if (p_) + i_.reset (db); + else + i_.reset (); + } + + template <class T> + template <class O> + inline typename object_traits<O>::id_type lazy_shared_ptr<T>:: + object_id () const + { + typedef typename object_traits<T>::object_type object_type; + + return p_ ? object_traits<object_type>::id (*p_) : i_.object_id<O> (); + } + + template <class T> + inline typename lazy_shared_ptr<T>::database_type& lazy_shared_ptr<T>:: + database () const + { + return *i_.database (); + } + + template<class T, class Y> + inline bool + operator== (const lazy_shared_ptr<T>& a, const lazy_shared_ptr<Y>& b) + { + return a.equal (b); + } + + template<class T, class Y> + inline bool + operator!= (const lazy_shared_ptr<T>& a, const lazy_shared_ptr<Y>& b) + { + return !a.equal (b); + } + + template<class T> + inline void + swap (lazy_shared_ptr<T>& a, lazy_shared_ptr<T>& b) + { + a.swap (b); + } + + template<class D, class T> + inline D* + get_deleter (const lazy_shared_ptr<T>& p) + { + return ::boost::get_deleter<D> (p.p_); + } + + + // + // lazy_weak_ptr + // + + template <class T> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr () {} + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (const lazy_shared_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {} + + template <class T> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (const lazy_weak_ptr<Y>& r): p_ (r.p_), i_ (r.i_) {} + + template <class T> + inline lazy_weak_ptr<T>:: + ~lazy_weak_ptr () {} + + template <class T> + inline lazy_weak_ptr<T>& lazy_weak_ptr<T>:: + operator= (const lazy_weak_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>& lazy_weak_ptr<T>:: + operator= (const lazy_weak_ptr<Y>& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>& lazy_weak_ptr<T>:: + operator= (const lazy_shared_ptr<Y>& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template <class T> + inline void lazy_weak_ptr<T>:: + swap (lazy_weak_ptr<T>& r) + { + p_.swap (r.p_); + i_.swap (r.i_); + } + + template <class T> + inline void lazy_weak_ptr<T>:: + reset () + { + p_.reset (); + i_.reset (); + } + + template <class T> + inline long lazy_weak_ptr<T>:: + use_count () const + { + return p_.use_count (); + } + + template <class T> + inline bool lazy_weak_ptr<T>:: + expired () const + { + return p_.expired (); + } + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (const ::boost::weak_ptr<Y>& r): p_ (r) {} + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (const ::boost::shared_ptr<Y>& r): p_ (r) {} + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>& lazy_weak_ptr<T>:: + operator= (const ::boost::weak_ptr<Y>& r) + { + p_ = r; + i_.reset (); + return this; + } + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>& lazy_weak_ptr<T>:: + operator= (const ::boost::shared_ptr<Y>& r) + { + p_ = r; + i_.reset (); + return this; + } + + template <class T> + inline bool lazy_weak_ptr<T>:: + loaded () const + { + return !expired () || !i_; + } + + template <class T> + inline ::boost::shared_ptr<T> lazy_weak_ptr<T>:: + load () const + { + ::boost::shared_ptr<T> r (p_.lock ()); + + if (r || !i_) + return r; + + r = i_.template load<T> (false); // Keep id. + p_ = r; + return r; + } + + template <class T> + inline void lazy_weak_ptr<T>:: + unload () const + { + // With weak pointer we always keep i_ up to date. + // + p_.reset (); + } + + template <class T> + template <class ID> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (database_type& db, const ID& id): i_ (db, id) {} + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (database_type& db, const ::boost::shared_ptr<Y>& r) + : p_ (r) + { + typedef typename object_traits<T>::object_type object_type; + + if (r) + i_.reset (db, object_traits<object_type>::id (*r)); + } + + template <class T> + template <class Y> + inline lazy_weak_ptr<T>:: + lazy_weak_ptr (database_type& db, const ::boost::weak_ptr<Y>& r) + : p_ (r) + { + typedef typename object_traits<T>::object_type object_type; + + ::boost::shared_ptr<T> sp (p_.lock ()); + + if (sp) + i_.reset (db, object_traits<object_type>::id (*sp)); + } + + template <class T> + template <class ID> + inline void lazy_weak_ptr<T>:: + reset (database_type& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template <class T> + template <class Y> + inline void lazy_weak_ptr<T>:: + reset (database_type& db, const ::boost::shared_ptr<Y>& r) + { + typedef typename object_traits<T>::object_type object_type; + + p_ = r; + + if (r) + i_.reset (db, object_traits<object_type>::id (*r)); + else + i_.reset (); + } + + template <class T> + template <class Y> + inline void lazy_weak_ptr<T>:: + reset (database_type& db, const ::boost::weak_ptr<Y>& r) + { + typedef typename object_traits<T>::object_type object_type; + + p_ = r; + ::boost::shared_ptr<T> sp (p_.lock ()); + + if (sp) + i_.reset (db, object_traits<object_type>::id (*sp)); + else + i_.reset (); + } + + template <class T> + template <class O> + inline typename object_traits<O>::id_type lazy_weak_ptr<T>:: + object_id () const + { + typedef typename object_traits<T>::object_type object_type; + + ::boost::shared_ptr<T> sp (p_.lock ()); + return sp ? object_traits<object_type>::id (*sp) : i_.object_id<O> (); + } + + template <class T> + inline typename lazy_weak_ptr<T>::database_type& lazy_weak_ptr<T>:: + database () const + { + return *i_.database (); + } + + template<class T> + inline void + swap (lazy_weak_ptr<T>& a, lazy_weak_ptr<T>& b) + { + a.swap (b); + } + } +} diff --git a/odb/boost/smart-ptr/lazy-ptr.txx b/odb/boost/smart-ptr/lazy-ptr.txx new file mode 100644 index 0000000..bca6fdb --- /dev/null +++ b/odb/boost/smart-ptr/lazy-ptr.txx @@ -0,0 +1,59 @@ +// file : odb/boost/smart-ptr/lazy-ptr.txx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace boost + { + // + // lazy_shared_ptr + // + + template <class T> + template <class Y> + bool lazy_shared_ptr<T>:: + equal (const lazy_shared_ptr<Y>& r) const + { + if (loaded () && r.loaded ()) + return p_ == r.p_; + + // If one of the object is not loaded, then we compare databases and + // object ids. Note that NULL pointers cannot have non-NULL databases + // and if both of them are NULL, we wouldn't have gotten here. + // + typedef typename object_traits<T>::object_type object_type1; + typedef typename object_traits<Y>::object_type object_type2; + + return i_.database () == r.i_.database () && + object_id<object_type1> () == r.object_id<object_type2> (); + } + + // + // lazy_weak_ptr + // + + template <class T> + lazy_shared_ptr<T> lazy_weak_ptr<T>:: + lock () const + { + ::boost::shared_ptr<T> sp (p_.lock ()); + + if (sp) + { + if (database_type* db = i_.database ()) + return lazy_shared_ptr<T> (*db, sp); + else + return lazy_shared_ptr<T> (sp); + } + else + { + if (i_) + return lazy_shared_ptr<T> (*i_.database (), i_.object_id<T> ()); + else + return lazy_shared_ptr<T> (); + } + } + } +} diff --git a/odb/boost/smart-ptr/pointer-traits.hxx b/odb/boost/smart-ptr/pointer-traits.hxx new file mode 100644 index 0000000..62a63a6 --- /dev/null +++ b/odb/boost/smart-ptr/pointer-traits.hxx @@ -0,0 +1,87 @@ +// file : odb/boost/smart-ptr/pointer-traits.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_SMART_PTR_POINTER_TRAITS_HXX +#define ODB_BOOST_SMART_PTR_POINTER_TRAITS_HXX + +#include <odb/pre.hxx> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <odb/pointer-traits.hxx> + +namespace odb +{ + // Specialization for boost::shared_ptr. + // + template <typename T> + class pointer_traits< ::boost::shared_ptr<T> > + { + public: + static pointer_kind const kind = pk_shared; + static bool const lazy = false; + + typedef T element_type; + typedef ::boost::shared_ptr<element_type> pointer_type; + typedef ::boost::shared_ptr<const element_type> const_pointer_type; + typedef smart_ptr_guard<pointer_type> guard; + + static element_type* + get_ptr (const pointer_type& p) + { + return p.get (); + } + + static element_type& + get_ref (const pointer_type& p) + { + return *p; + } + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + public: + static void* + allocate (std::size_t n) + { + return operator new (n); + } + + static void + free (void* p) + { + operator delete (p); + } + }; + + // Specialization for boost::weak_ptr. + // + template <typename T> + class pointer_traits< ::boost::weak_ptr<T> > + { + public: + static pointer_kind const kind = pk_weak; + static bool const lazy = false; + + typedef T element_type; + typedef ::boost::weak_ptr<element_type> pointer_type; + typedef ::boost::shared_ptr<element_type> strong_pointer_type; + + static strong_pointer_type + lock (const pointer_type& p) + { + return p.lock (); + } + }; +} + +#include <odb/post.hxx> + +#endif // ODB_BOOST_SMART_PTR_POINTER_TRAITS_HXX diff --git a/odb/boost/unordered.options b/odb/boost/unordered.options new file mode 100644 index 0000000..8f45085 --- /dev/null +++ b/odb/boost/unordered.options @@ -0,0 +1,9 @@ +# file : odb/boost/unordered.options +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +--profile boost/version + +--odb-epilogue '#include <odb/boost/unordered/container-traits.hxx>' +--hxx-prologue '#include <odb/boost/unordered/container-traits.hxx>' diff --git a/odb/boost/unordered/container-traits.hxx b/odb/boost/unordered/container-traits.hxx new file mode 100644 index 0000000..b967849 --- /dev/null +++ b/odb/boost/unordered/container-traits.hxx @@ -0,0 +1,252 @@ +// file : odb/boost/unordered/container-traits.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BOOST_UNORDERED_CONTAINER_TRAITS_HXX +#define ODB_BOOST_UNORDERED_CONTAINER_TRAITS_HXX + +#include <boost/version.hpp> + +// Unordered containers are available since 1.36.0. +// +#if BOOST_VERSION >= 103600 + +#include <odb/pre.hxx> + +#include <boost/unordered_set.hpp> +#include <boost/unordered_map.hpp> + +#include <odb/container-traits.hxx> + +namespace odb +{ + // unordered_set + // + template <typename V, typename H, typename P, typename A> + class access::container_traits< ::boost::unordered_set<V, H, P, A> > + { + public: + static container_kind const kind = ck_set; + + typedef ::boost::unordered_set<V, H, P, A> container_type; + typedef V value_type; + + typedef set_functions<value_type> functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (*i); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + value_type v; + more = f.load_all (v); + c.insert (v); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_all (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (*i); + } + + static void + erase (const functions& f) + { + f.delete_all (); + } + }; + + // unordered_multiset + // + // @@ Does multiset preserve insertion order of equal elements? The + // current implementation in the generated code does not guarantee + // this. + // + template <typename V, typename H, typename P, typename A> + class access::container_traits< ::boost::unordered_multiset<V, H, P, A> > + { + public: + static container_kind const kind = ck_multiset; + + typedef ::boost::unordered_multiset<V, H, P, A> container_type; + typedef V value_type; + + typedef set_functions<value_type> functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (*i); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + value_type v; + more = f.load_all (v); + c.insert (v); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_all (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (*i); + } + + static void + erase (const functions& f) + { + f.delete_all (); + } + }; + + // unordered_map + // + template <typename K, typename V, typename H, typename P, typename A> + class access::container_traits< ::boost::unordered_map<K, V, H, P, A> > + { + public: + static container_kind const kind = ck_map; + + typedef ::boost::unordered_map<K, V, H, P, A> container_type; + + typedef K key_type; + typedef V value_type; + typedef typename container_type::value_type pair_type; + + typedef map_functions<key_type, value_type> functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (i->first, i->second); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + key_type k; + value_type v; + more = f.load_all (k, v); + c.insert (pair_type (k, v)); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_all (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (i->first, i->second); + } + + static void + erase (const functions& f) + { + f.delete_all (); + } + }; + + // unordered_multimap + // + // @@ Does multimap preserve insertion order of equal elements? The + // current implementation in the generated code does not guarantee + // this. + // + template <typename K, typename V, typename H, typename P, typename A> + class access::container_traits< ::boost::unordered_multimap<K, V, H, P, A> > + { + public: + static container_kind const kind = ck_multimap; + + typedef ::boost::unordered_multimap<K, V, H, P, A> container_type; + + typedef K key_type; + typedef V value_type; + typedef typename container_type::value_type pair_type; + + typedef map_functions<key_type, value_type> functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (i->first, i->second); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + key_type k; + value_type v; + more = f.load_all (k, v); + c.insert (pair_type (k, v)); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_all (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert_one (i->first, i->second); + } + + static void + erase (const functions& f) + { + f.delete_all (); + } + }; +} + +#include <odb/post.hxx> + +#endif // BOOST_VERSION +#endif // ODB_BOOST_UNORDERED_CONTAINER_TRAITS_HXX diff --git a/odb/boost/version.options b/odb/boost/version.options new file mode 100644 index 0000000..c551bcb --- /dev/null +++ b/odb/boost/version.options @@ -0,0 +1,13 @@ +# file : odb/boost/version.options +# author : Boris Kolpackov <boris@codesynthesis.com> +# copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC +# license : GNU GPL v2; see accompanying LICENSE file + +# Make sure the options files as seen by the ODB compiler and header +# files as seen by the C++ compiler are from the same profile version. +# +--hxx-prologue '#include <odb/boost/version.hxx>' + +#--hxx-prologue '#if LIBODB_BOOST_VERSION != 1010000 // 1.1.0' +#--hxx-prologue '# error ODB and C++ compilers see different libodb-boost versions' +#--hxx-prologue '#endif' |