From 26e36b3a9d7b49d46ecfa69b447482251acba8ac Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 24 Jan 2024 16:53:38 +0300 Subject: Turn libodb repository into package for muti-package repository --- .gitignore | 37 - GPLv2 | 340 ----- INSTALL | 81 - INSTALL-GIT | 78 - LICENSE | 20 - Makefile.am | 10 - NEWS | 1 - README | 20 - README-GIT | 4 - bootstrap | 16 - build/.gitignore | 3 - build/bootstrap.build | 10 - build/bootstrap.make | 73 - build/configuration-rules.make | 16 - build/configuration.make | 20 - build/configure | 24 - build/export.build | 9 - build/export/libodb/stub.make | 8 - build/import/libodb/configuration-rules.make | 13 - build/import/libodb/configure | 53 - build/import/libodb/stub.make | 28 - build/root.build | 17 - buildfile | 9 - configure.ac | 67 - libodb-vc10.sln | 26 - libodb-vc11.sln | 26 - libodb-vc12.sln | 28 - libodb-vc8.sln | 26 - libodb-vc9.sln | 26 - libodb.pc.in | 14 - libodb/.gitignore | 25 + libodb/GPLv2 | 340 +++++ libodb/INSTALL | 6 + libodb/LICENSE | 20 + libodb/README | 20 + libodb/build/.gitignore | 3 + libodb/build/bootstrap.build | 10 + libodb/build/export.build | 9 + libodb/build/root.build | 17 + libodb/buildfile | 9 + libodb/manifest | 19 + libodb/odb/buildfile | 81 + libodb/odb/c-array-traits.hxx | 103 ++ libodb/odb/cache-traits.hxx | 182 +++ libodb/odb/callback.hxx | 42 + libodb/odb/connection.cxx | 125 ++ libodb/odb/connection.hxx | 228 +++ libodb/odb/connection.ixx | 131 ++ libodb/odb/connection.txx | 44 + libodb/odb/container-traits.hxx | 219 +++ libodb/odb/core.hxx | 20 + libodb/odb/database.cxx | 83 + libodb/odb/database.hxx | 657 ++++++++ libodb/odb/database.ixx | 879 +++++++++++ libodb/odb/database.txx | 491 ++++++ libodb/odb/details/buffer.cxx | 35 + libodb/odb/details/buffer.hxx | 92 ++ libodb/odb/details/build2/config-stub.h | 5 + libodb/odb/details/build2/config-vc-stub.h | 5 + libodb/odb/details/build2/config-vc.h | 23 + libodb/odb/details/build2/config.h | 19 + libodb/odb/details/c-string.hxx | 28 + libodb/odb/details/condition.cxx | 13 + libodb/odb/details/condition.hxx | 68 + libodb/odb/details/config-vc.h | 13 + libodb/odb/details/config.h.in | 18 + libodb/odb/details/config.hxx | 80 + libodb/odb/details/exception.hxx | 21 + libodb/odb/details/export.hxx | 78 + libodb/odb/details/function-wrapper.hxx | 90 ++ libodb/odb/details/function-wrapper.ixx | 49 + libodb/odb/details/function-wrapper.txx | 89 ++ libodb/odb/details/lock.cxx | 13 + libodb/odb/details/lock.hxx | 59 + libodb/odb/details/meta/answer.hxx | 30 + libodb/odb/details/meta/class-p.hxx | 34 + libodb/odb/details/meta/polymorphic-p.hxx | 57 + libodb/odb/details/meta/remove-const-volatile.hxx | 31 + libodb/odb/details/meta/remove-const.hxx | 32 + libodb/odb/details/meta/remove-pointer.hxx | 32 + libodb/odb/details/meta/remove-volatile.hxx | 32 + libodb/odb/details/meta/static-assert.hxx | 32 + libodb/odb/details/mutex.cxx | 13 + libodb/odb/details/mutex.hxx | 53 + libodb/odb/details/posix/condition.hxx | 47 + libodb/odb/details/posix/condition.ixx | 38 + libodb/odb/details/posix/exceptions.cxx | 22 + libodb/odb/details/posix/exceptions.hxx | 38 + libodb/odb/details/posix/mutex.hxx | 44 + libodb/odb/details/posix/mutex.ixx | 37 + libodb/odb/details/posix/thread.cxx | 44 + libodb/odb/details/posix/thread.hxx | 41 + libodb/odb/details/posix/thread.ixx | 29 + libodb/odb/details/posix/tls.hxx | 106 ++ libodb/odb/details/posix/tls.ixx | 20 + libodb/odb/details/posix/tls.txx | 121 ++ libodb/odb/details/shared-ptr-fwd.hxx | 24 + libodb/odb/details/shared-ptr.hxx | 167 ++ libodb/odb/details/shared-ptr/base.cxx | 83 + libodb/odb/details/shared-ptr/base.hxx | 131 ++ libodb/odb/details/shared-ptr/base.ixx | 119 ++ libodb/odb/details/shared-ptr/base.txx | 198 +++ libodb/odb/details/shared-ptr/counter-type.hxx | 23 + libodb/odb/details/shared-ptr/exception.hxx | 31 + libodb/odb/details/thread.cxx | 22 + libodb/odb/details/thread.hxx | 65 + libodb/odb/details/tls.hxx | 168 ++ libodb/odb/details/transfer-ptr.hxx | 73 + libodb/odb/details/type-info.hxx | 36 + libodb/odb/details/unique-ptr.hxx | 95 ++ libodb/odb/details/unused.hxx | 21 + libodb/odb/details/win32/condition.cxx | 54 + libodb/odb/details/win32/condition.hxx | 52 + libodb/odb/details/win32/condition.ixx | 30 + libodb/odb/details/win32/dll.cxx | 51 + libodb/odb/details/win32/exceptions.cxx | 22 + libodb/odb/details/win32/exceptions.hxx | 40 + libodb/odb/details/win32/init.cxx | 41 + libodb/odb/details/win32/init.hxx | 36 + libodb/odb/details/win32/lock.hxx | 49 + libodb/odb/details/win32/mutex.hxx | 43 + libodb/odb/details/win32/mutex.ixx | 32 + libodb/odb/details/win32/once-init.hxx | 23 + libodb/odb/details/win32/once.cxx | 26 + libodb/odb/details/win32/once.hxx | 50 + libodb/odb/details/win32/once.ixx | 42 + libodb/odb/details/win32/thread.cxx | 88 ++ libodb/odb/details/win32/thread.hxx | 59 + libodb/odb/details/win32/tls-init.hxx | 26 + libodb/odb/details/win32/tls.cxx | 245 +++ libodb/odb/details/win32/tls.hxx | 120 ++ libodb/odb/details/win32/tls.ixx | 20 + libodb/odb/details/win32/tls.txx | 94 ++ libodb/odb/details/win32/windows.hxx | 33 + libodb/odb/details/wrapper-p.hxx | 38 + libodb/odb/exception.hxx | 36 + libodb/odb/exceptions.cxx | 430 ++++++ libodb/odb/exceptions.hxx | 523 +++++++ libodb/odb/forward.hxx | 178 +++ libodb/odb/function-table.hxx | 50 + libodb/odb/lazy-pointer-traits.hxx | 141 ++ libodb/odb/lazy-ptr-impl.hxx | 188 +++ libodb/odb/lazy-ptr-impl.ixx | 397 +++++ libodb/odb/lazy-ptr-impl.txx | 60 + libodb/odb/lazy-ptr.hxx | 681 +++++++++ libodb/odb/lazy-ptr.ixx | 1681 +++++++++++++++++++++ libodb/odb/lazy-ptr.txx | 114 ++ libodb/odb/nested-container.hxx | 218 +++ libodb/odb/no-id-object-result.hxx | 182 +++ libodb/odb/no-id-object-result.txx | 21 + libodb/odb/no-op-cache-traits.hxx | 236 +++ libodb/odb/nullable.hxx | 229 +++ libodb/odb/object-result.hxx | 164 ++ libodb/odb/pointer-traits.hxx | 405 +++++ libodb/odb/polymorphic-info.hxx | 188 +++ libodb/odb/polymorphic-map.hxx | 276 ++++ libodb/odb/polymorphic-map.ixx | 19 + libodb/odb/polymorphic-map.txx | 75 + libodb/odb/polymorphic-object-result.hxx | 224 +++ libodb/odb/polymorphic-object-result.txx | 70 + libodb/odb/post.hxx | 6 + libodb/odb/pre.hxx | 23 + libodb/odb/prepared-query.cxx | 47 + libodb/odb/prepared-query.hxx | 201 +++ libodb/odb/query-dynamic.cxx | 200 +++ libodb/odb/query-dynamic.hxx | 1067 +++++++++++++ libodb/odb/query-dynamic.ixx | 18 + libodb/odb/query-dynamic.txx | 139 ++ libodb/odb/query.hxx | 119 ++ libodb/odb/result.cxx | 40 + libodb/odb/result.hxx | 247 +++ libodb/odb/result.txx | 49 + libodb/odb/schema-catalog-impl.hxx | 54 + libodb/odb/schema-catalog.cxx | 387 +++++ libodb/odb/schema-catalog.hxx | 392 +++++ libodb/odb/schema-version.hxx | 71 + libodb/odb/section.cxx | 27 + libodb/odb/section.hxx | 122 ++ libodb/odb/session.cxx | 66 + libodb/odb/session.hxx | 217 +++ libodb/odb/session.ixx | 60 + libodb/odb/session.txx | 90 ++ libodb/odb/simple-object-result.hxx | 201 +++ libodb/odb/simple-object-result.txx | 58 + libodb/odb/statement-processing-common.hxx | 214 +++ libodb/odb/statement-processing.cxx | 685 +++++++++ libodb/odb/statement.cxx | 12 + libodb/odb/statement.hxx | 108 ++ libodb/odb/std-array-traits.hxx | 72 + libodb/odb/std-deque-traits.hxx | 69 + libodb/odb/std-forward-list-traits.hxx | 73 + libodb/odb/std-list-traits.hxx | 73 + libodb/odb/std-map-traits.hxx | 142 ++ libodb/odb/std-set-traits.hxx | 134 ++ libodb/odb/std-unordered-map-traits.hxx | 133 ++ libodb/odb/std-unordered-set-traits.hxx | 125 ++ libodb/odb/std-vector-traits.hxx | 123 ++ libodb/odb/tr1/lazy-pointer-traits.hxx | 61 + libodb/odb/tr1/lazy-ptr.hxx | 267 ++++ libodb/odb/tr1/lazy-ptr.ixx | 638 ++++++++ libodb/odb/tr1/lazy-ptr.txx | 43 + libodb/odb/tr1/memory.hxx | 37 + libodb/odb/tr1/pointer-traits.hxx | 121 ++ libodb/odb/tr1/wrapper-traits.hxx | 76 + libodb/odb/tracer.cxx | 95 ++ libodb/odb/tracer.hxx | 36 + libodb/odb/traits.hxx | 317 ++++ libodb/odb/transaction.cxx | 356 +++++ libodb/odb/transaction.hxx | 278 ++++ libodb/odb/transaction.ixx | 68 + libodb/odb/vector-impl.cxx | 208 +++ libodb/odb/vector-impl.hxx | 221 +++ libodb/odb/vector-impl.ixx | 210 +++ libodb/odb/vector-traits.hxx | 106 ++ libodb/odb/vector-traits.txx | 100 ++ libodb/odb/vector.hxx | 635 ++++++++ libodb/odb/vector.ixx | 359 +++++ libodb/odb/version-build2-stub.hxx | 4 + libodb/odb/version-build2.hxx | 0 libodb/odb/version-build2.hxx.in | 42 + libodb/odb/version.hxx | 43 + libodb/odb/view-image.hxx | 36 + libodb/odb/view-result.hxx | 231 +++ libodb/odb/view-result.txx | 39 + libodb/odb/wrapper-traits.hxx | 276 ++++ libodb/tests/.gitignore | 1 + libodb/tests/basics/buildfile | 6 + libodb/tests/basics/driver.cxx | 29 + libodb/tests/build/.gitignore | 3 + libodb/tests/build/bootstrap.build | 8 + libodb/tests/build/root.build | 23 + libodb/tests/buildfile | 4 + m4/acx-pthread.m4 | 259 ---- m4/disable-rpath.m4 | 24 - m4/libodb.m4 | 81 - m4/libtool-link.m4 | 45 - m4/pkgconfig.m4 | 11 - m4/static-lib.m4 | 17 - m4/threads.m4 | 68 - makefile | 35 - manifest | 19 - odb/Makefile.am | 31 - odb/buildfile | 81 - odb/c-array-traits.hxx | 103 -- odb/cache-traits.hxx | 182 --- odb/callback.hxx | 42 - odb/connection.cxx | 125 -- odb/connection.hxx | 228 --- odb/connection.ixx | 131 -- odb/connection.txx | 44 - odb/container-traits.hxx | 219 --- odb/core.hxx | 20 - odb/database.cxx | 83 - odb/database.hxx | 657 -------- odb/database.ixx | 879 ----------- odb/database.txx | 491 ------ odb/details/buffer.cxx | 35 - odb/details/buffer.hxx | 92 -- odb/details/build2/config-stub.h | 5 - odb/details/build2/config-vc-stub.h | 5 - odb/details/build2/config-vc.h | 23 - odb/details/build2/config.h | 19 - odb/details/c-string.hxx | 28 - odb/details/condition.cxx | 13 - odb/details/condition.hxx | 68 - odb/details/config-vc.h | 13 - odb/details/config.h.in | 18 - odb/details/config.hxx | 80 - odb/details/exception.hxx | 21 - odb/details/export.hxx | 78 - odb/details/function-wrapper.hxx | 90 -- odb/details/function-wrapper.ixx | 49 - odb/details/function-wrapper.txx | 89 -- odb/details/lock.cxx | 13 - odb/details/lock.hxx | 59 - odb/details/meta/answer.hxx | 30 - odb/details/meta/class-p.hxx | 34 - odb/details/meta/polymorphic-p.hxx | 57 - odb/details/meta/remove-const-volatile.hxx | 31 - odb/details/meta/remove-const.hxx | 32 - odb/details/meta/remove-pointer.hxx | 32 - odb/details/meta/remove-volatile.hxx | 32 - odb/details/meta/static-assert.hxx | 32 - odb/details/mutex.cxx | 13 - odb/details/mutex.hxx | 53 - odb/details/posix/condition.hxx | 47 - odb/details/posix/condition.ixx | 38 - odb/details/posix/exceptions.cxx | 22 - odb/details/posix/exceptions.hxx | 38 - odb/details/posix/mutex.hxx | 44 - odb/details/posix/mutex.ixx | 37 - odb/details/posix/thread.cxx | 44 - odb/details/posix/thread.hxx | 41 - odb/details/posix/thread.ixx | 29 - odb/details/posix/tls.hxx | 106 -- odb/details/posix/tls.ixx | 20 - odb/details/posix/tls.txx | 121 -- odb/details/shared-ptr-fwd.hxx | 24 - odb/details/shared-ptr.hxx | 167 -- odb/details/shared-ptr/base.cxx | 83 - odb/details/shared-ptr/base.hxx | 131 -- odb/details/shared-ptr/base.ixx | 119 -- odb/details/shared-ptr/base.txx | 198 --- odb/details/shared-ptr/counter-type.hxx | 23 - odb/details/shared-ptr/exception.hxx | 31 - odb/details/thread.cxx | 22 - odb/details/thread.hxx | 65 - odb/details/tls.hxx | 168 -- odb/details/transfer-ptr.hxx | 73 - odb/details/type-info.hxx | 36 - odb/details/unique-ptr.hxx | 95 -- odb/details/unused.hxx | 21 - odb/details/win32/condition.cxx | 54 - odb/details/win32/condition.hxx | 52 - odb/details/win32/condition.ixx | 30 - odb/details/win32/dll.cxx | 51 - odb/details/win32/exceptions.cxx | 22 - odb/details/win32/exceptions.hxx | 40 - odb/details/win32/init.cxx | 41 - odb/details/win32/init.hxx | 36 - odb/details/win32/lock.hxx | 49 - odb/details/win32/mutex.hxx | 43 - odb/details/win32/mutex.ixx | 32 - odb/details/win32/once-init.hxx | 23 - odb/details/win32/once.cxx | 26 - odb/details/win32/once.hxx | 50 - odb/details/win32/once.ixx | 42 - odb/details/win32/thread.cxx | 88 -- odb/details/win32/thread.hxx | 59 - odb/details/win32/tls-init.hxx | 26 - odb/details/win32/tls.cxx | 245 --- odb/details/win32/tls.hxx | 120 -- odb/details/win32/tls.ixx | 20 - odb/details/win32/tls.txx | 94 -- odb/details/win32/windows.hxx | 33 - odb/details/wrapper-p.hxx | 38 - odb/exception.hxx | 36 - odb/exceptions.cxx | 430 ------ odb/exceptions.hxx | 523 ------- odb/forward.hxx | 178 --- odb/function-table.hxx | 50 - odb/lazy-pointer-traits.hxx | 141 -- odb/lazy-ptr-impl.hxx | 188 --- odb/lazy-ptr-impl.ixx | 397 ----- odb/lazy-ptr-impl.txx | 60 - odb/lazy-ptr.hxx | 681 --------- odb/lazy-ptr.ixx | 1681 --------------------- odb/lazy-ptr.txx | 114 -- odb/libodb-vc10.vcxproj | 173 --- odb/libodb-vc10.vcxproj.filters | 21 - odb/libodb-vc11.vcxproj | 177 --- odb/libodb-vc11.vcxproj.filters | 21 - odb/libodb-vc12.vcxproj | 181 --- odb/libodb-vc12.vcxproj.filters | 21 - odb/libodb-vc8.vcproj | 351 ----- odb/libodb-vc9.vcproj | 358 ----- odb/makefile | 184 --- odb/nested-container.hxx | 218 --- odb/no-id-object-result.hxx | 182 --- odb/no-id-object-result.txx | 21 - odb/no-op-cache-traits.hxx | 236 --- odb/nullable.hxx | 229 --- odb/object-result.hxx | 164 -- odb/pointer-traits.hxx | 405 ----- odb/polymorphic-info.hxx | 188 --- odb/polymorphic-map.hxx | 276 ---- odb/polymorphic-map.ixx | 19 - odb/polymorphic-map.txx | 75 - odb/polymorphic-object-result.hxx | 224 --- odb/polymorphic-object-result.txx | 70 - odb/post.hxx | 6 - odb/pre.hxx | 23 - odb/prepared-query.cxx | 47 - odb/prepared-query.hxx | 201 --- odb/query-dynamic.cxx | 200 --- odb/query-dynamic.hxx | 1067 ------------- odb/query-dynamic.ixx | 18 - odb/query-dynamic.txx | 139 -- odb/query.hxx | 119 -- odb/result.cxx | 40 - odb/result.hxx | 247 --- odb/result.txx | 49 - odb/schema-catalog-impl.hxx | 54 - odb/schema-catalog.cxx | 387 ----- odb/schema-catalog.hxx | 392 ----- odb/schema-version.hxx | 71 - odb/section.cxx | 27 - odb/section.hxx | 122 -- odb/session.cxx | 66 - odb/session.hxx | 217 --- odb/session.ixx | 60 - odb/session.txx | 90 -- odb/simple-object-result.hxx | 201 --- odb/simple-object-result.txx | 58 - odb/statement-processing-common.hxx | 214 --- odb/statement-processing.cxx | 685 --------- odb/statement.cxx | 12 - odb/statement.hxx | 108 -- odb/std-array-traits.hxx | 72 - odb/std-deque-traits.hxx | 69 - odb/std-forward-list-traits.hxx | 73 - odb/std-list-traits.hxx | 73 - odb/std-map-traits.hxx | 142 -- odb/std-set-traits.hxx | 134 -- odb/std-unordered-map-traits.hxx | 133 -- odb/std-unordered-set-traits.hxx | 125 -- odb/std-vector-traits.hxx | 123 -- odb/tr1/lazy-pointer-traits.hxx | 61 - odb/tr1/lazy-ptr.hxx | 267 ---- odb/tr1/lazy-ptr.ixx | 638 -------- odb/tr1/lazy-ptr.txx | 43 - odb/tr1/memory.hxx | 37 - odb/tr1/pointer-traits.hxx | 121 -- odb/tr1/wrapper-traits.hxx | 76 - odb/tracer.cxx | 95 -- odb/tracer.hxx | 36 - odb/traits.hxx | 317 ---- odb/transaction.cxx | 356 ----- odb/transaction.hxx | 278 ---- odb/transaction.ixx | 68 - odb/vector-impl.cxx | 208 --- odb/vector-impl.hxx | 221 --- odb/vector-impl.ixx | 210 --- odb/vector-traits.hxx | 106 -- odb/vector-traits.txx | 100 -- odb/vector.hxx | 635 -------- odb/vector.ixx | 359 ----- odb/version-build2-stub.hxx | 4 - odb/version-build2.hxx | 0 odb/version-build2.hxx.in | 42 - odb/version.hxx | 43 - odb/view-image.hxx | 36 - odb/view-result.hxx | 231 --- odb/view-result.txx | 39 - odb/wrapper-traits.hxx | 276 ---- tests/.gitignore | 1 - tests/basics/buildfile | 6 - tests/basics/driver.cxx | 29 - tests/build/.gitignore | 3 - tests/build/bootstrap.build | 8 - tests/build/root.build | 23 - tests/buildfile | 4 - version.txt | 1 - 443 files changed, 25691 insertions(+), 28394 deletions(-) delete mode 100644 .gitignore delete mode 100644 GPLv2 delete mode 100644 INSTALL delete mode 100644 INSTALL-GIT delete mode 100644 LICENSE delete mode 100644 Makefile.am delete mode 100644 NEWS delete mode 100644 README delete mode 100644 README-GIT delete mode 100755 bootstrap delete mode 100644 build/.gitignore delete mode 100644 build/bootstrap.build delete mode 100644 build/bootstrap.make delete mode 100644 build/configuration-rules.make delete mode 100644 build/configuration.make delete mode 100755 build/configure delete mode 100644 build/export.build delete mode 100644 build/export/libodb/stub.make delete mode 100644 build/import/libodb/configuration-rules.make delete mode 100755 build/import/libodb/configure delete mode 100644 build/import/libodb/stub.make delete mode 100644 build/root.build delete mode 100644 buildfile delete mode 100644 configure.ac delete mode 100644 libodb-vc10.sln delete mode 100644 libodb-vc11.sln delete mode 100644 libodb-vc12.sln delete mode 100644 libodb-vc8.sln delete mode 100644 libodb-vc9.sln delete mode 100644 libodb.pc.in create mode 100644 libodb/.gitignore create mode 100644 libodb/GPLv2 create mode 100644 libodb/INSTALL create mode 100644 libodb/LICENSE create mode 100644 libodb/README create mode 100644 libodb/build/.gitignore create mode 100644 libodb/build/bootstrap.build create mode 100644 libodb/build/export.build create mode 100644 libodb/build/root.build create mode 100644 libodb/buildfile create mode 100644 libodb/manifest create mode 100644 libodb/odb/buildfile create mode 100644 libodb/odb/c-array-traits.hxx create mode 100644 libodb/odb/cache-traits.hxx create mode 100644 libodb/odb/callback.hxx create mode 100644 libodb/odb/connection.cxx create mode 100644 libodb/odb/connection.hxx create mode 100644 libodb/odb/connection.ixx create mode 100644 libodb/odb/connection.txx create mode 100644 libodb/odb/container-traits.hxx create mode 100644 libodb/odb/core.hxx create mode 100644 libodb/odb/database.cxx create mode 100644 libodb/odb/database.hxx create mode 100644 libodb/odb/database.ixx create mode 100644 libodb/odb/database.txx create mode 100644 libodb/odb/details/buffer.cxx create mode 100644 libodb/odb/details/buffer.hxx create mode 100644 libodb/odb/details/build2/config-stub.h create mode 100644 libodb/odb/details/build2/config-vc-stub.h create mode 100644 libodb/odb/details/build2/config-vc.h create mode 100644 libodb/odb/details/build2/config.h create mode 100644 libodb/odb/details/c-string.hxx create mode 100644 libodb/odb/details/condition.cxx create mode 100644 libodb/odb/details/condition.hxx create mode 100644 libodb/odb/details/config-vc.h create mode 100644 libodb/odb/details/config.h.in create mode 100644 libodb/odb/details/config.hxx create mode 100644 libodb/odb/details/exception.hxx create mode 100644 libodb/odb/details/export.hxx create mode 100644 libodb/odb/details/function-wrapper.hxx create mode 100644 libodb/odb/details/function-wrapper.ixx create mode 100644 libodb/odb/details/function-wrapper.txx create mode 100644 libodb/odb/details/lock.cxx create mode 100644 libodb/odb/details/lock.hxx create mode 100644 libodb/odb/details/meta/answer.hxx create mode 100644 libodb/odb/details/meta/class-p.hxx create mode 100644 libodb/odb/details/meta/polymorphic-p.hxx create mode 100644 libodb/odb/details/meta/remove-const-volatile.hxx create mode 100644 libodb/odb/details/meta/remove-const.hxx create mode 100644 libodb/odb/details/meta/remove-pointer.hxx create mode 100644 libodb/odb/details/meta/remove-volatile.hxx create mode 100644 libodb/odb/details/meta/static-assert.hxx create mode 100644 libodb/odb/details/mutex.cxx create mode 100644 libodb/odb/details/mutex.hxx create mode 100644 libodb/odb/details/posix/condition.hxx create mode 100644 libodb/odb/details/posix/condition.ixx create mode 100644 libodb/odb/details/posix/exceptions.cxx create mode 100644 libodb/odb/details/posix/exceptions.hxx create mode 100644 libodb/odb/details/posix/mutex.hxx create mode 100644 libodb/odb/details/posix/mutex.ixx create mode 100644 libodb/odb/details/posix/thread.cxx create mode 100644 libodb/odb/details/posix/thread.hxx create mode 100644 libodb/odb/details/posix/thread.ixx create mode 100644 libodb/odb/details/posix/tls.hxx create mode 100644 libodb/odb/details/posix/tls.ixx create mode 100644 libodb/odb/details/posix/tls.txx create mode 100644 libodb/odb/details/shared-ptr-fwd.hxx create mode 100644 libodb/odb/details/shared-ptr.hxx create mode 100644 libodb/odb/details/shared-ptr/base.cxx create mode 100644 libodb/odb/details/shared-ptr/base.hxx create mode 100644 libodb/odb/details/shared-ptr/base.ixx create mode 100644 libodb/odb/details/shared-ptr/base.txx create mode 100644 libodb/odb/details/shared-ptr/counter-type.hxx create mode 100644 libodb/odb/details/shared-ptr/exception.hxx create mode 100644 libodb/odb/details/thread.cxx create mode 100644 libodb/odb/details/thread.hxx create mode 100644 libodb/odb/details/tls.hxx create mode 100644 libodb/odb/details/transfer-ptr.hxx create mode 100644 libodb/odb/details/type-info.hxx create mode 100644 libodb/odb/details/unique-ptr.hxx create mode 100644 libodb/odb/details/unused.hxx create mode 100644 libodb/odb/details/win32/condition.cxx create mode 100644 libodb/odb/details/win32/condition.hxx create mode 100644 libodb/odb/details/win32/condition.ixx create mode 100644 libodb/odb/details/win32/dll.cxx create mode 100644 libodb/odb/details/win32/exceptions.cxx create mode 100644 libodb/odb/details/win32/exceptions.hxx create mode 100644 libodb/odb/details/win32/init.cxx create mode 100644 libodb/odb/details/win32/init.hxx create mode 100644 libodb/odb/details/win32/lock.hxx create mode 100644 libodb/odb/details/win32/mutex.hxx create mode 100644 libodb/odb/details/win32/mutex.ixx create mode 100644 libodb/odb/details/win32/once-init.hxx create mode 100644 libodb/odb/details/win32/once.cxx create mode 100644 libodb/odb/details/win32/once.hxx create mode 100644 libodb/odb/details/win32/once.ixx create mode 100644 libodb/odb/details/win32/thread.cxx create mode 100644 libodb/odb/details/win32/thread.hxx create mode 100644 libodb/odb/details/win32/tls-init.hxx create mode 100644 libodb/odb/details/win32/tls.cxx create mode 100644 libodb/odb/details/win32/tls.hxx create mode 100644 libodb/odb/details/win32/tls.ixx create mode 100644 libodb/odb/details/win32/tls.txx create mode 100644 libodb/odb/details/win32/windows.hxx create mode 100644 libodb/odb/details/wrapper-p.hxx create mode 100644 libodb/odb/exception.hxx create mode 100644 libodb/odb/exceptions.cxx create mode 100644 libodb/odb/exceptions.hxx create mode 100644 libodb/odb/forward.hxx create mode 100644 libodb/odb/function-table.hxx create mode 100644 libodb/odb/lazy-pointer-traits.hxx create mode 100644 libodb/odb/lazy-ptr-impl.hxx create mode 100644 libodb/odb/lazy-ptr-impl.ixx create mode 100644 libodb/odb/lazy-ptr-impl.txx create mode 100644 libodb/odb/lazy-ptr.hxx create mode 100644 libodb/odb/lazy-ptr.ixx create mode 100644 libodb/odb/lazy-ptr.txx create mode 100644 libodb/odb/nested-container.hxx create mode 100644 libodb/odb/no-id-object-result.hxx create mode 100644 libodb/odb/no-id-object-result.txx create mode 100644 libodb/odb/no-op-cache-traits.hxx create mode 100644 libodb/odb/nullable.hxx create mode 100644 libodb/odb/object-result.hxx create mode 100644 libodb/odb/pointer-traits.hxx create mode 100644 libodb/odb/polymorphic-info.hxx create mode 100644 libodb/odb/polymorphic-map.hxx create mode 100644 libodb/odb/polymorphic-map.ixx create mode 100644 libodb/odb/polymorphic-map.txx create mode 100644 libodb/odb/polymorphic-object-result.hxx create mode 100644 libodb/odb/polymorphic-object-result.txx create mode 100644 libodb/odb/post.hxx create mode 100644 libodb/odb/pre.hxx create mode 100644 libodb/odb/prepared-query.cxx create mode 100644 libodb/odb/prepared-query.hxx create mode 100644 libodb/odb/query-dynamic.cxx create mode 100644 libodb/odb/query-dynamic.hxx create mode 100644 libodb/odb/query-dynamic.ixx create mode 100644 libodb/odb/query-dynamic.txx create mode 100644 libodb/odb/query.hxx create mode 100644 libodb/odb/result.cxx create mode 100644 libodb/odb/result.hxx create mode 100644 libodb/odb/result.txx create mode 100644 libodb/odb/schema-catalog-impl.hxx create mode 100644 libodb/odb/schema-catalog.cxx create mode 100644 libodb/odb/schema-catalog.hxx create mode 100644 libodb/odb/schema-version.hxx create mode 100644 libodb/odb/section.cxx create mode 100644 libodb/odb/section.hxx create mode 100644 libodb/odb/session.cxx create mode 100644 libodb/odb/session.hxx create mode 100644 libodb/odb/session.ixx create mode 100644 libodb/odb/session.txx create mode 100644 libodb/odb/simple-object-result.hxx create mode 100644 libodb/odb/simple-object-result.txx create mode 100644 libodb/odb/statement-processing-common.hxx create mode 100644 libodb/odb/statement-processing.cxx create mode 100644 libodb/odb/statement.cxx create mode 100644 libodb/odb/statement.hxx create mode 100644 libodb/odb/std-array-traits.hxx create mode 100644 libodb/odb/std-deque-traits.hxx create mode 100644 libodb/odb/std-forward-list-traits.hxx create mode 100644 libodb/odb/std-list-traits.hxx create mode 100644 libodb/odb/std-map-traits.hxx create mode 100644 libodb/odb/std-set-traits.hxx create mode 100644 libodb/odb/std-unordered-map-traits.hxx create mode 100644 libodb/odb/std-unordered-set-traits.hxx create mode 100644 libodb/odb/std-vector-traits.hxx create mode 100644 libodb/odb/tr1/lazy-pointer-traits.hxx create mode 100644 libodb/odb/tr1/lazy-ptr.hxx create mode 100644 libodb/odb/tr1/lazy-ptr.ixx create mode 100644 libodb/odb/tr1/lazy-ptr.txx create mode 100644 libodb/odb/tr1/memory.hxx create mode 100644 libodb/odb/tr1/pointer-traits.hxx create mode 100644 libodb/odb/tr1/wrapper-traits.hxx create mode 100644 libodb/odb/tracer.cxx create mode 100644 libodb/odb/tracer.hxx create mode 100644 libodb/odb/traits.hxx create mode 100644 libodb/odb/transaction.cxx create mode 100644 libodb/odb/transaction.hxx create mode 100644 libodb/odb/transaction.ixx create mode 100644 libodb/odb/vector-impl.cxx create mode 100644 libodb/odb/vector-impl.hxx create mode 100644 libodb/odb/vector-impl.ixx create mode 100644 libodb/odb/vector-traits.hxx create mode 100644 libodb/odb/vector-traits.txx create mode 100644 libodb/odb/vector.hxx create mode 100644 libodb/odb/vector.ixx create mode 100644 libodb/odb/version-build2-stub.hxx create mode 100644 libodb/odb/version-build2.hxx create mode 100644 libodb/odb/version-build2.hxx.in create mode 100644 libodb/odb/version.hxx create mode 100644 libodb/odb/view-image.hxx create mode 100644 libodb/odb/view-result.hxx create mode 100644 libodb/odb/view-result.txx create mode 100644 libodb/odb/wrapper-traits.hxx create mode 100644 libodb/tests/.gitignore create mode 100644 libodb/tests/basics/buildfile create mode 100644 libodb/tests/basics/driver.cxx create mode 100644 libodb/tests/build/.gitignore create mode 100644 libodb/tests/build/bootstrap.build create mode 100644 libodb/tests/build/root.build create mode 100644 libodb/tests/buildfile delete mode 100644 m4/acx-pthread.m4 delete mode 100644 m4/disable-rpath.m4 delete mode 100644 m4/libodb.m4 delete mode 100644 m4/libtool-link.m4 delete mode 100644 m4/pkgconfig.m4 delete mode 100644 m4/static-lib.m4 delete mode 100644 m4/threads.m4 delete mode 100644 makefile delete mode 100644 manifest delete mode 100644 odb/Makefile.am delete mode 100644 odb/buildfile delete mode 100644 odb/c-array-traits.hxx delete mode 100644 odb/cache-traits.hxx delete mode 100644 odb/callback.hxx delete mode 100644 odb/connection.cxx delete mode 100644 odb/connection.hxx delete mode 100644 odb/connection.ixx delete mode 100644 odb/connection.txx delete mode 100644 odb/container-traits.hxx delete mode 100644 odb/core.hxx delete mode 100644 odb/database.cxx delete mode 100644 odb/database.hxx delete mode 100644 odb/database.ixx delete mode 100644 odb/database.txx delete mode 100644 odb/details/buffer.cxx delete mode 100644 odb/details/buffer.hxx delete mode 100644 odb/details/build2/config-stub.h delete mode 100644 odb/details/build2/config-vc-stub.h delete mode 100644 odb/details/build2/config-vc.h delete mode 100644 odb/details/build2/config.h delete mode 100644 odb/details/c-string.hxx delete mode 100644 odb/details/condition.cxx delete mode 100644 odb/details/condition.hxx delete mode 100644 odb/details/config-vc.h delete mode 100644 odb/details/config.h.in delete mode 100644 odb/details/config.hxx delete mode 100644 odb/details/exception.hxx delete mode 100644 odb/details/export.hxx delete mode 100644 odb/details/function-wrapper.hxx delete mode 100644 odb/details/function-wrapper.ixx delete mode 100644 odb/details/function-wrapper.txx delete mode 100644 odb/details/lock.cxx delete mode 100644 odb/details/lock.hxx delete mode 100644 odb/details/meta/answer.hxx delete mode 100644 odb/details/meta/class-p.hxx delete mode 100644 odb/details/meta/polymorphic-p.hxx delete mode 100644 odb/details/meta/remove-const-volatile.hxx delete mode 100644 odb/details/meta/remove-const.hxx delete mode 100644 odb/details/meta/remove-pointer.hxx delete mode 100644 odb/details/meta/remove-volatile.hxx delete mode 100644 odb/details/meta/static-assert.hxx delete mode 100644 odb/details/mutex.cxx delete mode 100644 odb/details/mutex.hxx delete mode 100644 odb/details/posix/condition.hxx delete mode 100644 odb/details/posix/condition.ixx delete mode 100644 odb/details/posix/exceptions.cxx delete mode 100644 odb/details/posix/exceptions.hxx delete mode 100644 odb/details/posix/mutex.hxx delete mode 100644 odb/details/posix/mutex.ixx delete mode 100644 odb/details/posix/thread.cxx delete mode 100644 odb/details/posix/thread.hxx delete mode 100644 odb/details/posix/thread.ixx delete mode 100644 odb/details/posix/tls.hxx delete mode 100644 odb/details/posix/tls.ixx delete mode 100644 odb/details/posix/tls.txx delete mode 100644 odb/details/shared-ptr-fwd.hxx delete mode 100644 odb/details/shared-ptr.hxx delete mode 100644 odb/details/shared-ptr/base.cxx delete mode 100644 odb/details/shared-ptr/base.hxx delete mode 100644 odb/details/shared-ptr/base.ixx delete mode 100644 odb/details/shared-ptr/base.txx delete mode 100644 odb/details/shared-ptr/counter-type.hxx delete mode 100644 odb/details/shared-ptr/exception.hxx delete mode 100644 odb/details/thread.cxx delete mode 100644 odb/details/thread.hxx delete mode 100644 odb/details/tls.hxx delete mode 100644 odb/details/transfer-ptr.hxx delete mode 100644 odb/details/type-info.hxx delete mode 100644 odb/details/unique-ptr.hxx delete mode 100644 odb/details/unused.hxx delete mode 100644 odb/details/win32/condition.cxx delete mode 100644 odb/details/win32/condition.hxx delete mode 100644 odb/details/win32/condition.ixx delete mode 100644 odb/details/win32/dll.cxx delete mode 100644 odb/details/win32/exceptions.cxx delete mode 100644 odb/details/win32/exceptions.hxx delete mode 100644 odb/details/win32/init.cxx delete mode 100644 odb/details/win32/init.hxx delete mode 100644 odb/details/win32/lock.hxx delete mode 100644 odb/details/win32/mutex.hxx delete mode 100644 odb/details/win32/mutex.ixx delete mode 100644 odb/details/win32/once-init.hxx delete mode 100644 odb/details/win32/once.cxx delete mode 100644 odb/details/win32/once.hxx delete mode 100644 odb/details/win32/once.ixx delete mode 100644 odb/details/win32/thread.cxx delete mode 100644 odb/details/win32/thread.hxx delete mode 100644 odb/details/win32/tls-init.hxx delete mode 100644 odb/details/win32/tls.cxx delete mode 100644 odb/details/win32/tls.hxx delete mode 100644 odb/details/win32/tls.ixx delete mode 100644 odb/details/win32/tls.txx delete mode 100644 odb/details/win32/windows.hxx delete mode 100644 odb/details/wrapper-p.hxx delete mode 100644 odb/exception.hxx delete mode 100644 odb/exceptions.cxx delete mode 100644 odb/exceptions.hxx delete mode 100644 odb/forward.hxx delete mode 100644 odb/function-table.hxx delete mode 100644 odb/lazy-pointer-traits.hxx delete mode 100644 odb/lazy-ptr-impl.hxx delete mode 100644 odb/lazy-ptr-impl.ixx delete mode 100644 odb/lazy-ptr-impl.txx delete mode 100644 odb/lazy-ptr.hxx delete mode 100644 odb/lazy-ptr.ixx delete mode 100644 odb/lazy-ptr.txx delete mode 100644 odb/libodb-vc10.vcxproj delete mode 100644 odb/libodb-vc10.vcxproj.filters delete mode 100644 odb/libodb-vc11.vcxproj delete mode 100644 odb/libodb-vc11.vcxproj.filters delete mode 100644 odb/libodb-vc12.vcxproj delete mode 100644 odb/libodb-vc12.vcxproj.filters delete mode 100644 odb/libodb-vc8.vcproj delete mode 100644 odb/libodb-vc9.vcproj delete mode 100644 odb/makefile delete mode 100644 odb/nested-container.hxx delete mode 100644 odb/no-id-object-result.hxx delete mode 100644 odb/no-id-object-result.txx delete mode 100644 odb/no-op-cache-traits.hxx delete mode 100644 odb/nullable.hxx delete mode 100644 odb/object-result.hxx delete mode 100644 odb/pointer-traits.hxx delete mode 100644 odb/polymorphic-info.hxx delete mode 100644 odb/polymorphic-map.hxx delete mode 100644 odb/polymorphic-map.ixx delete mode 100644 odb/polymorphic-map.txx delete mode 100644 odb/polymorphic-object-result.hxx delete mode 100644 odb/polymorphic-object-result.txx delete mode 100644 odb/post.hxx delete mode 100644 odb/pre.hxx delete mode 100644 odb/prepared-query.cxx delete mode 100644 odb/prepared-query.hxx delete mode 100644 odb/query-dynamic.cxx delete mode 100644 odb/query-dynamic.hxx delete mode 100644 odb/query-dynamic.ixx delete mode 100644 odb/query-dynamic.txx delete mode 100644 odb/query.hxx delete mode 100644 odb/result.cxx delete mode 100644 odb/result.hxx delete mode 100644 odb/result.txx delete mode 100644 odb/schema-catalog-impl.hxx delete mode 100644 odb/schema-catalog.cxx delete mode 100644 odb/schema-catalog.hxx delete mode 100644 odb/schema-version.hxx delete mode 100644 odb/section.cxx delete mode 100644 odb/section.hxx delete mode 100644 odb/session.cxx delete mode 100644 odb/session.hxx delete mode 100644 odb/session.ixx delete mode 100644 odb/session.txx delete mode 100644 odb/simple-object-result.hxx delete mode 100644 odb/simple-object-result.txx delete mode 100644 odb/statement-processing-common.hxx delete mode 100644 odb/statement-processing.cxx delete mode 100644 odb/statement.cxx delete mode 100644 odb/statement.hxx delete mode 100644 odb/std-array-traits.hxx delete mode 100644 odb/std-deque-traits.hxx delete mode 100644 odb/std-forward-list-traits.hxx delete mode 100644 odb/std-list-traits.hxx delete mode 100644 odb/std-map-traits.hxx delete mode 100644 odb/std-set-traits.hxx delete mode 100644 odb/std-unordered-map-traits.hxx delete mode 100644 odb/std-unordered-set-traits.hxx delete mode 100644 odb/std-vector-traits.hxx delete mode 100644 odb/tr1/lazy-pointer-traits.hxx delete mode 100644 odb/tr1/lazy-ptr.hxx delete mode 100644 odb/tr1/lazy-ptr.ixx delete mode 100644 odb/tr1/lazy-ptr.txx delete mode 100644 odb/tr1/memory.hxx delete mode 100644 odb/tr1/pointer-traits.hxx delete mode 100644 odb/tr1/wrapper-traits.hxx delete mode 100644 odb/tracer.cxx delete mode 100644 odb/tracer.hxx delete mode 100644 odb/traits.hxx delete mode 100644 odb/transaction.cxx delete mode 100644 odb/transaction.hxx delete mode 100644 odb/transaction.ixx delete mode 100644 odb/vector-impl.cxx delete mode 100644 odb/vector-impl.hxx delete mode 100644 odb/vector-impl.ixx delete mode 100644 odb/vector-traits.hxx delete mode 100644 odb/vector-traits.txx delete mode 100644 odb/vector.hxx delete mode 100644 odb/vector.ixx delete mode 100644 odb/version-build2-stub.hxx delete mode 100644 odb/version-build2.hxx delete mode 100644 odb/version-build2.hxx.in delete mode 100644 odb/version.hxx delete mode 100644 odb/view-image.hxx delete mode 100644 odb/view-result.hxx delete mode 100644 odb/view-result.txx delete mode 100644 odb/wrapper-traits.hxx delete mode 100644 tests/.gitignore delete mode 100644 tests/basics/buildfile delete mode 100644 tests/basics/driver.cxx delete mode 100644 tests/build/.gitignore delete mode 100644 tests/build/bootstrap.build delete mode 100644 tests/build/root.build delete mode 100644 tests/buildfile delete mode 100644 version.txt diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 3004ad1..0000000 --- a/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -.bdep/ - -# Compiler/linker output. -# -*.d -*.t -*.i -*.ii -*.o -*.obj -*.so -*.dll -*.a -*.lib -*.exp -*.pdb -*.ilk -*.exe -*.exe.dlls/ -*.exe.manifest -*.pc - -*.l -*.l.cpp-options - -# Generated documentation. -# -*.pdf -*.ps - -# Generated build system files. -# -*-dynamic.make - -# Generated .gitignore files. -# -.gitignore diff --git a/GPLv2 b/GPLv2 deleted file mode 100644 index 3912109..0000000 --- a/GPLv2 +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 0e6dcc6..0000000 --- a/INSTALL +++ /dev/null @@ -1,81 +0,0 @@ -Building on UNIX -================ - -The following build instructions are for the Linux/UNIX/Mac OS X -operating systems as well as for Cygwin and MinGW on Windows. - -The standard autotools-based build system is used on these platforms. After -unpacking the source code archive, change to the libodb package directory -(referred to as libodb/ from now on) and run the configure script: - -./configure - -To see the available configuration options run configure with --help: - -./configure --help - -As an example, the following configure command only builds shared libraries, -uses the specified C++ compiler, and compiles with optimization and without -debug information: - -./configure --disable-static CXX=g++-4.5 CXXFLAGS=-O3 - -Once configuration is complete, run make to build libodb: - -make - -Once the build is completed successfully, you can install the libodb headers -and libraries using the install target (you may need to do this step as root -depending on the installation directory): - -make install - - -Building on Windows -=================== - -The following build instructions are for Windows using Microsoft Visual -Studio. If you would like to build libodb 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. To build libodb, unpack the source code archive and open the -libodb-vc.sln file located in the libodb package directory (referred -to as libodb\ from now on). Here is the version of Visual Studio that -you are using. Once the solution is open, select the desired build -configuration (Debug or Release) and platform (Win32 or x64) and build -the solution. - -The resulting 32-bit DLLs and import libraries are placed into the -libodb\bin\ and libodb\lib\ directories, respectively. Similarly, the -64-bit DLLs and import libraries are placed into libodb\bin64\ and -libodb\lib64\. The Release versions of the import libraries are named -odb.lib and the Debug versions are named odb-d.lib. - -To configure Visual Studio to automatically locate the libodb headers, -DLLs, and import libraries, add the following paths to your VC++ -Directories: - -Win32: - - Include: ...\libodb - Library: ...\libodb\lib - Executable: ...\libodb\bin - -x64: - - Include: ...\libodb - Library: ...\libodb\lib64 - Executable: ...\libodb\bin64 - -Note also that by default libodb uses the __declspec(thread) storage-class -modifier for TLS support. This mechanism is known not to work correctly on -Windows XP/Server 2003 and earlier versions of Windows if a DLL that uses -this modifier is loaded dynamically. If you are planning to link libodb to a -DLL that will be loaded dynamically (e.g., delay loading, COM DLL, explicit -LoadLibrary() call, etc), then you will need to comment out the definition -of the ODB_THREADS_TLS_DECLSPEC macro in the odb\details\config-vc.h file -prior to building libodb. On the other hand, if you plan to link libodb -directly to an executable or another DLL that will be linked directly to -an executable or if you only need to support Windows Vista/Server 2008, -then you don't need to make this change. diff --git a/INSTALL-GIT b/INSTALL-GIT deleted file mode 100644 index f917af5..0000000 --- a/INSTALL-GIT +++ /dev/null @@ -1,78 +0,0 @@ -The following instructions describe how to work with the source code that was -checked out from the git repository. - -The major difference between using a released source code package and source -code from the repository is that the former does not contain autotools-based -makefiles or Visual Studio project files. Instead, it contains templates for -these files as well as its own, custom build system. This build system is -used for development as well as to automatically generate the autotools and -Visual Studio files. - -This file describes how to use this build system to build the package as well -as to create a release-ready source distribution which contains the autotools -build system and Visual Studio project files. - - -Prerequisites -============= - -Besides the prerequisites listed in the INSTALL file, you will need the -following additional packages: - - - GNU bash >= 2.0.0 http://www.gnu.org/software/bash/ - - GNU make >= 3.81 http://www.gnu.org/software/make/ - - build >= latest http://www.codesynthesis.com/projects/build/ - -If you are planning to create the source code distributions, then you will -also need the following packages: - - - GNU m4 >= 1.4.0 http://www.gnu.org/software/m4/ - - GNU sed >= 4.0.0 http://www.gnu.org/software/sed/ - - tofrodos >= 1.7.0 http://www.thefreecountry.com/tofrodos/ - -As we as the GNU autotools: - - - GNU libtool >= 2.2.6b http://www.gnu.org/software/libtool/ - - GNU autoconf >= 2.67 http://www.gnu.org/software/autoconf/ - - GNU automake >= 1.11.1 http://www.gnu.org/software/automake/ - -Any reasonably up to date GNU/Linux installation would normally have all of -the above packages already present, except for build and maybe tofrodos. - - -Configuring and Building -======================== - -To build the source code simply run make in the root directory of the package. -The first time you run make, the build process will also configure the -package by asking you several questions. On the subsequent runs, make will -only rebuild what has changed. - -To run the automated test suite (if any), run 'make test'. To clean the object -files, executables, etc., run 'make clean'. To de-configure the package (that -is, to remove configuration files in addition to objects, executables, etc.), -run 'make disfigure'. - - -Creating Distribution -===================== - -To create the source code distribution, use the dist make target as well as -the dist_prefix variable to specify the directory where the distribution files -should be placed. For example: - -make dist dist_prefix=/tmp/package-1.1.0 - -Once the distribution files are ready, change to the distribution directory -and run the bootstrap script to bootstrap the autotools build system, for -example: - -cd /tmp/package-1.1.0 -./bootsrap - -To create the source code archives, use the autotools build system. First -configuring the package (see the INSTALL file for more information on this -step) and then use the dist target to make the archives, for example: - -./configure -make dist diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 9d92da1..0000000 --- a/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2009-2024 Code Synthesis Tools CC. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -For more information on ODB licensing as well as for answers to -some of the common licensing questions, visit the ODB License -page: - -http://www.codesynthesis.com/products/odb/license.xhtml - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index e44eb5c..0000000 --- a/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -# file : Makefile.am -# license : GNU GPL v2; see accompanying LICENSE file - -SUBDIRS = __path__(dirs) -dist_doc_DATA = __file__(docs) -EXTRA_DIST = __file__(extra_dist) -ACLOCAL_AMFLAGS = -I m4 - -pkgconfigdir = @pkgconfigdir@ -pkgconfig_DATA= libodb.pc diff --git a/NEWS b/NEWS deleted file mode 100644 index 72d0f8b..0000000 --- a/NEWS +++ /dev/null @@ -1 +0,0 @@ -See the common NEWS file in the ODB compiler package. diff --git a/README b/README deleted file mode 100644 index 902e20b..0000000 --- a/README +++ /dev/null @@ -1,20 +0,0 @@ -ODB is an object-relational mapping (ORM) system for C++. It provides -tools, APIs, and library support that allow you to persist C++ objects -to a relational database (RDBMS) without having to deal with tables, -columns, or SQL and without manually writing any of the mapping code. -For more information see: - -http://www.codesynthesis.com/products/odb/ - -This package contains the common ODB runtime library. Every application -that includes code generated by the ODB compiler will need to link to -this library. - -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. - -Send questions, bug reports, or any other feedback to the -odb-users@codesynthesis.com mailing list. diff --git a/README-GIT b/README-GIT deleted file mode 100644 index 5375489..0000000 --- a/README-GIT +++ /dev/null @@ -1,4 +0,0 @@ -The checked out odb/version-build2.hxx will be overwritten during the build -process but these changes should be ignored. To do this automatically, run: - -git update-index --assume-unchanged odb/version-build2.hxx diff --git a/bootstrap b/bootstrap deleted file mode 100755 index 85d1399..0000000 --- a/bootstrap +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/sh - -# file : bootstrap -# license : GNU GPL v2; see accompanying LICENSE file - -# -# Bootstrap the automake build system. -# - -rm -f config.cache - -if test ! -d m4; then - mkdir m4 -fi - -autoreconf --install diff --git a/build/.gitignore b/build/.gitignore deleted file mode 100644 index 4a730a3..0000000 --- a/build/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -config.build -root/ -bootstrap/ diff --git a/build/bootstrap.build b/build/bootstrap.build deleted file mode 100644 index 9c8d1a9..0000000 --- a/build/bootstrap.build +++ /dev/null @@ -1,10 +0,0 @@ -# file : build/bootstrap.build -# license : GNU GPL v2; see accompanying LICENSE file - -project = libodb - -using version -using config -using dist -using test -using install diff --git a/build/bootstrap.make b/build/bootstrap.make deleted file mode 100644 index f26a5dc..0000000 --- a/build/bootstrap.make +++ /dev/null @@ -1,73 +0,0 @@ -# file : build/bootstrap.make -# license : GNU GPL v2; see accompanying LICENSE file - -project_name := libodb - -# 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 - -# Configuration -# -$(call include,$(scf_root)/configuration.make) - -# Aliases -# -.PHONY: $(out_base)/ \ - $(out_base)/.test \ - $(out_base)/.dist \ - $(out_base)/.clean - -ifdef %interactive% - -.PHONY: test dist clean - -test: $(out_base)/.test -dist: $(out_base)/.dist -clean: $(out_base)/.clean - -ifneq ($(filter $(.DEFAULT_GOAL),test dist clean),) -.DEFAULT_GOAL := -endif - -endif - -# Make sure the distribution prefix is set if the goal is dist. -# -ifneq ($(filter $(MAKECMDGOALS),dist),) -ifeq ($(dist_prefix),) -$(error dist_prefix is not set) -endif -endif - -# If we don't have dependency auto-generation then we need to manually -# make sure that generated files are generated before C++ file are -# compiler. To do this we make the object files ($2) depend in order- -# only on generated files ($3). -# -ifeq ($(cxx_id),generic) - -define include-dep -$(if $2,$(eval $2: | $3)) -endef - -else - -define include-dep -$(call -include,$1) -endef - -endif - -# Don't include dependency info for certain targets. -# -ifneq ($(filter $(MAKECMDGOALS),clean disfigure dist),) -include-dep = -endif diff --git a/build/configuration-rules.make b/build/configuration-rules.make deleted file mode 100644 index adfaf3c..0000000 --- a/build/configuration-rules.make +++ /dev/null @@ -1,16 +0,0 @@ -# file : build/configuration-rules.make -# license : GNU GPL v2; see accompanying LICENSE file - -$(dcf_root)/configuration-dynamic.make: | $(dcf_root)/. - $(call message,,$(scf_root)/configure $@) - -ifndef %foreign% - -disfigure:: - $(call message,rm $$1,rm -f $$1,$(dcf_root)/configuration-dynamic.make) - -endif - -ifeq ($(.DEFAULT_GOAL),$(dcf_root)/configuration-dynamic.make) -.DEFAULT_GOAL := -endif diff --git a/build/configuration.make b/build/configuration.make deleted file mode 100644 index 7a00b14..0000000 --- a/build/configuration.make +++ /dev/null @@ -1,20 +0,0 @@ -# file : build/configuration.make -# license : GNU GPL v2; see accompanying LICENSE file - -$(call include-once,$(scf_root)/configuration-rules.make,$(dcf_root)) - -# Dynamic configuration. -# -libodb_threads := - -$(call -include,$(dcf_root)/configuration-dynamic.make) - -ifdef libodb_threads - -$(out_root)/%: libodb_threads := $(libodb_threads) - -else - -.NOTPARALLEL: - -endif diff --git a/build/configure b/build/configure deleted file mode 100755 index 0109cb2..0000000 --- a/build/configure +++ /dev/null @@ -1,24 +0,0 @@ -#! /usr/bin/env bash - -# file : build/configure -# license : GNU GPL v2; see accompanying LICENSE file - -# $1 out file -# -# bld_root - build root -# project_name - project name -# - -source $bld_root/dialog.bash - -$echo -$echo "Please select the threading implementation:" -$echo -$echo "(1) POSIX" -$echo "(2) Win32" -$echo "(3) None" -$echo - -threads=`read_option "posix win32 none" "posix"` - -echo "libodb_threads := $threads" >$1 diff --git a/build/export.build b/build/export.build deleted file mode 100644 index 56312c8..0000000 --- a/build/export.build +++ /dev/null @@ -1,9 +0,0 @@ -# file : build/export.build -# license : GNU GPL v2; see accompanying LICENSE file - -$out_root/ -{ - include odb/ -} - -export $out_root/odb/lib{odb} diff --git a/build/export/libodb/stub.make b/build/export/libodb/stub.make deleted file mode 100644 index 10eeb22..0000000 --- a/build/export/libodb/stub.make +++ /dev/null @@ -1,8 +0,0 @@ -# file : build/export/libodb/stub.make -# license : GNU GPL v2; see accompanying LICENSE file - -$(call include-once,$(src_root)/odb/makefile,$(out_root)) - -$(call export,\ - l: $(out_root)/odb/odb.l,\ - cpp-options: $(out_root)/odb/odb.l.cpp-options) diff --git a/build/import/libodb/configuration-rules.make b/build/import/libodb/configuration-rules.make deleted file mode 100644 index 340c418..0000000 --- a/build/import/libodb/configuration-rules.make +++ /dev/null @@ -1,13 +0,0 @@ -# file : build/import/libodb/configuration-rules.make -# license : GNU GPL v2; see accompanying LICENSE file - -$(dcf_root)/import/libodb/configuration-dynamic.make: | $(dcf_root)/import/libodb/. - $(call message,,$(scf_root)/import/libodb/configure $@) - -ifndef %foreign% - -$(dcf_root)/.disfigure:: - $(call message,rm $(dcf_root)/import/libodb/configuration-dynamic.make,\ -rm -f $(dcf_root)/import/libodb/configuration-dynamic.make) - -endif diff --git a/build/import/libodb/configure b/build/import/libodb/configure deleted file mode 100755 index 261a202..0000000 --- a/build/import/libodb/configure +++ /dev/null @@ -1,53 +0,0 @@ -#! /usr/bin/env bash - -# file : build/import/libodb/configure -# license : GNU GPL v2; 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 'libodb' for '$project_name'." -$echo - -$echo -$echo "Would you like to configure dependency on the installed " -$echo "version of 'libodb' 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 'libodb'." -$echo - -src_root=`read_path --directory --exist` - -$echo -$echo "Please enter the out_root for 'libodb'." -$echo - -out_root=`read_path --directory $src_root` - -fi - -echo libodb_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/libodb/stub.make b/build/import/libodb/stub.make deleted file mode 100644 index 04dc786..0000000 --- a/build/import/libodb/stub.make +++ /dev/null @@ -1,28 +0,0 @@ -# file : build/import/libodb/stub.make -# license : GNU GPL v2; see accompanying LICENSE file - -$(call include-once,$(scf_root)/import/libodb/configuration-rules.make,$(dcf_root)) - -libodb_installed := - -$(call -include,$(dcf_root)/import/libodb/configuration-dynamic.make) - -ifdef libodb_installed - -ifeq ($(libodb_installed),y) - -$(call export,l: -lodb,cpp-options: ) - -else - -# Include export stub. -# -$(call include,$(scf_root)/export/libodb/stub.make) - -endif - -else - -.NOTPARALLEL: - -endif diff --git a/build/root.build b/build/root.build deleted file mode 100644 index 882047d..0000000 --- a/build/root.build +++ /dev/null @@ -1,17 +0,0 @@ -# file : build/root.build -# license : GNU GPL v2; see accompanying LICENSE file - -cxx.std = latest - -using cxx - -hxx{*}: extension = hxx -ixx{*}: extension = ixx -txx{*}: extension = txx -cxx{*}: extension = cxx - -if ($cxx.target.system == 'win32-msvc') - cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS - -if ($cxx.class == 'msvc') - cxx.coptions += /wd4251 /wd4275 /wd4800 diff --git a/buildfile b/buildfile deleted file mode 100644 index 406853f..0000000 --- a/buildfile +++ /dev/null @@ -1,9 +0,0 @@ -# file : buildfile -# license : GNU GPL v2; see accompanying LICENSE file - -./: {*/ -build/ -m4/} doc{INSTALL NEWS README} legal{GPLv2 LICENSE} manifest - -# Don't install tests or the INSTALL file. -# -tests/: install = false -doc{INSTALL}@./: install = false diff --git a/configure.ac b/configure.ac deleted file mode 100644 index e368d3b..0000000 --- a/configure.ac +++ /dev/null @@ -1,67 +0,0 @@ -# file : configure.ac -# license : GNU GPL v2; see accompanying LICENSE file - -AC_PREREQ(2.60) -AC_INIT([libodb], [__value__(version)], [odb-users@codesynthesis.com]) -AC_CONFIG_AUX_DIR([config]) -AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_SRCDIR([odb/version.hxx]) - -AM_INIT_AUTOMAKE([-Wall -Werror foreign nostdinc subdir-objects dist-bzip2 dist-zip tar-ustar]) -m4_equote()[m4_ifdef]m4_dquote()([AM_PROG_AR], [AM_PROG_AR]) # Required by automake 1.12. - -LT_INIT([win32-dll]) - -AC_CANONICAL_HOST - -# Check for C++ compiler and use it to compile the tests. -# -AC_PROG_CXX -AC_LANG(C++) - -# Create the libtool executable so that we can use it in further tests. -# -LT_OUTPUT - -# Check for Windows. -# -win32=no -case $host_os in - windows* | mingw*) - win32=yes - ;; -esac - -AM_CONDITIONAL([ODB_WIN32], [test x$win32 = xyes]) - -# Check for threads. -# -THREADS - -AM_CONDITIONAL([ODB_THREADS_NONE], [test x$threads = xnone]) -AM_CONDITIONAL([ODB_THREADS_WIN32], [test x$threads = xwin32]) -AM_CONDITIONAL([ODB_THREADS_POSIX], [test x$threads = xposix]) - -AS_IF([test x$threads = xnone], AC_DEFINE([ODB_THREADS_NONE], [1], [Have no threads.])) -AS_IF([test x$threads = xwin32], AC_DEFINE([ODB_THREADS_WIN32], [1], [Have Win32 threads.])) -AS_IF([test x$threads = xposix], AC_DEFINE([ODB_THREADS_POSIX], [1], [Have POSIX threads.])) - -AS_IF([test x$threads_thread_keyword = xyes], AC_DEFINE([ODB_THREADS_TLS_KEYWORD], [1], [Have __thread keyword.])) - -# Define LIBODB_STATIC_LIB if we are build static library on certain platforms. -# -STATIC_LIB([LIBODB_STATIC_LIB], [Static library interface.]) - -# Allow the user to specify the pkgconfig directory. -# -PKGCONFIG - -# Check if we should disable rpath. -# -DISABLE_RPATH - -# Output. -# -AC_CONFIG_HEADERS([odb/config.h odb/details/config.h]) -AC_CONFIG_FILES([__path__(config_files)]) -AC_OUTPUT diff --git a/libodb-vc10.sln b/libodb-vc10.sln deleted file mode 100644 index 0a9c5dd..0000000 --- a/libodb-vc10.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libodb", "odb\libodb-vc10.vcxproj", "{1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|Win32.Build.0 = Debug|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|x64.ActiveCfg = Debug|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|x64.Build.0 = Debug|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|Win32.ActiveCfg = Release|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|Win32.Build.0 = Release|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|x64.ActiveCfg = Release|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libodb-vc11.sln b/libodb-vc11.sln deleted file mode 100644 index 6368225..0000000 --- a/libodb-vc11.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libodb", "odb\libodb-vc11.vcxproj", "{1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|Win32.Build.0 = Debug|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|x64.ActiveCfg = Debug|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|x64.Build.0 = Debug|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|Win32.ActiveCfg = Release|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|Win32.Build.0 = Release|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|x64.ActiveCfg = Release|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libodb-vc12.sln b/libodb-vc12.sln deleted file mode 100644 index 862f9c9..0000000 --- a/libodb-vc12.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libodb", "odb\libodb-vc12.vcxproj", "{1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|Win32.ActiveCfg = Debug|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|Win32.Build.0 = Debug|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|x64.ActiveCfg = Debug|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Debug|x64.Build.0 = Debug|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|Win32.ActiveCfg = Release|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|Win32.Build.0 = Release|Win32 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|x64.ActiveCfg = Release|x64 - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libodb-vc8.sln b/libodb-vc8.sln deleted file mode 100644 index d6e2b1c..0000000 --- a/libodb-vc8.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libodb", "odb\libodb-vc8.vcproj", "{513E5721-D318-46B0-8CFB-054042DF87A7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|Win32.ActiveCfg = Debug|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|Win32.Build.0 = Debug|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|x64.ActiveCfg = Debug|x64 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|x64.Build.0 = Debug|x64 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|Win32.ActiveCfg = Release|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|Win32.Build.0 = Release|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|x64.ActiveCfg = Release|x64 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libodb-vc9.sln b/libodb-vc9.sln deleted file mode 100644 index 2ca5e34..0000000 --- a/libodb-vc9.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libodb", "odb\libodb-vc9.vcproj", "{513E5721-D318-46B0-8CFB-054042DF87A7}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|Win32.ActiveCfg = Debug|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|Win32.Build.0 = Debug|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|x64.ActiveCfg = Debug|x64 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Debug|x64.Build.0 = Debug|x64 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|Win32.ActiveCfg = Release|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|Win32.Build.0 = Release|Win32 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|x64.ActiveCfg = Release|x64 - {513E5721-D318-46B0-8CFB-054042DF87A7}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/libodb.pc.in b/libodb.pc.in deleted file mode 100644 index 05978d6..0000000 --- a/libodb.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -# file : libodb.pc.in -# license : GNU GPL v2; see accompanying LICENSE file - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: libodb -Description: Object-relational mapping (ORM) system for C++, common runtime library -URL: http://www.codesynthesis.com/products/odb/ -Version: @VERSION@ -Libs: -L${libdir} -lodb -Cflags: -I${includedir} diff --git a/libodb/.gitignore b/libodb/.gitignore new file mode 100644 index 0000000..1c363a0 --- /dev/null +++ b/libodb/.gitignore @@ -0,0 +1,25 @@ +# Compiler/linker output. +# +*.d +*.t +*.i +*.i.* +*.ii +*.ii.* +*.o +*.obj +*.gcm +*.pcm +*.ifc +*.so +*.dylib +*.dll +*.a +*.lib +*.exp +*.pdb +*.ilk +*.exe +*.exe.dlls/ +*.exe.manifest +*.pc diff --git a/libodb/GPLv2 b/libodb/GPLv2 new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/libodb/GPLv2 @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libodb/INSTALL b/libodb/INSTALL new file mode 100644 index 0000000..46b79ad --- /dev/null +++ b/libodb/INSTALL @@ -0,0 +1,6 @@ +The easiest way to build this package is with the bpkg package manager: + +$ bpkg build libodb + +But if you don't want to use the package manager, then you can also build it +manually using the standard build2 build system. diff --git a/libodb/LICENSE b/libodb/LICENSE new file mode 100644 index 0000000..9d92da1 --- /dev/null +++ b/libodb/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2009-2024 Code Synthesis Tools CC. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +For more information on ODB licensing as well as for answers to +some of the common licensing questions, visit the ODB License +page: + +http://www.codesynthesis.com/products/odb/license.xhtml + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/libodb/README b/libodb/README new file mode 100644 index 0000000..902e20b --- /dev/null +++ b/libodb/README @@ -0,0 +1,20 @@ +ODB is an object-relational mapping (ORM) system for C++. It provides +tools, APIs, and library support that allow you to persist C++ objects +to a relational database (RDBMS) without having to deal with tables, +columns, or SQL and without manually writing any of the mapping code. +For more information see: + +http://www.codesynthesis.com/products/odb/ + +This package contains the common ODB runtime library. Every application +that includes code generated by the ODB compiler will need to link to +this library. + +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. + +Send questions, bug reports, or any other feedback to the +odb-users@codesynthesis.com mailing list. diff --git a/libodb/build/.gitignore b/libodb/build/.gitignore new file mode 100644 index 0000000..4a730a3 --- /dev/null +++ b/libodb/build/.gitignore @@ -0,0 +1,3 @@ +config.build +root/ +bootstrap/ diff --git a/libodb/build/bootstrap.build b/libodb/build/bootstrap.build new file mode 100644 index 0000000..9c8d1a9 --- /dev/null +++ b/libodb/build/bootstrap.build @@ -0,0 +1,10 @@ +# file : build/bootstrap.build +# license : GNU GPL v2; see accompanying LICENSE file + +project = libodb + +using version +using config +using dist +using test +using install diff --git a/libodb/build/export.build b/libodb/build/export.build new file mode 100644 index 0000000..56312c8 --- /dev/null +++ b/libodb/build/export.build @@ -0,0 +1,9 @@ +# file : build/export.build +# license : GNU GPL v2; see accompanying LICENSE file + +$out_root/ +{ + include odb/ +} + +export $out_root/odb/lib{odb} diff --git a/libodb/build/root.build b/libodb/build/root.build new file mode 100644 index 0000000..882047d --- /dev/null +++ b/libodb/build/root.build @@ -0,0 +1,17 @@ +# file : build/root.build +# license : GNU GPL v2; see accompanying LICENSE file + +cxx.std = latest + +using cxx + +hxx{*}: extension = hxx +ixx{*}: extension = ixx +txx{*}: extension = txx +cxx{*}: extension = cxx + +if ($cxx.target.system == 'win32-msvc') + cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS + +if ($cxx.class == 'msvc') + cxx.coptions += /wd4251 /wd4275 /wd4800 diff --git a/libodb/buildfile b/libodb/buildfile new file mode 100644 index 0000000..a04e206 --- /dev/null +++ b/libodb/buildfile @@ -0,0 +1,9 @@ +# file : buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +./: {*/ -build/} doc{INSTALL NEWS README} legal{GPLv2 LICENSE} manifest + +# Don't install tests or the INSTALL file. +# +tests/: install = false +doc{INSTALL}@./: install = false diff --git a/libodb/manifest b/libodb/manifest new file mode 100644 index 0000000..d728912 --- /dev/null +++ b/libodb/manifest @@ -0,0 +1,19 @@ +: 1 +name: libodb +version: 2.5.0-b.26.z +project: odb +summary: Common ODB runtime library +license: GPL-2.0-only +license: other: proprietary ; Not free/open source. +topics: C++, ORM, SQL, object persistence, relational database +description-file: README +changes-file: NEWS +url: https://www.codesynthesis.com/products/odb/ +doc-url: https://www.codesynthesis.com/products/odb/doc/manual.xhtml +src-url: https://git.codesynthesis.com/cgit/odb/libodb/ +email: odb-users@codesynthesis.com +build-warning-email: odb-builds@codesynthesis.com +builds: all +requires: c++11 +depends: * build2 >= 0.16.0- +depends: * bpkg >= 0.16.0- diff --git a/libodb/odb/buildfile b/libodb/odb/buildfile new file mode 100644 index 0000000..ec95e94 --- /dev/null +++ b/libodb/odb/buildfile @@ -0,0 +1,81 @@ +# file : odb/buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +lib{odb}: {hxx ixx txx cxx}{* -version-build2} \ + {hxx}{version-build2} \ + details/{hxx ixx txx}{*} \ + details/{cxx}{* -condition -lock -mutex} \ + details/build2/{h}{*} \ + details/meta/{hxx}{*} \ +details/shared-ptr/{hxx ixx txx cxx}{*} \ + details/win32/{hxx}{windows} + +# Include the generated version header into the distribution (so that we don't +# pick up an installed one) and don't remove it when cleaning in src (so that +# clean results in a state identical to distributed). +# +hxx{version-build2}: in{version-build2} $src_root/manifest +hxx{version-build2}: +{ + dist = true + clean = ($src_root != $out_root) +} + +# Build options. +# +cxx.poptions =+ "-I$out_root" "-I$src_root" -DLIBODB_BUILD2 + +obja{*}: cxx.poptions += -DLIBODB_STATIC_BUILD +objs{*}: cxx.poptions += -DLIBODB_SHARED_BUILD + +# Export options. +# +lib{odb}: cxx.export.poptions = "-I$out_root" "-I$src_root" -DLIBODB_BUILD2 + +liba{odb}: cxx.export.poptions += -DLIBODB_STATIC +libs{odb}: cxx.export.poptions += -DLIBODB_SHARED + +# For pre-releases use the complete version to make sure they cannot be used +# in place of another pre-release or the final version. See the version module +# for details on the version.* variable values. +# +if $version.pre_release + lib{odb}: bin.lib.version = @"-$version.project_id" +else + lib{odb}: bin.lib.version = @"-$version.major.$version.minor" + +# Install into the odb/ subdirectory of, say, /usr/include/ recreating +# subdirectories. +# +install_include = [dir_path] include/odb/ + +{hxx ixx txx}{*}: +{ + install = $install_include + install.subdirs = true +} + +if ($cxx.target.class != "windows") + details/win32/*: install = false + +# We want these to be picked up whether LIBODB_BUILD2 is defined or not. +# +hxx{version}@./: install = false +hxx{version-build2}: install = $install_include/version.hxx +hxx{version-build2-stub}@./: install = $install_include/version-build2.hxx + +details/build2/ +{ + h{*}: install = false + + if ($cxx.target.system == 'win32-msvc') + { + h{config-vc}@./: install = $install_include/details/ + h{config-vc-stub}@./: install = $install_include/details/build2/config-vc.h + } + else + { + h{config}@./: install = $install_include/details/ + h{config-stub}@./: install = $install_include/details/build2/config.h + } +} diff --git a/libodb/odb/c-array-traits.hxx b/libodb/odb/c-array-traits.hxx new file mode 100644 index 0000000..fff7880 --- /dev/null +++ b/libodb/odb/c-array-traits.hxx @@ -0,0 +1,103 @@ +// file : odb/c-array-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_C_ARRAY_TRAITS_HXX +#define ODB_C_ARRAY_TRAITS_HXX + +#include + +#include // std::size_t +#include + +#include + +namespace odb +{ + // Optional mapping of C arrays as containers. Note that this mapping is not + // enable by default. To enable, pass the following options to the ODB + // compiler: + // + // --odb-epilogue '#include ' + // --hxx-prologue '#include ' + // + // Note also that the array types have to be named, for example: + // + // class object + // { + // // composite_type values[5]; // Won't work. + // + // typedef composite_type composite_array[5]; + // composite_array values; + // }; + // + // Finally, this mapping is disabled for the char[N] and wchar_t[N] types + // (they are mapped as strings by default). + // + template + class access::container_traits + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef V container_type[N]; + + typedef V value_type; + typedef std::size_t index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (index_type i (0); i < N; ++i) + f.insert (i, c[i]); + } + + static void + load (container_type& c, bool more, const functions& f) + { + index_type i (0); + + for (; more && i < N; ++i) + { + index_type dummy; + more = f.select (dummy, c[i]); + } + + assert (!more && i == N); + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (index_type i (0); i < N; ++i) + f.insert (i, c[i]); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; + + // Disable for char[N] and wchar_t[N]. + // +#ifdef ODB_COMPILER + template + class access::container_traits; + +#ifdef _WIN32 + template + class access::container_traits; +#endif +#endif +} + +#include + +#endif // ODB_C_ARRAY_TRAITS_HXX diff --git a/libodb/odb/cache-traits.hxx b/libodb/odb/cache-traits.hxx new file mode 100644 index 0000000..a8cf750 --- /dev/null +++ b/libodb/odb/cache-traits.hxx @@ -0,0 +1,182 @@ +// file : odb/cache-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_CACHE_TRAITS_HXX +#define ODB_CACHE_TRAITS_HXX + +#include + +#include +#include +#include +#include +#include + +namespace odb +{ + // pointer_cache_traits + // + // Caching traits for objects passed by pointer. P should be the canonical + // pointer (non-const). + // + template + struct pointer_cache_traits_impl + { + typedef P pointer_type; + typedef S session_type; + typedef odb::pointer_traits pointer_traits; + typedef typename pointer_traits::element_type object_type; + typedef typename object_traits::id_type id_type; + typedef typename session_type::template cache_position + position_type; + + struct insert_guard + { + insert_guard () {} + insert_guard (const position_type& pos): pos_ (pos) {} + ~insert_guard () {session_type::_cache_erase (pos_);} + + const position_type& + position () const {return pos_;} + + void + release () {pos_ = position_type ();} + + // Note: doesn't call erase() on the old position (assumes empty). + // + void + reset (const position_type& pos) {pos_ = pos;} + + private: + position_type pos_; + }; + + // Cache management. + // + // We need the insert() overload with explicit id to handle self- + // references. In such cases the object is not yet loaded and the + // id member does not contain the correct id. + // + // Qualify the database type to resolve a phony ambiguity in VC 10. + // + static position_type + insert (odb::database& db, const id_type& id, const pointer_type& p) + { + return session_type::template _cache_insert (db, id, p); + } + + static position_type + insert (odb::database& db, const pointer_type& p) + { + const id_type& id ( + object_traits::id ( + pointer_traits::get_ref (p))); + + return session_type::template _cache_insert (db, id, p); + } + + static pointer_type + find (odb::database& db, const id_type& id) + { + return session_type::template _cache_find (db, id); + } + + static void + erase (const position_type& p) + { + session_type::template _cache_erase (p); + } + + // Notifications. + // + static void + persist (const position_type& p) + { + session_type::template _cache_persist (p); + } + + static void + load (const position_type& p) + { + session_type::template _cache_load (p); + } + + static void + update (odb::database& db, const object_type& obj) + { + session_type::template _cache_update (db, obj); + } + + static void + erase (odb::database& db, const id_type& id) + { + session_type::template _cache_erase (db, id); + } + }; + + // Unique pointers don't work with the object cache. + // + template + struct pointer_cache_traits_impl: + no_op_pointer_cache_traits

{}; + + template + struct pointer_cache_traits: + pointer_cache_traits_impl::kind> {}; + + // reference_cache_traits + // + // Caching traits for objects passed by reference. T should be the + // canonical object type (non-const). Only if the object pointer + // kind is raw do we add the object to the session. + // + template + struct reference_cache_traits_impl: no_op_reference_cache_traits {}; + + template + struct reference_cache_traits_impl + { + typedef T object_type; + typedef typename object_traits::pointer_type pointer_type; + typedef typename object_traits::id_type id_type; + + typedef pointer_cache_traits pointer_traits; + typedef typename pointer_traits::position_type position_type; + typedef typename pointer_traits::insert_guard insert_guard; + + static position_type + insert (odb::database& db, const id_type& id, object_type& obj) + { + pointer_type p (&obj); + return pointer_traits::insert (db, id, p); + } + + static position_type + insert (odb::database& db, object_type& obj) + { + pointer_type p (&obj); + return pointer_traits::insert (db, p); + } + + static void + persist (const position_type& p) + { + pointer_traits::persist (p); + } + + static void + load (const position_type& p) + { + pointer_traits::load (p); + } + }; + + template + struct reference_cache_traits: + reference_cache_traits_impl< + T, S, pointer_traits::pointer_type>::kind> {}; +} + +#include + +#endif // ODB_CACHE_TRAITS_HXX diff --git a/libodb/odb/callback.hxx b/libodb/odb/callback.hxx new file mode 100644 index 0000000..aaa066f --- /dev/null +++ b/libodb/odb/callback.hxx @@ -0,0 +1,42 @@ +// file : odb/callback.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_CALLBACK_HXX +#define ODB_CALLBACK_HXX + +#include + +#include // odb::core + +namespace odb +{ + struct callback_event + { + enum value + { + pre_persist, + post_persist, + pre_load, + post_load, + pre_update, + post_update, + pre_erase, + post_erase + }; + + callback_event (value v): v_ (v) {} + operator value () const {return v_;} + + private: + value v_; + }; + + namespace common + { + using odb::callback_event; + } +} + +#include + +#endif // ODB_CALLBACK_HXX diff --git a/libodb/odb/connection.cxx b/libodb/odb/connection.cxx new file mode 100644 index 0000000..29743a2 --- /dev/null +++ b/libodb/odb/connection.cxx @@ -0,0 +1,125 @@ +// file : odb/connection.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include +#include +#include // prepared_* + +using namespace std; + +namespace odb +{ + // connection + // + connection:: + ~connection () + { + assert (prepared_queries_ == 0); + assert (prepared_map_.empty ()); + } + + void connection:: + clear_prepared_map () + { + for (prepared_map_type::iterator i (prepared_map_.begin ()), + e (prepared_map_.end ()); i != e; ++i) + { + if (i->second.params != 0) + i->second.params_deleter (i->second.params); + } + + prepared_map_.clear (); + } + + void connection:: + recycle () + { + while (prepared_queries_ != 0) + { + prepared_queries_->stmt.reset (); + prepared_queries_->list_remove (); + } + } + + void connection:: + invalidate_results () + { + while (results_ != 0) + { + results_->invalidate (); + results_->list_remove (); + } + } + + void connection:: + cache_query_ (prepared_query_impl* pq, + const type_info& ti, + void* params, + const type_info* params_info, + void (*params_deleter) (void*)) + { + pair r ( + prepared_map_.insert ( + prepared_map_type::value_type (pq->name, prepared_entry_type ()))); + + if (!r.second) + throw prepared_already_cached (pq->name); + + prepared_entry_type& e (r.first->second); + + // Mark this prepared query as cached , get its ref count to 1 + // (prepared_query instances now reference this impl object), + // and remove it from the invalidation list. + // + pq->cached = true; + + while (pq->_ref_count () > 1) + pq->_dec_ref (); + + pq->list_remove (); + + e.prep_query.reset (pq); + e.type_info = &ti; + e.params = params; + e.params_info = params_info; + e.params_deleter = params_deleter; + } + + prepared_query_impl* connection:: + lookup_query_ (const char* name, + const type_info& ti, + void** params, + const type_info* params_info) const + { + prepared_map_type::const_iterator i (prepared_map_.find (name)); + + if (i == prepared_map_.end ()) + { + // Use a factory, if there is one. + // + if (factory_.database ().call_query_factory ( + name, const_cast (*this))) + i = prepared_map_.find (name); + } + + if (i == prepared_map_.end ()) + return 0; + + // Make sure the types match. + // + if (*i->second.type_info != ti) + throw prepared_type_mismatch (name); + + if (params != 0) + { + if (*i->second.params_info != *params_info) + throw prepared_type_mismatch (name); + + *params = i->second.params; + } + + return i->second.prep_query.get (); + } +} diff --git a/libodb/odb/connection.hxx b/libodb/odb/connection.hxx new file mode 100644 index 0000000..8ce4544 --- /dev/null +++ b/libodb/odb/connection.hxx @@ -0,0 +1,228 @@ +// file : odb/connection.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_CONNECTION_HXX +#define ODB_CONNECTION_HXX + +#include + +#include +#include +#include // std::auto_ptr, std::unique_ptr +#include // std::size_t +#include + +#include +#include +#include +#include + +#include // ODB_CXX11 +#include +#include +#include + +namespace odb +{ + class transaction_impl; + class connection_factory; + + class connection; + typedef details::shared_ptr connection_ptr; + + class LIBODB_EXPORT connection: public details::shared_base + { + public: + typedef odb::database database_type; + + database_type& + database (); + + // Transactions. + // + public: + virtual transaction_impl* + begin () = 0; + + // Native database statement execution. Note that unlike the + // versions in the database class, these can be executed + // without a transaction. + // + public: + unsigned long long + execute (const char* statement); + + unsigned long long + execute (const std::string& statement); + + virtual unsigned long long + execute (const char* statement, std::size_t length) = 0; + + // Query preparation. + // + public: + template + prepared_query + prepare_query (const char* name, const char*); + + template + prepared_query + prepare_query (const char* name, const std::string&); + + template + prepared_query + prepare_query (const char* name, const query&); + + template + void + cache_query (const prepared_query&); + +#ifdef ODB_CXX11 + template + void + cache_query (const prepared_query&, std::unique_ptr

params); +#else + template + void + cache_query (const prepared_query&, std::auto_ptr

params); +#endif + + template + prepared_query + lookup_query (const char* name); + + template + prepared_query + lookup_query (const char* name, P*& params); + + // SQL statement tracing. + // + public: + typedef odb::tracer tracer_type; + + void + tracer (tracer_type&); + + void + tracer (tracer_type*); + + tracer_type* + tracer () const; + + public: + // Store the transaction-spacific tracer in the connection. If we + // were to store it in the transaction, then in order to check if + // it was set, we would need to get the transaction instance using + // the current() API. But that requires a TLS lookup, which can be + // slow. + // + tracer_type* + transaction_tracer () const; + + public: + virtual + ~connection (); + + // Recycle the connection to be used by another thread. This call + // invalidates uncached prepared queries. + // + void + recycle (); + + protected: + connection (connection_factory&); + + template ::kind> + struct query_; + + virtual void + cache_query_ (prepared_query_impl* pq, + const std::type_info& ti, + void* params, + const std::type_info* params_info, + void (*params_deleter) (void*)); + + prepared_query_impl* + lookup_query_ (const char* name, + const std::type_info& ti, + void** params, // out + const std::type_info* params_info) const; + + template + static void + params_deleter (void*); + + private: + connection (const connection&); + connection& operator= (const connection&); + + // Prepared query cache. + // + protected: + struct prepared_entry_type + { + details::shared_ptr prep_query; + const std::type_info* type_info; + void* params; + const std::type_info* params_info; + void (*params_deleter) (void*); + }; + + typedef + std::map + prepared_map_type; + + prepared_map_type prepared_map_; + + void + clear_prepared_map (); + + protected: + connection_factory& factory_; + tracer_type* tracer_; + + // Active query result list. + // + protected: + friend class result_impl; + result_impl* results_; + + void + invalidate_results (); + + // Prepared but uncached query list (cached ones are stored in + // prepared_map_). + // + protected: + friend class prepared_query_impl; + prepared_query_impl* prepared_queries_; + + // Implementation details. + // + public: + tracer_type* transaction_tracer_; + }; + + class connection_factory + { + public: + typedef odb::database database_type; + + connection_factory (): db_ (0) {} + + database_type& + database () {return *db_;} + + protected: + database_type* db_; + }; +} + +#include +#include + +#include + +#endif // ODB_CONNECTION_HXX diff --git a/libodb/odb/connection.ixx b/libodb/odb/connection.ixx new file mode 100644 index 0000000..d19390a --- /dev/null +++ b/libodb/odb/connection.ixx @@ -0,0 +1,131 @@ +// file : odb/connection.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::string +#include + +namespace odb +{ + inline connection:: + connection (connection_factory& f) + : factory_ (f), + tracer_ (0), + results_ (0), + prepared_queries_ (0), + transaction_tracer_ (0) + { + } + + inline connection::database_type& connection:: + database () + { + return factory_.database (); + } + + inline unsigned long long connection:: + execute (const char* st) + { + return execute (st, std::strlen (st)); + } + + inline unsigned long long connection:: + execute (const std::string& st) + { + return execute (st.c_str (), st.size ()); + } + + template + inline prepared_query connection:: + prepare_query (const char* n, const char* q) + { + return prepare_query (n, query (q)); + } + + template + inline prepared_query connection:: + prepare_query (const char* n, const std::string& q) + { + return prepare_query (n, query (q)); + } + + template + inline prepared_query connection:: + prepare_query (const char* n, const query& q) + { + return query_::call (*this, n, q); + } + + template + inline void connection:: + cache_query (const prepared_query& pq) + { + assert (pq); + cache_query_ (pq.impl_, typeid (T), 0, 0, 0); + } + +#ifdef ODB_CXX11 + template + inline void connection:: + cache_query (const prepared_query& pq, std::unique_ptr

params) + { + assert (pq); + assert (params); + cache_query_ ( + pq.impl_, typeid (T), params.get (), &typeid (P), ¶ms_deleter

); + params.release (); + } +#else + template + inline void connection:: + cache_query (const prepared_query& pq, std::auto_ptr

params) + { + assert (pq); + assert (params.get () != 0); + cache_query_ ( + pq.impl_, typeid (T), params.get (), &typeid (P), ¶ms_deleter

); + params.release (); + } +#endif + + template + inline prepared_query connection:: + lookup_query (const char* name) + { + return prepared_query (lookup_query_ (name, typeid (T), 0, 0)); + } + + template + inline prepared_query connection:: + lookup_query (const char* name, P*& params) + { + return prepared_query ( + lookup_query_ (name, + typeid (T), + reinterpret_cast (¶ms), + &typeid (P))); + } + + inline void connection:: + tracer (tracer_type& t) + { + tracer_ = &t; + } + + inline void connection:: + tracer (tracer_type* t) + { + tracer_ = t; + } + + inline connection::tracer_type* connection:: + tracer () const + { + return tracer_; + } + + inline connection::tracer_type* connection:: + transaction_tracer () const + { + return transaction_tracer_; + } +} diff --git a/libodb/odb/connection.txx b/libodb/odb/connection.txx new file mode 100644 index 0000000..a082f14 --- /dev/null +++ b/libodb/odb/connection.txx @@ -0,0 +1,44 @@ +// file : odb/connection.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + template + struct connection::query_ + { + template + static prepared_query + call (connection& c, const char* n, const Q& q) + { + // C++ compiler complaining there is no prepare_query()? Perhaps + // you forgot to specify --generate-prepared when compiling your + // persistent classes. + // + return prepared_query ( + object_traits_impl::prepare_query (c, n, q)); + } + }; + + template + struct connection::query_ + { + template + static prepared_query + call (connection& c, const char* n, const Q& q) + { + // C++ compiler complaining there is no prepare_query()? Perhaps + // you forgot to specify --generate-prepared when compiling your + // views. + // + return prepared_query ( + view_traits_impl::prepare_query (c, n, q)); + } + }; + + template + void connection:: + params_deleter (void* p) + { + delete static_cast (p); + } +} diff --git a/libodb/odb/container-traits.hxx b/libodb/odb/container-traits.hxx new file mode 100644 index 0000000..e2f44ce --- /dev/null +++ b/libodb/odb/container-traits.hxx @@ -0,0 +1,219 @@ +// file : odb/container-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_CONTAINER_TRAITS_HXX +#define ODB_CONTAINER_TRAITS_HXX + +#include + +#include +#include // ODB_CXX11 + +namespace odb +{ + // Keep this enum synchronized with the one in odb/odb/context.hxx. + // + enum container_kind + { + ck_ordered, + ck_set, + ck_multiset, + ck_map, + ck_multimap + }; + + // + // Container API provided by the generated code. + // + + // Ordered containers. + // + template + struct ordered_functions + { + typedef I index_type; + typedef V value_type; + + // Return true if the order is preserved in the database. If the + // order is not preserved, then the index argument in the functions + // below is not used. + // + bool + ordered () const + { + return ordered_; + } + + void + insert (I index, const V& value) const + { + insert_ (index, value, data_); + } + + bool + select (I& next_index, V& next_value) const + { + return select_ (next_index, next_value, data_); + } + + void + delete_ () const + { + delete__ (data_); + } + + // Implementation details. + // + public: + ordered_functions (void* data): data_ (data) {} + + public: + void* data_; + bool ordered_; + + void (*insert_) (I, const V&, void*); + bool (*select_) (I&, V&, void*); + void (*delete__) (void*); + }; + + template + struct smart_ordered_functions + { + typedef I index_type; + typedef V value_type; + + void + insert (I index, const V& value) const + { + insert_ (index, value, data_); + } + + bool + select (I& next_index, V& next_value) const + { + return select_ (next_index, next_value, data_); + } + + void + update (I index, const V& value) const + { + update_ (index, value, data_); + } + + // Delete all the elements starting with the specified index. To + // delete everything, pass 0. + // + void + delete_ (I start_index) const + { + delete__ (start_index, data_); + } + + // Implementation details. + // + public: + smart_ordered_functions (void* data) : data_ (data) {} + + public: + void* data_; + + void (*insert_) (I, const V&, void*); + bool (*select_) (I&, V&, void*); + void (*update_) (I, const V&, void*); + void (*delete__) (I, void*); + }; + + // Set/multiset containers. + // + template + struct set_functions + { + typedef V value_type; + + void + insert (const V& value) const + { + insert_ (value, data_); + } + + bool + select (V& next_value) const + { + return select_ (next_value, data_); + } + + void + delete_ () const + { + delete__ (data_); + } + + // Implementation details. + // + public: + set_functions (void* data): data_ (data) {} + + public: + void* data_; + + void (*insert_) (const V&, void*); + bool (*select_) (V&, void*); + void (*delete__) (void*); + }; + + // Map/multimap containers. + // + template + struct map_functions + { + typedef K key_type; + typedef V value_type; + + void + insert (const K& key, const V& value) const + { + insert_ (key, value, data_); + } + + bool + select (K& next_key, V& next_value) const + { + return select_ (next_key, next_value, data_); + } + + void + delete_ () const + { + delete__ (data_); + } + + // Implementation details. + // + public: + map_functions (void* data): data_ (data) {} + + public: + void* data_; + + void (*insert_) (const K&, const V&, void*); + bool (*select_) (K&, V&, void*); + void (*delete__) (void*); + }; +} + +#include + +#include +#include +#include +#include +#include + +#ifdef ODB_CXX11 +# include +# include +# include +# include +#endif + +#endif // ODB_CONTAINER_TRAITS_HXX diff --git a/libodb/odb/core.hxx b/libodb/odb/core.hxx new file mode 100644 index 0000000..bca295d --- /dev/null +++ b/libodb/odb/core.hxx @@ -0,0 +1,20 @@ +// file : odb/core.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_CORE_HXX +#define ODB_CORE_HXX + +#include + +#ifdef ODB_COMPILER +# define PRAGMA_DB_IMPL(x) _Pragma (#x) +# define PRAGMA_DB(x) PRAGMA_DB_IMPL (db x) +#else +# define PRAGMA_DB(x) +#endif + +#include + +#include + +#endif // ODB_CORE_HXX diff --git a/libodb/odb/database.cxx b/libodb/odb/database.cxx new file mode 100644 index 0000000..9e098c7 --- /dev/null +++ b/libodb/odb/database.cxx @@ -0,0 +1,83 @@ +// file : odb/database.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +#include + +using namespace std; + +namespace odb +{ + using details::lock; + + database:: + ~database () + { + } + + unsigned long long database:: + execute (const char* st, std::size_t n) + { + connection_type& c (transaction::current ().connection (*this)); + return c.execute (st, n); + } + + const database::schema_version_migration_type& database:: + schema_version_migration (const string& name) const + { + lock l (*mutex_); // Prevents concurrent loading. + + schema_version_map::const_iterator i (schema_version_map_.find (name)); + return i != schema_version_map_.end () && i->second.version != 0 + ? i->second + : load_schema_version (name); + } + + void database:: + schema_version_migration (const schema_version_migration_type& svm, + const string& name) + { + // Note: no lock, not thread-safe. + + schema_version_info& svi (schema_version_map_[name]); + if (svi.version != svm.version || svi.migration != svm.migration) + { + svi.version = svm.version; + svi.migration = svm.migration; + schema_version_seq_++; + } + } + + bool database:: + call_query_factory (const char* name, connection_type& c) const + { + query_factory_map::const_iterator i (query_factory_map_.find (name)); + + if (i == query_factory_map_.end ()) + i = query_factory_map_.find (""); // Wildcard factory. + + if (i == query_factory_map_.end ()) + return false; + + const query_factory_wrapper& fw (i->second); + if (fw.std_function == 0) + fw.function (name, c); + else + { + typedef void (*caller) (const void*, const char*, connection_type&); + fw.cast () (fw.std_function, name, c); + } + + return true; + } + + void database:: + query_factory (const char* name, query_factory_wrapper w) + { + if (w) + query_factory_map_[name] = w; // Destructive copy assignment (move). + else + query_factory_map_.erase (name); + } +} diff --git a/libodb/odb/database.hxx b/libodb/odb/database.hxx new file mode 100644 index 0000000..e18e8ee --- /dev/null +++ b/libodb/odb/database.hxx @@ -0,0 +1,657 @@ +// file : odb/database.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DATABASE_HXX +#define ODB_DATABASE_HXX + +#include + +#include // ODB_CXX11 + +#include +#include +#include // std::auto_ptr, std::unique_ptr +#include // std::size_t + +#ifdef ODB_CXX11 +# include // std::move +# include // std::function +# include // std::enable_if, std::is_convertible +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace odb +{ + class transaction_impl; + + class LIBODB_EXPORT database + { + public: + virtual + ~database (); + +#ifdef ODB_CXX11 + //database (database&&) = default; // VC 2013 + + // Note: noexcept is not specified since *_map_ (std::map) can throw. + // + database (database&& d) + : id_ (d.id_), + tracer_ (d.tracer_), + query_factory_map_ (std::move (d.query_factory_map_)), + mutex_ (std::move (d.mutex_)), + schema_version_map_ (std::move (d.schema_version_map_)), + schema_version_table_ (std::move (d.schema_version_table_)), + schema_version_seq_ (d.schema_version_seq_) + { + } +#endif + + private: + database (const database&); + database& operator= (const database&); + +#ifdef ODB_CXX11 + database& operator= (const database&&); +#endif + + // Object persistence API. + // + public: + // Make the object persistent. + // + template + typename object_traits::id_type + persist (T& object); + + template + typename object_traits::id_type + persist (const T& object); + + template + typename object_traits::id_type + persist (T* obj_ptr); + + template class P> + typename object_traits::id_type + persist (const P& obj_ptr); + + template class P> + typename object_traits::id_type + persist (const P& obj_ptr); + + template class P> + typename object_traits::id_type + persist (P& obj_ptr); + + template class P> + typename object_traits::id_type + persist (P& obj_ptr); + + template + typename object_traits::id_type + persist (const typename object_traits::pointer_type& obj_ptr); + + // Bulk persist. Can be a range of references or pointers (including + // smart pointers) to objects. + // + template + void + persist (I begin, I end, bool continue_failed = true); + + // Load an object. Throw object_not_persistent if not found. + // + template + typename object_traits::pointer_type + load (const typename object_traits::id_type& id); + + template + void + load (const typename object_traits::id_type& id, T& object); + + // Load (or reload, if it is already loaded) a section of an object. + // + template + void + load (T& object, section&); + + // Reload an object. + // + template + void + reload (T& object); + + template + void + reload (T* obj_ptr); + + template class P> + void + reload (const P& obj_ptr); + + template class P> + void + reload (const P& obj_ptr); + + template class P> + void + reload (P& obj_ptr); + + template class P> + void + reload (P& obj_ptr); + + template + void + reload (const typename object_traits::pointer_type& obj_ptr); + + // Loan an object if found. Return NULL/false if not found. + // + template + typename object_traits::pointer_type + find (const typename object_traits::id_type& id); + + template + bool + find (const typename object_traits::id_type& id, T& object); + + // Update the state of a modified objects. + // + template + void + update (T& object); + + template + void + update (T* obj_ptr); + + template class P> + void + update (const P& obj_ptr); + + template class P> + void + update (const P& obj_ptr); + + template class P> + void + update (P& obj_ptr); + + template class P> + void + update (P& obj_ptr); + + template + void + update (const typename object_traits::pointer_type& obj_ptr); + + // Bulk update. Can be a range of references or pointers (including + // smart pointers) to objects. + // + template + void + update (I begin, I end, bool continue_failed = true); + + // Update a section of an object. Throws section_not_loaded exception + // if section is not loaded. Note also that this function does not + // clear the changed flag if it is set. + // + template + void + update (const T& object, const section&); + + // Make the object transient. Throw object_not_persistent if not + // found. + // + template + void + erase (const typename object_traits::id_type& id); + + template + void + erase (T& object); + + template + void + erase (T* obj_ptr); + + template class P> + void + erase (const P& obj_ptr); + + template class P> + void + erase (const P& obj_ptr); + + template class P> + void + erase (P& obj_ptr); + + template class P> + void + erase (P& obj_ptr); + + template + void + erase (const typename object_traits::pointer_type& obj_ptr); + + // Bulk erase. + // + template + void + erase (I id_begin, I id_end, bool continue_failed = true); + + // Can be a range of references or pointers (including smart pointers) + // to objects. + // + template + void + erase (I obj_begin, I obj_end, bool continue_failed = true); + + // Erase multiple objects matching a query predicate. + // + template + unsigned long long + erase_query (); + + template + unsigned long long + erase_query (const char*); + + template + unsigned long long + erase_query (const std::string&); + + template + unsigned long long + erase_query (const odb::query&); + + // Query API. + // + template + result + query (bool cache = true); + + template + result + query (const char*, bool cache = true); + + template + result + query (const std::string&, bool cache = true); + + template + result + query (const odb::query&, bool cache = true); + + // Query one API. + // + template + typename result::pointer_type + query_one (); + + template + bool + query_one (T& object); + + template + T + query_value (); + + template + typename result::pointer_type + query_one (const char*); + + template + bool + query_one (const char*, T& object); + + template + T + query_value (const char*); + + template + typename result::pointer_type + query_one (const std::string&); + + template + bool + query_one (const std::string&, T& object); + + template + T + query_value (const std::string&); + + template + typename result::pointer_type + query_one (const odb::query&); + + template + bool + query_one (const odb::query&, T& object); + + template + T + query_value (const odb::query&); + + // Query preparation. + // + template + prepared_query + prepare_query (const char* name, const char*); + + template + prepared_query + prepare_query (const char* name, const std::string&); + + template + prepared_query + prepare_query (const char* name, const odb::query&); + + template + void + cache_query (const prepared_query&); + +#ifdef ODB_CXX11 + template + void + cache_query (const prepared_query&, std::unique_ptr

params); +#else + template + void + cache_query (const prepared_query&, std::auto_ptr

params); +#endif + + template + prepared_query + lookup_query (const char* name); + + template + prepared_query + lookup_query (const char* name, P*& params); + + // Prepared query factory. + // + public: + typedef odb::connection connection_type; + + typedef void query_factory_type (const char* name, connection_type&); + typedef query_factory_type* query_factory_ptr; + typedef details::function_wrapper< + query_factory_type> query_factory_wrapper; + +#ifndef ODB_CXX11 + void + query_factory (const char* name, query_factory_ptr); +#else + template + typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + query_factory (const char* name, F f) + { + query_factory (name, query_factory_wrapper (std::move (f))); + } +#endif + + bool + call_query_factory (const char* name, connection_type&) const; + + private: + void + query_factory (const char* name, query_factory_wrapper); + + // Native database statement execution. + // + public: + unsigned long long + execute (const char* statement); + + unsigned long long + execute (const std::string& statement); + + unsigned long long + execute (const char* statement, std::size_t length); + + // Transactions. + // + public: + virtual transaction_impl* + begin () = 0; + + // Connections. + // + public: + connection_ptr + connection (); + + // SQL statement tracing. + // + public: + typedef odb::tracer tracer_type; + + void + tracer (tracer_type&); + + void + tracer (tracer_type*); + + tracer_type* + tracer () const; + + // Database schema version. + // + public: + typedef odb::schema_version schema_version_type; + typedef odb::schema_version_migration schema_version_migration_type; + + schema_version_type + schema_version (const std::string& schema_name = "") const; + + bool + schema_migration (const std::string& schema_name = "") const; + + // Note that there is code that relies on the returned reference + // being valid until the version is changed or the database instance + // is destroyed. + // + const schema_version_migration_type& + schema_version_migration (const std::string& schema_name = "") const; + + // Set schema version and migration state manually. + // + // Note that the modifier API is not thread-safe. That is, you should + // not modify the schema version while other threads may be accessing + // or modifying the same information. + // + void + schema_version_migration (schema_version_type, + bool migration, + const std::string& schema_name = ""); + + void + schema_version_migration (const schema_version_migration_type&, + const std::string& schema_name = ""); + + // Set default schema version table for all the schema names. The table + // name should already be quoted if necessary. + // + void + schema_version_table (const std::string& table_name); + + // Set schema version table for a specific schema. + // + void + schema_version_table (const std::string& table_name, + const std::string& schema_name); + + // Schema version sequence number. It is incremented every time the + // schema version or migration flag is changed and can be used to + // detect overall version changes. The starting value is 1. + // + unsigned int + schema_version_sequence () const; + + protected: + struct schema_version_info: schema_version_migration_type + { + std::string version_table; + }; + + virtual const schema_version_info& + load_schema_version (const std::string& schema_name) const = 0; + + private: + const schema_version_info& + schema_version_migration_ (const std::string& schema_name) const; + + // Database id. + // + public: + database_id + id () const; + + protected: + database (database_id); + + protected: + virtual connection_type* + connection_ () = 0; + + protected: + template + typename object_traits::id_type + persist_ (T&); + + template + typename object_traits::id_type + persist_ (const typename object_traits::pointer_type&); + + template + void + persist_ (I, I, bool); + + template + void + persist_ (I, I, bool, details::meta::no ptr); + + template + void + persist_ (I, I, bool, details::meta::yes ptr); + + template + typename object_traits::pointer_type + load_ (const typename object_traits::id_type&); + + template + void + load_ (const typename object_traits::id_type&, T&); + + template + void + load_ (T&, section&); + + template + void + reload_ (T&); + + template + typename object_traits::pointer_type + find_ (const typename object_traits::id_type&); + + template + bool + find_ (const typename object_traits::id_type&, T&); + + template + void + update_ (T&); + + template + void + update_ (const typename object_traits::pointer_type&); + + template + void + update_ (I, I, bool); + + template + void + update_ (const T&, const section&); + + template + void + erase_ (const typename object_traits::id_type&); + + template + void + erase_ (T&); + + template + void + erase_ (const typename object_traits::pointer_type&); + + template + void + erase_id_ (I, I, bool); + + template + void + erase_object_ (I, I, bool); + + template + typename result::pointer_type + query_one_ (const Q&); + + template + bool + query_one_ (const Q&, T&); + + template + T + query_value_ (const Q&); + + template ::kind> + struct query_; + + protected: + typedef + std::map + query_factory_map; + + typedef std::map schema_version_map; + + database_id id_; + tracer_type* tracer_; + query_factory_map query_factory_map_; + + details::unique_ptr mutex_; // Dynamic for move support. + mutable schema_version_map schema_version_map_; + std::string schema_version_table_; + unsigned int schema_version_seq_; + }; +} + +#include +#include + +#include + +#endif // ODB_DATABASE_HXX diff --git a/libodb/odb/database.ixx b/libodb/odb/database.ixx new file mode 100644 index 0000000..c3cf2e2 --- /dev/null +++ b/libodb/odb/database.ixx @@ -0,0 +1,879 @@ +// file : odb/database.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::strlen() +#include // std::move +#include + +#include +#include + +namespace odb +{ + template + struct object_pointer_traits + { + typedef details::meta::no result_type; + typedef T object_type; + static const T& get_ref (const T& x) {return x;} + }; + + template + struct object_pointer_traits + { + typedef details::meta::yes result_type; + typedef T object_type; + static const T& get_ref (const T* p) {return *p;} + }; + + template + struct object_pointer_traits + { + typedef details::meta::yes result_type; + typedef T object_type; + static const T& get_ref (const T* p) {return *p;} + }; + + template class P> + struct object_pointer_traits > + { + typedef details::meta::yes result_type; + typedef T object_type; + static const T& get_ref (const P& p) { + return pointer_traits >::get_ref (p);} + }; + + template class P> + struct object_pointer_traits > + { + typedef details::meta::yes result_type; + typedef T object_type; + static const T& get_ref (const P& p) { + return pointer_traits >::get_ref (p);} + }; + + template class P> + struct object_pointer_traits > + { + typedef details::meta::yes result_type; + typedef T object_type; + static const T& get_ref (const P& p) { + return pointer_traits >::get_ref (p);} + }; + + template class P> + struct object_pointer_traits > + { + typedef details::meta::yes result_type; + typedef T object_type; + static const T& get_ref (const P& p) { + return pointer_traits >::get_ref (p);} + }; + + inline database:: + database (database_id id) + : id_ (id), + tracer_ (0), + mutex_ (new details::mutex), + schema_version_seq_ (1) + { + } + + inline database_id database:: + id () const + { + return id_; + } + + inline database::schema_version_type database:: + schema_version (const std::string& name) const + { + return schema_version_migration (name).version; + } + + inline bool database:: + schema_migration (const std::string& name) const + { + return schema_version_migration (name).migration; + } + + inline void database:: + schema_version_migration (schema_version_type v, + bool m, + const std::string& name) + { + schema_version_migration (schema_version_migration_type (v, m), name); + } + + inline void database:: + schema_version_table (const std::string& tname) + { + schema_version_table_ = tname; + } + + inline void database:: + schema_version_table (const std::string& tname, const std::string& sname) + { + schema_version_map_[sname].version_table = tname; + } + + inline unsigned int database:: + schema_version_sequence () const + { + return schema_version_seq_; + } + + inline connection_ptr database:: + connection () + { + return connection_ptr (connection_ ()); + } + +#ifndef ODB_CXX11 + inline void database:: + query_factory (const char* name, query_factory_ptr f) + { + query_factory (name, query_factory_wrapper (f)); + } +#endif + + inline void database:: + tracer (tracer_type& t) + { + tracer_ = &t; + } + + inline void database:: + tracer (tracer_type* t) + { + tracer_ = t; + } + + inline database::tracer_type* database:: + tracer () const + { + return tracer_; + } + + template + inline typename object_traits::id_type database:: + persist (T& obj) + { + return persist_ (obj); + } + + template + inline typename object_traits::id_type database:: + persist (const T& obj) + { + return persist_ (obj); + } + + template + inline typename object_traits::id_type database:: + persist (T* p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + return persist_ (pobj); + } + + template class P> + inline typename object_traits::id_type database:: + persist (const P& p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + return persist_ (pobj); + } + + template class P> + inline typename object_traits::id_type database:: + persist (const P& p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + return persist_ (pobj); + } + + template class P> + inline typename object_traits::id_type database:: + persist (P& p) + { + const P& cr (p); + return persist (cr); + } + + template class P> + inline typename object_traits::id_type database:: + persist (P& p) + { + const P& cr (p); + return persist (cr); + } + + template + inline typename object_traits::id_type database:: + persist (const typename object_traits::pointer_type& pobj) + { + return persist_ (pobj); + } + + template + inline void database:: + persist (I b, I e, bool cont) + { + persist_ (b, e, cont); + } + + template + inline typename object_traits::pointer_type database:: + load (const typename object_traits::id_type& id) + { + return load_ (id); + } + + template + inline void database:: + load (const typename object_traits::id_type& id, T& obj) + { + return load_ (id, obj); + } + + template + inline void database:: + load (T& obj, section& s) + { + return load_ (obj, s); + } + + template + inline typename object_traits::pointer_type database:: + find (const typename object_traits::id_type& id) + { + return find_ (id); + } + + template + inline bool database:: + find (const typename object_traits::id_type& id, T& obj) + { + return find_ (id, obj); + } + + template + inline void database:: + reload (T& obj) + { + reload_ (obj); + } + + template + inline void database:: + reload (T* p) + { + reload (*p); + } + + template class P> + inline void database:: + reload (const P& p) + { + reload (odb::pointer_traits< P >::get_ref (p)); + } + + template class P> + inline void database:: + reload (const P& p) + { + reload (odb::pointer_traits< P >::get_ref (p)); + } + + template class P> + inline void database:: + reload (P& p) + { + reload (odb::pointer_traits< P >::get_ref (p)); + } + + template class P> + inline void database:: + reload (P& p) + { + reload (odb::pointer_traits< P >::get_ref (p)); + } + + template + inline void database:: + reload (const typename object_traits::pointer_type& pobj) + { + typedef typename object_traits::pointer_type pointer_type; + + reload (odb::pointer_traits::get_ref (pobj)); + } + + template + inline void database:: + update (T& obj) + { + update_ (obj); + } + + template + inline void database:: + update (T* p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + update_ (pobj); + } + + template class P> + inline void database:: + update (const P& p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + update_ (pobj); + } + + template class P> + inline void database:: + update (const P& p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + update_ (pobj); + } + + template class P> + inline void database:: + update (P& p) + { + const P& cr (p); + update (cr); + } + + template class P> + inline void database:: + update (P& p) + { + const P& cr (p); + update (cr); + } + + template + inline void database:: + update (const typename object_traits::pointer_type& pobj) + { + update_ (pobj); + } + + template + inline void database:: + update (I b, I e, bool cont) + { + update_ (b, e, cont); + } + + template + inline void database:: + update (const T& obj, const section& s) + { + update_ (obj, s); + } + + template + inline void database:: + erase (const typename object_traits::id_type& id) + { + return erase_ (id); + } + + template + inline void database:: + erase (T& obj) + { + return erase_ (obj); + } + + template + inline void database:: + erase (T* p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + erase_ (pobj); + } + + template class P> + inline void database:: + erase (const P& p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + erase_ (pobj); + } + + template class P> + inline void database:: + erase (const P& p) + { + typedef typename object_traits::pointer_type object_pointer; + + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const object_pointer& pobj (p); + + erase_ (pobj); + } + + template class P> + inline void database:: + erase (P& p) + { + const P& cr (p); + erase (cr); + } + + template class P> + inline void database:: + erase (P& p) + { + const P& cr (p); + erase (cr); + } + + template + inline void database:: + erase (const typename object_traits::pointer_type& pobj) + { + erase_ (pobj); + } + + template + inline void database:: + erase (I idb, I ide, bool cont) + { + erase_id_ (idb, ide, cont); + } + + template + inline void database:: + erase (I ob, I oe, bool cont) + { + erase_object_ (ob, oe, cont); + } + + template + inline unsigned long long database:: + erase_query () + { + // T is always object_type. + // + return erase_query (odb::query ()); + } + + template + inline unsigned long long database:: + erase_query (const char* q) + { + // T is always object_type. + // + return erase_query (odb::query (q)); + } + + template + inline unsigned long long database:: + erase_query (const std::string& q) + { + // T is always object_type. + // + return erase_query (odb::query (q)); + } + + template + inline unsigned long long database:: + erase_query (const odb::query& q) + { + // T is always object_type. + // + return object_traits_impl::erase_query (*this, q); + } + + template + inline result database:: + query (bool cache) + { + return query (odb::query (), cache); + } + + template + inline result database:: + query (const char* q, bool cache) + { + return query (odb::query (q), cache); + } + + template + inline result database:: + query (const std::string& q, bool cache) + { + return query (odb::query (q), cache); + } + + template + inline typename result::pointer_type database:: + query_one () + { + return query_one (odb::query ()); + } + + template + inline bool database:: + query_one (T& o) + { + return query_one (odb::query (), o); + } + + template + inline T database:: + query_value () + { + return query_value (odb::query ()); + } + + template + inline typename result::pointer_type database:: + query_one (const char* q) + { + return query_one (odb::query (q)); + } + + template + inline bool database:: + query_one (const char* q, T& o) + { + return query_one (odb::query (q), o); + } + + template + inline T database:: + query_value (const char* q) + { + return query_value (odb::query (q)); + } + + template + inline typename result::pointer_type database:: + query_one (const std::string& q) + { + return query_one (odb::query (q)); + } + + template + inline bool database:: + query_one (const std::string& q, T& o) + { + return query_one (odb::query (q), o); + } + + template + inline T database:: + query_value (const std::string& q) + { + return query_value (odb::query (q)); + } + + template + inline bool database:: + query_one (const odb::query& q, T& o) + { + return query_one_ (q, o); + } + + template + inline typename result::pointer_type database:: + query_one (const odb::query& q) + { + return query_one_ (q); + } + + template + inline T database:: + query_value (const odb::query& q) + { + return query_value_ (q); + } + + template + inline prepared_query database:: + prepare_query (const char* n, const char* q) + { + return prepare_query (n, odb::query (q)); + } + + template + inline prepared_query database:: + prepare_query (const char* n, const std::string& q) + { + return prepare_query (n, odb::query (q)); + } + + template + inline prepared_query database:: + prepare_query (const char* n, const odb::query& q) + { + connection_type& c (transaction::current ().connection (*this)); + return c.prepare_query (n, q); + } + + template + inline void database:: + cache_query (const prepared_query& pq) + { + connection_type& c (transaction::current ().connection (*this)); + c.cache_query (pq); + } + +#ifdef ODB_CXX11 + template + inline void database:: + cache_query (const prepared_query& pq, std::unique_ptr

params) + { + connection_type& c (transaction::current ().connection (*this)); + c.cache_query (pq, std::move (params)); + } +#else + template + inline void database:: + cache_query (const prepared_query& pq, std::auto_ptr

params) + { + connection_type& c (transaction::current ().connection (*this)); + c.cache_query (pq, params); + } +#endif + + template + inline prepared_query database:: + lookup_query (const char* name) + { + connection_type& c (transaction::current ().connection (*this)); + return c.lookup_query (name); + } + + template + inline prepared_query database:: + lookup_query (const char* name, P*& params) + { + connection_type& c (transaction::current ().connection (*this)); + return c.lookup_query (name, params); + } + + // Implementations (i.e., the *_() functions). + // + template + inline void database:: + persist_ (I b, I e, bool cont) + { + // Sun CC with non-standard STL does not have iterator_traits. + // +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + typedef typename std::iterator_traits::value_type value_type; +#else + // Assume iterator is just a pointer. + // + typedef typename object_pointer_traits::object_type value_type; +#endif + + typedef object_pointer_traits opt; + + persist_ ( + b, e, cont, typename opt::result_type ()); + } + + template + inline typename object_traits::pointer_type database:: + find_ (const typename object_traits::id_type& id) + { + // T is always object_type. + // + + // Compiler error pointing here? Perhaps the object doesn't have the + // default constructor? + // + return object_traits_impl::find (*this, id); + } + + template + inline bool database:: + find_ (const typename object_traits::id_type& id, T& obj) + { + // T is always object_type. + // + return object_traits_impl::find (*this, id, obj); + } + + template + inline void database:: + update_ (T& obj) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + + // Compiler error pointing here? Perhaps the object is readonly or + // doesn't have an object id? Such objects cannot be updated. + // + object_traits_impl::update (*this, obj); + } + + template + inline void database:: + update_ (const typename object_traits::pointer_type& pobj) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::pointer_type pointer_type; + + T& obj (pointer_traits::get_ref (pobj)); + + // Compiler error pointing here? Perhaps the object is readonly or + // doesn't have an object id? Such objects cannot be updated. + // + object_traits_impl::update (*this, obj); + } + + template + inline void database:: + erase_ (const typename object_traits::id_type& id) + { + // T is always object_type. + // + object_traits_impl::erase (*this, id); + } + + template + inline void database:: + erase_ (T& obj) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + + object_traits_impl::erase (*this, obj); + } + + template + inline void database:: + erase_ (const typename object_traits::pointer_type& pobj) + { + typedef typename object_traits::pointer_type pointer_type; + + erase_ (pointer_traits::get_ref (pobj)); + } + + template + inline typename result::pointer_type database:: + query_one_ (const Q& q) + { + result r (query_::call (*this, q)); + + // We still have to cache the result since loading the object + // may result in loading of it's related objects and that would + // invalidate the result even for just getting the 'end' status. + // + r.cache (); + + return r.one (); + } + + template + inline bool database:: + query_one_ (const Q& q, T& o) + { + result r (query_::call (*this, q)); + r.cache (); // See above. + return r.one (o); + } + + template + inline T database:: + query_value_ (const Q& q) + { + result r (query_::call (*this, q)); + r.cache (); // See above. + + // Compiler error pointing here? The object must be default-constructible + // in order to use the return-by-value API. + // + T o; + r.value (o); + return o; + } + + // execute() + // + inline unsigned long long database:: + execute (const char* statement) + { + return execute (statement, std::strlen (statement)); + } + + inline unsigned long long database:: + execute (const std::string& statement) + { + return execute (statement.c_str (), statement.size ()); + } +} diff --git a/libodb/odb/database.txx b/libodb/odb/database.txx new file mode 100644 index 0000000..5659b6f --- /dev/null +++ b/libodb/odb/database.txx @@ -0,0 +1,491 @@ +// file : odb/database.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include +#include + +namespace odb +{ + template + result database:: + query (const odb::query& q, bool cache) + { + // T is always object_type. We also don't need to check for transaction + // here; object_traits::query () does this. + // + result r (query_::call (*this, q)); + + if (cache) + r.cache (); + + return r; + } + + // Implementations (i.e., the *_() functions). + // + template + typename object_traits::id_type database:: + persist_ (T& obj) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + typedef object_traits_impl object_traits; + + object_traits::persist (*this, obj); + + typename object_traits::reference_cache_traits::position_type p ( + object_traits::reference_cache_traits::insert ( + *this, reference_cache_type::convert (obj))); + + object_traits::reference_cache_traits::persist (p); + + return object_traits::id (obj); + } + + template + typename object_traits::id_type database:: + persist_ (const typename object_traits::pointer_type& pobj) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::pointer_type pointer_type; + + typedef object_traits_impl object_traits; + + T& obj (pointer_traits::get_ref (pobj)); + object_traits::persist (*this, obj); + + // Get the canonical object pointer and insert it into object cache. + // + typename object_traits::pointer_cache_traits::position_type p ( + object_traits::pointer_cache_traits::insert ( + *this, pointer_cache_type::convert (pobj))); + + object_traits::pointer_cache_traits::persist (p); + + return object_traits::id (obj); + } + + template ::auto_id> struct persist_type; + template struct persist_type {typedef T type;}; + template struct persist_type {typedef const T type;}; + + template + void database:: + persist_ (I b, I e, bool cont, details::meta::no /*ptr*/) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + typedef object_traits_impl object_traits; + + multiple_exceptions mex (typeid (object_already_persistent)); + try + { + while (b != e && (cont || mex.empty ())) + { + std::size_t n (0); + T* a[object_traits::batch]; // T instead of persist_type for cache. + + for (; b != e && n < object_traits::batch; ++n) + { + // Compiler error pointing here? Perhaps the passed range is + // of const objects? + // + typename persist_type::type* p (&(*b++)); + + a[n] = const_cast (p); + } + + // Compiler error pointing here? Perhaps the object or the + // database does not support bulk operations? + // + object_traits::persist ( + *this, + const_cast::type**> (a), + n, + mex); + + if (mex.fatal ()) + break; + + for (std::size_t i (0); i < n; ++i) + { + if (mex[i] != 0) // Don't cache objects that have failed. + continue; + + mex.current (i); // Set position in case the below code throws. + + typename object_traits::reference_cache_traits::position_type p ( + object_traits::reference_cache_traits::insert ( + *this, reference_cache_type::convert (*a[i]))); + + object_traits::reference_cache_traits::persist (p); + } + + mex.delta (n); + } + } + catch (const odb::exception& ex) + { + mex.insert (ex, true); + } + + if (!mex.empty ()) + { + mex.prepare (); + throw mex; + } + } + + template + struct pointer_copy + { + const P* ref; + P copy; + + void assign (const P& p) {ref = &p;} + template void assign (const P1& p1) + { + // The passed pointer should be the same or implicit-convertible + // to the object pointer. This way we make sure the object pointer + // does not assume ownership of the passed object. + // + const P& p (p1); + + copy = p; + ref = © + } + }; + + template + void database:: + persist_ (I b, I e, bool cont, details::meta::yes /*ptr*/) + { + // T can be const T while object_type will always be T. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::pointer_type pointer_type; + + typedef object_traits_impl object_traits; + + multiple_exceptions mex (typeid (object_already_persistent)); + try + { + while (b != e && (cont || mex.empty ())) + { + std::size_t n (0); + typename persist_type::type* a[object_traits::batch]; + pointer_copy p[object_traits::batch]; + + for (; b != e && n < object_traits::batch; ++n) + { + p[n].assign (*b++); + a[n] = &pointer_traits::get_ref (*p[n].ref); + } + + // Compiler error pointing here? Perhaps the object or the + // database does not support bulk operations? + // + object_traits::persist (*this, a, n, mex); + + if (mex.fatal ()) + break; + + for (std::size_t i (0); i < n; ++i) + { + if (mex[i] != 0) // Don't cache objects that have failed. + continue; + + mex.current (i); // Set position in case the below code throws. + + // Get the canonical object pointer and insert it into object cache. + // + typename object_traits::pointer_cache_traits::position_type pos ( + object_traits::pointer_cache_traits::insert ( + *this, pointer_cache_type::convert (*p[i].ref))); + + object_traits::pointer_cache_traits::persist (pos); + } + + mex.delta (n); + } + } + catch (const odb::exception& ex) + { + mex.insert (ex, true); + } + + if (!mex.empty ()) + { + mex.prepare (); + throw mex; + } + } + + template + typename object_traits::pointer_type database:: + load_ (const typename object_traits::id_type& id) + { + // T is always object_type. + // + typedef typename object_traits::pointer_type pointer_type; + + pointer_type r (find_ (id)); + + if (pointer_traits::null_ptr (r)) + throw object_not_persistent (); + + return r; + } + + template + void database:: + load_ (const typename object_traits::id_type& id, T& obj) + { + if (!find_ (id, obj)) + throw object_not_persistent (); + } + + template + void database:: + load_ (T& obj, section& s) + { + connection_type& c (transaction::current ().connection (*this)); + + // T is always object_type. + // + if (object_traits_impl::load (c, obj, s)) + s.reset (true, false); // Loaded, unchanged. + else + throw section_not_in_object (); + } + + template + void database:: + reload_ (T& obj) + { + // T should be object_type (cannot be const). We also don't need to + // check for transaction here; object_traits::reload () does this. + // + if (!object_traits_impl::reload (*this, obj)) + throw object_not_persistent (); + } + + template + void database:: + update_ (I b, I e, bool cont) + { + // Sun CC with non-standard STL does not have iterator_traits. + // +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + typedef typename std::iterator_traits::value_type value_type; +#else + // Assume iterator is just a pointer. + // + typedef typename object_pointer_traits::object_type value_type; +#endif + + // object_pointer_traits::object_type can be const. + // + typedef object_pointer_traits opt; + + typedef + typename object_traits::object_type + object_type; + + typedef object_traits_impl object_traits; + + multiple_exceptions mex ( + object_traits::managed_optimistic_column_count == 0 + ? typeid (object_not_persistent) + : typeid (object_changed)); + + try + { + while (b != e && (cont || mex.empty ())) + { + std::size_t n (0); + const object_type* a[object_traits::batch]; + + for (; b != e && n < object_traits::batch; ++n) + a[n] = &opt::get_ref (*b++); + + // Compiler error pointing here? Perhaps the object or the + // database does not support bulk operations? + // + object_traits::update (*this, a, n, mex); + + if (mex.fatal ()) + break; + + mex.delta (n); + } + } + catch (const odb::exception& ex) + { + mex.insert (ex, true); + } + + if (!mex.empty ()) + { + mex.prepare (); + throw mex; + } + } + + template + void database:: + update_ (const T& obj, const section& s) + { + if (!s.loaded ()) + throw section_not_loaded (); + + transaction& t (transaction::current ()); + + // T is always object_type. + // + if (object_traits_impl::update (t.connection (*this), obj, s)) + { + if (s.changed ()) + s.reset (true, false, &t); // Clear the change flag. + } + else + throw section_not_in_object (); + } + + template + void database:: + erase_id_ (I b, I e, bool cont) + { + // T is explicitly specified by the caller, so assume it is object type. + // + typedef T object_type; + typedef object_traits_impl object_traits; + typedef typename object_traits::id_type id_type; + + multiple_exceptions mex (typeid (object_not_persistent)); + try + { + while (b != e && (cont || mex.empty ())) + { + std::size_t n (0); + const id_type* a[object_traits::batch]; + + for (; b != e && n < object_traits::batch; ++n) + // Compiler error pointing here? Perhaps the object id type + // and the range element type don't match? + // + a[n] = &(*b++); + + // Compiler error pointing here? Perhaps the object or the + // database does not support bulk operations? + // + object_traits::erase (*this, a, n, mex); + + if (mex.fatal ()) + break; + + mex.delta (n); + } + } + catch (const odb::exception& ex) + { + mex.insert (ex, true); + } + + if (!mex.empty ()) + { + mex.prepare (); + throw mex; + } + } + + template + void database:: + erase_object_ (I b, I e, bool cont) + { + // Sun CC with non-standard STL does not have iterator_traits. + // +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + typedef typename std::iterator_traits::value_type value_type; +#else + // Assume iterator is just a pointer. + // + typedef typename object_pointer_traits::object_type value_type; +#endif + + // object_pointer_traits::object_type can be const. + // + typedef object_pointer_traits opt; + + typedef + typename object_traits::object_type + object_type; + + typedef object_traits_impl object_traits; + + multiple_exceptions mex ( + object_traits::managed_optimistic_column_count == 0 + ? typeid (object_not_persistent) + : typeid (object_changed)); + + try + { + while (b != e && (cont || mex.empty ())) + { + std::size_t n (0); + const object_type* a[object_traits::batch]; + + for (; b != e && n < object_traits::batch; ++n) + a[n] = &opt::get_ref (*b++); + + // Compiler error pointing here? Perhaps the object or the + // database does not support bulk operations? + // + object_traits::erase (*this, a, n, mex); + + if (mex.fatal ()) + break; + + mex.delta (n); + } + } + catch (const odb::exception& ex) + { + mex.insert (ex, true); + } + + if (!mex.empty ()) + { + mex.prepare (); + throw mex; + } + } + + template + struct database::query_ + { + template + static result + call (database& db, const Q& q) + { + return object_traits_impl::query (db, q); + } + }; + + template + struct database::query_ + { + template + static result + call (database& db, const Q& q) + { + return view_traits_impl::query (db, q); + } + }; +} diff --git a/libodb/odb/details/buffer.cxx b/libodb/odb/details/buffer.cxx new file mode 100644 index 0000000..595329e --- /dev/null +++ b/libodb/odb/details/buffer.cxx @@ -0,0 +1,35 @@ +// file : odb/details/buffer.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::memcpy + +#include + +using namespace std; + +namespace odb +{ + namespace details + { + void basic_buffer_base:: + capacity (size_t c, size_t data_size) + { + if (c > capacity_) + { + size_t n (capacity_ * 2 > c ? capacity_ * 2 : c); + void* d (operator new (n)); + + if (data_ != 0) + { + if (data_size != 0) + memcpy (d, data_, data_size); + + operator delete (data_); + } + + data_ = d; + capacity_ = n; + } + } + } +} diff --git a/libodb/odb/details/buffer.hxx b/libodb/odb/details/buffer.hxx new file mode 100644 index 0000000..558be9b --- /dev/null +++ b/libodb/odb/details/buffer.hxx @@ -0,0 +1,92 @@ +// file : odb/details/buffer.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_BUFFER_DETAILS_HXX +#define ODB_BUFFER_DETAILS_HXX + +#include + +#include +#include // std::size_t + +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT basic_buffer_base + { + public: + ~basic_buffer_base () + { + if (data_ != 0) + operator delete (data_); + } + + basic_buffer_base (std::size_t capacity) + : capacity_ (capacity) + { + data_ = capacity_ == 0 ? 0 : operator new (capacity_); + } + + std::size_t + capacity () const + { + return capacity_; + } + + void + capacity (std::size_t, std::size_t data_size = 0); + + protected: + void* data_; + std::size_t capacity_; + }; + + template + class basic_buffer: public basic_buffer_base + { + public: + basic_buffer (std::size_t capacity = 256) + : basic_buffer_base (capacity) + { + } + + T* + data () + { + return static_cast (data_); + } + + const T* + data () const + { + return static_cast (data_); + } + + // Note that strictly speaking the return type should be void* const* + // but that would make using this function too awkward since we often + // store the result as void*. + // + void** + data_ptr () + { + return &data_; + } + + const void* const* + data_ptr () const + { + return &data_; + } + }; + + typedef basic_buffer buffer; + typedef basic_buffer ubuffer; + } +} + +#include + +#endif // ODB_BUFFER_DETAILS_HXX diff --git a/libodb/odb/details/build2/config-stub.h b/libodb/odb/details/build2/config-stub.h new file mode 100644 index 0000000..83ea927 --- /dev/null +++ b/libodb/odb/details/build2/config-stub.h @@ -0,0 +1,5 @@ +/* file : odb/details/build2/config-stub.h + * license : GNU GPL v2; see accompanying LICENSE file + */ + +#include diff --git a/libodb/odb/details/build2/config-vc-stub.h b/libodb/odb/details/build2/config-vc-stub.h new file mode 100644 index 0000000..e440e70 --- /dev/null +++ b/libodb/odb/details/build2/config-vc-stub.h @@ -0,0 +1,5 @@ +/* file : odb/details/build2/config-vc-stub.h + * license : GNU GPL v2; see accompanying LICENSE file + */ + +#include diff --git a/libodb/odb/details/build2/config-vc.h b/libodb/odb/details/build2/config-vc.h new file mode 100644 index 0000000..77ce106 --- /dev/null +++ b/libodb/odb/details/build2/config-vc.h @@ -0,0 +1,23 @@ +/* file : odb/details/build2/config-vc.h + * license : GNU GPL v2; see accompanying LICENSE file + */ + +/* Configuration file for Windows/VC++ for the build2 build. */ + +#ifndef ODB_DETAILS_CONFIG_VC_H +#define ODB_DETAILS_CONFIG_VC_H + +/* Define LIBODB_BUILD2 for the installed case. */ +#ifndef LIBODB_BUILD2 +# define LIBODB_BUILD2 +#endif + +#ifndef ODB_THREADS_NONE +# if _MSC_VER >= 1900 +# define ODB_THREADS_CXX11 +# else +# error Unsupoprted MSVC version (no thread_local) +# endif +#endif + +#endif /* ODB_DETAILS_CONFIG_VC_H */ diff --git a/libodb/odb/details/build2/config.h b/libodb/odb/details/build2/config.h new file mode 100644 index 0000000..ba434f4 --- /dev/null +++ b/libodb/odb/details/build2/config.h @@ -0,0 +1,19 @@ +/* file : odb/details/build2/config.h + * license : GNU GPL v2; see accompanying LICENSE file + */ + +/* Static configuration file for the build2 build. */ + +#ifndef ODB_DETAILS_CONFIG_H +#define ODB_DETAILS_CONFIG_H + +/* Define LIBODB_BUILD2 for the installed case. */ +#ifndef LIBODB_BUILD2 +# define LIBODB_BUILD2 +#endif + +#ifndef ODB_THREADS_NONE +# define ODB_THREADS_CXX11 +#endif + +#endif /* ODB_DETAILS_CONFIG_H */ diff --git a/libodb/odb/details/c-string.hxx b/libodb/odb/details/c-string.hxx new file mode 100644 index 0000000..6ab1adc --- /dev/null +++ b/libodb/odb/details/c-string.hxx @@ -0,0 +1,28 @@ +// file : odb/details/c-string.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_C_STRING_HXX +#define ODB_DETAILS_C_STRING_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + struct c_string_comparator + { + bool + operator() (const char* x, const char* y) const + { + return std::strcmp (x, y) < 0; + } + }; + } +} + +#include + +#endif // ODB_DETAILS_C_STRING_HXX diff --git a/libodb/odb/details/condition.cxx b/libodb/odb/details/condition.cxx new file mode 100644 index 0000000..2c4cbdb --- /dev/null +++ b/libodb/odb/details/condition.cxx @@ -0,0 +1,13 @@ +// file : odb/details/condition.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + // This otherwise unnecessary file is here to allow instantiation + // of inline functions for exporting. + } +} diff --git a/libodb/odb/details/condition.hxx b/libodb/odb/details/condition.hxx new file mode 100644 index 0000000..10b6b4a --- /dev/null +++ b/libodb/odb/details/condition.hxx @@ -0,0 +1,68 @@ +// file : odb/details/condition.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_CONDITION_HXX +#define ODB_DETAILS_CONDITION_HXX + +#include + +#include + +#ifdef ODB_THREADS_NONE + +namespace odb +{ + namespace details + { + class mutex; + class lock; + + class condition + { + public: + condition (mutex&) {} + + void + signal () {} + + void + wait (lock&) {} + + private: + condition (const condition&); + condition& operator= (const condition&); + }; + } +} + +#elif defined(ODB_THREADS_CXX11) +# include +# include +# include + +namespace odb +{ + namespace details + { + class condition: public std::condition_variable + { + public: + condition (mutex&) {} + + void + signal () {notify_one ();} + }; + } +} + +#elif defined(ODB_THREADS_POSIX) +#include +#elif defined(ODB_THREADS_WIN32) +#include +#else +# error unknown threading model +#endif + +#include + +#endif // ODB_DETAILS_CONDITION_HXX diff --git a/libodb/odb/details/config-vc.h b/libodb/odb/details/config-vc.h new file mode 100644 index 0000000..b1e38b2 --- /dev/null +++ b/libodb/odb/details/config-vc.h @@ -0,0 +1,13 @@ +/* file : odb/details/config-vc.h + * license : GNU GPL v2; see accompanying LICENSE file + */ + +/* Configuration file for Windows/VC++. */ + +#ifndef ODB_DETAILS_CONFIG_VC_H +#define ODB_DETAILS_CONFIG_VC_H + +#define ODB_THREADS_WIN32 +#define ODB_THREADS_TLS_DECLSPEC + +#endif /* ODB_DETAILS_CONFIG_VC_H */ diff --git a/libodb/odb/details/config.h.in b/libodb/odb/details/config.h.in new file mode 100644 index 0000000..2396606 --- /dev/null +++ b/libodb/odb/details/config.h.in @@ -0,0 +1,18 @@ +/* file : odb/details/config.h.in + * license : GNU GPL v2; see accompanying LICENSE file + */ + +/* This file is automatically processed by configure. */ + +#ifndef ODB_DETAILS_CONFIG_H +#define ODB_DETAILS_CONFIG_H + +#undef ODB_THREADS_NONE +#undef ODB_THREADS_POSIX +#undef ODB_THREADS_WIN32 +#undef ODB_THREADS_TLS_KEYWORD +#undef ODB_THREADS_TLS_DECLSPEC + +#undef LIBODB_STATIC_LIB + +#endif /* ODB_DETAILS_CONFIG_H */ diff --git a/libodb/odb/details/config.hxx b/libodb/odb/details/config.hxx new file mode 100644 index 0000000..a42dd69 --- /dev/null +++ b/libodb/odb/details/config.hxx @@ -0,0 +1,80 @@ +// file : odb/details/config.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_CONFIG_HXX +#define ODB_DETAILS_CONFIG_HXX + +// no pre + +// C++11 support. +// +#ifdef _MSC_VER +# if _MSC_VER >= 1600 // VC++10 and later have C++11 always enabled. +# define ODB_CXX11 +# define ODB_CXX11_NULLPTR +# if _MSC_VER >= 1700 +# define ODB_CXX11_ENUM +# if _MSC_VER >= 1800 +# define ODB_CXX11_DELETED_FUNCTION +# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR +# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT +# define ODB_CXX11_VARIADIC_TEMPLATE +# define ODB_CXX11_INITIALIZER_LIST +# if _MSC_VER >= 1900 +# define ODB_CXX11_NOEXCEPT +# endif +# endif +# endif +# endif +#else +# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L +# define ODB_CXX11 +# ifdef __clang__ // Pretends to be a really old __GNUC__ on some platforms. +# define ODB_CXX11_NULLPTR +# define ODB_CXX11_NOEXCEPT +# elif defined(__GNUC__) +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 +# define ODB_CXX11_NULLPTR +# define ODB_CXX11_NOEXCEPT +# endif +# else +# define ODB_CXX11_NULLPTR +# define ODB_CXX11_NOEXCEPT +# endif +# define ODB_CXX11_DELETED_FUNCTION +# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR +# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT +# define ODB_CXX11_VARIADIC_TEMPLATE +# define ODB_CXX11_INITIALIZER_LIST +# define ODB_CXX11_ENUM // GCC 4.4 (forward -- 4.6), Clang 2.9 (3.1). +# endif +#endif + +#ifdef ODB_CXX11_NOEXCEPT +# define ODB_NOTHROW_NOEXCEPT noexcept +#else +# define ODB_NOTHROW_NOEXCEPT throw() +#endif + +// Once we drop support for C++98, we can probably get rid of config.h except +// for the autotools case by fixing ODB_THREADS_CXX11 (and perhaps supporting +// the ODB_THREADS_NONE case via a "global" (command line) define). +// +#ifdef ODB_COMPILER +# define ODB_THREADS_NONE +# define LIBODB_STATIC_LIB +#elif defined(LIBODB_BUILD2) +# if defined(_MSC_VER) +# include +# else +# include +# endif +#elif defined(_MSC_VER) +# include +#else +# include +#endif + +// no post + +#endif // ODB_DETAILS_CONFIG_HXX diff --git a/libodb/odb/details/exception.hxx b/libodb/odb/details/exception.hxx new file mode 100644 index 0000000..ab838e1 --- /dev/null +++ b/libodb/odb/details/exception.hxx @@ -0,0 +1,21 @@ +// file : odb/details/exception.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_EXCEPTION_HXX +#define ODB_DETAILS_EXCEPTION_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + struct exception: odb::exception {}; + } +} + +#include + +#endif // ODB_DETAILS_EXCEPTION_HXX diff --git a/libodb/odb/details/export.hxx b/libodb/odb/details/export.hxx new file mode 100644 index 0000000..80fe342 --- /dev/null +++ b/libodb/odb/details/export.hxx @@ -0,0 +1,78 @@ +// file : odb/details/export.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_EXPORT_HXX +#define ODB_DETAILS_EXPORT_HXX + +#include + +#include + +// Normally we don't export class templates (but do complete specializations), +// inline functions, and classes with only inline member functions. Exporting +// classes that inherit from non-exported/imported bases (e.g., std::string) +// will end up badly. The only known workarounds are to not inherit or to not +// export. Also, MinGW GCC doesn't like seeing non-exported function being +// used before their inline definition. The workaround is to reorder code. In +// the end it's all trial and error. + +#ifdef LIBODB_BUILD2 + +#if defined(LIBODB_STATIC) // Using static. +# define LIBODB_EXPORT +#elif defined(LIBODB_STATIC_BUILD) // Building static. +# define LIBODB_EXPORT +#elif defined(LIBODB_SHARED) // Using shared. +# ifdef _WIN32 +# define LIBODB_EXPORT __declspec(dllimport) +# else +# define LIBODB_EXPORT +# endif +#elif defined(LIBODB_SHARED_BUILD) // Building shared. +# ifdef _WIN32 +# define LIBODB_EXPORT __declspec(dllexport) +# else +# define LIBODB_EXPORT +# endif +#else +// If none of the above macros are defined, then we assume we are being used +// by some third-party build system that cannot/doesn't signal the library +// type. Note that this fallback works for both static and shared but in case +// of shared will be sub-optimal compared to having dllimport. +// +# define LIBODB_EXPORT // Using static or shared. +#endif + +#else // LIBODB_BUILD2 + +#ifdef LIBODB_STATIC_LIB +# define LIBODB_EXPORT +#else +# ifdef _WIN32 +# ifdef _MSC_VER +# ifdef LIBODB_DYNAMIC_LIB +# define LIBODB_EXPORT __declspec(dllexport) +# else +# define LIBODB_EXPORT __declspec(dllimport) +# endif +# else +# ifdef LIBODB_DYNAMIC_LIB +# ifdef DLL_EXPORT +# define LIBODB_EXPORT __declspec(dllexport) +# else +# define LIBODB_EXPORT +# endif +# else +# define LIBODB_EXPORT __declspec(dllimport) +# endif +# endif +# else +# define LIBODB_EXPORT +# endif +#endif + +#endif // LIBODB_BUILD2 + +#include + +#endif // ODB_DETAILS_EXPORT_HXX diff --git a/libodb/odb/details/function-wrapper.hxx b/libodb/odb/details/function-wrapper.hxx new file mode 100644 index 0000000..418a625 --- /dev/null +++ b/libodb/odb/details/function-wrapper.hxx @@ -0,0 +1,90 @@ +// file : odb/details/function-wrapper.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_FUNCTION_WRAPPER_HXX +#define ODB_DETAILS_FUNCTION_WRAPPER_HXX + +#include + +#include // ODB_CXX11 + +#ifdef ODB_CXX11 +# include // std::function +# include // std::enable_if, std::is_convertible +#endif + +namespace odb +{ + namespace details + { + // Low-level 'callable object' wrapper similar to std::function but + // that works in both C++98 and 11. In particular, the call site can + // be compiled in C++98 and the registration site in C++11 and it + // will work. + // + template + struct function_wrapper + { + ~function_wrapper (); + + explicit + function_wrapper (F* = 0); + +#ifdef ODB_CXX11 + typedef typename std::function std_function_type; + + // This overload accepts lambdas and std::functions, but when the + // argument is convertible to F*, then we disable it in favor of the + // other overload (above), which is more efficient. + // + // Subtlety alert: if you're thinking of changing this to accept a + // std::function argument, stop. That creates an overload ambiguity + // when the actual parameter is a lambda, which is convertible to either + // std::function or F*. + // + template + function_wrapper(F1, + typename std::enable_if< + !std::is_convertible::value>::type* = 0); +#endif + + // Destructive copy construction and assignment (aka move). These + // should really only be called by containers when they need to + // reallocate the underlying buffer and move the elements. + // + function_wrapper (const function_wrapper&); + function_wrapper& + operator= (const function_wrapper&); + + void swap (function_wrapper&); + + // Cleanly cast to an incompatible function type. + // + template R + cast () const; + + // Conversion to bool. + // + public: + typedef void (function_wrapper::*bool_convertible) (); + void true_value () {} + + operator bool_convertible () const + { + return function != 0 ? &function_wrapper::true_value : 0; + } + + public: + F* function; + void (*deleter) (const void*); + const void* std_function; + }; + } +} + +#include +#include + +#include + +#endif // ODB_DETAILS_FUNCTION_WRAPPER_HXX diff --git a/libodb/odb/details/function-wrapper.ixx b/libodb/odb/details/function-wrapper.ixx new file mode 100644 index 0000000..5b83b96 --- /dev/null +++ b/libodb/odb/details/function-wrapper.ixx @@ -0,0 +1,49 @@ +// file : odb/details/function-wrapper.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace details + { + template + inline function_wrapper:: + ~function_wrapper () + { + if (deleter != 0) + deleter (std_function); + } + + template + inline function_wrapper:: + function_wrapper (F* f) + : function (f), deleter (0), std_function (0) + { + } + + template + inline function_wrapper:: + function_wrapper (const function_wrapper& x) + : function (0), deleter (0), std_function (0) + { + swap (const_cast&> (x)); + } + + template + inline function_wrapper& function_wrapper:: + operator= (const function_wrapper& x) + { + swap (const_cast&> (x)); + return *this; + } + + template + template + inline R function_wrapper:: + cast () const + { + union { F* f; R r; } r; + r.f = function; + return r.r; + } + } +} diff --git a/libodb/odb/details/function-wrapper.txx b/libodb/odb/details/function-wrapper.txx new file mode 100644 index 0000000..db73e8d --- /dev/null +++ b/libodb/odb/details/function-wrapper.txx @@ -0,0 +1,89 @@ +// file : odb/details/function-wrapper.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::swap, std::move + +namespace odb +{ + namespace details + { +#ifdef ODB_CXX11 + template + struct caller_impl; + +#ifdef ODB_CXX11_VARIADIC_TEMPLATE + template + struct caller_impl + { + static R + function (const void* f, A... a) + { + return (*static_cast*> (f)) (a...); + } + }; +#else + template + struct caller_impl + { + static R + function (const void* f, A1 a1) + { + return (*static_cast*> (f)) (a1); + } + }; + + template + struct caller_impl + { + static R + function (const void* f, A1 a1, A2 a2) + { + return (*static_cast*> (f)) (a1, a2); + } + }; +#endif + + template + void + deleter_impl (const void* f) + { + delete static_cast*> (f); + } + + template + template + function_wrapper:: + function_wrapper ( + F1 f, + typename std::enable_if::value>::type*) + { + std_function_type sf (std::move (f)); + + if (F* const* const f = sf.template target ()) + { + function = *f; + deleter = 0; + std_function = 0; + } + else + { + function_wrapper::function)> fw ( + &caller_impl::function); + + function = fw.template cast (); + deleter = &deleter_impl; + std_function = new std_function_type (std::move (sf)); + } + } +#endif + + template + void function_wrapper:: + swap (function_wrapper& x) + { + std::swap (function, x.function); + std::swap (deleter, x.deleter); + std::swap (std_function, x.std_function); + } + } +} diff --git a/libodb/odb/details/lock.cxx b/libodb/odb/details/lock.cxx new file mode 100644 index 0000000..f474bf5 --- /dev/null +++ b/libodb/odb/details/lock.cxx @@ -0,0 +1,13 @@ +// file : odb/details/lock.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + // This otherwise unnecessary file is here to allow instantiation + // of inline functions for exporting. + } +} diff --git a/libodb/odb/details/lock.hxx b/libodb/odb/details/lock.hxx new file mode 100644 index 0000000..0c54f03 --- /dev/null +++ b/libodb/odb/details/lock.hxx @@ -0,0 +1,59 @@ +// file : odb/details/lock.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_LOCK_HXX +#define ODB_DETAILS_LOCK_HXX + +#include + +#include + +#ifdef ODB_THREADS_CXX11 +# include +namespace odb +{ + namespace details + { + using lock = std::unique_lock; + } +} +#else +namespace odb +{ + namespace details + { + class lock + { + public: + lock (mutex& m) + : mutex_ (&m) + { + mutex_->lock (); + } + + ~lock () + { + if (mutex_ != 0) + mutex_->unlock (); + } + + void + unlock () + { + if (mutex_ != 0) + { + mutex_->unlock (); + mutex_ = 0; + } + } + + private: + mutex* mutex_; + }; + } +} +#endif + +#include + +#endif // ODB_DETAILS_LOCK_HXX diff --git a/libodb/odb/details/meta/answer.hxx b/libodb/odb/details/meta/answer.hxx new file mode 100644 index 0000000..f15dc43 --- /dev/null +++ b/libodb/odb/details/meta/answer.hxx @@ -0,0 +1,30 @@ +// file : odb/details/meta/answer.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_ANSWER_HXX +#define ODB_DETAILS_META_ANSWER_HXX + +#include + +namespace odb +{ + namespace details + { + namespace meta + { + struct yes + { + char filling; + }; + + struct no + { + char filling[2]; + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_ANSWER_HXX diff --git a/libodb/odb/details/meta/class-p.hxx b/libodb/odb/details/meta/class-p.hxx new file mode 100644 index 0000000..bddb452 --- /dev/null +++ b/libodb/odb/details/meta/class-p.hxx @@ -0,0 +1,34 @@ +// file : odb/details/meta/class-p.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_CLASS_HXX +#define ODB_DETAILS_META_CLASS_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + namespace meta + { + // g++ cannot have these inside class_p. + // + template no class_p_test (...); + template yes class_p_test (void (X::*) ()); + + template + struct class_p + { + static const bool result = + sizeof (class_p_test (0)) == sizeof (yes); + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_CLASS_HXX diff --git a/libodb/odb/details/meta/polymorphic-p.hxx b/libodb/odb/details/meta/polymorphic-p.hxx new file mode 100644 index 0000000..10fef6a --- /dev/null +++ b/libodb/odb/details/meta/polymorphic-p.hxx @@ -0,0 +1,57 @@ +// file : odb/details/meta/polymorphic-p.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_POLYMORPHIC_HXX +#define ODB_DETAILS_META_POLYMORPHIC_HXX + +#include + +#include // ODB_NOTHROW_NOEXCEPT +#include +#include + +namespace odb +{ + namespace details + { + namespace meta + { + template + struct polymorphic_p + { + typedef typename remove_const_volatile::result X; + + template + struct impl + { + static const bool result = false; + }; + + template + struct impl + { + struct t1: Y + { + t1 (); + }; + + struct t2: Y + { + t2 (); + + virtual + ~t2 () ODB_NOTHROW_NOEXCEPT; + }; + + static const bool result = sizeof (t1) == sizeof (t2); + }; + + static const bool result = impl::result>::result; + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_POLYMORPHIC_HXX diff --git a/libodb/odb/details/meta/remove-const-volatile.hxx b/libodb/odb/details/meta/remove-const-volatile.hxx new file mode 100644 index 0000000..910ec35 --- /dev/null +++ b/libodb/odb/details/meta/remove-const-volatile.hxx @@ -0,0 +1,31 @@ +// file : odb/details/meta/remove-const-volatile.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_REMOVE_CONST_VOLATILE_HXX +#define ODB_DETAILS_META_REMOVE_CONST_VOLATILE_HXX + +#include + +#include +#include + +namespace odb +{ + namespace details + { + namespace meta + { + template + struct remove_const_volatile + { + typedef + typename remove_volatile::result>::result + result; + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_REMOVE_CONST_VOLATILE_HXX diff --git a/libodb/odb/details/meta/remove-const.hxx b/libodb/odb/details/meta/remove-const.hxx new file mode 100644 index 0000000..4a92ed3 --- /dev/null +++ b/libodb/odb/details/meta/remove-const.hxx @@ -0,0 +1,32 @@ +// file : odb/details/meta/remove-const.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_REMOVE_CONST_HXX +#define ODB_DETAILS_META_REMOVE_CONST_HXX + +#include + +namespace odb +{ + namespace details + { + namespace meta + { + template + struct remove_const + { + typedef X result; + }; + + template + struct remove_const + { + typedef X result; + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_REMOVE_CONST_HXX diff --git a/libodb/odb/details/meta/remove-pointer.hxx b/libodb/odb/details/meta/remove-pointer.hxx new file mode 100644 index 0000000..9963fd7 --- /dev/null +++ b/libodb/odb/details/meta/remove-pointer.hxx @@ -0,0 +1,32 @@ +// file : odb/details/meta/remove-pointer.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_REMOVE_POINTER_HXX +#define ODB_DETAILS_META_REMOVE_POINTER_HXX + +#include + +namespace odb +{ + namespace details + { + namespace meta + { + template + struct remove_pointer + { + typedef X result; + }; + + template + struct remove_pointer + { + typedef X result; + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_REMOVE_POINTER_HXX diff --git a/libodb/odb/details/meta/remove-volatile.hxx b/libodb/odb/details/meta/remove-volatile.hxx new file mode 100644 index 0000000..877e532 --- /dev/null +++ b/libodb/odb/details/meta/remove-volatile.hxx @@ -0,0 +1,32 @@ +// file : odb/details/meta/remove-volatile.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_REMOVE_VOLATILE_HXX +#define ODB_DETAILS_META_REMOVE_VOLATILE_HXX + +#include + +namespace odb +{ + namespace details + { + namespace meta + { + template + struct remove_volatile + { + typedef X result; + }; + + template + struct remove_volatile + { + typedef X result; + }; + } + } +} + +#include + +#endif // ODB_DETAILS_META_REMOVE_VOLATILE_HXX diff --git a/libodb/odb/details/meta/static-assert.hxx b/libodb/odb/details/meta/static-assert.hxx new file mode 100644 index 0000000..a2cc81b --- /dev/null +++ b/libodb/odb/details/meta/static-assert.hxx @@ -0,0 +1,32 @@ +// file : odb/details/meta/static-assert.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_META_STATIC_ASSERT_HXX +#define ODB_DETAILS_META_STATIC_ASSERT_HXX + +#include + +#include // ODB_CXX11 + +#ifndef ODB_CXX11 + +namespace odb +{ + namespace details + { + namespace meta + { + template + struct static_assert_test; + + template <> + struct static_assert_test {}; + } + } +} + +#endif + +#include + +#endif // ODB_DETAILS_META_STATIC_ASSERT_HXX diff --git a/libodb/odb/details/mutex.cxx b/libodb/odb/details/mutex.cxx new file mode 100644 index 0000000..df367d8 --- /dev/null +++ b/libodb/odb/details/mutex.cxx @@ -0,0 +1,13 @@ +// file : odb/details/mutex.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + // This otherwise unnecessary file is here to allow instantiation + // of inline functions for exporting. + } +} diff --git a/libodb/odb/details/mutex.hxx b/libodb/odb/details/mutex.hxx new file mode 100644 index 0000000..df12013 --- /dev/null +++ b/libodb/odb/details/mutex.hxx @@ -0,0 +1,53 @@ +// file : odb/details/mutex.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_MUTEX_HXX +#define ODB_DETAILS_MUTEX_HXX + +#include + +#include + +#ifdef ODB_THREADS_NONE + +namespace odb +{ + namespace details + { + class mutex + { + public: + mutex () {} + + void + lock () {} + + void + unlock () {} + + private: + mutex (const mutex&); + mutex& operator= (const mutex&); + }; + } +} +#elif defined(ODB_THREADS_CXX11) +# include +namespace odb +{ + namespace details + { + using std::mutex; + } +} +#elif defined(ODB_THREADS_POSIX) +#include +#elif defined(ODB_THREADS_WIN32) +#include +#else +# error unknown threading model +#endif + +#include + +#endif // ODB_DETAILS_MUTEX_HXX diff --git a/libodb/odb/details/posix/condition.hxx b/libodb/odb/details/posix/condition.hxx new file mode 100644 index 0000000..4f7c42a --- /dev/null +++ b/libodb/odb/details/posix/condition.hxx @@ -0,0 +1,47 @@ +// file : odb/details/posix/condition.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_POSIX_CONDITION_HXX +#define ODB_DETAILS_POSIX_CONDITION_HXX + +#include + +#include + +#include +#include + +namespace odb +{ + namespace details + { + class lock; + + class LIBODB_EXPORT condition + { + public: + ~condition (); + condition (mutex&); + + void + signal (); + + void + wait (lock&); + + private: + condition (const condition&); + condition& operator= (const condition&); + + private: + mutex& mutex_; + pthread_cond_t cond_; + }; + } +} + +#include + +#include + +#endif // ODB_DETAILS_POSIX_CONDITION_HXX diff --git a/libodb/odb/details/posix/condition.ixx b/libodb/odb/details/posix/condition.ixx new file mode 100644 index 0000000..9b68d9f --- /dev/null +++ b/libodb/odb/details/posix/condition.ixx @@ -0,0 +1,38 @@ +// file : odb/details/posix/condition.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + inline condition:: + ~condition () + { + pthread_cond_destroy (&cond_); + } + + inline condition:: + condition (mutex& mutex) + : mutex_ (mutex) + { + if (int e = pthread_cond_init (&cond_, 0)) + throw posix_exception (e); + } + + inline void condition:: + signal () + { + if (int e = pthread_cond_signal (&cond_)) + throw posix_exception (e); + } + + inline void condition:: + wait (lock&) + { + if (int e = pthread_cond_wait (&cond_, &mutex_.mutex_)) + throw posix_exception (e); + } + } +} diff --git a/libodb/odb/details/posix/exceptions.cxx b/libodb/odb/details/posix/exceptions.cxx new file mode 100644 index 0000000..c346655 --- /dev/null +++ b/libodb/odb/details/posix/exceptions.cxx @@ -0,0 +1,22 @@ +// file : odb/details/posix/exceptions.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + const char* posix_exception:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "POSIX API error"; + } + + posix_exception* posix_exception:: + clone () const + { + return new posix_exception (*this); + } + } +} diff --git a/libodb/odb/details/posix/exceptions.hxx b/libodb/odb/details/posix/exceptions.hxx new file mode 100644 index 0000000..aff33b6 --- /dev/null +++ b/libodb/odb/details/posix/exceptions.hxx @@ -0,0 +1,38 @@ +// file : odb/details/posix/exceptions.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_POSIX_EXCEPTIONS_HXX +#define ODB_DETAILS_POSIX_EXCEPTIONS_HXX + +#include + +#include // ODB_NOTHROW_NOEXCEPT +#include +#include + +namespace odb +{ + namespace details + { + struct LIBODB_EXPORT posix_exception: details::exception + { + posix_exception (int code) : code_ (code) {} + + int + code () const {return code_;} + + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual posix_exception* + clone () const; + + private: + int code_; + }; + } +} + +#include + +#endif // ODB_DETAILS_POSIX_EXCEPTIONS_HXX diff --git a/libodb/odb/details/posix/mutex.hxx b/libodb/odb/details/posix/mutex.hxx new file mode 100644 index 0000000..0cb94db --- /dev/null +++ b/libodb/odb/details/posix/mutex.hxx @@ -0,0 +1,44 @@ +// file : odb/details/posix/mutex.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_POSIX_MUTEX_HXX +#define ODB_DETAILS_POSIX_MUTEX_HXX + +#include + +#include + +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT mutex + { + public: + ~mutex (); + mutex (); + + void + lock (); + + void + unlock (); + + private: + mutex (const mutex&); + mutex& operator= (const mutex&); + + private: + friend class condition; + pthread_mutex_t mutex_; + }; + } +} + +#include + +#include + +#endif // ODB_DETAILS_POSIX_MUTEX_HXX diff --git a/libodb/odb/details/posix/mutex.ixx b/libodb/odb/details/posix/mutex.ixx new file mode 100644 index 0000000..ee73d09 --- /dev/null +++ b/libodb/odb/details/posix/mutex.ixx @@ -0,0 +1,37 @@ +// file : odb/details/posix/mutex.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + inline mutex:: + ~mutex () + { + pthread_mutex_destroy (&mutex_); + } + + inline mutex:: + mutex () + { + if (int e = pthread_mutex_init (&mutex_, 0)) + throw posix_exception (e); + } + + inline void mutex:: + lock () + { + if (int e = pthread_mutex_lock (&mutex_)) + throw posix_exception (e); + } + + inline void mutex:: + unlock () + { + if (int e = pthread_mutex_unlock (&mutex_)) + throw posix_exception (e); + } + } +} diff --git a/libodb/odb/details/posix/thread.cxx b/libodb/odb/details/posix/thread.cxx new file mode 100644 index 0000000..045f32a --- /dev/null +++ b/libodb/odb/details/posix/thread.cxx @@ -0,0 +1,44 @@ +// file : odb/details/posix/thread.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +typedef void* (*thread_func) (void*); + +struct thread_data +{ + thread_func func; + void* arg; +}; + +extern "C" void* +odb_thread_thunk (void* arg) +{ + thread_data* data (static_cast (arg)); + thread_func func = data->func; + arg = data->arg; + delete data; + return func (arg); +} + +namespace odb +{ + namespace details + { + thread:: + thread (void* (*func) (void*), void* arg) + : detached_ (false) + { + unique_ptr data (new thread_data); + data->func = func; + data->arg = arg; + + if (int e = pthread_create (&id_, 0, &odb_thread_thunk, data.get ())) + throw posix_exception (e); + + data.release (); // Thread thunk will free this. + } + } +} diff --git a/libodb/odb/details/posix/thread.hxx b/libodb/odb/details/posix/thread.hxx new file mode 100644 index 0000000..f0d29a7 --- /dev/null +++ b/libodb/odb/details/posix/thread.hxx @@ -0,0 +1,41 @@ +// file : odb/details/posix/thread.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_POSIX_THREAD_HXX +#define ODB_DETAILS_POSIX_THREAD_HXX + +#include + +#include + +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT thread + { + public: + ~thread (); + thread (void* (*thread_func) (void*), void* arg = 0); + + void* + join (); + + private: + thread (const thread&); + thread& operator= (const thread&); + + private: + bool detached_; + pthread_t id_; + }; + } +} + +#include + +#include + +#endif // ODB_DETAILS_POSIX_THREAD_HXX diff --git a/libodb/odb/details/posix/thread.ixx b/libodb/odb/details/posix/thread.ixx new file mode 100644 index 0000000..6576101 --- /dev/null +++ b/libodb/odb/details/posix/thread.ixx @@ -0,0 +1,29 @@ +// file : odb/details/posix/thread.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + inline thread:: + ~thread () + { + if (!detached_) + pthread_detach (id_); + } + + inline void* thread:: + join () + { + void* r; + + if (int e = pthread_join (id_, &r)) + throw posix_exception (e); + + detached_ = true; + return r; + } + } +} diff --git a/libodb/odb/details/posix/tls.hxx b/libodb/odb/details/posix/tls.hxx new file mode 100644 index 0000000..e868819 --- /dev/null +++ b/libodb/odb/details/posix/tls.hxx @@ -0,0 +1,106 @@ +// file : odb/details/posix/tls.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_POSIX_TLS_HXX +#define ODB_DETAILS_POSIX_TLS_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + template + class tls + { + public: + tls (); + + T& + get () const; + + void + free (); + + private: + tls (const tls&); + tls& operator= (const tls&); + + private: + static void + key_init (); + + static void + destructor (void*); + + private: + static int error_; + static pthread_once_t once_; + static pthread_key_t key_; + }; + + template + class tls + { + public: + tls (); + + T* + get () const; + + void + set (T* p); + + private: + tls (const tls&); + tls& operator= (const tls&); + + private: + static void + key_init (); + + private: + static int error_; + static pthread_once_t once_; + static pthread_key_t key_; + }; + + template + inline T& + tls_get (const tls& t) + { + return t.get (); + } + + template + inline void + tls_free (tls& t) + { + t.free (); + } + + template + inline T* + tls_get (const tls& t) + { + return t.get (); + } + + template + inline void + tls_set (tls& t, T1* p1) + { + T* p (p1); + t.set (p); + } + } +} + +#include +#include + +#include + +#endif // ODB_DETAILS_POSIX_TLS_HXX diff --git a/libodb/odb/details/posix/tls.ixx b/libodb/odb/details/posix/tls.ixx new file mode 100644 index 0000000..7acc173 --- /dev/null +++ b/libodb/odb/details/posix/tls.ixx @@ -0,0 +1,20 @@ +// file : odb/details/posix/tls.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace details + { + template + inline tls:: + tls () + { + } + + template + inline tls:: + tls () + { + } + } +} diff --git a/libodb/odb/details/posix/tls.txx b/libodb/odb/details/posix/tls.txx new file mode 100644 index 0000000..e4c5b8f --- /dev/null +++ b/libodb/odb/details/posix/tls.txx @@ -0,0 +1,121 @@ +// file : odb/details/posix/tls.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +namespace odb +{ + namespace details + { + // tls + // + + template + int tls::error_ = 0; + + template + pthread_once_t tls::once_ = PTHREAD_ONCE_INIT; + + template + pthread_key_t tls::key_; + + template + T& tls:: + get () const + { + int e (pthread_once (&once_, key_init)); + + if (e != 0 || error_ != 0) + throw posix_exception (e ? e : error_); + + if (void* v = pthread_getspecific (key_)) + return *static_cast (v); + + unique_ptr p (new T); + + if ((e = pthread_setspecific (key_, p.get ()))) + throw posix_exception (e); + + T& r (*p); + p.release (); + return r; + } + + template + void tls:: + free () + { + int e (pthread_once (&once_, key_init)); + + if (e != 0 || error_ != 0) + throw posix_exception (e ? e : error_); + + if (void* v = pthread_getspecific (key_)) + { + if ((e = pthread_setspecific (key_, 0))) + throw posix_exception (e); + + delete static_cast (v); + } + } + + template + void tls:: + key_init () + { + error_ = pthread_key_create (&key_, destructor); + } + + template + void tls:: + destructor (void* v) + { + delete static_cast (v); + } + + // tls + // + + template + int tls::error_ = 0; + + template + pthread_once_t tls::once_ = PTHREAD_ONCE_INIT; + + template + pthread_key_t tls::key_; + + template + T* tls:: + get () const + { + int e (pthread_once (&once_, key_init)); + + if (e != 0 || error_ != 0) + throw posix_exception (e ? e : error_); + + return static_cast (pthread_getspecific (key_)); + } + + template + void tls:: + set (T* p) + { + int e (pthread_once (&once_, key_init)); + + if (e != 0 || error_ != 0) + throw posix_exception (e ? e : error_); + + if ((e = pthread_setspecific (key_, p))) + throw posix_exception (e); + } + + template + void tls:: + key_init () + { + error_ = pthread_key_create (&key_, 0); + } + } +} diff --git a/libodb/odb/details/shared-ptr-fwd.hxx b/libodb/odb/details/shared-ptr-fwd.hxx new file mode 100644 index 0000000..73377b9 --- /dev/null +++ b/libodb/odb/details/shared-ptr-fwd.hxx @@ -0,0 +1,24 @@ +// file : odb/details/shared-ptr-fwd.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_SHARED_PTR_FWD_HXX +#define ODB_DETAILS_SHARED_PTR_FWD_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + template + class shared_ptr; + + class shared_base; + } +} + +#include + +#endif // ODB_DETAILS_SHARED_PTR_FWD_HXX diff --git a/libodb/odb/details/shared-ptr.hxx b/libodb/odb/details/shared-ptr.hxx new file mode 100644 index 0000000..5a1e842 --- /dev/null +++ b/libodb/odb/details/shared-ptr.hxx @@ -0,0 +1,167 @@ +// file : odb/details/shared-ptr.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_SHARED_PTR_HXX +#define ODB_DETAILS_SHARED_PTR_HXX + +#include + +#include +#include +#include + +namespace odb +{ + namespace details + { + template + class shared_ptr: + private 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 (const shared_ptr& x) + : base (x), x_ (x.x_) + { + if (x_ != 0) + base::inc (x_); + } + + template + shared_ptr (const shared_ptr& x) + : base (x), x_ (x.x_) + { + if (x_ != 0) + base::inc (x_); + } + + shared_ptr& + operator= (const shared_ptr& 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= (const shared_ptr& 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; + } + + void + reset (X* x = 0) + { + if (x_ != 0) + base::dec (x_); + + base::reset (x); + x_ = x; + } + + std::size_t + count () const + { + return x_ != 0 ? base::count (x_) : 0; + } + + private: + template + friend class shared_ptr; + + X* x_; + }; + + template + inline bool + operator== (const shared_ptr& x, const shared_ptr& y) + { + return x.get () == y.get (); + } + + template + inline bool + operator!= (const shared_ptr& x, const shared_ptr& y) + { + return x.get () != y.get (); + } + } +} + +#include + +#endif // ODB_DETAILS_SHARED_PTR_HXX diff --git a/libodb/odb/details/shared-ptr/base.cxx b/libodb/odb/details/shared-ptr/base.cxx new file mode 100644 index 0000000..d937400 --- /dev/null +++ b/libodb/odb/details/shared-ptr/base.cxx @@ -0,0 +1,83 @@ +// file : odb/details/shared-ptr/base.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +using std::size_t; + +namespace odb +{ + namespace details + { + share shared = share (1); + share exclusive = share (2); + + const char* not_shared:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "object is not shared"; + } + + not_shared* not_shared:: + clone () const + { + return new not_shared (*this); + } + + namespace bits + { + size_t* locator_common:: + counter (void* x) + { + size_t* p (static_cast (x)); + + if (*(--p) != 0xDEADBEEF) + throw not_shared (); + + return --p; + } + } + } +} + +void* +#ifdef ODB_CXX11 +operator new (size_t n, odb::details::share s) +#else +operator new (size_t n, odb::details::share s) throw (std::bad_alloc) +#endif +{ + if (s == odb::details::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, odb::details::share s) ODB_NOTHROW_NOEXCEPT +{ + // 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 == odb::details::shared) + { + size_t* sp = static_cast (p); + sp -= 2; + operator delete (sp); + } + else + operator delete (p); +} diff --git a/libodb/odb/details/shared-ptr/base.hxx b/libodb/odb/details/shared-ptr/base.hxx new file mode 100644 index 0000000..8cd4c86 --- /dev/null +++ b/libodb/odb/details/shared-ptr/base.hxx @@ -0,0 +1,131 @@ +// file : odb/details/shared-ptr/base.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_SHARED_PTR_BASE_HXX +#define ODB_DETAILS_SHARED_PTR_BASE_HXX + +#include + +#include // ODB_CXX11, ODB_NOTHROW_NOEXCEPT + +#include +#include // std::size_t + +#ifdef ODB_CXX11 +#include +#endif + +#include +#include + +namespace odb +{ + namespace details + { + struct share + { + explicit + share (char id); + + bool + operator== (share) const; + + private: + char id_; + }; + + extern LIBODB_EXPORT share shared; + extern LIBODB_EXPORT share exclusive; + } +} + +#ifdef ODB_CXX11 +LIBODB_EXPORT void* +operator new (std::size_t, odb::details::share); +#else +LIBODB_EXPORT void* +operator new (std::size_t, odb::details::share) throw (std::bad_alloc); +#endif + +LIBODB_EXPORT void +operator delete (void*, odb::details::share) ODB_NOTHROW_NOEXCEPT; + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT shared_base + { + public: + shared_base (); + shared_base (const shared_base&); + shared_base& + operator= (const shared_base&); + + void + _inc_ref (); + + bool + _dec_ref (); + + std::size_t + _ref_count () const; + +#ifdef ODB_CXX11 + void* + operator new (std::size_t); + + void* + operator new (std::size_t, share); +#else + void* + operator new (std::size_t) throw (std::bad_alloc); + + void* + operator new (std::size_t, share) throw (std::bad_alloc); +#endif + + void + operator delete (void*, share) ODB_NOTHROW_NOEXCEPT; + + void + operator delete (void*) ODB_NOTHROW_NOEXCEPT; + + struct refcount_callback + { + void* arg; + + // Return true if the object should be deleted, false otherwise. + // + bool (*zero_counter) (void*); + }; + + protected: +#ifdef ODB_CXX11 + std::atomic counter_; +#else + std::size_t counter_; +#endif + refcount_callback* callback_; + }; + + template + inline X* + inc_ref (X*); + + template + inline void + dec_ref (X*); + + template + inline std::size_t + ref_count (const X*); + } +} + +#include +#include + +#include + +#endif // ODB_DETAILS_SHARED_PTR_BASE_HXX diff --git a/libodb/odb/details/shared-ptr/base.ixx b/libodb/odb/details/shared-ptr/base.ixx new file mode 100644 index 0000000..1e2fd4b --- /dev/null +++ b/libodb/odb/details/shared-ptr/base.ixx @@ -0,0 +1,119 @@ +// file : odb/details/shared-ptr/base.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace details + { + // 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), callback_ (0) + { + } + + inline shared_base:: + shared_base (const shared_base&) + : counter_ (1), callback_ (0) + { + } + + inline shared_base& shared_base:: + operator= (const shared_base&) + { + return *this; + } + + inline void shared_base:: + _inc_ref () + { +#ifdef ODB_CXX11 + counter_.fetch_add (1, std::memory_order_relaxed); +#else + ++counter_; +#endif + } + + inline bool shared_base:: + _dec_ref () + { + // While there are ways to avoid acquire (which is unnecessary except + // when the counter drops to zero), for our use-cases we'd rather keep + // it simple. + // + return +#ifdef ODB_CXX11 + counter_.fetch_sub (1, std::memory_order_acq_rel) == 1 +#else + --counter_ == 0 +#endif + ? callback_ == 0 || callback_->zero_counter (callback_->arg) + : false; + } + + inline std::size_t shared_base:: + _ref_count () const + { +#ifdef ODB_CXX11 + return counter_.load (std::memory_order_relaxed); +#else + return counter_; +#endif + } + +#ifdef ODB_CXX11 + inline void* shared_base:: + operator new (std::size_t n) + { + return ::operator new (n); + } + + inline void* shared_base:: + operator new (std::size_t n, share) + { + return ::operator new (n); + } +#else + inline void* shared_base:: + operator new (std::size_t n) throw (std::bad_alloc) + { + return ::operator new (n); + } + + inline void* shared_base:: + operator new (std::size_t n, share) throw (std::bad_alloc) + { + return ::operator new (n); + } +#endif + + inline void shared_base:: + operator delete (void* p, share) ODB_NOTHROW_NOEXCEPT + { + ::operator delete (p); + } + + inline void shared_base:: + operator delete (void* p) ODB_NOTHROW_NOEXCEPT + { + ::operator delete (p); + } + } +} diff --git a/libodb/odb/details/shared-ptr/base.txx b/libodb/odb/details/shared-ptr/base.txx new file mode 100644 index 0000000..77a957d --- /dev/null +++ b/libodb/odb/details/shared-ptr/base.txx @@ -0,0 +1,198 @@ +// file : odb/details/shared-ptr/base.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +namespace odb +{ + namespace details + { + namespace bits + { + // Support for locating the counter in the memory block. + // + struct LIBODB_EXPORT locator_common + { + static std::size_t* + counter (void*); + }; + + template ::result> + struct locator; + + template + struct locator: locator_common + { + static std::size_t* + counter (X* x) + { + return locator_common::counter (x); + } + }; + + template + struct locator: locator_common + { + static std::size_t* + counter (X* x) + { + return locator_common::counter (dynamic_cast (x)); + } + }; + + template + std::size_t* + counter (const X* 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 typename details::counter_type::counter r; + }; + + template + struct counter_type + { + typedef shared_base r; + }; + + template + struct counter_ops; + + template + struct counter_ops + { + counter_ops (const X* p) : counter_ (p ? bits::counter (p) : 0) {} + counter_ops (const counter_ops& x) : counter_ (x.counter_) {} + + template + counter_ops (const counter_ops& x) : counter_ (x.counter_) {} + + counter_ops& + operator= (const counter_ops& x) + { + counter_ = x.counter_; + return *this; + } + + template + counter_ops& + operator= (const counter_ops& x) + { + counter_ = x.counter_; + return *this; + } + + void + reset (const X* p) + { + counter_ = p ? bits::counter (p) : 0; + } + + void + inc (X*) + { + (*counter_)++; + } + + void + dec (X* p) + { + if (--(*counter_) == 0) + { + p->~X (); + + // Counter is the top of the memory block. + // + operator delete (counter_); + } + } + + std::size_t + count (const X*) const + { + return *counter_; + } + + std::size_t* counter_; + }; + + template + struct counter_ops + { + counter_ops (const Y*) {} + counter_ops (const counter_ops&) {} + + template + counter_ops (const counter_ops&) {} + + counter_ops& + operator= (const counter_ops&) + { + return *this; + } + + template + counter_ops& + operator= (const counter_ops&) + { + return *this; + } + + void + reset (const Y*) {} + + void + inc (shared_base* p) {p->_inc_ref ();} + + void + dec (Y* p) + { + if (static_cast (p)->_dec_ref ()) + delete p; + } + + std::size_t + count (const shared_base* 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 (const X* p) + { + bits::counter_ops::r, X> c (p); + return c.count (p); + } + } +} diff --git a/libodb/odb/details/shared-ptr/counter-type.hxx b/libodb/odb/details/shared-ptr/counter-type.hxx new file mode 100644 index 0000000..2b6caad --- /dev/null +++ b/libodb/odb/details/shared-ptr/counter-type.hxx @@ -0,0 +1,23 @@ +// file : odb/details/shared-ptr/counter-type.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_SHARED_PTR_COUNTER_TYPE_HXX +#define ODB_DETAILS_SHARED_PTR_COUNTER_TYPE_HXX + +#include + +namespace odb +{ + namespace details + { + template + struct counter_type + { + typedef X counter; + }; + } +} + +#include + +#endif // ODB_DETAILS_SHARED_PTR_COUNTER_TYPE_HXX diff --git a/libodb/odb/details/shared-ptr/exception.hxx b/libodb/odb/details/shared-ptr/exception.hxx new file mode 100644 index 0000000..0ed50be --- /dev/null +++ b/libodb/odb/details/shared-ptr/exception.hxx @@ -0,0 +1,31 @@ +// file : odb/details/shared-ptr/exception.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_SHARED_PTR_EXCEPTION_HXX +#define ODB_DETAILS_SHARED_PTR_EXCEPTION_HXX + +#include + +#include + +#include // ODB_NOTHROW_NOEXCEPT +#include + +namespace odb +{ + namespace details + { + struct LIBODB_EXPORT not_shared: exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual not_shared* + clone () const; + }; + } +} + +#include + +#endif // ODB_DETAILS_SHARED_PTR_EXCEPTION_HXX diff --git a/libodb/odb/details/thread.cxx b/libodb/odb/details/thread.cxx new file mode 100644 index 0000000..b1fbe42 --- /dev/null +++ b/libodb/odb/details/thread.cxx @@ -0,0 +1,22 @@ +// file : odb/details/thread.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +// We might be compiled with ODB_THREADS_NONE. +// +#ifdef ODB_THREADS_CXX11 + +namespace odb +{ + namespace details + { + void thread:: + thunk (void* (*f) (void*), void* a, std::promise p) + { + p.set_value (f (a)); + } + } +} + +#endif diff --git a/libodb/odb/details/thread.hxx b/libodb/odb/details/thread.hxx new file mode 100644 index 0000000..9095f68 --- /dev/null +++ b/libodb/odb/details/thread.hxx @@ -0,0 +1,65 @@ +// file : odb/details/thread.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_THREAD_HXX +#define ODB_DETAILS_THREAD_HXX + +#include + +#include +#include + +#ifdef ODB_THREADS_NONE +# error no thread support available +#elif defined(ODB_THREADS_CXX11) +# include +# include +# include // move() + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT thread + { + public: + thread (void* (*thread_func) (void*), void* arg = 0) + { + std::promise p; + f_ = p.get_future (); + t_ = std::thread (thunk, thread_func, arg, std::move (p)); + } + + void* + join () + { + f_.wait (); + t_.join (); + return f_.get (); + } + + thread (const thread&) = delete; + thread& operator= (const thread&) = delete; + + private: + static void + thunk (void* (*) (void*), void*, std::promise); + + private: + std::thread t_; + std::future f_; + }; + } +} + +#elif defined(ODB_THREADS_POSIX) +#include +#elif defined(ODB_THREADS_WIN32) +#include +#else +# error unknown threading model +#endif + +#include + +#endif // ODB_DETAILS_THREAD_HXX diff --git a/libodb/odb/details/tls.hxx b/libodb/odb/details/tls.hxx new file mode 100644 index 0000000..de6c344 --- /dev/null +++ b/libodb/odb/details/tls.hxx @@ -0,0 +1,168 @@ +// file : odb/details/tls.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_TLS_HXX +#define ODB_DETAILS_TLS_HXX + +#include + +#include + +#ifdef ODB_THREADS_NONE + +# define ODB_TLS_POINTER(type) type* +# define ODB_TLS_OBJECT(type) type + +namespace odb +{ + namespace details + { + template + inline T& + tls_get (T& x) + { + return x; + } + + // If early destructions is possible, destroy the object and free + // any allocated resources. + // + template + inline void + tls_free (T&) + { + } + + template + inline T* + tls_get (T* p) + { + return p; + } + + template + inline void + tls_set (T*& rp, T1* p) + { + rp = p; + } + } +} + +#elif defined(ODB_THREADS_CXX11) + +// Apparently Apple's Clang "temporarily disabled" C++11 thread_local until +// they can implement a "fast" version, which reportedly happened in XCode 8. +// So for now we will continue using __thread for this target. +// +# if defined(__apple_build_version__) && __apple_build_version__ < 8000000 +# define ODB_TLS_POINTER(type) __thread type* +# define ODB_TLS_OBJECT(type) thread_local type +# else +# define ODB_TLS_POINTER(type) thread_local type* +# define ODB_TLS_OBJECT(type) thread_local type +# endif + +namespace odb +{ + namespace details + { + template + inline T& + tls_get (T& x) + { + return x; + } + + template + inline void + tls_free (T&) + { + } + + template + inline T* + tls_get (T* p) + { + return p; + } + + template + inline void + tls_set (T*& rp, T1* p) + { + rp = p; + } + } +} + +#elif defined(ODB_THREADS_POSIX) + +# include + +# ifdef ODB_THREADS_TLS_KEYWORD +# define ODB_TLS_POINTER(type) __thread type* + +namespace odb +{ + namespace details + { + template + inline T* + tls_get (T* p) + { + return p; + } + + template + inline void + tls_set (T*& rp, T1* p) + { + rp = p; + } + } +} + +# else +# define ODB_TLS_POINTER(type) tls +# endif +# define ODB_TLS_OBJECT(type) tls + +#elif defined(ODB_THREADS_WIN32) + +# include + +# ifdef ODB_THREADS_TLS_DECLSPEC +# define ODB_TLS_POINTER(type) __declspec(thread) type* + +namespace odb +{ + namespace details + { + template + inline T* + tls_get (T* p) + { + return p; + } + + template + inline void + tls_set (T*& rp, T1* p) + { + rp = p; + } + } +} + +# else +# define ODB_TLS_POINTER(type) tls +# endif +# define ODB_TLS_OBJECT(type) tls +#else +# error unknown threading model +#endif + +#include + +#endif // ODB_DETAILS_TLS_HXX diff --git a/libodb/odb/details/transfer-ptr.hxx b/libodb/odb/details/transfer-ptr.hxx new file mode 100644 index 0000000..4b63df6 --- /dev/null +++ b/libodb/odb/details/transfer-ptr.hxx @@ -0,0 +1,73 @@ +// file : odb/details/transfer-ptr.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_TRANSFER_PTR_HXX +#define ODB_DETAILS_TRANSFER_PTR_HXX + +#include + +#include // std::auto_ptr, std::unique_ptr + +#include // ODB_CXX11 + +namespace odb +{ + namespace details + { + template + class transfer_ptr + { + public: + typedef T element_type; + + transfer_ptr (): p_ (0) {} + +#ifndef ODB_CXX11 + template + transfer_ptr (std::auto_ptr p): p_ (p.release ()) {} + + private: + transfer_ptr& operator= (const transfer_ptr&); + + public: + // In our usage transfer_ptr is always created implicitly and + // never const. So while this is not very clean, it is legal. + // Plus it will all go away once we drop C++98 (I can hardly + // wait). + // + transfer_ptr (const transfer_ptr& p) + : p_ (const_cast (p).transfer ()) {} +#else +#ifdef ODB_CXX11_NULLPTR + transfer_ptr (std::nullptr_t): p_ (0) {} +#endif + template + transfer_ptr (std::unique_ptr&& p): p_ (p.release ()) {} + + private: + transfer_ptr (const transfer_ptr&); + transfer_ptr& operator= (const transfer_ptr&); + + public: + transfer_ptr (transfer_ptr&& p) noexcept: p_ (p.transfer ()) {} +#endif + + ~transfer_ptr () {delete p_;} + + T* + transfer () + { + T* r (p_); + p_ = 0; + return r; + } + + private: + T* p_; + }; + } +} + +#include + +#endif // ODB_DETAILS_TRANSFER_PTR_HXX diff --git a/libodb/odb/details/type-info.hxx b/libodb/odb/details/type-info.hxx new file mode 100644 index 0000000..fe01699 --- /dev/null +++ b/libodb/odb/details/type-info.hxx @@ -0,0 +1,36 @@ +// file : odb/details/type-info.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_TYPE_INFO_HXX +#define ODB_DETAILS_TYPE_INFO_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + struct type_info_comparator + { + bool + operator() (const std::type_info* x, const std::type_info* y) const + { + // XL C++ on AIX has buggy type_info::before() in that + // it returns true for two different type_info objects + // that happened to be for the same type. + // +#if defined(__xlC__) && defined(_AIX) + return *x != *y && x->before (*y); +#else + return x->before (*y); +#endif + } + }; + } +} + +#include + +#endif // ODB_DETAILS_TYPE_INFO_HXX diff --git a/libodb/odb/details/unique-ptr.hxx b/libodb/odb/details/unique-ptr.hxx new file mode 100644 index 0000000..06b2c76 --- /dev/null +++ b/libodb/odb/details/unique-ptr.hxx @@ -0,0 +1,95 @@ +// file : odb/details/unique-ptr.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_UNIQUE_PTR_HXX +#define ODB_DETAILS_UNIQUE_PTR_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + template + class unique_ptr + { + public: + typedef T element_type; + + explicit unique_ptr (T* p = 0): p_ (p) {} + ~unique_ptr () {delete p_;} + +#ifdef ODB_CXX11 + unique_ptr (unique_ptr&& p) noexcept: p_ (p.p_) {p.p_ = 0;} + unique_ptr& operator= (unique_ptr&& p) noexcept + { + if (this != &p) + { + delete p_; + p_ = p.p_; + p.p_ = 0; + } + return *this; + } +#endif + + private: + unique_ptr (const unique_ptr&); + unique_ptr& operator= (const unique_ptr&); + + public: + T* + operator-> () const {return p_;} + + T& + operator* () const {return *p_;} + + typedef T* unique_ptr::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return p_ != 0 ? &unique_ptr::p_ : 0; + } + + T* + get () const {return p_;} + + void + reset (T* p = 0) + { + delete p_; + p_ = p; + } + + T* + release () + { + T* r (p_); + p_ = 0; + return r; + } + + private: + T* p_; + }; + + template + inline bool + operator== (const unique_ptr& a, const unique_ptr& b) + { + return a.get () == b.get (); + } + + template + inline bool + operator!= (const unique_ptr& a, const unique_ptr& b) + { + return a.get () != b.get (); + } + } +} + +#include + +#endif // ODB_DETAILS_UNIQUE_PTR_HXX diff --git a/libodb/odb/details/unused.hxx b/libodb/odb/details/unused.hxx new file mode 100644 index 0000000..8364c44 --- /dev/null +++ b/libodb/odb/details/unused.hxx @@ -0,0 +1,21 @@ +// file : odb/details/unused.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_UNUSED_DETAILS_HXX +#define ODB_UNUSED_DETAILS_HXX + +#include + +// VC++ and xlC don't like the (void)x expression if x is a reference +// to an incomplete type. On the other hand, GCC warns that (void*)&x +// doesn't have any effect. +// +#if defined(_MSC_VER) || defined(__xlC__) +# define ODB_POTENTIALLY_UNUSED(x) (void*)&x +#else +# define ODB_POTENTIALLY_UNUSED(x) (void)x +#endif + +#include + +#endif // ODB_UNUSED_DETAILS_HXX diff --git a/libodb/odb/details/win32/condition.cxx b/libodb/odb/details/win32/condition.cxx new file mode 100644 index 0000000..3a4b605 --- /dev/null +++ b/libodb/odb/details/win32/condition.cxx @@ -0,0 +1,54 @@ +// file : odb/details/win32/condition.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +namespace odb +{ + namespace details + { + void condition:: + signal () + { + mutex_.lock (); + + if (waiters_ > signals_) + { + if (signals_++ == 0) + { + if (SetEvent (event_) == 0) + throw win32_exception (); + } + } + + mutex_.unlock (); + } + + void condition:: + wait (lock&) + { + // When we enter this functions the mutex is locked. When we + // return from this function the mutex must be locked. + // + waiters_++; + mutex_.unlock (); + + if (WaitForSingleObject (event_, INFINITE) != 0) + throw win32_exception (); + + mutex_.lock (); + waiters_--; + signals_--; + + if (signals_ > 0) + { + // Wake up the next thread. + // + if (SetEvent (event_) == 0) + throw win32_exception (); + } + } + } +} diff --git a/libodb/odb/details/win32/condition.hxx b/libodb/odb/details/win32/condition.hxx new file mode 100644 index 0000000..69972a0 --- /dev/null +++ b/libodb/odb/details/win32/condition.hxx @@ -0,0 +1,52 @@ +// file : odb/details/win32/condition.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_CONDITION_HXX +#define ODB_DETAILS_WIN32_CONDITION_HXX + +#include + +#include + +#include // std::size_t + +#include +#include + +namespace odb +{ + namespace details + { + class lock; + + class LIBODB_EXPORT condition + { + public: + ~condition (); + condition (mutex&); + + void + signal (); + + void + wait (lock&); + + private: + condition (const condition&); + condition& operator= (const condition&); + + private: + mutex& mutex_; + HANDLE event_; + + std::size_t waiters_; + std::size_t signals_; + }; + } +} + +#include + +#include + +#endif // ODB_DETAILS_WIN32_CONDITION_HXX diff --git a/libodb/odb/details/win32/condition.ixx b/libodb/odb/details/win32/condition.ixx new file mode 100644 index 0000000..37a2bac --- /dev/null +++ b/libodb/odb/details/win32/condition.ixx @@ -0,0 +1,30 @@ +// file : odb/details/win32/condition.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + inline condition:: + ~condition () + { + CloseHandle (event_); + } + + inline condition:: + condition (mutex& mutex) + : mutex_ (mutex), waiters_ (0), signals_ (0) + { + // Auto-reset event. Releases one waiting thread and automatically + // resets the event state. If no threads are waiting the event + // remains signalled. + // + event_ = CreateEvent (0, false, false, 0); + + if (event_ == 0) + throw win32_exception (); + } + } +} diff --git a/libodb/odb/details/win32/dll.cxx b/libodb/odb/details/win32/dll.cxx new file mode 100644 index 0000000..49b660c --- /dev/null +++ b/libodb/odb/details/win32/dll.cxx @@ -0,0 +1,51 @@ +// file : odb/details/win32/dll.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// If we are building a static library from VC++ (LIBODB_STATIC_LIB) or +// a static library from automake (!DLL_EXPORT), then omit DllMain. +// + +#if (defined(_MSC_VER) && defined(LIBODB_DYNAMIC_LIB)) || \ + (!defined(_MSC_VER) && defined(DLL_EXPORT)) + +#include +#include + +using namespace odb::details; + +extern "C" BOOL WINAPI +DllMain (HINSTANCE, DWORD reason, LPVOID reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + { + process_start (); + thread_start (); + break; + } + + case DLL_THREAD_ATTACH: + { + thread_start (); + break; + } + + case DLL_THREAD_DETACH: + { + thread_end (); + break; + } + + case DLL_PROCESS_DETACH: + { + thread_end (); + process_end (reserved == NULL); + break; + } + } + + return 1; +} + +#endif diff --git a/libodb/odb/details/win32/exceptions.cxx b/libodb/odb/details/win32/exceptions.cxx new file mode 100644 index 0000000..3cf11c2 --- /dev/null +++ b/libodb/odb/details/win32/exceptions.cxx @@ -0,0 +1,22 @@ +// file : odb/details/win32/exceptions.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + const char* win32_exception:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "Win32 API error"; + } + + win32_exception* win32_exception:: + clone () const + { + return new win32_exception (*this); + } + } +} diff --git a/libodb/odb/details/win32/exceptions.hxx b/libodb/odb/details/win32/exceptions.hxx new file mode 100644 index 0000000..b61a447 --- /dev/null +++ b/libodb/odb/details/win32/exceptions.hxx @@ -0,0 +1,40 @@ +// file : odb/details/win32/exceptions.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_EXCEPTIONS_HXX +#define ODB_DETAILS_WIN32_EXCEPTIONS_HXX + +#include + +#include // ODB_NOTHROW_NOEXCEPT +#include +#include +#include + +namespace odb +{ + namespace details + { + struct LIBODB_EXPORT win32_exception: details::exception + { + win32_exception () : code_ (GetLastError ()) {} + win32_exception (DWORD code) : code_ (code) {} + + DWORD + code () const {return code_;} + + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual win32_exception* + clone () const; + + private: + DWORD code_; + }; + } +} + +#include + +#endif // ODB_DETAILS_WIN32_EXCEPTIONS_HXX diff --git a/libodb/odb/details/win32/init.cxx b/libodb/odb/details/win32/init.cxx new file mode 100644 index 0000000..f6e0f9a --- /dev/null +++ b/libodb/odb/details/win32/init.cxx @@ -0,0 +1,41 @@ +// file : odb/details/win32/init.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +namespace odb +{ + namespace details + { + void + process_start () + { + // The order is important. + // + once_process_start (); + tls_process_start (); + } + + void + process_end (bool safe) + { + // The order is important. + // + tls_process_end (safe); + once_process_end (safe); + } + + void + thread_start () + { + } + + void + thread_end () + { + tls_thread_end (); + } + } +} diff --git a/libodb/odb/details/win32/init.hxx b/libodb/odb/details/win32/init.hxx new file mode 100644 index 0000000..1c15ffd --- /dev/null +++ b/libodb/odb/details/win32/init.hxx @@ -0,0 +1,36 @@ +// file : odb/details/win32/init.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_INIT_HXX +#define ODB_DETAILS_WIN32_INIT_HXX + +#include + +namespace odb +{ + namespace details + { + void + process_start (); + + // The safe parameter indicates whether it is safe to free heap objects. + // If the process is terminated by a call to ExitProcess(), some threads + // might have been killed leaving things in inconsistent state. + // + void + process_end (bool safe = true); + + void + thread_start (); + + // This function may be called even for thread for which thread_start() + // hasn't been called. + // + void + thread_end (); + } +} + +#include + +#endif // ODB_DETAILS_WIN32_INIT_HXX diff --git a/libodb/odb/details/win32/lock.hxx b/libodb/odb/details/win32/lock.hxx new file mode 100644 index 0000000..2e81ac6 --- /dev/null +++ b/libodb/odb/details/win32/lock.hxx @@ -0,0 +1,49 @@ +// file : odb/details/win32/lock.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_LOCK_HXX +#define ODB_DETAILS_WIN32_LOCK_HXX + +#include + +#include + +namespace odb +{ + namespace details + { + // Critical section lock. Not exported; for internal use only. + // + struct win32_lock + { + win32_lock (CRITICAL_SECTION& cs) + : cs_ (&cs) + { + EnterCriticalSection (cs_); + } + + ~win32_lock () + { + if (cs_ != 0) + LeaveCriticalSection (cs_); + } + + void + unlock () + { + if (cs_ != 0) + { + LeaveCriticalSection (cs_); + cs_ = 0; + } + } + + private: + CRITICAL_SECTION* cs_; + }; + } +} + +#include + +#endif // ODB_DETAILS_WIN32_LOCK_HXX diff --git a/libodb/odb/details/win32/mutex.hxx b/libodb/odb/details/win32/mutex.hxx new file mode 100644 index 0000000..b2cd997 --- /dev/null +++ b/libodb/odb/details/win32/mutex.hxx @@ -0,0 +1,43 @@ +// file : odb/details/win32/mutex.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_MUTEX_HXX +#define ODB_DETAILS_WIN32_MUTEX_HXX + +#include + +#include +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT mutex + { + public: + ~mutex (); + mutex (); + + void + lock (); + + void + unlock (); + + private: + mutex (const mutex&); + mutex& operator= (const mutex&); + + private: + friend class condition; + CRITICAL_SECTION cs_; + }; + } +} + +#include + +#include + +#endif // ODB_DETAILS_WIN32_MUTEX_HXX diff --git a/libodb/odb/details/win32/mutex.ixx b/libodb/odb/details/win32/mutex.ixx new file mode 100644 index 0000000..bb06415 --- /dev/null +++ b/libodb/odb/details/win32/mutex.ixx @@ -0,0 +1,32 @@ +// file : odb/details/win32/mutex.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace details + { + inline mutex:: + ~mutex () + { + DeleteCriticalSection (&cs_); + } + + inline mutex:: + mutex () + { + InitializeCriticalSection (&cs_); + } + + inline void mutex:: + lock () + { + EnterCriticalSection (&cs_); + } + + inline void mutex:: + unlock () + { + LeaveCriticalSection (&cs_); + } + } +} diff --git a/libodb/odb/details/win32/once-init.hxx b/libodb/odb/details/win32/once-init.hxx new file mode 100644 index 0000000..a465c90 --- /dev/null +++ b/libodb/odb/details/win32/once-init.hxx @@ -0,0 +1,23 @@ +// file : odb/details/win32/once-init.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_ONCE_INIT_HXX +#define ODB_DETAILS_WIN32_ONCE_INIT_HXX + +#include + +namespace odb +{ + namespace details + { + void + once_process_start (); + + void + once_process_end (bool safe); + } +} + +#include + +#endif // ODB_DETAILS_WIN32_ONCE_INIT_HXX diff --git a/libodb/odb/details/win32/once.cxx b/libodb/odb/details/win32/once.cxx new file mode 100644 index 0000000..7b98d80 --- /dev/null +++ b/libodb/odb/details/win32/once.cxx @@ -0,0 +1,26 @@ +// file : odb/details/win32/once.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +namespace odb +{ + namespace details + { + CRITICAL_SECTION win32_once_cs_; + + void + once_process_start () + { + InitializeCriticalSection (&win32_once_cs_); + } + + void + once_process_end (bool) + { + DeleteCriticalSection (&win32_once_cs_); + } + } +} diff --git a/libodb/odb/details/win32/once.hxx b/libodb/odb/details/win32/once.hxx new file mode 100644 index 0000000..45748b8 --- /dev/null +++ b/libodb/odb/details/win32/once.hxx @@ -0,0 +1,50 @@ +// file : odb/details/win32/once.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_ONCE_HXX +#define ODB_DETAILS_WIN32_ONCE_HXX + +#include + +#include +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT once + { + public: + once (); + + void + call (void (*func) ()); + + private: + once (const once&); + once& operator= (const once&); + + private: + bool called_; + }; + + // Low-level, POSIX-like API that can be used safely during static + // initialization (that is, win32_once() can be called during static + // initialization) provided once_process_start() has been called. + // + typedef unsigned int win32_once_t; + const win32_once_t WIN32_ONCE_INIT = 0; + + LIBODB_EXPORT void + win32_once (win32_once_t&, void (*func) ()); + + extern LIBODB_EXPORT CRITICAL_SECTION win32_once_cs_; + } +} + +#include + +#include + +#endif // ODB_DETAILS_WIN32_ONCE_HXX diff --git a/libodb/odb/details/win32/once.ixx b/libodb/odb/details/win32/once.ixx new file mode 100644 index 0000000..1638706 --- /dev/null +++ b/libodb/odb/details/win32/once.ixx @@ -0,0 +1,42 @@ +// file : odb/details/win32/once.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + namespace details + { + inline void + win32_once (win32_once_t& o, void (*func) ()) + { + win32_lock l (win32_once_cs_); + + if (o == 0) + { + o = 1; + l.unlock (); + func (); + } + } + + inline once:: + once () + : called_ (false) + { + } + + inline void once:: + call (void (*func) ()) + { + win32_lock l (win32_once_cs_); + + if (!called_) + { + called_ = true; + l.unlock (); + func (); + } + } + } +} diff --git a/libodb/odb/details/win32/thread.cxx b/libodb/odb/details/win32/thread.cxx new file mode 100644 index 0000000..46720d4 --- /dev/null +++ b/libodb/odb/details/win32/thread.cxx @@ -0,0 +1,88 @@ +// file : odb/details/win32/thread.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include // _beginthreadex, _endthreadex + +#include +#include +#include + +unsigned int __stdcall +odb_thread_thunk (void* arg) +{ + odb::details::thread::thread_thunk (arg); + _endthreadex (0); + return 0; +} + +namespace odb +{ + namespace details + { + void thread:: + thread_thunk (void* arg) + { + data* d (static_cast (arg)); + d->ret = d->func (d->arg); + d->mutex.lock (); + unsigned char count = --d->count; + d->mutex.unlock (); + + if (count == 0) + delete d; + } + + thread:: + ~thread () + { + if (handle_ != 0) + { + CloseHandle (handle_); + + // Win32 mutex implementation does not throw. + // + data_->mutex.lock (); + unsigned char count = --data_->count; + data_->mutex.unlock (); + + if (count == 0) + delete data_; + } + } + + thread:: + thread (void* (*func) (void*), void* arg) + { + unique_ptr d (new data); + d->func = func; + d->arg = arg; + d->count = 2; // One for the thread and one for us. + + handle_ = (HANDLE)_beginthreadex ( + 0, 0, &odb_thread_thunk, d.get (), 0, 0); + + if (handle_ == 0) + throw win32_exception (); + + data_ = d.release (); + } + + void* thread:: + join () + { + void* r; + + if (WaitForSingleObject (handle_, INFINITE) != 0) + throw win32_exception (); + + r = data_->ret; + + CloseHandle (handle_); + delete data_; + handle_ = 0; + data_ = 0; + return r; + } + } +} diff --git a/libodb/odb/details/win32/thread.hxx b/libodb/odb/details/win32/thread.hxx new file mode 100644 index 0000000..a4e1a15 --- /dev/null +++ b/libodb/odb/details/win32/thread.hxx @@ -0,0 +1,59 @@ +// file : odb/details/win32/thread.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_THREAD_HXX +#define ODB_DETAILS_WIN32_THREAD_HXX + +#include + +#include +#include +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT thread + { + public: + ~thread (); + thread (void* (*thread_func) (void*), void* arg = 0); + + void* + join (); + + private: + thread (const thread&); + thread& operator= (const thread&); + + private: + typedef void* (*thread_func) (void*); + + struct data + { + thread_func func; + void* arg; + void* ret; + + // Thread-safe reference counter. + // + details::mutex mutex; + unsigned char count; + }; + + + public: + static void + thread_thunk (void*); + + private: + HANDLE handle_; + data* data_; + }; + } +} + +#include + +#endif // ODB_DETAILS_WIN32_THREAD_HXX diff --git a/libodb/odb/details/win32/tls-init.hxx b/libodb/odb/details/win32/tls-init.hxx new file mode 100644 index 0000000..0a44a10 --- /dev/null +++ b/libodb/odb/details/win32/tls-init.hxx @@ -0,0 +1,26 @@ +// file : odb/details/win32/tls-init.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_TLS_INIT_HXX +#define ODB_DETAILS_WIN32_TLS_INIT_HXX + +#include + +namespace odb +{ + namespace details + { + void + tls_process_start (); + + void + tls_process_end (bool safe); + + void + tls_thread_end (); + } +} + +#include + +#endif // ODB_DETAILS_WIN32_TLS_INIT_HXX diff --git a/libodb/odb/details/win32/tls.cxx b/libodb/odb/details/win32/tls.cxx new file mode 100644 index 0000000..2edc364 --- /dev/null +++ b/libodb/odb/details/win32/tls.cxx @@ -0,0 +1,245 @@ +// file : odb/details/win32/tls.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include // ERROR_INVALID_INDEX + +#include +#include // std::size_t + +#include +#include +#include +#include + +#ifdef _MSC_VER +# pragma warning (disable:4200) // zero-sized array in struct +#endif + +using namespace std; + +namespace odb +{ + namespace details + { + typedef void (*dtor_func) (void*); + + struct entry + { + void* value; + dtor_func dtor; + }; + + struct thread_data + { + size_t size; + size_t capacity; + entry entries[0]; + }; + + struct process_data + { + size_t size; + size_t capacity; + dtor_func dtors[0]; + }; + + static DWORD index_ = TLS_OUT_OF_INDEXES; + static CRITICAL_SECTION cs_; + static process_data* proc_data_; + + const size_t init_capacity = 4; + + void + tls_process_start () + { + index_ = TlsAlloc (); + + if (index_ == TLS_OUT_OF_INDEXES) + throw win32_exception (); + + InitializeCriticalSection (&cs_); + + process_data* pd ( + static_cast ( + operator new ( + sizeof (process_data) + sizeof (dtor_func) * init_capacity))); + + pd->size = 0; + pd->capacity = init_capacity; + memset (pd->dtors, 0, sizeof (dtor_func) * init_capacity); + + proc_data_ = pd; + } + + void + tls_process_end (bool) + { + operator delete (proc_data_); + DeleteCriticalSection (&cs_); + + if (index_ != TLS_OUT_OF_INDEXES) + { + if (!TlsFree (index_)) + throw win32_exception (); + } + } + + void + tls_thread_end () + { + if (thread_data* d = static_cast (TlsGetValue (index_))) + { + // Call destructors. Implement the pthread semantics in that the + // destructors are called until all the values become 0. + // + for (bool pass (true); pass;) + { + pass = false; + + for (size_t i (0); i < d->size; ++i) + { + if (d->entries[i].dtor != 0 && d->entries[i].value != 0) + { + pass = true; + void* tmp (d->entries[i].value); + d->entries[i].value = 0; + d->entries[i].dtor (tmp); + } + } + } + + operator delete (d); + } + } + + // + // tls_common + // + + std::size_t tls_common:: + _allocate (dtor_func dtor) + { + win32_lock l (cs_); + + size_t n (proc_data_->size); + size_t c (proc_data_->capacity); + + if (n == c) + { + c *= 2; + + // Try to do "atomic" switch-over so that proc_data_ always points + // to memory that can be freed even if this thread is killed in the + // middle. + // + process_data* pd ( + static_cast ( + operator new (sizeof (process_data) + sizeof (dtor_func) * c))); + + memcpy (pd->dtors, proc_data_->dtors, n * sizeof (dtor_func)); + memset (pd->dtors + n, 0, sizeof (dtor_func) * (c - n)); + + pd->size = n; + pd->capacity = c; + + process_data* old (proc_data_); + proc_data_ = pd; + operator delete (old); + } + + proc_data_->dtors[n] = dtor; + return proc_data_->size++; + } + + void* tls_common:: + _get (std::size_t key) + { + if (thread_data* d = static_cast (TlsGetValue (index_))) + { + if (key < d->size) + return d->entries[key].value; + } + + // Check if this key is valid. + // + win32_lock l (cs_); + + if (key < proc_data_->size) + return 0; + + throw win32_exception (ERROR_INVALID_INDEX); + } + + void tls_common:: + _set (std::size_t key, void* value) + { + thread_data* d (static_cast (TlsGetValue (index_))); + + if (d != 0 && key < d->capacity) + { + if (key >= d->size) + { + // Check if this key is valid. If so then we need to copy + // dtors for new slots. + // + win32_lock l (cs_); + + size_t n (proc_data_->size); + + if (key >= n) + throw win32_exception (ERROR_INVALID_INDEX); + + for (size_t i (d->size); i < n; ++i) + d->entries[i].dtor = proc_data_->dtors[i]; + + d->size = n; + } + + d->entries[key].value = value; + } + else + { + // Check if this key is valid. If so then we need to (re)-allocate + // our storage. + // + win32_lock l (cs_); + + size_t n (proc_data_->size); + + if (key >= n) + throw win32_exception (ERROR_INVALID_INDEX); + + size_t c (proc_data_->capacity); + + thread_data* nd ( + static_cast ( + operator new (sizeof (thread_data) + sizeof (entry) * c))); + + size_t on (d == 0 ? 0 : d->size); + + // Copy over the data. + // + if (on != 0) + memcpy (nd->entries, d->entries, sizeof (entry) * on); + + // Zero out the rest. + // + memset (nd->entries + on, 0, sizeof (entry) * (c - on)); + + // Assign destructors to new slots [on, n). + // + for (size_t i (on); i < n; ++i) + nd->entries[i].dtor = proc_data_->dtors[i]; + + nd->size = n; + nd->capacity = c; + + operator delete (d); + TlsSetValue (index_, nd); + + nd->entries[key].value = value; + } + } + } +} diff --git a/libodb/odb/details/win32/tls.hxx b/libodb/odb/details/win32/tls.hxx new file mode 100644 index 0000000..2a75cc8 --- /dev/null +++ b/libodb/odb/details/win32/tls.hxx @@ -0,0 +1,120 @@ +// file : odb/details/win32/tls.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_TLS_HXX +#define ODB_DETAILS_WIN32_TLS_HXX + +#include + +#include // std::size_t + +#include +#include + +namespace odb +{ + namespace details + { + class LIBODB_EXPORT tls_common + { + public: + static std::size_t + _allocate (void (*dtor) (void*)); + + static void* + _get (std::size_t key); + + static void + _set (std::size_t key, void* value); + }; + + template + class tls: protected tls_common + { + public: + tls (); + + T& + get () const; + + void + free (); + + private: + tls (const tls&); + tls& operator= (const tls&); + + private: + static void + key_init (); + + static void + destructor (void*); + + private: + static win32_once_t once_; + static std::size_t key_; + }; + + template + class tls: protected tls_common + { + public: + tls (); + + T* + get () const; + + void + set (T* p); + + private: + tls (const tls&); + tls& operator= (const tls&); + + private: + static void + key_init (); + + private: + static win32_once_t once_; + static std::size_t key_; + }; + + template + inline T& + tls_get (const tls& t) + { + return t.get (); + } + + template + inline void + tls_free (tls& t) + { + t.free (); + } + + template + inline T* + tls_get (const tls& t) + { + return t.get (); + } + + template + inline void + tls_set (tls& t, T1* p1) + { + T* p (p1); + t.set (p); + } + } +} + +#include +#include + +#include + +#endif // ODB_DETAILS_WIN32_TLS_HXX diff --git a/libodb/odb/details/win32/tls.ixx b/libodb/odb/details/win32/tls.ixx new file mode 100644 index 0000000..fbcc3dd --- /dev/null +++ b/libodb/odb/details/win32/tls.ixx @@ -0,0 +1,20 @@ +// file : odb/details/win32/tls.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace details + { + template + inline tls:: + tls () + { + } + + template + inline tls:: + tls () + { + } + } +} diff --git a/libodb/odb/details/win32/tls.txx b/libodb/odb/details/win32/tls.txx new file mode 100644 index 0000000..96bed4c --- /dev/null +++ b/libodb/odb/details/win32/tls.txx @@ -0,0 +1,94 @@ +// file : odb/details/win32/tls.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +namespace odb +{ + namespace details + { + // tls + // + template + win32_once_t tls::once_= WIN32_ONCE_INIT; + + template + size_t tls::key_; + + template + T& tls:: + get () const + { + win32_once (once_, key_init); + + if (void* v = _get (key_)) + return *static_cast (v); + + unique_ptr p (new T); + _set (key_, p.get ()); + + T& r (*p); + p.release (); + return r; + } + + template + void tls:: + free () + { + win32_once (once_, key_init); + + if (void* v = _get (key_)) + { + _set (key_, 0); + delete static_cast (v); + } + } + + template + void tls:: + key_init () + { + key_ = _allocate (destructor); + } + + template + void tls:: + destructor (void* v) + { + delete static_cast (v); + } + + // tls + // + template + win32_once_t tls::once_ = WIN32_ONCE_INIT; + + template + size_t tls::key_; + + template + T* tls:: + get () const + { + win32_once (once_, key_init); + return static_cast (_get (key_)); + } + + template + void tls:: + set (T* p) + { + win32_once (once_, key_init); + _set (key_, p); + } + + template + void tls:: + key_init () + { + key_ = _allocate (0); + } + } +} diff --git a/libodb/odb/details/win32/windows.hxx b/libodb/odb/details/win32/windows.hxx new file mode 100644 index 0000000..9ff4cb4 --- /dev/null +++ b/libodb/odb/details/win32/windows.hxx @@ -0,0 +1,33 @@ +// file : odb/details/win32/windows.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WIN32_WINDOWS_HXX +#define ODB_DETAILS_WIN32_WINDOWS_HXX + +#include + +// Try to include so that it doesn't mess other things up. +// +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# ifndef NOMINMAX // No min and max macros. +# define NOMINMAX +# include +# undef NOMINMAX +# else +# include +# endif +# undef WIN32_LEAN_AND_MEAN +#else +# ifndef NOMINMAX +# define NOMINMAX +# include +# undef NOMINMAX +# else +# include +# endif +#endif + +#include + +#endif // ODB_DETAILS_WIN32_WINDOWS_HXX diff --git a/libodb/odb/details/wrapper-p.hxx b/libodb/odb/details/wrapper-p.hxx new file mode 100644 index 0000000..8f72b5d --- /dev/null +++ b/libodb/odb/details/wrapper-p.hxx @@ -0,0 +1,38 @@ +// file : odb/details/wrapper-p.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_DETAILS_WRAPPER_P_HXX +#define ODB_DETAILS_WRAPPER_P_HXX + +#include + +#include + +#include + +namespace odb +{ + namespace details + { + // GCC doesn't like these to be inside wrapper_p. + // + template + meta::no + wrapper_p_test (...); + + template + meta::yes + wrapper_p_test (typename wrapper_traits::wrapped_type*); + + template + struct wrapper_p + { + static const bool r = + sizeof (wrapper_p_test (0)) == sizeof (meta::yes); + }; + } +} + +#include + +#endif // ODB_DETAILS_WRAPPER_P_HXX diff --git a/libodb/odb/exception.hxx b/libodb/odb/exception.hxx new file mode 100644 index 0000000..39daf92 --- /dev/null +++ b/libodb/odb/exception.hxx @@ -0,0 +1,36 @@ +// file : odb/exception.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_EXCEPTION_HXX +#define ODB_EXCEPTION_HXX + +#include + +#include + +#include // odb::core + +#include // ODB_NOTHROW_NOEXCEPT +#include +#include + +namespace odb +{ + struct LIBODB_EXPORT exception: std::exception, details::shared_base + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT = 0; + + virtual exception* + clone () const = 0; + }; + + namespace common + { + using odb::exception; + } +} + +#include + +#endif // ODB_EXCEPTION_HXX diff --git a/libodb/odb/exceptions.cxx b/libodb/odb/exceptions.cxx new file mode 100644 index 0000000..bb13b6c --- /dev/null +++ b/libodb/odb/exceptions.cxx @@ -0,0 +1,430 @@ +// file : odb/exceptions.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include // std::strlen +#include +#include + +#include + +using namespace std; + +namespace odb +{ + const char* null_pointer:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "NULL pointer"; + } + + null_pointer* null_pointer:: + clone () const + { + return new null_pointer (*this); + } + + const char* already_in_transaction:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "transaction already in progress in this thread"; + } + + already_in_transaction* already_in_transaction:: + clone () const + { + return new already_in_transaction (*this); + } + + const char* not_in_transaction:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "operation can only be performed in transaction"; + } + + not_in_transaction* not_in_transaction:: + clone () const + { + return new not_in_transaction (*this); + } + + const char* transaction_already_finalized:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "transaction already committed or rolled back"; + } + + transaction_already_finalized* transaction_already_finalized:: + clone () const + { + return new transaction_already_finalized (*this); + } + + const char* already_in_session:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "session already in effect in this thread"; + } + + already_in_session* already_in_session:: + clone () const + { + return new already_in_session (*this); + } + + const char* not_in_session:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "session not in effect in this thread"; + } + + not_in_session* not_in_session:: + clone () const + { + return new not_in_session (*this); + } + + const char* session_required:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "session required to load this object relationship"; + } + + session_required* session_required:: + clone () const + { + return new session_required (*this); + } + + const char* deadlock:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "transaction aborted due to deadlock"; + } + + deadlock* deadlock:: + clone () const + { + return new deadlock (*this); + } + + const char* connection_lost:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "connection to database lost"; + } + + connection_lost* connection_lost:: + clone () const + { + return new connection_lost (*this); + } + + const char* timeout:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "database operation timeout"; + } + + timeout* timeout:: + clone () const + { + return new timeout (*this); + } + + const char* object_not_persistent:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "object not persistent"; + } + + object_not_persistent* object_not_persistent:: + clone () const + { + return new object_not_persistent (*this); + } + + const char* object_already_persistent:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "object already persistent"; + } + + object_already_persistent* object_already_persistent:: + clone () const + { + return new object_already_persistent (*this); + } + + const char* object_changed:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "object changed concurrently"; + } + + object_changed* object_changed:: + clone () const + { + return new object_changed (*this); + } + + const char* result_not_cached:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "query result is not cached"; + } + + result_not_cached* result_not_cached:: + clone () const + { + return new result_not_cached (*this); + } + + const char* abstract_class:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "database operation on instance of abstract class"; + } + + abstract_class* abstract_class:: + clone () const + { + return new abstract_class (*this); + } + + const char* no_type_info:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "no type information"; + } + + no_type_info* no_type_info:: + clone () const + { + return new no_type_info (*this); + } + + prepared_already_cached:: + prepared_already_cached (const char* name) + : name_ (name) + { + what_ = "prepared query '"; + what_ += name; + what_ += "' is already cached"; + } + + prepared_already_cached:: + ~prepared_already_cached () ODB_NOTHROW_NOEXCEPT + { + } + + const char* prepared_already_cached:: + what () const ODB_NOTHROW_NOEXCEPT + { + return what_.c_str (); + } + + prepared_already_cached* prepared_already_cached:: + clone () const + { + return new prepared_already_cached (*this); + } + + prepared_type_mismatch:: + prepared_type_mismatch (const char* name) + : name_ (name) + { + what_ = "type mismatch while looking up prepared query '"; + what_ += name; + what_ += "'"; + } + + prepared_type_mismatch:: + ~prepared_type_mismatch () ODB_NOTHROW_NOEXCEPT + { + } + + const char* prepared_type_mismatch:: + what () const ODB_NOTHROW_NOEXCEPT + { + return what_.c_str (); + } + + prepared_type_mismatch* prepared_type_mismatch:: + clone () const + { + return new prepared_type_mismatch (*this); + } + + unknown_schema:: + unknown_schema (const string& name) + : name_ (name) + { + what_ = "unknown database schema '"; + what_ += name; + what_ += "'"; + } + + unknown_schema:: + ~unknown_schema () ODB_NOTHROW_NOEXCEPT + { + } + + const char* unknown_schema:: + what () const ODB_NOTHROW_NOEXCEPT + { + return what_.c_str (); + } + + unknown_schema* unknown_schema:: + clone () const + { + return new unknown_schema (*this); + } + + unknown_schema_version:: + unknown_schema_version (schema_version v) + : version_ (v) + { + ostringstream os; + os << v; + what_ = "unknown database schema version "; + what_ += os.str (); + } + + unknown_schema_version:: + ~unknown_schema_version () ODB_NOTHROW_NOEXCEPT + { + } + + const char* unknown_schema_version:: + what () const ODB_NOTHROW_NOEXCEPT + { + return what_.c_str (); + } + + unknown_schema_version* unknown_schema_version:: + clone () const + { + return new unknown_schema_version (*this); + } + + const char* section_not_loaded:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "section is not loaded"; + } + + section_not_loaded* section_not_loaded:: + clone () const + { + return new section_not_loaded (*this); + } + + const char* section_not_in_object:: + what () const ODB_NOTHROW_NOEXCEPT + { + return "section instance is not part of an object (section was copied?)"; + } + + section_not_in_object* section_not_in_object:: + clone () const + { + return new section_not_in_object (*this); + } + + // multiple_exceptions + // + multiple_exceptions:: + ~multiple_exceptions () ODB_NOTHROW_NOEXCEPT {} + + void multiple_exceptions:: + insert (size_t p, bool maybe, const odb::exception& e, bool fatal) + { + details::shared_ptr pe; + + if (common_exception_ti_ != typeid (e)) + pe.reset (e.clone ()); + else + { + if (common_exception_ == 0) + common_exception_.reset (e.clone ()); + + pe = common_exception_; + } + + set_.insert (value_type (delta_ + p, maybe, pe)); + fatal_ = fatal_ || fatal; + } + + const multiple_exceptions::value_type* multiple_exceptions:: + lookup (size_t p) const + { + p += delta_; // Called while populating multiple_exceptions. + + iterator i (set_.find (value_type (p))); + return i == set_.end () ? 0 : &*i; + } + + void multiple_exceptions:: + prepare () + { + current_ = 0; + delta_ = 0; + common_exception_.reset (); + + ostringstream os; + os << "multiple exceptions, " + << attempted_ << " element" << (attempted_ != 1 ? "s" : "") << + " attempted, " + << failed () << " failed" + << (fatal_ ? ", fatal" : "") << ":"; + + for (iterator i (begin ()); i != end ();) + { + size_t p (i->position ()); + const odb::exception& e (i->exception ()); + + os << '\n'; + + if (!i->maybe ()) + { + os << '[' << p << ']'; + ++i; + } + else + { + // In this case we will normally have a large number of maybe + // failures in a row (usually the whole batch). So let's try + // to represent them all as a single range. + // + size_t n (0); + for (++i; i != end () && i->maybe (); ++i) + { + assert (&e == &i->exception ()); // The same common exception. + n++; + } + + if (n == 0) + os << '[' << p << ']'; + else + os << '[' << p << '-' << (p + n) << "] (some)"; + } + + os << ' ' << e.what (); + } + + what_ = os.str (); + } + + const char* multiple_exceptions:: + what () const ODB_NOTHROW_NOEXCEPT + { + return what_.c_str (); + } + + multiple_exceptions* multiple_exceptions:: + clone () const + { + return new multiple_exceptions (*this); + } +} diff --git a/libodb/odb/exceptions.hxx b/libodb/odb/exceptions.hxx new file mode 100644 index 0000000..d283010 --- /dev/null +++ b/libodb/odb/exceptions.hxx @@ -0,0 +1,523 @@ +// file : odb/exceptions.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_EXCEPTIONS_HXX +#define ODB_EXCEPTIONS_HXX + +#include + +#include +#include +#include // std::size_t +#include + +#include // schema_version, odb::core +#include + +#include // ODB_NOTHROW_NOEXCEPT +#include +#include + +namespace odb +{ + struct LIBODB_EXPORT null_pointer: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual null_pointer* + clone () const; + }; + + // Transaction exceptions. + // + struct LIBODB_EXPORT already_in_transaction: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual already_in_transaction* + clone () const; + }; + + struct LIBODB_EXPORT not_in_transaction: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual not_in_transaction* + clone () const; + }; + + struct LIBODB_EXPORT transaction_already_finalized: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual transaction_already_finalized* + clone () const; + }; + + // Session exceptions. + // + struct LIBODB_EXPORT already_in_session: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual already_in_session* + clone () const; + }; + + struct LIBODB_EXPORT not_in_session: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual not_in_session* + clone () const; + }; + + struct LIBODB_EXPORT session_required: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual session_required* + clone () const; + }; + + // Database operations exceptions. + // + struct LIBODB_EXPORT recoverable: odb::exception + { + // Abstract. + }; + + struct LIBODB_EXPORT connection_lost: recoverable + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual connection_lost* + clone () const; + }; + + struct LIBODB_EXPORT timeout: recoverable + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual timeout* + clone () const; + }; + + struct LIBODB_EXPORT deadlock: recoverable + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual deadlock* + clone () const; + }; + + struct LIBODB_EXPORT object_not_persistent: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual object_not_persistent* + clone () const; + }; + + struct LIBODB_EXPORT object_already_persistent: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual object_already_persistent* + clone () const; + }; + + struct LIBODB_EXPORT object_changed: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual object_changed* + clone () const; + }; + + struct LIBODB_EXPORT result_not_cached: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual result_not_cached* + clone () const; + }; + + struct LIBODB_EXPORT database_exception: odb::exception + { + // Abstract. + }; + + // Polymorphism support exceptions. + // + struct LIBODB_EXPORT abstract_class: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual abstract_class* + clone () const; + }; + + struct LIBODB_EXPORT no_type_info: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual no_type_info* + clone () const; + }; + + // Prepared query support exceptions. + // + struct LIBODB_EXPORT prepared_already_cached: odb::exception + { + prepared_already_cached (const char* name); + ~prepared_already_cached () ODB_NOTHROW_NOEXCEPT; + + const char* + name () const + { + return name_; + } + + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual prepared_already_cached* + clone () const; + + private: + const char* name_; + std::string what_; + }; + + struct LIBODB_EXPORT prepared_type_mismatch: odb::exception + { + prepared_type_mismatch (const char* name); + ~prepared_type_mismatch () ODB_NOTHROW_NOEXCEPT; + + const char* + name () const {return name_;} + + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual prepared_type_mismatch* + clone () const; + + private: + const char* name_; + std::string what_; + }; + + // Schema catalog exceptions. + // + struct LIBODB_EXPORT unknown_schema: odb::exception + { + unknown_schema (const std::string& name); + ~unknown_schema () ODB_NOTHROW_NOEXCEPT; + + const std::string& + name () const {return name_;} + + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual unknown_schema* + clone () const; + + private: + std::string name_; + std::string what_; + }; + + struct LIBODB_EXPORT unknown_schema_version: odb::exception + { + unknown_schema_version (schema_version); + ~unknown_schema_version () ODB_NOTHROW_NOEXCEPT; + + schema_version + version () const {return version_;} + + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual unknown_schema_version* + clone () const; + + private: + schema_version version_; + std::string what_; + }; + + // Section exceptions. + // + struct LIBODB_EXPORT section_not_loaded: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual section_not_loaded* + clone () const; + }; + + struct LIBODB_EXPORT section_not_in_object: odb::exception + { + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual section_not_in_object* + clone () const; + }; + + // Bulk operation exceptions. + // + struct LIBODB_EXPORT multiple_exceptions: odb::exception + { + struct value_type + { + std::size_t + position () const {return p_;} + + // If true, then this means that some positions in the batch have + // triggered the exception but it is not possible, due to the + // limitations of the underlying database API, to discern exactly + // which ones. As a result, all the positions in the batch are + // marked as "maybe failed". + // + bool + maybe () const {return m_;} + + const odb::exception& + exception () const {return *e_;} + + // Implementation details. + // + public: + value_type (std::size_t p, + bool maybe, + details::shared_ptr e) + : m_ (maybe), p_ (p), e_ (e) {} + + value_type (std::size_t p): p_ (p) {} // "Key" for set lookup. + + private: + bool m_; + std::size_t p_; + details::shared_ptr e_; + }; + + struct comparator_type + { + bool + operator() (const value_type& x, const value_type& y) const + { + return x.position () < y.position (); + } + }; + + typedef std::set set_type; + + // Iteration. + // + public: + typedef set_type::const_iterator iterator; + typedef set_type::const_iterator const_iterator; // For pedantic types. + + iterator + begin () const {return set_.begin ();} + + iterator + end () const {return set_.end ();} + + // Lookup. + // + public: + // Return NULL if the element at this position has no exception. Note + // that the returned value is value_type* and not odb::exception* in + // order to provide access to maybe(); see value_type::maybe() for + // details. + // + const value_type* + operator[] (std::size_t p) const + { + return set_.empty () ? 0 : lookup (p); + } + + // Severity, failed and attempt counts. + // + public: + // Return the number of elements for which the operation has been + // attempted. + // + std::size_t + attempted () const {return attempted_;} + + // Return the number of positions for which the operation has failed. + // Note that this count includes the maybe failed positions. + // + std::size_t + failed () const {return set_.size ();} + + // If fatal() returns true, then (some of) the exceptions were fatal. + // In this case, even for elements that were processed but did not + // cause the exception, no attempts were made to complete the bulk + // operation and the transaction must be aborted. + // + // If fatal() returns false, then the operation on the elements that + // don't have an exception has succeeded. The application can try to + // correct the errors and re-attempt the operation on the elements + // that did cause an exception. In either case, the transaction can + // be committed. + // + bool + fatal () const {return fatal_;} + + // Normally you shouldn't need to do this explicitly but you can + // "upgrade" an exception to fatal, for example, for specific + // database error codes. + // + void + fatal (bool f) {fatal_ = fatal_ || f;} + + // odb::exception interface. + // + public: + virtual const char* + what () const ODB_NOTHROW_NOEXCEPT; + + virtual multiple_exceptions* + clone () const; + + // Direct set access. + // + public: + const set_type& + set () const {return set_;} + + // Implementation details. + // + public: + ~multiple_exceptions () ODB_NOTHROW_NOEXCEPT; + + // All instances of the common exception must be equal since we are + // going to create and share just one. + // + multiple_exceptions (const std::type_info& common_exception_ti) + : common_exception_ti_ (common_exception_ti), + fatal_ (false), + delta_ (0), + current_ (0) {} + + // Set the attempted count as (delta + n). + // + void + attempted (std::size_t n) {attempted_ = delta_ + n;} + + // Increment the position of the current batch. Also resets the + // current position in the batch. + // + void + delta (std::size_t d) {delta_ += d; current_ = 0;} + + // Current position in the batch. + // + std::size_t + current () const {return current_;} + + void + current (std::size_t c) {current_ = c;} + + void + insert (std::size_t p, + bool maybe, + const odb::exception& e, + bool fatal = false); + + void + insert (std::size_t p, const odb::exception& e, bool fatal = false) + { + insert (p, false, e, fatal); + } + + void + insert (const odb::exception& e, bool fatal = false) + { + insert (current_, e, fatal); + } + + bool + empty () const {return set_.empty ();} + + void + prepare (); + + private: + const value_type* + lookup (std::size_t p) const; + + private: + const std::type_info& common_exception_ti_; + details::shared_ptr common_exception_; + + set_type set_; + bool fatal_; + std::size_t attempted_; + std::size_t delta_; // Position of the batch. + std::size_t current_; // Position in the batch. + std::string what_; + }; + + namespace common + { + using odb::null_pointer; + + using odb::already_in_transaction; + using odb::not_in_transaction; + using odb::transaction_already_finalized; + + using odb::already_in_session; + using odb::not_in_session; + using odb::session_required; + + using odb::recoverable; + using odb::deadlock; + using odb::connection_lost; + using odb::timeout; + using odb::object_not_persistent; + using odb::object_already_persistent; + using odb::object_changed; + using odb::result_not_cached; + using odb::database_exception; + + using odb::abstract_class; + using odb::no_type_info; + + using odb::unknown_schema; + using odb::unknown_schema_version; + + using odb::section_not_loaded; + using odb::section_not_in_object; + + using odb::multiple_exceptions; + } +} + +#include + +#endif // ODB_EXCEPTIONS_HXX diff --git a/libodb/odb/forward.hxx b/libodb/odb/forward.hxx new file mode 100644 index 0000000..6f1176d --- /dev/null +++ b/libodb/odb/forward.hxx @@ -0,0 +1,178 @@ +// file : odb/forward.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_FORWARD_HXX +#define ODB_FORWARD_HXX + +#include + +#include // std::size_t + +#include +#include + +namespace odb +{ + // Common and core namespaces. The idea is that you can use the + // using directive to get database-independent (common) names or + // all core names (core). + // + namespace common {} + + namespace core + { + using namespace common; + } + + // + // + typedef unsigned long long schema_version; + struct schema_version_migration; + + class database; + class connection; + typedef details::shared_ptr connection_ptr; + class transaction; + class statement; + class session; + class section; + template class result; + + namespace common + { + using odb::schema_version; + using odb::schema_version_migration; + using odb::session; + using odb::section; + using odb::result; + } + + namespace core + { + using odb::database; + using odb::connection; + using odb::connection_ptr; + using odb::transaction; + using odb::statement; + } + + // Tracing. + // + class tracer; // Not in core. + extern LIBODB_EXPORT tracer& stderr_tracer; + extern LIBODB_EXPORT tracer& stderr_full_tracer; + + namespace common + { + using odb::stderr_tracer; + } + + // Implementation details. + // + + // Keep real databases first since their enumerators are used as array + // indexes. + // + enum database_id + { + id_mysql, + id_sqlite, + id_pgsql, + id_oracle, + id_mssql, + id_common + }; + + // Number of real databases (i.e., excluding default) in the database_id + // enum. + // + const std::size_t database_count = id_common; + + // Traits. + // + class access + { + public: + template + class object_traits; + + template + class object_traits_impl; + + template + class object_factory; + + template + class view_traits; + + template + class view_traits_impl; + + template + class view_factory; + + template + class pointer_factory; + + template + class composite_value_traits; + + template + class container_traits; + }; + + template + struct object_traits; + + template + struct object_traits_impl; + + template + struct view_traits; + + template + struct view_traits_impl; + + // Cache traits. + // + template struct no_id_pointer_cache_traits; + template struct no_op_pointer_cache_traits; + template struct pointer_cache_traits; + template struct no_id_reference_cache_traits; + template struct no_op_reference_cache_traits; + template struct reference_cache_traits; + + // + // + class query_base; + + template + struct query_column; + + // + // + class result_impl; + class prepared_query_impl; + + // + // + struct multiple_exceptions; + + // Polymorphism support. + // + template + struct polymorphic_map; + + namespace details + { + template <> + struct counter_type + { + typedef shared_base counter; + }; + } +} + +#include + +#endif // ODB_FORWARD_HXX diff --git a/libodb/odb/function-table.hxx b/libodb/odb/function-table.hxx new file mode 100644 index 0000000..b1a5a94 --- /dev/null +++ b/libodb/odb/function-table.hxx @@ -0,0 +1,50 @@ +// file : odb/function-table.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_FUNCTION_TABLE_HXX +#define ODB_FUNCTION_TABLE_HXX + +#include + +#include + +namespace odb +{ + template + struct object_function_table_entry + { + typedef access::object_traits_impl common_traits; + + object_function_table_entry ( + const typename common_traits::function_table_type* t) + { + common_traits::function_table[DB] = t; + } + + ~object_function_table_entry () + { + common_traits::function_table[DB] = 0; + } + }; + + template + struct view_function_table_entry + { + typedef access::view_traits_impl common_traits; + + view_function_table_entry ( + const typename common_traits::function_table_type* t) + { + common_traits::function_table[DB] = t; + } + + ~view_function_table_entry () + { + common_traits::function_table[DB] = 0; + } + }; +} + +#include + +#endif // ODB_FUNCTION_TABLE_HXX diff --git a/libodb/odb/lazy-pointer-traits.hxx b/libodb/odb/lazy-pointer-traits.hxx new file mode 100644 index 0000000..2a6c8eb --- /dev/null +++ b/libodb/odb/lazy-pointer-traits.hxx @@ -0,0 +1,141 @@ +// file : odb/lazy-pointer-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_LAZY_POINTER_TRAITS_HXX +#define ODB_LAZY_POINTER_TRAITS_HXX + +#include + +#include +#include +#include // ODB_CXX11 + +namespace odb +{ + template + class pointer_traits< lazy_ptr > + { + public: + static const pointer_kind kind = pk_raw; + static const bool lazy = true; + + typedef T element_type; + typedef lazy_ptr pointer_type; + typedef element_type* eager_pointer_type; + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + template + static typename object_traits::id_type + object_id (const pointer_type& p) + { + return p.template object_id (); + } + }; + +#ifndef ODB_CXX11 + template + class pointer_traits< lazy_auto_ptr > + { + public: + static const pointer_kind kind = pk_unique; + static const bool lazy = true; + + typedef T element_type; + typedef lazy_auto_ptr pointer_type; + typedef std::auto_ptr eager_pointer_type; + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + template + static typename object_traits::id_type + object_id (const pointer_type& p) + { + return p.template object_id (); + } + }; +#endif + +#ifdef ODB_CXX11 + template + class pointer_traits> + { + public: + static const pointer_kind kind = pk_unique; + static const bool lazy = true; + + typedef T element_type; + typedef lazy_unique_ptr pointer_type; + typedef std::unique_ptr eager_pointer_type; + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + template + static typename object_traits::id_type + object_id (const pointer_type& p) + { + return p.template object_id (); + } + }; + + template + class pointer_traits> + { + public: + static const pointer_kind kind = pk_shared; + static const bool lazy = true; + + typedef T element_type; + typedef lazy_shared_ptr pointer_type; + typedef std::shared_ptr eager_pointer_type; + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + template + static typename object_traits::id_type + object_id (const pointer_type& p) + { + return p.template object_id (); + } + }; + + template + class pointer_traits> + { + public: + static const pointer_kind kind = pk_weak; + static const bool lazy = true; + + typedef T element_type; + typedef lazy_weak_ptr pointer_type; + typedef lazy_shared_ptr strong_pointer_type; + typedef std::weak_ptr eager_pointer_type; + + static strong_pointer_type + lock (const pointer_type& p) + { + return p.lock (); + } + }; +#endif // ODB_CXX11 +} + +#include + +#endif // ODB_LAZY_POINTER_TRAITS_HXX diff --git a/libodb/odb/lazy-ptr-impl.hxx b/libodb/odb/lazy-ptr-impl.hxx new file mode 100644 index 0000000..89fe798 --- /dev/null +++ b/libodb/odb/lazy-ptr-impl.hxx @@ -0,0 +1,188 @@ +// file : odb/lazy-ptr-impl.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_LAZY_PTR_IMPL_HXX +#define ODB_LAZY_PTR_IMPL_HXX + +#include + +#include // std::move + +#include // odb::database +#include + +#include // ODB_CXX11 + +namespace odb +{ + struct lazy_ptr_impl_ref + { + void* id_; + database* db_; + void* loader_; + void (*free_) (void*); + void* (*copy_) (const void*); + }; + + class lazy_ptr_base + { + public: + typedef odb::database database_type; + + ~lazy_ptr_base (); + lazy_ptr_base (); + lazy_ptr_base (const lazy_ptr_base&); + lazy_ptr_base (const lazy_ptr_impl_ref&); + + lazy_ptr_base& + operator= (const lazy_ptr_base&); + + lazy_ptr_base& + operator= (const lazy_ptr_impl_ref&); + + // C++11 support. + // + public: +#ifdef ODB_CXX11 + lazy_ptr_base (lazy_ptr_base&&) noexcept; + + lazy_ptr_base& + operator= (lazy_ptr_base&&) noexcept; +#endif + + public: + // Reset both the id and database. + // + void + reset (); + + // Reset the id. + // + void + reset_id (); + + void + swap (lazy_ptr_base&); + + database_type* + database () const; + + typedef void* lazy_ptr_base::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return db_ != 0 ? &lazy_ptr_base::id_ : 0; + } + + operator lazy_ptr_impl_ref (); + + protected: + typedef void (*free_func) (void*); + typedef void* (*copy_func) (const void*); + + // Makes a copy of id. + // + void + reset_ (database_type*, + void* loader, + const void* id, + free_func, copy_func); + + template + static void + free (void*); + + template + static void* + copy (const void*); + + template + static typename object_traits::pointer_type + loader (database_type&, const typename object_traits::id_type&); + + protected: + void* id_; + database_type* db_; + void* loader_; + + private: + free_func free_; + copy_func copy_; + }; + + template + class lazy_ptr_impl: public lazy_ptr_base + { + public: + lazy_ptr_impl (); + + template + lazy_ptr_impl (DB&, const ID&); + + lazy_ptr_impl (const lazy_ptr_impl&); + + template + lazy_ptr_impl (const lazy_ptr_impl&); + + lazy_ptr_impl (const lazy_ptr_impl_ref&); + + lazy_ptr_impl& + operator= (const lazy_ptr_impl&); + + template + lazy_ptr_impl& + operator= (const lazy_ptr_impl&); + + lazy_ptr_impl& + operator= (const lazy_ptr_impl_ref&); + + // C++11 support. + // + public: +#ifdef ODB_CXX11 + lazy_ptr_impl (lazy_ptr_impl&&) noexcept; + + template + lazy_ptr_impl (lazy_ptr_impl&&); + + lazy_ptr_impl& + operator= (lazy_ptr_impl&&) noexcept; + + template + lazy_ptr_impl& + operator= (lazy_ptr_impl&&); +#endif + + public: + using lazy_ptr_base::reset; + using lazy_ptr_base::reset_id; + + template + void + reset (DB&, const ID&); + + // Reset the id and set the database to the new value. + // + template + void + reset_db (DB&); + + template + void + reset_id (const ID&); + + template + typename object_traits::pointer_type + load (bool reset_id); + + template + typename object_traits::id_type + object_id () const; + }; +} + +#include +#include + +#include + +#endif // ODB_LAZY_PTR_IMPL_HXX diff --git a/libodb/odb/lazy-ptr-impl.ixx b/libodb/odb/lazy-ptr-impl.ixx new file mode 100644 index 0000000..9ab0471 --- /dev/null +++ b/libodb/odb/lazy-ptr-impl.ixx @@ -0,0 +1,397 @@ +// file : odb/lazy-ptr-impl.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // lazy_ptr_base + // + + inline lazy_ptr_base:: + lazy_ptr_base () + : id_ (0), db_ (0), loader_ (0), free_ (0), copy_ (0) + { + } + + inline lazy_ptr_base:: + lazy_ptr_base (const lazy_ptr_base& r) + : id_ (0), db_ (r.db_), loader_ (r.loader_), + free_ (r.free_), copy_ (r.copy_) + { + if (r.id_) + id_ = copy_ (r.id_); + } + + inline lazy_ptr_base:: + lazy_ptr_base (const lazy_ptr_impl_ref& r) + : id_ (r.id_), db_ (r.db_), loader_ (r.loader_), + free_ (r.free_), copy_ (r.copy_) + { + } + +#ifdef ODB_CXX11 + inline lazy_ptr_base:: + lazy_ptr_base (lazy_ptr_base&& r) noexcept + : id_ (r.id_), db_ (r.db_), loader_ (r.loader_), + free_ (r.free_), copy_ (r.copy_) + { + r.id_ = 0; + } +#endif + + inline void lazy_ptr_base:: + reset_id () + { + if (id_) + free_ (id_); + + id_ = 0; + } + + inline void lazy_ptr_base:: + reset_ (database_type* db, + void* loader, + const void* id, + free_func free, + copy_func copy) + { + void* idc (id ? copy (id) : 0); + + if (id_) + free_ (id_); + + free_ = free; + copy_ = copy; + + id_ = idc; + db_ = db; + loader_ = loader; + } + + inline void lazy_ptr_base:: + reset () + { + reset_id (); + db_ = 0; + loader_ = 0; + } + +#ifdef ODB_CXX11 + inline lazy_ptr_base& lazy_ptr_base:: + operator= (lazy_ptr_base&& r) noexcept + { + if (id_ != r.id_) + { + reset_id (); + id_ = r.id_; + free_ = r.free_; + copy_ = r.copy_; + + r.id_ = 0; + } + + db_ = r.db_; + loader_ = r.loader_; + return *this; + } +#endif + + inline lazy_ptr_base& lazy_ptr_base:: + operator= (const lazy_ptr_base& r) + { + if (id_ != r.id_) + reset_ (r.db_, r.loader_, r.id_, r.free_, r.copy_); + else + { + db_ = r.db_; + loader_ = r.loader_; + } + + return *this; + } + + inline lazy_ptr_base& lazy_ptr_base:: + operator= (const lazy_ptr_impl_ref& r) + { + if (id_ != r.id_) + { + reset_id (); + id_ = r.id_; + free_ = r.free_; + copy_ = r.copy_; + } + + db_ = r.db_; + loader_ = r.loader_; + return *this; + } + + inline lazy_ptr_base:: + ~lazy_ptr_base () + { + if (id_) + free_ (id_); + } + + inline void lazy_ptr_base:: + swap (lazy_ptr_base& r) + { + void* id (id_); + database_type* db (db_); + void* l (loader_); + free_func f (free_); + copy_func c (copy_); + + id_ = r.id_; + db_ = r.db_; + loader_ = r.loader_; + free_ = r.free_; + copy_ = r.copy_; + + r.id_ = id; + r.db_ = db; + r.loader_ = l; + r.free_ = f; + r.copy_ = c; + } + + inline lazy_ptr_base::database_type* lazy_ptr_base:: + database () const + { + return db_; + } + + inline lazy_ptr_base:: + operator lazy_ptr_impl_ref () + { + lazy_ptr_impl_ref r; + r.id_ = id_; + r.db_ = db_; + r.loader_ = loader_; + r.free_ = free_; + r.copy_ = copy_; + id_ = 0; + db_ = 0; + loader_ = 0; + return r; + } + + // + // lazy_ptr_impl + // + + template + inline lazy_ptr_impl:: + lazy_ptr_impl () + { + } + + template + template + inline lazy_ptr_impl:: + lazy_ptr_impl (DB& db, const ID& id) + { + typedef typename object_traits::id_type id_type; + typedef typename object_traits::pointer_type pointer_type; + typedef pointer_type (*loader_type) (database_type&, const id_type&); + + // Make sure that ID and T's object id types are the same + // (or implicit-convertible). If you get a compile error + // pointing here, then you most likely used a wrong object + // id argument in the constructor call. + // + const id_type& r (id); + + // Compiler error pointing here? Perhaps db is not an + // odb::::database instance? + // + database_type& bdb (db); + + // For some reason GCC needs this statically-typed pointer in + // order to instantiate the functions. + // + loader_type ldr (&loader); + + reset_ (&bdb, + reinterpret_cast (ldr), + &r, + &free, + ©); + } + + template + inline lazy_ptr_impl:: + lazy_ptr_impl (const lazy_ptr_impl& r) + : lazy_ptr_base (r) + { + } + + template + template + inline lazy_ptr_impl:: + lazy_ptr_impl (const lazy_ptr_impl& r) + : lazy_ptr_base (r) + { + } + + template + inline lazy_ptr_impl:: + lazy_ptr_impl (const lazy_ptr_impl_ref& r) + : lazy_ptr_base (r) + { + } + + template + inline lazy_ptr_impl& lazy_ptr_impl:: + operator= (const lazy_ptr_impl& r) + { + lazy_ptr_base& b (*this); + b = r; + return *this; + } + + template + template + inline lazy_ptr_impl& lazy_ptr_impl:: + operator= (const lazy_ptr_impl& r) + { + lazy_ptr_base& b (*this); + b = r; + return *this; + } + + template + inline lazy_ptr_impl& lazy_ptr_impl:: + operator= (const lazy_ptr_impl_ref& r) + { + lazy_ptr_base& b (*this); + b = r; + return *this; + } + +#ifdef ODB_CXX11 + template + inline lazy_ptr_impl:: + lazy_ptr_impl (lazy_ptr_impl&& r) noexcept + : lazy_ptr_base (std::move (r)) + { + } + + template + template + inline lazy_ptr_impl:: + lazy_ptr_impl (lazy_ptr_impl&& r) + : lazy_ptr_base (std::move (r)) + { + } + + template + inline lazy_ptr_impl& lazy_ptr_impl:: + operator= (lazy_ptr_impl&& r) noexcept + { + lazy_ptr_base& b (*this); + b = std::move (r); + return *this; + } + + template + template + inline lazy_ptr_impl& lazy_ptr_impl:: + operator= (lazy_ptr_impl&& r) + { + lazy_ptr_base& b (*this); + b = std::move (r); + return *this; + } +#endif + + template + template + inline void lazy_ptr_impl:: + reset (DB& db, const ID& id) + { + typedef typename object_traits::id_type id_type; + typedef typename object_traits::pointer_type pointer_type; + typedef pointer_type (*loader_type) (database_type&, const id_type&); + + // Make sure that ID and T's object id types are the same + // (or implicit-convertible). If you get a compile error + // pointing here, then you most likely used a wrong object + // id argument in the constructor call. + // + const id_type& r (id); + + // Compiler error pointing here? Perhaps db is not an + // odb::::database instance? + // + database_type& bdb (db); + + // For some reason GCC needs this statically-typed pointer in + // order to instantiate the functions. + // + loader_type ldr (&loader); + + reset_ (&bdb, + reinterpret_cast (ldr), + &r, + &free, + ©); + } + + template + template + inline void lazy_ptr_impl:: + reset_db (DB& db) + { + typedef typename object_traits::id_type id_type; + typedef typename object_traits::pointer_type pointer_type; + typedef pointer_type (*loader_type) (database_type&, const id_type&); + + reset_id (); + + // Compiler error pointing here? Perhaps db is not an + // odb::::database instance? + // + db_ = &db; + + // For some reason GCC needs this statically-typed pointer in + // order to instantiate the functions. + // + loader_type ldr (&loader); + loader_ = reinterpret_cast (ldr); + } + + template + template + inline void lazy_ptr_impl:: + reset_id (const ID& id) + { + typedef typename object_traits::id_type id_type; + + // Make sure that ID and T's object id types are the same + // (or implicit-convertible). If you get a compile error + // pointing here, then you most likely used a wrong object + // id argument in the constructor call. + // + const id_type& r (id); + + reset_ (db_, loader_, &r, &free, ©); + } + + template + template + inline typename object_traits::id_type lazy_ptr_impl:: + object_id () const + { + typedef typename object_traits::id_type id_type; + const id_type& id (*static_cast (id_)); + + // Make sure that O' and T's object id types are the same + // (or implicit-convertible). If you get a compile error + // pointing here, then you most likely used a wrong type + // as a template argument in the object_id() call. + // + const typename object_traits::id_type& r (id); + return r; + } +} diff --git a/libodb/odb/lazy-ptr-impl.txx b/libodb/odb/lazy-ptr-impl.txx new file mode 100644 index 0000000..7aea9c3 --- /dev/null +++ b/libodb/odb/lazy-ptr-impl.txx @@ -0,0 +1,60 @@ +// file : odb/lazy-ptr-impl.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // lazy_ptr_base + // + + template + void lazy_ptr_base:: + free (void* p) + { + delete static_cast (p); + } + + template + void* lazy_ptr_base:: + copy (const void* p) + { + return new T (*static_cast (p)); + } + + template + typename object_traits::pointer_type lazy_ptr_base:: + loader (database_type& db, const typename object_traits::id_type& id) + { + // Compiler error pointing here? Perhaps you did not include + // ? + // + return static_cast (db).template load< + typename object_traits::object_type> (id); + } + + // + // lazy_ptr_impl + // + + template + template + inline typename object_traits::pointer_type lazy_ptr_impl:: + load (bool reset) + { + typedef typename object_traits::id_type id_type; + typedef typename object_traits::pointer_type pointer_type; + typedef pointer_type (*loader_type) (database_type&, const id_type&); + + loader_type loader (reinterpret_cast (loader_)); + const id_type& id (*static_cast (id_)); + pointer_type p (loader (*db_, id)); + + if (reset) + reset_id (); + + // If you get a compile error pointing here, then you most likely + // used a wrong type as a template argument in the load() call. + // + return p; + } +} diff --git a/libodb/odb/lazy-ptr.hxx b/libodb/odb/lazy-ptr.hxx new file mode 100644 index 0000000..ab31dfc --- /dev/null +++ b/libodb/odb/lazy-ptr.hxx @@ -0,0 +1,681 @@ +// file : odb/lazy-ptr.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_LAZY_PTR_HXX +#define ODB_LAZY_PTR_HXX + +#include + +#include // std::auto_ptr, std::shared_ptr/weak_ptr +#include // std::move + +#include // odb::core, odb::database +#include +#include +#include // ODB_CXX11 + +namespace odb +{ + // Raw pointer lazy version. + // + template + class lazy_ptr + { + // Pointer interface. + // + public: + typedef T element_type; + + lazy_ptr (); + template lazy_ptr (Y*); + + lazy_ptr (const lazy_ptr&); + template lazy_ptr (const lazy_ptr&); + + lazy_ptr& operator= (const lazy_ptr&); + template lazy_ptr& operator= (Y*); + template lazy_ptr& operator= (const lazy_ptr&); + + void swap (lazy_ptr&); + void reset (); + template void reset (Y*); + + T& operator* () const; + T* operator-> () const; + T* get () const; + + typedef T* lazy_ptr::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return (p_ || i_) ? &lazy_ptr::p_ : 0; + } + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + // NULL loaded() + // + // true true NULL pointer to transient object + // false true valid pointer to persistent object + // true false unloaded pointer to persistent object + // false false valid pointer to transient object + // + bool loaded () const; + + T* load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + T* get_eager () const; + + template lazy_ptr (DB&, const ID&); + template lazy_ptr (DB&, Y*); + + template void reset (DB&, const ID&); + template void reset (DB&, Y*); + +#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT + template +#else + template +#endif + typename object_traits::id_type object_id () const; + + database_type& database () const; + + // Helpers. + // + public: + template bool equal (const lazy_ptr&) const; + + private: + template friend class lazy_ptr; + + mutable T* p_; + mutable lazy_ptr_impl i_; + }; + + // operator< and operator<< are not provided. + // + template + bool operator== (const lazy_ptr&, const lazy_ptr&); + + template + bool operator!= (const lazy_ptr&, const lazy_ptr&); + + template void swap (lazy_ptr&, lazy_ptr&); + + // std::auto_ptr lazy version. + // +#ifndef ODB_CXX11 + template + struct lazy_auto_ptr_ref + { + explicit lazy_auto_ptr_ref (T*, const lazy_ptr_impl_ref&); + + T* p_; + lazy_ptr_impl_ref i_; + }; + + template + class lazy_auto_ptr + { + // Standard auto_ptr interface. + // + public: + typedef T element_type; + + explicit lazy_auto_ptr (T* = 0); + lazy_auto_ptr (lazy_auto_ptr&); + template lazy_auto_ptr (lazy_auto_ptr&); + + lazy_auto_ptr& operator= (lazy_auto_ptr&); + template lazy_auto_ptr& operator= (lazy_auto_ptr&); + + T& operator* () const; + T* operator-> () const; + T* get () const; + T* release (); + void reset (T* = 0); + + lazy_auto_ptr (const lazy_auto_ptr_ref&); + lazy_auto_ptr& operator= (const lazy_auto_ptr_ref&); + template operator lazy_auto_ptr_ref (); + template operator lazy_auto_ptr (); + + // Extension: conversion to bool. + // + public: + typedef std::auto_ptr lazy_auto_ptr::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return (p_.get () != 0 || i_) ? &lazy_auto_ptr::p_ : 0; + } + + // Initialization/assignment from auto_ptr. + // + public: + template lazy_auto_ptr (std::auto_ptr&); + lazy_auto_ptr (std::auto_ptr_ref); + + template lazy_auto_ptr& operator= (std::auto_ptr&); + lazy_auto_ptr& operator= (std::auto_ptr_ref); + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + // NULL loaded() + // + // true true NULL pointer to transient object + // false true valid pointer to persistent object + // true false unloaded pointer to persistent object + // false false valid pointer to transient object + // + bool loaded () const; + + std::auto_ptr& load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + std::auto_ptr& get_eager () const; + + template lazy_auto_ptr (DB&, const ID&); + template lazy_auto_ptr (DB&, T*); + template lazy_auto_ptr (DB&, std::auto_ptr&); + + template void reset (DB&, const ID&); + template void reset (DB&, T*); + template void reset (DB&, std::auto_ptr&); + + template + typename object_traits::id_type object_id () const; + + database_type& database () const; + + private: + template friend class lazy_auto_ptr; + + // Note that it is possible to have a situation where p_ is NULL, + // i_.id is NULL and i_.db is not NULL. This will happen if the + // auto_ptr reference returned by load() is transferred to another + // pointer or reset. + // + mutable std::auto_ptr p_; + mutable lazy_ptr_impl i_; + }; +#endif + +#ifdef ODB_CXX11 + + // C++11 std::unique_ptr lazy version. + // + template > + class lazy_unique_ptr + { + // Standard lazy_unique_ptr interface. + // + public: + typedef T* pointer; // For now assume it is T*. + typedef T element_type; + typedef D deleter_type; + + /*constexpr*/ lazy_unique_ptr () /*noexcept*/; +#ifdef ODB_CXX11_NULLPTR + /*constexpr*/ lazy_unique_ptr (std::nullptr_t) /*noexcept*/; +#endif + explicit lazy_unique_ptr (pointer) /*noexcept*/; + + // For now assume D is non-reference. + // + lazy_unique_ptr (pointer, const deleter_type&) /*noexcept*/; + lazy_unique_ptr (pointer, deleter_type&&) /*noexcept*/; + + lazy_unique_ptr (lazy_unique_ptr&&) noexcept; + template lazy_unique_ptr (lazy_unique_ptr&&) /*noexcept*/; + //template lazy_unique_ptr (std::auto_ptr&&) /*noexcept*/; + +#ifdef ODB_CXX11_NULLPTR + lazy_unique_ptr& operator= (std::nullptr_t) /*noexcept*/; +#endif + lazy_unique_ptr& operator= (lazy_unique_ptr&&) noexcept; + template lazy_unique_ptr& operator= (lazy_unique_ptr&&) /*noexcept*/; + + T& operator* () const; + pointer operator-> () const /*noexcept*/; + pointer get () const /*noexcept*/; +#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR + explicit operator bool() const /*noexcept*/; +#else + typedef std::unique_ptr lazy_unique_ptr::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return (p_ || i_) ? &lazy_unique_ptr::p_ : 0; + } +#endif + + pointer release () /*noexcept*/; + void reset (pointer = pointer ()) /*noexcept*/; + void swap (lazy_unique_ptr&) /*noexcept*/; + + deleter_type& get_deleter () /*noexcept*/; + const deleter_type& get_deleter () const /*noexcept*/; + +#ifdef ODB_CXX11_DELETED_FUNCTION + lazy_unique_ptr (const lazy_unique_ptr&) = delete; + lazy_unique_ptr& operator= (const lazy_unique_ptr&) = delete; +#else + private: + lazy_unique_ptr (const lazy_unique_ptr&); + lazy_unique_ptr& operator= (const lazy_unique_ptr&); +#endif + + // Initialization/assignment from unique_ptr. + // + public: + template lazy_unique_ptr (std::unique_ptr&&) /*noexcept*/; + template lazy_unique_ptr& operator= (std::unique_ptr&&) /*noexcept*/; + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + // NULL loaded() + // + // true true NULL pointer to transient object + // false true valid pointer to persistent object + // true false unloaded pointer to persistent object + // false false valid pointer to transient object + // + bool loaded () const; + + std::unique_ptr& load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + std::unique_ptr& get_eager () const; + + template lazy_unique_ptr (DB&, const ID&); + template lazy_unique_ptr (DB&, pointer); + template lazy_unique_ptr (DB&, pointer, const deleter_type&); + template lazy_unique_ptr (DB&, pointer, deleter_type&&); + template lazy_unique_ptr (DB&, std::unique_ptr&&); + //template lazy_unique_ptr (DB&, std::auto_ptr&&); + + template void reset (DB&, const ID&); + template void reset (DB&, pointer); + template void reset (DB&, std::unique_ptr&&); + //template void reset (DB&, std::auto_ptr&&); + +#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT + template +#else + template +#endif + typename object_traits::id_type object_id () const; + + database_type& database () const; + + // Helpers. + // + public: + template bool equal (const lazy_unique_ptr&) const; + + private: + template friend class lazy_unique_ptr; + + // Note that it is possible to have a situation where p_ is NULL, + // i_.id is NULL and i_.db is not NULL. This will happen if the + // unique_ptr reference returned by load() is transferred to + // another pointer or reset. + // + mutable std::unique_ptr p_; + mutable lazy_ptr_impl i_; + }; + + template void swap (lazy_unique_ptr&, lazy_unique_ptr&) /*noexcept*/; + + // operator< and operator<< are not provided. + // + template + bool operator== (const lazy_unique_ptr&, const lazy_unique_ptr&); + + template + bool operator!= (const lazy_unique_ptr&, const lazy_unique_ptr&); + +#ifdef ODB_CXX11_NULLPTR + template + bool operator== (const lazy_unique_ptr&, std::nullptr_t) /*noexcept*/; + + template + bool operator== (std::nullptr_t, const lazy_unique_ptr&) /*noexcept*/; + + template + bool operator!= (const lazy_unique_ptr&, std::nullptr_t) /*noexcept*/; + + template + bool operator!= (std::nullptr_t, const lazy_unique_ptr&) /*noexcept*/; +#endif + + // C++11 std::shared_ptr lazy version. + // + template + class lazy_weak_ptr; + + template + class lazy_shared_ptr + { + // The standard shared_ptr interface. + // + public: + typedef T element_type; + + /*constexpr*/ lazy_shared_ptr () /*noexcept*/; +#ifdef ODB_CXX11_NULLPTR + /*constexpr*/ lazy_shared_ptr (std::nullptr_t) /*noexcept*/; +#endif + template explicit lazy_shared_ptr (Y*); + template lazy_shared_ptr (Y*, D); + template lazy_shared_ptr (Y*, D, A); +#ifdef ODB_CXX11_NULLPTR + template lazy_shared_ptr (std::nullptr_t, D); + template lazy_shared_ptr (std::nullptr_t, D, A); +#endif + template lazy_shared_ptr (const lazy_shared_ptr&, T*) /*noexcept*/; + + lazy_shared_ptr (const lazy_shared_ptr&) /*noexcept*/; + template lazy_shared_ptr (const lazy_shared_ptr&) /*noexcept*/; + lazy_shared_ptr (lazy_shared_ptr&&) noexcept; + template lazy_shared_ptr (lazy_shared_ptr&&) /*noexcept*/; + template explicit lazy_shared_ptr (const lazy_weak_ptr&); + //template explicit lazy_shared_ptr (std::auto_ptr&&); + template lazy_shared_ptr (std::unique_ptr&&); + + ~lazy_shared_ptr (); + + lazy_shared_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; + template lazy_shared_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; + lazy_shared_ptr& operator= (lazy_shared_ptr&&) noexcept; + template lazy_shared_ptr& operator= (lazy_shared_ptr&&) /*noexcept*/; + //template lazy_shared_ptr& operator= (std::auto_ptr&&); + template lazy_shared_ptr& operator= (std::unique_ptr&&); + + void swap (lazy_shared_ptr&) /*noexcept*/; + void reset () /*noexcept*/; + template void reset (Y*); + template void reset (Y*, D); + template void reset (Y*, D, A); + + T* get () const /*noexcept*/; + T& operator* () const /*noexcept*/; + T* operator-> () const /*noexcept*/; + long use_count () const /*noexcept*/; + bool unique () const /*noexcept*/; +#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR + explicit operator bool () const /*noexcept*/; +#else + typedef std::shared_ptr lazy_shared_ptr::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return (p_ || i_) ? &lazy_shared_ptr::p_ : 0; + } +#endif + + // owner_before () is not provded. + + // Initialization/assignment from shared_ptr and weak_ptr. + // + public: + template lazy_shared_ptr (const std::shared_ptr&); + template lazy_shared_ptr (std::shared_ptr&&); + template explicit lazy_shared_ptr (const std::weak_ptr&); + + template lazy_shared_ptr& operator= (const std::shared_ptr&); + template lazy_shared_ptr& operator= (std::shared_ptr&&); + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + // NULL loaded() + // + // true true NULL pointer to transient object + // false true valid pointer to persistent object + // true false unloaded pointer to persistent object + // false false valid pointer to transient object + // + bool loaded () const; + + std::shared_ptr load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + std::shared_ptr get_eager () const; + + template lazy_shared_ptr (DB&, const ID&); + template lazy_shared_ptr (DB&, Y*); + template lazy_shared_ptr (DB&, Y*, D); + template lazy_shared_ptr (DB&, Y*, D, A); + //template lazy_shared_ptr (DB&, std::auto_ptr&&); + template lazy_shared_ptr (DB&, const std::shared_ptr&); + template lazy_shared_ptr (DB&, std::shared_ptr&&); + template lazy_shared_ptr (DB&, const std::weak_ptr&); + + template void reset (DB&, const ID&); + template void reset (DB&, Y*); + template void reset (DB&, Y*, D); + template void reset (DB&, Y*, D, A); + //template void reset (DB&, std::auto_ptr&&); + template void reset (DB&, const std::shared_ptr&); + template void reset (DB&, std::shared_ptr&&); + +#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT + template +#else + template +#endif + typename object_traits::id_type object_id () const; + + database_type& database () const; + + // Helpers. + // + public: + template bool equal (const lazy_shared_ptr&) const; + + private: + template friend class lazy_shared_ptr; + template friend class lazy_weak_ptr; + + // For lazy_weak_ptr::lock(). + // + lazy_shared_ptr (std::shared_ptr&& p, const lazy_ptr_impl& i) + : p_ (std::move (p)), i_ (i) {} + + private: + mutable std::shared_ptr p_; + mutable lazy_ptr_impl i_; + }; + + template void swap (lazy_shared_ptr&, lazy_shared_ptr&) /*noexcept*/; + + template + D* get_deleter (const lazy_shared_ptr&) /*noexcept*/; + + // operator< and operator<< are not provided. + // + template + bool operator== (const lazy_shared_ptr&, const lazy_shared_ptr&) /*noexcept*/; + + template + bool operator!= (const lazy_shared_ptr&, const lazy_shared_ptr&) /*noexcept*/; + +#ifdef ODB_CXX11_NULLPTR + template + bool operator== (const lazy_shared_ptr&, std::nullptr_t) /*noexcept*/; + + template + bool operator== (std::nullptr_t, const lazy_shared_ptr&) /*noexcept*/; + + template + bool operator!= (const lazy_shared_ptr&, std::nullptr_t) /*noexcept*/; + + template + bool operator!= (std::nullptr_t, const lazy_shared_ptr&) /*noexcept*/; +#endif + + // C++11 std::weak_ptr lazy version. + // + template + class lazy_weak_ptr + { + // The standard weak_ptr interface. + // + public: + typedef T element_type; + + /*constexpr*/ lazy_weak_ptr () /*noexcept*/; + template lazy_weak_ptr (const lazy_shared_ptr&) /*noexcept*/; + lazy_weak_ptr (const lazy_weak_ptr&) /*noexcept*/; + template lazy_weak_ptr (const lazy_weak_ptr&) /*noexcept*/; + + ~lazy_weak_ptr (); + + lazy_weak_ptr& operator= (const lazy_weak_ptr&) /*noexcept*/; + template lazy_weak_ptr& operator= (const lazy_weak_ptr&) /*noexcept*/; + template lazy_weak_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; + + void swap (lazy_weak_ptr&) /*noexcept*/; + void reset () /*noexcept*/; + + long use_count () const /*noexcept*/; + bool expired () const /*noexcept*/; + + lazy_shared_ptr lock () const /*noexcept*/; + + // owner_before () is not provded. + + // Initialization/assignment from shared_ptr and weak_ptr. + // + public: + template lazy_weak_ptr (const std::weak_ptr&); + template lazy_weak_ptr (const std::shared_ptr&); + + template lazy_weak_ptr& operator= (const std::weak_ptr&); + template lazy_weak_ptr& operator= (const std::shared_ptr&); + + // 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 transient object + // + bool loaded () const; + + // Performs both lock and load. + // + std::shared_ptr load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + std::weak_ptr get_eager () const; + + template lazy_weak_ptr (DB&, const ID&); + template lazy_weak_ptr (DB&, const std::shared_ptr&); + template lazy_weak_ptr (DB&, const std::weak_ptr&); + + template void reset (DB&, const ID&); + template void reset (DB&, const std::shared_ptr&); + template void reset (DB&, const std::weak_ptr&); + + // The object_id() function can only be called when the object is + // persistent, or: expired() XOR loaded() (can use != for XOR). + // +#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT + template +#else + template +#endif + typename object_traits::id_type object_id () const; + + database_type& database () const; + + private: + template friend class lazy_shared_ptr; + template friend class lazy_weak_ptr; + + mutable std::weak_ptr p_; + mutable lazy_ptr_impl i_; + }; + + // operator< is not provided. + // + template void swap (lazy_weak_ptr&, lazy_weak_ptr&); + +#endif // ODB_CXX11 + + namespace common + { + using odb::lazy_ptr; + +#ifndef ODB_CXX11 + using odb::lazy_auto_ptr; +#endif + +#ifdef ODB_CXX11 + using odb::lazy_unique_ptr; + using odb::lazy_shared_ptr; + using odb::lazy_weak_ptr; +#endif + } +} + +#include +#include + +#include + +#include + +#endif // ODB_LAZY_PTR_HXX diff --git a/libodb/odb/lazy-ptr.ixx b/libodb/odb/lazy-ptr.ixx new file mode 100644 index 0000000..a2d72f5 --- /dev/null +++ b/libodb/odb/lazy-ptr.ixx @@ -0,0 +1,1681 @@ +// file : odb/lazy-ptr.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // lazy_ptr + // + + template + inline lazy_ptr:: + lazy_ptr (): p_ (0) {} + + template + template + inline lazy_ptr:: + lazy_ptr (Y* p): p_ (p) {} + + template + inline lazy_ptr:: + lazy_ptr (const lazy_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + template + inline lazy_ptr:: + lazy_ptr (const lazy_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_ptr& lazy_ptr:: + operator= (const lazy_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_ptr& lazy_ptr:: + operator= (Y* r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + template + inline lazy_ptr& lazy_ptr:: + operator= (const lazy_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + inline void lazy_ptr:: + swap (lazy_ptr& b) + { + T* p (p_); + p_ = b.p_; + b.p_ = p; + i_.swap (b.i_); + } + + template + inline void lazy_ptr:: + reset () + { + p_ = 0; + i_.reset (); + } + + template + template + inline void lazy_ptr:: + reset (Y* p) + { + p_ = p; + i_.reset (); + } + + template + inline T& lazy_ptr:: + operator* () const + { + return *p_; + } + + template + inline T* lazy_ptr:: + operator-> () const + { + return p_; + } + + template + inline T* lazy_ptr:: + get () const + { + return p_; + } + + template + inline bool lazy_ptr:: + loaded () const + { + bool i (i_); + return (p_ == 0) != i; // !p_ XOR i + } + + template + inline T* lazy_ptr:: + load () const + { + if (p_ == 0 && i_) + p_ = i_.template load (true); // Reset id. + + return p_; + } + + template + inline void lazy_ptr:: + unload () const + { + typedef typename object_traits::object_type object_type; + + if (p_) + { + if (i_.database () != 0) + i_.reset_id (object_traits::id (*p_)); + + p_ = 0; + } + } + + template + inline T* lazy_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_ptr:: + lazy_ptr (DB& db, const ID& id): p_ (0), i_ (db, id) {} + + template + template + inline lazy_ptr:: + lazy_ptr (DB& db, Y* r) + : p_ (r) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline void lazy_ptr:: + reset (DB& db, const ID& id) + { + p_ = 0; + i_.reset (db, id); + } + + template + template + inline void lazy_ptr:: + reset (DB& db, Y* r) + { + p_ = r; + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline typename object_traits::id_type lazy_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + return p_ + ? object_traits::id (*p_) + : i_.template object_id (); + } + + template + inline typename lazy_ptr::database_type& lazy_ptr:: + database () const + { + return *i_.database (); + } + + template + inline bool + operator== (const lazy_ptr& a, const lazy_ptr& b) + { + return a.equal (b); + } + + template + inline bool + operator!= (const lazy_ptr& a, const lazy_ptr& b) + { + return !a.equal (b); + } + + template + inline void + swap (lazy_ptr& a, lazy_ptr& b) + { + a.swap (b); + } + + // + // lazy_auto_ptr_ref + // +#ifndef ODB_CXX11 + + template + inline lazy_auto_ptr_ref:: + lazy_auto_ptr_ref (T* p, const lazy_ptr_impl_ref& i): p_ (p), i_ (i) {} + + // + // lazy_auto_ptr + // + + template + inline lazy_auto_ptr:: + lazy_auto_ptr (T* p): p_ (p) {} + + template + inline lazy_auto_ptr:: + lazy_auto_ptr (lazy_auto_ptr& r) + : p_ (r.p_), i_ (static_cast (r.i_)) + { + } + + template + template + inline lazy_auto_ptr:: + lazy_auto_ptr (lazy_auto_ptr& r) + : p_ (r.p_), i_ (static_cast (r.i_)) + { + } + + template + inline lazy_auto_ptr& lazy_auto_ptr:: + operator= (lazy_auto_ptr& r) + { + p_ = r.p_; + i_ = static_cast (r.i_); + return *this; + } + + template + template + inline lazy_auto_ptr& lazy_auto_ptr:: + operator= (lazy_auto_ptr& r) + { + p_ = r.p_; + i_ = static_cast (r.i_); + return *this; + } + + template + inline T& lazy_auto_ptr:: + operator* () const + { + return *p_; + } + + template + inline T* lazy_auto_ptr:: + operator-> () const + { + return p_.operator-> (); + } + + template + inline T* lazy_auto_ptr:: + get () const + { + return p_.get (); + } + + template + inline T* lazy_auto_ptr:: + release () + { + i_.reset (); + return p_.release (); + } + + template + inline void lazy_auto_ptr:: + reset (T* p) + { + i_.reset (); + p_.reset (p); + } + + template + inline lazy_auto_ptr:: + lazy_auto_ptr (const lazy_auto_ptr_ref& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_auto_ptr& lazy_auto_ptr:: + operator= (const lazy_auto_ptr_ref& r) + { + if (p_.get () != r.p_) + p_.reset (r.p_); + + i_ = r.i_; + return *this; + } + + template + template + inline lazy_auto_ptr:: + operator lazy_auto_ptr_ref () + { + return lazy_auto_ptr_ref (p_.release (), i_); + } + + template + template + inline lazy_auto_ptr:: + operator lazy_auto_ptr () + { + return lazy_auto_ptr (*this); + } + + template + template + inline lazy_auto_ptr:: + lazy_auto_ptr (std::auto_ptr& r): p_ (r) {} + + template + inline lazy_auto_ptr:: + lazy_auto_ptr (std::auto_ptr_ref r): p_ (r) {} + + template + template + inline lazy_auto_ptr& lazy_auto_ptr:: + operator= (std::auto_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + inline lazy_auto_ptr& lazy_auto_ptr:: + operator= (std::auto_ptr_ref r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + inline bool lazy_auto_ptr:: + loaded () const + { + bool i (i_); + return (p_.get () == 0) != i; // XOR + } + + template + inline std::auto_ptr& lazy_auto_ptr:: + load () const + { + if (p_.get () == 0 && i_) + { + std::auto_ptr tmp (i_.template load (true)); // Reset id. + p_ = tmp; + } + + return p_; + } + + template + inline void lazy_auto_ptr:: + unload () const + { + typedef typename object_traits::object_type object_type; + + if (p_.get () != 0) + { + if (i_.database () != 0) + i_.reset_id (object_traits::id (*p_)); + + p_.reset (); + } + } + + template + inline std::auto_ptr& lazy_auto_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_auto_ptr:: + lazy_auto_ptr (DB& db, const ID& id): i_ (db, id) {} + + template + template + inline lazy_auto_ptr:: + lazy_auto_ptr (DB& db, T* p) + : p_ (p) + { + if (p) + i_.reset_db (db); + } + + template + template + inline lazy_auto_ptr:: + lazy_auto_ptr (DB& db, std::auto_ptr& p) + : p_ (p) + { + if (p_.get () != 0) + i_.reset_db (db); + } + + template + template + inline void lazy_auto_ptr:: + reset (DB& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template + template + inline void lazy_auto_ptr:: + reset (DB& db, T* p) + { + p_.reset (p); + + if (p) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_auto_ptr:: + reset (DB& db, std::auto_ptr& p) + { + p_ = p; + + if (p_.get () != 0) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline typename object_traits::id_type lazy_auto_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + return p_.get () != 0 + ? object_traits::id (*p_) + : i_.template object_id (); + } + + template + inline typename lazy_auto_ptr::database_type& lazy_auto_ptr:: + database () const + { + return *i_.database (); + } +#endif + +#ifdef ODB_CXX11 + + // + // lazy_unique_ptr + // + + template + lazy_unique_ptr:: + lazy_unique_ptr () {} + +#ifdef ODB_CXX11_NULLPTR + template + lazy_unique_ptr:: + lazy_unique_ptr (std::nullptr_t) {} +#endif + + template + lazy_unique_ptr:: + lazy_unique_ptr (pointer p): p_ (p) {} + + template + lazy_unique_ptr:: + lazy_unique_ptr (pointer p, const deleter_type& d): p_ (p, d) {} + + template + lazy_unique_ptr:: + lazy_unique_ptr (pointer p, deleter_type&& d): p_ (p, std::move (d)) {} + + template + lazy_unique_ptr:: + lazy_unique_ptr (lazy_unique_ptr&& r) noexcept + : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} + + template + template + lazy_unique_ptr:: + lazy_unique_ptr (lazy_unique_ptr&& r) + : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} + + // template + // template + // lazy_unique_ptr:: + // lazy_unique_ptr (std::auto_ptr&& r): p_ (std::move (r)) {} + +#ifdef ODB_CXX11_NULLPTR + template + lazy_unique_ptr& lazy_unique_ptr:: + operator= (std::nullptr_t) + { + reset (); + return *this; + } +#endif + + template + lazy_unique_ptr& lazy_unique_ptr:: + operator= (lazy_unique_ptr&& r) noexcept + { + p_ = std::move (r.p_); + i_ = std::move (r.i_); + return *this; + } + + template + template + lazy_unique_ptr& lazy_unique_ptr:: + operator= (lazy_unique_ptr&& r) + { + p_ = std::move (r.p_); + i_ = std::move (r.i_); + return *this; + } + + template + T& lazy_unique_ptr:: + operator* () const + { + return *p_; + } + + template + typename lazy_unique_ptr::pointer lazy_unique_ptr:: + operator-> () const + { + return p_.operator-> (); + } + + template + typename lazy_unique_ptr::pointer lazy_unique_ptr:: + get () const + { + return p_.get (); + } + +#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR + template + lazy_unique_ptr:: + operator bool() const + { + return p_ || i_; + } +#endif + + template + typename lazy_unique_ptr::pointer lazy_unique_ptr:: + release () + { + i_.reset (); + return p_.release (); + } + + template + void lazy_unique_ptr:: + reset (pointer p) + { + p_.reset (p); + i_.reset (); + } + + template + void lazy_unique_ptr:: + swap (lazy_unique_ptr& b) + { + p_.swap (b.p_); + i_.swap (b.i_); + } + + template + typename lazy_unique_ptr::deleter_type& lazy_unique_ptr:: + get_deleter () + { + return p_.get_deleter (); + } + + template + const typename lazy_unique_ptr::deleter_type& lazy_unique_ptr:: + get_deleter () const + { + return p_.get_deleter (); + } + + template + template + inline lazy_unique_ptr:: + lazy_unique_ptr (std::unique_ptr&& p) + : p_ (std::move (p)) + { + } + + template + template + inline lazy_unique_ptr& lazy_unique_ptr:: + operator= (std::unique_ptr&& p) + { + p_ = std::move (p); + i_.reset (); + return *this; + } + + template + inline bool lazy_unique_ptr:: + loaded () const + { + bool i (i_); + return !p_ != i; // !p_ XOR i_ + } + + template + inline std::unique_ptr& lazy_unique_ptr:: + load () const + { + if (!p_ && i_) + p_ = std::unique_ptr (i_.template load (true)); // Reset id. + + return p_; + } + + template + inline void lazy_unique_ptr:: + unload () const + { + typedef typename object_traits::object_type object_type; + + if (p_) + { + if (i_.database () != 0) + i_.reset_id (object_traits::id (*p_)); + + p_.reset (); + } + } + + template + inline std::unique_ptr& lazy_unique_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_unique_ptr:: + lazy_unique_ptr (DB& db, const ID& id): i_ (db, id) {} + + template + template + inline lazy_unique_ptr:: + lazy_unique_ptr (DB& db, T* p) + : p_ (p) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_unique_ptr:: + lazy_unique_ptr (DB& db, T* p, const deleter_type& d) + : p_ (p, d) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_unique_ptr:: + lazy_unique_ptr (DB& db, T* p, deleter_type&& d) + : p_ (p, std::move (d)) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_unique_ptr:: + lazy_unique_ptr (DB& db, std::unique_ptr&& p) + : p_ (std::move (p)) + { + if (p_) + i_.reset_db (db); + } + + // template + // template + // inline lazy_unique_ptr:: + // lazy_unique_ptr (DB& db, std::auto_ptr&& p) + // : p_ (std::move (p)) + // { + // if (p_) + // i_.reset_db (db); + // } + + template + template + inline void lazy_unique_ptr:: + reset (DB& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template + template + inline void lazy_unique_ptr:: + reset (DB& db, T* p) + { + p_.reset (p); + + if (p) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_unique_ptr:: + reset (DB& db, std::unique_ptr&& p) + { + p_ = std::move (p); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + // template + // template + // inline void lazy_unique_ptr:: + // reset (DB& db, std::auto_ptr&& p) + // { + // p_ = std::unique_ptr (std::move (p)); + // + // if (p_) + // i_.reset_db (db); + // else + // i_.reset (); + // } + + template + template + inline typename object_traits::id_type lazy_unique_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + return p_ + ? object_traits::id (*p_) + : i_.template object_id (); + } + + template + inline typename lazy_unique_ptr::database_type& lazy_unique_ptr:: + database () const + { + return *i_.database (); + } + + template + inline void + swap (lazy_unique_ptr& a, lazy_unique_ptr& b) + { + a.swap (b); + } + + template + inline bool + operator== (const lazy_unique_ptr& a, + const lazy_unique_ptr& b) + { + return a.equal (b); + } + + template + inline bool + operator!= (const lazy_unique_ptr& a, + const lazy_unique_ptr& b) + { + return !a.equal (b); + } + +#ifdef ODB_CXX11_NULLPTR + template + inline bool + operator== (const lazy_unique_ptr& a, std::nullptr_t) + { + return !a; + } + + template + inline bool + operator== (std::nullptr_t, const lazy_unique_ptr& b) + { + return !b; + } + + template + inline bool + operator!= (const lazy_unique_ptr& a, std::nullptr_t) + { + return bool (a); // Explicit to-bool conversion. + } + + template + inline bool + operator!= (std::nullptr_t, const lazy_unique_ptr& b) + { + return bool (b); // Explicit to-bool conversion. + } +#endif + + // + // lazy_shared_ptr + // + + template + inline lazy_shared_ptr:: + lazy_shared_ptr () {} + +#ifdef ODB_CXX11_NULLPTR + template + inline lazy_shared_ptr:: + lazy_shared_ptr (std::nullptr_t) {} +#endif + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (Y* p): p_ (p) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (Y* p, D d): p_ (p, d) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (Y* p, D d, A a): p_ (p, d, a) {} + +#ifdef ODB_CXX11_NULLPTR + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (std::nullptr_t p, D d): p_ (p, d) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (std::nullptr_t p, D d, A a): p_ (p, d, a) {} +#endif + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_shared_ptr& r, T* p) + // r.p_ has to be loaded + : p_ (r.p_, p) {} + + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_shared_ptr:: + lazy_shared_ptr (lazy_shared_ptr&& r) noexcept + : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (lazy_shared_ptr&& r) + : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_weak_ptr& r): i_ (r.i_) + { + // If the pointer has expired but can be re-loaded, then don't throw. + // + p_ = r.lock ().get_eager (); + + if (!p_ && !i_) + throw std::bad_weak_ptr (); + } + + // template + // template + // inline lazy_shared_ptr:: + // lazy_shared_ptr (std::auto_ptr&& r): p_ (std::move (r)) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (std::unique_ptr&& r): p_ (std::move (r)) {} + + template + inline lazy_shared_ptr:: + ~lazy_shared_ptr () {} + + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (lazy_shared_ptr&& r) noexcept + { + p_ = std::move (r.p_); + i_ = std::move (r.i_); + return *this; + } + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (lazy_shared_ptr&& r) + { + p_ = std::move (r.p_); + i_ = std::move (r.i_); + return *this; + } + + // template + // template + // inline lazy_shared_ptr& lazy_shared_ptr:: + // operator= (std::auto_ptr&& r) + // { + // p_ = std::move (r); + // i_.reset (); + // return *this; + // } + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (std::unique_ptr&& r) + { + p_ = std::move (r); + i_.reset (); + return *this; + } + + template + inline void lazy_shared_ptr:: + swap (lazy_shared_ptr& b) + { + p_.swap (b.p_); + i_.swap (b.i_); + } + + template + inline void lazy_shared_ptr:: + reset () + { + p_.reset (); + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (Y* p) + { + p_.reset (p); + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (Y* p, D d) + { + p_.reset (p, d); + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (Y* p, D d, A a) + { + p_.reset (p, d, a); + i_.reset (); + } + + template + inline T& lazy_shared_ptr:: + operator* () const + { + return *p_; + } + + template + inline T* lazy_shared_ptr:: + operator-> () const + { + return p_.operator-> (); + } + + template + inline T* lazy_shared_ptr:: + get () const + { + return p_.get (); + } + + template + inline bool lazy_shared_ptr:: + unique () const + { + return p_.unique (); + } + + template + inline long lazy_shared_ptr:: + use_count () const + { + return p_.use_count (); + } + +#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR + template + inline lazy_shared_ptr:: + operator bool () const + { + return p_ || i_; + } +#endif + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const std::shared_ptr& r): p_ (r) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (std::shared_ptr&& r): p_ (std::move (r)) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const std::weak_ptr& r): p_ (r) {} + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (const std::shared_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (std::shared_ptr&& r) + { + p_ = std::move (r); + i_.reset (); + return *this; + } + + template + inline bool lazy_shared_ptr:: + loaded () const + { + bool i (i_); + return !p_ != i; // !p_ XOR i_ + } + + template + inline std::shared_ptr lazy_shared_ptr:: + load () const + { + if (!p_ && i_) + p_ = i_.template load (true); // Reset id. + + return p_; + } + + template + inline void lazy_shared_ptr:: + unload () const + { + typedef typename object_traits::object_type object_type; + + if (p_) + { + if (i_.database () != 0) + i_.reset_id (object_traits::id (*p_)); + + p_.reset (); + } + } + + template + inline std::shared_ptr lazy_shared_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, const ID& id): i_ (db, id) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, Y* p) + : p_ (p) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, Y* p, D d) + : p_ (p, d) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, Y* p, D d, A a) + : p_ (p, d, a) + { + if (p_) + i_.reset_db (db); + } + + // template + // template + // inline lazy_shared_ptr:: + // lazy_shared_ptr (DB& db, std::auto_ptr&& r) + // : p_ (std::move (r)) + // { + // if (p_) + // i_.reset_db (db); + // } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, const std::shared_ptr& r) + : p_ (r) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, std::shared_ptr&& r) + : p_ (std::move (r)) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, const std::weak_ptr& r) + : p_ (r) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, Y* p) + { + p_.reset (p); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, Y* p, D d) + { + p_.reset (p, d); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, Y* p, D d, A a) + { + p_.reset (p, d, a); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + // template + // template + // inline void lazy_shared_ptr:: + // reset (DB& db, std::auto_ptr&& r) + // { + // p_ = std::move (r); + // + // if (p_) + // i_.reset_db (db); + // else + // i_.reset (); + // } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, const std::shared_ptr& r) + { + p_ = r; + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, std::shared_ptr&& r) + { + p_ = std::move (r); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline typename object_traits::id_type lazy_shared_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + return p_ + ? object_traits::id (*p_) + : i_.template object_id (); + } + + template + inline typename lazy_shared_ptr::database_type& lazy_shared_ptr:: + database () const + { + return *i_.database (); + } + + template + inline bool + operator== (const lazy_shared_ptr& a, const lazy_shared_ptr& b) + { + return a.equal (b); + } + + template + inline bool + operator!= (const lazy_shared_ptr& a, const lazy_shared_ptr& b) + { + return !a.equal (b); + } + +#ifdef ODB_CXX11_NULLPTR + template + inline bool + operator== (const lazy_shared_ptr& p, std::nullptr_t) + { + return !p; + } + + template + inline bool + operator== (std::nullptr_t, const lazy_shared_ptr& p) + { + return !p; + } + + template + inline bool + operator!= (const lazy_shared_ptr& p, std::nullptr_t) + { + return bool (p); // Explicit to-bool conversion. + } + + template + inline bool + operator!= (std::nullptr_t, const lazy_shared_ptr& p) + { + return bool (p); // Explicit to-bool conversion. + } +#endif + + template + inline void + swap (lazy_shared_ptr& a, lazy_shared_ptr& b) + { + a.swap (b); + } + + template + inline D* + get_deleter (const lazy_shared_ptr& p) + { + return std::get_deleter (p.p_); + } + + // + // lazy_weak_ptr + // + + template + inline lazy_weak_ptr:: + lazy_weak_ptr () {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_weak_ptr:: + ~lazy_weak_ptr () {} + + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const lazy_weak_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const lazy_weak_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + inline void lazy_weak_ptr:: + swap (lazy_weak_ptr& r) + { + p_.swap (r.p_); + i_.swap (r.i_); + } + + template + inline void lazy_weak_ptr:: + reset () + { + p_.reset (); + i_.reset (); + } + + template + inline long lazy_weak_ptr:: + use_count () const + { + return p_.use_count (); + } + + template + inline bool lazy_weak_ptr:: + expired () const + { + return p_.expired (); + } + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const std::weak_ptr& r): p_ (r) {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const std::shared_ptr& r): p_ (r) {} + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const std::weak_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const std::shared_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + inline bool lazy_weak_ptr:: + loaded () const + { + bool i (i_); + return expired () != i; // expired () XOR i_ + } + + template + inline lazy_shared_ptr lazy_weak_ptr:: + lock () const + { + return lazy_shared_ptr (p_.lock (), i_); + } + + template + inline std::shared_ptr lazy_weak_ptr:: + load () const + { + std::shared_ptr r (p_.lock ()); + + if (!r && i_) + { + r = i_.template load (false); // Keep id. + p_ = r; + } + + return r; + } + + template + inline void lazy_weak_ptr:: + unload () const + { + // With weak pointer we always keep i_ up to date. + // + p_.reset (); + } + + template + inline std::weak_ptr lazy_weak_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (DB& db, const ID& id): i_ (db, id) {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (DB& db, const std::shared_ptr& r) + : p_ (r) + { + typedef typename object_traits::object_type object_type; + + if (r) + i_.reset (db, object_traits::id (*r)); + } + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (DB& db, const std::weak_ptr& r) + : p_ (r) + { + typedef typename object_traits::object_type object_type; + + std::shared_ptr sp (p_.lock ()); + + if (sp) + i_.reset (db, object_traits::id (*sp)); + } + + template + template + inline void lazy_weak_ptr:: + reset (DB& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template + template + inline void lazy_weak_ptr:: + reset (DB& db, const std::shared_ptr& r) + { + typedef typename object_traits::object_type object_type; + + p_ = r; + + if (r) + i_.reset (db, object_traits::id (*r)); + else + i_.reset (); + } + + template + template + inline void lazy_weak_ptr:: + reset (DB& db, const std::weak_ptr& r) + { + typedef typename object_traits::object_type object_type; + + p_ = r; + std::shared_ptr sp (p_.lock ()); + + if (sp) + i_.reset (db, object_traits::id (*sp)); + else + i_.reset (); + } + + template + template + inline typename object_traits::id_type lazy_weak_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + std::shared_ptr sp (p_.lock ()); + return sp + ? object_traits::id (*sp) + : i_.template object_id (); + } + + template + inline typename lazy_weak_ptr::database_type& lazy_weak_ptr:: + database () const + { + return *i_.database (); + } + + template + inline void + swap (lazy_weak_ptr& a, lazy_weak_ptr& b) + { + a.swap (b); + } + +#endif // ODB_CXX11 + +} diff --git a/libodb/odb/lazy-ptr.txx b/libodb/odb/lazy-ptr.txx new file mode 100644 index 0000000..17a7405 --- /dev/null +++ b/libodb/odb/lazy-ptr.txx @@ -0,0 +1,114 @@ +// file : odb/lazy-ptr.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // lazy_ptr + // + + template + template + bool lazy_ptr:: + equal (const lazy_ptr& r) const + { + bool t1 ((p_ == 0) == loaded ()); + bool t2 ((r.p_ == 0) == r.loaded ()); + + // If both are transient, then compare the underlying pointers. + // + if (t1 && t2) + return p_ == r.p_; + + // If one is transient and the other is persistent, then compare + // the underlying pointers but only if they are non NULL. Note + // that an unloaded persistent object is always unequal to a + // transient object. + // + if (t1 || t2) + return p_ == r.p_ && p_ != 0; + + // If both objects are persistent, then we compare databases and + // object ids. + // + typedef typename object_traits::object_type object_type1; + typedef typename object_traits::object_type object_type2; + + return i_.database () == r.i_.database () && + object_id () == r.template object_id (); + } + +#ifdef ODB_CXX11 + + // + // lazy_unique_ptr + // + + template + template + bool lazy_unique_ptr:: + equal (const lazy_unique_ptr& r) const + { + bool t1 (!p_ == loaded ()); + bool t2 (!r.p_ == r.loaded ()); + + // If both are transient, then compare the underlying pointers. + // + if (t1 && t2) + return p_ == r.p_; + + // If one is transient and the other is persistent, then compare + // the underlying pointers but only if they are non NULL. Note + // that an unloaded persistent object is always unequal to a + // transient object. + // + if (t1 || t2) + return p_ == r.p_ && p_; + + // If both objects are persistent, then we compare databases and + // object ids. + // + typedef typename object_traits::object_type object_type1; + typedef typename object_traits::object_type object_type2; + + return i_.database () == r.i_.database () && + object_id () == r.template object_id (); + } + + // + // lazy_shared_ptr + // + + template + template + bool lazy_shared_ptr:: + equal (const lazy_shared_ptr& r) const + { + bool t1 (!p_ == loaded ()); + bool t2 (!r.p_ == r.loaded ()); + + // If both are transient, then compare the underlying pointers. + // + if (t1 && t2) + return p_ == r.p_; + + // If one is transient and the other is persistent, then compare + // the underlying pointers but only if they are non NULL. Note + // that an unloaded persistent object is always unequal to a + // transient object. + // + if (t1 || t2) + return p_ == r.p_ && p_; + + // If both objects are persistent, then we compare databases and + // object ids. + // + typedef typename object_traits::object_type object_type1; + typedef typename object_traits::object_type object_type2; + + return i_.database () == r.i_.database () && + object_id () == r.template object_id (); + } +#endif // ODB_CXX11 + +} diff --git a/libodb/odb/nested-container.hxx b/libodb/odb/nested-container.hxx new file mode 100644 index 0000000..d7e4ec1 --- /dev/null +++ b/libodb/odb/nested-container.hxx @@ -0,0 +1,218 @@ +// file : odb/nested-container.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_NESTED_CONTAINER_HXX +#define ODB_NESTED_CONTAINER_HXX + +#include + +#include // size_t + +#include +#include // ODB_CXX11 + +#ifndef ODB_CXX11 +# error nested container support is only available in C++11 +#endif + +namespace odb +{ + // Nested container emulation support for ODB. + // + // In a nutshell, the idea is to represent a nested container, for example, + // vector>, as map where nested_key is a composite + // key consisting of the outer and inner container indexes. + // + // Note that with this approach the empty trailing entries of the outer + // container will not be added on load. It is assumed that the user handles + // that on their own, for example, by pre-loading the outer container entry + // members if there are any. + // + // Also note that the outer key in the inner container should strictly + // speaking be a foreign key pointing to the key of the outer container. The + // only way to achieve this currently is to manually add the constraint via + // ALTER TABLE ADD CONSTRAINT. Note, however, that as long as we only modify + // these tables via the ODB container interface, not having the foreign key + // (and not having ON DELETE CASCADE) should be harmless (since we have a + // foreign key pointing to the object id). + + // Map key that is used to emulate 1-level nested container mapping (for + // example, vector>). Template parameter IC is a tag that allows + // us to distinguish keys for unrelated containers in order to assign column + // names, etc. Use the inner container type (for example, vector) for IC. + // + template + struct nested_key + { + using outer_type = O; + using inner_type = I; + + outer_type outer; + inner_type inner; + + nested_key () = default; + nested_key (outer_type o, inner_type i): outer (o), inner (i) {} + + bool + operator< (const nested_key& v) const + { + return outer < v.outer || (outer == v.outer && inner < v.inner); + } + }; + + // Map key that is used to emulate 2-level nested container mapping (for + // example, vector>>>). Use the middle container type for + // MC (for example, vector>). + // + template + struct nested2_key + { + using outer_type = O; + using middle_type = M; + using inner_type = I; + + outer_type outer; + middle_type middle; + inner_type inner; + + nested2_key () = default; + nested2_key (outer_type o, middle_type m, inner_type i) + : outer (o), middle (m), inner (i) {} + + bool + operator< (const nested2_key& v) const + { + return outer != v.outer ? outer < v.outer : + middle != v.middle ? middle < v.middle : + inner < v.inner ; + } + }; +} + +#include +#include // size_t +#include // move(), declval() +#include +#include // remove_reference + +namespace odb +{ + template + struct nested1_type: + std::remove_reference ()[0])> {}; + + template + struct nested2_type: + std::remove_reference ()[0][0])> {}; + + template + struct nested3_type: + std::remove_reference ()[0][0][0])> {}; + + // 1-level nesting. + // + template // For example, OC = vector>. + std::map::type>, + typename nested2_type::type> + nested_get (const OC& oc) + { + using namespace std; + + using IC = typename nested1_type::type; + using V = typename nested2_type::type; + using K = nested_key; + + map r; + for (size_t o (0); o != oc.size (); ++o) + { + const IC& ic (oc[o]); + for (size_t i (0); i != ic.size (); ++i) + r.emplace (K (o, i), ic[i]); + } + return r; + } + + template + void + nested_set (OC& oc, std::map&& r) + { + using namespace std; + + for (auto& p: r) + { + size_t o (p.first.outer); + size_t i (p.first.inner); + V& v (p.second); + + if (o >= oc.size ()) + oc.resize (o + 1); + + assert (i == oc[o].size ()); + + oc[o].push_back (move (v)); + } + } + + // 2-level nesting. + // + template // For example, OC = vector>>. + std::map::type>, + typename nested3_type::type> + nested2_get (const OC& oc) + { + using namespace std; + + using MC = typename nested1_type::type; + using V = typename nested3_type::type; + using K = nested2_key; + + map r; + for (size_t o (0); o != oc.size (); ++o) + { + const auto& mc (oc[o]); + for (size_t m (0); m != mc.size (); ++m) + { + const auto& ic (mc[m]); + for (size_t i (0); i != ic.size (); ++i) + r.emplace (K (o, m, i), ic[i]); + } + } + return r; + } + + template + void + nested2_set (OC& oc, std::map&& r) + { + using namespace std; + + for (auto& p: r) + { + size_t o (p.first.outer); + size_t m (p.first.middle); + size_t i (p.first.inner); + V& v (p.second); + + if (o >= oc.size ()) + oc.resize (o + 1); + + auto& mc (oc[o]); + + if (m >= mc.size ()) + mc.resize (m + 1); + + assert (i == mc[m].size ()); + + mc[m].push_back (move (v)); + } + } +} + +#include + +#endif // ODB_NESTED_CONTAINER_HXX diff --git a/libodb/odb/no-id-object-result.hxx b/libodb/odb/no-id-object-result.hxx new file mode 100644 index 0000000..556065b --- /dev/null +++ b/libodb/odb/no-id-object-result.hxx @@ -0,0 +1,182 @@ +// file : odb/no-id-object-result.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_NO_ID_OBJECT_RESULT_HXX +#define ODB_NO_ID_OBJECT_RESULT_HXX + +#include + +#include // std::size_t +#include // std::move + +#include +#include +#include +#include +#include + +#include // ODB_CXX11 + +namespace odb +{ + // Implementation for objects without object id (always non-polymorphic). + // + template + class no_id_object_result_impl: public result_impl + { + protected: + // In result_impl, T is always non-const and the same as object_type. + // + typedef T object_type; + typedef odb::object_traits object_traits; + + typedef typename object_traits::pointer_type pointer_type; + typedef odb::pointer_traits pointer_traits; + + friend class result; + friend class result; + friend class result_iterator; + friend class result_iterator; + friend class object_result_iterator; + friend class object_result_iterator; + + protected: + no_id_object_result_impl (odb::connection& conn) + : result_impl (conn), begin_ (true), end_ (false), current_ () + { + } + + // To make this work with all kinds of pointers (raw, std::auto_ptr, + // shared), we need to make sure we don't make any copies of the + // pointer on the return path. + // + pointer_type& + current () + { + if (pointer_traits::null_ptr (current_) && !end_) + load (); + + return current_; + } + + void + release () + { + current_ = pointer_type (); + guard_.release (); + } + + void + begin () + { + if (begin_) + { + next (); + begin_ = false; + } + } + + bool + end () const + { + return end_; + } + + protected: + virtual void + load (object_type&) = 0; + + virtual void + next () = 0; + + virtual void + cache () = 0; + + virtual std::size_t + size () = 0; + + protected: +#ifdef ODB_CXX11 + void + current (pointer_type& p) + { + current_ = std::move (p); + guard_.reset (current_); + } + + void + current (pointer_type&& p) + { + current (p); + } +#else + void + current (pointer_type p) + { + current_ = p; + guard_.reset (current_); + } +#endif + + bool begin_; + bool end_; + + private: + void + load (); + + private: + pointer_type current_; + typename pointer_traits::guard guard_; + }; + + template + class object_result_iterator + { + public: + // T can be const T while object_type is always non-const. + // + typedef typename object_traits::object_type object_type; + + typedef no_id_object_result_impl result_impl_type; + + public: + object_result_iterator (result_impl_type* res) + : res_ (res) + { + } + + public: + typedef typename object_traits::pointer_type pointer_type; + + pointer_type + load () + { +#ifdef ODB_CXX11 + pointer_type r (std::move (res_->current ())); +#else + pointer_type r (res_->current ()); +#endif + res_->release (); + return r; + } + + void + load (object_type& obj) + { + // Objects without ids are not stored in session cache. + // + if (!res_->end ()) + res_->load (obj); + } + + protected: + result_impl_type* res_; + }; +} + +#include + +#include + +#endif // ODB_NO_ID_OBJECT_RESULT_HXX diff --git a/libodb/odb/no-id-object-result.txx b/libodb/odb/no-id-object-result.txx new file mode 100644 index 0000000..886fe4b --- /dev/null +++ b/libodb/odb/no-id-object-result.txx @@ -0,0 +1,21 @@ +// file : odb/no-id-object-result.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // object_result_impl + // + + template + void no_id_object_result_impl:: + load () + { + // Objects without ids are not stored in session cache. + // + pointer_type p (object_traits::create ()); + object_type& obj (pointer_traits::get_ref (p)); + current (p); + load (obj); + } +} diff --git a/libodb/odb/no-op-cache-traits.hxx b/libodb/odb/no-op-cache-traits.hxx new file mode 100644 index 0000000..b6d0518 --- /dev/null +++ b/libodb/odb/no-op-cache-traits.hxx @@ -0,0 +1,236 @@ +// file : odb/no-op-cache-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_NO_OP_CACHE_TRAITS_HXX +#define ODB_NO_OP_CACHE_TRAITS_HXX + +#include + +#include +#include +#include + +namespace odb +{ + // pointer_cache_type + // + // Used to convert an object pointer to the canonical form (non-const), + // suitable for insertion into the cache. + // + template ::element_type, + typename O = typename object_traits::object_type, + pointer_kind pk = pointer_traits

::kind> + struct pointer_cache_type + { + typedef typename object_traits::pointer_type pointer_type; + + static pointer_type + convert (const P& p) + { + return pointer_traits

::const_pointer_cast (p); + } + }; + + template + struct pointer_cache_type + { + // If element_type and object_type are the same, then it is already + // the canonical pointer. + // + static const P& + convert (const P& p) {return p;} + }; + + template + struct pointer_cache_type + { + // If the pointer is unique, then casting it can transfer ownership. + // In this case we return NULL void*, which will be ignored down the + // chain. + // + static void* + convert (const P&) {return 0;} + }; + + template + struct pointer_cache_type + { + static void* + convert (const P&) {return 0;} + }; + + // reference_cache_type + // + // Used to convert an object reference to the canonical form (non-const), + // suitable for insertion into the cache. + // + template ::object_type> + struct reference_cache_type + { + static O& + convert (T& r) + { + return const_cast (r); + } + }; + + template + struct reference_cache_type + { + // If the types are the same, then it is already the canonical form. + // + static T& + convert (T& r) {return r;} + }; + + // pointer_cache_traits + // + // Caching traits for objects passed by pointer. P should be the canonical + // pointer (non-const). + // + template + struct no_op_pointer_cache_traits + { + typedef P pointer_type; + typedef typename pointer_traits::element_type object_type; + typedef typename object_traits::id_type id_type; + struct position_type {}; + + struct insert_guard + { + insert_guard () {} + insert_guard (const position_type&) {} + + position_type + position () const {return position_type ();} + + void + release () {} + + void + reset (const position_type&) {} + }; + + // Cache management. + // + static position_type + insert (odb::database&, const id_type&, const pointer_type&) + { + return position_type (); + } + + static position_type + insert (odb::database&, const pointer_type&) {return position_type ();} + + // Special signature for unique pointers. + // + static position_type + insert (odb::database&, void*) {return position_type ();} + + static pointer_type + find (odb::database&, const id_type&) {return pointer_type ();} + + static void + erase (const position_type&) {} + + // Notifications. + // + static void + persist (const position_type&) {} + + static void + load (const position_type&) {} + + static void + update (odb::database&, const object_type&) {} + + static void + erase (odb::database&, const id_type&) {} + }; + + template + struct no_id_pointer_cache_traits + { + typedef P pointer_type; + struct position_type {}; + + static position_type + insert (odb::database&, const pointer_type&) {return position_type ();} + + // Special signature for unique pointers. + // + static position_type + insert (odb::database&, void*) {return position_type ();} + + static void + persist (const position_type&) {} + + static void + load (const position_type&) {} + }; + + // reference_cache_traits + // + // Caching traits for objects passed by reference. T should be the + // canonical object type (non-const). + // + template + struct no_op_reference_cache_traits + { + typedef T object_type; + typedef typename object_traits::id_type id_type; + struct position_type {}; + + struct insert_guard + { + insert_guard () {} + insert_guard (const position_type&) {} + + position_type + position () const {return position_type ();} + + void + release () {} + + void + reset () {} + }; + + static position_type + insert (odb::database&, const id_type&, object_type&) + { + return position_type (); + } + + static position_type + insert (odb::database&, object_type&) {return position_type ();} + + static void + persist (const position_type&) {} + + static void + load (const position_type&) {} + }; + + template + struct no_id_reference_cache_traits + { + typedef T object_type; + struct position_type {}; + + static position_type + insert (odb::database&, object_type&) {return position_type ();} + + static void + persist (const position_type&) {} + + static void + load (const position_type&) {} + }; +} + +#include + +#endif // ODB_NO_OP_CACHE_TRAITS_HXX diff --git a/libodb/odb/nullable.hxx b/libodb/odb/nullable.hxx new file mode 100644 index 0000000..d13f0c9 --- /dev/null +++ b/libodb/odb/nullable.hxx @@ -0,0 +1,229 @@ +// file : odb/nullable.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_NULLABLE_HXX +#define ODB_NULLABLE_HXX + +#include + +#include // odb::core + +namespace odb +{ + template + class nullable + { + public: + typedef T value_type; + + nullable (); + nullable (const T&); + nullable (const nullable&); + template explicit nullable (const nullable&); + + nullable& operator= (const T&); + nullable& operator= (const nullable&); + template nullable& operator= (const nullable&); + + void swap (nullable&); + + bool null () const; + + T& get (); + const T& get () const; + + T* operator-> (); + const T* operator-> () const; + + T& operator* (); + const T& operator* () const; + + typedef void (nullable::*bool_convertible) (); + operator bool_convertible () const + { + return null_ ? 0 : &nullable::true_value; + } + + void reset (); + + private: + void true_value () {}; + + T value_; + bool null_; + }; + + namespace common + { + using odb::nullable; + } + + template + inline bool + operator== (const nullable& x, const nullable& y) + { + return x.null () == y.null () && (x.null () || *x == *y); + } + + template + inline bool + operator!= (const nullable& x, const nullable& y) {return !(x == y);} + + template + inline bool + operator< (const nullable& x, const nullable& y) + { + return x.null () > y.null () || (!x.null () && !y.null () && *x < *y); + } + + template + inline bool + operator> (const nullable& x, const nullable& y) + { + return x.null () < y.null () || (!x.null () && !y.null () && *x > *y); + } + + template + inline bool + operator<= (const nullable& x, const nullable& y) {return !(x > y);} + + template + inline bool + operator>= (const nullable& x, const nullable& y) {return !(x < y);} + + template + inline nullable:: + nullable () + : null_ (true) + { + } + + template + inline nullable:: + nullable (const T& v) + : value_ (v), null_ (false) + { + } + + template + inline nullable:: + nullable (const nullable& y) + : value_ (y.value_), null_ (y.null_) + { + } + + template + template + inline nullable:: + nullable (const nullable& y) + : value_ (y.value_), null_ (y.null_) + { + } + + template + inline nullable& nullable:: + operator= (const T& v) + { + value_ = v; + null_ = false; + return *this; + } + + template + inline nullable& nullable:: + operator= (const nullable& y) + { + if (this != &y) + { + value_ = y.value_; + null_ = y.null_; + } + + return *this; + } + + template + template + inline nullable& nullable:: + operator= (const nullable& y) + { + value_ = y.value_; + null_ = y.null_; + return *this; + } + + template + inline void nullable:: + swap (nullable& y) + { + T v (value_); + bool n (null_); + + value_ = y.value_; + null_ = y.null_; + + y.value_ = v; + y.null_ = n; + } + + template + inline bool nullable:: + null () const + { + return null_; + } + + template + inline T& nullable:: + get () + { + return value_; + } + + template + inline const T& nullable:: + get () const + { + return value_; + } + + template + inline T* nullable:: + operator-> () + { + return null_ ? 0 : &value_; + } + + template + inline const T* nullable:: + operator-> () const + { + return null_ ? 0 : &value_; + } + + template + inline T& nullable:: + operator* () + { + return value_; + } + + template + inline const T& nullable:: + operator* () const + { + return value_; + } + + template + inline void nullable:: + reset () + { + value_ = T (); + null_ = true; + } +} + +#include + +#endif // ODB_NULLABLE_HXX diff --git a/libodb/odb/object-result.hxx b/libodb/odb/object-result.hxx new file mode 100644 index 0000000..056d518 --- /dev/null +++ b/libodb/odb/object-result.hxx @@ -0,0 +1,164 @@ +// file : odb/object-result.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_OBJECT_RESULT_HXX +#define ODB_OBJECT_RESULT_HXX + +#include + +#include // std::ptrdiff_t +#include // iterator categories + +#include +#include +#include +#include + +namespace odb +{ + // + // object_result_impl + // + template + class object_result_impl; + + template + class polymorphic_object_result_impl; + + template + class no_id_object_result_impl; + + // + // object_result_impl_selector + // + template ::id_type, + bool polymorphic = object_traits::polymorphic> + struct object_result_impl_selector; + + template + struct object_result_impl_selector + { + typedef object_result_impl type; + }; + + template + struct object_result_impl_selector + { + typedef polymorphic_object_result_impl type; + }; + + template + struct object_result_impl_selector + { + typedef no_id_object_result_impl type; + }; + + // + // result_iterator + // + + template + class object_result_iterator; + + template + class result_iterator: public object_result_iterator< + T, + typename object_traits::id_type, + object_traits::polymorphic> + { + public: + typedef T value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + + // T can be const T while object_type is always non-const. + // + typedef + object_result_iterator::id_type, + object_traits::polymorphic> base_type; + + public: + explicit + result_iterator (typename base_type::result_impl_type* res = 0) + : base_type (res) + { + } + + // Input iterator requirements. + // + public: + reference + operator* () const + { + return pointer_traits::get_ref (this->res_->current ()); + } + + // Our value_type is already a pointer so return it instead of + // a pointer to it (operator-> will just have to go one deeper + // in the latter case). + // + pointer + operator-> () const + { + return pointer_traits::get_ptr (this->res_->current ()); + } + + result_iterator& + operator++ () + { + this->res_->next (); + return *this; + } + + result_iterator + operator++ (int) + { + // All non-end iterators for a result object move together. + // + this->res_->next (); + return *this; + } + + public: + bool + equal (result_iterator j) const + { + return (this->res_ ? this->res_->end () : true) == + (j.res_ ? j.res_->end () : true); + } + + private: + // Use unrestricted pointer traits since that's what is returned by + // result_impl. + // + typedef + odb::pointer_traits< + typename object_traits< + typename base_type::object_type>::pointer_type> + pointer_traits; + }; + + // + // + template + class result_base + { + public: + typedef typename object_traits::pointer_type value_type; + + // T can be const T while object_type is always non-const. + // + typedef typename object_traits::object_type object_type; + typedef + typename object_result_impl_selector::type + result_impl_type; + }; +} + +#include + +#endif // ODB_OBJECT_RESULT_HXX diff --git a/libodb/odb/pointer-traits.hxx b/libodb/odb/pointer-traits.hxx new file mode 100644 index 0000000..a0baa21 --- /dev/null +++ b/libodb/odb/pointer-traits.hxx @@ -0,0 +1,405 @@ +// file : odb/pointer-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_POINTER_TRAITS_HXX +#define ODB_POINTER_TRAITS_HXX + +#include + +#include // operators new/delete +#include // std::auto_ptr, std::unique_ptr, std::shared_ptr/weak_ptr +#include // std::size_t + +#include // ODB_CXX11 +#include + +namespace odb +{ + enum pointer_kind + { + pk_raw, // Raw pointer or equivalent (i.e., unmanaged). + pk_unique, // Smart pointer that doesn't support sharing. + pk_shared, // Smart pointer that supports sharing. + pk_weak // Weak counterpart for shared pointer. + }; + + template + class pointer_traits; + + // + // Standard pointer guards. + // + + // Raw pointer guard. + // + template + class raw_ptr_guard + { + public: + ~raw_ptr_guard () {delete p_;} + raw_ptr_guard (): p_ (0) {} + + explicit + raw_ptr_guard (P p): p_ (p) {} + + void + release () {p_ = 0;} + + void + reset (P p = 0) {delete p_; p_ = p;} + + private: + P p_; + }; + + // No-op pointer guard for smart pointers. + // + template + class smart_ptr_guard + { + public: + smart_ptr_guard () {} + + explicit + smart_ptr_guard (const P&) {} + + void + release () {} + + void + reset () {} + + void + reset (const P&) {} + }; + + // Specialization for raw pointers. + // + template + class pointer_traits + { + public: + static const pointer_kind kind = pk_raw; + static const bool lazy = false; + + typedef T element_type; + typedef T* pointer_type; + typedef const T* const_pointer_type; + typedef typename odb::details::meta::remove_const::result* + unrestricted_pointer_type; + typedef raw_ptr_guard guard; + + // Return raw pointer to the pointed-to element, including NULL. + // + static element_type* + get_ptr (pointer_type p) + { + return p; + } + + // Return reference to the pointed-to element. + // + static element_type& + get_ref (pointer_type p) + { + return *p; + } + + // Return true if the pointer is NULL. + // + static bool + null_ptr (pointer_type p) + { + return p == 0; + } + + // Casts. + // + static unrestricted_pointer_type + const_pointer_cast (pointer_type p) + { + return const_cast (p); + } + + template + static T1* + static_pointer_cast (pointer_type p) + { + return static_cast (p); + } + + template + static T1* + dynamic_pointer_cast (pointer_type p) + { + return dynamic_cast (p); + } + + public: + // Allocate memory for an element that will be managed by this + // pointer. + // + static void* + allocate (std::size_t n) + { + return operator new (n); + } + + // Free memory allocated for an element. This functions is only + // called if the constructor of the element being created fails. + // Otherwise, the pointer (or guard) is used to delete the object + // and free the memory. This behavior is identical to the one + // used by operator delete overloading. + // + static void + free (void* p) + { + operator delete (p); + } + }; + + // Specialization for std::auto_ptr. + // +#ifndef ODB_CXX11 + template + class pointer_traits< std::auto_ptr > + { + public: + static const pointer_kind kind = pk_unique; + static const bool lazy = false; + + typedef T element_type; + typedef std::auto_ptr pointer_type; + typedef std::auto_ptr const_pointer_type; + typedef smart_ptr_guard 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.get () == 0; + } + + // const_pointer_cast() is not provided. + // + + // Note: transfers ownership. + // + template + static std::auto_ptr + static_pointer_cast (pointer_type& p) + { + return std::auto_ptr (static_cast (p.release ())); + } + + // Note: transfers ownership if successful. + // + template + static std::auto_ptr + dynamic_pointer_cast (pointer_type& p) + { + T1* p1 (dynamic_cast (p.get ())); + + if (p1 != 0) + p.release (); + + return std::auto_ptr (p1); + } + + public: + static void* + allocate (std::size_t n) + { + return operator new (n); + } + + static void + free (void* p) + { + operator delete (p); + } + }; +#endif + +#ifdef ODB_CXX11 + + // Specialization for C++11 std::unique_ptr. + // + template class D> + class pointer_traits>> + { + public: + static const pointer_kind kind = pk_unique; + static const bool lazy = false; + + typedef T element_type; + typedef std::unique_ptr> pointer_type; + typedef std::unique_ptr> const_pointer_type; + typedef smart_ptr_guard 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; + } + + // const_pointer_cast() is not provided. + // + + // Note: transfers ownership. + // + template + static std::unique_ptr> + static_pointer_cast (pointer_type& p) + { + return std::unique_ptr> (static_cast (p.release ())); + } + + // Note: transfers ownership if successful. + // + template + static std::unique_ptr> + dynamic_pointer_cast (pointer_type& p) + { + T1* p1 (dynamic_cast (p.get ())); + + if (p1 != 0) + p.release (); + + return std::unique_ptr> (p1); + } + + public: + static void* + allocate (std::size_t n) + { + return operator new (n); + } + + static void + free (void* p) + { + operator delete (p); + } + }; + + // Specialization for C++11 std::shared_ptr. + // + template + class pointer_traits> + { + public: + static const pointer_kind kind = pk_shared; + static const bool lazy = false; + + typedef T element_type; + typedef std::shared_ptr pointer_type; + typedef std::shared_ptr const_pointer_type; + typedef typename odb::details::meta::remove_const::result + unrestricted_element_type; + typedef std::shared_ptr + unrestricted_pointer_type; + typedef smart_ptr_guard 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; + } + + static unrestricted_pointer_type + const_pointer_cast (const pointer_type& p) + { + return std::const_pointer_cast (p); + } + + template + static std::shared_ptr + static_pointer_cast (const pointer_type& p) + { + return std::static_pointer_cast (p); + } + + template + static std::shared_ptr + dynamic_pointer_cast (const pointer_type& p) + { + return std::dynamic_pointer_cast (p); + } + + public: + static void* + allocate (std::size_t n) + { + return operator new (n); + } + + static void + free (void* p) + { + operator delete (p); + } + }; + + // Specialization for C++11 std::weak_ptr. + // + template + class pointer_traits> + { + public: + static const pointer_kind kind = pk_weak; + static const bool lazy = false; + + typedef T element_type; + typedef std::weak_ptr pointer_type; + typedef std::shared_ptr strong_pointer_type; + + static strong_pointer_type + lock (const pointer_type& p) + { + return p.lock (); + } + }; + +#endif // ODB_CXX11 + +} + +#include + +#endif // ODB_POINTER_TRAITS_HXX diff --git a/libodb/odb/polymorphic-info.hxx b/libodb/odb/polymorphic-info.hxx new file mode 100644 index 0000000..0f410d5 --- /dev/null +++ b/libodb/odb/polymorphic-info.hxx @@ -0,0 +1,188 @@ +// file : odb/polymorphic-info.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_POLYMORPHIC_INFO_HXX +#define ODB_POLYMORPHIC_INFO_HXX + +#include + +#include // std::size_t +#include + +#include // database, connection +#include +#include + +namespace odb +{ + template + struct polymorphic_abstract_info + { + typedef void (*section_load) (odb::connection&, R&, bool top); + typedef void (*section_update) (odb::connection&, const R&); + + struct section_functions + { + section_load load; + section_update update; + }; + + struct section_list + { + std::size_t count; + const section_functions* functions; + }; + + public: + polymorphic_abstract_info (const std::type_info& t, + const polymorphic_abstract_info* b, + const section_list* s) + : type (t), base (b), sections (s) {} + + bool + derived (const polymorphic_abstract_info& b) const + { + for (const polymorphic_abstract_info* p (base); p != 0; p = p->base) + if (&b == p) + return true; + + return false; + } + + // Find the "most overridden" section functions. + // + section_load + find_section_load (std::size_t index) const + { + for (const polymorphic_abstract_info* b (this); b != 0; b = b->base) + if (b->sections != 0 && + index < b->sections->count && + b->sections->functions[index].load != 0) + return b->sections->functions[index].load; + + return 0; + } + + section_update + find_section_update (std::size_t index) const + { + for (const polymorphic_abstract_info* b (this); b != 0; b = b->base) + if (b->sections != 0 && + index < b->sections->count && + b->sections->functions[index].update != 0) + return b->sections->functions[index].update; + + return 0; + } + + bool + final_section_update (const polymorphic_abstract_info& i, + std::size_t index) const + { + return i.sections != 0 && + index < i.sections->count && + i.sections->functions[index].update != 0 && + i.sections->functions[index].update == find_section_update (index); + } + + public: + const std::type_info& type; + const polymorphic_abstract_info* base; + + // Sections. + // + // There could be "concrete" (i.e., not overridden) section in an + // abstract class. Which means the section table has to be in + // abstract_info. + // + const section_list* sections; + }; + + template + struct polymorphic_concrete_info: polymorphic_abstract_info + { + // Have to use access::object_traits directly because of VC10. + // + typedef R root_type; + typedef access::object_traits root_traits; + typedef typename root_traits::id_type id_type; + typedef typename root_traits::pointer_type pointer_type; + typedef typename root_traits::discriminator_type discriminator_type; + + typedef typename polymorphic_abstract_info::section_list section_list; + + enum call_type + { + call_callback, // arg points to callback event. + call_persist, // arg is not used. + call_update, // arg is not used. + call_find, // arg points to object id. + call_reload, // arg is not used. + call_load, // arg points to depth. + call_erase // arg points to object id. + }; + + typedef pointer_type (*create_function) (); + typedef bool (*dispatch_function) ( + call_type, odb::database&, const root_type*, const void* arg); + typedef void (*delayed_loader_function) ( + odb::database&, + const id_type&, + root_type&, + const schema_version_migration*); + + public: + polymorphic_concrete_info (const std::type_info& t, + const polymorphic_abstract_info* b, + const section_list* s, + const discriminator_type& d, + create_function cf, + dispatch_function df, + delayed_loader_function dlf) + : polymorphic_abstract_info (t, b, s), + discriminator (d), + create (cf), dispatch (df), delayed_loader (dlf) + { + } + + public: + discriminator_type discriminator; + create_function create; + dispatch_function dispatch; + delayed_loader_function delayed_loader; + }; + + // Register concrete type T in the root's map. + // + template + struct polymorphic_entry + { + typedef T object_type; + typedef object_traits_impl object_traits; + typedef typename object_traits::root_type root_type; + + polymorphic_entry (); + ~polymorphic_entry (); + }; + + // Helper functions that either return the concrete info or NULL + // depending on what kind of info we pass (used in query support). + // + template + inline const polymorphic_concrete_info* + polymorphic_info (const polymorphic_concrete_info& i) + { + return &i; + } + + template + inline const polymorphic_concrete_info* + polymorphic_info (const polymorphic_abstract_info&) + { + return 0; + } +} + +#include + +#endif // ODB_POLYMORPHIC_INFO_HXX diff --git a/libodb/odb/polymorphic-map.hxx b/libodb/odb/polymorphic-map.hxx new file mode 100644 index 0000000..2e61314 --- /dev/null +++ b/libodb/odb/polymorphic-map.hxx @@ -0,0 +1,276 @@ +// file : odb/polymorphic-map.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_POLYMORPHIC_MAP_HXX +#define ODB_POLYMORPHIC_MAP_HXX + +#include + +#include +#include // std::move +#include // std::size_t +#include +#include + +#include + +#include // ODB_CXX11 +#include + +#include + +namespace odb +{ + template + struct polymorphic_map + { + typedef R root_type; + typedef polymorphic_concrete_info info_type; + typedef typename info_type::discriminator_type discriminator_type; + + polymorphic_map (): ref_count_ (1) {} + + const info_type& + find (const std::type_info& t) const; + + const info_type& + find (const discriminator_type& d) const; + + public: + typedef + std::map // VC bug. + type_map; + + struct discriminator_comparator + { + bool + operator() (const discriminator_type* x, + const discriminator_type* y) const + { + return *x < *y; + } + }; + + typedef + std::map + discriminator_map; + + public: + std::size_t ref_count_; + type_map type_map_; + discriminator_map discriminator_map_; + }; + + template + struct polymorphic_entry_impl + { + typedef R root_type; + typedef object_traits_impl root_traits; + typedef polymorphic_concrete_info info_type; + + static void + insert (const info_type&); + + static void + erase (const info_type&); + }; + + template + typename object_traits::root_type>::pointer_type + create_impl () + { + typedef object_traits derived_traits; + typedef object_traits root_traits; + + typedef typename derived_traits::pointer_type derived_pointer_type; + typedef typename root_traits::pointer_type root_pointer_type; + + derived_pointer_type p ( + access::object_factory::create ()); + + // Implicit downcast. + // +#ifdef ODB_CXX11 + root_pointer_type r (std::move (p)); +#else + root_pointer_type r (p); +#endif + return r; + } + + template + struct dispatch_load + { + static void + call (database& db, T& obj, std::size_t d) + { + object_traits_impl::load_ (db, obj, d); + } + }; + + template + struct dispatch_load + { + static void + call (database&, R&, std::size_t) + { + assert (false); + } + }; + + template + struct dispatch_persist + { + static void + call (database& db, const T& obj) + { + // Top-level call, no dynamic type checking. + // + object_traits_impl::persist (db, obj, true, false); + } + }; + + template + struct dispatch_persist + { + static void + call (database& db, const T& obj) + { + // Top-level call, no dynamic type checking. + // + object_traits_impl::persist ( + db, const_cast (obj), true, false); + } + }; + + template + bool + dispatch_impl ( + typename polymorphic_concrete_info< + typename object_traits::root_type>::call_type c, + database& db, + const typename object_traits::root_type* pobj, + const void* arg) + { + typedef object_traits_impl derived_traits; + typedef typename derived_traits::root_type root_type; + typedef object_traits_impl root_traits; + typedef typename root_traits::id_type id_type; + typedef polymorphic_concrete_info info_type; + + bool r (false); + + switch (c) + { + case info_type::call_callback: + { + derived_traits::callback ( + db, + *const_cast (static_cast (pobj)), + *static_cast (arg)); + break; + } + case info_type::call_persist: + { + dispatch_persist::call ( + db, + *static_cast (pobj)); + break; + } + case info_type::call_update: + { + derived_traits::update ( + db, + *static_cast (pobj), + true, // Top-level call. + false); // No dynamic type checking. + break; + } + case info_type::call_find: + { + r = derived_traits::find ( + db, + *static_cast (arg), + *const_cast (static_cast (pobj)), + false); // No dynamic type checking. + break; + } + case info_type::call_reload: + { + r = derived_traits::reload ( + db, + *const_cast (static_cast (pobj)), + false); // No dynamic type checking. + break; + } + case info_type::call_load: + { + dispatch_load::call ( + db, + *const_cast (static_cast (pobj)), + *static_cast (arg)); + break; + } + case info_type::call_erase: + { + if (pobj != 0) + derived_traits::erase ( + db, + *static_cast (pobj), + true, // Top-level call. + false); // No dynamic type checking. + else + derived_traits::erase ( + db, + *static_cast (arg), + true, // Top-level call. + false); // No dynamic type checking. + break; + } + } + + return r; + } + + template + void + section_load_impl (odb::connection& conn, + typename object_traits::root_type& obj, + bool top) + { + typedef object_traits_impl derived_traits; + typedef typename derived_traits::statements_type statements_type; + typedef typename statements_type::connection_type connection_type; + + connection_type& c (static_cast (conn)); + statements_type& sts (c.statement_cache ().template find_object ()); + + ST::load (sts.extra_statement_cache (), static_cast (obj), top); + } + + template + void + section_update_impl (odb::connection& conn, + const typename object_traits::root_type& obj) + { + typedef object_traits_impl derived_traits; + typedef typename derived_traits::statements_type statements_type; + typedef typename statements_type::connection_type connection_type; + + connection_type& c (static_cast (conn)); + statements_type& sts (c.statement_cache ().template find_object ()); + + ST::update (sts.extra_statement_cache (), static_cast (obj)); + } +} + +#include +#include + +#include + +#endif // ODB_POLYMORPHIC_MAP_HXX diff --git a/libodb/odb/polymorphic-map.ixx b/libodb/odb/polymorphic-map.ixx new file mode 100644 index 0000000..4e00c46 --- /dev/null +++ b/libodb/odb/polymorphic-map.ixx @@ -0,0 +1,19 @@ +// file : odb/polymorphic-map.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + template + inline polymorphic_entry:: + polymorphic_entry () + { + polymorphic_entry_impl::insert (object_traits::info); + } + + template + inline polymorphic_entry:: + ~polymorphic_entry () + { + polymorphic_entry_impl::erase (object_traits::info); + } +} diff --git a/libodb/odb/polymorphic-map.txx b/libodb/odb/polymorphic-map.txx new file mode 100644 index 0000000..9e0c0f0 --- /dev/null +++ b/libodb/odb/polymorphic-map.txx @@ -0,0 +1,75 @@ +// file : odb/polymorphic-map.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include // no_type_info + +namespace odb +{ + // + // polymorphic_map + // + + template + const typename polymorphic_map::info_type& polymorphic_map:: + find (const std::type_info& t) const + { + typename type_map::const_iterator i (type_map_.find (&t)); + + if (i != type_map_.end ()) + return *i->second; + else + throw no_type_info (); + } + + template + const typename polymorphic_map::info_type& polymorphic_map:: + find (const discriminator_type& d) const + { + typename discriminator_map::const_iterator i ( + discriminator_map_.find (&d)); + + if (i != discriminator_map_.end ()) + return *i->second; + else + throw no_type_info (); + } + + // + // polymorphic_entry_impl + // + + template + void polymorphic_entry_impl:: + insert (const info_type& i) + { + // VC10 cannot grok constructor call syntax here. + // + polymorphic_map*& pm = root_traits::map; + + if (pm == 0) + pm = new polymorphic_map; + else + pm->ref_count_++; + + pm->type_map_[&i.type] = &i; + pm->discriminator_map_[&i.discriminator] = &i; + } + + template + void polymorphic_entry_impl:: + erase (const info_type& i) + { + // VC10 cannot grok constructor call syntax here. + // + polymorphic_map*& pm = root_traits::map; + + pm->discriminator_map_.erase (&i.discriminator); + pm->type_map_.erase (&i.type); + + if (--pm->ref_count_ == 0) + { + delete pm; + pm = 0; + } + } +} diff --git a/libodb/odb/polymorphic-object-result.hxx b/libodb/odb/polymorphic-object-result.hxx new file mode 100644 index 0000000..5498856 --- /dev/null +++ b/libodb/odb/polymorphic-object-result.hxx @@ -0,0 +1,224 @@ +// file : odb/polymorphic-object-result.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_POLYMORPHIC_OBJECT_RESULT_HXX +#define ODB_POLYMORPHIC_OBJECT_RESULT_HXX + +#include + +#include // std::size_t +#include // std::move + +#include +#include +#include +#include +#include + +#include // ODB_CXX11 + +namespace odb +{ + // Implementation for polymorphic objects with object id. + // + template + class polymorphic_object_result_impl: public result_impl + { + protected: + // In result_impl, T is always non-const and the same as object_type. + // + typedef T object_type; + typedef odb::object_traits object_traits; + typedef typename object_traits::id_type id_type; + + typedef typename object_traits::pointer_type pointer_type; + typedef odb::pointer_traits pointer_traits; + + typedef typename object_traits::root_type root_type; + typedef odb::object_traits root_traits; + typedef typename root_traits::discriminator_type discriminator_type; + + friend class result; + friend class result; + friend class result_iterator; + friend class result_iterator; + friend class object_result_iterator; + friend class object_result_iterator; + + protected: + polymorphic_object_result_impl (odb::connection& conn) + : result_impl (conn), begin_ (true), end_ (false), current_ () + { + } + + // To make this work with all kinds of pointers (raw, std::auto_ptr, + // shared), we need to make sure we don't make any copies of the + // pointer on the return path. + // + pointer_type& + current () + { + if (pointer_traits::null_ptr (current_) && !end_) + load (); + + return current_; + } + + void + release () + { + current_ = pointer_type (); + guard_.release (); + } + + void + begin () + { + if (begin_) + { + next (); + begin_ = false; + } + } + + bool + end () const + { + return end_; + } + + protected: + // The fetch argument is a hint to the implementation. If it is + // false then it means load_id() was already called (and presumably + // fetched the data into the object image) and the object image + // is still valid (so the implementation doesn't need to fetch + // the data again). + // + // The load() signature differs from the non-polymorphic cases in + // that we pass a pointer to object instead of a reference. The + // object is only passed if the user requests loading into an + // existing instance. Otherwise, we pass NULL and load() is + // responsible for creating the object of a correct dynamic + // type and managing the object cache insertion. + // + virtual void + load (object_type*, bool fetch = true) = 0; + + virtual id_type + load_id () = 0; + + virtual discriminator_type + load_discriminator () = 0; + + virtual void + next () = 0; + + virtual void + cache () = 0; + + virtual std::size_t + size () = 0; + + protected: +#ifdef ODB_CXX11 + void + current (pointer_type& p, bool guard = true) + { + current_ = std::move (p); + + if (guard) + guard_.reset (current_); + else + guard_.reset (); + } + + void + current (pointer_type&& p, bool guard = true) + { + current (p, guard); + } +#else + void + current (pointer_type p, bool guard = true) + { + current_ = p; + + if (guard) + guard_.reset (current_); + else + guard_.reset (); + } +#endif + + bool begin_; + bool end_; + + private: + void + load (); + + private: + pointer_type current_; + typename pointer_traits::guard guard_; + }; + + template + class object_result_iterator + { + public: + // T can be const T while object_type is always non-const. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::id_type id_type; + typedef typename object_traits::root_type root_type; + typedef typename object_traits::discriminator_type + discriminator_type; + + typedef polymorphic_object_result_impl result_impl_type; + + public: + object_result_iterator (result_impl_type* res) + : res_ (res) + { + } + + public: + typedef typename object_traits::pointer_type pointer_type; + + pointer_type + load () + { +#ifdef ODB_CXX11 + pointer_type r (std::move (res_->current ())); +#else + pointer_type r (res_->current ()); +#endif + res_->release (); + return r; + } + + void + load (object_type&); + + id_type + id () + { + return res_->load_id (); + } + + discriminator_type + discriminator () + { + return res_->load_discriminator (); + } + + protected: + result_impl_type* res_; + }; +} + +#include + +#include + +#endif // ODB_POLYMORPHIC_OBJECT_RESULT_HXX diff --git a/libodb/odb/polymorphic-object-result.txx b/libodb/odb/polymorphic-object-result.txx new file mode 100644 index 0000000..d9252e9 --- /dev/null +++ b/libodb/odb/polymorphic-object-result.txx @@ -0,0 +1,70 @@ +// file : odb/polymorphic-object-result.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + // + // polymorphic_object_result_impl + // + + template + void polymorphic_object_result_impl:: + load () + { + typedef typename root_traits::pointer_type root_pointer_type; + typedef typename root_traits::pointer_traits root_pointer_traits; + + // First check the session. + // + const id_type& id (load_id ()); + + root_pointer_type rp ( + object_traits::pointer_cache_traits::find (this->db_, id)); + + if (!root_pointer_traits::null_ptr (rp)) + { + // Check if the types match. + // + pointer_type p ( + root_pointer_traits::template dynamic_pointer_cast< + object_type> (rp)); + + if (!pointer_traits::null_ptr (p)) + current (p, false); // Pointer from cache should not be guarded. + else + // We have an object in session that has a different type + // compared to the one in the database. + // + throw object_not_persistent (); // @@ type_mismatch? + } + else + // load() is responsible for creating the object of a correct + // dynamic type and for object cache insertion. + // + load (0, false); + } + + // + // object_result_iterator + // + + template + void object_result_iterator:: + load (object_type& obj) + { + if (res_->end ()) + return; + + typedef odb::object_traits object_traits; + + typename object_traits::reference_cache_traits::position_type p ( + object_traits::reference_cache_traits::insert ( + res_->db_, res_->load_id (), obj)); + typename object_traits::reference_cache_traits::insert_guard ig (p); + res_->load (&obj, false); + object_traits::reference_cache_traits::load (p); + ig.release (); + } +} diff --git a/libodb/odb/post.hxx b/libodb/odb/post.hxx new file mode 100644 index 0000000..3cdfd94 --- /dev/null +++ b/libodb/odb/post.hxx @@ -0,0 +1,6 @@ +// file : odb/post.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifdef _MSC_VER +# pragma warning (pop) +#endif diff --git a/libodb/odb/pre.hxx b/libodb/odb/pre.hxx new file mode 100644 index 0000000..088f172 --- /dev/null +++ b/libodb/odb/pre.hxx @@ -0,0 +1,23 @@ +// file : odb/pre.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifdef _MSC_VER + // Push warning state. + // +# pragma warning (push, 3) + + // Disabled warnings. + // +# pragma warning (disable:4068) // unknown pragma +# pragma warning (disable:4251) // needs to have DLL-interface +# pragma warning (disable:4290) // exception specification ignored +# pragma warning (disable:4355) // passing 'this' to a member +# pragma warning (disable:4800) // forcing value to bool +# pragma warning (disable:4231) // non-standard extension (extern template) +# pragma warning (disable:4275) // "C4251 is essentially noise and can be + // silenced" - Stephan T. Lavavej [And C4275 + // is essentially the same thing.] + // Elevated warnings. + // +# pragma warning (2:4239) // standard doesn't allow this conversion +#endif diff --git a/libodb/odb/prepared-query.cxx b/libodb/odb/prepared-query.cxx new file mode 100644 index 0000000..70bcaa1 --- /dev/null +++ b/libodb/odb/prepared-query.cxx @@ -0,0 +1,47 @@ +// file : odb/prepared-query.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +namespace odb +{ + prepared_query_impl:: + ~prepared_query_impl () + { + if (next_ != this) + list_remove (); + } + + prepared_query_impl:: + prepared_query_impl (connection& c) + : cached (false), conn (c), prev_ (0), next_ (this) + { + // Add to the list. + // + next_ = conn.prepared_queries_; + conn.prepared_queries_ = this; + + if (next_ != 0) + next_->prev_ = this; + } + + bool prepared_query_impl:: + verify_connection (transaction& t) + { + return &t.connection () == &stmt->connection (); + } + + void prepared_query_impl:: + list_remove () + { + (prev_ == 0 ? conn.prepared_queries_ : prev_->next_) = next_; + + if (next_ != 0) + next_->prev_ = prev_; + + prev_ = 0; + next_ = this; + } +} diff --git a/libodb/odb/prepared-query.hxx b/libodb/odb/prepared-query.hxx new file mode 100644 index 0000000..7cac6da --- /dev/null +++ b/libodb/odb/prepared-query.hxx @@ -0,0 +1,201 @@ +// file : odb/prepared-query.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_PREPARED_QUERY_HXX +#define ODB_PREPARED_QUERY_HXX + +#include + +#include // odb::core +#include +#include +#include + +#include +#include + +namespace odb +{ + class LIBODB_EXPORT prepared_query_impl: public details::shared_base + { + public: + virtual + ~prepared_query_impl (); + + prepared_query_impl (connection&); + + // Verify this prepared query and the specified transaction use the + // same connection. + // + virtual bool + verify_connection (transaction&); + + bool cached; + connection& conn; + const char* name; + details::shared_ptr stmt; + details::shared_ptr (*execute) (prepared_query_impl&); + + private: + prepared_query_impl (const prepared_query_impl&); + prepared_query_impl& operator= (const prepared_query_impl&); + + // Doubly-linked list of results. + // + // prev_ == 0 means we are the first element. + // next_ == 0 means we are the last element. + // next_ == this means we are not on the list. + // + protected: + friend class connection; + + void + list_remove (); + + prepared_query_impl* prev_; + prepared_query_impl* next_; + }; + + template + struct prepared_query + { + // Cached version. + // + explicit + prepared_query (prepared_query_impl* impl = 0): impl_ (impl) {} + + // Uncached version. + // + explicit + prepared_query (const details::shared_ptr& impl) + : impl_ (impl.get ()) + { + impl_->_inc_ref (); + } + + result + execute (bool cache = true) + { + typedef + typename result_base::kind>::result_impl_type + derived_type; + + details::shared_ptr ri (impl_->execute (*impl_)); + result r ( + details::shared_ptr ( + static_cast (ri.release ()))); + + if (cache) + r.cache (); + + return r; + } + + typename object_traits::pointer_type + execute_one () + { + return execute (false).one (); + } + + bool + execute_one (T& object) + { + return execute (false).one (object); + } + + T + execute_value () + { + // Compiler error pointing here? The object must be default- + // constructible in order to use the return-by-value API. + // + T o; + execute (false).value (o); + return o; + } + + const char* + name () const + { + return impl_->name; + } + + typedef odb::statement statement_type; + + statement_type& + statement () const + { + return *impl_->stmt; + } + + typedef prepared_query_impl* prepared_query::*unspecified_bool_type; + operator unspecified_bool_type () const + { + return impl_ ? &prepared_query::impl_ : 0; + } + + public: + ~prepared_query () + { + if (impl_ != 0 && !impl_->cached && impl_->_dec_ref ()) + delete impl_; + } + + prepared_query (const prepared_query& x) + : impl_ (x.impl_) + { + if (!impl_->cached) + impl_->_inc_ref (); + } + + prepared_query& + operator= (const prepared_query& x) + { + if (impl_ != x.impl_) + { + if (impl_ != 0 && !impl_->cached && impl_->_dec_ref ()) + delete impl_; + + impl_ = x.impl_; + + if (!impl_->cached) + impl_->_inc_ref (); + } + + return *this; + } + + private: + // Ideally, we would just use shared_ptr to manage the impl object. + // However, there is a problem if the prepared query is cached on + // the connection and the connection is released early when the + // transaction is committed or rolled back. In this case, the + // prepared_query object might still be around pointing to impl. If + // this connection and the prepared query are then used by another + // thread while we release the impl object, then we have a race + // condition. + // + // To work around this problem we will simply "reference" the impl + // object without counting if the prepared query is cached. For + // transition from pointer to reference, see cache_query_() in + // connection.cxx. + // + // You may also observe that in order to know whether this is a + // cached prepared query or not, we have to read the cached data + // member in the impl object. This does not cause a race because, + // unlike the reference count, this member is immutable once set + // to true. + // + friend class connection; + prepared_query_impl* impl_; + }; + + namespace common + { + using odb::prepared_query; + } +} + +#include + +#endif // ODB_PREPARED_QUERY_HXX diff --git a/libodb/odb/query-dynamic.cxx b/libodb/odb/query-dynamic.cxx new file mode 100644 index 0000000..bf9fd9c --- /dev/null +++ b/libodb/odb/query-dynamic.cxx @@ -0,0 +1,200 @@ +// file : odb/query-dynamic.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +using namespace std; + +namespace odb +{ + // query_param + // + query_param:: + ~query_param () + { + } + + // query_base + // + void query_base:: + clear () + { + for (clause_type::iterator i (clause_.begin ()); i != clause_.end (); ++i) + { + if (i->kind == clause_part::kind_param_val || + i->kind == clause_part::kind_param_ref) + { + query_param* qp (reinterpret_cast (i->data)); + + if (qp != 0 && qp->_dec_ref ()) + delete qp; + } + } + + clause_.clear (); + strings_.clear (); + } + + void query_base:: + append (const string& native) + { + strings_.push_back (native); + clause_.push_back (clause_part ()); + clause_.back ().kind = clause_part::kind_native; + clause_.back ().data = strings_.size () - 1; + } + + void query_base:: + append (const query_base& x) + { + size_t i (clause_.size ()), delta (i); + size_t n (i + x.clause_.size ()); + clause_.resize (n); + + for (size_t j (0); i < n; ++i, ++j) + { + const clause_part& s (x.clause_[j]); + clause_part& d (clause_[i]); + + d = s; + + // We need to increment the param references, update pointers + // to strings and update argument positions. + // + switch (s.kind) + { + case clause_part::kind_param_val: + case clause_part::kind_param_ref: + { + reinterpret_cast (d.data)->_inc_ref (); + break; + } + case clause_part::kind_native: + { + strings_.push_back (x.strings_[s.data]); + d.data = strings_.size () - 1; + break; + } + case clause_part::op_add: + + case clause_part::op_and: + case clause_part::op_or: + + case clause_part::op_eq: + case clause_part::op_ne: + case clause_part::op_lt: + case clause_part::op_gt: + case clause_part::op_le: + case clause_part::op_ge: + { + d.data += delta; + break; + } + // Do not use default here to remember to handle new op codes. + // + case clause_part::kind_column: + case clause_part::kind_true: + case clause_part::kind_false: + case clause_part::op_not: + case clause_part::op_null: + case clause_part::op_not_null: + case clause_part::op_in: + case clause_part::op_like: + case clause_part::op_like_escape: + break; + } + } + } + + void query_base:: + append_ref (const void* ref, const native_column_info* c) + { + clause_.push_back (clause_part ()); + clause_part& p (clause_.back ()); + + p.kind = clause_part::kind_param_ref; + p.data = 0; // In case new below throws. + p.native_info = c; + + p.data = reinterpret_cast ( + new (details::shared) query_param (ref)); + } + + query_base& query_base:: + operator+= (const std::string& native) + { + if (!native.empty ()) + { + size_t p (clause_.size ()); + append (native); + + if (p != 0) + append (clause_part::op_add, p - 1); + } + + return *this; + } + + query_base& query_base:: + operator+= (const query_base& x) + { + if (!x.empty ()) + { + size_t p (clause_.size ()); + append (x); + + if (p != 0) + append (clause_part::op_add, p - 1); + } + + return *this; + } + + query_base + operator&& (const query_base& x, const query_base& y) + { + // Optimize cases where one or both sides are constant truth. + // + bool xt (x.const_true ()), yt (y.const_true ()); + + if (xt && yt) + return x; + + if (xt || x.empty ()) + return y; + + if (yt || y.empty ()) + return x; + + query_base r (x); + r.append (y); + r.append (query_base::clause_part::op_and, x.clause ().size () - 1); + return r; + } + + query_base + operator|| (const query_base& x, const query_base& y) + { + if (x.empty ()) + return y; + + if (y.empty ()) + return x; + + query_base r (x); + r.append (y); + r.append (query_base::clause_part::op_or, x.clause ().size () - 1); + return r; + } + + query_base + operator! (const query_base& x) + { + if (x.empty ()) + return x; + + query_base r (x); + r.append (query_base::clause_part::op_not, 0); + return r; + } +} diff --git a/libodb/odb/query-dynamic.hxx b/libodb/odb/query-dynamic.hxx new file mode 100644 index 0000000..cd0ce05 --- /dev/null +++ b/libodb/odb/query-dynamic.hxx @@ -0,0 +1,1067 @@ +// file : odb/query-dynamic.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_QUERY_DYNAMIC_HXX +#define ODB_QUERY_DYNAMIC_HXX + +#include + +#include +#include +#include // std::size_t + +#include +#include + +#include +#include + +namespace odb +{ + struct native_column_info; + + template + struct val_bind + { + typedef const T& type; + + explicit + val_bind (type v): val (v) {} + + type val; + }; + + // Passing arrays by value in dynamic queries is not supported. + // Pass by reference instead. + // + template + struct val_bind; + + template + struct ref_bind + { + typedef const T& type; + + explicit + ref_bind (type r): ref (r) {} + + const void* + ptr () const {return &ref;} + + type ref; + }; + + template + struct ref_bind + { + typedef const T* type; + + explicit + ref_bind (type r): ref (r) {} + + // Allow implicit conversion from decayed ref_bind's. + // + ref_bind (ref_bind r): ref (r.ref) {} + ref_bind (ref_bind r): ref (r.ref) {} + + const void* + ptr () const {return ref;} + + type ref; + }; + + // + // + struct LIBODB_EXPORT query_param: details::shared_base + { + virtual ~query_param (); + query_param (const void* v): value (v) {} + + const void* value; + }; + + // For by-value parameters we have to make a copy since the original + // can be gone by the time we translate to native query. + // + template + struct val_query_param: query_param + { + val_query_param (const T& v): query_param (©), copy (v) {} + + T copy; + }; + + // + // + class LIBODB_EXPORT query_base + { + public: + // Internally the query clause is stored in a Reverse Polish Notation- + // like representation which also allows us to traverse it as a syntax + // tree. + // + // Let's keep this class POD so that std::vector can do more + // efficient copying, etc. + // + struct clause_part + { + // Note that the order of enumerators is important (used as indexes). + // + enum kind_type + { + kind_column, // native_info points to the native_column_info array. + + kind_param_val, // data points to query_param while native_info points + kind_param_ref, // to the native_column_info array. + + kind_native, // data is the index in the strings vector. + + kind_true, // true literal. + kind_false, // false literal. + + // Operators. + // + // For binary operators, data is the index of the last element + // belonging to the left hand side sub-expression. + // + op_add, // + (concatenation of two sub-expressions) + + op_and, // && + op_or, // || + op_not, // ! + + op_null, // is_null () + op_not_null, // is_not_null () + + op_in, // in(), data is the number of arguments + op_like, // like(pattern) + op_like_escape, // like(pattern, escape) + + op_eq, // == + op_ne, // != + op_lt, // < + op_gt, // > + op_le, // <= + op_ge // >= + }; + + kind_type kind; + std::size_t data; + const native_column_info* native_info; + }; + + public: + ~query_base () + { + clear (); + } + + query_base () {} + + // True or false literal. + // + explicit + query_base (bool v) + { + append (v ? clause_part::kind_true : clause_part::kind_false, 0); + } + + explicit + query_base (const char* native) + { + append (native); + } + + explicit + query_base (const std::string& native) + { + append (native); + } + + query_base (const query_column&); + + query_base (const query_base& x) + { + append (x); + } + + query_base& + operator= (const query_base& x) + { + if (this != &x) + { + clear (); + append (x); + } + + return *this; + } + + public: + template + static val_bind + _val (const T& x) + { + return val_bind (x); + } + + template + static ref_bind + _ref (const T& x) + { + return ref_bind (x); + } + + // Some compilers (notably VC++), when deducing const T& from const + // array do not strip const from the array type. As a result, in the + // above signatures we get, for example, T = const char[4] instead + // of T = char[4], which is what we want. So to "fix" such compilers, + // we will have to provide the following specialization of the above + // _ref() function (we don't need _val() since we don't support passing + // arrays by value; see val_bind definition). + // + template + static ref_bind + _ref (const T (&x) [N]) + { + return ref_bind (x); + } + + public: + query_base& + operator+= (const query_base&); + + query_base& + operator+= (const std::string& native); + + public: + bool + empty () const + { + return clause_.empty (); + } + + bool + const_true () const + { + return clause_.size () == 1 && + clause_.front ().kind == clause_part::kind_true; + } + + // Implementation details. + // + public: + explicit + query_base (const native_column_info* c) + { + append (c); + } + + // Native. + // + void + append (const std::string&); + + // Query fragment. + // + void + append (const query_base&); + + // Operator. + // + void + append (clause_part::kind_type k, std::size_t data) + { + clause_.push_back (clause_part ()); + clause_.back ().kind = k; + clause_.back ().data = data; + } + + // Column. + // + void + append (const native_column_info* c) + { + clause_.push_back (clause_part ()); + clause_.back ().kind = clause_part::kind_column; + clause_.back ().native_info = c; + } + + // Parameter. + // + void + append_ref (const void* ref, const native_column_info*); + + template + void + append_val (const T& val, const native_column_info*); + + void + clear (); + + public: + typedef std::vector clause_type; + typedef std::vector strings_type; + + const clause_type& + clause () const + { + return clause_; + } + + const strings_type& + strings () const + { + return strings_; + } + + private: + clause_type clause_; + strings_type strings_; + }; + + inline query_base + operator+ (const query_base& x, const query_base& y) + { + query_base r (x); + r += y; + return r; + } + + inline query_base + operator+ (const query_base& q, const std::string& s) + { + query_base r (q); + r += s; + return r; + } + + inline query_base + operator+ (const std::string& s, const query_base& q) + { + query_base r (s); + r += q; + return r; + } + + LIBODB_EXPORT query_base + operator&& (const query_base&, const query_base&); + + LIBODB_EXPORT query_base + operator|| (const query_base&, const query_base&); + + LIBODB_EXPORT query_base + operator! (const query_base&); + + // + // + struct native_column_info + { + const void* column; + void* param_factory; + }; + + template + const T& + type_instance (); + + // This class template has to remain POD since we rely on it being + // 0-initialized before any dynamic initialization takes place in + // any other translation unit. + // + template + struct query_column + { + // Array of pointers to database-specific columns. It will be + // automatically zero-initialized since query_column instances + // are always static. + // + native_column_info native_info[database_count]; + + // is_null, is_not_null + // + public: + query_base + is_null () const + { + query_base q (native_info); + q.append (query_base::clause_part::op_null, 0); + return q; + } + + query_base + is_not_null () const + { + query_base q (native_info); + q.append (query_base::clause_part::op_not_null, 0); + return q; + } + + // in + // + public: + query_base + in (const T&, const T&) const; + + query_base + in (const T&, const T&, const T&) const; + + query_base + in (const T&, const T&, const T&, const T&) const; + + query_base + in (const T&, const T&, const T&, const T&, const T&) const; + + template + query_base + in_range (I begin, I end) const; + + // like + // + public: + query_base + like (const T& pattern) const + { + return like (val_bind (pattern)); + } + + query_base + like (val_bind pattern) const; + + template + query_base + like (val_bind pattern) const + { + return like (val_bind (T (pattern.val))); + } + + query_base + like (ref_bind pattern) const; + + query_base + like (const T& pattern, const T& escape) const + { + return like (val_bind (pattern), escape); + } + + query_base + like (val_bind pattern, const T& escape) const; + + template + query_base + like (val_bind pattern, const T& escape) const + { + return like (val_bind (T (pattern.val)), escape); + } + + query_base + like (ref_bind pattern, const T& escape) const; + + // == + // + public: + query_base + equal (val_bind v) const + { + query_base q (native_info); + q.append_val (v.val, native_info); + q.append (query_base::clause_part::op_eq, 0); + return q; + } + + query_base + equal (ref_bind r) const + { + query_base q (native_info); + q.append_ref (r.ptr (), native_info); + q.append (query_base::clause_part::op_eq, 0); + return q; + } + + friend query_base + operator== (const query_column& c, const T& v) + { + return c.equal (val_bind (v)); + } + + friend query_base + operator== (const T& v, const query_column& c) + { + return c.equal (val_bind (v)); + } + + friend query_base + operator== (const query_column& c, val_bind v) + { + return c.equal (v); + } + + friend query_base + operator== (val_bind v, const query_column& c) + { + return c.equal (v); + } + + template + friend query_base + operator== (const query_column& c, val_bind v) + { + return c.equal (val_bind (T (v.val))); + } + + template + friend query_base + operator== (val_bind v, const query_column& c) + { + return c.equal (val_bind (T (v.val))); + } + + friend query_base + operator== (const query_column& c, ref_bind r) + { + return c.equal (r); + } + + friend query_base + operator== (ref_bind r, const query_column& c) + { + return c.equal (r); + } + + // != + // + public: + query_base + unequal (val_bind v) const + { + query_base q (native_info); + q.append_val (v.val, native_info); + q.append (query_base::clause_part::op_ne, 0); + return q; + } + + query_base + unequal (ref_bind r) const + { + query_base q (native_info); + q.append_ref (r.ptr (), native_info); + q.append (query_base::clause_part::op_ne, 0); + return q; + } + + friend query_base + operator!= (const query_column& c, const T& v) + { + return c.unequal (val_bind (v)); + } + + friend query_base + operator!= (const T& v, const query_column& c) + { + return c.unequal (val_bind (v)); + } + + friend query_base + operator!= (const query_column& c, val_bind v) + { + return c.unequal (v); + } + + friend query_base + operator!= (val_bind v, const query_column& c) + { + return c.unequal (v); + } + + template + friend query_base + operator!= (const query_column& c, val_bind v) + { + return c.unequal (val_bind (T (v.val))); + } + + template + friend query_base + operator!= (val_bind v, const query_column& c) + { + return c.unequal (val_bind (T (v.val))); + } + + friend query_base + operator!= (const query_column& c, ref_bind r) + { + return c.unequal (r); + } + + friend query_base + operator!= (ref_bind r, const query_column& c) + { + return c.unequal (r); + } + + // < + // + public: + query_base + less (val_bind v) const + { + query_base q (native_info); + q.append_val (v.val, native_info); + q.append (query_base::clause_part::op_lt, 0); + return q; + } + + query_base + less (ref_bind r) const + { + query_base q (native_info); + q.append_ref (r.ptr (), native_info); + q.append (query_base::clause_part::op_lt, 0); + return q; + } + + friend query_base + operator< (const query_column& c, const T& v) + { + return c.less (val_bind (v)); + } + + friend query_base + operator< (const T& v, const query_column& c) + { + return c.greater (val_bind (v)); + } + + friend query_base + operator< (const query_column& c, val_bind v) + { + return c.less (v); + } + + friend query_base + operator< (val_bind v, const query_column& c) + { + return c.greater (v); + } + + template + friend query_base + operator< (const query_column& c, val_bind v) + { + return c.less (val_bind (T (v.val))); + } + + template + friend query_base + operator< (val_bind v, const query_column& c) + { + return c.greater (val_bind (T (v.val))); + } + + friend query_base + operator< (const query_column& c, ref_bind r) + { + return c.less (r); + } + + friend query_base + operator< (ref_bind r, const query_column& c) + { + return c.greater (r); + } + + // > + // + public: + query_base + greater (val_bind v) const + { + query_base q (native_info); + q.append_val (v.val, native_info); + q.append (query_base::clause_part::op_gt, 0); + return q; + } + + query_base + greater (ref_bind r) const + { + query_base q (native_info); + q.append_ref (r.ptr (), native_info); + q.append (query_base::clause_part::op_gt, 0); + return q; + } + + friend query_base + operator> (const query_column& c, const T& v) + { + return c.greater (val_bind (v)); + } + + friend query_base + operator> (const T& v, const query_column& c) + { + return c.less (val_bind (v)); + } + + friend query_base + operator> (const query_column& c, val_bind v) + { + return c.greater (v); + } + + friend query_base + operator> (val_bind v, const query_column& c) + { + return c.less (v); + } + + template + friend query_base + operator> (const query_column& c, val_bind v) + { + return c.greater (val_bind (T (v.val))); + } + + template + friend query_base + operator> (val_bind v, const query_column& c) + { + return c.less (val_bind (T (v.val))); + } + + friend query_base + operator> (const query_column& c, ref_bind r) + { + return c.greater (r); + } + + friend query_base + operator> (ref_bind r, const query_column& c) + { + return c.less (r); + } + + // <= + // + public: + query_base + less_equal (val_bind v) const + { + query_base q (native_info); + q.append_val (v.val, native_info); + q.append (query_base::clause_part::op_le, 0); + return q; + } + + query_base + less_equal (ref_bind r) const + { + query_base q (native_info); + q.append_ref (r.ptr (), native_info); + q.append (query_base::clause_part::op_le, 0); + return q; + } + + friend query_base + operator<= (const query_column& c, const T& v) + { + return c.less_equal (val_bind (v)); + } + + friend query_base + operator<= (const T& v, const query_column& c) + { + return c.greater_equal (val_bind (v)); + } + + friend query_base + operator<= (const query_column& c, val_bind v) + { + return c.less_equal (v); + } + + friend query_base + operator<= (val_bind v, const query_column& c) + { + return c.greater_equal (v); + } + + template + friend query_base + operator<= (const query_column& c, val_bind v) + { + return c.less_equal (val_bind (T (v.val))); + } + + template + friend query_base + operator<= (val_bind v, const query_column& c) + { + return c.greater_equal (val_bind (T (v.val))); + } + + friend query_base + operator<= (const query_column& c, ref_bind r) + { + return c.less_equal (r); + } + + friend query_base + operator<= (ref_bind r, const query_column& c) + { + return c.greater_equal (r); + } + + // >= + // + public: + query_base + greater_equal (val_bind v) const + { + query_base q (native_info); + q.append_val (v.val, native_info); + q.append (query_base::clause_part::op_ge, 0); + return q; + } + + query_base + greater_equal (ref_bind r) const + { + query_base q (native_info); + q.append_ref (r.ptr (), native_info); + q.append (query_base::clause_part::op_ge, 0); + return q; + } + + friend query_base + operator>= (const query_column& c, const T& v) + { + return c.greater_equal (val_bind (v)); + } + + friend query_base + operator>= (const T& v, const query_column& c) + { + return c.less_equal (val_bind (v)); + } + + friend query_base + operator>= (const query_column& c, val_bind v) + { + return c.greater_equal (v); + } + + friend query_base + operator>= (val_bind v, const query_column& c) + { + return c.less_equal (v); + } + + template + friend query_base + operator>= (const query_column& c, val_bind v) + { + return c.greater_equal (val_bind (T (v.val))); + } + + template + friend query_base + operator>= (val_bind v, const query_column& c) + { + return c.less_equal (val_bind (T (v.val))); + } + + friend query_base + operator>= (const query_column& c, ref_bind r) + { + return c.greater_equal (r); + } + + friend query_base + operator>= (ref_bind r, const query_column& c) + { + return c.less_equal (r); + } + + // Column comparison. + // + public: + template + query_base + operator== (const query_column& c) const + { + // We can compare columns only if we can compare their C++ types. + // + (void) (sizeof (type_instance () == type_instance ())); + + query_base q (native_info); + q.append (c.native_info); + q.append (query_base::clause_part::op_eq, 0); + return q; + } + + template + query_base + operator!= (const query_column& c) const + { + // We can compare columns only if we can compare their C++ types. + // + (void) (sizeof (type_instance () != type_instance ())); + + query_base q (native_info); + q.append (c.native_info); + q.append (query_base::clause_part::op_ne, 0); + return q; + } + + template + query_base + operator< (const query_column& c) const + { + // We can compare columns only if we can compare their C++ types. + // + (void) (sizeof (type_instance () < type_instance ())); + + query_base q (native_info); + q.append (c.native_info); + q.append (query_base::clause_part::op_lt, 0); + return q; + } + + template + query_base + operator> (const query_column& c) const + { + // We can compare columns only if we can compare their C++ types. + // + (void) (sizeof (type_instance () > type_instance ())); + + query_base q (native_info); + q.append (c.native_info); + q.append (query_base::clause_part::op_gt, 0); + return q; + } + + template + query_base + operator<= (const query_column& c) const + { + // We can compare columns only if we can compare their C++ types. + // + (void) (sizeof (type_instance () <= type_instance ())); + + query_base q (native_info); + q.append (c.native_info); + q.append (query_base::clause_part::op_le, 0); + return q; + } + + template + query_base + operator>= (const query_column& c) const + { + // We can compare columns only if we can compare their C++ types. + // + (void) (sizeof (type_instance () >= type_instance ())); + + query_base q (native_info); + q.append (c.native_info); + q.append (query_base::clause_part::op_ge, 0); + return q; + } + }; + + // Provide operator+() for using columns to construct native + // query fragments (e.g., ORDER BY). + // + template + inline query_base + operator+ (const query_column& c, const std::string& s) + { + query_base q (c.native_info); + q.append (s); + q.append (query_base::clause_part::op_add, 0); + return q; + } + + template + inline query_base + operator+ (const std::string& s, const query_column& c) + { + query_base q (s); + q.append (c.native_info); + q.append (query_base::clause_part::op_add, 0); + return q; + } + + template + inline query_base + operator+ (const query_column& c, const query_base& q) + { + query_base r (c.native_info); + r.append (q); + r.append (query_base::clause_part::op_add, 0); + return r; + } + + template + inline query_base + operator+ (const query_base& q, const query_column& c) + { + query_base r (q); + r.append (c.native_info); + r.append (query_base::clause_part::op_add, q.clause ().size () - 1); + return r; + } + + // + // + template + class query: public query_base, + public query_selector::columns_type + { + public: + // We don't define any typedefs here since they may clash with + // column names defined by our base type. + // + + query () + { + } + + explicit + query (bool v) + : query_base (v) + { + } + + explicit + query (const char* q) + : query_base (q) + { + } + + explicit + query (const std::string& q) + : query_base (q) + { + } + + query (const query_base& q) + : query_base (q) + { + } + + query (const query_column& qc) + : query_base (qc) + { + } + }; +} + +#include +#include + +#include + +#endif // ODB_QUERY_DYNAMIC_HXX diff --git a/libodb/odb/query-dynamic.ixx b/libodb/odb/query-dynamic.ixx new file mode 100644 index 0000000..8de7b8e --- /dev/null +++ b/libodb/odb/query-dynamic.ixx @@ -0,0 +1,18 @@ +// file : odb/query-dynamic.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // query_base + // + inline query_base:: + query_base (const query_column& c) + { + // Some databases provide the IS TRUE operator. However, we cannot + // use it since the column type might now be SQL boolean type. + // + append (c.native_info); + append_val (true, c.native_info); + append (query_base::clause_part::op_eq, 0); + } +} diff --git a/libodb/odb/query-dynamic.txx b/libodb/odb/query-dynamic.txx new file mode 100644 index 0000000..9ea16d2 --- /dev/null +++ b/libodb/odb/query-dynamic.txx @@ -0,0 +1,139 @@ +// file : odb/query-dynamic.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // query_base + // + + template + void query_base:: + append_val (const T& val, const native_column_info* c) + { + clause_.push_back (clause_part ()); + clause_part& p (clause_.back ()); + + p.kind = clause_part::kind_param_val; + p.data = 0; // In case new below throws. + p.native_info = c; + + query_param* qp (new (details::shared) val_query_param (val)); + p.data = reinterpret_cast (qp); + } + + // + // query_column + // + + // in + // + template + query_base query_column:: + in (const T& v1, const T& v2) const + { + query_base q (native_info); + q.append_val (v1, native_info); + q.append_val (v2, native_info); + q.append (query_base::clause_part::op_in, 2); + return q; + } + + template + query_base query_column:: + in (const T& v1, const T& v2, const T& v3) const + { + query_base q (native_info); + q.append_val (v1, native_info); + q.append_val (v2, native_info); + q.append_val (v3, native_info); + q.append (query_base::clause_part::op_in, 3); + return q; + } + + template + query_base query_column:: + in (const T& v1, const T& v2, const T& v3, const T& v4) const + { + query_base q (native_info); + q.append_val (v1, native_info); + q.append_val (v2, native_info); + q.append_val (v3, native_info); + q.append_val (v4, native_info); + q.append (query_base::clause_part::op_in, 4); + return q; + } + + template + query_base query_column:: + in (const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) const + { + query_base q (native_info); + q.append_val (v1, native_info); + q.append_val (v2, native_info); + q.append_val (v3, native_info); + q.append_val (v4, native_info); + q.append_val (v5, native_info); + q.append (query_base::clause_part::op_in, 5); + return q; + } + + template + template + query_base query_column:: + in_range (I i, I end) const + { + query_base q (native_info); + + std::size_t n (0); + for (; i != end; ++i, ++n) + q.append_val (*i, native_info); // Force implicit conversion. + + q.append (query_base::clause_part::op_in, n); + return q; + } + + // like + // + template + query_base query_column:: + like (val_bind p) const + { + query_base q (native_info); + q.append_val (p.val, native_info); + q.append (query_base::clause_part::op_like, 0); + return q; + } + + template + query_base query_column:: + like (ref_bind p) const + { + query_base q (native_info); + q.append_ref (p.ptr (), native_info); + q.append (query_base::clause_part::op_like, 0); + return q; + } + + template + query_base query_column:: + like (val_bind p, const T& e) const + { + query_base q (native_info); + q.append_val (p.val, native_info); + q.append_val (e, native_info); + q.append (query_base::clause_part::op_like_escape, 0); + return q; + } + + template + query_base query_column:: + like (ref_bind p, const T& e) const + { + query_base q (native_info); + q.append_ref (p.ptr (), native_info); + q.append_val (e, native_info); + q.append (query_base::clause_part::op_like_escape, 0); + return q; + } +} diff --git a/libodb/odb/query.hxx b/libodb/odb/query.hxx new file mode 100644 index 0000000..9375738 --- /dev/null +++ b/libodb/odb/query.hxx @@ -0,0 +1,119 @@ +// file : odb/query.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_QUERY_HXX +#define ODB_QUERY_HXX + +#include + +#include +#include + +namespace odb +{ + // Table alias for type T and tag Tag. + // + // The alias_traits interface consists of two things: the table_name + // static variable containing the name and, in case of a derived type + // in a polymorphic hierarchy, the base_traits typedef. Note that the + // same interface is exposed by object_traits, which is used when + // we need straight tables instead of aliases. + // + // + template + struct alias_traits; + + template + struct query_columns_base; + + template + struct query_columns; + + template + struct pointer_query_columns; + + // Object pointer syntax wrapper. + // + template + struct query_pointer + { + query_pointer () + { + // For some reason GCC needs this dummy c-tor if we make a static + // data member of this type const. + } + + T* + operator-> () const + { + return 0; // All members in T are static. + } + }; + + // Query parameter decay traits. + // + template + struct decay_traits + { + typedef const T& type; + + static type + instance (); + }; + + template + struct decay_traits + { + typedef const T* type; + + // Use the pointer comparability as a proxy for data comparability. + // Note that it is stricter than using element comparability (i.e., + // one can compare int to char but not int* to char*). + // + static type + instance (); + }; + + // VC9 cannot handle certain cases of non-type arguments with default + // values in template functions (e.g., database::query()). As a result, + // we have to use the impl trick below instead of simply having kind + // as a second template argument with a default value. + // + template + struct query_selector_impl; + + template + struct query_selector_impl + { + typedef typename object_traits_impl::query_base_type base_type; + + typedef + query_columns > + columns_type; + }; + + template + struct query_selector_impl + { + typedef typename view_traits_impl::query_base_type base_type; + typedef typename view_traits_impl::query_columns columns_type; + }; + + template + struct query_selector: query_selector_impl::kind> + { + }; + + template ::base_type> + class query; + + namespace core + { + using odb::query; + } +} + +#include + +#endif // ODB_QUERY_HXX diff --git a/libodb/odb/result.cxx b/libodb/odb/result.cxx new file mode 100644 index 0000000..e9393ca --- /dev/null +++ b/libodb/odb/result.cxx @@ -0,0 +1,40 @@ +// file : odb/result.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +namespace odb +{ + result_impl:: + ~result_impl () + { + if (next_ != this) + list_remove (); + } + + result_impl:: + result_impl (connection& c) + : db_ (c.database ()), conn_ (c), prev_ (0), next_ (this) + { + // Add to the list. + // + next_ = conn_.results_; + conn_.results_ = this; + + if (next_ != 0) + next_->prev_ = this; + } + + void result_impl:: + list_remove () + { + (prev_ == 0 ? conn_.results_ : prev_->next_) = next_; + + if (next_ != 0) + next_->prev_ = prev_; + + prev_ = 0; + next_ = this; + } +} diff --git a/libodb/odb/result.hxx b/libodb/odb/result.hxx new file mode 100644 index 0000000..87a6869 --- /dev/null +++ b/libodb/odb/result.hxx @@ -0,0 +1,247 @@ +// file : odb/result.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_RESULT_HXX +#define ODB_RESULT_HXX + +#include + +#include // std::ptrdiff_t, std::size_t + +#include // odb::core +#include + +#include +#include + +namespace odb +{ + class LIBODB_EXPORT result_impl: public details::shared_base + { + public: + virtual + ~result_impl (); + + virtual void + invalidate () = 0; + + protected: + result_impl (connection&); + + protected: + database& db_; + connection& conn_; + + // Doubly-linked list of results. + // + // prev_ == 0 means we are the first element. + // next_ == 0 means we are the last element. + // next_ == this means we are not on the list. + // + protected: + friend class connection; + + void + list_remove (); + + result_impl* prev_; + result_impl* next_; + }; + + template + class result_base; + + template ::kind> + class result_iterator; + + // Input iterator requirements. + // + template + inline bool + operator== (result_iterator i, result_iterator j) + { + return i.equal (j); + } + + template + inline bool + operator!= (result_iterator i, result_iterator j) + { + return !i.equal (j); + } + + template + class result: result_base::kind> + { + public: + static const class_kind kind = class_traits::kind; + + typedef result_base base; + + typedef typename base::value_type value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef result_iterator iterator; + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef typename base::result_impl_type result_impl_type; + + public: + result () + { + } + + explicit + result (details::shared_ptr impl) + : impl_ (impl) + { + } + + // Copying or assignment of a result instance leads to one instance + // being an alias for another. Think of copying a result as copying + // a file handle -- the file you access through either of them is + // still the same. + // + public: + result (const result& r) + : impl_ (r.impl_) + { + } + + result& + operator= (const result& r) + { + if (impl_ != r.impl_) + impl_ = r.impl_; + + return *this; + } + + // Conversion from result to result. + // + template + result (const result& r) + // + // If you get a compiler error pointing to the line below saying + // that the impl_ member is inaccessible, then you are most likely + // trying to perform an illegal result conversion, for example, + // from result to result. + // + : impl_ (r.impl_) + { + } + + template + result& + operator= (const result& r) + { + // If you get a compiler error pointing to the line below saying + // that the impl_ member is inaccessible, then you are most likely + // trying to perform an illegal result conversion, for example, + // from result to result. + // + if (impl_ != r.impl_) + impl_ = r.impl_; + + return *this; + } + + void + swap (result& r) + { + // @@ add swap() to shared_ptr. + // + details::shared_ptr p (impl_); + impl_ = r.impl_; + r.impl_ = p; + } + + public: + iterator + begin () + { + if (impl_) + impl_->begin (); + + return iterator (impl_.get ()); + } + + iterator + end () + { + return iterator (); + } + + // Cache the result instead of fetching the data from the database + // one row at a time. This is necessary if you plan on performing + // database operations while iterating over the result. + // + public: + void + cache () + { + if (impl_) + impl_->cache (); + } + + public: + bool + empty () const + { + if (impl_ == 0) + return true; + + impl_->begin (); + return impl_->end (); + } + + // Size is only known in cached results. + // + size_type + size () const + { + return impl_ ? impl_->size () : 0; + } + + // query_one() and query_value() implementation details. + // + public: + typedef typename iterator::pointer_type pointer_type; + + pointer_type + one (); + + bool + one (T&); + + // We cannot return by value here since result can be instantiated + // for an abstract type (polymorphic abstract base) and it seems + // the signature must be valid to the point being able to call the + // necessary constructors. + // + void + value (T&); + + private: + friend class result; + + details::shared_ptr impl_; + }; + + namespace common + { + using odb::result; + using odb::result_iterator; + } +} + +#include + +#include + +#endif // ODB_RESULT_HXX diff --git a/libodb/odb/result.txx b/libodb/odb/result.txx new file mode 100644 index 0000000..b69d92a --- /dev/null +++ b/libodb/odb/result.txx @@ -0,0 +1,49 @@ +// file : odb/result.txx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + template + typename result::pointer_type result:: + one () + { + iterator i (begin ()); + + if (i != end ()) + { + pointer_type o (i.load ()); + assert (++i == end ()); // More than one element in query_one() result. + return o; + } + + return pointer_type (); + } + + template + bool result:: + one (T& o) + { + iterator i (begin ()); + + if (i != end ()) + { + i.load (o); + assert (++i == end ()); // More than one element in query_one() result. + return true; + } + + return false; + } + + template + void result:: + value (T& o) + { + iterator i (begin ()); + assert (i != end ()); // Zero elements in query_value() result. + i.load (o); + assert (++i == end ()); // More than one element in query_value() result. + } +} diff --git a/libodb/odb/schema-catalog-impl.hxx b/libodb/odb/schema-catalog-impl.hxx new file mode 100644 index 0000000..dd729db --- /dev/null +++ b/libodb/odb/schema-catalog-impl.hxx @@ -0,0 +1,54 @@ +// file : odb/schema-catalog-impl.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SCHEMA_CATALOG_IMPL_HXX +#define ODB_SCHEMA_CATALOG_IMPL_HXX + +#include + +#include + +#include // schema_version + +#include + +namespace odb +{ + struct schema_catalog_impl; + + // Translation unit initializer. + // + struct LIBODB_EXPORT schema_catalog_init + { + static schema_catalog_impl* catalog; + static std::size_t count; + + schema_catalog_init (); + ~schema_catalog_init (); + }; + + static const schema_catalog_init schema_catalog_init_; + + // Catalog entry registration. + // + struct LIBODB_EXPORT schema_catalog_create_entry + { + schema_catalog_create_entry ( + database_id, + const char* name, + bool (*create_function) (database&, unsigned short pass, bool drop)); + }; + + struct LIBODB_EXPORT schema_catalog_migrate_entry + { + schema_catalog_migrate_entry ( + database_id, + const char* name, + schema_version, + bool (*migrate_function) (database&, unsigned short pass, bool pre)); + }; +} + +#include + +#endif // ODB_SCHEMA_CATALOG_IMPL_HXX diff --git a/libodb/odb/schema-catalog.cxx b/libodb/odb/schema-catalog.cxx new file mode 100644 index 0000000..1bdc112 --- /dev/null +++ b/libodb/odb/schema-catalog.cxx @@ -0,0 +1,387 @@ +// file : odb/schema-catalog.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include +#include + +#include +#include +#include + +using namespace std; + +namespace odb +{ + // Schema. + // + typedef bool (*create_function) (database&, unsigned short pass, bool drop); + typedef bool (*migrate_function) (database&, unsigned short pass, bool pre); + + typedef pair key; + typedef vector create_functions; + typedef vector migrate_functions; + typedef map version_map; + + struct schema_functions + { + create_functions create; + version_map migrate; + }; + typedef map schema_map; + + // Data. Normally the code would be database-independent, though there + // could be database-specific migration steps. + // + typedef pair data_key; + + struct data_function + { + typedef schema_catalog::data_migration_function_wrapper + function_wrapper_type; + + data_function () {} + data_function (database_id i, function_wrapper_type m) + : id (i), migrate (m) {} + + database_id id; + function_wrapper_type migrate; + }; + typedef vector data_functions; + typedef map data_map; + + struct schema_catalog_impl + { + schema_map schema; + data_map data; + }; + + // Static initialization. + // + schema_catalog_impl* schema_catalog_init::catalog = 0; + size_t schema_catalog_init::count = 0; + + struct schema_catalog_init_extra + { + bool initialized; + + schema_catalog_init_extra (): initialized (false) {} + ~schema_catalog_init_extra () + { + if (initialized && --schema_catalog_init::count == 0) + delete schema_catalog_init::catalog; + } + }; + + static schema_catalog_init_extra schema_catalog_init_extra_; + + bool schema_catalog:: + exists (database_id id, const string& name) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + return c.schema.find (key (id, name)) != c.schema.end (); + } + + void schema_catalog:: + create_schema (database& db, const string& name, bool drop) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_map::const_iterator i (c.schema.find (key (db.id (), name))); + + if (i == c.schema.end ()) + throw unknown_schema (name); + + const create_functions& fs (i->second.create); + + if (drop) + drop_schema (db, name); + + // Run the passes until we ran them all or all the functions + // return false, which means no more passes necessary. + // + for (unsigned short pass (1); pass < 3; ++pass) + { + bool done (true); + + for (create_functions::const_iterator j (fs.begin ()), e (fs.end ()); + j != e; ++j) + { + if ((*j) (db, pass, false)) + done = false; + } + + if (done) + break; + } + } + + void schema_catalog:: + drop_schema (database& db, const string& name) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_map::const_iterator i (c.schema.find (key (db.id (), name))); + + if (i == c.schema.end ()) + throw unknown_schema (name); + + const create_functions& fs (i->second.create); + + // Run the passes until we ran them all or all the functions + // return false, which means no more passes necessary. + // + for (unsigned short pass (1); pass < 3; ++pass) + { + bool done (true); + + for (create_functions::const_iterator j (fs.begin ()), e (fs.end ()); + j != e; ++j) + { + if ((*j) (db, pass, true)) + done = false; + } + + if (done) + break; + } + } + + void schema_catalog:: + migrate_schema_impl (database& db, + schema_version v, + const string& name, + migrate_mode m) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_map::const_iterator i (c.schema.find (key (db.id (), name))); + + if (i == c.schema.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); + version_map::const_iterator j (vm.find (v)); + + if (j == vm.end ()) + throw unknown_schema_version (v); + + const migrate_functions& fs (j->second); + + // Run the passes until we ran them all or all the functions + // return false, which means no more passes necessary. + // + for (bool pre (m != migrate_post);; pre = false) + { + for (unsigned short pass (1); pass < 3; ++pass) + { + bool done (true); + + for (migrate_functions::const_iterator i (fs.begin ()), e (fs.end ()); + i != e; ++i) + { + if ((*i) (db, pass, pre)) + done = false; + } + + if (done) + break; + } + + if (!pre || m != migrate_both) + break; + } + + // Update the schema version on the database instance. + // + db.schema_version_migration (v, m == migrate_pre, name); + } + + size_t schema_catalog:: + migrate_data (database& db, schema_version v, const string& name) + { + if (v == 0) + { + if (!db.schema_migration ()) + return 0; + + v = db.schema_version (); + } + + const schema_catalog_impl& c (*schema_catalog_init::catalog); + data_map::const_iterator i (c.data.find (data_key (name, v))); + + if (i == c.data.end ()) + return 0; // No data migration for this schema/version. + + size_t r (0); + + const data_functions& df (i->second); + for (data_functions::const_iterator i (df.begin ()), e (df.end ()); + i != e; ++i) + { + if (i->id == id_common || i->id == db.id ()) + { + const data_migration_function_wrapper &m = i->migrate; + + if (m.std_function == 0) + m.function (db); + else + { + typedef void (*caller) (const void*, database&); + m.cast () (m.std_function, db); + } + r++; + } + } + + return r; + } + + void schema_catalog:: + data_migration_function (database_id id, + schema_version v, + data_migration_function_wrapper f, + const string& name) + { + // This function can be called from a static initializer in which + // case the catalog might not have yet been created. + // + if (schema_catalog_init::count == 0) + { + schema_catalog_init::catalog = new schema_catalog_impl; + ++schema_catalog_init::count; + schema_catalog_init_extra_.initialized = true; + } + + schema_catalog_impl& c (*schema_catalog_init::catalog); + c.data[data_key (name, v)].push_back (data_function (id, f)); + } + + void schema_catalog:: + migrate (database& db, schema_version v, const string& name) + { + schema_version cur (current_version (db, name)); + + if (v == 0) + v = cur; + else if (v > cur) + throw unknown_schema_version (v); + + schema_version i (db.schema_version (name)); + + if (i > v) + throw unknown_schema_version (i); // Database too new. + + // If there is no schema, then "migrate" by creating it. + // + if (i == 0) + { + // Schema creation can only "migrate" straight to current. + // + if (v != cur) + throw unknown_schema_version (v); + + create_schema (db, name, false); + return; + } + + for (i = next_version (db, i, name); + i <= v; + i = next_version (db, i, name)) + { + migrate_schema_pre (db, i, name); + migrate_data (db, i, name); + migrate_schema_post (db, i, name); + } + } + + schema_version schema_catalog:: + base_version (database_id id, const string& name) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_map::const_iterator i (c.schema.find (key (id, name))); + + if (i == c.schema.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); + assert (!vm.empty ()); + return vm.begin ()->first; + } + + schema_version schema_catalog:: + current_version (database_id id, const string& name) + { + const schema_catalog_impl& c (*schema_catalog_init::catalog); + schema_map::const_iterator i (c.schema.find (key (id, name))); + + if (i == c.schema.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); + assert (!vm.empty ()); + return vm.rbegin ()->first; + } + + schema_version schema_catalog:: + next_version (database_id id, schema_version v, const string& name) + { + const schema_catalog_impl& sc (*schema_catalog_init::catalog); + schema_map::const_iterator i (sc.schema.find (key (id, name))); + + if (i == sc.schema.end ()) + throw unknown_schema (name); + + const version_map& vm (i->second.migrate); // Cannot be empty. + + schema_version b (vm.begin ()->first); + schema_version c (vm.rbegin ()->first); + + if (v == 0) + return c; // "Migration" to the current via schema creation. + else if (v < b) + throw unknown_schema_version (v); // Unsupported migration. + + version_map::const_iterator j (vm.upper_bound (v)); + return j != vm.end () ? j->first : c + 1; + } + + // schema_catalog_init + // + schema_catalog_init:: + schema_catalog_init () + { + if (count == 0) + catalog = new schema_catalog_impl; + + ++count; + } + + schema_catalog_init:: + ~schema_catalog_init () + { + if (--count == 0) + delete catalog; + } + + // schema_catalog_create_entry + // + schema_catalog_create_entry:: + schema_catalog_create_entry (database_id id, + const char* name, + create_function cf) + { + schema_catalog_impl& c (*schema_catalog_init::catalog); + c.schema[key(id, name)].create.push_back (cf); + } + + // schema_catalog_migrate_entry + // + schema_catalog_migrate_entry:: + schema_catalog_migrate_entry (database_id id, + const char* name, + schema_version v, + migrate_function mf) + { + schema_catalog_impl& c (*schema_catalog_init::catalog); + c.schema[key(id, name)].migrate[v].push_back (mf); + } +} diff --git a/libodb/odb/schema-catalog.hxx b/libodb/odb/schema-catalog.hxx new file mode 100644 index 0000000..c38cd4f --- /dev/null +++ b/libodb/odb/schema-catalog.hxx @@ -0,0 +1,392 @@ +// file : odb/schema-catalog.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SCHEMA_CATALOG_HXX +#define ODB_SCHEMA_CATALOG_HXX + +#include + +#include // ODB_CXX11 + +#include +#include // std::size_t + +#ifdef ODB_CXX11 +# include // std::move +# include // std::function +# include // std::enable_if, std::is_convertible +#endif + +#include // schema_version, odb::core +#include + +#include +#include +#include + +namespace odb +{ + class LIBODB_EXPORT schema_catalog + { + public: + // Schema creation. + // + static void + create_schema (database&, const std::string& name = "", bool drop = true); + + static void + drop_schema (database&, const std::string& name = ""); + + // Schema migration. + // + public: + static void + migrate_schema_pre (database& db, + schema_version v, + const std::string& name = "") + { + migrate_schema_impl (db, v, name, migrate_pre); + } + + static void + migrate_schema_post (database& db, + schema_version v, + const std::string& name = "") + { + migrate_schema_impl (db, v, name, migrate_post); + } + + static void + migrate_schema (database& db, + schema_version v, + const std::string& name = "") + { + migrate_schema_impl (db, v, name, migrate_both); + } + + // Data migration. + // + public: + // If version is 0, then use the current database version and also + // check whether we are in migration. Returns the number of calls made. + // + static std::size_t + migrate_data (database&, + schema_version = 0, + const std::string& name = ""); + + typedef void data_migration_function_type (database&); + typedef data_migration_function_type* data_migration_function_ptr; + + typedef details::function_wrapper + data_migration_function_wrapper; + + // The following three variants of the registration functions make + // sure that the version is greater that the base model version. + // This helps with identifying and removing data migration function + // that are no longer required. + // + // Data migration functions are called in the order of registration. + // +#ifndef ODB_CXX11 + template + static void + data_migration_function (data_migration_function_ptr f, + const std::string& name = "") + { + data_migration_function (id_common, f, name); + } + +#else + template + static typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + data_migration_function (F f, const std::string& name = "") + { + data_migration_function (id_common, std::move (f), name); + } +#endif + + // Database-specific data migration. + // +#ifndef ODB_CXX11 + template + static void + data_migration_function (database& db, + data_migration_function_ptr f, + const std::string& name = "") + { + data_migration_function (db.id (), f, name); + } +#else + template + static typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + data_migration_function (database& db, F f, const std::string& name = "") + { + data_migration_function (db.id (), std::move (f), name); + } +#endif + +#ifndef ODB_CXX11 + template + static void + data_migration_function (database_id id, + data_migration_function_ptr f, + const std::string& name = "") + { + // If the data migration version is below the base model version + // then it will never be called. + // + + // Poor man's static_assert. + // + typedef details::meta::static_assert_test<(v > base || base == 0)> + data_migration_function_is_no_longer_necessary; + + char sa [sizeof (data_migration_function_is_no_longer_necessary)]; + ODB_POTENTIALLY_UNUSED (sa); + + data_migration_function (id, v, f, name); + } +#else + template + static typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + data_migration_function (database_id id, F f, const std::string& name = "") + { + // If the data migration version is below the base model version + // then it will never be called. + // + static_assert (v > base || base == 0, + "data migration function is no longer necessary"); + + data_migration_function (id, v, std::move (f), name); + } +#endif + + // The same as above but take the version as an argument and do + // not check whether it is greater than the base model version. + // +#ifndef ODB_CXX11 + static void + data_migration_function (schema_version v, + data_migration_function_ptr f, + const std::string& name = "") + { + data_migration_function (id_common, v, f, name); + } +#else + template + static typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + data_migration_function (schema_version v, + F f, + const std::string& name = "") + { + data_migration_function (id_common, v, std::move (f), name); + } +#endif + +#ifndef ODB_CXX11 + static void + data_migration_function (database& db, + schema_version v, + data_migration_function_ptr f, + const std::string& name = "") + { + data_migration_function (db.id (), v, f, name); + } +#else + template + static typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + data_migration_function (database& db, + schema_version v, + F f, + const std::string& name = "") + { + data_migration_function (db.id (), v, std::move (f), name); + } +#endif + +#ifndef ODB_CXX11 + static void + data_migration_function (database_id i, + schema_version v, + data_migration_function_ptr f, + const std::string& name = "") + { + data_migration_function (i, + v, + data_migration_function_wrapper (f), + name); + } +#else + template + static typename std::enable_if< + std::is_convertible< + F, std::function>::value, void>::type + data_migration_function (database_id i, + schema_version v, + F f, + const std::string& name = "") + { + data_migration_function ( + i, + v, + data_migration_function_wrapper (std::move (f)), + name); + } +#endif + + private: + static void + data_migration_function (database_id, + schema_version, + data_migration_function_wrapper, + const std::string& name); + + // Combined schema and data migration. + // + public: + // Migrate both schema and data to the specified version. If version + // is not specified, then migrate to the current model version. + // + static void + migrate (database&, schema_version = 0, const std::string& name = ""); + + // Schema version information. + // + public: + // Return the base model version. + // + static schema_version + base_version (const database& db, const std::string& name = "") + { + return base_version (db.id (), name); + } + + static schema_version + base_version (database_id, const std::string& name = ""); + + // Return the current model version. + // + static schema_version + current_version (const database& db, const std::string& name = "") + { + return current_version (db.id (), name); + } + + static schema_version + current_version (database_id, const std::string& name = ""); + + // Return current model version + 1 (that is, one past current) if + // the passed version is equal to or greater than current. If the + // version is not specified, then use the current database version. + // + static schema_version + next_version (const database& db, + schema_version v = 0, + const std::string& name = "") + { + return next_version (db.id (), v == 0 ? db.schema_version () : v, name); + } + + static schema_version + next_version (database_id, + schema_version, + const std::string& name = ""); + + // Schema existence. + // + public: + // Test for presence of a schema with a specific name. + // + static bool + exists (const database& db, const std::string& name = "") + { + return exists (db.id (), name); + } + + static bool + exists (database_id, const std::string& name = ""); + + private: + enum migrate_mode + { + migrate_pre, + migrate_post, + migrate_both + }; + + static void + migrate_schema_impl (database&, + schema_version, + const std::string& name, + migrate_mode); + }; + + // Static data migration function registration. + // + template + struct data_migration_entry + { + typedef schema_catalog::data_migration_function_type function_type; + +#ifndef ODB_CXX11 + data_migration_entry (function_type* f, const std::string& name = "") + { + schema_catalog::data_migration_function (f, name); + } +#else + template + data_migration_entry (F f, + const std::string& name = "", + typename std::enable_if>::value> + ::type* = 0) + { + schema_catalog::data_migration_function (std::move (f), name); + } +#endif + +#ifndef ODB_CXX11 + data_migration_entry (database_id id, + function_type *f, + const std::string& name = "") + { + schema_catalog::data_migration_function (id, v, f, name); + } +#else + template + data_migration_entry (database_id id, + F f, + const std::string& name = "", + typename std::enable_if>::value> + ::type* = 0) + { + schema_catalog::data_migration_function (id, + v, + std::move (f), + name); + } +#endif + }; + + namespace common + { + using odb::schema_catalog; + using odb::data_migration_entry; + } +} + +#include + +#endif // ODB_SCHEMA_CATALOG_HXX diff --git a/libodb/odb/schema-version.hxx b/libodb/odb/schema-version.hxx new file mode 100644 index 0000000..1f047a4 --- /dev/null +++ b/libodb/odb/schema-version.hxx @@ -0,0 +1,71 @@ +// file : odb/schema-version.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SCHEMA_VERSION_HXX +#define ODB_SCHEMA_VERSION_HXX + +#include + +#include // schema_version + +namespace odb +{ + struct schema_version_migration + { + schema_version_migration (schema_version v = 0, bool m = false) + : version (v), migration (m) {} + + schema_version version; + bool migration; + }; + + // Version ordering is as follows: {1,f} < {2,t} < {2,f} < {3,t} + // + inline bool + operator== (const schema_version_migration& x, + const schema_version_migration& y) + { + return x.version == y.version && x.migration == y.migration; + } + + inline bool + operator!= (const schema_version_migration& x, + const schema_version_migration& y) + { + return !(x == y); + } + + inline bool + operator< (const schema_version_migration& x, + const schema_version_migration& y) + { + return x.version < y.version || + (x.version == y.version && x.migration && !y.migration); + } + + inline bool + operator> (const schema_version_migration& x, + const schema_version_migration& y) + { + return x.version > y.version || + (x.version == y.version && !x.migration && y.migration); + } + + inline bool + operator<= (const schema_version_migration& x, + const schema_version_migration& y) + { + return !(x > y); + } + + inline bool + operator>= (const schema_version_migration& x, + const schema_version_migration& y) + { + return !(x < y); + } +} + +#include + +#endif // ODB_SCHEMA_VERSION_HXX diff --git a/libodb/odb/section.cxx b/libodb/odb/section.cxx new file mode 100644 index 0000000..0fe5211 --- /dev/null +++ b/libodb/odb/section.cxx @@ -0,0 +1,27 @@ +// file : odb/section.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + void section:: + disarm () + { + transaction& t (transaction::current ()); + t.callback_unregister (this); + state_.armed = 0; + } + + void section:: + transacion_callback (unsigned short event, void* key, unsigned long long) + { + section& s (*static_cast (key)); + + if (event == transaction::event_rollback && s.state_.restore) + s.state_.changed = 1; + + s.state_.armed = 0; + s.state_.restore = 0; + } +} diff --git a/libodb/odb/section.hxx b/libodb/odb/section.hxx new file mode 100644 index 0000000..98b98cf --- /dev/null +++ b/libodb/odb/section.hxx @@ -0,0 +1,122 @@ +// file : odb/section.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SECTION_HXX +#define ODB_SECTION_HXX + +#include + +#include +#include + +namespace odb +{ + class LIBODB_EXPORT section + { + public: + // Load state. + // + bool + loaded () const {return state_.loaded;} + + // Mark a loaded section as not loaded. This, for example, can be + // useful if you don't want the section to be reloaded during the + // object reload. + // + void + unload () + { + state_.loaded = 0; + state_.changed = 0; + state_.restore = 0; + } + + // Mark an unloaded section as loaded. This, for example, can be useful if + // you don't want to load the old data before overwriting it with update(). + // + void + load () + { + state_.loaded = 1; + } + + // Change state. + // + bool + changed () const {return state_.changed;} + + // Mark the section as changed. + // + void + change () + { + state_.changed = 1; + state_.restore = 0; + } + + // User data. 4 bits of custom state. + // + unsigned char + user_data () const {return state_.user;} + + void + user_data (unsigned char u) {state_.user = u;} + + public: + section () + { + state_.loaded = 0; + state_.changed = 0; + state_.armed = 0; + state_.restore = 0; + } + + ~section () + { + if (state_.armed) + disarm (); + } + + // Implementation details. + // + public: + // Arm the callback and set the restore flag if transaction is not NULL. + // + void + reset (bool l = false, bool c = false, transaction* t = 0) const + { + state_.loaded = l; + state_.changed = c; + + if (t != 0 && !state_.armed) + { + t->callback_register (&transacion_callback, + const_cast (this)); + state_.armed = 1; + } + + state_.restore = (t != 0); + } + + private: + void + disarm (); + + static void + transacion_callback (unsigned short, void* key, unsigned long long); + + private: + mutable struct + { + unsigned char loaded : 1; + unsigned char changed : 1; + unsigned char armed : 1; // Transaction callback is armed. + unsigned char restore: 1; // Restore changed flag on rollback. + unsigned char user : 4; // User data. + } state_; + }; +} + +#include + +#endif // ODB_SECTION_HXX diff --git a/libodb/odb/session.cxx b/libodb/odb/session.cxx new file mode 100644 index 0000000..bc0e854 --- /dev/null +++ b/libodb/odb/session.cxx @@ -0,0 +1,66 @@ +// file : odb/session.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +#include + +namespace odb +{ + using namespace details; + + static ODB_TLS_POINTER (session) current_session; + + session:: + session (bool make_current) + { + if (make_current) + { + if (has_current ()) + throw already_in_session (); + + current_pointer (this); + } + } + + session:: + ~session () + { + // If we are the current thread's session, reset it. + // + if (current_pointer () == this) + reset_current (); + } + + session* session:: + current_pointer () + { + return tls_get (current_session); + } + + void session:: + current_pointer (session* s) + { + tls_set (current_session, s); + } + + session& session:: + current () + { + session* cur (tls_get (current_session)); + + if (cur == 0) + throw not_in_session (); + + return *cur; + } + + // + // object_map_base + // + session::object_map_base:: + ~object_map_base () + { + } +} diff --git a/libodb/odb/session.hxx b/libodb/odb/session.hxx new file mode 100644 index 0000000..a14c42f --- /dev/null +++ b/libodb/odb/session.hxx @@ -0,0 +1,217 @@ +// file : odb/session.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SESSION_HXX +#define ODB_SESSION_HXX + +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +namespace odb +{ + class LIBODB_EXPORT session + { + public: + typedef odb::database database_type; + + // If the make_current argument is true, then set the current thread's + // session to this session. If another session is already in effect, + // throw the already_in_session exception. + // + session (bool make_current = true); + + // Reset the current thread's session if it is this session. + // + ~session (); + + // Current session. + // + public: + // Return true if there is a session in effect in the current + // thread. + // + static bool + has_current () {return current_pointer () != 0;} + + // Get current thread's session. Throw if no session is in effect. + // + static session& + current (); + + // Set current thread's session. + // + static void + current (session& s) {current_pointer (&s);} + + // Revert to the no session in effect state for the current thread. + // + static void + reset_current () {current_pointer (0);} + + // Pointer versions. + // + static session* + current_pointer (); + + static void + current_pointer (session*); + + // Copying or assignment of sessions is not supported. + // + private: + session (const session&); + session& operator= (const session&); + + public: + struct LIBODB_EXPORT object_map_base: details::shared_base + { + virtual + ~object_map_base (); + }; + + template + struct object_map: object_map_base, + std::map::id_type, + typename object_traits::pointer_type> + { + }; + + // Object cache. + // + public: + // Position in the cache of the inserted element. + // + template + struct cache_position; + + template + cache_position + cache_insert (database_type&, + const typename object_traits::id_type&, + const typename object_traits::pointer_type&); + + template + typename object_traits::pointer_type + cache_find (database_type&, + const typename object_traits::id_type&) const; + + template + void + cache_erase (const cache_position&); + + template + void + cache_erase (database_type&, const typename object_traits::id_type&); + + // Low-level object cache access (iteration, etc). + // + public: + typedef std::map, + details::type_info_comparator> type_map; + + typedef std::map database_map; + + database_map& + map () {return db_map_;} + + const database_map& + map () const {return db_map_;} + + // Static cache API as expected by the rest of ODB. + // + public: + static bool + _has_cache () {return has_current ();} + + // Position in the cache of the inserted element. The requirements + // for this class template are: default and copy-constructible as + // well as copy-assignable. The default constructor creates an + // empty/NULL position. + // + template + struct cache_position + { + typedef object_map map; + typedef typename map::iterator iterator; + + cache_position (): map_ (0) {} + cache_position (map& m, const iterator& p): map_ (&m), pos_ (p) {} + + cache_position (const cache_position& p) + : map_ (p.map_), pos_ (p.pos_) {} + + cache_position& + operator= (const cache_position& p) + { + // It might not be ok to use an uninitialized iterator on the rhs. + // + if (p.map_ != 0) + pos_ = p.pos_; + map_ = p.map_; + return *this; + } + + map* map_; + iterator pos_; + }; + + // The following cache management functions are all static to + // allow for a custom notion of a current session. The erase() + // function is called to remove the object if the operation + // that caused it to be inserted (e.g., load) failed. + // + template + static cache_position + _cache_insert (database_type&, + const typename object_traits::id_type&, + const typename object_traits::pointer_type&); + + template + static typename object_traits::pointer_type + _cache_find (database_type&, const typename object_traits::id_type&); + + template + static void + _cache_erase (const cache_position&); + + // Notifications. These are called after per-object callbacks for + // post_{persist, load, update, erase} events. + // + template + static void + _cache_persist (const cache_position&) {} + + template + static void + _cache_load (const cache_position&) {} + + template + static void + _cache_update (database_type&, const T&) {} + + template + static void + _cache_erase (database_type&, const typename object_traits::id_type&); + + protected: + database_map db_map_; + }; +} + +#include +#include + +#include + +#endif // ODB_SESSION_HXX diff --git a/libodb/odb/session.ixx b/libodb/odb/session.ixx new file mode 100644 index 0000000..4acdc1b --- /dev/null +++ b/libodb/odb/session.ixx @@ -0,0 +1,60 @@ +// file : odb/session.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + template + inline void session:: + cache_erase (const cache_position& p) + { + // @@ Empty maps are not cleaned up by this version of erase. + // + if (p.map_ != 0) + p.map_->erase (p.pos_); + } + + template + inline typename session::cache_position session:: + _cache_insert (database_type& db, + const typename object_traits::id_type& id, + const typename object_traits::pointer_type& obj) + { + if (session* s = current_pointer ()) + return s->cache_insert (db, id, obj); + else + return cache_position (); + } + + template + inline typename object_traits::pointer_type session:: + _cache_find (database_type& db, const typename object_traits::id_type& id) + { + typedef typename object_traits::pointer_type pointer_type; + + if (const session* s = current_pointer ()) + return s->cache_find (db, id); + else + return pointer_type (); + } + + template + inline void session:: + _cache_erase (const cache_position& p) + { + // @@ Empty maps are not cleaned up by this version of erase. + // + if (p.map_ != 0) + p.map_->erase (p.pos_); + } + + template + inline void session:: + _cache_erase (database_type& db, + const typename object_traits::id_type& id) + { + if (session* s = current_pointer ()) + s->cache_erase (db, id); + } +} diff --git a/libodb/odb/session.txx b/libodb/odb/session.txx new file mode 100644 index 0000000..d74fe0f --- /dev/null +++ b/libodb/odb/session.txx @@ -0,0 +1,90 @@ +// file : odb/session.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + template + typename session::cache_position session:: + cache_insert (database_type& db, + const typename object_traits::id_type& id, + const typename object_traits::pointer_type& obj) + { + type_map& tm (db_map_[&db]); + details::shared_ptr& pom (tm[&typeid (T)]); + + if (!pom) + pom.reset (new (details::shared) object_map); + + object_map& om (static_cast&> (*pom)); + + typename object_map::value_type vt (id, obj); + std::pair::iterator, bool> r (om.insert (vt)); + + // In what situation may we possibly attempt to reinsert the object? + // For example, when the user loads the same object in two different + // instances (i.e., load into a pre-allocated object). In this case + // we should probably update our entries accordingly. + // + if (!r.second) + r.first->second = obj; + + return cache_position (om, r.first); + } + + template + typename object_traits::pointer_type session:: + cache_find (database_type& db, + const typename object_traits::id_type& id) const + { + typedef typename object_traits::pointer_type pointer_type; + + database_map::const_iterator di (db_map_.find (&db)); + + if (di == db_map_.end ()) + return pointer_type (); + + const type_map& tm (di->second); + type_map::const_iterator ti (tm.find (&typeid (T))); + + if (ti == tm.end ()) + return pointer_type (); + + const object_map& om (static_cast&> (*ti->second)); + typename object_map::const_iterator oi (om.find (id)); + + if (oi == om.end ()) + return pointer_type (); + + return oi->second; + } + + template + void session:: + cache_erase (database_type& db, const typename object_traits::id_type& id) + { + database_map::iterator di (db_map_.find (&db)); + + if (di == db_map_.end ()) + return; + + type_map& tm (di->second); + type_map::iterator ti (tm.find (&typeid (T))); + + if (ti == tm.end ()) + return; + + object_map& om (static_cast&> (*ti->second)); + typename object_map::iterator oi (om.find (id)); + + if (oi == om.end ()) + return; + + om.erase (oi); + + if (om.empty ()) + tm.erase (ti); + + if (tm.empty ()) + db_map_.erase (di); + } +} diff --git a/libodb/odb/simple-object-result.hxx b/libodb/odb/simple-object-result.hxx new file mode 100644 index 0000000..53c0cb2 --- /dev/null +++ b/libodb/odb/simple-object-result.hxx @@ -0,0 +1,201 @@ +// file : odb/simple-object-result.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SIMPLE_OBJECT_RESULT_HXX +#define ODB_SIMPLE_OBJECT_RESULT_HXX + +#include + +#include // std::size_t +#include // std::move + +#include +#include +#include +#include +#include + +#include // ODB_CXX11 + +namespace odb +{ + // Implementation for non-polymorphic objects with object id. + // + template + class object_result_impl: public result_impl + { + protected: + // In result_impl, T is always non-const and the same as object_type. + // + typedef T object_type; + typedef odb::object_traits object_traits; + typedef typename object_traits::id_type id_type; + + typedef typename object_traits::pointer_type pointer_type; + typedef odb::pointer_traits pointer_traits; + + friend class result; + friend class result; + friend class result_iterator; + friend class result_iterator; + friend class object_result_iterator; + friend class object_result_iterator; + + protected: + object_result_impl (odb::connection& conn) + : result_impl (conn), begin_ (true), end_ (false), current_ () + { + } + + // To make this work with all kinds of pointers (raw, std::auto_ptr, + // shared), we need to make sure we don't make any copies of the + // pointer on the return path. + // + pointer_type& + current () + { + if (pointer_traits::null_ptr (current_) && !end_) + load (); + + return current_; + } + + void + release () + { + current_ = pointer_type (); + guard_.release (); + } + + void + begin () + { + if (begin_) + { + next (); + begin_ = false; + } + } + + bool + end () const + { + return end_; + } + + protected: + // The fetch argument is a hint to the implementation. If it is + // false then it means load_id() was already called (and presumably + // fetched the data into the object image) and the object image + // is still valid (so the implementation doesn't need to fetch + // the data again). + // + virtual void + load (object_type&, bool fetch = true) = 0; + + virtual id_type + load_id () = 0; + + virtual void + next () = 0; + + virtual void + cache () = 0; + + virtual std::size_t + size () = 0; + + protected: +#ifdef ODB_CXX11 + void + current (pointer_type& p, bool guard = true) + { + current_ = std::move (p); + + if (guard) + guard_.reset (current_); + else + guard_.reset (); + } + + void + current (pointer_type&& p, bool guard = true) + { + current (p, guard); + } +#else + void + current (pointer_type p, bool guard = true) + { + current_ = p; + + if (guard) + guard_.reset (current_); + else + guard_.reset (); + } +#endif + + bool begin_; + bool end_; + + private: + void + load (); + + private: + pointer_type current_; + typename pointer_traits::guard guard_; + }; + + template + class object_result_iterator + { + public: + // T can be const T while object_type is always non-const. + // + typedef typename object_traits::object_type object_type; + typedef typename object_traits::id_type id_type; + + typedef object_result_impl result_impl_type; + + public: + object_result_iterator (result_impl_type* res) + : res_ (res) + { + } + + public: + typedef typename object_traits::pointer_type pointer_type; + + pointer_type + load () + { +#ifdef ODB_CXX11 + pointer_type r (std::move (res_->current ())); +#else + pointer_type r (res_->current ()); +#endif + res_->release (); + return r; + } + + void + load (object_type&); + + id_type + id () + { + return res_->load_id (); + } + + protected: + result_impl_type* res_; + }; +} + +#include + +#include + +#endif // ODB_SIMPLE_OBJECT_RESULT_HXX diff --git a/libodb/odb/simple-object-result.txx b/libodb/odb/simple-object-result.txx new file mode 100644 index 0000000..00521f8 --- /dev/null +++ b/libodb/odb/simple-object-result.txx @@ -0,0 +1,58 @@ +// file : odb/simple-object-result.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // object_result_impl + // + + template + void object_result_impl:: + load () + { + // First check the session. + // + const id_type& id (load_id ()); + + pointer_type p (object_traits::pointer_cache_traits::find (db_, id)); + + if (!pointer_traits::null_ptr (p)) + current (p, false); // Pointer from cache should not be guarded. + else + { + p = object_traits::create (); + + typename object_traits::pointer_cache_traits::insert_guard ig ( + object_traits::pointer_cache_traits::insert (db_, id, p)); + + object_type& obj (pointer_traits::get_ref (p)); + current (p); + load (obj, false); + object_traits::pointer_cache_traits::load (ig.position ()); + ig.release (); + } + } + + // + // object_result_iterator + // + + template + void object_result_iterator:: + load (object_type& obj) + { + if (res_->end ()) + return; + + typedef odb::object_traits object_traits; + + typename object_traits::reference_cache_traits::position_type p ( + object_traits::reference_cache_traits::insert ( + res_->db_, res_->load_id (), obj)); + typename object_traits::reference_cache_traits::insert_guard ig (p); + res_->load (obj, false); + object_traits::reference_cache_traits::load (p); + ig.release (); + } +} diff --git a/libodb/odb/statement-processing-common.hxx b/libodb/odb/statement-processing-common.hxx new file mode 100644 index 0000000..23661fc --- /dev/null +++ b/libodb/odb/statement-processing-common.hxx @@ -0,0 +1,214 @@ +// file : odb/statement-processingc-common.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STATEMENT_PROCESSING_COMMON_HXX +#define ODB_STATEMENT_PROCESSING_COMMON_HXX + +#include + +//#define LIBODB_DEBUG_STATEMENT_PROCESSING 1 +//#define LIBODB_TRACE_STATEMENT_PROCESSING 1 + +#include +#include // std::size_t + +namespace odb +{ + typedef std::char_traits traits; + + static inline const char* + find (const char* b, const char* e, char c) + { + return traits::find (b, e - b, c); + } + + static inline const char* + rfind (const char* b, const char* e, char c) + { + for (--e; b != e; --e) + if (*e == c) + return e; + + return 0; + } + + static inline const char* + find (const char* b, const char* e, const char* s, std::size_t n) + { + for (; b != e; ++b) + { + if (*b == *s && + static_cast (e - b) >= n && + traits::compare (b, s, n) == 0) + return b; + } + + return 0; + } + + // Iterate over INSERT column/value list, UPDATE SET expression list, + // or SELECT column/join list. + // + // for (const char* b (columns_begin), *e (begin (b, end)); + // e != 0; + // next (b, e, end)) + // { + // // b points to the beginning of the value (i.e., one past '('). + // // e points one past the end of the value (i.e., to ',', ')', or '\n'). + // } + // + // // b points one past the last value. + // + static inline const char* + paren_begin (const char*& b, const char* end) + { + // Note that the list may not end with '\n'. + + b++; // Skip '('. + const char* e (find (b, end, '\n')); + return (e != 0 ? e : end) - 1; // Skip ',' or ')'. + } + + static inline void + paren_next (const char*& b, const char*& e, const char* end) + { + if (*e == ',') + { + b = e + 2; // Skip past '\n'. + e = find (b, end, '\n'); + e = (e != 0 ? e : end) - 1; // Skip ',' or ')'. + } + else + { + b = (e + 1 != end ? e + 2 : end); // Skip past '\n'. + e = 0; + } + } + + static inline const char* + comma_begin (const char* b, const char* end) + { + // Note that the list may not end with '\n'. + + const char* e (find (b, end, '\n')); + return e != 0 ? e - (*(e - 1) == ',' ? 1 : 0) : end; // Skip ','. + } + + static inline void + comma_next (const char*& b, const char*& e, const char* end) + { + if (*e == ',') + { + b = e + 2; // Skip past '\n'. + e = find (b, end, '\n'); + e = (e != 0 ? e - (*(e - 1) == ',' ? 1 : 0) : end); // Skip ','. + } + else + { + b = (e != end ? e + 1 : end); // Skip past '\n'. + e = 0; + } + } + + // Only allows A-Z and spaces before prefix (e.g., JOIN in LEFT OUTER JOIN). + // + static inline bool + fuzzy_prefix (const char* b, + const char* end, + const char* prefix, + std::size_t prefix_size) + { + for (; b != end; ++b) + { + char c (*b); + + if ((c < 'A' || c > 'Z') && c != ' ') + break; + + if (c == *prefix && + static_cast (end - b) > prefix_size && + traits::compare (b, prefix, prefix_size) == 0) + return true; + } + + return false; + } + + static inline const char* + newline_begin (const char* b, const char* end) + { + // Note that the list may not end with '\n'. + + const char* e (find (b, end, '\n')); + return e != 0 ? e : end; + } + + static inline void + newline_next (const char*& b, + const char*& e, + const char* end, + const char* prefix, + std::size_t prefix_size, + bool prefix_fuzzy = false) + { + if (e != end) + e++; // Skip past '\n'. + + b = e; + + // Do we have another element? + // + if (static_cast (end - b) > prefix_size && + (prefix_fuzzy + ? fuzzy_prefix (b, end, prefix, prefix_size) + : traits::compare (b, prefix, prefix_size) == 0)) + { + e = find (b, end, '\n'); + if (e == 0) + e = end; + } + else + e = 0; + } + + // Note that end must point to the beginning of the list. + // + static inline const char* + newline_rbegin (const char* e, const char* end) + { + const char* b (rfind (end, e - 1, '\n')); + return b != 0 ? b + 1 : end; // Skip past '\n'. + } + + static inline void + newline_rnext (const char*& b, const char*& e, const char* end) + { + if (b != end) + { + e = b - 1; // Skip to previous '\n'. + b = rfind (end, e - 1, '\n'); + b = (b != 0 ? b + 1 : end); // Skip past '\n'. + } + else + { + e = end - 1; // One before the first element. + b = 0; + } + } + + // Fast path: just remove the "structure". + // + static inline void + process_fast (const char* s, std::string& r) + { + r = s; + for (std::size_t i (r.find ('\n')); + i != std::string::npos; + i = r.find ('\n', i)) + r[i++] = ' '; + } +} + +#include + +#endif // ODB_STATEMENT_PROCESSING_COMMON_HXX diff --git a/libodb/odb/statement-processing.cxx b/libodb/odb/statement-processing.cxx new file mode 100644 index 0000000..708c9ab --- /dev/null +++ b/libodb/odb/statement-processing.cxx @@ -0,0 +1,685 @@ +// file : odb/statement-processing.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +#include + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING +# include +#endif + +#include + +using namespace std; + +namespace odb +{ + typedef const void* const* bind_type; + + static inline const void* + bind_at (size_t i, bind_type bind, size_t bind_skip) + { + const char* b (reinterpret_cast (bind)); + return *reinterpret_cast (b + i * bind_skip); + } + + void statement:: + process_insert (string& r, + const char* s, + bind_type bind, + size_t bind_size, + size_t bind_skip, + char param_symbol, + char param_symbol2) + { +#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING + assert (bind_size != 0); // Cannot be versioned. +#endif + + bool fast (true); // Fast case (if all present). + for (size_t i (0); i != bind_size && fast; ++i) + { + if (bind_at (i, bind, bind_skip) == 0) + fast = false; + } + + // Fast path: just remove the "structure". + // +#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING + if (fast) + { + process_fast (s, r); + return; + } +#endif + + // Scan the statement and store the positions of various parts. + // + size_t n (traits::length (s)); + const char* e (s + n); + + // Header. + // + const char* p (find (s, e, '\n')); + assert (p != 0); + size_t header_size (p - s); + p++; + + // Column list. + // + const char* columns_begin (0); + if (*p == '(') + { + columns_begin = p; + + // Find the end of the column list. + // + for (const char* ce (paren_begin (p, e)); ce != 0; paren_next (p, ce, e)) + ; + } + + // OUTPUT + // + const char* output_begin (0); + size_t output_size (0); + if (e - p > 7 && traits::compare (p, "OUTPUT ", 7) == 0) + { + output_begin = p; + p += 7; + p = find (p, e, '\n'); + assert (p != 0); + output_size = p - output_begin; + p++; + } + + // VALUES or DEFAULT VALUES + // + bool empty (true); // DEFAULT VALUES case (if none present). + const char* values_begin (0); + if (e - p > 7 && traits::compare (p, "VALUES\n", 7) == 0) + { + p += 7; + values_begin = p; + + size_t bi (0); + for (const char* ve (paren_begin (p, e)); ve != 0; paren_next (p, ve, e)) + { + // We cannot be empty if we have a non-parameterized value, e.g., + // INSERT ... VALUES(1,?). We also cannot be empty if this value + // is present in the bind array. + // + if ((find (p, ve, param_symbol) == 0 && + (param_symbol2 == '\0' || find (p, ve, param_symbol2) == 0)) || + bind_at (bi++, bind, bind_skip) != 0) + empty = false; + } + } + else + { + // Must be DEFAULT VALUES. + // + assert (traits::compare (p, "DEFAULT VALUES", 14) == 0); + p += 14; + + if (*p == '\n') + p++; + } + + // Trailer. + // + const char* trailer_begin (0); + size_t trailer_size (0); + if (e - p != 0) + { + trailer_begin = p; + trailer_size = e - p; + } + + // Empty case. + // + if (empty) + { + r.reserve (header_size + + (output_size == 0 ? 0 : output_size + 1) + + 15 + // For " DEFAULT VALUES" + (trailer_size == 0 ? 0 : trailer_size + 1)); + + r.assign (s, header_size); + + if (output_size != 0) + { + r += ' '; + r.append (output_begin, output_size); + } + + r += " DEFAULT VALUES"; + + if (trailer_size != 0) + { + r += ' '; + r.append (trailer_begin, trailer_size); + } + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING + if (r.size () != n) + cerr << endl + << "old: '" << s << "'" << endl << endl + << "new: '" << r << "'" << endl << endl; +#endif + + return; + } + + // Assume the same size as the original. It can only shrink, and in + // most cases only slightly. So this is a good approximation. + // + r.reserve (n); + r.assign (s, header_size); + + // Column list. + // + { + r += ' '; + + size_t i (0), bi (0); + + for (const char *c (columns_begin), *ce (paren_begin (c, e)), + *v (values_begin), *ve (paren_begin (v, e)); + ce != 0; paren_next (c, ce, e), paren_next (v, ve, e)) + { + // See if the value contains the parameter symbol and, if so, + // whether it is present in the bind array. + // + if ((find (v, ve, param_symbol) != 0 || + (param_symbol2 != '\0' && find (v, ve, param_symbol2) != 0)) && + bind_at (bi++, bind, bind_skip) == 0) + continue; + + // Append the column. + // + if (i++ == 0) + r += '('; + else + r += ", "; // Add the space for consistency with the fast path. + + r.append (c, ce - c); + } + + r += ')'; + } + + // OUTPUT + // + if (output_size != 0) + { + r += ' '; + r.append (output_begin, output_size); + } + + // Value list. + // + { + r += " VALUES "; + + size_t i (0), bi (0); + + for (const char* v (values_begin), *ve (paren_begin (v, e)); + ve != 0; paren_next (v, ve, e)) + { + // See if the value contains the parameter symbol and, if so, + // whether it is present in the bind array. + // + if ((find (v, ve, param_symbol) != 0 || + (param_symbol2 != '\0' && find (v, ve, param_symbol2) != 0)) && + bind_at (bi++, bind, bind_skip) == 0) + continue; + + // Append the value. + // + if (i++ == 0) + r += '('; + else + r += ", "; // Add the space for consistency with the fast path. + + r.append (v, ve - v); + } + + r += ')'; + } + + // Trailer. + // + if (trailer_size != 0) + { + r += ' '; + r.append (trailer_begin, trailer_size); + } + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING + if (r.size () != n) + cerr << endl + << "old: '" << s << "'" << endl << endl + << "new: '" << r << "'" << endl << endl; +#endif + } + + void statement:: + process_update (string& r, + const char* s, + bind_type bind, + size_t bind_size, + size_t bind_skip, + char param_symbol, + char param_symbol2) + { + bool fast (true); // Fast case (if all present). + for (size_t i (0); i != bind_size && fast; ++i) + { + if (bind_at (i, bind, bind_skip) == 0) + fast = false; + } + + // Fast path: just remove the "structure". + // +#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING + if (fast) + { + process_fast (s, r); + return; + } +#endif + + // Scan the statement and store the positions of various parts. + // + size_t n (traits::length (s)); + const char* e (s + n); + + // Header. + // + const char* p (find (s, e, '\n')); + assert (p != 0); + size_t header_size (p - s); + p++; + + // SET + // + bool empty (true); // Empty SET case. + const char* set_begin (0); + if (e - p > 4 && traits::compare (p, "SET\n", 4) == 0) + { + p += 4; + set_begin = p; + + // Scan the SET list. + // + size_t bi (0); + for (const char* pe (comma_begin (p, e)); pe != 0; comma_next (p, pe, e)) + { + if (empty) + { + // We cannot be empty if we have a non-parameterized set expression, + // e.g., UPDATE ... SET ver=ver+1 ... We also cannot be empty if + // this expression is present in the bind array. + // + if ((find (p, pe, param_symbol) == 0 && + (param_symbol2 == '\0' || find (p, pe, param_symbol2) == 0)) || + bind_at (bi++, bind, bind_skip) != 0) + empty = false; + } + } + } + + // Empty case. + // + if (empty) + { + r.clear (); + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING + if (n != 0) + cerr << endl + << "old: '" << s << "'" << endl << endl + << "new: '" << r << "'" << endl << endl; +#endif + + return; + } + + // Trailer. + // + const char* trailer_begin (0); + size_t trailer_size (0); + if (e - p != 0) + { + trailer_begin = p; + trailer_size = e - p; + } + + // Assume the same size as the original. It can only shrink, and in + // most cases only slightly. So this is a good approximation. + // + r.reserve (n); + r.assign (s, header_size); + + // SET list. + // + { + r += " SET "; + + size_t i (0), bi (0); + + for (const char* p (set_begin), *pe (comma_begin (p, e)); + pe != 0; comma_next (p, pe, e)) + { + // See if the value contains the parameter symbol and, if so, + // whether it is present in the bind array. + // + if ((find (p, pe, param_symbol) != 0 || + (param_symbol2 != '\0' && find (p, pe, param_symbol2) != 0)) && + bind_at (bi++, bind, bind_skip) == 0) + continue; + + // Append the expression. + // + if (i++ != 0) + r += ", "; // Add the space for consistency with the fast path. + + r.append (p, pe - p); + } + } + + // Trailer. + // + if (trailer_size != 0) + { + r += ' '; + r.append (trailer_begin, trailer_size); + } + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING + if (r.size () != n) + cerr << endl + << "old: '" << s << "'" << endl << endl + << "new: '" << r << "'" << endl << endl; +#endif + } + + void statement:: + process_select (string& r, + const char* s, + bind_type bind, + size_t bind_size, + size_t bind_skip, + char quote_open, + char quote_close, +#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING + bool optimize, +#else + bool, +#endif + bool as) + { + bool empty (true); // Empty case (if none present). + bool fast (true); // Fast case (if all present). + for (size_t i (0); i != bind_size && (empty || fast); ++i) + { + if (bind_at (i, bind, bind_skip) != 0) + empty = false; + else + fast = false; + } + + // Empty. + // + if (empty) + { + r.clear (); + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING + if (*s != '\0') + cerr << endl + << "old: '" << s << "'" << endl << endl + << "new: '" << r << "'" << endl << endl; +#endif + return; + } + + // Fast path: just remove the "structure". + // +#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING + if (fast && !optimize) + { + process_fast (s, r); + return; + } +#endif + + // Scan the statement and store the positions of various parts. + // + size_t n (traits::length (s)); + const char* e (s + n); + + // Header. + // + const char* p (find (s, e, '\n')); + assert (p != 0); + size_t header_size (p - s); + p++; + + // Column list. + // + const char* columns_begin (p); + for (const char* ce (comma_begin (p, e)); ce != 0; comma_next (p, ce, e)) + ; + + // FROM. + assert (traits::compare (p, "FROM ", 5) == 0); + const char* from_begin (p); + p = find (p, e, '\n'); // May not end with '\n'. + if (p == 0) + p = e; + size_t from_size (p - from_begin); + if (p != e) + p++; + + // JOIN list. + // + const char* joins_begin (0), *joins_end (0); + if (e - p > 5 && fuzzy_prefix (p, e, "JOIN ", 5)) + { + joins_begin = p; + + // Find the end of the JOIN list. + // + for (const char* je (newline_begin (p, e)); + je != 0; newline_next (p, je, e, "JOIN ", 5, true)) + ; + + joins_end = (p != e ? p - 1 : p); + } + +#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING + if (fast && joins_begin == 0) + { + // No JOINs to optimize so can still take the fast path. + // + process_fast (s, r); + return; + } +#endif + + // Trailer (WHERE, ORDER BY, etc). + // + const char* trailer_begin (0); + size_t trailer_size (0); + if (e - p != 0) + { + trailer_begin = p; + trailer_size = e - p; + } + + // Assume the same size as the original. It can only shrink, and in + // most cases only slightly. So this is a good approximation. + // + r.reserve (n); + r.assign (s, header_size); + + // Column list. + // + { + r += ' '; + + size_t i (0), bi (0); + + for (const char *c (columns_begin), *ce (comma_begin (c, e)); + ce != 0; comma_next (c, ce, e)) + { + // See if the column is present in the bind array. + // + if (bind_at (bi++, bind, bind_skip) == 0) + continue; + + // Append the column. + // + if (i++ != 0) + r += ", "; // Add the space for consistency with the fast path. + + r.append (c, ce - c); + } + } + + // From. + // + r += ' '; + r.append (from_begin, from_size); + + // JOIN list, pass 1. + // + size_t join_pos (0); + if (joins_begin != 0) + { + // Fill in the JOIN "area" with spaces. + // + r.resize (r.size () + joins_end - joins_begin + 1, ' '); + join_pos = r.size () + 1; // End of the last JOIN. + } + + // Trailer. + // + if (trailer_size != 0) + { + r += ' '; + r.append (trailer_begin, trailer_size); + } + + // JOIN list, pass 2. + // + if (joins_begin != 0) + { + // Splice the JOINs into the pre-allocated area. + // + for (const char* je (joins_end), *j (newline_rbegin (je, joins_begin)); + j != 0; newline_rnext (j, je, joins_begin)) + { + size_t n (je - j); + + // Get the alias or, if none used, the table name. + // + p = find (j, je, "JOIN ", 5) + 5; // Skip past "JOIN ". + const char* table_begin (p); + p = find (p, je, ' '); // End of the table name. + const char* table_end (p); + p++; // Skip space. + + // We may or may not have the AS keyword. + // + const char* alias_begin (0); + size_t alias_size (0); + + if (p != je && // Not the end. + (je - p < 4 || traits::compare (p, "ON ", 3) != 0)) + { + // Something other than "ON ", so got to be an alias. + // + if (as) + p += 3; + + alias_begin = p; + p = find (p, je, ' '); // There might be no ON (CROSS JOIN). + alias_size = (p != 0 ? p : je) - alias_begin; + } + else + { + // Just the table. + // + alias_begin = table_begin; + alias_size = table_end - alias_begin; + } + + // The alias must be quoted. + // + assert (*alias_begin == quote_open && + *(alias_begin + alias_size - 1) == quote_close); + + // We now need to see if the alias is used in either the SELECT + // list, the WHERE conditions, or the ON condition of any of the + // JOINs that we have already processed and decided to keep. + // + // Instead of re-parsing the whole thing again, we are going to + // take a shortcut and simply search for the alias in the statement + // we have constructed so far (that's why we have added the + // trailer before filling in the JOINs). To make it more robust, + // we are going to do a few extra sanity checks, specifically, + // that the alias is a top level identifier and is followed by + // only a single identifer (column). This will catch cases like + // [s].[t].[c] where [s] is also used as an alias or LEFT JOIN [t] + // where [t] is also used as an alias in another JOIN. + // + bool found (false); + for (size_t p (r.find (alias_begin, 0, alias_size)); + p != string::npos; + p = r.find (alias_begin, p + alias_size, alias_size)) + { + size_t e (p + alias_size); + + // If we are not a top-level qualifier or not a bottom-level, + // then we are done (3 is for at least "[a]"). + // + if ((p != 0 && r[p - 1] == '.') || + (e + 3 >= r.size () || (r[e] != '.' || r[e + 1] != quote_open))) + continue; + + // The only way to distinguish the [a].[c] from FROM [a].[c] or + // JOIN [a].[c] is by checking the prefix. + // + if ((p > 5 && r.compare (p - 5, 5, "FROM ") == 0) || + (p > 5 && r.compare (p - 5, 5, "JOIN ") == 0)) + continue; + + // Check that we are followed by a single identifier. + // + e = r.find (quote_close, e + 2); + if (e == string::npos || (e + 1 != r.size () && r[e + 1] == '.')) + continue; + + found = true; + break; + } + + join_pos -= n + 1; // Extra one for space. + if (found) + r.replace (join_pos, n, j, n); + else + r.erase (join_pos - 1, n + 1); // Extra one for space. + } + } + +#ifdef LIBODB_TRACE_STATEMENT_PROCESSING + if (r.size () != n) + cerr << endl + << "old: '" << s << "'" << endl << endl + << "new: '" << r << "'" << endl << endl; +#endif + } +} diff --git a/libodb/odb/statement.cxx b/libodb/odb/statement.cxx new file mode 100644 index 0000000..35e7b77 --- /dev/null +++ b/libodb/odb/statement.cxx @@ -0,0 +1,12 @@ +// file : odb/statement.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + statement:: + ~statement () + { + } +} diff --git a/libodb/odb/statement.hxx b/libodb/odb/statement.hxx new file mode 100644 index 0000000..83513c0 --- /dev/null +++ b/libodb/odb/statement.hxx @@ -0,0 +1,108 @@ +// file : odb/statement.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STATEMENT_HXX +#define ODB_STATEMENT_HXX + +#include + +#include +#include // std::size_t + +#include // connection + +#include +#include + +namespace odb +{ + class LIBODB_EXPORT statement: public details::shared_base + { + private: + statement (const statement&); + statement& operator= (const statement&); + + public: + typedef odb::connection connection_type; + + virtual const char* + text () const = 0; + + virtual connection_type& + connection () = 0; + + virtual + ~statement () = 0; + + protected: + statement () {} + + // Statement processing. Kept public only for testing. + // + public: + // Expected statement structure: + // + // INSERT INTO table\n + // [(a,\n + // b)\n] + // [OUTPUT ...\n] + // [VALUES\n + // ($1,\n + // $2)[\n]] + // [DEFAULT VALUES[\n]] + // [RETURNING ...] + // [; SELECT ...] + // + static void + process_insert (std::string& result, + const char* statement, + const void* const* bind, // Array of bind buffer pointers. + std::size_t bind_size, // Number of bind elements. + std::size_t bind_skip, // Offset to the next bind. + char param_symbol, // $, ?, :, etc. + char param_symbol2 = '\0'); + + // Expected statement structure: + // + // UPDATE table\n + // SET\n + // a=$1,\n + // b=$2[\n] + // [OUTPUT ...] + // [WHERE ...] + // + static void + process_update (std::string& result, + const char* statement, + const void* const* bind, // Array of bind buffer pointers. + std::size_t bind_size, // Number of bind elements. + std::size_t bind_skip, // Offset to the next bind. + char param_symbol, // $, ?, :, etc. + char param_symbol2 = '\0'); + + + // Expected statement structure: + // + // SELECT\n + // [schema.]table.a [AS b],\n + // alias.b\n + // FROM [schema.]table[\n] + // [{A-Z }* JOIN [schema.]table [AS alias][ ON ...][\n]]* + // [WHERE ...] + // + static void + process_select (std::string& result, + const char* statement, + const void* const* bind, // Array of bind buffer pointers. + std::size_t bind_size, // Number of bind elements. + std::size_t bind_skip, // Offset to the next bind. + char quote_open, // Identifier opening quote. + char quote_close, // Identifier closing quote. + bool optimize, // Remove unused JOINs. + bool as = true); // JOINs use AS keyword. + }; +} + +#include + +#endif // ODB_STATEMENT_HXX diff --git a/libodb/odb/std-array-traits.hxx b/libodb/odb/std-array-traits.hxx new file mode 100644 index 0000000..1d0f1a1 --- /dev/null +++ b/libodb/odb/std-array-traits.hxx @@ -0,0 +1,72 @@ +// file : odb/std-array-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_ARRAY_TRAITS_HXX +#define ODB_STD_ARRAY_TRAITS_HXX + +#include + +#include +#include // std::size_t +#include + +#include + +namespace odb +{ + template + class access::container_traits> + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef std::array container_type; + + typedef V value_type; + typedef typename container_type::size_type index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (index_type i (0); i < N; ++i) + f.insert (i, c[i]); + } + + static void + load (container_type& c, bool more, const functions& f) + { + index_type i (0); + + for (; more && i < N; ++i) + { + index_type dummy; + more = f.select (dummy, c[i]); + } + + assert (!more && i == N); + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (index_type i (0); i < N; ++i) + f.insert (i, c[i]); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_ARRAY_TRAITS_HXX diff --git a/libodb/odb/std-deque-traits.hxx b/libodb/odb/std-deque-traits.hxx new file mode 100644 index 0000000..351c6db --- /dev/null +++ b/libodb/odb/std-deque-traits.hxx @@ -0,0 +1,69 @@ +// file : odb/std-deque-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_DEQUE_TRAITS_HXX +#define ODB_STD_DEQUE_TRAITS_HXX + +#include + +#include + +#include + +namespace odb +{ + template + class access::container_traits > + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef std::deque container_type; + + typedef V value_type; + typedef typename container_type::size_type index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + index_type dummy; + c.push_back (value_type ()); + more = f.select (dummy, c.back ()); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_DEQUE_TRAITS_HXX diff --git a/libodb/odb/std-forward-list-traits.hxx b/libodb/odb/std-forward-list-traits.hxx new file mode 100644 index 0000000..7978b1c --- /dev/null +++ b/libodb/odb/std-forward-list-traits.hxx @@ -0,0 +1,73 @@ +// file : odb/std-forward-list-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_FORWARD_LIST_TRAITS_HXX +#define ODB_STD_FORWARD_LIST_TRAITS_HXX + +#include + +#include + +#include + +namespace odb +{ + template + class access::container_traits> + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef std::forward_list container_type; + + typedef V value_type; + typedef typename container_type::size_type index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + index_type i (0); + for (typename container_type::const_iterator j (c.begin ()), + e (c.end ()); j != e; ++j) + f.insert (i++, *j); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + for (typename container_type::iterator i (c.before_begin ()); more; ) + { + index_type dummy; + i = c.insert_after (i, value_type ()); + more = f.select (dummy, *i); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + index_type i (0); + for (typename container_type::const_iterator j (c.begin ()), + e (c.end ()); j != e; ++j) + f.insert (i++, *j); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_FORWARD_LIST_TRAITS_HXX diff --git a/libodb/odb/std-list-traits.hxx b/libodb/odb/std-list-traits.hxx new file mode 100644 index 0000000..f349079 --- /dev/null +++ b/libodb/odb/std-list-traits.hxx @@ -0,0 +1,73 @@ +// file : odb/std-list-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_LIST_TRAITS_HXX +#define ODB_STD_LIST_TRAITS_HXX + +#include + +#include + +#include + +namespace odb +{ + template + class access::container_traits > + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef std::list container_type; + + typedef V value_type; + typedef typename container_type::size_type index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + index_type i (0); + for (typename container_type::const_iterator j (c.begin ()), + e (c.end ()); j != e; ++j) + f.insert (i++, *j); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + index_type dummy; + c.push_back (value_type ()); + more = f.select (dummy, c.back ()); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + index_type i (0); + for (typename container_type::const_iterator j (c.begin ()), + e (c.end ()); j != e; ++j) + f.insert (i++, *j); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_LIST_TRAITS_HXX diff --git a/libodb/odb/std-map-traits.hxx b/libodb/odb/std-map-traits.hxx new file mode 100644 index 0000000..2b9bf7d --- /dev/null +++ b/libodb/odb/std-map-traits.hxx @@ -0,0 +1,142 @@ +// file : odb/std-map-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_MAP_TRAITS_HXX +#define ODB_STD_MAP_TRAITS_HXX + +#include + +#include +#include // std::move + +#include +#include // ODB_CXX11 + +namespace odb +{ + template + class access::container_traits > + { + public: + static const container_kind kind = ck_map; + static const bool smart = false; + + typedef std::map container_type; + + typedef K key_type; + typedef V value_type; + typedef typename container_type::value_type pair_type; + + typedef map_functions 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 (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.select (k, v); +#ifdef ODB_CXX11 + c.insert (pair_type (std::move (k), std::move (v))); +#else + c.insert (pair_type (k, v)); +#endif + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (i->first, i->second); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; + + // C++03 does not guarantee insertion order of equal values but C++11 + // changes that. The current implementation in the generated code does + // not guarantee this either. + // + template + class access::container_traits > + { + public: + static const container_kind kind = ck_multimap; + static const bool smart = false; + + typedef std::multimap container_type; + + typedef K key_type; + typedef V value_type; + typedef typename container_type::value_type pair_type; + + typedef map_functions 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 (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.select (k, v); +#ifdef ODB_CXX11 + c.insert (pair_type (std::move (k), std::move (v))); +#else + c.insert (pair_type (k, v)); +#endif + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (i->first, i->second); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_MAP_TRAITS_HXX diff --git a/libodb/odb/std-set-traits.hxx b/libodb/odb/std-set-traits.hxx new file mode 100644 index 0000000..45a5dcc --- /dev/null +++ b/libodb/odb/std-set-traits.hxx @@ -0,0 +1,134 @@ +// file : odb/std-set-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_SET_TRAITS_HXX +#define ODB_STD_SET_TRAITS_HXX + +#include + +#include +#include // std::move + +#include +#include // ODB_CXX11 + +namespace odb +{ + template + class access::container_traits > + { + public: + static const container_kind kind = ck_set; + static const bool smart = false; + + typedef std::set container_type; + typedef V value_type; + + typedef set_functions 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 (*i); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + value_type v; + more = f.select (v); +#ifdef ODB_CXX11 + c.insert (std::move (v)); +#else + c.insert (v); +#endif + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (*i); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; + + // C++03 does not guarantee insertion order of equal values but C++11 + // changes that. The current implementation in the generated code does + // not guarantee this either. + // + template + class access::container_traits > + { + public: + static const container_kind kind = ck_multiset; + static const bool smart = false; + + typedef std::multiset container_type; + typedef V value_type; + + typedef set_functions 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 (*i); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + value_type v; + more = f.select (v); +#ifdef ODB_CXX11 + c.insert (std::move (v)); +#else + c.insert (v); +#endif + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (*i); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_SET_TRAITS_HXX diff --git a/libodb/odb/std-unordered-map-traits.hxx b/libodb/odb/std-unordered-map-traits.hxx new file mode 100644 index 0000000..461eb06 --- /dev/null +++ b/libodb/odb/std-unordered-map-traits.hxx @@ -0,0 +1,133 @@ +// file : odb/std-unordered-map-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_UNORDERED_MAP_TRAITS_HXX +#define ODB_STD_UNORDERED_MAP_TRAITS_HXX + +#include + +#include // std::move +#include + +#include + +namespace odb +{ + template + class access::container_traits> + { + public: + static const container_kind kind = ck_map; + static const bool smart = false; + + typedef std::unordered_map container_type; + + typedef K key_type; + typedef V value_type; + typedef typename container_type::value_type pair_type; + + typedef map_functions 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 (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.select (k, v); + c.insert (pair_type (std::move (k), std::move (v))); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (i->first, i->second); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; + + // @@ Does multimap preserve insertion order of equal elements? The + // current implementation in the generated code does not guarantee + // this. + // + template + class access::container_traits> + { + public: + static const container_kind kind = ck_multimap; + static const bool smart = false; + + typedef std::unordered_multimap container_type; + + typedef K key_type; + typedef V value_type; + typedef typename container_type::value_type pair_type; + + typedef map_functions 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 (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.select (k, v); + c.insert (pair_type (std::move (k), std::move (v))); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (i->first, i->second); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_UNORDERED_MAP_TRAITS_HXX diff --git a/libodb/odb/std-unordered-set-traits.hxx b/libodb/odb/std-unordered-set-traits.hxx new file mode 100644 index 0000000..f590665 --- /dev/null +++ b/libodb/odb/std-unordered-set-traits.hxx @@ -0,0 +1,125 @@ +// file : odb/std-unordered-set-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_UNORDERED_SET_TRAITS_HXX +#define ODB_STD_UNORDERED_SET_TRAITS_HXX + +#include + +#include // std::move +#include + +#include + +namespace odb +{ + template + class access::container_traits> + { + public: + static const container_kind kind = ck_set; + static const bool smart = false; + + typedef std::unordered_set container_type; + typedef V value_type; + + typedef set_functions 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 (*i); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + value_type v; + more = f.select (v); + c.insert (std::move (v)); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (*i); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; + + // @@ Does multiset preserve insertion order of equal elements? The + // current implementation in the generated code does not guarantee + // this. + // + template + class access::container_traits> + { + public: + static const container_kind kind = ck_multiset; + static const bool smart = false; + + typedef std::unordered_multiset container_type; + typedef V value_type; + + typedef set_functions 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 (*i); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + value_type v; + more = f.select (v); + c.insert (std::move (v)); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (typename container_type::const_iterator i (c.begin ()), + e (c.end ()); i != e; ++i) + f.insert (*i); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_UNORDERED_SET_TRAITS_HXX diff --git a/libodb/odb/std-vector-traits.hxx b/libodb/odb/std-vector-traits.hxx new file mode 100644 index 0000000..c6bb39e --- /dev/null +++ b/libodb/odb/std-vector-traits.hxx @@ -0,0 +1,123 @@ +// file : odb/std-vector-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_STD_VECTOR_TRAITS_HXX +#define ODB_STD_VECTOR_TRAITS_HXX + +#include + +#include + +#include + +namespace odb +{ + template + class access::container_traits > + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef std::vector container_type; + + typedef V value_type; + typedef typename container_type::size_type index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + index_type dummy; + c.push_back (value_type ()); + more = f.select (dummy, c.back ()); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; + + // std::vector is special. + // + template + class access::container_traits > + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = false; + + typedef std::vector container_type; + + typedef bool value_type; + typedef typename container_type::size_type index_type; + + typedef ordered_functions functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + } + + static void + load (container_type& c, bool more, const functions& f) + { + c.clear (); + + while (more) + { + index_type dummy; + value_type value; + more = f.select (dummy, value); + c.push_back (value); + } + } + + static void + update (const container_type& c, const functions& f) + { + f.delete_ (); + + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + } + + static void + erase (const functions& f) + { + f.delete_ (); + } + }; +} + +#include + +#endif // ODB_STD_VECTOR_TRAITS_HXX diff --git a/libodb/odb/tr1/lazy-pointer-traits.hxx b/libodb/odb/tr1/lazy-pointer-traits.hxx new file mode 100644 index 0000000..7adf957 --- /dev/null +++ b/libodb/odb/tr1/lazy-pointer-traits.hxx @@ -0,0 +1,61 @@ +// file : odb/tr1/lazy-pointer-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TR1_LAZY_POINTER_TRAITS_HXX +#define ODB_TR1_LAZY_POINTER_TRAITS_HXX + +#include + +#include +#include + +namespace odb +{ + template + class pointer_traits > + { + public: + static const pointer_kind kind = pk_shared; + static const bool lazy = true; + + typedef T element_type; + typedef tr1::lazy_shared_ptr pointer_type; + typedef std::tr1::shared_ptr eager_pointer_type; + + static bool + null_ptr (const pointer_type& p) + { + return !p; + } + + template + static typename object_traits::id_type + object_id (const pointer_type& p) + { + return p.template object_id (); + } + }; + + template + class pointer_traits > + { + public: + static const pointer_kind kind = pk_weak; + static const bool lazy = true; + + typedef T element_type; + typedef tr1::lazy_weak_ptr pointer_type; + typedef tr1::lazy_shared_ptr strong_pointer_type; + typedef std::tr1::weak_ptr eager_pointer_type; + + static strong_pointer_type + lock (const pointer_type& p) + { + return p.lock (); + } + }; +} + +#include + +#endif // ODB_TR1_LAZY_POINTER_TRAITS_HXX diff --git a/libodb/odb/tr1/lazy-ptr.hxx b/libodb/odb/tr1/lazy-ptr.hxx new file mode 100644 index 0000000..b4946ec --- /dev/null +++ b/libodb/odb/tr1/lazy-ptr.hxx @@ -0,0 +1,267 @@ +// file : odb/tr1/lazy-ptr.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TR1_LAZY_PTR_HXX +#define ODB_TR1_LAZY_PTR_HXX + +#include + +// +// This header assumes that the necessary TR1 header has already +// been included. +// + +#include // std::auto_ptr + +#include // odb::database +#include +#include +#include // ODB_CXX11 + +namespace odb +{ + namespace tr1 + { + template + class lazy_weak_ptr; + + // + // + template + class lazy_shared_ptr + { + // The standard shared_ptr interface. + // + public: + typedef T element_type; + + lazy_shared_ptr (); + template explicit lazy_shared_ptr (Y*); + template lazy_shared_ptr (Y*, D); + + lazy_shared_ptr (const lazy_shared_ptr&); + template lazy_shared_ptr (const lazy_shared_ptr&); + template explicit lazy_shared_ptr (const lazy_weak_ptr&); + template explicit lazy_shared_ptr (std::auto_ptr&); + + ~lazy_shared_ptr (); + + lazy_shared_ptr& operator= (const lazy_shared_ptr&); + template lazy_shared_ptr& operator= (const lazy_shared_ptr&); + template lazy_shared_ptr& operator= (std::auto_ptr&); + + void swap (lazy_shared_ptr&); + void reset (); + template void reset (Y*); + template void reset (Y*, D); + + T& operator* () const; + T* operator-> () const; + T* get () const; + + bool unique () const; + long use_count () const; + + typedef std::tr1::shared_ptr 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 lazy_shared_ptr (const std::tr1::shared_ptr&); + template explicit lazy_shared_ptr (const std::tr1::weak_ptr&); + + template lazy_shared_ptr& operator= (const std::tr1::shared_ptr&); + + // Lazy loading interface. + // + public: + typedef odb::database database_type; + + // NULL loaded() + // + // true true NULL pointer to transient object + // false true valid pointer to persistent object + // true false unloaded pointer to persistent object + // false false valid pointer to transient object + // + bool loaded () const; + + std::tr1::shared_ptr load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + std::tr1::shared_ptr get_eager () const; + + template lazy_shared_ptr (DB&, const ID&); + template lazy_shared_ptr (DB&, Y*); + template lazy_shared_ptr (DB&, Y*, D); + template lazy_shared_ptr (DB&, std::auto_ptr&); + template lazy_shared_ptr (DB&, const std::tr1::shared_ptr&); + template lazy_shared_ptr (DB&, const std::tr1::weak_ptr&); + + template void reset (DB&, const ID&); + template void reset (DB&, Y*); + template void reset (DB&, Y*, D); + template void reset (DB&, std::auto_ptr&); + template void reset (DB&, const std::tr1::shared_ptr&); + +#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT + template +#else + template +#endif + typename object_traits::id_type object_id () const; + + database_type& database () const; + + // Helpers. + // + public: + template bool equal (const lazy_shared_ptr&) const; + + private: + template friend class lazy_shared_ptr; + template friend class lazy_weak_ptr; + + // For lazy_weak_ptr::lock(). + // + lazy_shared_ptr (const std::tr1::shared_ptr& p, + const lazy_ptr_impl& i) + : p_ (p), i_ (i) {} + + private: + mutable std::tr1::shared_ptr p_; + mutable lazy_ptr_impl i_; + }; + + // operator< and operator<< are not provided. + // + template + bool operator== (const lazy_shared_ptr&, const lazy_shared_ptr&); + + template + bool operator!= (const lazy_shared_ptr&, const lazy_shared_ptr&); + + template void swap (lazy_shared_ptr&, lazy_shared_ptr&); + + template + D* get_deleter (const lazy_shared_ptr&); + + // + // + template + class lazy_weak_ptr + { + // The standard weak_ptr interface. + // + public: + typedef T element_type; + + lazy_weak_ptr (); + template lazy_weak_ptr (const lazy_shared_ptr&); + lazy_weak_ptr (const lazy_weak_ptr&); + template lazy_weak_ptr (const lazy_weak_ptr&); + + ~lazy_weak_ptr (); + + lazy_weak_ptr& operator= (const lazy_weak_ptr&); + template lazy_weak_ptr& operator= (const lazy_weak_ptr&); + template lazy_weak_ptr& operator= (const lazy_shared_ptr&); + + void swap (lazy_weak_ptr&); + void reset (); + + long use_count () const; + bool expired () const; + + lazy_shared_ptr lock () const; + + // Initialization/assignment from shared_ptr and weak_ptr. + // + public: + template lazy_weak_ptr (const std::tr1::weak_ptr&); + template lazy_weak_ptr (const std::tr1::shared_ptr&); + + template lazy_weak_ptr& operator= (const std::tr1::weak_ptr&); + template lazy_weak_ptr& operator= (const std::tr1::shared_ptr&); + + // 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 transient object + // + bool loaded () const; + + // Performs both lock and load. + // + std::tr1::shared_ptr load () const; + + // Unload the pointer. For transient objects this function is + // equivalent to reset(). + // + void unload () const; + + // Get the underlying eager pointer. If this is an unloaded pointer + // to a persistent object, then the returned pointer will be NULL. + // + std::tr1::weak_ptr get_eager () const; + + template lazy_weak_ptr (DB&, const ID&); + template lazy_weak_ptr (DB&, const std::tr1::shared_ptr&); + template lazy_weak_ptr (DB&, const std::tr1::weak_ptr&); + + template void reset (DB&, const ID&); + template void reset (DB&, const std::tr1::shared_ptr&); + template void reset (DB&, const std::tr1::weak_ptr&); + + // The object_id() function can only be called when the object is + // persistent, or: expired() XOR loaded() (can use != for XOR). + // +#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT + template +#else + template +#endif + typename object_traits::id_type object_id () const; + + database_type& database () const; + + private: + template friend class lazy_shared_ptr; + template friend class lazy_weak_ptr; + + mutable std::tr1::weak_ptr p_; + mutable lazy_ptr_impl i_; + }; + + // operator< is not provided. + // + template void swap (lazy_weak_ptr&, lazy_weak_ptr&); + } +} + +#include +#include + +#include + +#include + +#endif // ODB_TR1_LAZY_PTR_HXX diff --git a/libodb/odb/tr1/lazy-ptr.ixx b/libodb/odb/tr1/lazy-ptr.ixx new file mode 100644 index 0000000..dc5000f --- /dev/null +++ b/libodb/odb/tr1/lazy-ptr.ixx @@ -0,0 +1,638 @@ +// file : odb/tr1/lazy-ptr.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace tr1 + { + // + // lazy_shared_ptr + // + + template + inline lazy_shared_ptr:: + lazy_shared_ptr () {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (Y* p): p_ (p) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (Y* p, D d): p_ (p, d) {} + + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const lazy_weak_ptr& 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 std::tr1::bad_weak_ptr (); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (std::auto_ptr& r): p_ (r) {} + + template + inline lazy_shared_ptr:: + ~lazy_shared_ptr () {} + + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (std::auto_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + inline void lazy_shared_ptr:: + swap (lazy_shared_ptr& b) + { + p_.swap (b.p_); + i_.swap (b.i_); + } + + template + inline void lazy_shared_ptr:: + reset () + { + p_.reset (); + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (Y* p) + { + p_.reset (p); + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (Y* p, D d) + { + p_.reset (p, d); + i_.reset (); + } + + template + inline T& lazy_shared_ptr:: + operator* () const + { + return *p_; + } + + template + inline T* lazy_shared_ptr:: + operator-> () const + { + return p_.operator-> (); + } + + template + inline T* lazy_shared_ptr:: + get () const + { + return p_.get (); + } + + template + inline bool lazy_shared_ptr:: + unique () const + { + return p_.unique (); + } + + template + inline long lazy_shared_ptr:: + use_count () const + { + return p_.use_count (); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const std::tr1::shared_ptr& r): p_ (r) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (const std::tr1::weak_ptr& r): p_ (r) {} + + template + template + inline lazy_shared_ptr& lazy_shared_ptr:: + operator= (const std::tr1::shared_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + inline bool lazy_shared_ptr:: + loaded () const + { + bool i (i_); + return !p_ != i; // !p_ XOR i_ + } + + template + inline std::tr1::shared_ptr lazy_shared_ptr:: + load () const + { + if (!p_ && i_) + p_ = i_.template load (true); // Reset id. + + return p_; + } + + template + inline void lazy_shared_ptr:: + unload () const + { + typedef typename object_traits::object_type object_type; + + if (p_) + { + if (i_.database () != 0) + i_.reset_id (object_traits::id (*p_)); + + p_.reset (); + } + } + + template + inline std::tr1::shared_ptr lazy_shared_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, const ID& id): i_ (db, id) {} + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, Y* p) + : p_ (p) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, Y* p, D d) + : p_ (p, d) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, std::auto_ptr& r) + : p_ (r) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, const std::tr1::shared_ptr& r) + : p_ (r) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline lazy_shared_ptr:: + lazy_shared_ptr (DB& db, const std::tr1::weak_ptr& r) + : p_ (r) + { + if (p_) + i_.reset_db (db); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, Y* p) + { + p_.reset (p); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, Y* p, D d) + { + p_.reset (p, d); + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, std::auto_ptr& r) + { + p_ = r; + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline void lazy_shared_ptr:: + reset (DB& db, const std::tr1::shared_ptr& r) + { + p_ = r; + + if (p_) + i_.reset_db (db); + else + i_.reset (); + } + + template + template + inline typename object_traits::id_type lazy_shared_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + return p_ + ? object_traits::id (*p_) + : i_.template object_id (); + } + + template + inline typename lazy_shared_ptr::database_type& lazy_shared_ptr:: + database () const + { + return *i_.database (); + } + + template + inline bool + operator== (const lazy_shared_ptr& a, const lazy_shared_ptr& b) + { + return a.equal (b); + } + + template + inline bool + operator!= (const lazy_shared_ptr& a, const lazy_shared_ptr& b) + { + return !a.equal (b); + } + + template + inline void + swap (lazy_shared_ptr& a, lazy_shared_ptr& b) + { + a.swap (b); + } + + template + inline D* + get_deleter (const lazy_shared_ptr& p) + { + return std::tr1::get_deleter (p.p_); + } + + + // + // lazy_weak_ptr + // + + template + inline lazy_weak_ptr:: + lazy_weak_ptr () {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} + + template + inline lazy_weak_ptr:: + ~lazy_weak_ptr () {} + + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const lazy_weak_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const lazy_weak_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const lazy_shared_ptr& r) + { + p_ = r.p_; + i_ = r.i_; + return *this; + } + + template + inline void lazy_weak_ptr:: + swap (lazy_weak_ptr& r) + { + p_.swap (r.p_); + i_.swap (r.i_); + } + + template + inline void lazy_weak_ptr:: + reset () + { + p_.reset (); + i_.reset (); + } + + template + inline long lazy_weak_ptr:: + use_count () const + { + return p_.use_count (); + } + + template + inline bool lazy_weak_ptr:: + expired () const + { + return p_.expired (); + } + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const std::tr1::weak_ptr& r): p_ (r) {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (const std::tr1::shared_ptr& r): p_ (r) {} + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const std::tr1::weak_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + template + inline lazy_weak_ptr& lazy_weak_ptr:: + operator= (const std::tr1::shared_ptr& r) + { + p_ = r; + i_.reset (); + return *this; + } + + template + inline bool lazy_weak_ptr:: + loaded () const + { + bool i (i_); + return expired () != i; // expired () XOR i_ + } + + template + inline lazy_shared_ptr lazy_weak_ptr:: + lock () const + { + return lazy_shared_ptr (p_.lock (), i_); + } + + template + inline std::tr1::shared_ptr lazy_weak_ptr:: + load () const + { + std::tr1::shared_ptr r (p_.lock ()); + + if (!r && i_) + { + r = i_.template load (false); // Keep id. + p_ = r; + } + + return r; + } + + template + inline void lazy_weak_ptr:: + unload () const + { + // With weak pointer we always keep i_ up to date. + // + p_.reset (); + } + + template + inline std::tr1::weak_ptr lazy_weak_ptr:: + get_eager () const + { + return p_; + } + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (DB& db, const ID& id): i_ (db, id) {} + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (DB& db, const std::tr1::shared_ptr& r) + : p_ (r) + { + typedef typename object_traits::object_type object_type; + + if (r) + i_.reset (db, object_traits::id (*r)); + } + + template + template + inline lazy_weak_ptr:: + lazy_weak_ptr (DB& db, const std::tr1::weak_ptr& r) + : p_ (r) + { + typedef typename object_traits::object_type object_type; + + std::tr1::shared_ptr sp (p_.lock ()); + + if (sp) + i_.reset (db, object_traits::id (*sp)); + } + + template + template + inline void lazy_weak_ptr:: + reset (DB& db, const ID& id) + { + p_.reset (); + i_.reset (db, id); + } + + template + template + inline void lazy_weak_ptr:: + reset (DB& db, const std::tr1::shared_ptr& r) + { + typedef typename object_traits::object_type object_type; + + p_ = r; + + if (r) + i_.reset (db, object_traits::id (*r)); + else + i_.reset (); + } + + template + template + inline void lazy_weak_ptr:: + reset (DB& db, const std::tr1::weak_ptr& r) + { + typedef typename object_traits::object_type object_type; + + p_ = r; + std::tr1::shared_ptr sp (p_.lock ()); + + if (sp) + i_.reset (db, object_traits::id (*sp)); + else + i_.reset (); + } + + template + template + inline typename object_traits::id_type lazy_weak_ptr:: + object_id () const + { + typedef typename object_traits::object_type object_type; + + std::tr1::shared_ptr sp (p_.lock ()); + return sp + ? object_traits::id (*sp) + : i_.template object_id (); + } + + template + inline typename lazy_weak_ptr::database_type& lazy_weak_ptr:: + database () const + { + return *i_.database (); + } + + template + inline void + swap (lazy_weak_ptr& a, lazy_weak_ptr& b) + { + a.swap (b); + } + } +} diff --git a/libodb/odb/tr1/lazy-ptr.txx b/libodb/odb/tr1/lazy-ptr.txx new file mode 100644 index 0000000..7e36cd9 --- /dev/null +++ b/libodb/odb/tr1/lazy-ptr.txx @@ -0,0 +1,43 @@ +// file : odb/tr1/lazy-ptr.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + namespace tr1 + { + // + // lazy_shared_ptr + // + + template + template + bool lazy_shared_ptr:: + equal (const lazy_shared_ptr& r) const + { + bool t1 (!p_ == loaded ()); + bool t2 (!r.p_ == r.loaded ()); + + // If both are transient, then compare the underlying pointers. + // + if (t1 && t2) + return p_ == r.p_; + + // If one is transient and the other is persistent, then compare + // the underlying pointers but only if they are non NULL. Note + // that an unloaded persistent object is always unequal to a + // transient object. + // + if (t1 || t2) + return p_ == r.p_ && p_; + + // If both objects are persistent, then we compare databases and + // object ids. + // + typedef typename object_traits::object_type object_type1; + typedef typename object_traits::object_type object_type2; + + return i_.database () == r.i_.database () && + object_id () == r.template object_id (); + } + } +} diff --git a/libodb/odb/tr1/memory.hxx b/libodb/odb/tr1/memory.hxx new file mode 100644 index 0000000..b9e9f45 --- /dev/null +++ b/libodb/odb/tr1/memory.hxx @@ -0,0 +1,37 @@ +// file : odb/tr1/memory.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TR1_MEMORY_HXX +#define ODB_TR1_MEMORY_HXX + +// +// Try to include TR1 in a compiler-specific manner. Fall back +// on the Boost TR1 implementation if the compiler does not support TR1. +// + +#include // __GLIBCXX__, _HAS_TR1 + +// GNU C++ or Intel C++ using libstd++. +// +#if defined (__GNUC__) && __GNUC__ >= 4 && defined (__GLIBCXX__) +# include +// +// IBM XL C++. +// +#elif defined (__xlC__) && __xlC__ >= 0x0900 +# define __IBMCPP_TR1__ +# include +// +// VC++ or Intel C++ using VC++ standard library. +// +#elif defined (_MSC_VER) && \ + (_MSC_VER == 1500 && defined (_HAS_TR1) || _MSC_VER > 1500) +# include +// +// Boost fall-back. +// +#else +# include +#endif + +#endif // ODB_TR1_MEMORY_HXX diff --git a/libodb/odb/tr1/pointer-traits.hxx b/libodb/odb/tr1/pointer-traits.hxx new file mode 100644 index 0000000..df4f25f --- /dev/null +++ b/libodb/odb/tr1/pointer-traits.hxx @@ -0,0 +1,121 @@ +// file : odb/tr1/pointer-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TR1_POINTER_TRAITS_HXX +#define ODB_TR1_POINTER_TRAITS_HXX + +#include + +#include // ODB_CXX11 + +// In VC++ std::shared_ptr and std::tr1::shared_ptr is the same class +// template. One is just a using-declaration for the other. +// +#if !(defined(ODB_CXX11) && defined(_MSC_VER)) + +// +// This header assumes that the necessary TR1 header has already +// been included. +// + +#include +#include + +namespace odb +{ + // Specialization for std::tr1::shared_ptr. + // + template + class pointer_traits > + { + public: + static const pointer_kind kind = pk_shared; + static const bool lazy = false; + + typedef T element_type; + typedef std::tr1::shared_ptr pointer_type; + typedef std::tr1::shared_ptr const_pointer_type; + typedef typename odb::details::meta::remove_const::result + unrestricted_element_type; + typedef std::tr1::shared_ptr + unrestricted_pointer_type; + typedef smart_ptr_guard 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; + } + + static unrestricted_pointer_type + const_pointer_cast (const pointer_type& p) + { + return std::tr1::const_pointer_cast (p); + } + + template + static std::tr1::shared_ptr + static_pointer_cast (const pointer_type& p) + { + return std::tr1::static_pointer_cast (p); + } + + template + static std::tr1::shared_ptr + dynamic_pointer_cast (const pointer_type& p) + { + return std::tr1::dynamic_pointer_cast (p); + } + + public: + static void* + allocate (std::size_t n) + { + return operator new (n); + } + + static void + free (void* p) + { + operator delete (p); + } + }; + + // Specialization for std::tr1::weak_ptr. + // + template + class pointer_traits > + { + public: + static const pointer_kind kind = pk_weak; + static const bool lazy = false; + + typedef T element_type; + typedef std::tr1::weak_ptr pointer_type; + typedef std::tr1::shared_ptr strong_pointer_type; + + static strong_pointer_type + lock (const pointer_type& p) + { + return p.lock (); + } + }; +} + +#endif // !(ODB_CXX11 && _MSC_VER) + +#include + +#endif // ODB_TR1_POINTER_TRAITS_HXX diff --git a/libodb/odb/tr1/wrapper-traits.hxx b/libodb/odb/tr1/wrapper-traits.hxx new file mode 100644 index 0000000..f878ef6 --- /dev/null +++ b/libodb/odb/tr1/wrapper-traits.hxx @@ -0,0 +1,76 @@ +// file : odb/tr1/wrapper-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TR1_WRAPPER_TRAITS_HXX +#define ODB_TR1_WRAPPER_TRAITS_HXX + +#include + +#include // ODB_CXX11 + +// In VC++ std::shared_ptr and std::tr1::shared_ptr is the same class +// template. One is just a using-declaration for the other. +// +#if !(defined(ODB_CXX11) && defined(_MSC_VER)) + +// +// This header assumes that the necessary TR1 header has already +// been included. +// + +#include + +namespace odb +{ + // Specialization for std::tr1::shared_ptr. + // + template + class wrapper_traits< std::tr1::shared_ptr > + { + public: + typedef T wrapped_type; + typedef std::tr1::shared_ptr wrapper_type; + + // T can be const. + // + typedef + typename odb::details::meta::remove_const::result + unrestricted_wrapped_type; + + static const bool null_handler = true; + static const bool null_default = false; + + static bool + get_null (const wrapper_type& p) + { + return !p; + } + + static void + set_null (wrapper_type& p) + { + p.reset (); + } + + static const wrapped_type& + get_ref (const wrapper_type& p) + { + return *p; + } + + static unrestricted_wrapped_type& + set_ref (wrapper_type& p) + { + if (!p) + p.reset (new unrestricted_wrapped_type); + + return const_cast (*p); + } + }; +} + +#endif // !(ODB_CXX11 && _MSC_VER) + +#include + +#endif // ODB_TR1_WRAPPER_TRAITS_HXX diff --git a/libodb/odb/tracer.cxx b/libodb/odb/tracer.cxx new file mode 100644 index 0000000..1e636a7 --- /dev/null +++ b/libodb/odb/tracer.cxx @@ -0,0 +1,95 @@ +// file : odb/tracer.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +#include +#include + +using namespace std; + +namespace odb +{ + // + // tracer + // + + tracer:: + ~tracer () + { + } + + void tracer:: + prepare (connection&, const statement&) + { + } + + void tracer:: + execute (connection& c, const statement& s) + { + execute (c, s.text ()); + } + + void tracer:: + deallocate (connection&, const statement&) + { + } + + // + // stderr_tracer + // + + class stderr_tracer_type: public tracer + { + public: + stderr_tracer_type (bool full): full_ (full) {} + + virtual void + prepare (connection&, const statement&); + + virtual void + execute (connection&, const char* statement); + + virtual void + deallocate (connection&, const statement&); + + // Override the other version to get rid of a Sun CC warning. + // + virtual void + execute (connection&, const statement&); + + private: + bool full_; + }; + + void stderr_tracer_type:: + prepare (connection&, const statement& s) + { + if (full_) + cerr << "PREPARE " << s.text () << endl; + } + + void stderr_tracer_type:: + execute (connection&, const char* s) + { + cerr << s << endl; + } + + void stderr_tracer_type:: + deallocate (connection&, const statement& s) + { + if (full_) + cerr << "DEALLOCATE " << s.text () << endl; + } + + void stderr_tracer_type:: + execute (connection& c, const statement& s) + { + execute (c, s.text ()); + } + + static stderr_tracer_type stderr_tracer_ (false); + static stderr_tracer_type stderr_full_tracer_ (true); + tracer& stderr_tracer = stderr_tracer_; + tracer& stderr_full_tracer = stderr_full_tracer_; +} diff --git a/libodb/odb/tracer.hxx b/libodb/odb/tracer.hxx new file mode 100644 index 0000000..11e4e76 --- /dev/null +++ b/libodb/odb/tracer.hxx @@ -0,0 +1,36 @@ +// file : odb/tracer.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TRACER_HXX +#define ODB_TRACER_HXX + +#include + +#include +#include + +namespace odb +{ + class LIBODB_EXPORT tracer + { + public: + virtual + ~tracer (); + + virtual void + prepare (connection&, const statement&); + + virtual void + execute (connection&, const statement&); + + virtual void + execute (connection&, const char* statement) = 0; + + virtual void + deallocate (connection&, const statement&); + }; +} + +#include + +#endif // ODB_TRACER_HXX diff --git a/libodb/odb/traits.hxx b/libodb/odb/traits.hxx new file mode 100644 index 0000000..2c6f5d6 --- /dev/null +++ b/libodb/odb/traits.hxx @@ -0,0 +1,317 @@ +// file : odb/traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TRAITS_HXX +#define ODB_TRAITS_HXX + +#include + +#include +#include + +namespace odb +{ + // Fallback dummy for non-persistent classes. It is necessary to allow + // the C++ compiler to instantiate persist(), etc., signatures in class + // database when T is a pointer (raw, smart). The overloads that use + // these dummy would never actually be selected by the compiler. + // + template + class access::object_traits + { + // If a C++ compiler issues an error pointing to this class and saying + // that it is missing some declaration, then you are most likely trying + // to perform a database operation on a C++ type that is not a persistent + // object. Or you forgot to include the corresponding -odb.hxx file. + // + public: + struct id_type {}; + typedef T object_type; + typedef T* pointer_type; + + static const bool polymorphic = false; + }; + + template + class access::object_factory + { + public: + typedef T object_type; + typedef P pointer_type; + + static P + create () + { + // By default use pointer-specific construction. + // + return pointer_factory::create (); + } + }; + + template + class access::view_factory + { + public: + typedef T view_type; + typedef P pointer_type; + + static P + create () + { + // By default use pointer-specific construction. + // + return pointer_factory::create (); + } + }; + + template + class access::pointer_factory + { + public: + typedef T value_type; + typedef P pointer_type; + + + // Suppress bogus use-after-free introduced in GCC 12 (GCC bug #105327). + // +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuse-after-free" +#endif + + static P + create () + { + void* v (pointer_traits

::allocate (sizeof (T))); + mem_guard g (v); + P p (new (v) T); + g.release (); + return p; + } + +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12 +#pragma GCC diagnostic pop +#endif + + private: + struct mem_guard + { + mem_guard (void* p): p_ (p) {} + ~mem_guard () {if (p_) pointer_traits

::free (p_);} + void release () {p_ = 0;} + void* p_; + }; + }; + + // + // class_traits + // + enum class_kind + { + class_object, + class_view, + class_other + }; + + template + struct class_traits + { + static const class_kind kind = class_other; + }; + + template + struct class_traits + { + static const class_kind kind = class_traits::kind; + }; + + // + // object_traits + // + + template + // + // If a C++ compiler issues an error pointing to this struct and + // saying that it is incomplete, then you are most likely trying to + // perform a database operation on a C++ type that is not a persistent + // object. Or you forgot to include the corresponding -odb.hxx file. + // + struct object_traits: + access::object_traits, + access::object_factory::pointer_type> + { + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + typedef typename access::object_traits::object_type object_type; + typedef typename access::object_traits::pointer_type pointer_type; + typedef typename pointer_traits::const_pointer_type const_pointer_type; + }; + + // Specialization for const objects. It only defines the id, object, + // pointer, and const_pointer types with pointer and const_pointer + // being the same. The idea is to only use this specialization in the + // interfaces, with the implementations detecting this situation and + // using the non-const object_traits version. + // + template + struct object_traits + { + private: + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + public: + typedef typename access::object_traits::id_type id_type; + typedef typename access::object_traits::object_type object_type; + typedef typename pointer_traits::const_pointer_type const_pointer_type; + typedef const_pointer_type pointer_type; + + static const bool polymorphic = access::object_traits::polymorphic; + }; + + // Specialization for section to allow instantiation of all the load() + // signature. + // + template <> + struct object_traits

{}; + + template + // + // If a C++ compiler issues an error pointing to this struct and + // saying that it is incomplete, then you are most likely trying to + // perform a database operation on a C++ type that is not a persistent + // object. Or you forgot to include the corresponding -odb.hxx file. + // + struct object_traits_impl: + access::object_traits_impl, + access::object_factory::pointer_type> + { + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + typedef typename access::object_traits::object_type object_type; + typedef typename access::object_traits::pointer_type pointer_type; + typedef typename pointer_traits::const_pointer_type const_pointer_type; + }; + + // + // view_traits + // + + template + // + // If a C++ compiler issues an error pointing to this struct and + // saying that it is incomplete, then you are most likely trying to + // perform a database operation on a C++ type that is not a view + // Or you forgot to include the corresponding -odb.hxx file. + // + struct view_traits: + access::view_traits, + access::view_factory::pointer_type> + { + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + typedef typename access::view_traits::view_type view_type; + typedef typename access::view_traits::pointer_type pointer_type; + }; + + // Specialization for const views. It only defines the view, pointer, + // and const_pointer types with pointer and const_pointer being the + // same. Similar to objects, the idea is to only use this specialization + // in the interfaces, with the implementations detecting this situation + // and using the non-const view_traits version. + // + template + struct view_traits + { + private: + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + public: + typedef typename access::view_traits::view_type view_type; + typedef typename pointer_traits::const_pointer_type const_pointer_type; + typedef const_pointer_type pointer_type; + }; + + template + // + // If a C++ compiler issues an error pointing to this struct and + // saying that it is incomplete, then you are most likely trying to + // perform a database operation on a C++ type that is not a view + // Or you forgot to include the corresponding -odb.hxx file. + // + struct view_traits_impl: + access::view_traits_impl, + access::view_factory::pointer_type> + { + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + typedef typename access::view_traits::view_type view_type; + typedef typename access::view_traits::pointer_type pointer_type; + }; + + // + // composite_value_traits + // + + template + struct composite_value_traits: access::composite_value_traits + { + }; + + // + // Get root image from a polymorphic image chain. + // + + template + struct root_image_impl + { + typedef root_image_impl base_type; + typedef typename base_type::image_type image_type; + + static image_type& + get (typename T::image_type& i) {return base_type::get (*i.base);} + }; + + template + struct root_image_impl + { + typedef typename T::image_type image_type; + + static image_type& + get (image_type& i) {return i;} + }; + + template + struct root_image + { + typedef root_image_impl impl_type; + typedef typename impl_type::image_type image_type; + + static image_type& + get (typename T::image_type& i) {return impl_type::get (i);} + }; + + template + struct root_image + { + typedef typename T::image_type image_type; + + static image_type& + get (image_type& i) {return i;} + }; +} + +#include + +#endif // ODB_TRAITS_HXX diff --git a/libodb/odb/transaction.cxx b/libodb/odb/transaction.cxx new file mode 100644 index 0000000..f75cf32 --- /dev/null +++ b/libodb/odb/transaction.cxx @@ -0,0 +1,356 @@ +// file : odb/transaction.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include +#include + +#include + +using namespace std; + +namespace odb +{ + using namespace details; + + // + // transaction + // + + static ODB_TLS_POINTER (transaction) current_transaction; + + transaction:: + ~transaction () + { + if (!finalized_) + try {rollback ();} catch (...) {} + } + + void transaction:: + reset (transaction_impl* impl, bool make_current) + { + details::unique_ptr i (impl); + + if (!finalized_) + rollback (); + + impl_.reset (i.release ()); + + if (make_current && tls_get (current_transaction) != 0) + throw already_in_transaction (); + + impl_->start (); + finalized_ = false; + + if (make_current) + tls_set (current_transaction, this); + } + + bool transaction:: + has_current () + { + return tls_get (current_transaction) != 0; + } + + transaction& transaction:: + current () + { + transaction* cur (tls_get (current_transaction)); + + if (cur == 0) + throw not_in_transaction (); + + return *cur; + } + + void transaction:: + current (transaction& t) + { + tls_set (current_transaction, &t); + } + + void transaction:: + reset_current () + { + transaction* t (0); + tls_set (current_transaction, t); + } + + struct rollback_guard + { + rollback_guard (transaction& t): t_ (&t) {} + ~rollback_guard () + {if (t_ != 0) t_->callback_call (transaction::event_rollback);} + void release () {t_ = 0;} + private: + transaction* t_; + }; + + void transaction:: + commit () + { + if (finalized_) + throw transaction_already_finalized (); + + finalized_ = true; + rollback_guard rg (*this); + + impl_->tracer (0); + + if (tls_get (current_transaction) == this) + { + transaction* t (0); + tls_set (current_transaction, t); + } + + impl_->commit (); + rg.release (); + + if (callback_count_ != 0) + callback_call (event_commit); + } + + void transaction:: + rollback () + { + if (finalized_) + throw transaction_already_finalized (); + + finalized_ = true; + rollback_guard rg (*this); + + impl_->tracer (0); + + if (tls_get (current_transaction) == this) + { + transaction* t (0); + tls_set (current_transaction, t); + } + + impl_->rollback (); + rg.release (); + + if (callback_count_ != 0) + callback_call (event_rollback); + } + + void transaction:: + callback_call (unsigned short event) + { + size_t stack_count (callback_count_ < stack_callback_count + ? callback_count_ : stack_callback_count); + size_t dyn_count (callback_count_ - stack_count); + + // We need to be careful with the situation where a callback + // throws and we neither call the rest of the callbacks nor + // reset their states. To make sure this doesn't happen, we + // do a first pass and reset all the states. + // + for (size_t i (0); i < stack_count; ++i) + { + callback_data& d (stack_callbacks_[i]); + if (d.event != 0 && d.state != 0) + *d.state = 0; + } + + for (size_t i (0); i < dyn_count; ++i) + { + callback_data& d (dyn_callbacks_[i]); + if (d.event != 0 && d.state != 0) + *d.state = 0; + } + + // Now do the actual calls. + // + for (size_t i (0); i < stack_count; ++i) + { + callback_data& d (stack_callbacks_[i]); + if (d.event & event) + d.func (event, d.key, d.data); + } + + for (size_t i (0); i < dyn_count; ++i) + { + callback_data& d (dyn_callbacks_[i]); + if (d.event & event) + d.func (event, d.key, d.data); + } + + // Clean things up in case this instance is going to be reused. + // + if (dyn_count != 0) + dyn_callbacks_.clear (); + + free_callback_ = max_callback_count; + callback_count_ = 0; + } + + void transaction:: + callback_register (callback_type func, + void* key, + unsigned short event, + unsigned long long data, + transaction** state) + { + callback_data* s; + + // If we have a free slot, use it. + // + if (free_callback_ != max_callback_count) + { + s = (free_callback_ < stack_callback_count) + ? stack_callbacks_ + free_callback_ + : &dyn_callbacks_[free_callback_ - stack_callback_count]; + + free_callback_ = reinterpret_cast (s->key); + } + // If we have space in the stack, grab that. + // + else if (callback_count_ < stack_callback_count) + { + s = stack_callbacks_ + callback_count_; + callback_count_++; + } + // Otherwise use the dynamic storage. + // + else + { + dyn_callbacks_.push_back (callback_data ()); + s = &dyn_callbacks_.back (); + callback_count_++; + } + + s->func = func; + s->key = key; + s->event = event; + s->data = data; + s->state = state; + } + + size_t transaction:: + callback_find (void* key) + { + if (callback_count_ == 0) + return 0; + + size_t stack_count; + + // See if this is the last slot registered. This will be a fast path if, + // for example, things are going to be unregistered from destructors. + // + if (callback_count_ <= stack_callback_count) + { + if (stack_callbacks_[callback_count_ - 1].key == key) + return callback_count_ - 1; + + stack_count = callback_count_; + } + else + { + if (dyn_callbacks_.back ().key == key) + return callback_count_ - 1; + + stack_count = stack_callback_count; + } + + // Otherwise do a linear search. + // + for (size_t i (0); i < stack_count; ++i) + if (stack_callbacks_[i].key == key) + return i; + + for (size_t i (0), dyn_count (callback_count_ - stack_count); + i < dyn_count; ++i) + if (dyn_callbacks_[i].key == key) + return i + stack_callback_count; + + return callback_count_; + } + + void transaction:: + callback_unregister (void* key) + { + size_t i (callback_find (key)); + + // It is ok for this function not to find the key. + // + if (i == callback_count_) + return; + + // See if this is the last slot registered. + // + if (i == callback_count_ - 1) + { + if (i >= stack_callback_count) + dyn_callbacks_.pop_back (); + + callback_count_--; + } + else + { + callback_data& d ( + i < stack_callback_count + ? stack_callbacks_[i] + : dyn_callbacks_[i - stack_callback_count]); + + // Add to the free list. + // + d.event = 0; + d.key = reinterpret_cast (free_callback_); + free_callback_ = i; + } + } + + void transaction:: + callback_update (void* key, + unsigned short event, + unsigned long long data, + transaction** state) + { + size_t i (callback_find (key)); + + // It is ok for this function not to find the key. + // + if (i == callback_count_) + return; + + callback_data& d ( + i < stack_callback_count + ? stack_callbacks_[i] + : dyn_callbacks_[i - stack_callback_count]); + + d.event = event; + d.data = data; + d.state = state; + } + + // + // transaction_impl + // + + transaction_impl:: + ~transaction_impl () + { + } + + connection& transaction_impl:: + connection (database_type* db) + { + assert (db == 0 || db == &database_); + return *connection_; + } + + // The transaction-specific tracer is stored in the connection. See the + // connection class for the reason. + // + void transaction_impl:: + tracer (tracer_type* t) + { + connection_->transaction_tracer_ = t; + } + + tracer* transaction_impl:: + tracer () const + { + return connection_->transaction_tracer_; + } +} diff --git a/libodb/odb/transaction.hxx b/libodb/odb/transaction.hxx new file mode 100644 index 0000000..1958df3 --- /dev/null +++ b/libodb/odb/transaction.hxx @@ -0,0 +1,278 @@ +// file : odb/transaction.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_TRANSACTION_HXX +#define ODB_TRANSACTION_HXX + +#include + +#include +#include // std::size_t + +#include + +#include +#include + +namespace odb +{ + class transaction_impl; + + class LIBODB_EXPORT transaction + { + public: + typedef odb::database database_type; + typedef odb::connection connection_type; + + // If the second argument is false, then this transaction is not made + // the current transaction of the thread. + // + explicit + transaction (transaction_impl*, bool make_current = true); + + // Create a finalized transaction instance which can later be initialized + // with reset(). + // + transaction (); + + // Unless the transaction has already been finalized (explicitly + // committed or rolled back), the destructor will roll it back. + // + ~transaction (); + + // Unless the current transaction has already been finalized (explicitly + // committed or rolled back), reset will roll it back. If the second + // argument is false, then this transaction is not made the current + // transaction of the thread. + // + void + reset (transaction_impl*, bool make_current = true); + + void + commit (); + + void + rollback (); + + // Return the database this transaction is on. + // + database_type& + database (); + + // Return the connection this transaction is on. + // + // The second version verifies the connection is to the specified + // database. For database implementations that support attaching multiple + // databases it may also select the connection corresponding to the + // specified database. + // + connection_type& + connection (); + + connection_type& + connection (database_type&); + + bool + finalized () const {return finalized_;} + + public: + // Return true if there is a transaction in effect. + // + static bool + has_current (); + + // Return current transaction or throw if there is no transaction + // in effect. + // + static transaction& + current (); + + // Set the current thread's transaction. + // + static void + current (transaction&); + + // Revert to the no transaction in effect state for the current thread. + // + static void + reset_current (); + + // SQL statement tracing. + // + public: + typedef odb::tracer tracer_type; + + void + tracer (tracer_type&); + + void + tracer (tracer_type*); + + tracer_type* + tracer () const; + + // Post-commit/rollback callbacks. + // + public: + static const unsigned short event_commit = 0x01; + static const unsigned short event_rollback = 0x02; + static const unsigned short event_all = event_commit | event_rollback; + + typedef void (*callback_type) ( + unsigned short event, void* key, unsigned long long data); + + // Register a post-commit/rollback callback. The data argument + // can be used to store any user data that does not exceed 8 + // bytes and doesn't require alignment greater than unsigned + // long long, such as an old value that needs to be restored + // in case of a rollback. + // + // The state argument can be used to indicate to the caller + // that the callback has been unregistered because the + // transaction has terminated. In this case the transaction + // resets the passed pointer to 0. + // + // Note that the order in which the callbacks are called is + // unspecified. + // + void + callback_register (callback_type, + void* key, + unsigned short event = event_all, + unsigned long long data = 0, + transaction** state = 0); + + // Unregister a post-commit/rollback callback. Note that this is a + // potentially slow operation. You also don't need to unregister + // a callback that has been called or auto-reset using the state + // argument passed to register(). This function does nothing if + // the key is not found. + // + void + callback_unregister (void* key); + + // Update the event, data, and state values for a callback. Note + // that just like unregister(), this is a potentially slow operation. + // + void + callback_update (void* key, + unsigned short event, + unsigned long long data = 0, + transaction** state = 0); + + public: + transaction_impl& + implementation (); + + // Copying or assignment of transactions is not supported. + // + private: + transaction (const transaction&); + transaction& operator= (const transaction&); + + protected: + friend struct rollback_guard; + + std::size_t + callback_find (void* key); + + void + callback_call (unsigned short event); + + protected: + bool finalized_; + details::unique_ptr impl_; + + // Callbacks. + // + struct callback_data + { + unsigned short event; + callback_type func; + void* key; + unsigned long long data; + transaction** state; + }; + + // Slots for the first 20 callback are pre-allocated on the stack. + // For the rest they are allocated dynamically as needed. + // + // Note, if you change stack_callback_count, make sure you also + // update the common/transaction/callback test accordingly. + // + static const std::size_t stack_callback_count = 20; + static const std::size_t max_callback_count = ~(std::size_t (0)); + + callback_data stack_callbacks_[stack_callback_count]; + std::vector dyn_callbacks_; + + // When a callback is unregistered, the free slot from the stack is + // added to the linked list of free slots which is organized by + // re-using the key data member to store the slot's index (we cannot + // store a pointer because std::vector may move slots on expansion). + // The value equal to max_callback_count indicates no free slots are + // available. + // + std::size_t free_callback_; + + // Total number of used slots, both registered and in the free list. + // + std::size_t callback_count_; + }; + + class LIBODB_EXPORT transaction_impl + { + public: + typedef odb::tracer tracer_type; + typedef odb::database database_type; + typedef odb::connection connection_type; + + virtual + ~transaction_impl (); + + virtual void + start () = 0; + + virtual void + commit () = 0; + + virtual void + rollback () = 0; + + database_type& + database () + { + return database_; + } + + virtual connection_type& + connection (database_type*); + + virtual void + tracer (tracer_type*); + + virtual tracer_type* + tracer () const; + + protected: + transaction_impl (database_type& db) + : database_ (db), connection_ (0) + { + } + + transaction_impl (database_type& db, connection_type& c) + : database_ (db), connection_ (&c) + { + } + + protected: + database_type& database_; + connection_type* connection_; + }; +} + +#include + +#include + +#endif // ODB_TRANSACTION_HXX diff --git a/libodb/odb/transaction.ixx b/libodb/odb/transaction.ixx new file mode 100644 index 0000000..cc1ce5e --- /dev/null +++ b/libodb/odb/transaction.ixx @@ -0,0 +1,68 @@ +// file : odb/transaction.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +namespace odb +{ + inline transaction:: + transaction () + : finalized_ (true), + impl_ (0), + free_callback_ (max_callback_count), + callback_count_ (0) + { + } + + inline transaction:: + transaction (transaction_impl* impl, bool make_current) + : finalized_ (true), + impl_ (0), + free_callback_ (max_callback_count), + callback_count_ (0) + { + reset (impl, make_current); + } + + inline transaction::database_type& transaction:: + database () + { + return impl_->database (); + } + + inline transaction::connection_type& transaction:: + connection () + { + return impl_->connection (0); + } + + inline transaction::connection_type& transaction:: + connection (database_type& db) + { + return impl_->connection (&db); + } + + inline transaction_impl& transaction:: + implementation () + { + return *impl_; + } + + inline void transaction:: + tracer (tracer_type& t) + { + impl_->tracer (&t); + } + + inline void transaction:: + tracer (tracer_type* t) + { + impl_->tracer (t); + } + + inline transaction::tracer_type* transaction:: + tracer () const + { + return impl_->tracer (); + } +} diff --git a/libodb/odb/vector-impl.cxx b/libodb/odb/vector-impl.cxx new file mode 100644 index 0000000..ca30f8d --- /dev/null +++ b/libodb/odb/vector-impl.cxx @@ -0,0 +1,208 @@ +// file : odb/vector-impl.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include + +#include // std::memcpy, std::memset +#include // std::swap + +using namespace std; + +namespace odb +{ + // vector_impl + // + const unsigned char vector_impl::mask_[4] = {0x3, 0xC, 0x30, 0xC0}; + const unsigned char vector_impl::shift_[4] = {0, 2, 4, 6}; + + vector_impl:: + vector_impl (const vector_impl& x) + : state_ (x.state_), size_ (0), tail_ (0), capacity_ (0), data_ (0) + { + // Copy the data over if we are tracking. + // + if (state_ == state_tracking && x.size_ != 0) + { + realloc (x.size_ < 1024 ? 1024 : x.size_); + memcpy (data_, x.data_, x.size_ / 4 + (x.size_ % 4 == 0 ? 0 : 1)); + size_ = x.size_; + tail_ = x.tail_; + } + } + + void vector_impl:: + realloc (size_t n) + { + // The new capacity can be less or greater than the old one, but + // it cannot be less than size. + // + size_t b (n / 4 + (n % 4 == 0 ? 0 : 1)); + + if (b != capacity_ * 4) + { + unsigned char* d (static_cast (operator new (b))); + + if (size_ != 0) + memcpy (d, data_, size_ / 4 + (size_ % 4 == 0 ? 0 : 1)); + + if (data_ != 0) + operator delete (data_); + + data_ = d; + capacity_ = b * 4; + } + } + + void vector_impl:: + shrink_to_fit () + { + if (size_ != capacity_) + { + if (size_ != 0) + realloc (size_); + else + { + operator delete (data_); + data_ = 0; + capacity_ = 0; + } + } + } + + void vector_impl:: + start (size_t n) + { + if (n != 0) + { + if (capacity_ < n) + { + size_ = 0; + realloc (n < 1024 ? 1024 : n); + } + + memset (data_, 0, n / 4 + (n % 4 == 0 ? 0 : 1)); + } + + state_ = state_tracking; + size_ = tail_ = n; + } + + void vector_impl:: + push_back (size_t n) + { + for (; n != 0; --n) + { + size_t i (tail_); + + element_state_type s; + if (i != size_) + // We have an erased element we can reuse. + // + s = state_updated; + else + { + if (size_ == capacity_) + { + size_t c (capacity_ == 0 ? 1024 : capacity_ * 2); + if (c < size_ + n) + c = size_ + n; + realloc (c); + } + + s = state_inserted; + size_++; + } + + set (i, s); + tail_++; + } + } + + void vector_impl:: + pop_back (size_t n) + { + for (; n != 0; --n) + { + size_t i (tail_ - 1); + + if (state (i) != state_inserted) + set (i, state_erased); + else + size_--; // tail_ == size_ + + tail_--; + } + } + + void vector_impl:: + insert (size_t i, size_t n) + { + for (; i != tail_; ++i) + if (state (i) != state_inserted) + set (i, state_updated); + + push_back (n); + } + + void vector_impl:: + erase (size_t i, size_t n) + { + pop_back (n); + + for (; i != tail_; ++i) + if (state (i) != state_inserted) + set (i, state_updated); + } + + void vector_impl:: + clear () + { + // The idea is to drop any inserted elements from the back and + // set everything else to erased. + // + if (tail_ == size_) + { + while (size_ != 0 && state (size_ - 1) == state_inserted) + size_--; + + tail_ = size_; + } + + if (tail_ != 0) + memset (data_, 0xFF, tail_ / 4 + (tail_ % 4 == 0 ? 0 : 1)); + + tail_ = 0; + } + + // vector_base + // + void vector_base:: + rollback (unsigned short, void* key, unsigned long long) + { + // Mark as changed. + // + static_cast (key)->impl_.change (); + } + + void vector_base:: + swap_tran (vector_base& x) + { + // If either instance is armed, then we need to update the + // callback registration. + // + transaction* t (x.tran_); + if (tran_ != 0) + { + tran_->callback_unregister (this); + x._arm (*tran_); + } + + if (t != 0) + { + t->callback_unregister (&x); + _arm (*t); + } + + std::swap (tran_, x.tran_); + } +} diff --git a/libodb/odb/vector-impl.hxx b/libodb/odb/vector-impl.hxx new file mode 100644 index 0000000..9f2ea7c --- /dev/null +++ b/libodb/odb/vector-impl.hxx @@ -0,0 +1,221 @@ +// file : odb/vector-impl.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_VECTOR_IMPL_HXX +#define ODB_VECTOR_IMPL_HXX + +#include +#include // ODB_CXX11 + +#include +#include // std::size_t + +#include +#include + +namespace odb +{ + // Change tracking vector implementation details. + // + class LIBODB_EXPORT vector_impl + { + public: + enum element_state_type + { + state_unchanged, + state_inserted, + state_updated, + state_erased + }; + + enum container_state_type + { + state_tracking, + state_not_tracking, + state_changed // Container has changed but individual changes + // were not tracked. + }; + + vector_impl (); + ~vector_impl (); + + // The copy constructor will copy the state. The idea is that the + // copy keeps tracking changes, just like the original. + // + vector_impl (const vector_impl&); + +#ifdef ODB_CXX11 + vector_impl (vector_impl&&) noexcept; +#endif + + void + swap (vector_impl& x); + + // Allocate enough memory to store the specified number of + // elements. + // + void + reserve (std::size_t); + + // Reduce capacity to size. + // + void + shrink_to_fit (); + + // Capacity (each entry takes 2 bits). + // + std::size_t + capacity () const; + + // (Re)start tracking changes for a vector with n elements. + // + void + start (std::size_t); + + // Stop tracking changes. + // + void + stop (); + + // Mark the container as changed without tracking the changes. + // This state is useful as a fallback mechnism for situations + // where the change information has been discarded (e.g., after + // its state has been updated in the database) but the container + // should remain changed (e.g., after the transaction is rolled + // back). + // + void + change (); + + // Get the state of the container. + // + container_state_type + state () const; + + // Shortcut for state() == state_tracking. + // + bool + tracking () const; + + // Note that the returned size can be greater than the actual, + // parallel vector size. In this case the difference is the + // erased elements at the back. + // + std::size_t + size () const; + + // Get the change state of the specified element. + // + element_state_type + state (std::size_t) const; + + // Change notifications. + // + void + push_back (std::size_t n = 1); + + void + pop_back (std::size_t n = 1); + + void + insert (std::size_t, std::size_t n = 1); + + void + erase (std::size_t, std::size_t n = 1); + + void + modify (std::size_t, std::size_t n = 1); + + void + clear (); + + void + assign (std::size_t n); + + void + resize (std::size_t n); + + private: + // Assignment does not make sense (it is changing of the content). + // + vector_impl& operator= (const vector_impl&); + + private: + void + realloc (std::size_t); + + void + set (std::size_t, element_state_type); + + static const unsigned char mask_[4]; + static const unsigned char shift_[4]; + + container_state_type state_; + + // Size, tail, and capacity are in 2-bit blocks. Size is the number + // of elements we have in data. Tail is the position of the first + // erased element at the back. If there are no erased elements, then + // tail is equal size. Capacity is the number of elements we can + // store in data. + // + std::size_t size_; + std::size_t tail_; + std::size_t capacity_; + unsigned char* data_; + }; + + // Base class that provides a change tracking interface and + // handles the rollback callback. The only function that's + // missing is _start() which needs to know the number of + // elements currently in the vector. + // + class LIBODB_EXPORT vector_base + { + public: + void + _stop () const; + + bool + _tracking () const; + + void + _arm (transaction& t) const; + + vector_impl& + _impl () const {return impl_;} + + private: + // Assignment is changing of the content. + // + vector_base& operator= (const vector_base&); + + protected: + ~vector_base (); + vector_base (); + vector_base (const vector_base&); + +#ifdef ODB_CXX11 + vector_base (vector_base&&) noexcept; +#endif + + void + swap (vector_base&); + + static void + rollback (unsigned short, void* key, unsigned long long); + + private: + void + swap_tran (vector_base&); + + protected: + mutable vector_impl impl_; + mutable transaction* tran_; + }; +} + +#include + +#include + +#endif // ODB_VECTOR_IMPL_HXX diff --git a/libodb/odb/vector-impl.ixx b/libodb/odb/vector-impl.ixx new file mode 100644 index 0000000..21999d5 --- /dev/null +++ b/libodb/odb/vector-impl.ixx @@ -0,0 +1,210 @@ +// file : odb/vector-impl.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifdef ODB_CXX11 +# include // std::swap, std::move +#else +# include // std::swap +#endif + +namespace odb +{ + // vector_impl + // + inline vector_impl:: + vector_impl () + : state_ (state_not_tracking), + size_ (0), tail_ (0), capacity_ (0), data_ (0) + { + } + + inline void vector_impl:: + swap (vector_impl& x) + { + std::swap (state_, x.state_); + std::swap (size_, x.size_); + std::swap (tail_, x.tail_); + std::swap (capacity_, x.capacity_); + std::swap (data_, x.data_); + } + +#ifdef ODB_CXX11 + inline vector_impl:: + vector_impl (vector_impl&& x) noexcept + : state_ (state_not_tracking), + size_ (0), tail_ (0), capacity_ (0), data_ (0) + { + swap (x); + } +#endif + + inline vector_impl:: + ~vector_impl () + { + if (data_ != 0) + operator delete (data_); + } + + inline void vector_impl:: + reserve (std::size_t n) + { + if (n > capacity_) + realloc (n); + } + + inline void vector_impl:: + stop () + { + state_ = state_not_tracking; + size_ = tail_ = 0; + } + + inline void vector_impl:: + change () + { + state_ = state_changed; + size_ = tail_ = 0; + } + + inline vector_impl::container_state_type vector_impl:: + state () const + { + return state_; + } + + inline bool vector_impl:: + tracking () const + { + return state_ == state_tracking; + } + + inline std::size_t vector_impl:: + size () const + { + return size_; + } + + inline std::size_t vector_impl:: + capacity () const + { + return capacity_; + } + + inline vector_impl::element_state_type vector_impl:: + state (std::size_t i) const + { + std::size_t r (i % 4); + unsigned char v (data_[i / 4]); + return static_cast ((v & mask_[r]) >> shift_[r]); + } + + inline void vector_impl:: + set (std::size_t i, element_state_type s) + { + std::size_t r (i % 4); + i /= 4; + unsigned char v (static_cast (s)); + v <<= shift_[r]; + data_[i] = (data_[i] & ~mask_[r]) | v; + } + + inline void vector_impl:: + modify (std::size_t i, std::size_t n) + { + for (; n != 0; --n, ++i) + if (state (i) != state_inserted) + set (i, state_updated); + } + + inline void vector_impl:: + assign (std::size_t n) + { + if (tail_ != 0) + clear (); + + push_back (n); + } + + inline void vector_impl:: + resize (size_t n) + { + if (n < tail_) + pop_back (tail_ - n); + else if (n > tail_) + push_back (n - tail_); + } + + // vector_base + // + inline vector_base:: + ~vector_base () + { + if (tran_ != 0) + tran_->callback_unregister (this); + } + + inline vector_base:: + vector_base (): tran_ (0) {} + + inline void vector_base:: + _arm (transaction& t) const + { + tran_ = &t; + t.callback_register (&rollback, + const_cast (this), + transaction::event_rollback, + 0, + &tran_); + } + + inline vector_base:: + vector_base (const vector_base& x) + : impl_ (x.impl_), tran_ (0) + { + // If the original is armed, then arm ourselves as well. + // + if (x.tran_ != 0) + _arm (*x.tran_); + } + + inline void vector_base:: + swap (vector_base& x) + { + impl_.swap (x.impl_); + + if (tran_ != 0 || x.tran_ != 0) + swap_tran (x); + } + +#ifdef ODB_CXX11 + inline vector_base:: + vector_base (vector_base&& x) noexcept + : impl_ (std::move (x.impl_)), tran_ (0) + { + if (x.tran_ != 0) + { + x.tran_->callback_unregister (&x); + + // Note that _arm() can potentially throw bad_alloc while adding a new + // callback to the callbacks list of the transaction object. However, we + // assume that this will not happen since the new callback should be + // saved into an existing slot, freed by the above callback_unregister() + // call. + // + _arm (*x.tran_); + } + } +#endif + + inline void vector_base:: + _stop () const + { + impl_.stop (); + } + + inline bool vector_base:: + _tracking () const + { + return impl_.tracking (); + } +} diff --git a/libodb/odb/vector-traits.hxx b/libodb/odb/vector-traits.hxx new file mode 100644 index 0000000..5e6cf14 --- /dev/null +++ b/libodb/odb/vector-traits.hxx @@ -0,0 +1,106 @@ +// file : odb/vector-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_VECTOR_TRAITS_HXX +#define ODB_VECTOR_TRAITS_HXX + +#include + +#include +#include +#include +#include + +namespace odb +{ + template + class access::container_traits > + { + public: + static const container_kind kind = ck_ordered; + static const bool smart = true; + + typedef vector container_type; + + typedef V value_type; + typedef typename container_type::size_type index_type; + + typedef smart_ordered_functions functions; + typedef ordered_functions dumb_functions; + + public: + static void + persist (const container_type& c, const functions& f) + { + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + + // Now that this container is persistent, start tracking changes. + // + c._start (); + } + + static void + load (container_type& c, bool more, const functions& f) + { + // Stop tracking changes. + // + c._stop (); + + // Load. + // + c.clear (); + while (more) + { + index_type dummy; + c.push_back (value_type ()); + more = f.select (dummy, c.modify_back ()); + } + + // Start tracking changes. + // + c._start (); + } + + static bool + changed (const container_type&); + + static void + update (const container_type&, const functions&); + + static void + erase (const container_type* c, const functions& f) + { + f.delete_ (0); + + // Stop tracking changes. + // + if (c != 0) + c->_stop (); + } + + // Version of load() for dumb functions. Used to support + // inverse members of the container type. The implementation + // is identical to the smart one except we don't turn off/on + // change tracking. + // + static void + load (container_type& c, bool more, const dumb_functions& f) + { + c.clear (); + + while (more) + { + index_type dummy; + c.push_back (value_type ()); + more = f.select (dummy, c.modify_back ()); + } + } + }; +} + +#include + +#include + +#endif // ODB_VECTOR_TRAITS_HXX diff --git a/libodb/odb/vector-traits.txx b/libodb/odb/vector-traits.txx new file mode 100644 index 0000000..6c33876 --- /dev/null +++ b/libodb/odb/vector-traits.txx @@ -0,0 +1,100 @@ +// file : odb/vector-traits.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + template + bool access::container_traits >:: + changed (const container_type& c) + { + // Because modifications can cancel each other (e.g., push and pop), + // it is tricky to keep track of whether there are any changes in + // the container. Instead, we are just going to examine each element + // just like update(). + // + + // We should either be tracking or summarily changed. + // + if (c._tracking ()) + { + const vector_impl& impl (c._impl ()); + + for (std::size_t i (0), n (impl.size ()); i < n; ++i) + { + if (impl.state (i) != vector_impl::state_unchanged) + return true; + } + } + else + return true; + + return false; + } + + template + void access::container_traits >:: + update (const container_type& c, const functions& f) + { + bool u (false); // Updated flag. + + if (c._tracking ()) + { + const vector_impl& impl (c._impl ()); + + for (std::size_t i (0), n (impl.size ()); i < n; ++i) + { + vector_impl::element_state_type s (impl.state (i)); + + switch (s) + { + case vector_impl::state_unchanged: + { + break; + } + case vector_impl::state_inserted: + { + f.insert (i, c[static_cast (i)]); + u = u || true; + break; + } + case vector_impl::state_updated: + { + f.update (i, c[static_cast (i)]); + u = u || true; + break; + } + case vector_impl::state_erased: + { + f.delete_ (i); // Delete from i onwards. + u = u || true; + break; + } + } + + // We delete all trailing elements in one go. + // + if (s == vector_impl::state_erased) + break; + } + } + else + { + // Fall back to delete all/insert all. + // + f.delete_ (0); + + for (index_type i (0), n (c.size ()); i < n; ++i) + f.insert (i, c[i]); + + u = true; + } + + // Arm the rollback callback and (re)start change tracking. + // + if (u) + { + c._arm (transaction::current ()); + c._start (); + } + } +} diff --git a/libodb/odb/vector.hxx b/libodb/odb/vector.hxx new file mode 100644 index 0000000..3fe7d8a --- /dev/null +++ b/libodb/odb/vector.hxx @@ -0,0 +1,635 @@ +// file : odb/vector.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_VECTOR_HXX +#define ODB_VECTOR_HXX + +#include +#include // ODB_CXX11 + +#include +#include +#include // std::ptrdiff_t + +#ifdef ODB_CXX11 +# include // std::move, std::forward +# ifdef ODB_CXX11_INITIALIZER_LIST +# include +# endif +#endif + +#include + +// Because both std::vector and odb::vector are called 'vector' (who +// cares about namespace qualifications, right?), Sun CC complains +// with a bogus "Ambiguous partial specialization" error. A really +// hideous workaround for this bug is to to add a dummy third template +// argument (with a default value). +// +#ifdef __SUNPRO_CC +# define LIBODB_VECTOR_ARG_DEFAULT ,int = 0 +# define LIBODB_VECTOR_ARG_DECL ,int DUMMY +# define LIBODB_VECTOR_ARG_USE ,DUMMY +#else +# define LIBODB_VECTOR_ARG_DEFAULT +# define LIBODB_VECTOR_ARG_DECL +# define LIBODB_VECTOR_ARG_USE +#endif + +namespace odb +{ + // An std::vector-like container that keeps track of changes. + // + // Note that the style and order of definitions is as appears + // in the standard. + // + template + class vector_iterator; + + template LIBODB_VECTOR_ARG_DEFAULT> + class vector: public vector_base + { + public: + typedef std::vector base_vector_type; + typedef typename base_vector_type::iterator base_iterator_type; + typedef typename base_vector_type::reverse_iterator + base_reverse_iterator_type; + // types: + // + typedef typename base_vector_type::reference reference; + typedef typename base_vector_type::const_reference const_reference; + typedef vector_iterator iterator; + typedef typename base_vector_type::const_iterator const_iterator; + typedef typename base_vector_type::size_type size_type; + typedef typename base_vector_type::difference_type difference_type; + typedef T value_type; + typedef A allocator_type; + typedef typename base_vector_type::pointer pointer; + typedef typename base_vector_type::const_pointer const_pointer; + // No non-const reverse iterator support for Sun CC with non-standard STL. + // +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + typedef vector_iterator + reverse_iterator; +#endif + typedef typename base_vector_type::const_reverse_iterator + const_reverse_iterator; + // construct/copy/destroy: + // + explicit vector(const A& a = A()): v_ (a) {} + explicit vector(size_type n): v_ (n) {} // C++11 + vector(size_type n, const T& v, const A& a = A()): v_ (n, v, a) {} + template + vector(I f, I l, const A& a = A()) : v_ (f, l, a) {} + vector(const vector& x): vector_base (x), v_ (x.v_) {} + // ~vector() {} + vector& operator=(const vector&); + template + void assign(I f, I l); + void assign(size_type n, const T& u); + allocator_type get_allocator() const /*noexcept*/ + {return v_.get_allocator ();} + +#ifdef ODB_CXX11 + vector(vector&& x) noexcept + : vector_base (std::move (x)), v_ (std::move (x.v_)) {} + + vector(const vector& x, const A& a): vector_base (x), v_ (x.v_, a) {} + vector(vector&& x, const A& a) + : vector_base (std::move (x)), v_ (std::move (x.v_), a) {} + + // Note: noexcept is not specified since it can throw while reallocating + // impl_. + // + vector& operator=(vector&&); +#ifdef ODB_CXX11_INITIALIZER_LIST + vector(std::initializer_list il, const A& a = A()): v_ (il, a) {} + vector& operator=(std::initializer_list); + void assign(std::initializer_list); +#endif +#endif + + // iterators: (all /*noexcept*/) + // + iterator begin() {return iterator (this, v_.begin ());} + iterator end() {return iterator (this, v_.end ());} + const_iterator begin() const {return v_.begin ();} + const_iterator end() const {return v_.end ();} +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + reverse_iterator rbegin() {return reverse_iterator (this, v_.rbegin ());} + reverse_iterator rend() {return reverse_iterator (this, v_.rend ());} +#endif + const_reverse_iterator rbegin() const {return v_.rbegin ();} + const_reverse_iterator rend() const {return v_.rend ();} + + // Return standard vector iterators. The begin() functions mark all + // the elements as modified. + // + base_iterator_type mbegin (); + base_iterator_type mend () {return v_.end ();} + base_reverse_iterator_type mrbegin (); + base_reverse_iterator_type mrend () {return v_.rend ();} + +#ifdef ODB_CXX11 + const_iterator cbegin() const {return v_.cbegin ();} + const_iterator cend() const {return v_.cend ();} + const_reverse_iterator crbegin() const {return v_.crbegin ();} + const_reverse_iterator crend() const {return v_.crend ();} +#endif + + // capacity: + // + size_type size() const /*noexcept*/ {return v_.size ();} + size_type max_size() const /*noexcept*/ {return v_.max_size ();} + void resize(size_type); // C++11 + void resize(size_type, const T&); + size_type capacity() const /*noexcept*/ {return v_.capacity ();} + bool empty() const /*noexcept*/ {return v_.empty ();} + void reserve(size_type); + +#ifdef ODB_CXX11 + void shrink_to_fit(); +#endif + + // element access: + // + //reference operator[](size_type n); + reference modify(size_type n); + const_reference operator[](size_type n) const {return v_[n];} + //reference at(size_type n); + reference modify_at(size_type n); + const_reference at(size_type n) const {return v_.at (n);} + //reference front(); + reference modify_front(); + const_reference front() const {return v_.front ();} + //reference back(); + reference modify_back(); + const_reference back() const {return v_.back ();} + + // data access: + // +#ifdef ODB_CXX11 + //T* data() noexcept; + T* modify_data() /*noexcept*/; + const T* data() const /*noexcept*/ {return v_.data ();} +#endif + + // modifiers: + // + void push_back(const T& x); + void pop_back(); + iterator insert(iterator position, const T& x); + void insert(iterator position, size_type n, const T& x); + template + void insert(iterator position, I first, I last); + iterator erase(iterator position); + iterator erase(iterator first, iterator last); + void swap(vector&); + void clear() /*noexcept*/; + +#ifdef ODB_CXX11 + // In C++11 all modifiers use const_iterator instead of iterator + // to represent position. However, some standard libraries (notably + // GCC's) still use iterator and so we will do that as well, for now. + // + void push_back(T&& x); + iterator insert(iterator position, T&& x); + +#ifdef ODB_CXX11_VARIADIC_TEMPLATE + template + void emplace_back(Args&&... args); + template + iterator emplace(iterator position, Args&&... args); +#endif +#endif + + // Interfacing with the base vector. + // + vector (const base_vector_type& x): v_ (x) {} + vector& operator= (const base_vector_type&); + operator const base_vector_type& () const {return v_;} + base_vector_type& base () {return v_;} + const base_vector_type& base () const {return v_;} + +#ifdef ODB_CXX11 + vector (base_vector_type&& x): v_ (std::move (x)) {} + vector& operator= (base_vector_type&&); +#endif + + // Change tracking (the rest comes from vector_base). + // + public: + void + _start () const {impl_.start (v_.size ());} + + private: + base_vector_type v_; + }; + + namespace core + { + using odb::vector; + } + + template + inline bool operator==(const vector& x, + const vector& y) + {return x.base () == y.base ();} + + template + inline bool operator==(const vector& x, + const std::vector& y) + {return x.base () == y;} + + template + inline bool operator==(const std::vector& x, + const vector& y) + {return x == y.base ();} + + template + inline bool operator< (const vector& x, + const vector& y) + {return x.base () < y.base ();} + + template + inline bool operator<(const vector& x, + const std::vector& y) + {return x.base () < y;} + + template + inline bool operator<(const std::vector& x, + const vector& y) + {return x < y.base ();} + + template + inline bool operator!=(const vector& x, + const vector& y) + {return x.base () != y.base ();} + + template + inline bool operator!=(const vector& x, + const std::vector& y) + {return x.base () != y;} + + template + inline bool operator!=(const std::vector& x, + const vector& y) + {return x != y.base ();} + + template + inline bool operator> (const vector& x, + const vector& y) + {return x.base () > y.base ();} + + template + inline bool operator>=(const vector& x, + const vector& y) + {return x.base () >= y.base ();} + + template + inline bool operator>=(const vector& x, + const std::vector& y) + {return x.base () >= y;} + + template + inline bool operator>=(const std::vector& x, + const vector& y) + {return x >= y.base ();} + + template + inline bool operator<=(const vector& x, + const vector& y) + {return x.base () <= y.base ();} + + template + inline bool operator<=(const vector& x, + const std::vector& y) + {return x.base () <= y;} + + template + inline bool operator<=(const std::vector& x, + const vector& y) + {return x <= y.base ();} + + template + class vector_iterator + { + public: + typedef V vector_type; + typedef I base_iterator_type; + typedef typename vector_type::const_iterator const_iterator_type; + + // Sun CC with non-standard STL does not have iterator_traits. + // +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + typedef std::iterator_traits base_iterator_traits; + + typedef typename base_iterator_traits::value_type value_type; + typedef typename base_iterator_traits::difference_type difference_type; + typedef typename base_iterator_traits::pointer pointer; + typedef typename base_iterator_traits::reference reference; + typedef typename base_iterator_traits::iterator_category iterator_category; +#else + // Base iterator is just a pointer. + // + typedef typename vector_type::value_type value_type; + typedef typename vector_type::pointer pointer; + typedef typename vector_type::reference reference; + typedef std::random_access_iterator_tag iterator_category; + typedef std::ptrdiff_t difference_type; +#endif + + typedef typename vector_type::size_type size_type; + typedef typename vector_type::const_reference const_reference; + typedef typename vector_type::const_pointer const_pointer; + + vector_iterator (): v_ (0), i_ () {} + vector_iterator (vector_type* v, const base_iterator_type& i) + : v_ (v), i_ (i) {} + operator const_iterator_type () const {return i_;} + base_iterator_type base () const {return i_;} + vector_type* vector () const {return v_;} + + // Note: const_{reference,pointer}. + // + const_reference operator* () const {return *i_;} + const_pointer operator-> () const {return i_.operator -> ();} + const_reference operator[] (difference_type n) const {return i_[n];} + + // Modifiers. + // + // Buggy Sun CC cannot have them out of class. + // + reference modify () const + { + if (v_->_tracking ()) + v_->_impl ().modify ( + static_cast (i_ - v_->base ().begin ())); + return *i_; + } + + reference modify (difference_type n) const + { + if (v_->_tracking ()) + v_->_impl ().modify ( + static_cast (i_ - v_->base ().begin () + n)); + return i_[n]; + } + + vector_iterator& operator++ () {++i_; return *this;} + vector_iterator operator++ (int) {return vector_iterator (v_, i_++);} + vector_iterator& operator-- () {--i_; return *this;} + vector_iterator operator-- (int) {return vector_iterator (v_, i_--);} + + vector_iterator operator+ (difference_type n) const + {return vector_iterator (v_, i_ + n);} + vector_iterator& operator+= (difference_type n) {i_ += n; return *this;} + vector_iterator operator- (difference_type n) const + {return vector_iterator (v_, i_ - n);} + vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;} + + // Implementation details. + // + public: + base_iterator_type _base () const {return i_;} // Same as base (). + + private: + vector_type* v_; + base_iterator_type i_; + }; + +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC + template + class vector_iterator > + { + public: + typedef V vector_type; + typedef std::reverse_iterator base_iterator_type; + typedef typename vector_type::const_reverse_iterator const_iterator_type; + typedef std::iterator_traits base_iterator_traits; + + typedef typename vector_type::iterator iterator_type; + typedef typename base_iterator_traits::value_type value_type; + typedef typename base_iterator_traits::difference_type difference_type; + typedef typename base_iterator_traits::pointer pointer; + typedef typename base_iterator_traits::reference reference; + typedef typename base_iterator_traits::iterator_category iterator_category; + + typedef typename vector_type::size_type size_type; + typedef typename vector_type::const_reference const_reference; + typedef typename vector_type::const_pointer const_pointer; + + vector_iterator (): v_ (0), i_ () {} + explicit vector_iterator (const iterator_type& i) + : v_ (i.vector ()), i_ (i.base ()) {} + vector_iterator (vector_type* v, const base_iterator_type& i) + : v_ (v), i_ (i) {} + operator const_iterator_type () const {return i_;} + iterator_type base () const {return iterator_type (v_, i_.base ());} + base_iterator_type rbase () const {return i_;} + vector_type* vector () const {return v_;} + + // Note: const_{reference,pointer}. + // + const_reference operator* () const {return *i_;} + const_pointer operator-> () const {return i_.operator -> ();} + const_reference operator[] (difference_type n) const {return i_[n];} + + // Modifiers. + // + reference modify () const + { + if (v_->_tracking ()) + v_->_impl ().modify ( + static_cast (v_->base ().rend () - i_ - 1)); + return *i_; + } + + reference modify (difference_type n) const + { + if (v_->_tracking ()) + // Note: going in the opposite direction. + v_->_impl ().modify ( + static_cast (v_->base ().rend () - i_ - 1 - n)); + return i_[n]; + } + + vector_iterator& operator++ () {++i_; return *this;} + vector_iterator operator++ (int) {return vector_iterator (v_, i_++);} + vector_iterator& operator-- () {--i_; return *this;} + vector_iterator operator-- (int) {return vector_iterator (v_, i_--);} + + vector_iterator operator+ (difference_type n) const + {return vector_iterator (v_, i_ + n);} + vector_iterator& operator+= (difference_type n) {i_ += n; return *this;} + vector_iterator operator- (difference_type n) const + {return vector_iterator (v_, i_ - n);} + vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;} + + // Implementation details. + // + public: + base_iterator_type _base () const {return i_;} // Same as rbase(). + + private: + vector_type* v_; + base_iterator_type i_; + }; +#endif // _RWSTD_NO_CLASS_PARTIAL_SPEC + + // operator== + // + template + inline bool + operator== (const vector_iterator& x, const vector_iterator& y) + {return x._base () == y._base ();} + + template + inline bool + operator== (const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () == y;} + + template + inline bool + operator== (const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x == y._base ();} + + // operator< + // + template + inline bool + operator< (const vector_iterator& x, const vector_iterator& y) + {return x._base () < y._base ();} + + template + inline bool + operator< (const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () < y;} + + template + inline bool + operator< (const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x < y._base ();} + + // operator!= + // + template + inline bool + operator!= (const vector_iterator& x, const vector_iterator& y) + {return x._base () != y._base ();} + + template + inline bool + operator!= (const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () != y;} + + template + inline bool + operator!= (const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x != y._base ();} + + // operator> + // + template + inline bool + operator> (const vector_iterator& x, const vector_iterator& y) + {return x._base () > y._base ();} + + template + inline bool + operator> (const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () > y;} + + template + inline bool + operator> (const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x > y._base ();} + + // operator>= + // + template + inline bool + operator>= (const vector_iterator& x, const vector_iterator& y) + {return x._base () >= y._base ();} + + template + inline bool + operator>= (const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () >= y;} + + template + inline bool + operator>= (const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x >= y._base ();} + + // operator<= + // + template + inline bool + operator<= (const vector_iterator& x, const vector_iterator& y) + {return x._base () <= y._base ();} + + template + inline bool + operator<= (const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () <= y;} + + template + inline bool + operator<= (const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x <= y._base ();} + + // operator- + // + template + inline typename vector_iterator::difference_type + operator-(const vector_iterator& x, const vector_iterator& y) + {return x._base () - y._base ();} + + template + inline typename vector_iterator::difference_type + operator-(const vector_iterator& x, + const typename vector_iterator::const_iterator_type& y) + {return x._base () - y;} + + template + inline typename vector_iterator::difference_type + operator-(const typename vector_iterator::const_iterator_type& x, + const vector_iterator& y) + {return x - y._base ();} + + // operator+ + // + template + inline vector_iterator + operator+(typename vector_iterator::difference_type n, + const vector_iterator& x) + {return vector_iterator (x.vector (), n + x._base ());} +} + +namespace std +{ + template + inline void swap(odb::vector& x, + odb::vector& y) {x.swap (y);} +} + +#include + +#include + +#include + +#endif // ODB_VECTOR_HXX diff --git a/libodb/odb/vector.ixx b/libodb/odb/vector.ixx new file mode 100644 index 0000000..230b187 --- /dev/null +++ b/libodb/odb/vector.ixx @@ -0,0 +1,359 @@ +// file : odb/vector.ixx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // construct/copy/destroy: + // + template + inline vector& + vector:: + operator= (const vector& x) + { + v_ = x.v_; + if (_tracking ()) + impl_.assign (v_.size ()); + return *this; + } + + template + template + inline void vector:: + assign (I f, I l) + { + v_.assign (f, l); + if (_tracking ()) + impl_.assign (v_.size ()); + } + + template + inline void vector:: + assign (size_type n, const T& u) + { + v_.assign (n, u); + if (_tracking ()) + impl_.assign (n); + } + +#ifdef ODB_CXX11 + template + inline vector& + vector:: + operator=(vector&& x) + { + v_ = std::move (x.v_); + if (_tracking ()) + impl_.assign (v_.size ()); + return *this; + } + +#ifdef ODB_CXX11_INITIALIZER_LIST + template + inline vector& + vector:: + operator= (std::initializer_list il) + { + v_ = il; + if (_tracking ()) + impl_.assign (v_.size ()); + return *this; + } + + template + inline void vector:: + assign (std::initializer_list il) + { + v_.assign (il); + if (_tracking ()) + impl_.assign (v_.size ()); + } +#endif +#endif + + // iterators: + // + template + inline typename vector::base_iterator_type + vector:: + mbegin () + { + if (_tracking ()) + impl_.modify (0, v_.size ()); + return v_.begin (); + } + + template + inline + typename vector::base_reverse_iterator_type + vector:: + mrbegin () + { + if (_tracking ()) + impl_.modify (0, v_.size ()); + return v_.rbegin (); + } + + // capacity: + // + template + inline void vector:: + resize (size_type n) + { + v_.resize (n); + if (_tracking ()) + impl_.resize (n); + } + + template + inline void vector:: + resize (size_type n, const T& c) + { + v_.resize (n, c); + if (_tracking ()) + impl_.resize (n); + } + + template + inline void vector:: + reserve (size_type n) + { + v_.reserve (n); + if (_tracking ()) + impl_.reserve (n); + } + +#ifdef ODB_CXX11 + template + inline void vector:: + shrink_to_fit () + { + v_.shrink_to_fit (); + impl_.shrink_to_fit (); + } +#endif + + // element access: + // + template + inline typename vector::reference + vector:: + modify (size_type n) + { + reference r (v_[n]); + if (_tracking ()) + impl_.modify (n); + return r; + } + + template + inline typename vector::reference + vector:: + modify_at (size_type n) + { + reference r (v_.at (n)); + if (_tracking ()) + impl_.modify (n); + return r; + } + + template + inline typename vector::reference + vector:: + modify_front () + { + reference r (v_.front ()); + if (_tracking ()) + impl_.modify (0); + return r; + } + + template + inline typename vector::reference + vector:: + modify_back () + { + reference r (v_.back ()); + if (_tracking ()) + impl_.modify (v_.size () - 1); + return r; + } + +#ifdef ODB_CXX11 + template + inline T* vector:: + modify_data() /*noexcept*/ + { + if (_tracking ()) + impl_.modify (0, v_.size ()); + return v_.data (); + } +#endif + + // modifiers: + // + template + inline void vector:: + push_back (const T& x) + { + v_.push_back (x); + if (_tracking ()) + impl_.push_back (); + } + + template + inline void vector:: + pop_back () + { + v_.pop_back (); + if (_tracking ()) + impl_.pop_back (); + } + + template + inline typename vector::iterator + vector:: + insert (iterator p, const T& x) + { + if (_tracking ()) + impl_.insert (static_cast (p.base () - v_.begin ())); + return iterator (this, v_.insert (p.base (), x)); + } + + template + inline void vector:: + insert (iterator p, size_type n, const T& x) + { + if (_tracking ()) + impl_.insert (static_cast (p.base () - v_.begin ()), n); + v_.insert (p.base (), n, x); + } + + template + template + inline void vector:: + insert (iterator p, I f, I l) + { + size_type i, n; + if (_tracking ()) + { + i = static_cast (p.base () - v_.begin ()); + n = v_.size (); + } + + v_.insert (p.base (), f, l); + + if (_tracking ()) + impl_.insert (i, v_.size () - n); + } + + template + inline typename vector::iterator + vector:: + erase (iterator p) + { + if (_tracking ()) + impl_.erase (static_cast (p.base () - v_.begin ())); + return iterator (this, v_.erase (p.base ())); + } + + template + inline typename vector::iterator + vector:: + erase (iterator f, iterator l) + { + if (_tracking ()) + impl_.erase (static_cast (f.base () - v_.begin ()), + static_cast (l - f)); + return iterator (this, v_.erase (f.base (), l.base ())); + } + + template + inline void vector:: + swap (vector& x) + { + v_.swap (x.v_); + vector_base::swap (x); + } + + template + inline void vector:: + clear () + { + v_.clear (); + if (_tracking ()) + impl_.clear (); + } + +#ifdef ODB_CXX11 + template + inline void vector:: + push_back(T&& x) + { + v_.push_back (std::move (x)); + if (_tracking ()) + impl_.push_back (); + } + + template + inline typename vector::iterator + vector:: + insert (iterator p, T&& x) + { + base_iterator_type r (v_.insert (p.base (), std::move (x))); + if (_tracking ()) + impl_.insert (static_cast (r - v_.begin ())); + return iterator (this, r); + } + +#ifdef ODB_CXX11_VARIADIC_TEMPLATE + template + template + inline void vector:: + emplace_back (Args&&... args) + { + v_.push_back (std::forward (args)...); + if (_tracking ()) + impl_.push_back (); + } + + template + template + inline typename vector::iterator + vector:: + emplace (iterator p, Args&&... args) + { + base_iterator_type r ( + v_.emplace (p.base (), std::forward (args)...)); + if (_tracking ()) + impl_.insert (static_cast (r - v_.begin ())); + return iterator (this, r); + } +#endif +#endif + + // Interfacing with base vector. + // + template + inline vector& + vector:: + operator= (const base_vector_type& x) + { + v_ = x; + if (_tracking ()) + impl_.assign (v_.size ()); + return *this; + } + +#ifdef ODB_CXX11 + template + inline vector& + vector:: + operator= (base_vector_type&& x) + { + v_ = std::move (x); + if (_tracking ()) + impl_.assign (v_.size ()); + return *this; + } +#endif +} diff --git a/libodb/odb/version-build2-stub.hxx b/libodb/odb/version-build2-stub.hxx new file mode 100644 index 0000000..f4c7937 --- /dev/null +++ b/libodb/odb/version-build2-stub.hxx @@ -0,0 +1,4 @@ +// file : odb/version-build2-stub.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#include diff --git a/libodb/odb/version-build2.hxx b/libodb/odb/version-build2.hxx new file mode 100644 index 0000000..e69de29 diff --git a/libodb/odb/version-build2.hxx.in b/libodb/odb/version-build2.hxx.in new file mode 100644 index 0000000..3672585 --- /dev/null +++ b/libodb/odb/version-build2.hxx.in @@ -0,0 +1,42 @@ +// file : odb/version-build2.hxx.in +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef LIBODB_VERSION // Note: using the version macro itself. + +// For the ODB compiler (temporary). +// +#define ODB_VERSION 20476 + +// The numeric version format is AAAAABBBBBCCCCCDDDE where: +// +// AAAAA - major version number +// BBBBB - minor version number +// CCCCC - bugfix version number +// DDD - alpha / beta (DDD + 500) version number +// E - final (0) / snapshot (1) +// +// When DDDE is not 0, 1 is subtracted from AAAAABBBBBCCCCC. For example: +// +// Version AAAAABBBBBCCCCCDDDE +// +// 0.1.0 0000000001000000000 +// 0.1.2 0000000001000020000 +// 1.2.3 0000100002000030000 +// 2.2.0-a.1 0000200001999990010 +// 3.0.0-b.2 0000299999999995020 +// 2.2.0-a.1.z 0000200001999990011 +// +#define LIBODB_VERSION $libodb.version.project_number$ULL +#define LIBODB_VERSION_STR "$libodb.version.project$" +#define LIBODB_VERSION_ID "$libodb.version.project_id$" + +#define LIBODB_VERSION_MAJOR $libodb.version.major$ +#define LIBODB_VERSION_MINOR $libodb.version.minor$ +#define LIBODB_VERSION_PATCH $libodb.version.patch$ + +#define LIBODB_PRE_RELEASE $libodb.version.pre_release$ + +#define LIBODB_SNAPSHOT $libodb.version.snapshot_sn$ULL +#define LIBODB_SNAPSHOT_ID "$libodb.version.snapshot_id$" + +#endif // LIBODB_VERSION diff --git a/libodb/odb/version.hxx b/libodb/odb/version.hxx new file mode 100644 index 0000000..4961e1a --- /dev/null +++ b/libodb/odb/version.hxx @@ -0,0 +1,43 @@ +// file : odb/version.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifdef LIBODB_BUILD2 +# include +#else + +#ifndef ODB_VERSION_HXX +#define ODB_VERSION_HXX + +#include + +// Version format is AABBCCDD where +// +// AA - major version number +// BB - minor version number +// CC - bugfix version number +// DD - alpha / beta (DD + 50) version number +// +// When DD is not 00, 1 is subtracted from AABBCC. For example: +// +// Version AABBCCDD +// 2.0.0 02000000 +// 2.1.0 02010000 +// 2.1.1 02010100 +// 2.2.0.a1 02019901 +// 3.0.0.b2 02999952 +// + +// ODB interface version: minor, major, and alpha/beta versions. +// +#define ODB_VERSION 20476 +#define ODB_VERSION_STR "2.5-b.26" + +// libodb version: interface version plus the bugfix version. +// +#define LIBODB_VERSION 2049976 +#define LIBODB_VERSION_STR "2.5.0-b.26" + +#include + +#endif // ODB_VERSION_HXX +#endif // LIBODB_BUILD2 diff --git a/libodb/odb/view-image.hxx b/libodb/odb/view-image.hxx new file mode 100644 index 0000000..51f7cc0 --- /dev/null +++ b/libodb/odb/view-image.hxx @@ -0,0 +1,36 @@ +// file : odb/view-image.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_VIEW_IMAGE_HXX +#define ODB_VIEW_IMAGE_HXX + +#include + +#include +#include + +namespace odb +{ + // Helper to create a complete image chain for a polymorphic + // object hierarchy. + // + template + struct view_object_image: object_traits_impl::image_type + { + view_object_image () {this->base = &base_;} + + private: + // Data member names in the generated image_type never end with + // an underscore, so this name shouldn't clash. + // + view_object_image::base_type, R, DB> + base_; + }; + + template + struct view_object_image: object_traits_impl::image_type {}; +} + +#include + +#endif // ODB_VIEW_IMAGE_HXX diff --git a/libodb/odb/view-result.hxx b/libodb/odb/view-result.hxx new file mode 100644 index 0000000..601c3b4 --- /dev/null +++ b/libodb/odb/view-result.hxx @@ -0,0 +1,231 @@ +// file : odb/view-result.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_VIEW_RESULT_HXX +#define ODB_VIEW_RESULT_HXX + +#include + +#include // std::ptrdiff_t, std::size_t +#include // iterator categories +#include // std::move + +#include +#include +#include +#include + +#include // ODB_CXX11 + +namespace odb +{ + template + class view_result_impl: public result_impl + { + protected: + friend class result; + friend class result; + friend class result_iterator; + friend class result_iterator; + + // In result_impl, T is always non-const and the same as view_type. + // + typedef T view_type; + typedef odb::view_traits view_traits; + + typedef typename view_traits::pointer_type pointer_type; + typedef odb::pointer_traits pointer_traits; + + view_result_impl (odb::connection& conn) + : result_impl (conn), begin_ (true), end_ (false), current_ () + { + } + + // To make this work with all kinds of pointers (raw, std::auto_ptr, + // shared), we need to make sure we don't make any copies of the + // pointer on the return path. + // + pointer_type& + current (); + + void + release () + { + current_ = pointer_type (); + guard_.release (); + } + + void + begin () + { + if (begin_) + { + next (); + begin_ = false; + } + } + + bool + end () const + { + return end_; + } + + protected: + virtual void + load (view_type&) = 0; + + virtual void + next () = 0; + + virtual void + cache () = 0; + + virtual std::size_t + size () = 0; + + protected: +#ifdef ODB_CXX11 + void + current (pointer_type& p) + { + current_ = std::move (p); + guard_.reset (current_); + } + + void + current (pointer_type&& p) + { + current (p); + } +#else + void + current (pointer_type p) + { + current_ = p; + guard_.reset (current_); + } +#endif + + bool begin_; + bool end_; + + private: + pointer_type current_; + typename pointer_traits::guard guard_; + }; + + template + class result_iterator + { + public: + typedef T value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + + // T can be const T while view_type is always non-const. + // + typedef typename view_traits::view_type view_type; + + typedef view_result_impl result_impl_type; + + public: + explicit + result_iterator (result_impl_type* res = 0) + : res_ (res) + { + } + + // Input iterator requirements. + // + public: + reference + operator* () const + { + return pointer_traits::get_ref (res_->current ()); + } + + // Our value_type is already a pointer so return it instead of + // a pointer to it (operator-> will just have to go one deeper + // in the latter case). + // + pointer + operator-> () const + { + return pointer_traits::get_ptr (res_->current ()); + } + + result_iterator& + operator++ () + { + res_->next (); + return *this; + } + + result_iterator + operator++ (int) + { + // All non-end iterators for a result object move together. + // + res_->next (); + return *this; + } + + public: + typedef typename view_traits::pointer_type pointer_type; + + pointer_type + load () + { +#ifdef ODB_CXX11 + pointer_type r (std::move (res_->current ())); +#else + pointer_type r (res_->current ()); +#endif + res_->release (); + return r; + } + + void + load (view_type&); + + public: + bool + equal (result_iterator j) const + { + return (res_ ? res_->end () : true) == (j.res_ ? j.res_->end () : true); + } + + private: + // Use unrestricted pointer traits since that's what is returned by + // result_impl. + // + typedef + odb::pointer_traits::pointer_type> + pointer_traits; + + result_impl_type* res_; + }; + + // + // + template + class result_base + { + public: + typedef typename view_traits::pointer_type value_type; + + // T can be const T while view_type is always non-const. + // + typedef typename view_traits::view_type view_type; + typedef view_result_impl result_impl_type; + }; +} + +#include + +#include + +#endif // ODB_VIEW_RESULT_HXX diff --git a/libodb/odb/view-result.txx b/libodb/odb/view-result.txx new file mode 100644 index 0000000..5c62253 --- /dev/null +++ b/libodb/odb/view-result.txx @@ -0,0 +1,39 @@ +// file : odb/view-result.txx +// license : GNU GPL v2; see accompanying LICENSE file + +namespace odb +{ + // + // view_result_impl + // + + template + typename view_result_impl::pointer_type& + view_result_impl:: + current () + { + if (pointer_traits::null_ptr (current_) && !end_) + { + pointer_type p (view_traits::create ()); + view_type& view (pointer_traits::get_ref (p)); + current (p); + load (view); + } + + return current_; + } + + // + // result_iterator + // + + template + void result_iterator:: + load (view_type& view) + { + if (res_->end ()) + return; + + res_->load (view); + } +} diff --git a/libodb/odb/wrapper-traits.hxx b/libodb/odb/wrapper-traits.hxx new file mode 100644 index 0000000..d31425d --- /dev/null +++ b/libodb/odb/wrapper-traits.hxx @@ -0,0 +1,276 @@ +// file : odb/wrapper-traits.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_WRAPPER_TRAITS_HXX +#define ODB_WRAPPER_TRAITS_HXX + +#include + +#include // std::auto_ptr, std::unique_ptr, std::shared_ptr/weak_ptr + +#include + +#include // ODB_CXX11 +#include + +namespace odb +{ + template + class wrapper_traits; + + // Sample specialization for raw pointers. It is not enabled by default + // since it makes many assumptions that may not always hold true (such + // as that instances are allocated with new and freed with delete). + // This makes it too dangerous to be enabled unconditionally. If you + // need this functionality, you can copy the below code into your + // application. Also consider changing it to only specialize for + // specific types instead of for any pointer (it will almost always + // do the wrong thing for char*). + // +#if 0 + template + class wrapper_traits + { + public: + typedef T wrapped_type; + typedef T* wrapper_type; + + // T can be const. + // + typedef + typename details::meta::remove_const::result + unrestricted_wrapped_type; + + static const bool null_handler = true; + static const bool null_default = false; + + static bool + get_null (const wrapper_type& p) + { + return p == 0; + } + + static void + set_null (wrapper_type& p) + { + delete p; + p = 0; + } + + static const wrapped_type& + get_ref (const wrapper_type& p) + { + return *p; + } + + static unrestricted_wrapped_type& + set_ref (wrapper_type& p) + { + if (p == 0) + p = new unrestricted_wrapped_type; + + return const_cast (*p); + } + }; +#endif + + // Specialization for std::auto_ptr. + // +#ifndef ODB_CXX11 + template + class wrapper_traits< std::auto_ptr > + { + public: + // T can be const. + // + typedef T wrapped_type; + typedef std::auto_ptr wrapper_type; + + // T can be const. + // + typedef + typename odb::details::meta::remove_const::result + unrestricted_wrapped_type; + + static const bool null_handler = true; + static const bool null_default = false; + + static bool + get_null (const wrapper_type& p) + { + return p.get () == 0; + } + + static void + set_null (wrapper_type& p) + { + p.reset (); + } + + static const wrapped_type& + get_ref (const wrapper_type& p) + { + return *p; + } + + static unrestricted_wrapped_type& + set_ref (wrapper_type& p) + { + if (p.get () == 0) + p.reset (new unrestricted_wrapped_type ()); + + return const_cast (*p); + } + }; +#endif + +#ifdef ODB_CXX11 + + // Specialization for C++11 std::unique_ptr. + // + template + class wrapper_traits> + { + public: + // T can be const. + // + typedef T wrapped_type; + typedef std::unique_ptr wrapper_type; + + // T can be const. + // + typedef + typename odb::details::meta::remove_const::result + unrestricted_wrapped_type; + + static const bool null_handler = true; + static const bool null_default = false; + + static bool + get_null (const wrapper_type& p) + { + return !p; + } + + static void + set_null (wrapper_type& p) + { + p.reset (); + } + + static const wrapped_type& + get_ref (const wrapper_type& p) + { + return *p; + } + + static unrestricted_wrapped_type& + set_ref (wrapper_type& p) + { + if (!p) + p.reset (new unrestricted_wrapped_type ()); + + return const_cast (*p); + } + }; + + // Specialization for C++11 std::shared_ptr. + // + template + class wrapper_traits> + { + public: + typedef T wrapped_type; + typedef std::shared_ptr wrapper_type; + + // T can be const. + // + typedef + typename odb::details::meta::remove_const::result + unrestricted_wrapped_type; + + static const bool null_handler = true; + static const bool null_default = false; + + static bool + get_null (const wrapper_type& p) + { + return !p; + } + + static void + set_null (wrapper_type& p) + { + p.reset (); + } + + static const wrapped_type& + get_ref (const wrapper_type& p) + { + return *p; + } + + static unrestricted_wrapped_type& + set_ref (wrapper_type& p) + { + if (!p) + p.reset (new unrestricted_wrapped_type); + + return const_cast (*p); + } + }; + +#endif // ODB_CXX11 + + // Specialization for odb::nullable. + // + template + class wrapper_traits< nullable > + { + public: + // T can be const. + // + typedef T wrapped_type; + typedef nullable wrapper_type; + + // T can be const. + // + typedef + typename odb::details::meta::remove_const::result + unrestricted_wrapped_type; + + static const bool null_handler = true; + static const bool null_default = true; + + static bool + get_null (const wrapper_type& n) + { + return n.null (); + } + + static void + set_null (wrapper_type& n) + { + n.reset (); + } + + static const wrapped_type& + get_ref (const wrapper_type& n) + { + return *n; + } + + static unrestricted_wrapped_type& + set_ref (wrapper_type& n) + { + if (n.null ()) + n = unrestricted_wrapped_type (); + + return const_cast (*n); + } + }; +} + +#include + +#endif // ODB_WRAPPER_TRAITS_HXX diff --git a/libodb/tests/.gitignore b/libodb/tests/.gitignore new file mode 100644 index 0000000..e54525b --- /dev/null +++ b/libodb/tests/.gitignore @@ -0,0 +1 @@ +driver diff --git a/libodb/tests/basics/buildfile b/libodb/tests/basics/buildfile new file mode 100644 index 0000000..d568216 --- /dev/null +++ b/libodb/tests/basics/buildfile @@ -0,0 +1,6 @@ +# file : tests/basics/buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +import libs = libodb%lib{odb} + +exe{driver}: {hxx cxx}{*} $libs diff --git a/libodb/tests/basics/driver.cxx b/libodb/tests/basics/driver.cxx new file mode 100644 index 0000000..57cec1c --- /dev/null +++ b/libodb/tests/basics/driver.cxx @@ -0,0 +1,29 @@ +// file : tests/basics/driver.cxx +// license : GNU GPL v2; see accompanying LICENSE file + +// Basic test to make sure the library is usable. Functionality testing +// is done in the odb-tests package. + +#include + +#include +#include + +using namespace odb; + +int +main () +{ + // Transaction. + // + { + assert (!transaction::has_current ()); + + try + { + transaction::current (); + assert(false); + } + catch (const not_in_transaction&) {} + } +} diff --git a/libodb/tests/build/.gitignore b/libodb/tests/build/.gitignore new file mode 100644 index 0000000..4a730a3 --- /dev/null +++ b/libodb/tests/build/.gitignore @@ -0,0 +1,3 @@ +config.build +root/ +bootstrap/ diff --git a/libodb/tests/build/bootstrap.build b/libodb/tests/build/bootstrap.build new file mode 100644 index 0000000..6ee38db --- /dev/null +++ b/libodb/tests/build/bootstrap.build @@ -0,0 +1,8 @@ +# file : tests/build/bootstrap.build +# license : GNU GPL v2; see accompanying LICENSE file + +project = # Unnamed subproject. + +using config +using dist +using test diff --git a/libodb/tests/build/root.build b/libodb/tests/build/root.build new file mode 100644 index 0000000..6c5a90b --- /dev/null +++ b/libodb/tests/build/root.build @@ -0,0 +1,23 @@ +# file : tests/build/root.build +# license : GNU GPL v2; see accompanying LICENSE file + +cxx.std = latest + +using cxx + +hxx{*}: extension = hxx +cxx{*}: extension = cxx + +if ($cxx.target.system == 'win32-msvc') + cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS + +if ($cxx.class == 'msvc') + cxx.coptions += /wd4251 /wd4275 /wd4800 + +# Every exe{} in this subproject is by default a test. +# +exe{*}: test = true + +# Specify the test target for cross-testing. +# +test.target = $cxx.target diff --git a/libodb/tests/buildfile b/libodb/tests/buildfile new file mode 100644 index 0000000..57588a4 --- /dev/null +++ b/libodb/tests/buildfile @@ -0,0 +1,4 @@ +# file : tests/buildfile +# license : GNU GPL v2; see accompanying LICENSE file + +./: {*/ -build/} diff --git a/m4/acx-pthread.m4 b/m4/acx-pthread.m4 deleted file mode 100644 index 204b32d..0000000 --- a/m4/acx-pthread.m4 +++ /dev/null @@ -1,259 +0,0 @@ -dnl -dnl NOTE: This file was modified. See the comments starting with 'CS:' -dnl for more information. In particular, it was changed to use C++ -dnl instead of C. -dnl -dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -dnl -dnl @summary figure out how to build C++ programs using POSIX threads -dnl -dnl This macro figures out how to build C++ programs using POSIX threads. -dnl It sets the PTHREAD_LIBS output variable to the threads library and -dnl linker flags, and the PTHREAD_CXXFLAGS output variable to any special -dnl C++ compiler flags that are needed. (The user can also force certain -dnl compiler flags/libs to be tested by setting these environment -dnl variables.) -dnl -dnl Also sets PTHREAD_CXX to any special C++ compiler that is needed for -dnl multi-threaded programs (defaults to the value of CXX otherwise). -dnl (This is necessary on AIX to use the special xlC_r compiler alias.) -dnl -dnl NOTE: You are assumed to not only compile your program with these -dnl flags, but also link it with them as well. e.g. you should link -dnl with $PTHREAD_CXX $CXXFLAGS $PTHREAD_CXXFLAGS $LDFLAGS ... $PTHREAD_LIBS -dnl $LIBS -dnl -dnl If you are only building threads programs, you may wish to use -dnl these variables in your default LIBS, CXXFLAGS, and CXX: -dnl -dnl LIBS="$PTHREAD_LIBS $LIBS" -dnl CXXFLAGS="$CXXFLAGS $PTHREAD_CXXFLAGS" -dnl CXX="$PTHREAD_CXX" -dnl -dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute -dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to -dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -dnl -dnl ACTION-IF-FOUND is a list of shell commands to run if a threads -dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to -dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the -dnl default action will define HAVE_PTHREAD. -dnl -dnl Please let the authors know if this macro fails on any platform, or -dnl if you have any other suggestions or comments. This macro was based -dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with -dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros -dnl posted by Alejandro Forero Cuervo to the autoconf macro repository. -dnl We are also grateful for the helpful feedback of numerous users. -dnl -dnl @category InstalledPackages -dnl @author Steven G. Johnson -dnl @version 2006-05-29 -dnl @license GPLWithACException - -AC_DEFUN([ACX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_LANG_SAVE -AC_LANG(C++) -acx_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CXXFLAGS" != x; then - save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $PTHREAD_CXXFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CXXFLAGS=$PTHREAD_CXXFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) - AC_MSG_RESULT($acx_pthread_ok) - if test x"$acx_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CXXFLAGS="" - fi - LIBS="$save_LIBS" - CXXFLAGS="$save_CXXFLAGS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. - -# CS: On GNU/Linux with gcc both -pthread and -lpthread are valid. -# However, libtool links libraries with -nostdlib which results in -# -pthread being stripped from the linker command line. To resolve -# this we move pthread from after -mthreads to after pthreads. -# -acx_pthread_flags="pthreads pthread none -Kthread -kthread lthread -pthread -pthreads -mthreads --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case "${host_cpu}-${host_os}" in - *solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - # CS: Move -mt to the front of the list; Sun CC will use -mt, - # gcc will use -pthreads. - # - acx_pthread_flags="-mt -pthreads pthread -pthread $acx_pthread_flags" - ;; -esac - -if test x"$acx_pthread_ok" = xno; then -for flag in $acx_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CXXFLAGS="$flag" - ;; - - pthread-config) - AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) - if test x"$acx_pthread_config" = xno; then continue; fi - PTHREAD_CXXFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CXXFLAGS="$CXXFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CXXFLAGS="$CXXFLAGS $PTHREAD_CXXFLAGS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - # - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0);], - [acx_pthread_ok=yes]) - - LIBS="$save_LIBS" - CXXFLAGS="$save_CXXFLAGS" - - AC_MSG_RESULT($acx_pthread_ok) - if test "x$acx_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CXXFLAGS="" -done -fi - -# Various other checks: -if test "x$acx_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $PTHREAD_CXXFLAGS" - -dnl # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. -dnl AC_MSG_CHECKING([for joinable pthread attribute]) -dnl attr_name=unknown -dnl for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do -dnl AC_TRY_LINK([#include ], [int attr=$attr; return attr;], -dnl [attr_name=$attr; break]) -dnl done -dnl AC_MSG_RESULT($attr_name) -dnl if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then -dnl AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, -dnl [Define to necessary symbol if this constant -dnl uses a non-standard name on your system.]) -dnl fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; - # CS: Add _REENTRANT in Linux to emulate -pthread. - # - *-linux* | *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CXXFLAGS="$flag $PTHREAD_CXXFLAGS" - fi - - LIBS="$save_LIBS" - CXXFLAGS="$save_CXXFLAGS" - -dnl # More AIX lossage: must compile with xlC_r -dnl if test x"$GXX" != xyes; then -dnl AC_CHECK_PROGS(PTHREAD_CXX, xlC_r, ${CXX}) -dnl else -dnl PTHREAD_CXX=$CXX -dnl fi - -else - PTHREAD_CXX="$CXX" -fi - -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CXXFLAGS) -AC_SUBST(PTHREAD_CXX) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$acx_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) - : -else - acx_pthread_ok=no - $2 -fi -AC_LANG_RESTORE -])dnl ACX_PTHREAD diff --git a/m4/disable-rpath.m4 b/m4/disable-rpath.m4 deleted file mode 100644 index 0864209..0000000 --- a/m4/disable-rpath.m4 +++ /dev/null @@ -1,24 +0,0 @@ -dnl file : m4/disable-rpath.m4 -dnl license : GNU GPL v2; see accompanying LICENSE file -dnl -AC_DEFUN([DISABLE_RPATH],[ - -AC_MSG_CHECKING([whether to use rpath]) -AC_ARG_ENABLE( - [rpath], - [AC_HELP_STRING([--disable-rpath], [patch libtool to not use rpath])], - [libtool_rpath="$enable_rpath"], - [libtool_rpath="yes"]) -AC_MSG_RESULT($libtool_rpath) - -# Patch libtool to not use rpath if requested. -# -AC_CONFIG_COMMANDS( - [libtool-rpath-patch], - [if test "$libtool_use_rpath" = "no"; then - sed < libtool > libtool-2 's/^hardcode_libdir_flag_spec.*$'/'hardcode_libdir_flag_spec=" -D__LIBTOOL_NO_RPATH__ "/' - mv libtool-2 libtool - chmod 755 libtool - fi], - [libtool_use_rpath=$libtool_rpath]) -])dnl diff --git a/m4/libodb.m4 b/m4/libodb.m4 deleted file mode 100644 index 0dba7c4..0000000 --- a/m4/libodb.m4 +++ /dev/null @@ -1,81 +0,0 @@ -dnl file : m4/libodb.m4 -dnl license : GNU GPL v2; see accompanying LICENSE file -dnl -dnl LIBODB([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -dnl -dnl -AC_DEFUN([LIBODB], [ -libodb_found=no - -AC_ARG_WITH( - [libodb], - [AC_HELP_STRING([--with-libodb=DIR],[location of libodb build directory])], - [libodb_dir=${withval}], - [libodb_dir=]) - -AC_MSG_CHECKING([for libodb]) - -# If libodb_dir was given, add the necessary preprocessor and linker flags. -# -if test x"$libodb_dir" != x; then - save_CPPFLAGS="$CPPFLAGS" - save_LDFLAGS="$LDFLAGS" - - AS_SET_CATFILE([abs_libodb_dir], [$ac_pwd], [$libodb_dir]) - - CPPFLAGS="$CPPFLAGS -I$abs_libodb_dir" - LDFLAGS="$LDFLAGS -L$abs_libodb_dir/odb" -fi - -save_LIBS="$LIBS" -LIBS="-lodb $LIBS" - -CXX_LIBTOOL_LINK_IFELSE([ -AC_LANG_SOURCE([ -#include - -void -f () -{ -} - -const char* -g () -{ - try - { - f (); - } - catch (const odb::exception& e) - { - return e.what (); - } - return 0; -} - -int -main () -{ - const char* m (g ()); - return m != 0; -} -])], -[libodb_found=yes]) - -if test x"$libodb_found" = xno; then - LIBS="$save_LIBS" - - if test x"$libodb_dir" != x; then - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - fi -fi - -if test x"$libodb_found" = xyes; then - AC_MSG_RESULT([yes]) - $1 -else - AC_MSG_RESULT([no]) - $2 -fi -])dnl diff --git a/m4/libtool-link.m4 b/m4/libtool-link.m4 deleted file mode 100644 index 302639f..0000000 --- a/m4/libtool-link.m4 +++ /dev/null @@ -1,45 +0,0 @@ -dnl file : m4/libtool-link.m4 -dnl license : GNU GPL v2; see accompanying LICENSE file -dnl -dnl -dnl CXX_LIBTOOL_LINK_IFELSE (input, [action-if-true], [action-if-false]) -dnl -dnl Similar to AC_LINK_IFELSE except it uses libtool to perform the -dnl linking and it does this using the C++ compiler. -dnl -AC_DEFUN([CXX_LIBTOOL_LINK_IFELSE],[ -AC_LANG_SAVE -AC_LANG(C++) - -if test -d .libs; then - delete_libs_dir=no -else - delete_libs_dir=yes -fi - -AC_COMPILE_IFELSE([$1], -[ - ac_try='./libtool --tag=CXX --mode=link $CXX -no-install $CXXFLAGS $LDFLAGS -o conftest conftest.$OBJEXT $LIBS >&AS_MESSAGE_LOG_FD' - if _AC_DO_VAR(ac_try); then - libtool_link_ok=yes - else - libtool_link_ok=no - fi -], -[ - libtool_link_ok=no -]) - -if test x"$delete_libs_dir" = xyes; then - rm -rf .libs -fi - -if test x"$libtool_link_ok" = xyes; then -[$2] -: -else -[$3] -: -fi - -AC_LANG_RESTORE])dnl diff --git a/m4/pkgconfig.m4 b/m4/pkgconfig.m4 deleted file mode 100644 index c48ea56..0000000 --- a/m4/pkgconfig.m4 +++ /dev/null @@ -1,11 +0,0 @@ -dnl file : m4/pkgconfig.m4 -dnl license : GNU GPL v2; see accompanying LICENSE file -dnl -AC_DEFUN([PKGCONFIG],[ -AC_ARG_WITH( - [pkgconfigdir], - [AC_HELP_STRING([--with-pkgconfigdir=DIR],[location of pkgconfig dir (default is libdir/pkgconfig)])], - [pkgconfigdir=${withval}], - [pkgconfigdir='${libdir}/pkgconfig']) -AC_SUBST([pkgconfigdir]) -])dnl diff --git a/m4/static-lib.m4 b/m4/static-lib.m4 deleted file mode 100644 index 5fb1c11..0000000 --- a/m4/static-lib.m4 +++ /dev/null @@ -1,17 +0,0 @@ -dnl file : m4/static-lib.m4 -dnl license : GNU GPL v2; see accompanying LICENSE file -dnl -dnl STATIC_LIB(MACRO, DESCRIPTION) -dnl -dnl Define MACRO if we are on MinGW and are only building static library. -dnl -AC_DEFUN([STATIC_LIB], -[ -if test x$enable_shared = xno; then - case $host_os in - mingw*) - AC_DEFINE([$1], [1], [$2]) - ;; - esac -fi -])dnl diff --git a/m4/threads.m4 b/m4/threads.m4 deleted file mode 100644 index 6f2e25f..0000000 --- a/m4/threads.m4 +++ /dev/null @@ -1,68 +0,0 @@ -dnl file : m4/threads.m4 -dnl license : GNU GPL v2; see accompanying LICENSE file -dnl -AC_DEFUN([THREADS],[ - -threads_thread_keyword=no - -AC_ARG_ENABLE( - [threads], - AS_HELP_STRING([--disable-threads], [disable threads (enabled by default)]), - [AS_IF([test x"$enableval" = xno], [threads=none], [threads=check])], - [threads=check]) - -# If thread support is not disabled by the user, figure out what we can use. -# -if test x$threads = xcheck; then - case $host_os in - windows* | mingw*) - case $host_os in - mingw*) - CXXFLAGS="$CXXFLAGS -mthreads" - ;; - esac - - # Newer versions of GCC can be configured to use either Win32 or POSIX - # threads. It appears that -mthreads should be used in both cases but - # if the model is POSIX then GCC will also link -lpthread by default. - # Use that fact to test which model we have. - # - AC_TRY_LINK([#include ], - [pthread_create(0,0,0,0);], - [threads=posix], - [threads=win32]) - ;; - *) - ACX_PTHREAD - - if test x$acx_pthread_ok = xyes; then - threads=posix - LIBS="$LIBS $PTHREAD_LIBS" - CXXFLAGS="$CXXFLAGS $PTHREAD_CXXFLAGS" - - # Check if we can use the __thread keyword. - # - AC_MSG_CHECKING([for __thread keyword]) - - CXX_LIBTOOL_LINK_IFELSE([ - AC_LANG_SOURCE([ - __thread int tls_var; - - int - main () - { - tls_var = 0; - } - ])], - [threads_thread_keyword=yes]) - - AC_MSG_RESULT([$threads_thread_keyword]) - fi - ;; - esac -fi - -if test x$threads = xcheck; then - AC_MSG_ERROR([thread support not available; use --disable-threads to force single-threaded mode]) -fi -])dnl diff --git a/makefile b/makefile deleted file mode 100644 index 74e1b6e..0000000 --- a/makefile +++ /dev/null @@ -1,35 +0,0 @@ -# file : makefile -# license : GNU GPL v2; see accompanying LICENSE file - -include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make - -dirs := odb - -default := $(out_base)/ -dist := $(out_base)/.dist -clean := $(out_base)/.clean - -$(default): $(addprefix $(out_base)/,$(addsuffix /,$(dirs))) - -$(dist): export dirs := $(dirs) -$(dist): export docs := GPLv2 LICENSE README NEWS version.txt -$(dist): data_dist := INSTALL libodb-vc8.sln libodb-vc9.sln libodb-vc10.sln \ -libodb-vc11.sln libodb-vc12.sln -$(dist): exec_dist := bootstrap -$(dist): export extra_dist := $(data_dist) $(exec_dist) -$(dist): export version = $(shell cat $(src_root)/version.txt) - -$(dist): $(addprefix $(out_base)/,$(addsuffix /.dist,$(dirs))) - $(call dist-data,$(docs) $(data_dist) libodb.pc.in) - $(call dist-exec,$(exec_dist)) - $(call dist-dir,m4) - $(call meta-automake) - $(call meta-autoconf) - -$(clean): $(addprefix $(out_base)/,$(addsuffix /.clean,$(dirs))) - -$(call include,$(bld_root)/dist.make) -$(call include,$(bld_root)/meta/automake.make) -$(call include,$(bld_root)/meta/autoconf.make) - -$(foreach d,$(dirs),$(call import,$(src_base)/$d/makefile)) diff --git a/manifest b/manifest deleted file mode 100644 index d728912..0000000 --- a/manifest +++ /dev/null @@ -1,19 +0,0 @@ -: 1 -name: libodb -version: 2.5.0-b.26.z -project: odb -summary: Common ODB runtime library -license: GPL-2.0-only -license: other: proprietary ; Not free/open source. -topics: C++, ORM, SQL, object persistence, relational database -description-file: README -changes-file: NEWS -url: https://www.codesynthesis.com/products/odb/ -doc-url: https://www.codesynthesis.com/products/odb/doc/manual.xhtml -src-url: https://git.codesynthesis.com/cgit/odb/libodb/ -email: odb-users@codesynthesis.com -build-warning-email: odb-builds@codesynthesis.com -builds: all -requires: c++11 -depends: * build2 >= 0.16.0- -depends: * bpkg >= 0.16.0- diff --git a/odb/Makefile.am b/odb/Makefile.am deleted file mode 100644 index af5141c..0000000 --- a/odb/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -# file : odb/Makefile.am -# license : GNU GPL v2; see accompanying LICENSE file - -lib_LTLIBRARIES = libodb.la -libodb_la_SOURCES = __path__(sources) - -odbincludedir = $(includedir)/odb -nobase_odbinclude_HEADERS = __path__(headers) -nobase_nodist_odbinclude_HEADERS = details/config.h - -EXTRA_DIST = __file__(extra_dist) - -# At the moment, DllMain() is only necessary if we are using Win32 -# threads. So keep win32_dll_sources in ODB_THREADS_WIN32. -# -if ODB_WIN32 -nobase_odbinclude_HEADERS += __path__(win32_headers) -endif - -if ODB_THREADS_POSIX -libodb_la_SOURCES += __path__(posix_threads_sources) -nobase_odbinclude_HEADERS += __path__(posix_threads_headers) -endif - -if ODB_THREADS_WIN32 -libodb_la_SOURCES += __path__(win32_threads_sources) __path__(win32_dll_sources) -nobase_odbinclude_HEADERS += __path__(win32_threads_headers) -endif - -AM_CPPFLAGS= -I'$(top_builddir)' -I'$(top_srcdir)' -DLIBODB_DYNAMIC_LIB -AM_LDFLAGS = -release __value__(interface_version) -no-undefined diff --git a/odb/buildfile b/odb/buildfile deleted file mode 100644 index ec95e94..0000000 --- a/odb/buildfile +++ /dev/null @@ -1,81 +0,0 @@ -# file : odb/buildfile -# license : GNU GPL v2; see accompanying LICENSE file - -lib{odb}: {hxx ixx txx cxx}{* -version-build2} \ - {hxx}{version-build2} \ - details/{hxx ixx txx}{*} \ - details/{cxx}{* -condition -lock -mutex} \ - details/build2/{h}{*} \ - details/meta/{hxx}{*} \ -details/shared-ptr/{hxx ixx txx cxx}{*} \ - details/win32/{hxx}{windows} - -# Include the generated version header into the distribution (so that we don't -# pick up an installed one) and don't remove it when cleaning in src (so that -# clean results in a state identical to distributed). -# -hxx{version-build2}: in{version-build2} $src_root/manifest -hxx{version-build2}: -{ - dist = true - clean = ($src_root != $out_root) -} - -# Build options. -# -cxx.poptions =+ "-I$out_root" "-I$src_root" -DLIBODB_BUILD2 - -obja{*}: cxx.poptions += -DLIBODB_STATIC_BUILD -objs{*}: cxx.poptions += -DLIBODB_SHARED_BUILD - -# Export options. -# -lib{odb}: cxx.export.poptions = "-I$out_root" "-I$src_root" -DLIBODB_BUILD2 - -liba{odb}: cxx.export.poptions += -DLIBODB_STATIC -libs{odb}: cxx.export.poptions += -DLIBODB_SHARED - -# For pre-releases use the complete version to make sure they cannot be used -# in place of another pre-release or the final version. See the version module -# for details on the version.* variable values. -# -if $version.pre_release - lib{odb}: bin.lib.version = @"-$version.project_id" -else - lib{odb}: bin.lib.version = @"-$version.major.$version.minor" - -# Install into the odb/ subdirectory of, say, /usr/include/ recreating -# subdirectories. -# -install_include = [dir_path] include/odb/ - -{hxx ixx txx}{*}: -{ - install = $install_include - install.subdirs = true -} - -if ($cxx.target.class != "windows") - details/win32/*: install = false - -# We want these to be picked up whether LIBODB_BUILD2 is defined or not. -# -hxx{version}@./: install = false -hxx{version-build2}: install = $install_include/version.hxx -hxx{version-build2-stub}@./: install = $install_include/version-build2.hxx - -details/build2/ -{ - h{*}: install = false - - if ($cxx.target.system == 'win32-msvc') - { - h{config-vc}@./: install = $install_include/details/ - h{config-vc-stub}@./: install = $install_include/details/build2/config-vc.h - } - else - { - h{config}@./: install = $install_include/details/ - h{config-stub}@./: install = $install_include/details/build2/config.h - } -} diff --git a/odb/c-array-traits.hxx b/odb/c-array-traits.hxx deleted file mode 100644 index fff7880..0000000 --- a/odb/c-array-traits.hxx +++ /dev/null @@ -1,103 +0,0 @@ -// file : odb/c-array-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_C_ARRAY_TRAITS_HXX -#define ODB_C_ARRAY_TRAITS_HXX - -#include - -#include // std::size_t -#include - -#include - -namespace odb -{ - // Optional mapping of C arrays as containers. Note that this mapping is not - // enable by default. To enable, pass the following options to the ODB - // compiler: - // - // --odb-epilogue '#include ' - // --hxx-prologue '#include ' - // - // Note also that the array types have to be named, for example: - // - // class object - // { - // // composite_type values[5]; // Won't work. - // - // typedef composite_type composite_array[5]; - // composite_array values; - // }; - // - // Finally, this mapping is disabled for the char[N] and wchar_t[N] types - // (they are mapped as strings by default). - // - template - class access::container_traits - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef V container_type[N]; - - typedef V value_type; - typedef std::size_t index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - for (index_type i (0); i < N; ++i) - f.insert (i, c[i]); - } - - static void - load (container_type& c, bool more, const functions& f) - { - index_type i (0); - - for (; more && i < N; ++i) - { - index_type dummy; - more = f.select (dummy, c[i]); - } - - assert (!more && i == N); - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (index_type i (0); i < N; ++i) - f.insert (i, c[i]); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; - - // Disable for char[N] and wchar_t[N]. - // -#ifdef ODB_COMPILER - template - class access::container_traits; - -#ifdef _WIN32 - template - class access::container_traits; -#endif -#endif -} - -#include - -#endif // ODB_C_ARRAY_TRAITS_HXX diff --git a/odb/cache-traits.hxx b/odb/cache-traits.hxx deleted file mode 100644 index a8cf750..0000000 --- a/odb/cache-traits.hxx +++ /dev/null @@ -1,182 +0,0 @@ -// file : odb/cache-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_CACHE_TRAITS_HXX -#define ODB_CACHE_TRAITS_HXX - -#include - -#include -#include -#include -#include -#include - -namespace odb -{ - // pointer_cache_traits - // - // Caching traits for objects passed by pointer. P should be the canonical - // pointer (non-const). - // - template - struct pointer_cache_traits_impl - { - typedef P pointer_type; - typedef S session_type; - typedef odb::pointer_traits pointer_traits; - typedef typename pointer_traits::element_type object_type; - typedef typename object_traits::id_type id_type; - typedef typename session_type::template cache_position - position_type; - - struct insert_guard - { - insert_guard () {} - insert_guard (const position_type& pos): pos_ (pos) {} - ~insert_guard () {session_type::_cache_erase (pos_);} - - const position_type& - position () const {return pos_;} - - void - release () {pos_ = position_type ();} - - // Note: doesn't call erase() on the old position (assumes empty). - // - void - reset (const position_type& pos) {pos_ = pos;} - - private: - position_type pos_; - }; - - // Cache management. - // - // We need the insert() overload with explicit id to handle self- - // references. In such cases the object is not yet loaded and the - // id member does not contain the correct id. - // - // Qualify the database type to resolve a phony ambiguity in VC 10. - // - static position_type - insert (odb::database& db, const id_type& id, const pointer_type& p) - { - return session_type::template _cache_insert (db, id, p); - } - - static position_type - insert (odb::database& db, const pointer_type& p) - { - const id_type& id ( - object_traits::id ( - pointer_traits::get_ref (p))); - - return session_type::template _cache_insert (db, id, p); - } - - static pointer_type - find (odb::database& db, const id_type& id) - { - return session_type::template _cache_find (db, id); - } - - static void - erase (const position_type& p) - { - session_type::template _cache_erase (p); - } - - // Notifications. - // - static void - persist (const position_type& p) - { - session_type::template _cache_persist (p); - } - - static void - load (const position_type& p) - { - session_type::template _cache_load (p); - } - - static void - update (odb::database& db, const object_type& obj) - { - session_type::template _cache_update (db, obj); - } - - static void - erase (odb::database& db, const id_type& id) - { - session_type::template _cache_erase (db, id); - } - }; - - // Unique pointers don't work with the object cache. - // - template - struct pointer_cache_traits_impl: - no_op_pointer_cache_traits

{}; - - template - struct pointer_cache_traits: - pointer_cache_traits_impl::kind> {}; - - // reference_cache_traits - // - // Caching traits for objects passed by reference. T should be the - // canonical object type (non-const). Only if the object pointer - // kind is raw do we add the object to the session. - // - template - struct reference_cache_traits_impl: no_op_reference_cache_traits {}; - - template - struct reference_cache_traits_impl - { - typedef T object_type; - typedef typename object_traits::pointer_type pointer_type; - typedef typename object_traits::id_type id_type; - - typedef pointer_cache_traits pointer_traits; - typedef typename pointer_traits::position_type position_type; - typedef typename pointer_traits::insert_guard insert_guard; - - static position_type - insert (odb::database& db, const id_type& id, object_type& obj) - { - pointer_type p (&obj); - return pointer_traits::insert (db, id, p); - } - - static position_type - insert (odb::database& db, object_type& obj) - { - pointer_type p (&obj); - return pointer_traits::insert (db, p); - } - - static void - persist (const position_type& p) - { - pointer_traits::persist (p); - } - - static void - load (const position_type& p) - { - pointer_traits::load (p); - } - }; - - template - struct reference_cache_traits: - reference_cache_traits_impl< - T, S, pointer_traits::pointer_type>::kind> {}; -} - -#include - -#endif // ODB_CACHE_TRAITS_HXX diff --git a/odb/callback.hxx b/odb/callback.hxx deleted file mode 100644 index aaa066f..0000000 --- a/odb/callback.hxx +++ /dev/null @@ -1,42 +0,0 @@ -// file : odb/callback.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_CALLBACK_HXX -#define ODB_CALLBACK_HXX - -#include - -#include // odb::core - -namespace odb -{ - struct callback_event - { - enum value - { - pre_persist, - post_persist, - pre_load, - post_load, - pre_update, - post_update, - pre_erase, - post_erase - }; - - callback_event (value v): v_ (v) {} - operator value () const {return v_;} - - private: - value v_; - }; - - namespace common - { - using odb::callback_event; - } -} - -#include - -#endif // ODB_CALLBACK_HXX diff --git a/odb/connection.cxx b/odb/connection.cxx deleted file mode 100644 index 29743a2..0000000 --- a/odb/connection.cxx +++ /dev/null @@ -1,125 +0,0 @@ -// file : odb/connection.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include -#include -#include // prepared_* - -using namespace std; - -namespace odb -{ - // connection - // - connection:: - ~connection () - { - assert (prepared_queries_ == 0); - assert (prepared_map_.empty ()); - } - - void connection:: - clear_prepared_map () - { - for (prepared_map_type::iterator i (prepared_map_.begin ()), - e (prepared_map_.end ()); i != e; ++i) - { - if (i->second.params != 0) - i->second.params_deleter (i->second.params); - } - - prepared_map_.clear (); - } - - void connection:: - recycle () - { - while (prepared_queries_ != 0) - { - prepared_queries_->stmt.reset (); - prepared_queries_->list_remove (); - } - } - - void connection:: - invalidate_results () - { - while (results_ != 0) - { - results_->invalidate (); - results_->list_remove (); - } - } - - void connection:: - cache_query_ (prepared_query_impl* pq, - const type_info& ti, - void* params, - const type_info* params_info, - void (*params_deleter) (void*)) - { - pair r ( - prepared_map_.insert ( - prepared_map_type::value_type (pq->name, prepared_entry_type ()))); - - if (!r.second) - throw prepared_already_cached (pq->name); - - prepared_entry_type& e (r.first->second); - - // Mark this prepared query as cached , get its ref count to 1 - // (prepared_query instances now reference this impl object), - // and remove it from the invalidation list. - // - pq->cached = true; - - while (pq->_ref_count () > 1) - pq->_dec_ref (); - - pq->list_remove (); - - e.prep_query.reset (pq); - e.type_info = &ti; - e.params = params; - e.params_info = params_info; - e.params_deleter = params_deleter; - } - - prepared_query_impl* connection:: - lookup_query_ (const char* name, - const type_info& ti, - void** params, - const type_info* params_info) const - { - prepared_map_type::const_iterator i (prepared_map_.find (name)); - - if (i == prepared_map_.end ()) - { - // Use a factory, if there is one. - // - if (factory_.database ().call_query_factory ( - name, const_cast (*this))) - i = prepared_map_.find (name); - } - - if (i == prepared_map_.end ()) - return 0; - - // Make sure the types match. - // - if (*i->second.type_info != ti) - throw prepared_type_mismatch (name); - - if (params != 0) - { - if (*i->second.params_info != *params_info) - throw prepared_type_mismatch (name); - - *params = i->second.params; - } - - return i->second.prep_query.get (); - } -} diff --git a/odb/connection.hxx b/odb/connection.hxx deleted file mode 100644 index 8ce4544..0000000 --- a/odb/connection.hxx +++ /dev/null @@ -1,228 +0,0 @@ -// file : odb/connection.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_CONNECTION_HXX -#define ODB_CONNECTION_HXX - -#include - -#include -#include -#include // std::auto_ptr, std::unique_ptr -#include // std::size_t -#include - -#include -#include -#include -#include - -#include // ODB_CXX11 -#include -#include -#include - -namespace odb -{ - class transaction_impl; - class connection_factory; - - class connection; - typedef details::shared_ptr connection_ptr; - - class LIBODB_EXPORT connection: public details::shared_base - { - public: - typedef odb::database database_type; - - database_type& - database (); - - // Transactions. - // - public: - virtual transaction_impl* - begin () = 0; - - // Native database statement execution. Note that unlike the - // versions in the database class, these can be executed - // without a transaction. - // - public: - unsigned long long - execute (const char* statement); - - unsigned long long - execute (const std::string& statement); - - virtual unsigned long long - execute (const char* statement, std::size_t length) = 0; - - // Query preparation. - // - public: - template - prepared_query - prepare_query (const char* name, const char*); - - template - prepared_query - prepare_query (const char* name, const std::string&); - - template - prepared_query - prepare_query (const char* name, const query&); - - template - void - cache_query (const prepared_query&); - -#ifdef ODB_CXX11 - template - void - cache_query (const prepared_query&, std::unique_ptr

params); -#else - template - void - cache_query (const prepared_query&, std::auto_ptr

params); -#endif - - template - prepared_query - lookup_query (const char* name); - - template - prepared_query - lookup_query (const char* name, P*& params); - - // SQL statement tracing. - // - public: - typedef odb::tracer tracer_type; - - void - tracer (tracer_type&); - - void - tracer (tracer_type*); - - tracer_type* - tracer () const; - - public: - // Store the transaction-spacific tracer in the connection. If we - // were to store it in the transaction, then in order to check if - // it was set, we would need to get the transaction instance using - // the current() API. But that requires a TLS lookup, which can be - // slow. - // - tracer_type* - transaction_tracer () const; - - public: - virtual - ~connection (); - - // Recycle the connection to be used by another thread. This call - // invalidates uncached prepared queries. - // - void - recycle (); - - protected: - connection (connection_factory&); - - template ::kind> - struct query_; - - virtual void - cache_query_ (prepared_query_impl* pq, - const std::type_info& ti, - void* params, - const std::type_info* params_info, - void (*params_deleter) (void*)); - - prepared_query_impl* - lookup_query_ (const char* name, - const std::type_info& ti, - void** params, // out - const std::type_info* params_info) const; - - template - static void - params_deleter (void*); - - private: - connection (const connection&); - connection& operator= (const connection&); - - // Prepared query cache. - // - protected: - struct prepared_entry_type - { - details::shared_ptr prep_query; - const std::type_info* type_info; - void* params; - const std::type_info* params_info; - void (*params_deleter) (void*); - }; - - typedef - std::map - prepared_map_type; - - prepared_map_type prepared_map_; - - void - clear_prepared_map (); - - protected: - connection_factory& factory_; - tracer_type* tracer_; - - // Active query result list. - // - protected: - friend class result_impl; - result_impl* results_; - - void - invalidate_results (); - - // Prepared but uncached query list (cached ones are stored in - // prepared_map_). - // - protected: - friend class prepared_query_impl; - prepared_query_impl* prepared_queries_; - - // Implementation details. - // - public: - tracer_type* transaction_tracer_; - }; - - class connection_factory - { - public: - typedef odb::database database_type; - - connection_factory (): db_ (0) {} - - database_type& - database () {return *db_;} - - protected: - database_type* db_; - }; -} - -#include -#include - -#include - -#endif // ODB_CONNECTION_HXX diff --git a/odb/connection.ixx b/odb/connection.ixx deleted file mode 100644 index d19390a..0000000 --- a/odb/connection.ixx +++ /dev/null @@ -1,131 +0,0 @@ -// file : odb/connection.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include // std::string -#include - -namespace odb -{ - inline connection:: - connection (connection_factory& f) - : factory_ (f), - tracer_ (0), - results_ (0), - prepared_queries_ (0), - transaction_tracer_ (0) - { - } - - inline connection::database_type& connection:: - database () - { - return factory_.database (); - } - - inline unsigned long long connection:: - execute (const char* st) - { - return execute (st, std::strlen (st)); - } - - inline unsigned long long connection:: - execute (const std::string& st) - { - return execute (st.c_str (), st.size ()); - } - - template - inline prepared_query connection:: - prepare_query (const char* n, const char* q) - { - return prepare_query (n, query (q)); - } - - template - inline prepared_query connection:: - prepare_query (const char* n, const std::string& q) - { - return prepare_query (n, query (q)); - } - - template - inline prepared_query connection:: - prepare_query (const char* n, const query& q) - { - return query_::call (*this, n, q); - } - - template - inline void connection:: - cache_query (const prepared_query& pq) - { - assert (pq); - cache_query_ (pq.impl_, typeid (T), 0, 0, 0); - } - -#ifdef ODB_CXX11 - template - inline void connection:: - cache_query (const prepared_query& pq, std::unique_ptr

params) - { - assert (pq); - assert (params); - cache_query_ ( - pq.impl_, typeid (T), params.get (), &typeid (P), ¶ms_deleter

); - params.release (); - } -#else - template - inline void connection:: - cache_query (const prepared_query& pq, std::auto_ptr

params) - { - assert (pq); - assert (params.get () != 0); - cache_query_ ( - pq.impl_, typeid (T), params.get (), &typeid (P), ¶ms_deleter

); - params.release (); - } -#endif - - template - inline prepared_query connection:: - lookup_query (const char* name) - { - return prepared_query (lookup_query_ (name, typeid (T), 0, 0)); - } - - template - inline prepared_query connection:: - lookup_query (const char* name, P*& params) - { - return prepared_query ( - lookup_query_ (name, - typeid (T), - reinterpret_cast (¶ms), - &typeid (P))); - } - - inline void connection:: - tracer (tracer_type& t) - { - tracer_ = &t; - } - - inline void connection:: - tracer (tracer_type* t) - { - tracer_ = t; - } - - inline connection::tracer_type* connection:: - tracer () const - { - return tracer_; - } - - inline connection::tracer_type* connection:: - transaction_tracer () const - { - return transaction_tracer_; - } -} diff --git a/odb/connection.txx b/odb/connection.txx deleted file mode 100644 index a082f14..0000000 --- a/odb/connection.txx +++ /dev/null @@ -1,44 +0,0 @@ -// file : odb/connection.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - template - struct connection::query_ - { - template - static prepared_query - call (connection& c, const char* n, const Q& q) - { - // C++ compiler complaining there is no prepare_query()? Perhaps - // you forgot to specify --generate-prepared when compiling your - // persistent classes. - // - return prepared_query ( - object_traits_impl::prepare_query (c, n, q)); - } - }; - - template - struct connection::query_ - { - template - static prepared_query - call (connection& c, const char* n, const Q& q) - { - // C++ compiler complaining there is no prepare_query()? Perhaps - // you forgot to specify --generate-prepared when compiling your - // views. - // - return prepared_query ( - view_traits_impl::prepare_query (c, n, q)); - } - }; - - template - void connection:: - params_deleter (void* p) - { - delete static_cast (p); - } -} diff --git a/odb/container-traits.hxx b/odb/container-traits.hxx deleted file mode 100644 index e2f44ce..0000000 --- a/odb/container-traits.hxx +++ /dev/null @@ -1,219 +0,0 @@ -// file : odb/container-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_CONTAINER_TRAITS_HXX -#define ODB_CONTAINER_TRAITS_HXX - -#include - -#include -#include // ODB_CXX11 - -namespace odb -{ - // Keep this enum synchronized with the one in odb/odb/context.hxx. - // - enum container_kind - { - ck_ordered, - ck_set, - ck_multiset, - ck_map, - ck_multimap - }; - - // - // Container API provided by the generated code. - // - - // Ordered containers. - // - template - struct ordered_functions - { - typedef I index_type; - typedef V value_type; - - // Return true if the order is preserved in the database. If the - // order is not preserved, then the index argument in the functions - // below is not used. - // - bool - ordered () const - { - return ordered_; - } - - void - insert (I index, const V& value) const - { - insert_ (index, value, data_); - } - - bool - select (I& next_index, V& next_value) const - { - return select_ (next_index, next_value, data_); - } - - void - delete_ () const - { - delete__ (data_); - } - - // Implementation details. - // - public: - ordered_functions (void* data): data_ (data) {} - - public: - void* data_; - bool ordered_; - - void (*insert_) (I, const V&, void*); - bool (*select_) (I&, V&, void*); - void (*delete__) (void*); - }; - - template - struct smart_ordered_functions - { - typedef I index_type; - typedef V value_type; - - void - insert (I index, const V& value) const - { - insert_ (index, value, data_); - } - - bool - select (I& next_index, V& next_value) const - { - return select_ (next_index, next_value, data_); - } - - void - update (I index, const V& value) const - { - update_ (index, value, data_); - } - - // Delete all the elements starting with the specified index. To - // delete everything, pass 0. - // - void - delete_ (I start_index) const - { - delete__ (start_index, data_); - } - - // Implementation details. - // - public: - smart_ordered_functions (void* data) : data_ (data) {} - - public: - void* data_; - - void (*insert_) (I, const V&, void*); - bool (*select_) (I&, V&, void*); - void (*update_) (I, const V&, void*); - void (*delete__) (I, void*); - }; - - // Set/multiset containers. - // - template - struct set_functions - { - typedef V value_type; - - void - insert (const V& value) const - { - insert_ (value, data_); - } - - bool - select (V& next_value) const - { - return select_ (next_value, data_); - } - - void - delete_ () const - { - delete__ (data_); - } - - // Implementation details. - // - public: - set_functions (void* data): data_ (data) {} - - public: - void* data_; - - void (*insert_) (const V&, void*); - bool (*select_) (V&, void*); - void (*delete__) (void*); - }; - - // Map/multimap containers. - // - template - struct map_functions - { - typedef K key_type; - typedef V value_type; - - void - insert (const K& key, const V& value) const - { - insert_ (key, value, data_); - } - - bool - select (K& next_key, V& next_value) const - { - return select_ (next_key, next_value, data_); - } - - void - delete_ () const - { - delete__ (data_); - } - - // Implementation details. - // - public: - map_functions (void* data): data_ (data) {} - - public: - void* data_; - - void (*insert_) (const K&, const V&, void*); - bool (*select_) (K&, V&, void*); - void (*delete__) (void*); - }; -} - -#include - -#include -#include -#include -#include -#include - -#ifdef ODB_CXX11 -# include -# include -# include -# include -#endif - -#endif // ODB_CONTAINER_TRAITS_HXX diff --git a/odb/core.hxx b/odb/core.hxx deleted file mode 100644 index bca295d..0000000 --- a/odb/core.hxx +++ /dev/null @@ -1,20 +0,0 @@ -// file : odb/core.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_CORE_HXX -#define ODB_CORE_HXX - -#include - -#ifdef ODB_COMPILER -# define PRAGMA_DB_IMPL(x) _Pragma (#x) -# define PRAGMA_DB(x) PRAGMA_DB_IMPL (db x) -#else -# define PRAGMA_DB(x) -#endif - -#include - -#include - -#endif // ODB_CORE_HXX diff --git a/odb/database.cxx b/odb/database.cxx deleted file mode 100644 index 9e098c7..0000000 --- a/odb/database.cxx +++ /dev/null @@ -1,83 +0,0 @@ -// file : odb/database.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -#include - -using namespace std; - -namespace odb -{ - using details::lock; - - database:: - ~database () - { - } - - unsigned long long database:: - execute (const char* st, std::size_t n) - { - connection_type& c (transaction::current ().connection (*this)); - return c.execute (st, n); - } - - const database::schema_version_migration_type& database:: - schema_version_migration (const string& name) const - { - lock l (*mutex_); // Prevents concurrent loading. - - schema_version_map::const_iterator i (schema_version_map_.find (name)); - return i != schema_version_map_.end () && i->second.version != 0 - ? i->second - : load_schema_version (name); - } - - void database:: - schema_version_migration (const schema_version_migration_type& svm, - const string& name) - { - // Note: no lock, not thread-safe. - - schema_version_info& svi (schema_version_map_[name]); - if (svi.version != svm.version || svi.migration != svm.migration) - { - svi.version = svm.version; - svi.migration = svm.migration; - schema_version_seq_++; - } - } - - bool database:: - call_query_factory (const char* name, connection_type& c) const - { - query_factory_map::const_iterator i (query_factory_map_.find (name)); - - if (i == query_factory_map_.end ()) - i = query_factory_map_.find (""); // Wildcard factory. - - if (i == query_factory_map_.end ()) - return false; - - const query_factory_wrapper& fw (i->second); - if (fw.std_function == 0) - fw.function (name, c); - else - { - typedef void (*caller) (const void*, const char*, connection_type&); - fw.cast () (fw.std_function, name, c); - } - - return true; - } - - void database:: - query_factory (const char* name, query_factory_wrapper w) - { - if (w) - query_factory_map_[name] = w; // Destructive copy assignment (move). - else - query_factory_map_.erase (name); - } -} diff --git a/odb/database.hxx b/odb/database.hxx deleted file mode 100644 index e18e8ee..0000000 --- a/odb/database.hxx +++ /dev/null @@ -1,657 +0,0 @@ -// file : odb/database.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DATABASE_HXX -#define ODB_DATABASE_HXX - -#include - -#include // ODB_CXX11 - -#include -#include -#include // std::auto_ptr, std::unique_ptr -#include // std::size_t - -#ifdef ODB_CXX11 -# include // std::move -# include // std::function -# include // std::enable_if, std::is_convertible -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace odb -{ - class transaction_impl; - - class LIBODB_EXPORT database - { - public: - virtual - ~database (); - -#ifdef ODB_CXX11 - //database (database&&) = default; // VC 2013 - - // Note: noexcept is not specified since *_map_ (std::map) can throw. - // - database (database&& d) - : id_ (d.id_), - tracer_ (d.tracer_), - query_factory_map_ (std::move (d.query_factory_map_)), - mutex_ (std::move (d.mutex_)), - schema_version_map_ (std::move (d.schema_version_map_)), - schema_version_table_ (std::move (d.schema_version_table_)), - schema_version_seq_ (d.schema_version_seq_) - { - } -#endif - - private: - database (const database&); - database& operator= (const database&); - -#ifdef ODB_CXX11 - database& operator= (const database&&); -#endif - - // Object persistence API. - // - public: - // Make the object persistent. - // - template - typename object_traits::id_type - persist (T& object); - - template - typename object_traits::id_type - persist (const T& object); - - template - typename object_traits::id_type - persist (T* obj_ptr); - - template class P> - typename object_traits::id_type - persist (const P& obj_ptr); - - template class P> - typename object_traits::id_type - persist (const P& obj_ptr); - - template class P> - typename object_traits::id_type - persist (P& obj_ptr); - - template class P> - typename object_traits::id_type - persist (P& obj_ptr); - - template - typename object_traits::id_type - persist (const typename object_traits::pointer_type& obj_ptr); - - // Bulk persist. Can be a range of references or pointers (including - // smart pointers) to objects. - // - template - void - persist (I begin, I end, bool continue_failed = true); - - // Load an object. Throw object_not_persistent if not found. - // - template - typename object_traits::pointer_type - load (const typename object_traits::id_type& id); - - template - void - load (const typename object_traits::id_type& id, T& object); - - // Load (or reload, if it is already loaded) a section of an object. - // - template - void - load (T& object, section&); - - // Reload an object. - // - template - void - reload (T& object); - - template - void - reload (T* obj_ptr); - - template class P> - void - reload (const P& obj_ptr); - - template class P> - void - reload (const P& obj_ptr); - - template class P> - void - reload (P& obj_ptr); - - template class P> - void - reload (P& obj_ptr); - - template - void - reload (const typename object_traits::pointer_type& obj_ptr); - - // Loan an object if found. Return NULL/false if not found. - // - template - typename object_traits::pointer_type - find (const typename object_traits::id_type& id); - - template - bool - find (const typename object_traits::id_type& id, T& object); - - // Update the state of a modified objects. - // - template - void - update (T& object); - - template - void - update (T* obj_ptr); - - template class P> - void - update (const P& obj_ptr); - - template class P> - void - update (const P& obj_ptr); - - template class P> - void - update (P& obj_ptr); - - template class P> - void - update (P& obj_ptr); - - template - void - update (const typename object_traits::pointer_type& obj_ptr); - - // Bulk update. Can be a range of references or pointers (including - // smart pointers) to objects. - // - template - void - update (I begin, I end, bool continue_failed = true); - - // Update a section of an object. Throws section_not_loaded exception - // if section is not loaded. Note also that this function does not - // clear the changed flag if it is set. - // - template - void - update (const T& object, const section&); - - // Make the object transient. Throw object_not_persistent if not - // found. - // - template - void - erase (const typename object_traits::id_type& id); - - template - void - erase (T& object); - - template - void - erase (T* obj_ptr); - - template class P> - void - erase (const P& obj_ptr); - - template class P> - void - erase (const P& obj_ptr); - - template class P> - void - erase (P& obj_ptr); - - template class P> - void - erase (P& obj_ptr); - - template - void - erase (const typename object_traits::pointer_type& obj_ptr); - - // Bulk erase. - // - template - void - erase (I id_begin, I id_end, bool continue_failed = true); - - // Can be a range of references or pointers (including smart pointers) - // to objects. - // - template - void - erase (I obj_begin, I obj_end, bool continue_failed = true); - - // Erase multiple objects matching a query predicate. - // - template - unsigned long long - erase_query (); - - template - unsigned long long - erase_query (const char*); - - template - unsigned long long - erase_query (const std::string&); - - template - unsigned long long - erase_query (const odb::query&); - - // Query API. - // - template - result - query (bool cache = true); - - template - result - query (const char*, bool cache = true); - - template - result - query (const std::string&, bool cache = true); - - template - result - query (const odb::query&, bool cache = true); - - // Query one API. - // - template - typename result::pointer_type - query_one (); - - template - bool - query_one (T& object); - - template - T - query_value (); - - template - typename result::pointer_type - query_one (const char*); - - template - bool - query_one (const char*, T& object); - - template - T - query_value (const char*); - - template - typename result::pointer_type - query_one (const std::string&); - - template - bool - query_one (const std::string&, T& object); - - template - T - query_value (const std::string&); - - template - typename result::pointer_type - query_one (const odb::query&); - - template - bool - query_one (const odb::query&, T& object); - - template - T - query_value (const odb::query&); - - // Query preparation. - // - template - prepared_query - prepare_query (const char* name, const char*); - - template - prepared_query - prepare_query (const char* name, const std::string&); - - template - prepared_query - prepare_query (const char* name, const odb::query&); - - template - void - cache_query (const prepared_query&); - -#ifdef ODB_CXX11 - template - void - cache_query (const prepared_query&, std::unique_ptr

params); -#else - template - void - cache_query (const prepared_query&, std::auto_ptr

params); -#endif - - template - prepared_query - lookup_query (const char* name); - - template - prepared_query - lookup_query (const char* name, P*& params); - - // Prepared query factory. - // - public: - typedef odb::connection connection_type; - - typedef void query_factory_type (const char* name, connection_type&); - typedef query_factory_type* query_factory_ptr; - typedef details::function_wrapper< - query_factory_type> query_factory_wrapper; - -#ifndef ODB_CXX11 - void - query_factory (const char* name, query_factory_ptr); -#else - template - typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - query_factory (const char* name, F f) - { - query_factory (name, query_factory_wrapper (std::move (f))); - } -#endif - - bool - call_query_factory (const char* name, connection_type&) const; - - private: - void - query_factory (const char* name, query_factory_wrapper); - - // Native database statement execution. - // - public: - unsigned long long - execute (const char* statement); - - unsigned long long - execute (const std::string& statement); - - unsigned long long - execute (const char* statement, std::size_t length); - - // Transactions. - // - public: - virtual transaction_impl* - begin () = 0; - - // Connections. - // - public: - connection_ptr - connection (); - - // SQL statement tracing. - // - public: - typedef odb::tracer tracer_type; - - void - tracer (tracer_type&); - - void - tracer (tracer_type*); - - tracer_type* - tracer () const; - - // Database schema version. - // - public: - typedef odb::schema_version schema_version_type; - typedef odb::schema_version_migration schema_version_migration_type; - - schema_version_type - schema_version (const std::string& schema_name = "") const; - - bool - schema_migration (const std::string& schema_name = "") const; - - // Note that there is code that relies on the returned reference - // being valid until the version is changed or the database instance - // is destroyed. - // - const schema_version_migration_type& - schema_version_migration (const std::string& schema_name = "") const; - - // Set schema version and migration state manually. - // - // Note that the modifier API is not thread-safe. That is, you should - // not modify the schema version while other threads may be accessing - // or modifying the same information. - // - void - schema_version_migration (schema_version_type, - bool migration, - const std::string& schema_name = ""); - - void - schema_version_migration (const schema_version_migration_type&, - const std::string& schema_name = ""); - - // Set default schema version table for all the schema names. The table - // name should already be quoted if necessary. - // - void - schema_version_table (const std::string& table_name); - - // Set schema version table for a specific schema. - // - void - schema_version_table (const std::string& table_name, - const std::string& schema_name); - - // Schema version sequence number. It is incremented every time the - // schema version or migration flag is changed and can be used to - // detect overall version changes. The starting value is 1. - // - unsigned int - schema_version_sequence () const; - - protected: - struct schema_version_info: schema_version_migration_type - { - std::string version_table; - }; - - virtual const schema_version_info& - load_schema_version (const std::string& schema_name) const = 0; - - private: - const schema_version_info& - schema_version_migration_ (const std::string& schema_name) const; - - // Database id. - // - public: - database_id - id () const; - - protected: - database (database_id); - - protected: - virtual connection_type* - connection_ () = 0; - - protected: - template - typename object_traits::id_type - persist_ (T&); - - template - typename object_traits::id_type - persist_ (const typename object_traits::pointer_type&); - - template - void - persist_ (I, I, bool); - - template - void - persist_ (I, I, bool, details::meta::no ptr); - - template - void - persist_ (I, I, bool, details::meta::yes ptr); - - template - typename object_traits::pointer_type - load_ (const typename object_traits::id_type&); - - template - void - load_ (const typename object_traits::id_type&, T&); - - template - void - load_ (T&, section&); - - template - void - reload_ (T&); - - template - typename object_traits::pointer_type - find_ (const typename object_traits::id_type&); - - template - bool - find_ (const typename object_traits::id_type&, T&); - - template - void - update_ (T&); - - template - void - update_ (const typename object_traits::pointer_type&); - - template - void - update_ (I, I, bool); - - template - void - update_ (const T&, const section&); - - template - void - erase_ (const typename object_traits::id_type&); - - template - void - erase_ (T&); - - template - void - erase_ (const typename object_traits::pointer_type&); - - template - void - erase_id_ (I, I, bool); - - template - void - erase_object_ (I, I, bool); - - template - typename result::pointer_type - query_one_ (const Q&); - - template - bool - query_one_ (const Q&, T&); - - template - T - query_value_ (const Q&); - - template ::kind> - struct query_; - - protected: - typedef - std::map - query_factory_map; - - typedef std::map schema_version_map; - - database_id id_; - tracer_type* tracer_; - query_factory_map query_factory_map_; - - details::unique_ptr mutex_; // Dynamic for move support. - mutable schema_version_map schema_version_map_; - std::string schema_version_table_; - unsigned int schema_version_seq_; - }; -} - -#include -#include - -#include - -#endif // ODB_DATABASE_HXX diff --git a/odb/database.ixx b/odb/database.ixx deleted file mode 100644 index c3cf2e2..0000000 --- a/odb/database.ixx +++ /dev/null @@ -1,879 +0,0 @@ -// file : odb/database.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include // std::strlen() -#include // std::move -#include - -#include -#include - -namespace odb -{ - template - struct object_pointer_traits - { - typedef details::meta::no result_type; - typedef T object_type; - static const T& get_ref (const T& x) {return x;} - }; - - template - struct object_pointer_traits - { - typedef details::meta::yes result_type; - typedef T object_type; - static const T& get_ref (const T* p) {return *p;} - }; - - template - struct object_pointer_traits - { - typedef details::meta::yes result_type; - typedef T object_type; - static const T& get_ref (const T* p) {return *p;} - }; - - template class P> - struct object_pointer_traits > - { - typedef details::meta::yes result_type; - typedef T object_type; - static const T& get_ref (const P& p) { - return pointer_traits >::get_ref (p);} - }; - - template class P> - struct object_pointer_traits > - { - typedef details::meta::yes result_type; - typedef T object_type; - static const T& get_ref (const P& p) { - return pointer_traits >::get_ref (p);} - }; - - template class P> - struct object_pointer_traits > - { - typedef details::meta::yes result_type; - typedef T object_type; - static const T& get_ref (const P& p) { - return pointer_traits >::get_ref (p);} - }; - - template class P> - struct object_pointer_traits > - { - typedef details::meta::yes result_type; - typedef T object_type; - static const T& get_ref (const P& p) { - return pointer_traits >::get_ref (p);} - }; - - inline database:: - database (database_id id) - : id_ (id), - tracer_ (0), - mutex_ (new details::mutex), - schema_version_seq_ (1) - { - } - - inline database_id database:: - id () const - { - return id_; - } - - inline database::schema_version_type database:: - schema_version (const std::string& name) const - { - return schema_version_migration (name).version; - } - - inline bool database:: - schema_migration (const std::string& name) const - { - return schema_version_migration (name).migration; - } - - inline void database:: - schema_version_migration (schema_version_type v, - bool m, - const std::string& name) - { - schema_version_migration (schema_version_migration_type (v, m), name); - } - - inline void database:: - schema_version_table (const std::string& tname) - { - schema_version_table_ = tname; - } - - inline void database:: - schema_version_table (const std::string& tname, const std::string& sname) - { - schema_version_map_[sname].version_table = tname; - } - - inline unsigned int database:: - schema_version_sequence () const - { - return schema_version_seq_; - } - - inline connection_ptr database:: - connection () - { - return connection_ptr (connection_ ()); - } - -#ifndef ODB_CXX11 - inline void database:: - query_factory (const char* name, query_factory_ptr f) - { - query_factory (name, query_factory_wrapper (f)); - } -#endif - - inline void database:: - tracer (tracer_type& t) - { - tracer_ = &t; - } - - inline void database:: - tracer (tracer_type* t) - { - tracer_ = t; - } - - inline database::tracer_type* database:: - tracer () const - { - return tracer_; - } - - template - inline typename object_traits::id_type database:: - persist (T& obj) - { - return persist_ (obj); - } - - template - inline typename object_traits::id_type database:: - persist (const T& obj) - { - return persist_ (obj); - } - - template - inline typename object_traits::id_type database:: - persist (T* p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - return persist_ (pobj); - } - - template class P> - inline typename object_traits::id_type database:: - persist (const P& p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - return persist_ (pobj); - } - - template class P> - inline typename object_traits::id_type database:: - persist (const P& p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - return persist_ (pobj); - } - - template class P> - inline typename object_traits::id_type database:: - persist (P& p) - { - const P& cr (p); - return persist (cr); - } - - template class P> - inline typename object_traits::id_type database:: - persist (P& p) - { - const P& cr (p); - return persist (cr); - } - - template - inline typename object_traits::id_type database:: - persist (const typename object_traits::pointer_type& pobj) - { - return persist_ (pobj); - } - - template - inline void database:: - persist (I b, I e, bool cont) - { - persist_ (b, e, cont); - } - - template - inline typename object_traits::pointer_type database:: - load (const typename object_traits::id_type& id) - { - return load_ (id); - } - - template - inline void database:: - load (const typename object_traits::id_type& id, T& obj) - { - return load_ (id, obj); - } - - template - inline void database:: - load (T& obj, section& s) - { - return load_ (obj, s); - } - - template - inline typename object_traits::pointer_type database:: - find (const typename object_traits::id_type& id) - { - return find_ (id); - } - - template - inline bool database:: - find (const typename object_traits::id_type& id, T& obj) - { - return find_ (id, obj); - } - - template - inline void database:: - reload (T& obj) - { - reload_ (obj); - } - - template - inline void database:: - reload (T* p) - { - reload (*p); - } - - template class P> - inline void database:: - reload (const P& p) - { - reload (odb::pointer_traits< P >::get_ref (p)); - } - - template class P> - inline void database:: - reload (const P& p) - { - reload (odb::pointer_traits< P >::get_ref (p)); - } - - template class P> - inline void database:: - reload (P& p) - { - reload (odb::pointer_traits< P >::get_ref (p)); - } - - template class P> - inline void database:: - reload (P& p) - { - reload (odb::pointer_traits< P >::get_ref (p)); - } - - template - inline void database:: - reload (const typename object_traits::pointer_type& pobj) - { - typedef typename object_traits::pointer_type pointer_type; - - reload (odb::pointer_traits::get_ref (pobj)); - } - - template - inline void database:: - update (T& obj) - { - update_ (obj); - } - - template - inline void database:: - update (T* p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - update_ (pobj); - } - - template class P> - inline void database:: - update (const P& p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - update_ (pobj); - } - - template class P> - inline void database:: - update (const P& p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - update_ (pobj); - } - - template class P> - inline void database:: - update (P& p) - { - const P& cr (p); - update (cr); - } - - template class P> - inline void database:: - update (P& p) - { - const P& cr (p); - update (cr); - } - - template - inline void database:: - update (const typename object_traits::pointer_type& pobj) - { - update_ (pobj); - } - - template - inline void database:: - update (I b, I e, bool cont) - { - update_ (b, e, cont); - } - - template - inline void database:: - update (const T& obj, const section& s) - { - update_ (obj, s); - } - - template - inline void database:: - erase (const typename object_traits::id_type& id) - { - return erase_ (id); - } - - template - inline void database:: - erase (T& obj) - { - return erase_ (obj); - } - - template - inline void database:: - erase (T* p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - erase_ (pobj); - } - - template class P> - inline void database:: - erase (const P& p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - erase_ (pobj); - } - - template class P> - inline void database:: - erase (const P& p) - { - typedef typename object_traits::pointer_type object_pointer; - - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const object_pointer& pobj (p); - - erase_ (pobj); - } - - template class P> - inline void database:: - erase (P& p) - { - const P& cr (p); - erase (cr); - } - - template class P> - inline void database:: - erase (P& p) - { - const P& cr (p); - erase (cr); - } - - template - inline void database:: - erase (const typename object_traits::pointer_type& pobj) - { - erase_ (pobj); - } - - template - inline void database:: - erase (I idb, I ide, bool cont) - { - erase_id_ (idb, ide, cont); - } - - template - inline void database:: - erase (I ob, I oe, bool cont) - { - erase_object_ (ob, oe, cont); - } - - template - inline unsigned long long database:: - erase_query () - { - // T is always object_type. - // - return erase_query (odb::query ()); - } - - template - inline unsigned long long database:: - erase_query (const char* q) - { - // T is always object_type. - // - return erase_query (odb::query (q)); - } - - template - inline unsigned long long database:: - erase_query (const std::string& q) - { - // T is always object_type. - // - return erase_query (odb::query (q)); - } - - template - inline unsigned long long database:: - erase_query (const odb::query& q) - { - // T is always object_type. - // - return object_traits_impl::erase_query (*this, q); - } - - template - inline result database:: - query (bool cache) - { - return query (odb::query (), cache); - } - - template - inline result database:: - query (const char* q, bool cache) - { - return query (odb::query (q), cache); - } - - template - inline result database:: - query (const std::string& q, bool cache) - { - return query (odb::query (q), cache); - } - - template - inline typename result::pointer_type database:: - query_one () - { - return query_one (odb::query ()); - } - - template - inline bool database:: - query_one (T& o) - { - return query_one (odb::query (), o); - } - - template - inline T database:: - query_value () - { - return query_value (odb::query ()); - } - - template - inline typename result::pointer_type database:: - query_one (const char* q) - { - return query_one (odb::query (q)); - } - - template - inline bool database:: - query_one (const char* q, T& o) - { - return query_one (odb::query (q), o); - } - - template - inline T database:: - query_value (const char* q) - { - return query_value (odb::query (q)); - } - - template - inline typename result::pointer_type database:: - query_one (const std::string& q) - { - return query_one (odb::query (q)); - } - - template - inline bool database:: - query_one (const std::string& q, T& o) - { - return query_one (odb::query (q), o); - } - - template - inline T database:: - query_value (const std::string& q) - { - return query_value (odb::query (q)); - } - - template - inline bool database:: - query_one (const odb::query& q, T& o) - { - return query_one_ (q, o); - } - - template - inline typename result::pointer_type database:: - query_one (const odb::query& q) - { - return query_one_ (q); - } - - template - inline T database:: - query_value (const odb::query& q) - { - return query_value_ (q); - } - - template - inline prepared_query database:: - prepare_query (const char* n, const char* q) - { - return prepare_query (n, odb::query (q)); - } - - template - inline prepared_query database:: - prepare_query (const char* n, const std::string& q) - { - return prepare_query (n, odb::query (q)); - } - - template - inline prepared_query database:: - prepare_query (const char* n, const odb::query& q) - { - connection_type& c (transaction::current ().connection (*this)); - return c.prepare_query (n, q); - } - - template - inline void database:: - cache_query (const prepared_query& pq) - { - connection_type& c (transaction::current ().connection (*this)); - c.cache_query (pq); - } - -#ifdef ODB_CXX11 - template - inline void database:: - cache_query (const prepared_query& pq, std::unique_ptr

params) - { - connection_type& c (transaction::current ().connection (*this)); - c.cache_query (pq, std::move (params)); - } -#else - template - inline void database:: - cache_query (const prepared_query& pq, std::auto_ptr

params) - { - connection_type& c (transaction::current ().connection (*this)); - c.cache_query (pq, params); - } -#endif - - template - inline prepared_query database:: - lookup_query (const char* name) - { - connection_type& c (transaction::current ().connection (*this)); - return c.lookup_query (name); - } - - template - inline prepared_query database:: - lookup_query (const char* name, P*& params) - { - connection_type& c (transaction::current ().connection (*this)); - return c.lookup_query (name, params); - } - - // Implementations (i.e., the *_() functions). - // - template - inline void database:: - persist_ (I b, I e, bool cont) - { - // Sun CC with non-standard STL does not have iterator_traits. - // -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - typedef typename std::iterator_traits::value_type value_type; -#else - // Assume iterator is just a pointer. - // - typedef typename object_pointer_traits::object_type value_type; -#endif - - typedef object_pointer_traits opt; - - persist_ ( - b, e, cont, typename opt::result_type ()); - } - - template - inline typename object_traits::pointer_type database:: - find_ (const typename object_traits::id_type& id) - { - // T is always object_type. - // - - // Compiler error pointing here? Perhaps the object doesn't have the - // default constructor? - // - return object_traits_impl::find (*this, id); - } - - template - inline bool database:: - find_ (const typename object_traits::id_type& id, T& obj) - { - // T is always object_type. - // - return object_traits_impl::find (*this, id, obj); - } - - template - inline void database:: - update_ (T& obj) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - - // Compiler error pointing here? Perhaps the object is readonly or - // doesn't have an object id? Such objects cannot be updated. - // - object_traits_impl::update (*this, obj); - } - - template - inline void database:: - update_ (const typename object_traits::pointer_type& pobj) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - typedef typename object_traits::pointer_type pointer_type; - - T& obj (pointer_traits::get_ref (pobj)); - - // Compiler error pointing here? Perhaps the object is readonly or - // doesn't have an object id? Such objects cannot be updated. - // - object_traits_impl::update (*this, obj); - } - - template - inline void database:: - erase_ (const typename object_traits::id_type& id) - { - // T is always object_type. - // - object_traits_impl::erase (*this, id); - } - - template - inline void database:: - erase_ (T& obj) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - - object_traits_impl::erase (*this, obj); - } - - template - inline void database:: - erase_ (const typename object_traits::pointer_type& pobj) - { - typedef typename object_traits::pointer_type pointer_type; - - erase_ (pointer_traits::get_ref (pobj)); - } - - template - inline typename result::pointer_type database:: - query_one_ (const Q& q) - { - result r (query_::call (*this, q)); - - // We still have to cache the result since loading the object - // may result in loading of it's related objects and that would - // invalidate the result even for just getting the 'end' status. - // - r.cache (); - - return r.one (); - } - - template - inline bool database:: - query_one_ (const Q& q, T& o) - { - result r (query_::call (*this, q)); - r.cache (); // See above. - return r.one (o); - } - - template - inline T database:: - query_value_ (const Q& q) - { - result r (query_::call (*this, q)); - r.cache (); // See above. - - // Compiler error pointing here? The object must be default-constructible - // in order to use the return-by-value API. - // - T o; - r.value (o); - return o; - } - - // execute() - // - inline unsigned long long database:: - execute (const char* statement) - { - return execute (statement, std::strlen (statement)); - } - - inline unsigned long long database:: - execute (const std::string& statement) - { - return execute (statement.c_str (), statement.size ()); - } -} diff --git a/odb/database.txx b/odb/database.txx deleted file mode 100644 index 5659b6f..0000000 --- a/odb/database.txx +++ /dev/null @@ -1,491 +0,0 @@ -// file : odb/database.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include -#include - -namespace odb -{ - template - result database:: - query (const odb::query& q, bool cache) - { - // T is always object_type. We also don't need to check for transaction - // here; object_traits::query () does this. - // - result r (query_::call (*this, q)); - - if (cache) - r.cache (); - - return r; - } - - // Implementations (i.e., the *_() functions). - // - template - typename object_traits::id_type database:: - persist_ (T& obj) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - typedef object_traits_impl object_traits; - - object_traits::persist (*this, obj); - - typename object_traits::reference_cache_traits::position_type p ( - object_traits::reference_cache_traits::insert ( - *this, reference_cache_type::convert (obj))); - - object_traits::reference_cache_traits::persist (p); - - return object_traits::id (obj); - } - - template - typename object_traits::id_type database:: - persist_ (const typename object_traits::pointer_type& pobj) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - typedef typename object_traits::pointer_type pointer_type; - - typedef object_traits_impl object_traits; - - T& obj (pointer_traits::get_ref (pobj)); - object_traits::persist (*this, obj); - - // Get the canonical object pointer and insert it into object cache. - // - typename object_traits::pointer_cache_traits::position_type p ( - object_traits::pointer_cache_traits::insert ( - *this, pointer_cache_type::convert (pobj))); - - object_traits::pointer_cache_traits::persist (p); - - return object_traits::id (obj); - } - - template ::auto_id> struct persist_type; - template struct persist_type {typedef T type;}; - template struct persist_type {typedef const T type;}; - - template - void database:: - persist_ (I b, I e, bool cont, details::meta::no /*ptr*/) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - typedef object_traits_impl object_traits; - - multiple_exceptions mex (typeid (object_already_persistent)); - try - { - while (b != e && (cont || mex.empty ())) - { - std::size_t n (0); - T* a[object_traits::batch]; // T instead of persist_type for cache. - - for (; b != e && n < object_traits::batch; ++n) - { - // Compiler error pointing here? Perhaps the passed range is - // of const objects? - // - typename persist_type::type* p (&(*b++)); - - a[n] = const_cast (p); - } - - // Compiler error pointing here? Perhaps the object or the - // database does not support bulk operations? - // - object_traits::persist ( - *this, - const_cast::type**> (a), - n, - mex); - - if (mex.fatal ()) - break; - - for (std::size_t i (0); i < n; ++i) - { - if (mex[i] != 0) // Don't cache objects that have failed. - continue; - - mex.current (i); // Set position in case the below code throws. - - typename object_traits::reference_cache_traits::position_type p ( - object_traits::reference_cache_traits::insert ( - *this, reference_cache_type::convert (*a[i]))); - - object_traits::reference_cache_traits::persist (p); - } - - mex.delta (n); - } - } - catch (const odb::exception& ex) - { - mex.insert (ex, true); - } - - if (!mex.empty ()) - { - mex.prepare (); - throw mex; - } - } - - template - struct pointer_copy - { - const P* ref; - P copy; - - void assign (const P& p) {ref = &p;} - template void assign (const P1& p1) - { - // The passed pointer should be the same or implicit-convertible - // to the object pointer. This way we make sure the object pointer - // does not assume ownership of the passed object. - // - const P& p (p1); - - copy = p; - ref = © - } - }; - - template - void database:: - persist_ (I b, I e, bool cont, details::meta::yes /*ptr*/) - { - // T can be const T while object_type will always be T. - // - typedef typename object_traits::object_type object_type; - typedef typename object_traits::pointer_type pointer_type; - - typedef object_traits_impl object_traits; - - multiple_exceptions mex (typeid (object_already_persistent)); - try - { - while (b != e && (cont || mex.empty ())) - { - std::size_t n (0); - typename persist_type::type* a[object_traits::batch]; - pointer_copy p[object_traits::batch]; - - for (; b != e && n < object_traits::batch; ++n) - { - p[n].assign (*b++); - a[n] = &pointer_traits::get_ref (*p[n].ref); - } - - // Compiler error pointing here? Perhaps the object or the - // database does not support bulk operations? - // - object_traits::persist (*this, a, n, mex); - - if (mex.fatal ()) - break; - - for (std::size_t i (0); i < n; ++i) - { - if (mex[i] != 0) // Don't cache objects that have failed. - continue; - - mex.current (i); // Set position in case the below code throws. - - // Get the canonical object pointer and insert it into object cache. - // - typename object_traits::pointer_cache_traits::position_type pos ( - object_traits::pointer_cache_traits::insert ( - *this, pointer_cache_type::convert (*p[i].ref))); - - object_traits::pointer_cache_traits::persist (pos); - } - - mex.delta (n); - } - } - catch (const odb::exception& ex) - { - mex.insert (ex, true); - } - - if (!mex.empty ()) - { - mex.prepare (); - throw mex; - } - } - - template - typename object_traits::pointer_type database:: - load_ (const typename object_traits::id_type& id) - { - // T is always object_type. - // - typedef typename object_traits::pointer_type pointer_type; - - pointer_type r (find_ (id)); - - if (pointer_traits::null_ptr (r)) - throw object_not_persistent (); - - return r; - } - - template - void database:: - load_ (const typename object_traits::id_type& id, T& obj) - { - if (!find_ (id, obj)) - throw object_not_persistent (); - } - - template - void database:: - load_ (T& obj, section& s) - { - connection_type& c (transaction::current ().connection (*this)); - - // T is always object_type. - // - if (object_traits_impl::load (c, obj, s)) - s.reset (true, false); // Loaded, unchanged. - else - throw section_not_in_object (); - } - - template - void database:: - reload_ (T& obj) - { - // T should be object_type (cannot be const). We also don't need to - // check for transaction here; object_traits::reload () does this. - // - if (!object_traits_impl::reload (*this, obj)) - throw object_not_persistent (); - } - - template - void database:: - update_ (I b, I e, bool cont) - { - // Sun CC with non-standard STL does not have iterator_traits. - // -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - typedef typename std::iterator_traits::value_type value_type; -#else - // Assume iterator is just a pointer. - // - typedef typename object_pointer_traits::object_type value_type; -#endif - - // object_pointer_traits::object_type can be const. - // - typedef object_pointer_traits opt; - - typedef - typename object_traits::object_type - object_type; - - typedef object_traits_impl object_traits; - - multiple_exceptions mex ( - object_traits::managed_optimistic_column_count == 0 - ? typeid (object_not_persistent) - : typeid (object_changed)); - - try - { - while (b != e && (cont || mex.empty ())) - { - std::size_t n (0); - const object_type* a[object_traits::batch]; - - for (; b != e && n < object_traits::batch; ++n) - a[n] = &opt::get_ref (*b++); - - // Compiler error pointing here? Perhaps the object or the - // database does not support bulk operations? - // - object_traits::update (*this, a, n, mex); - - if (mex.fatal ()) - break; - - mex.delta (n); - } - } - catch (const odb::exception& ex) - { - mex.insert (ex, true); - } - - if (!mex.empty ()) - { - mex.prepare (); - throw mex; - } - } - - template - void database:: - update_ (const T& obj, const section& s) - { - if (!s.loaded ()) - throw section_not_loaded (); - - transaction& t (transaction::current ()); - - // T is always object_type. - // - if (object_traits_impl::update (t.connection (*this), obj, s)) - { - if (s.changed ()) - s.reset (true, false, &t); // Clear the change flag. - } - else - throw section_not_in_object (); - } - - template - void database:: - erase_id_ (I b, I e, bool cont) - { - // T is explicitly specified by the caller, so assume it is object type. - // - typedef T object_type; - typedef object_traits_impl object_traits; - typedef typename object_traits::id_type id_type; - - multiple_exceptions mex (typeid (object_not_persistent)); - try - { - while (b != e && (cont || mex.empty ())) - { - std::size_t n (0); - const id_type* a[object_traits::batch]; - - for (; b != e && n < object_traits::batch; ++n) - // Compiler error pointing here? Perhaps the object id type - // and the range element type don't match? - // - a[n] = &(*b++); - - // Compiler error pointing here? Perhaps the object or the - // database does not support bulk operations? - // - object_traits::erase (*this, a, n, mex); - - if (mex.fatal ()) - break; - - mex.delta (n); - } - } - catch (const odb::exception& ex) - { - mex.insert (ex, true); - } - - if (!mex.empty ()) - { - mex.prepare (); - throw mex; - } - } - - template - void database:: - erase_object_ (I b, I e, bool cont) - { - // Sun CC with non-standard STL does not have iterator_traits. - // -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - typedef typename std::iterator_traits::value_type value_type; -#else - // Assume iterator is just a pointer. - // - typedef typename object_pointer_traits::object_type value_type; -#endif - - // object_pointer_traits::object_type can be const. - // - typedef object_pointer_traits opt; - - typedef - typename object_traits::object_type - object_type; - - typedef object_traits_impl object_traits; - - multiple_exceptions mex ( - object_traits::managed_optimistic_column_count == 0 - ? typeid (object_not_persistent) - : typeid (object_changed)); - - try - { - while (b != e && (cont || mex.empty ())) - { - std::size_t n (0); - const object_type* a[object_traits::batch]; - - for (; b != e && n < object_traits::batch; ++n) - a[n] = &opt::get_ref (*b++); - - // Compiler error pointing here? Perhaps the object or the - // database does not support bulk operations? - // - object_traits::erase (*this, a, n, mex); - - if (mex.fatal ()) - break; - - mex.delta (n); - } - } - catch (const odb::exception& ex) - { - mex.insert (ex, true); - } - - if (!mex.empty ()) - { - mex.prepare (); - throw mex; - } - } - - template - struct database::query_ - { - template - static result - call (database& db, const Q& q) - { - return object_traits_impl::query (db, q); - } - }; - - template - struct database::query_ - { - template - static result - call (database& db, const Q& q) - { - return view_traits_impl::query (db, q); - } - }; -} diff --git a/odb/details/buffer.cxx b/odb/details/buffer.cxx deleted file mode 100644 index 595329e..0000000 --- a/odb/details/buffer.cxx +++ /dev/null @@ -1,35 +0,0 @@ -// file : odb/details/buffer.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include // std::memcpy - -#include - -using namespace std; - -namespace odb -{ - namespace details - { - void basic_buffer_base:: - capacity (size_t c, size_t data_size) - { - if (c > capacity_) - { - size_t n (capacity_ * 2 > c ? capacity_ * 2 : c); - void* d (operator new (n)); - - if (data_ != 0) - { - if (data_size != 0) - memcpy (d, data_, data_size); - - operator delete (data_); - } - - data_ = d; - capacity_ = n; - } - } - } -} diff --git a/odb/details/buffer.hxx b/odb/details/buffer.hxx deleted file mode 100644 index 558be9b..0000000 --- a/odb/details/buffer.hxx +++ /dev/null @@ -1,92 +0,0 @@ -// file : odb/details/buffer.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_BUFFER_DETAILS_HXX -#define ODB_BUFFER_DETAILS_HXX - -#include - -#include -#include // std::size_t - -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT basic_buffer_base - { - public: - ~basic_buffer_base () - { - if (data_ != 0) - operator delete (data_); - } - - basic_buffer_base (std::size_t capacity) - : capacity_ (capacity) - { - data_ = capacity_ == 0 ? 0 : operator new (capacity_); - } - - std::size_t - capacity () const - { - return capacity_; - } - - void - capacity (std::size_t, std::size_t data_size = 0); - - protected: - void* data_; - std::size_t capacity_; - }; - - template - class basic_buffer: public basic_buffer_base - { - public: - basic_buffer (std::size_t capacity = 256) - : basic_buffer_base (capacity) - { - } - - T* - data () - { - return static_cast (data_); - } - - const T* - data () const - { - return static_cast (data_); - } - - // Note that strictly speaking the return type should be void* const* - // but that would make using this function too awkward since we often - // store the result as void*. - // - void** - data_ptr () - { - return &data_; - } - - const void* const* - data_ptr () const - { - return &data_; - } - }; - - typedef basic_buffer buffer; - typedef basic_buffer ubuffer; - } -} - -#include - -#endif // ODB_BUFFER_DETAILS_HXX diff --git a/odb/details/build2/config-stub.h b/odb/details/build2/config-stub.h deleted file mode 100644 index 83ea927..0000000 --- a/odb/details/build2/config-stub.h +++ /dev/null @@ -1,5 +0,0 @@ -/* file : odb/details/build2/config-stub.h - * license : GNU GPL v2; see accompanying LICENSE file - */ - -#include diff --git a/odb/details/build2/config-vc-stub.h b/odb/details/build2/config-vc-stub.h deleted file mode 100644 index e440e70..0000000 --- a/odb/details/build2/config-vc-stub.h +++ /dev/null @@ -1,5 +0,0 @@ -/* file : odb/details/build2/config-vc-stub.h - * license : GNU GPL v2; see accompanying LICENSE file - */ - -#include diff --git a/odb/details/build2/config-vc.h b/odb/details/build2/config-vc.h deleted file mode 100644 index 77ce106..0000000 --- a/odb/details/build2/config-vc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* file : odb/details/build2/config-vc.h - * license : GNU GPL v2; see accompanying LICENSE file - */ - -/* Configuration file for Windows/VC++ for the build2 build. */ - -#ifndef ODB_DETAILS_CONFIG_VC_H -#define ODB_DETAILS_CONFIG_VC_H - -/* Define LIBODB_BUILD2 for the installed case. */ -#ifndef LIBODB_BUILD2 -# define LIBODB_BUILD2 -#endif - -#ifndef ODB_THREADS_NONE -# if _MSC_VER >= 1900 -# define ODB_THREADS_CXX11 -# else -# error Unsupoprted MSVC version (no thread_local) -# endif -#endif - -#endif /* ODB_DETAILS_CONFIG_VC_H */ diff --git a/odb/details/build2/config.h b/odb/details/build2/config.h deleted file mode 100644 index ba434f4..0000000 --- a/odb/details/build2/config.h +++ /dev/null @@ -1,19 +0,0 @@ -/* file : odb/details/build2/config.h - * license : GNU GPL v2; see accompanying LICENSE file - */ - -/* Static configuration file for the build2 build. */ - -#ifndef ODB_DETAILS_CONFIG_H -#define ODB_DETAILS_CONFIG_H - -/* Define LIBODB_BUILD2 for the installed case. */ -#ifndef LIBODB_BUILD2 -# define LIBODB_BUILD2 -#endif - -#ifndef ODB_THREADS_NONE -# define ODB_THREADS_CXX11 -#endif - -#endif /* ODB_DETAILS_CONFIG_H */ diff --git a/odb/details/c-string.hxx b/odb/details/c-string.hxx deleted file mode 100644 index 6ab1adc..0000000 --- a/odb/details/c-string.hxx +++ /dev/null @@ -1,28 +0,0 @@ -// file : odb/details/c-string.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_C_STRING_HXX -#define ODB_DETAILS_C_STRING_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - struct c_string_comparator - { - bool - operator() (const char* x, const char* y) const - { - return std::strcmp (x, y) < 0; - } - }; - } -} - -#include - -#endif // ODB_DETAILS_C_STRING_HXX diff --git a/odb/details/condition.cxx b/odb/details/condition.cxx deleted file mode 100644 index 2c4cbdb..0000000 --- a/odb/details/condition.cxx +++ /dev/null @@ -1,13 +0,0 @@ -// file : odb/details/condition.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - // This otherwise unnecessary file is here to allow instantiation - // of inline functions for exporting. - } -} diff --git a/odb/details/condition.hxx b/odb/details/condition.hxx deleted file mode 100644 index 10b6b4a..0000000 --- a/odb/details/condition.hxx +++ /dev/null @@ -1,68 +0,0 @@ -// file : odb/details/condition.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_CONDITION_HXX -#define ODB_DETAILS_CONDITION_HXX - -#include - -#include - -#ifdef ODB_THREADS_NONE - -namespace odb -{ - namespace details - { - class mutex; - class lock; - - class condition - { - public: - condition (mutex&) {} - - void - signal () {} - - void - wait (lock&) {} - - private: - condition (const condition&); - condition& operator= (const condition&); - }; - } -} - -#elif defined(ODB_THREADS_CXX11) -# include -# include -# include - -namespace odb -{ - namespace details - { - class condition: public std::condition_variable - { - public: - condition (mutex&) {} - - void - signal () {notify_one ();} - }; - } -} - -#elif defined(ODB_THREADS_POSIX) -#include -#elif defined(ODB_THREADS_WIN32) -#include -#else -# error unknown threading model -#endif - -#include - -#endif // ODB_DETAILS_CONDITION_HXX diff --git a/odb/details/config-vc.h b/odb/details/config-vc.h deleted file mode 100644 index b1e38b2..0000000 --- a/odb/details/config-vc.h +++ /dev/null @@ -1,13 +0,0 @@ -/* file : odb/details/config-vc.h - * license : GNU GPL v2; see accompanying LICENSE file - */ - -/* Configuration file for Windows/VC++. */ - -#ifndef ODB_DETAILS_CONFIG_VC_H -#define ODB_DETAILS_CONFIG_VC_H - -#define ODB_THREADS_WIN32 -#define ODB_THREADS_TLS_DECLSPEC - -#endif /* ODB_DETAILS_CONFIG_VC_H */ diff --git a/odb/details/config.h.in b/odb/details/config.h.in deleted file mode 100644 index 2396606..0000000 --- a/odb/details/config.h.in +++ /dev/null @@ -1,18 +0,0 @@ -/* file : odb/details/config.h.in - * license : GNU GPL v2; see accompanying LICENSE file - */ - -/* This file is automatically processed by configure. */ - -#ifndef ODB_DETAILS_CONFIG_H -#define ODB_DETAILS_CONFIG_H - -#undef ODB_THREADS_NONE -#undef ODB_THREADS_POSIX -#undef ODB_THREADS_WIN32 -#undef ODB_THREADS_TLS_KEYWORD -#undef ODB_THREADS_TLS_DECLSPEC - -#undef LIBODB_STATIC_LIB - -#endif /* ODB_DETAILS_CONFIG_H */ diff --git a/odb/details/config.hxx b/odb/details/config.hxx deleted file mode 100644 index a42dd69..0000000 --- a/odb/details/config.hxx +++ /dev/null @@ -1,80 +0,0 @@ -// file : odb/details/config.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_CONFIG_HXX -#define ODB_DETAILS_CONFIG_HXX - -// no pre - -// C++11 support. -// -#ifdef _MSC_VER -# if _MSC_VER >= 1600 // VC++10 and later have C++11 always enabled. -# define ODB_CXX11 -# define ODB_CXX11_NULLPTR -# if _MSC_VER >= 1700 -# define ODB_CXX11_ENUM -# if _MSC_VER >= 1800 -# define ODB_CXX11_DELETED_FUNCTION -# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR -# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT -# define ODB_CXX11_VARIADIC_TEMPLATE -# define ODB_CXX11_INITIALIZER_LIST -# if _MSC_VER >= 1900 -# define ODB_CXX11_NOEXCEPT -# endif -# endif -# endif -# endif -#else -# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L -# define ODB_CXX11 -# ifdef __clang__ // Pretends to be a really old __GNUC__ on some platforms. -# define ODB_CXX11_NULLPTR -# define ODB_CXX11_NOEXCEPT -# elif defined(__GNUC__) -# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 -# define ODB_CXX11_NULLPTR -# define ODB_CXX11_NOEXCEPT -# endif -# else -# define ODB_CXX11_NULLPTR -# define ODB_CXX11_NOEXCEPT -# endif -# define ODB_CXX11_DELETED_FUNCTION -# define ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR -# define ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT -# define ODB_CXX11_VARIADIC_TEMPLATE -# define ODB_CXX11_INITIALIZER_LIST -# define ODB_CXX11_ENUM // GCC 4.4 (forward -- 4.6), Clang 2.9 (3.1). -# endif -#endif - -#ifdef ODB_CXX11_NOEXCEPT -# define ODB_NOTHROW_NOEXCEPT noexcept -#else -# define ODB_NOTHROW_NOEXCEPT throw() -#endif - -// Once we drop support for C++98, we can probably get rid of config.h except -// for the autotools case by fixing ODB_THREADS_CXX11 (and perhaps supporting -// the ODB_THREADS_NONE case via a "global" (command line) define). -// -#ifdef ODB_COMPILER -# define ODB_THREADS_NONE -# define LIBODB_STATIC_LIB -#elif defined(LIBODB_BUILD2) -# if defined(_MSC_VER) -# include -# else -# include -# endif -#elif defined(_MSC_VER) -# include -#else -# include -#endif - -// no post - -#endif // ODB_DETAILS_CONFIG_HXX diff --git a/odb/details/exception.hxx b/odb/details/exception.hxx deleted file mode 100644 index ab838e1..0000000 --- a/odb/details/exception.hxx +++ /dev/null @@ -1,21 +0,0 @@ -// file : odb/details/exception.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_EXCEPTION_HXX -#define ODB_DETAILS_EXCEPTION_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - struct exception: odb::exception {}; - } -} - -#include - -#endif // ODB_DETAILS_EXCEPTION_HXX diff --git a/odb/details/export.hxx b/odb/details/export.hxx deleted file mode 100644 index 80fe342..0000000 --- a/odb/details/export.hxx +++ /dev/null @@ -1,78 +0,0 @@ -// file : odb/details/export.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_EXPORT_HXX -#define ODB_DETAILS_EXPORT_HXX - -#include - -#include - -// Normally we don't export class templates (but do complete specializations), -// inline functions, and classes with only inline member functions. Exporting -// classes that inherit from non-exported/imported bases (e.g., std::string) -// will end up badly. The only known workarounds are to not inherit or to not -// export. Also, MinGW GCC doesn't like seeing non-exported function being -// used before their inline definition. The workaround is to reorder code. In -// the end it's all trial and error. - -#ifdef LIBODB_BUILD2 - -#if defined(LIBODB_STATIC) // Using static. -# define LIBODB_EXPORT -#elif defined(LIBODB_STATIC_BUILD) // Building static. -# define LIBODB_EXPORT -#elif defined(LIBODB_SHARED) // Using shared. -# ifdef _WIN32 -# define LIBODB_EXPORT __declspec(dllimport) -# else -# define LIBODB_EXPORT -# endif -#elif defined(LIBODB_SHARED_BUILD) // Building shared. -# ifdef _WIN32 -# define LIBODB_EXPORT __declspec(dllexport) -# else -# define LIBODB_EXPORT -# endif -#else -// If none of the above macros are defined, then we assume we are being used -// by some third-party build system that cannot/doesn't signal the library -// type. Note that this fallback works for both static and shared but in case -// of shared will be sub-optimal compared to having dllimport. -// -# define LIBODB_EXPORT // Using static or shared. -#endif - -#else // LIBODB_BUILD2 - -#ifdef LIBODB_STATIC_LIB -# define LIBODB_EXPORT -#else -# ifdef _WIN32 -# ifdef _MSC_VER -# ifdef LIBODB_DYNAMIC_LIB -# define LIBODB_EXPORT __declspec(dllexport) -# else -# define LIBODB_EXPORT __declspec(dllimport) -# endif -# else -# ifdef LIBODB_DYNAMIC_LIB -# ifdef DLL_EXPORT -# define LIBODB_EXPORT __declspec(dllexport) -# else -# define LIBODB_EXPORT -# endif -# else -# define LIBODB_EXPORT __declspec(dllimport) -# endif -# endif -# else -# define LIBODB_EXPORT -# endif -#endif - -#endif // LIBODB_BUILD2 - -#include - -#endif // ODB_DETAILS_EXPORT_HXX diff --git a/odb/details/function-wrapper.hxx b/odb/details/function-wrapper.hxx deleted file mode 100644 index 418a625..0000000 --- a/odb/details/function-wrapper.hxx +++ /dev/null @@ -1,90 +0,0 @@ -// file : odb/details/function-wrapper.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_FUNCTION_WRAPPER_HXX -#define ODB_DETAILS_FUNCTION_WRAPPER_HXX - -#include - -#include // ODB_CXX11 - -#ifdef ODB_CXX11 -# include // std::function -# include // std::enable_if, std::is_convertible -#endif - -namespace odb -{ - namespace details - { - // Low-level 'callable object' wrapper similar to std::function but - // that works in both C++98 and 11. In particular, the call site can - // be compiled in C++98 and the registration site in C++11 and it - // will work. - // - template - struct function_wrapper - { - ~function_wrapper (); - - explicit - function_wrapper (F* = 0); - -#ifdef ODB_CXX11 - typedef typename std::function std_function_type; - - // This overload accepts lambdas and std::functions, but when the - // argument is convertible to F*, then we disable it in favor of the - // other overload (above), which is more efficient. - // - // Subtlety alert: if you're thinking of changing this to accept a - // std::function argument, stop. That creates an overload ambiguity - // when the actual parameter is a lambda, which is convertible to either - // std::function or F*. - // - template - function_wrapper(F1, - typename std::enable_if< - !std::is_convertible::value>::type* = 0); -#endif - - // Destructive copy construction and assignment (aka move). These - // should really only be called by containers when they need to - // reallocate the underlying buffer and move the elements. - // - function_wrapper (const function_wrapper&); - function_wrapper& - operator= (const function_wrapper&); - - void swap (function_wrapper&); - - // Cleanly cast to an incompatible function type. - // - template R - cast () const; - - // Conversion to bool. - // - public: - typedef void (function_wrapper::*bool_convertible) (); - void true_value () {} - - operator bool_convertible () const - { - return function != 0 ? &function_wrapper::true_value : 0; - } - - public: - F* function; - void (*deleter) (const void*); - const void* std_function; - }; - } -} - -#include -#include - -#include - -#endif // ODB_DETAILS_FUNCTION_WRAPPER_HXX diff --git a/odb/details/function-wrapper.ixx b/odb/details/function-wrapper.ixx deleted file mode 100644 index 5b83b96..0000000 --- a/odb/details/function-wrapper.ixx +++ /dev/null @@ -1,49 +0,0 @@ -// file : odb/details/function-wrapper.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace details - { - template - inline function_wrapper:: - ~function_wrapper () - { - if (deleter != 0) - deleter (std_function); - } - - template - inline function_wrapper:: - function_wrapper (F* f) - : function (f), deleter (0), std_function (0) - { - } - - template - inline function_wrapper:: - function_wrapper (const function_wrapper& x) - : function (0), deleter (0), std_function (0) - { - swap (const_cast&> (x)); - } - - template - inline function_wrapper& function_wrapper:: - operator= (const function_wrapper& x) - { - swap (const_cast&> (x)); - return *this; - } - - template - template - inline R function_wrapper:: - cast () const - { - union { F* f; R r; } r; - r.f = function; - return r.r; - } - } -} diff --git a/odb/details/function-wrapper.txx b/odb/details/function-wrapper.txx deleted file mode 100644 index db73e8d..0000000 --- a/odb/details/function-wrapper.txx +++ /dev/null @@ -1,89 +0,0 @@ -// file : odb/details/function-wrapper.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include // std::swap, std::move - -namespace odb -{ - namespace details - { -#ifdef ODB_CXX11 - template - struct caller_impl; - -#ifdef ODB_CXX11_VARIADIC_TEMPLATE - template - struct caller_impl - { - static R - function (const void* f, A... a) - { - return (*static_cast*> (f)) (a...); - } - }; -#else - template - struct caller_impl - { - static R - function (const void* f, A1 a1) - { - return (*static_cast*> (f)) (a1); - } - }; - - template - struct caller_impl - { - static R - function (const void* f, A1 a1, A2 a2) - { - return (*static_cast*> (f)) (a1, a2); - } - }; -#endif - - template - void - deleter_impl (const void* f) - { - delete static_cast*> (f); - } - - template - template - function_wrapper:: - function_wrapper ( - F1 f, - typename std::enable_if::value>::type*) - { - std_function_type sf (std::move (f)); - - if (F* const* const f = sf.template target ()) - { - function = *f; - deleter = 0; - std_function = 0; - } - else - { - function_wrapper::function)> fw ( - &caller_impl::function); - - function = fw.template cast (); - deleter = &deleter_impl; - std_function = new std_function_type (std::move (sf)); - } - } -#endif - - template - void function_wrapper:: - swap (function_wrapper& x) - { - std::swap (function, x.function); - std::swap (deleter, x.deleter); - std::swap (std_function, x.std_function); - } - } -} diff --git a/odb/details/lock.cxx b/odb/details/lock.cxx deleted file mode 100644 index f474bf5..0000000 --- a/odb/details/lock.cxx +++ /dev/null @@ -1,13 +0,0 @@ -// file : odb/details/lock.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - // This otherwise unnecessary file is here to allow instantiation - // of inline functions for exporting. - } -} diff --git a/odb/details/lock.hxx b/odb/details/lock.hxx deleted file mode 100644 index 0c54f03..0000000 --- a/odb/details/lock.hxx +++ /dev/null @@ -1,59 +0,0 @@ -// file : odb/details/lock.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_LOCK_HXX -#define ODB_DETAILS_LOCK_HXX - -#include - -#include - -#ifdef ODB_THREADS_CXX11 -# include -namespace odb -{ - namespace details - { - using lock = std::unique_lock; - } -} -#else -namespace odb -{ - namespace details - { - class lock - { - public: - lock (mutex& m) - : mutex_ (&m) - { - mutex_->lock (); - } - - ~lock () - { - if (mutex_ != 0) - mutex_->unlock (); - } - - void - unlock () - { - if (mutex_ != 0) - { - mutex_->unlock (); - mutex_ = 0; - } - } - - private: - mutex* mutex_; - }; - } -} -#endif - -#include - -#endif // ODB_DETAILS_LOCK_HXX diff --git a/odb/details/meta/answer.hxx b/odb/details/meta/answer.hxx deleted file mode 100644 index f15dc43..0000000 --- a/odb/details/meta/answer.hxx +++ /dev/null @@ -1,30 +0,0 @@ -// file : odb/details/meta/answer.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_ANSWER_HXX -#define ODB_DETAILS_META_ANSWER_HXX - -#include - -namespace odb -{ - namespace details - { - namespace meta - { - struct yes - { - char filling; - }; - - struct no - { - char filling[2]; - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_ANSWER_HXX diff --git a/odb/details/meta/class-p.hxx b/odb/details/meta/class-p.hxx deleted file mode 100644 index bddb452..0000000 --- a/odb/details/meta/class-p.hxx +++ /dev/null @@ -1,34 +0,0 @@ -// file : odb/details/meta/class-p.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_CLASS_HXX -#define ODB_DETAILS_META_CLASS_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - namespace meta - { - // g++ cannot have these inside class_p. - // - template no class_p_test (...); - template yes class_p_test (void (X::*) ()); - - template - struct class_p - { - static const bool result = - sizeof (class_p_test (0)) == sizeof (yes); - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_CLASS_HXX diff --git a/odb/details/meta/polymorphic-p.hxx b/odb/details/meta/polymorphic-p.hxx deleted file mode 100644 index 10fef6a..0000000 --- a/odb/details/meta/polymorphic-p.hxx +++ /dev/null @@ -1,57 +0,0 @@ -// file : odb/details/meta/polymorphic-p.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_POLYMORPHIC_HXX -#define ODB_DETAILS_META_POLYMORPHIC_HXX - -#include - -#include // ODB_NOTHROW_NOEXCEPT -#include -#include - -namespace odb -{ - namespace details - { - namespace meta - { - template - struct polymorphic_p - { - typedef typename remove_const_volatile::result X; - - template - struct impl - { - static const bool result = false; - }; - - template - struct impl - { - struct t1: Y - { - t1 (); - }; - - struct t2: Y - { - t2 (); - - virtual - ~t2 () ODB_NOTHROW_NOEXCEPT; - }; - - static const bool result = sizeof (t1) == sizeof (t2); - }; - - static const bool result = impl::result>::result; - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_POLYMORPHIC_HXX diff --git a/odb/details/meta/remove-const-volatile.hxx b/odb/details/meta/remove-const-volatile.hxx deleted file mode 100644 index 910ec35..0000000 --- a/odb/details/meta/remove-const-volatile.hxx +++ /dev/null @@ -1,31 +0,0 @@ -// file : odb/details/meta/remove-const-volatile.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_REMOVE_CONST_VOLATILE_HXX -#define ODB_DETAILS_META_REMOVE_CONST_VOLATILE_HXX - -#include - -#include -#include - -namespace odb -{ - namespace details - { - namespace meta - { - template - struct remove_const_volatile - { - typedef - typename remove_volatile::result>::result - result; - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_REMOVE_CONST_VOLATILE_HXX diff --git a/odb/details/meta/remove-const.hxx b/odb/details/meta/remove-const.hxx deleted file mode 100644 index 4a92ed3..0000000 --- a/odb/details/meta/remove-const.hxx +++ /dev/null @@ -1,32 +0,0 @@ -// file : odb/details/meta/remove-const.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_REMOVE_CONST_HXX -#define ODB_DETAILS_META_REMOVE_CONST_HXX - -#include - -namespace odb -{ - namespace details - { - namespace meta - { - template - struct remove_const - { - typedef X result; - }; - - template - struct remove_const - { - typedef X result; - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_REMOVE_CONST_HXX diff --git a/odb/details/meta/remove-pointer.hxx b/odb/details/meta/remove-pointer.hxx deleted file mode 100644 index 9963fd7..0000000 --- a/odb/details/meta/remove-pointer.hxx +++ /dev/null @@ -1,32 +0,0 @@ -// file : odb/details/meta/remove-pointer.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_REMOVE_POINTER_HXX -#define ODB_DETAILS_META_REMOVE_POINTER_HXX - -#include - -namespace odb -{ - namespace details - { - namespace meta - { - template - struct remove_pointer - { - typedef X result; - }; - - template - struct remove_pointer - { - typedef X result; - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_REMOVE_POINTER_HXX diff --git a/odb/details/meta/remove-volatile.hxx b/odb/details/meta/remove-volatile.hxx deleted file mode 100644 index 877e532..0000000 --- a/odb/details/meta/remove-volatile.hxx +++ /dev/null @@ -1,32 +0,0 @@ -// file : odb/details/meta/remove-volatile.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_REMOVE_VOLATILE_HXX -#define ODB_DETAILS_META_REMOVE_VOLATILE_HXX - -#include - -namespace odb -{ - namespace details - { - namespace meta - { - template - struct remove_volatile - { - typedef X result; - }; - - template - struct remove_volatile - { - typedef X result; - }; - } - } -} - -#include - -#endif // ODB_DETAILS_META_REMOVE_VOLATILE_HXX diff --git a/odb/details/meta/static-assert.hxx b/odb/details/meta/static-assert.hxx deleted file mode 100644 index a2cc81b..0000000 --- a/odb/details/meta/static-assert.hxx +++ /dev/null @@ -1,32 +0,0 @@ -// file : odb/details/meta/static-assert.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_META_STATIC_ASSERT_HXX -#define ODB_DETAILS_META_STATIC_ASSERT_HXX - -#include - -#include // ODB_CXX11 - -#ifndef ODB_CXX11 - -namespace odb -{ - namespace details - { - namespace meta - { - template - struct static_assert_test; - - template <> - struct static_assert_test {}; - } - } -} - -#endif - -#include - -#endif // ODB_DETAILS_META_STATIC_ASSERT_HXX diff --git a/odb/details/mutex.cxx b/odb/details/mutex.cxx deleted file mode 100644 index df367d8..0000000 --- a/odb/details/mutex.cxx +++ /dev/null @@ -1,13 +0,0 @@ -// file : odb/details/mutex.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - // This otherwise unnecessary file is here to allow instantiation - // of inline functions for exporting. - } -} diff --git a/odb/details/mutex.hxx b/odb/details/mutex.hxx deleted file mode 100644 index df12013..0000000 --- a/odb/details/mutex.hxx +++ /dev/null @@ -1,53 +0,0 @@ -// file : odb/details/mutex.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_MUTEX_HXX -#define ODB_DETAILS_MUTEX_HXX - -#include - -#include - -#ifdef ODB_THREADS_NONE - -namespace odb -{ - namespace details - { - class mutex - { - public: - mutex () {} - - void - lock () {} - - void - unlock () {} - - private: - mutex (const mutex&); - mutex& operator= (const mutex&); - }; - } -} -#elif defined(ODB_THREADS_CXX11) -# include -namespace odb -{ - namespace details - { - using std::mutex; - } -} -#elif defined(ODB_THREADS_POSIX) -#include -#elif defined(ODB_THREADS_WIN32) -#include -#else -# error unknown threading model -#endif - -#include - -#endif // ODB_DETAILS_MUTEX_HXX diff --git a/odb/details/posix/condition.hxx b/odb/details/posix/condition.hxx deleted file mode 100644 index 4f7c42a..0000000 --- a/odb/details/posix/condition.hxx +++ /dev/null @@ -1,47 +0,0 @@ -// file : odb/details/posix/condition.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_POSIX_CONDITION_HXX -#define ODB_DETAILS_POSIX_CONDITION_HXX - -#include - -#include - -#include -#include - -namespace odb -{ - namespace details - { - class lock; - - class LIBODB_EXPORT condition - { - public: - ~condition (); - condition (mutex&); - - void - signal (); - - void - wait (lock&); - - private: - condition (const condition&); - condition& operator= (const condition&); - - private: - mutex& mutex_; - pthread_cond_t cond_; - }; - } -} - -#include - -#include - -#endif // ODB_DETAILS_POSIX_CONDITION_HXX diff --git a/odb/details/posix/condition.ixx b/odb/details/posix/condition.ixx deleted file mode 100644 index 9b68d9f..0000000 --- a/odb/details/posix/condition.ixx +++ /dev/null @@ -1,38 +0,0 @@ -// file : odb/details/posix/condition.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - inline condition:: - ~condition () - { - pthread_cond_destroy (&cond_); - } - - inline condition:: - condition (mutex& mutex) - : mutex_ (mutex) - { - if (int e = pthread_cond_init (&cond_, 0)) - throw posix_exception (e); - } - - inline void condition:: - signal () - { - if (int e = pthread_cond_signal (&cond_)) - throw posix_exception (e); - } - - inline void condition:: - wait (lock&) - { - if (int e = pthread_cond_wait (&cond_, &mutex_.mutex_)) - throw posix_exception (e); - } - } -} diff --git a/odb/details/posix/exceptions.cxx b/odb/details/posix/exceptions.cxx deleted file mode 100644 index c346655..0000000 --- a/odb/details/posix/exceptions.cxx +++ /dev/null @@ -1,22 +0,0 @@ -// file : odb/details/posix/exceptions.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - const char* posix_exception:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "POSIX API error"; - } - - posix_exception* posix_exception:: - clone () const - { - return new posix_exception (*this); - } - } -} diff --git a/odb/details/posix/exceptions.hxx b/odb/details/posix/exceptions.hxx deleted file mode 100644 index aff33b6..0000000 --- a/odb/details/posix/exceptions.hxx +++ /dev/null @@ -1,38 +0,0 @@ -// file : odb/details/posix/exceptions.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_POSIX_EXCEPTIONS_HXX -#define ODB_DETAILS_POSIX_EXCEPTIONS_HXX - -#include - -#include // ODB_NOTHROW_NOEXCEPT -#include -#include - -namespace odb -{ - namespace details - { - struct LIBODB_EXPORT posix_exception: details::exception - { - posix_exception (int code) : code_ (code) {} - - int - code () const {return code_;} - - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual posix_exception* - clone () const; - - private: - int code_; - }; - } -} - -#include - -#endif // ODB_DETAILS_POSIX_EXCEPTIONS_HXX diff --git a/odb/details/posix/mutex.hxx b/odb/details/posix/mutex.hxx deleted file mode 100644 index 0cb94db..0000000 --- a/odb/details/posix/mutex.hxx +++ /dev/null @@ -1,44 +0,0 @@ -// file : odb/details/posix/mutex.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_POSIX_MUTEX_HXX -#define ODB_DETAILS_POSIX_MUTEX_HXX - -#include - -#include - -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT mutex - { - public: - ~mutex (); - mutex (); - - void - lock (); - - void - unlock (); - - private: - mutex (const mutex&); - mutex& operator= (const mutex&); - - private: - friend class condition; - pthread_mutex_t mutex_; - }; - } -} - -#include - -#include - -#endif // ODB_DETAILS_POSIX_MUTEX_HXX diff --git a/odb/details/posix/mutex.ixx b/odb/details/posix/mutex.ixx deleted file mode 100644 index ee73d09..0000000 --- a/odb/details/posix/mutex.ixx +++ /dev/null @@ -1,37 +0,0 @@ -// file : odb/details/posix/mutex.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - inline mutex:: - ~mutex () - { - pthread_mutex_destroy (&mutex_); - } - - inline mutex:: - mutex () - { - if (int e = pthread_mutex_init (&mutex_, 0)) - throw posix_exception (e); - } - - inline void mutex:: - lock () - { - if (int e = pthread_mutex_lock (&mutex_)) - throw posix_exception (e); - } - - inline void mutex:: - unlock () - { - if (int e = pthread_mutex_unlock (&mutex_)) - throw posix_exception (e); - } - } -} diff --git a/odb/details/posix/thread.cxx b/odb/details/posix/thread.cxx deleted file mode 100644 index 045f32a..0000000 --- a/odb/details/posix/thread.cxx +++ /dev/null @@ -1,44 +0,0 @@ -// file : odb/details/posix/thread.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include - -typedef void* (*thread_func) (void*); - -struct thread_data -{ - thread_func func; - void* arg; -}; - -extern "C" void* -odb_thread_thunk (void* arg) -{ - thread_data* data (static_cast (arg)); - thread_func func = data->func; - arg = data->arg; - delete data; - return func (arg); -} - -namespace odb -{ - namespace details - { - thread:: - thread (void* (*func) (void*), void* arg) - : detached_ (false) - { - unique_ptr data (new thread_data); - data->func = func; - data->arg = arg; - - if (int e = pthread_create (&id_, 0, &odb_thread_thunk, data.get ())) - throw posix_exception (e); - - data.release (); // Thread thunk will free this. - } - } -} diff --git a/odb/details/posix/thread.hxx b/odb/details/posix/thread.hxx deleted file mode 100644 index f0d29a7..0000000 --- a/odb/details/posix/thread.hxx +++ /dev/null @@ -1,41 +0,0 @@ -// file : odb/details/posix/thread.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_POSIX_THREAD_HXX -#define ODB_DETAILS_POSIX_THREAD_HXX - -#include - -#include - -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT thread - { - public: - ~thread (); - thread (void* (*thread_func) (void*), void* arg = 0); - - void* - join (); - - private: - thread (const thread&); - thread& operator= (const thread&); - - private: - bool detached_; - pthread_t id_; - }; - } -} - -#include - -#include - -#endif // ODB_DETAILS_POSIX_THREAD_HXX diff --git a/odb/details/posix/thread.ixx b/odb/details/posix/thread.ixx deleted file mode 100644 index 6576101..0000000 --- a/odb/details/posix/thread.ixx +++ /dev/null @@ -1,29 +0,0 @@ -// file : odb/details/posix/thread.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - inline thread:: - ~thread () - { - if (!detached_) - pthread_detach (id_); - } - - inline void* thread:: - join () - { - void* r; - - if (int e = pthread_join (id_, &r)) - throw posix_exception (e); - - detached_ = true; - return r; - } - } -} diff --git a/odb/details/posix/tls.hxx b/odb/details/posix/tls.hxx deleted file mode 100644 index e868819..0000000 --- a/odb/details/posix/tls.hxx +++ /dev/null @@ -1,106 +0,0 @@ -// file : odb/details/posix/tls.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_POSIX_TLS_HXX -#define ODB_DETAILS_POSIX_TLS_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - template - class tls - { - public: - tls (); - - T& - get () const; - - void - free (); - - private: - tls (const tls&); - tls& operator= (const tls&); - - private: - static void - key_init (); - - static void - destructor (void*); - - private: - static int error_; - static pthread_once_t once_; - static pthread_key_t key_; - }; - - template - class tls - { - public: - tls (); - - T* - get () const; - - void - set (T* p); - - private: - tls (const tls&); - tls& operator= (const tls&); - - private: - static void - key_init (); - - private: - static int error_; - static pthread_once_t once_; - static pthread_key_t key_; - }; - - template - inline T& - tls_get (const tls& t) - { - return t.get (); - } - - template - inline void - tls_free (tls& t) - { - t.free (); - } - - template - inline T* - tls_get (const tls& t) - { - return t.get (); - } - - template - inline void - tls_set (tls& t, T1* p1) - { - T* p (p1); - t.set (p); - } - } -} - -#include -#include - -#include - -#endif // ODB_DETAILS_POSIX_TLS_HXX diff --git a/odb/details/posix/tls.ixx b/odb/details/posix/tls.ixx deleted file mode 100644 index 7acc173..0000000 --- a/odb/details/posix/tls.ixx +++ /dev/null @@ -1,20 +0,0 @@ -// file : odb/details/posix/tls.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace details - { - template - inline tls:: - tls () - { - } - - template - inline tls:: - tls () - { - } - } -} diff --git a/odb/details/posix/tls.txx b/odb/details/posix/tls.txx deleted file mode 100644 index e4c5b8f..0000000 --- a/odb/details/posix/tls.txx +++ /dev/null @@ -1,121 +0,0 @@ -// file : odb/details/posix/tls.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -namespace odb -{ - namespace details - { - // tls - // - - template - int tls::error_ = 0; - - template - pthread_once_t tls::once_ = PTHREAD_ONCE_INIT; - - template - pthread_key_t tls::key_; - - template - T& tls:: - get () const - { - int e (pthread_once (&once_, key_init)); - - if (e != 0 || error_ != 0) - throw posix_exception (e ? e : error_); - - if (void* v = pthread_getspecific (key_)) - return *static_cast (v); - - unique_ptr p (new T); - - if ((e = pthread_setspecific (key_, p.get ()))) - throw posix_exception (e); - - T& r (*p); - p.release (); - return r; - } - - template - void tls:: - free () - { - int e (pthread_once (&once_, key_init)); - - if (e != 0 || error_ != 0) - throw posix_exception (e ? e : error_); - - if (void* v = pthread_getspecific (key_)) - { - if ((e = pthread_setspecific (key_, 0))) - throw posix_exception (e); - - delete static_cast (v); - } - } - - template - void tls:: - key_init () - { - error_ = pthread_key_create (&key_, destructor); - } - - template - void tls:: - destructor (void* v) - { - delete static_cast (v); - } - - // tls - // - - template - int tls::error_ = 0; - - template - pthread_once_t tls::once_ = PTHREAD_ONCE_INIT; - - template - pthread_key_t tls::key_; - - template - T* tls:: - get () const - { - int e (pthread_once (&once_, key_init)); - - if (e != 0 || error_ != 0) - throw posix_exception (e ? e : error_); - - return static_cast (pthread_getspecific (key_)); - } - - template - void tls:: - set (T* p) - { - int e (pthread_once (&once_, key_init)); - - if (e != 0 || error_ != 0) - throw posix_exception (e ? e : error_); - - if ((e = pthread_setspecific (key_, p))) - throw posix_exception (e); - } - - template - void tls:: - key_init () - { - error_ = pthread_key_create (&key_, 0); - } - } -} diff --git a/odb/details/shared-ptr-fwd.hxx b/odb/details/shared-ptr-fwd.hxx deleted file mode 100644 index 73377b9..0000000 --- a/odb/details/shared-ptr-fwd.hxx +++ /dev/null @@ -1,24 +0,0 @@ -// file : odb/details/shared-ptr-fwd.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_SHARED_PTR_FWD_HXX -#define ODB_DETAILS_SHARED_PTR_FWD_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - template - class shared_ptr; - - class shared_base; - } -} - -#include - -#endif // ODB_DETAILS_SHARED_PTR_FWD_HXX diff --git a/odb/details/shared-ptr.hxx b/odb/details/shared-ptr.hxx deleted file mode 100644 index 5a1e842..0000000 --- a/odb/details/shared-ptr.hxx +++ /dev/null @@ -1,167 +0,0 @@ -// file : odb/details/shared-ptr.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_SHARED_PTR_HXX -#define ODB_DETAILS_SHARED_PTR_HXX - -#include - -#include -#include -#include - -namespace odb -{ - namespace details - { - template - class shared_ptr: - private 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 (const shared_ptr& x) - : base (x), x_ (x.x_) - { - if (x_ != 0) - base::inc (x_); - } - - template - shared_ptr (const shared_ptr& x) - : base (x), x_ (x.x_) - { - if (x_ != 0) - base::inc (x_); - } - - shared_ptr& - operator= (const shared_ptr& 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= (const shared_ptr& 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; - } - - void - reset (X* x = 0) - { - if (x_ != 0) - base::dec (x_); - - base::reset (x); - x_ = x; - } - - std::size_t - count () const - { - return x_ != 0 ? base::count (x_) : 0; - } - - private: - template - friend class shared_ptr; - - X* x_; - }; - - template - inline bool - operator== (const shared_ptr& x, const shared_ptr& y) - { - return x.get () == y.get (); - } - - template - inline bool - operator!= (const shared_ptr& x, const shared_ptr& y) - { - return x.get () != y.get (); - } - } -} - -#include - -#endif // ODB_DETAILS_SHARED_PTR_HXX diff --git a/odb/details/shared-ptr/base.cxx b/odb/details/shared-ptr/base.cxx deleted file mode 100644 index d937400..0000000 --- a/odb/details/shared-ptr/base.cxx +++ /dev/null @@ -1,83 +0,0 @@ -// file : odb/details/shared-ptr/base.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -using std::size_t; - -namespace odb -{ - namespace details - { - share shared = share (1); - share exclusive = share (2); - - const char* not_shared:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "object is not shared"; - } - - not_shared* not_shared:: - clone () const - { - return new not_shared (*this); - } - - namespace bits - { - size_t* locator_common:: - counter (void* x) - { - size_t* p (static_cast (x)); - - if (*(--p) != 0xDEADBEEF) - throw not_shared (); - - return --p; - } - } - } -} - -void* -#ifdef ODB_CXX11 -operator new (size_t n, odb::details::share s) -#else -operator new (size_t n, odb::details::share s) throw (std::bad_alloc) -#endif -{ - if (s == odb::details::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, odb::details::share s) ODB_NOTHROW_NOEXCEPT -{ - // 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 == odb::details::shared) - { - size_t* sp = static_cast (p); - sp -= 2; - operator delete (sp); - } - else - operator delete (p); -} diff --git a/odb/details/shared-ptr/base.hxx b/odb/details/shared-ptr/base.hxx deleted file mode 100644 index 8cd4c86..0000000 --- a/odb/details/shared-ptr/base.hxx +++ /dev/null @@ -1,131 +0,0 @@ -// file : odb/details/shared-ptr/base.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_SHARED_PTR_BASE_HXX -#define ODB_DETAILS_SHARED_PTR_BASE_HXX - -#include - -#include // ODB_CXX11, ODB_NOTHROW_NOEXCEPT - -#include -#include // std::size_t - -#ifdef ODB_CXX11 -#include -#endif - -#include -#include - -namespace odb -{ - namespace details - { - struct share - { - explicit - share (char id); - - bool - operator== (share) const; - - private: - char id_; - }; - - extern LIBODB_EXPORT share shared; - extern LIBODB_EXPORT share exclusive; - } -} - -#ifdef ODB_CXX11 -LIBODB_EXPORT void* -operator new (std::size_t, odb::details::share); -#else -LIBODB_EXPORT void* -operator new (std::size_t, odb::details::share) throw (std::bad_alloc); -#endif - -LIBODB_EXPORT void -operator delete (void*, odb::details::share) ODB_NOTHROW_NOEXCEPT; - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT shared_base - { - public: - shared_base (); - shared_base (const shared_base&); - shared_base& - operator= (const shared_base&); - - void - _inc_ref (); - - bool - _dec_ref (); - - std::size_t - _ref_count () const; - -#ifdef ODB_CXX11 - void* - operator new (std::size_t); - - void* - operator new (std::size_t, share); -#else - void* - operator new (std::size_t) throw (std::bad_alloc); - - void* - operator new (std::size_t, share) throw (std::bad_alloc); -#endif - - void - operator delete (void*, share) ODB_NOTHROW_NOEXCEPT; - - void - operator delete (void*) ODB_NOTHROW_NOEXCEPT; - - struct refcount_callback - { - void* arg; - - // Return true if the object should be deleted, false otherwise. - // - bool (*zero_counter) (void*); - }; - - protected: -#ifdef ODB_CXX11 - std::atomic counter_; -#else - std::size_t counter_; -#endif - refcount_callback* callback_; - }; - - template - inline X* - inc_ref (X*); - - template - inline void - dec_ref (X*); - - template - inline std::size_t - ref_count (const X*); - } -} - -#include -#include - -#include - -#endif // ODB_DETAILS_SHARED_PTR_BASE_HXX diff --git a/odb/details/shared-ptr/base.ixx b/odb/details/shared-ptr/base.ixx deleted file mode 100644 index 1e2fd4b..0000000 --- a/odb/details/shared-ptr/base.ixx +++ /dev/null @@ -1,119 +0,0 @@ -// file : odb/details/shared-ptr/base.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace details - { - // 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), callback_ (0) - { - } - - inline shared_base:: - shared_base (const shared_base&) - : counter_ (1), callback_ (0) - { - } - - inline shared_base& shared_base:: - operator= (const shared_base&) - { - return *this; - } - - inline void shared_base:: - _inc_ref () - { -#ifdef ODB_CXX11 - counter_.fetch_add (1, std::memory_order_relaxed); -#else - ++counter_; -#endif - } - - inline bool shared_base:: - _dec_ref () - { - // While there are ways to avoid acquire (which is unnecessary except - // when the counter drops to zero), for our use-cases we'd rather keep - // it simple. - // - return -#ifdef ODB_CXX11 - counter_.fetch_sub (1, std::memory_order_acq_rel) == 1 -#else - --counter_ == 0 -#endif - ? callback_ == 0 || callback_->zero_counter (callback_->arg) - : false; - } - - inline std::size_t shared_base:: - _ref_count () const - { -#ifdef ODB_CXX11 - return counter_.load (std::memory_order_relaxed); -#else - return counter_; -#endif - } - -#ifdef ODB_CXX11 - inline void* shared_base:: - operator new (std::size_t n) - { - return ::operator new (n); - } - - inline void* shared_base:: - operator new (std::size_t n, share) - { - return ::operator new (n); - } -#else - inline void* shared_base:: - operator new (std::size_t n) throw (std::bad_alloc) - { - return ::operator new (n); - } - - inline void* shared_base:: - operator new (std::size_t n, share) throw (std::bad_alloc) - { - return ::operator new (n); - } -#endif - - inline void shared_base:: - operator delete (void* p, share) ODB_NOTHROW_NOEXCEPT - { - ::operator delete (p); - } - - inline void shared_base:: - operator delete (void* p) ODB_NOTHROW_NOEXCEPT - { - ::operator delete (p); - } - } -} diff --git a/odb/details/shared-ptr/base.txx b/odb/details/shared-ptr/base.txx deleted file mode 100644 index 77a957d..0000000 --- a/odb/details/shared-ptr/base.txx +++ /dev/null @@ -1,198 +0,0 @@ -// file : odb/details/shared-ptr/base.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -namespace odb -{ - namespace details - { - namespace bits - { - // Support for locating the counter in the memory block. - // - struct LIBODB_EXPORT locator_common - { - static std::size_t* - counter (void*); - }; - - template ::result> - struct locator; - - template - struct locator: locator_common - { - static std::size_t* - counter (X* x) - { - return locator_common::counter (x); - } - }; - - template - struct locator: locator_common - { - static std::size_t* - counter (X* x) - { - return locator_common::counter (dynamic_cast (x)); - } - }; - - template - std::size_t* - counter (const X* 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 typename details::counter_type::counter r; - }; - - template - struct counter_type - { - typedef shared_base r; - }; - - template - struct counter_ops; - - template - struct counter_ops - { - counter_ops (const X* p) : counter_ (p ? bits::counter (p) : 0) {} - counter_ops (const counter_ops& x) : counter_ (x.counter_) {} - - template - counter_ops (const counter_ops& x) : counter_ (x.counter_) {} - - counter_ops& - operator= (const counter_ops& x) - { - counter_ = x.counter_; - return *this; - } - - template - counter_ops& - operator= (const counter_ops& x) - { - counter_ = x.counter_; - return *this; - } - - void - reset (const X* p) - { - counter_ = p ? bits::counter (p) : 0; - } - - void - inc (X*) - { - (*counter_)++; - } - - void - dec (X* p) - { - if (--(*counter_) == 0) - { - p->~X (); - - // Counter is the top of the memory block. - // - operator delete (counter_); - } - } - - std::size_t - count (const X*) const - { - return *counter_; - } - - std::size_t* counter_; - }; - - template - struct counter_ops - { - counter_ops (const Y*) {} - counter_ops (const counter_ops&) {} - - template - counter_ops (const counter_ops&) {} - - counter_ops& - operator= (const counter_ops&) - { - return *this; - } - - template - counter_ops& - operator= (const counter_ops&) - { - return *this; - } - - void - reset (const Y*) {} - - void - inc (shared_base* p) {p->_inc_ref ();} - - void - dec (Y* p) - { - if (static_cast (p)->_dec_ref ()) - delete p; - } - - std::size_t - count (const shared_base* 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 (const X* p) - { - bits::counter_ops::r, X> c (p); - return c.count (p); - } - } -} diff --git a/odb/details/shared-ptr/counter-type.hxx b/odb/details/shared-ptr/counter-type.hxx deleted file mode 100644 index 2b6caad..0000000 --- a/odb/details/shared-ptr/counter-type.hxx +++ /dev/null @@ -1,23 +0,0 @@ -// file : odb/details/shared-ptr/counter-type.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_SHARED_PTR_COUNTER_TYPE_HXX -#define ODB_DETAILS_SHARED_PTR_COUNTER_TYPE_HXX - -#include - -namespace odb -{ - namespace details - { - template - struct counter_type - { - typedef X counter; - }; - } -} - -#include - -#endif // ODB_DETAILS_SHARED_PTR_COUNTER_TYPE_HXX diff --git a/odb/details/shared-ptr/exception.hxx b/odb/details/shared-ptr/exception.hxx deleted file mode 100644 index 0ed50be..0000000 --- a/odb/details/shared-ptr/exception.hxx +++ /dev/null @@ -1,31 +0,0 @@ -// file : odb/details/shared-ptr/exception.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_SHARED_PTR_EXCEPTION_HXX -#define ODB_DETAILS_SHARED_PTR_EXCEPTION_HXX - -#include - -#include - -#include // ODB_NOTHROW_NOEXCEPT -#include - -namespace odb -{ - namespace details - { - struct LIBODB_EXPORT not_shared: exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual not_shared* - clone () const; - }; - } -} - -#include - -#endif // ODB_DETAILS_SHARED_PTR_EXCEPTION_HXX diff --git a/odb/details/thread.cxx b/odb/details/thread.cxx deleted file mode 100644 index b1fbe42..0000000 --- a/odb/details/thread.cxx +++ /dev/null @@ -1,22 +0,0 @@ -// file : odb/details/thread.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -// We might be compiled with ODB_THREADS_NONE. -// -#ifdef ODB_THREADS_CXX11 - -namespace odb -{ - namespace details - { - void thread:: - thunk (void* (*f) (void*), void* a, std::promise p) - { - p.set_value (f (a)); - } - } -} - -#endif diff --git a/odb/details/thread.hxx b/odb/details/thread.hxx deleted file mode 100644 index 9095f68..0000000 --- a/odb/details/thread.hxx +++ /dev/null @@ -1,65 +0,0 @@ -// file : odb/details/thread.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_THREAD_HXX -#define ODB_DETAILS_THREAD_HXX - -#include - -#include -#include - -#ifdef ODB_THREADS_NONE -# error no thread support available -#elif defined(ODB_THREADS_CXX11) -# include -# include -# include // move() - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT thread - { - public: - thread (void* (*thread_func) (void*), void* arg = 0) - { - std::promise p; - f_ = p.get_future (); - t_ = std::thread (thunk, thread_func, arg, std::move (p)); - } - - void* - join () - { - f_.wait (); - t_.join (); - return f_.get (); - } - - thread (const thread&) = delete; - thread& operator= (const thread&) = delete; - - private: - static void - thunk (void* (*) (void*), void*, std::promise); - - private: - std::thread t_; - std::future f_; - }; - } -} - -#elif defined(ODB_THREADS_POSIX) -#include -#elif defined(ODB_THREADS_WIN32) -#include -#else -# error unknown threading model -#endif - -#include - -#endif // ODB_DETAILS_THREAD_HXX diff --git a/odb/details/tls.hxx b/odb/details/tls.hxx deleted file mode 100644 index de6c344..0000000 --- a/odb/details/tls.hxx +++ /dev/null @@ -1,168 +0,0 @@ -// file : odb/details/tls.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_TLS_HXX -#define ODB_DETAILS_TLS_HXX - -#include - -#include - -#ifdef ODB_THREADS_NONE - -# define ODB_TLS_POINTER(type) type* -# define ODB_TLS_OBJECT(type) type - -namespace odb -{ - namespace details - { - template - inline T& - tls_get (T& x) - { - return x; - } - - // If early destructions is possible, destroy the object and free - // any allocated resources. - // - template - inline void - tls_free (T&) - { - } - - template - inline T* - tls_get (T* p) - { - return p; - } - - template - inline void - tls_set (T*& rp, T1* p) - { - rp = p; - } - } -} - -#elif defined(ODB_THREADS_CXX11) - -// Apparently Apple's Clang "temporarily disabled" C++11 thread_local until -// they can implement a "fast" version, which reportedly happened in XCode 8. -// So for now we will continue using __thread for this target. -// -# if defined(__apple_build_version__) && __apple_build_version__ < 8000000 -# define ODB_TLS_POINTER(type) __thread type* -# define ODB_TLS_OBJECT(type) thread_local type -# else -# define ODB_TLS_POINTER(type) thread_local type* -# define ODB_TLS_OBJECT(type) thread_local type -# endif - -namespace odb -{ - namespace details - { - template - inline T& - tls_get (T& x) - { - return x; - } - - template - inline void - tls_free (T&) - { - } - - template - inline T* - tls_get (T* p) - { - return p; - } - - template - inline void - tls_set (T*& rp, T1* p) - { - rp = p; - } - } -} - -#elif defined(ODB_THREADS_POSIX) - -# include - -# ifdef ODB_THREADS_TLS_KEYWORD -# define ODB_TLS_POINTER(type) __thread type* - -namespace odb -{ - namespace details - { - template - inline T* - tls_get (T* p) - { - return p; - } - - template - inline void - tls_set (T*& rp, T1* p) - { - rp = p; - } - } -} - -# else -# define ODB_TLS_POINTER(type) tls -# endif -# define ODB_TLS_OBJECT(type) tls - -#elif defined(ODB_THREADS_WIN32) - -# include - -# ifdef ODB_THREADS_TLS_DECLSPEC -# define ODB_TLS_POINTER(type) __declspec(thread) type* - -namespace odb -{ - namespace details - { - template - inline T* - tls_get (T* p) - { - return p; - } - - template - inline void - tls_set (T*& rp, T1* p) - { - rp = p; - } - } -} - -# else -# define ODB_TLS_POINTER(type) tls -# endif -# define ODB_TLS_OBJECT(type) tls -#else -# error unknown threading model -#endif - -#include - -#endif // ODB_DETAILS_TLS_HXX diff --git a/odb/details/transfer-ptr.hxx b/odb/details/transfer-ptr.hxx deleted file mode 100644 index 4b63df6..0000000 --- a/odb/details/transfer-ptr.hxx +++ /dev/null @@ -1,73 +0,0 @@ -// file : odb/details/transfer-ptr.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_TRANSFER_PTR_HXX -#define ODB_DETAILS_TRANSFER_PTR_HXX - -#include - -#include // std::auto_ptr, std::unique_ptr - -#include // ODB_CXX11 - -namespace odb -{ - namespace details - { - template - class transfer_ptr - { - public: - typedef T element_type; - - transfer_ptr (): p_ (0) {} - -#ifndef ODB_CXX11 - template - transfer_ptr (std::auto_ptr p): p_ (p.release ()) {} - - private: - transfer_ptr& operator= (const transfer_ptr&); - - public: - // In our usage transfer_ptr is always created implicitly and - // never const. So while this is not very clean, it is legal. - // Plus it will all go away once we drop C++98 (I can hardly - // wait). - // - transfer_ptr (const transfer_ptr& p) - : p_ (const_cast (p).transfer ()) {} -#else -#ifdef ODB_CXX11_NULLPTR - transfer_ptr (std::nullptr_t): p_ (0) {} -#endif - template - transfer_ptr (std::unique_ptr&& p): p_ (p.release ()) {} - - private: - transfer_ptr (const transfer_ptr&); - transfer_ptr& operator= (const transfer_ptr&); - - public: - transfer_ptr (transfer_ptr&& p) noexcept: p_ (p.transfer ()) {} -#endif - - ~transfer_ptr () {delete p_;} - - T* - transfer () - { - T* r (p_); - p_ = 0; - return r; - } - - private: - T* p_; - }; - } -} - -#include - -#endif // ODB_DETAILS_TRANSFER_PTR_HXX diff --git a/odb/details/type-info.hxx b/odb/details/type-info.hxx deleted file mode 100644 index fe01699..0000000 --- a/odb/details/type-info.hxx +++ /dev/null @@ -1,36 +0,0 @@ -// file : odb/details/type-info.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_TYPE_INFO_HXX -#define ODB_DETAILS_TYPE_INFO_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - struct type_info_comparator - { - bool - operator() (const std::type_info* x, const std::type_info* y) const - { - // XL C++ on AIX has buggy type_info::before() in that - // it returns true for two different type_info objects - // that happened to be for the same type. - // -#if defined(__xlC__) && defined(_AIX) - return *x != *y && x->before (*y); -#else - return x->before (*y); -#endif - } - }; - } -} - -#include - -#endif // ODB_DETAILS_TYPE_INFO_HXX diff --git a/odb/details/unique-ptr.hxx b/odb/details/unique-ptr.hxx deleted file mode 100644 index 06b2c76..0000000 --- a/odb/details/unique-ptr.hxx +++ /dev/null @@ -1,95 +0,0 @@ -// file : odb/details/unique-ptr.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_UNIQUE_PTR_HXX -#define ODB_DETAILS_UNIQUE_PTR_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - template - class unique_ptr - { - public: - typedef T element_type; - - explicit unique_ptr (T* p = 0): p_ (p) {} - ~unique_ptr () {delete p_;} - -#ifdef ODB_CXX11 - unique_ptr (unique_ptr&& p) noexcept: p_ (p.p_) {p.p_ = 0;} - unique_ptr& operator= (unique_ptr&& p) noexcept - { - if (this != &p) - { - delete p_; - p_ = p.p_; - p.p_ = 0; - } - return *this; - } -#endif - - private: - unique_ptr (const unique_ptr&); - unique_ptr& operator= (const unique_ptr&); - - public: - T* - operator-> () const {return p_;} - - T& - operator* () const {return *p_;} - - typedef T* unique_ptr::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return p_ != 0 ? &unique_ptr::p_ : 0; - } - - T* - get () const {return p_;} - - void - reset (T* p = 0) - { - delete p_; - p_ = p; - } - - T* - release () - { - T* r (p_); - p_ = 0; - return r; - } - - private: - T* p_; - }; - - template - inline bool - operator== (const unique_ptr& a, const unique_ptr& b) - { - return a.get () == b.get (); - } - - template - inline bool - operator!= (const unique_ptr& a, const unique_ptr& b) - { - return a.get () != b.get (); - } - } -} - -#include - -#endif // ODB_DETAILS_UNIQUE_PTR_HXX diff --git a/odb/details/unused.hxx b/odb/details/unused.hxx deleted file mode 100644 index 8364c44..0000000 --- a/odb/details/unused.hxx +++ /dev/null @@ -1,21 +0,0 @@ -// file : odb/details/unused.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_UNUSED_DETAILS_HXX -#define ODB_UNUSED_DETAILS_HXX - -#include - -// VC++ and xlC don't like the (void)x expression if x is a reference -// to an incomplete type. On the other hand, GCC warns that (void*)&x -// doesn't have any effect. -// -#if defined(_MSC_VER) || defined(__xlC__) -# define ODB_POTENTIALLY_UNUSED(x) (void*)&x -#else -# define ODB_POTENTIALLY_UNUSED(x) (void)x -#endif - -#include - -#endif // ODB_UNUSED_DETAILS_HXX diff --git a/odb/details/win32/condition.cxx b/odb/details/win32/condition.cxx deleted file mode 100644 index 3a4b605..0000000 --- a/odb/details/win32/condition.cxx +++ /dev/null @@ -1,54 +0,0 @@ -// file : odb/details/win32/condition.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include - -namespace odb -{ - namespace details - { - void condition:: - signal () - { - mutex_.lock (); - - if (waiters_ > signals_) - { - if (signals_++ == 0) - { - if (SetEvent (event_) == 0) - throw win32_exception (); - } - } - - mutex_.unlock (); - } - - void condition:: - wait (lock&) - { - // When we enter this functions the mutex is locked. When we - // return from this function the mutex must be locked. - // - waiters_++; - mutex_.unlock (); - - if (WaitForSingleObject (event_, INFINITE) != 0) - throw win32_exception (); - - mutex_.lock (); - waiters_--; - signals_--; - - if (signals_ > 0) - { - // Wake up the next thread. - // - if (SetEvent (event_) == 0) - throw win32_exception (); - } - } - } -} diff --git a/odb/details/win32/condition.hxx b/odb/details/win32/condition.hxx deleted file mode 100644 index 69972a0..0000000 --- a/odb/details/win32/condition.hxx +++ /dev/null @@ -1,52 +0,0 @@ -// file : odb/details/win32/condition.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_CONDITION_HXX -#define ODB_DETAILS_WIN32_CONDITION_HXX - -#include - -#include - -#include // std::size_t - -#include -#include - -namespace odb -{ - namespace details - { - class lock; - - class LIBODB_EXPORT condition - { - public: - ~condition (); - condition (mutex&); - - void - signal (); - - void - wait (lock&); - - private: - condition (const condition&); - condition& operator= (const condition&); - - private: - mutex& mutex_; - HANDLE event_; - - std::size_t waiters_; - std::size_t signals_; - }; - } -} - -#include - -#include - -#endif // ODB_DETAILS_WIN32_CONDITION_HXX diff --git a/odb/details/win32/condition.ixx b/odb/details/win32/condition.ixx deleted file mode 100644 index 37a2bac..0000000 --- a/odb/details/win32/condition.ixx +++ /dev/null @@ -1,30 +0,0 @@ -// file : odb/details/win32/condition.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - inline condition:: - ~condition () - { - CloseHandle (event_); - } - - inline condition:: - condition (mutex& mutex) - : mutex_ (mutex), waiters_ (0), signals_ (0) - { - // Auto-reset event. Releases one waiting thread and automatically - // resets the event state. If no threads are waiting the event - // remains signalled. - // - event_ = CreateEvent (0, false, false, 0); - - if (event_ == 0) - throw win32_exception (); - } - } -} diff --git a/odb/details/win32/dll.cxx b/odb/details/win32/dll.cxx deleted file mode 100644 index 49b660c..0000000 --- a/odb/details/win32/dll.cxx +++ /dev/null @@ -1,51 +0,0 @@ -// file : odb/details/win32/dll.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -// If we are building a static library from VC++ (LIBODB_STATIC_LIB) or -// a static library from automake (!DLL_EXPORT), then omit DllMain. -// - -#if (defined(_MSC_VER) && defined(LIBODB_DYNAMIC_LIB)) || \ - (!defined(_MSC_VER) && defined(DLL_EXPORT)) - -#include -#include - -using namespace odb::details; - -extern "C" BOOL WINAPI -DllMain (HINSTANCE, DWORD reason, LPVOID reserved) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: - { - process_start (); - thread_start (); - break; - } - - case DLL_THREAD_ATTACH: - { - thread_start (); - break; - } - - case DLL_THREAD_DETACH: - { - thread_end (); - break; - } - - case DLL_PROCESS_DETACH: - { - thread_end (); - process_end (reserved == NULL); - break; - } - } - - return 1; -} - -#endif diff --git a/odb/details/win32/exceptions.cxx b/odb/details/win32/exceptions.cxx deleted file mode 100644 index 3cf11c2..0000000 --- a/odb/details/win32/exceptions.cxx +++ /dev/null @@ -1,22 +0,0 @@ -// file : odb/details/win32/exceptions.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - const char* win32_exception:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "Win32 API error"; - } - - win32_exception* win32_exception:: - clone () const - { - return new win32_exception (*this); - } - } -} diff --git a/odb/details/win32/exceptions.hxx b/odb/details/win32/exceptions.hxx deleted file mode 100644 index b61a447..0000000 --- a/odb/details/win32/exceptions.hxx +++ /dev/null @@ -1,40 +0,0 @@ -// file : odb/details/win32/exceptions.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_EXCEPTIONS_HXX -#define ODB_DETAILS_WIN32_EXCEPTIONS_HXX - -#include - -#include // ODB_NOTHROW_NOEXCEPT -#include -#include -#include - -namespace odb -{ - namespace details - { - struct LIBODB_EXPORT win32_exception: details::exception - { - win32_exception () : code_ (GetLastError ()) {} - win32_exception (DWORD code) : code_ (code) {} - - DWORD - code () const {return code_;} - - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual win32_exception* - clone () const; - - private: - DWORD code_; - }; - } -} - -#include - -#endif // ODB_DETAILS_WIN32_EXCEPTIONS_HXX diff --git a/odb/details/win32/init.cxx b/odb/details/win32/init.cxx deleted file mode 100644 index f6e0f9a..0000000 --- a/odb/details/win32/init.cxx +++ /dev/null @@ -1,41 +0,0 @@ -// file : odb/details/win32/init.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include - -namespace odb -{ - namespace details - { - void - process_start () - { - // The order is important. - // - once_process_start (); - tls_process_start (); - } - - void - process_end (bool safe) - { - // The order is important. - // - tls_process_end (safe); - once_process_end (safe); - } - - void - thread_start () - { - } - - void - thread_end () - { - tls_thread_end (); - } - } -} diff --git a/odb/details/win32/init.hxx b/odb/details/win32/init.hxx deleted file mode 100644 index 1c15ffd..0000000 --- a/odb/details/win32/init.hxx +++ /dev/null @@ -1,36 +0,0 @@ -// file : odb/details/win32/init.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_INIT_HXX -#define ODB_DETAILS_WIN32_INIT_HXX - -#include - -namespace odb -{ - namespace details - { - void - process_start (); - - // The safe parameter indicates whether it is safe to free heap objects. - // If the process is terminated by a call to ExitProcess(), some threads - // might have been killed leaving things in inconsistent state. - // - void - process_end (bool safe = true); - - void - thread_start (); - - // This function may be called even for thread for which thread_start() - // hasn't been called. - // - void - thread_end (); - } -} - -#include - -#endif // ODB_DETAILS_WIN32_INIT_HXX diff --git a/odb/details/win32/lock.hxx b/odb/details/win32/lock.hxx deleted file mode 100644 index 2e81ac6..0000000 --- a/odb/details/win32/lock.hxx +++ /dev/null @@ -1,49 +0,0 @@ -// file : odb/details/win32/lock.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_LOCK_HXX -#define ODB_DETAILS_WIN32_LOCK_HXX - -#include - -#include - -namespace odb -{ - namespace details - { - // Critical section lock. Not exported; for internal use only. - // - struct win32_lock - { - win32_lock (CRITICAL_SECTION& cs) - : cs_ (&cs) - { - EnterCriticalSection (cs_); - } - - ~win32_lock () - { - if (cs_ != 0) - LeaveCriticalSection (cs_); - } - - void - unlock () - { - if (cs_ != 0) - { - LeaveCriticalSection (cs_); - cs_ = 0; - } - } - - private: - CRITICAL_SECTION* cs_; - }; - } -} - -#include - -#endif // ODB_DETAILS_WIN32_LOCK_HXX diff --git a/odb/details/win32/mutex.hxx b/odb/details/win32/mutex.hxx deleted file mode 100644 index b2cd997..0000000 --- a/odb/details/win32/mutex.hxx +++ /dev/null @@ -1,43 +0,0 @@ -// file : odb/details/win32/mutex.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_MUTEX_HXX -#define ODB_DETAILS_WIN32_MUTEX_HXX - -#include - -#include -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT mutex - { - public: - ~mutex (); - mutex (); - - void - lock (); - - void - unlock (); - - private: - mutex (const mutex&); - mutex& operator= (const mutex&); - - private: - friend class condition; - CRITICAL_SECTION cs_; - }; - } -} - -#include - -#include - -#endif // ODB_DETAILS_WIN32_MUTEX_HXX diff --git a/odb/details/win32/mutex.ixx b/odb/details/win32/mutex.ixx deleted file mode 100644 index bb06415..0000000 --- a/odb/details/win32/mutex.ixx +++ /dev/null @@ -1,32 +0,0 @@ -// file : odb/details/win32/mutex.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace details - { - inline mutex:: - ~mutex () - { - DeleteCriticalSection (&cs_); - } - - inline mutex:: - mutex () - { - InitializeCriticalSection (&cs_); - } - - inline void mutex:: - lock () - { - EnterCriticalSection (&cs_); - } - - inline void mutex:: - unlock () - { - LeaveCriticalSection (&cs_); - } - } -} diff --git a/odb/details/win32/once-init.hxx b/odb/details/win32/once-init.hxx deleted file mode 100644 index a465c90..0000000 --- a/odb/details/win32/once-init.hxx +++ /dev/null @@ -1,23 +0,0 @@ -// file : odb/details/win32/once-init.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_ONCE_INIT_HXX -#define ODB_DETAILS_WIN32_ONCE_INIT_HXX - -#include - -namespace odb -{ - namespace details - { - void - once_process_start (); - - void - once_process_end (bool safe); - } -} - -#include - -#endif // ODB_DETAILS_WIN32_ONCE_INIT_HXX diff --git a/odb/details/win32/once.cxx b/odb/details/win32/once.cxx deleted file mode 100644 index 7b98d80..0000000 --- a/odb/details/win32/once.cxx +++ /dev/null @@ -1,26 +0,0 @@ -// file : odb/details/win32/once.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include - -namespace odb -{ - namespace details - { - CRITICAL_SECTION win32_once_cs_; - - void - once_process_start () - { - InitializeCriticalSection (&win32_once_cs_); - } - - void - once_process_end (bool) - { - DeleteCriticalSection (&win32_once_cs_); - } - } -} diff --git a/odb/details/win32/once.hxx b/odb/details/win32/once.hxx deleted file mode 100644 index 45748b8..0000000 --- a/odb/details/win32/once.hxx +++ /dev/null @@ -1,50 +0,0 @@ -// file : odb/details/win32/once.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_ONCE_HXX -#define ODB_DETAILS_WIN32_ONCE_HXX - -#include - -#include -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT once - { - public: - once (); - - void - call (void (*func) ()); - - private: - once (const once&); - once& operator= (const once&); - - private: - bool called_; - }; - - // Low-level, POSIX-like API that can be used safely during static - // initialization (that is, win32_once() can be called during static - // initialization) provided once_process_start() has been called. - // - typedef unsigned int win32_once_t; - const win32_once_t WIN32_ONCE_INIT = 0; - - LIBODB_EXPORT void - win32_once (win32_once_t&, void (*func) ()); - - extern LIBODB_EXPORT CRITICAL_SECTION win32_once_cs_; - } -} - -#include - -#include - -#endif // ODB_DETAILS_WIN32_ONCE_HXX diff --git a/odb/details/win32/once.ixx b/odb/details/win32/once.ixx deleted file mode 100644 index 1638706..0000000 --- a/odb/details/win32/once.ixx +++ /dev/null @@ -1,42 +0,0 @@ -// file : odb/details/win32/once.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - namespace details - { - inline void - win32_once (win32_once_t& o, void (*func) ()) - { - win32_lock l (win32_once_cs_); - - if (o == 0) - { - o = 1; - l.unlock (); - func (); - } - } - - inline once:: - once () - : called_ (false) - { - } - - inline void once:: - call (void (*func) ()) - { - win32_lock l (win32_once_cs_); - - if (!called_) - { - called_ = true; - l.unlock (); - func (); - } - } - } -} diff --git a/odb/details/win32/thread.cxx b/odb/details/win32/thread.cxx deleted file mode 100644 index 46720d4..0000000 --- a/odb/details/win32/thread.cxx +++ /dev/null @@ -1,88 +0,0 @@ -// file : odb/details/win32/thread.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include // _beginthreadex, _endthreadex - -#include -#include -#include - -unsigned int __stdcall -odb_thread_thunk (void* arg) -{ - odb::details::thread::thread_thunk (arg); - _endthreadex (0); - return 0; -} - -namespace odb -{ - namespace details - { - void thread:: - thread_thunk (void* arg) - { - data* d (static_cast (arg)); - d->ret = d->func (d->arg); - d->mutex.lock (); - unsigned char count = --d->count; - d->mutex.unlock (); - - if (count == 0) - delete d; - } - - thread:: - ~thread () - { - if (handle_ != 0) - { - CloseHandle (handle_); - - // Win32 mutex implementation does not throw. - // - data_->mutex.lock (); - unsigned char count = --data_->count; - data_->mutex.unlock (); - - if (count == 0) - delete data_; - } - } - - thread:: - thread (void* (*func) (void*), void* arg) - { - unique_ptr d (new data); - d->func = func; - d->arg = arg; - d->count = 2; // One for the thread and one for us. - - handle_ = (HANDLE)_beginthreadex ( - 0, 0, &odb_thread_thunk, d.get (), 0, 0); - - if (handle_ == 0) - throw win32_exception (); - - data_ = d.release (); - } - - void* thread:: - join () - { - void* r; - - if (WaitForSingleObject (handle_, INFINITE) != 0) - throw win32_exception (); - - r = data_->ret; - - CloseHandle (handle_); - delete data_; - handle_ = 0; - data_ = 0; - return r; - } - } -} diff --git a/odb/details/win32/thread.hxx b/odb/details/win32/thread.hxx deleted file mode 100644 index a4e1a15..0000000 --- a/odb/details/win32/thread.hxx +++ /dev/null @@ -1,59 +0,0 @@ -// file : odb/details/win32/thread.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_THREAD_HXX -#define ODB_DETAILS_WIN32_THREAD_HXX - -#include - -#include -#include -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT thread - { - public: - ~thread (); - thread (void* (*thread_func) (void*), void* arg = 0); - - void* - join (); - - private: - thread (const thread&); - thread& operator= (const thread&); - - private: - typedef void* (*thread_func) (void*); - - struct data - { - thread_func func; - void* arg; - void* ret; - - // Thread-safe reference counter. - // - details::mutex mutex; - unsigned char count; - }; - - - public: - static void - thread_thunk (void*); - - private: - HANDLE handle_; - data* data_; - }; - } -} - -#include - -#endif // ODB_DETAILS_WIN32_THREAD_HXX diff --git a/odb/details/win32/tls-init.hxx b/odb/details/win32/tls-init.hxx deleted file mode 100644 index 0a44a10..0000000 --- a/odb/details/win32/tls-init.hxx +++ /dev/null @@ -1,26 +0,0 @@ -// file : odb/details/win32/tls-init.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_TLS_INIT_HXX -#define ODB_DETAILS_WIN32_TLS_INIT_HXX - -#include - -namespace odb -{ - namespace details - { - void - tls_process_start (); - - void - tls_process_end (bool safe); - - void - tls_thread_end (); - } -} - -#include - -#endif // ODB_DETAILS_WIN32_TLS_INIT_HXX diff --git a/odb/details/win32/tls.cxx b/odb/details/win32/tls.cxx deleted file mode 100644 index 2edc364..0000000 --- a/odb/details/win32/tls.cxx +++ /dev/null @@ -1,245 +0,0 @@ -// file : odb/details/win32/tls.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include // ERROR_INVALID_INDEX - -#include -#include // std::size_t - -#include -#include -#include -#include - -#ifdef _MSC_VER -# pragma warning (disable:4200) // zero-sized array in struct -#endif - -using namespace std; - -namespace odb -{ - namespace details - { - typedef void (*dtor_func) (void*); - - struct entry - { - void* value; - dtor_func dtor; - }; - - struct thread_data - { - size_t size; - size_t capacity; - entry entries[0]; - }; - - struct process_data - { - size_t size; - size_t capacity; - dtor_func dtors[0]; - }; - - static DWORD index_ = TLS_OUT_OF_INDEXES; - static CRITICAL_SECTION cs_; - static process_data* proc_data_; - - const size_t init_capacity = 4; - - void - tls_process_start () - { - index_ = TlsAlloc (); - - if (index_ == TLS_OUT_OF_INDEXES) - throw win32_exception (); - - InitializeCriticalSection (&cs_); - - process_data* pd ( - static_cast ( - operator new ( - sizeof (process_data) + sizeof (dtor_func) * init_capacity))); - - pd->size = 0; - pd->capacity = init_capacity; - memset (pd->dtors, 0, sizeof (dtor_func) * init_capacity); - - proc_data_ = pd; - } - - void - tls_process_end (bool) - { - operator delete (proc_data_); - DeleteCriticalSection (&cs_); - - if (index_ != TLS_OUT_OF_INDEXES) - { - if (!TlsFree (index_)) - throw win32_exception (); - } - } - - void - tls_thread_end () - { - if (thread_data* d = static_cast (TlsGetValue (index_))) - { - // Call destructors. Implement the pthread semantics in that the - // destructors are called until all the values become 0. - // - for (bool pass (true); pass;) - { - pass = false; - - for (size_t i (0); i < d->size; ++i) - { - if (d->entries[i].dtor != 0 && d->entries[i].value != 0) - { - pass = true; - void* tmp (d->entries[i].value); - d->entries[i].value = 0; - d->entries[i].dtor (tmp); - } - } - } - - operator delete (d); - } - } - - // - // tls_common - // - - std::size_t tls_common:: - _allocate (dtor_func dtor) - { - win32_lock l (cs_); - - size_t n (proc_data_->size); - size_t c (proc_data_->capacity); - - if (n == c) - { - c *= 2; - - // Try to do "atomic" switch-over so that proc_data_ always points - // to memory that can be freed even if this thread is killed in the - // middle. - // - process_data* pd ( - static_cast ( - operator new (sizeof (process_data) + sizeof (dtor_func) * c))); - - memcpy (pd->dtors, proc_data_->dtors, n * sizeof (dtor_func)); - memset (pd->dtors + n, 0, sizeof (dtor_func) * (c - n)); - - pd->size = n; - pd->capacity = c; - - process_data* old (proc_data_); - proc_data_ = pd; - operator delete (old); - } - - proc_data_->dtors[n] = dtor; - return proc_data_->size++; - } - - void* tls_common:: - _get (std::size_t key) - { - if (thread_data* d = static_cast (TlsGetValue (index_))) - { - if (key < d->size) - return d->entries[key].value; - } - - // Check if this key is valid. - // - win32_lock l (cs_); - - if (key < proc_data_->size) - return 0; - - throw win32_exception (ERROR_INVALID_INDEX); - } - - void tls_common:: - _set (std::size_t key, void* value) - { - thread_data* d (static_cast (TlsGetValue (index_))); - - if (d != 0 && key < d->capacity) - { - if (key >= d->size) - { - // Check if this key is valid. If so then we need to copy - // dtors for new slots. - // - win32_lock l (cs_); - - size_t n (proc_data_->size); - - if (key >= n) - throw win32_exception (ERROR_INVALID_INDEX); - - for (size_t i (d->size); i < n; ++i) - d->entries[i].dtor = proc_data_->dtors[i]; - - d->size = n; - } - - d->entries[key].value = value; - } - else - { - // Check if this key is valid. If so then we need to (re)-allocate - // our storage. - // - win32_lock l (cs_); - - size_t n (proc_data_->size); - - if (key >= n) - throw win32_exception (ERROR_INVALID_INDEX); - - size_t c (proc_data_->capacity); - - thread_data* nd ( - static_cast ( - operator new (sizeof (thread_data) + sizeof (entry) * c))); - - size_t on (d == 0 ? 0 : d->size); - - // Copy over the data. - // - if (on != 0) - memcpy (nd->entries, d->entries, sizeof (entry) * on); - - // Zero out the rest. - // - memset (nd->entries + on, 0, sizeof (entry) * (c - on)); - - // Assign destructors to new slots [on, n). - // - for (size_t i (on); i < n; ++i) - nd->entries[i].dtor = proc_data_->dtors[i]; - - nd->size = n; - nd->capacity = c; - - operator delete (d); - TlsSetValue (index_, nd); - - nd->entries[key].value = value; - } - } - } -} diff --git a/odb/details/win32/tls.hxx b/odb/details/win32/tls.hxx deleted file mode 100644 index 2a75cc8..0000000 --- a/odb/details/win32/tls.hxx +++ /dev/null @@ -1,120 +0,0 @@ -// file : odb/details/win32/tls.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_TLS_HXX -#define ODB_DETAILS_WIN32_TLS_HXX - -#include - -#include // std::size_t - -#include -#include - -namespace odb -{ - namespace details - { - class LIBODB_EXPORT tls_common - { - public: - static std::size_t - _allocate (void (*dtor) (void*)); - - static void* - _get (std::size_t key); - - static void - _set (std::size_t key, void* value); - }; - - template - class tls: protected tls_common - { - public: - tls (); - - T& - get () const; - - void - free (); - - private: - tls (const tls&); - tls& operator= (const tls&); - - private: - static void - key_init (); - - static void - destructor (void*); - - private: - static win32_once_t once_; - static std::size_t key_; - }; - - template - class tls: protected tls_common - { - public: - tls (); - - T* - get () const; - - void - set (T* p); - - private: - tls (const tls&); - tls& operator= (const tls&); - - private: - static void - key_init (); - - private: - static win32_once_t once_; - static std::size_t key_; - }; - - template - inline T& - tls_get (const tls& t) - { - return t.get (); - } - - template - inline void - tls_free (tls& t) - { - t.free (); - } - - template - inline T* - tls_get (const tls& t) - { - return t.get (); - } - - template - inline void - tls_set (tls& t, T1* p1) - { - T* p (p1); - t.set (p); - } - } -} - -#include -#include - -#include - -#endif // ODB_DETAILS_WIN32_TLS_HXX diff --git a/odb/details/win32/tls.ixx b/odb/details/win32/tls.ixx deleted file mode 100644 index fbcc3dd..0000000 --- a/odb/details/win32/tls.ixx +++ /dev/null @@ -1,20 +0,0 @@ -// file : odb/details/win32/tls.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace details - { - template - inline tls:: - tls () - { - } - - template - inline tls:: - tls () - { - } - } -} diff --git a/odb/details/win32/tls.txx b/odb/details/win32/tls.txx deleted file mode 100644 index 96bed4c..0000000 --- a/odb/details/win32/tls.txx +++ /dev/null @@ -1,94 +0,0 @@ -// file : odb/details/win32/tls.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -namespace odb -{ - namespace details - { - // tls - // - template - win32_once_t tls::once_= WIN32_ONCE_INIT; - - template - size_t tls::key_; - - template - T& tls:: - get () const - { - win32_once (once_, key_init); - - if (void* v = _get (key_)) - return *static_cast (v); - - unique_ptr p (new T); - _set (key_, p.get ()); - - T& r (*p); - p.release (); - return r; - } - - template - void tls:: - free () - { - win32_once (once_, key_init); - - if (void* v = _get (key_)) - { - _set (key_, 0); - delete static_cast (v); - } - } - - template - void tls:: - key_init () - { - key_ = _allocate (destructor); - } - - template - void tls:: - destructor (void* v) - { - delete static_cast (v); - } - - // tls - // - template - win32_once_t tls::once_ = WIN32_ONCE_INIT; - - template - size_t tls::key_; - - template - T* tls:: - get () const - { - win32_once (once_, key_init); - return static_cast (_get (key_)); - } - - template - void tls:: - set (T* p) - { - win32_once (once_, key_init); - _set (key_, p); - } - - template - void tls:: - key_init () - { - key_ = _allocate (0); - } - } -} diff --git a/odb/details/win32/windows.hxx b/odb/details/win32/windows.hxx deleted file mode 100644 index 9ff4cb4..0000000 --- a/odb/details/win32/windows.hxx +++ /dev/null @@ -1,33 +0,0 @@ -// file : odb/details/win32/windows.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WIN32_WINDOWS_HXX -#define ODB_DETAILS_WIN32_WINDOWS_HXX - -#include - -// Try to include so that it doesn't mess other things up. -// -#ifndef WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# ifndef NOMINMAX // No min and max macros. -# define NOMINMAX -# include -# undef NOMINMAX -# else -# include -# endif -# undef WIN32_LEAN_AND_MEAN -#else -# ifndef NOMINMAX -# define NOMINMAX -# include -# undef NOMINMAX -# else -# include -# endif -#endif - -#include - -#endif // ODB_DETAILS_WIN32_WINDOWS_HXX diff --git a/odb/details/wrapper-p.hxx b/odb/details/wrapper-p.hxx deleted file mode 100644 index 8f72b5d..0000000 --- a/odb/details/wrapper-p.hxx +++ /dev/null @@ -1,38 +0,0 @@ -// file : odb/details/wrapper-p.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_DETAILS_WRAPPER_P_HXX -#define ODB_DETAILS_WRAPPER_P_HXX - -#include - -#include - -#include - -namespace odb -{ - namespace details - { - // GCC doesn't like these to be inside wrapper_p. - // - template - meta::no - wrapper_p_test (...); - - template - meta::yes - wrapper_p_test (typename wrapper_traits::wrapped_type*); - - template - struct wrapper_p - { - static const bool r = - sizeof (wrapper_p_test (0)) == sizeof (meta::yes); - }; - } -} - -#include - -#endif // ODB_DETAILS_WRAPPER_P_HXX diff --git a/odb/exception.hxx b/odb/exception.hxx deleted file mode 100644 index 39daf92..0000000 --- a/odb/exception.hxx +++ /dev/null @@ -1,36 +0,0 @@ -// file : odb/exception.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_EXCEPTION_HXX -#define ODB_EXCEPTION_HXX - -#include - -#include - -#include // odb::core - -#include // ODB_NOTHROW_NOEXCEPT -#include -#include - -namespace odb -{ - struct LIBODB_EXPORT exception: std::exception, details::shared_base - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT = 0; - - virtual exception* - clone () const = 0; - }; - - namespace common - { - using odb::exception; - } -} - -#include - -#endif // ODB_EXCEPTION_HXX diff --git a/odb/exceptions.cxx b/odb/exceptions.cxx deleted file mode 100644 index bb13b6c..0000000 --- a/odb/exceptions.cxx +++ /dev/null @@ -1,430 +0,0 @@ -// file : odb/exceptions.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include // std::strlen -#include -#include - -#include - -using namespace std; - -namespace odb -{ - const char* null_pointer:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "NULL pointer"; - } - - null_pointer* null_pointer:: - clone () const - { - return new null_pointer (*this); - } - - const char* already_in_transaction:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "transaction already in progress in this thread"; - } - - already_in_transaction* already_in_transaction:: - clone () const - { - return new already_in_transaction (*this); - } - - const char* not_in_transaction:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "operation can only be performed in transaction"; - } - - not_in_transaction* not_in_transaction:: - clone () const - { - return new not_in_transaction (*this); - } - - const char* transaction_already_finalized:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "transaction already committed or rolled back"; - } - - transaction_already_finalized* transaction_already_finalized:: - clone () const - { - return new transaction_already_finalized (*this); - } - - const char* already_in_session:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "session already in effect in this thread"; - } - - already_in_session* already_in_session:: - clone () const - { - return new already_in_session (*this); - } - - const char* not_in_session:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "session not in effect in this thread"; - } - - not_in_session* not_in_session:: - clone () const - { - return new not_in_session (*this); - } - - const char* session_required:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "session required to load this object relationship"; - } - - session_required* session_required:: - clone () const - { - return new session_required (*this); - } - - const char* deadlock:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "transaction aborted due to deadlock"; - } - - deadlock* deadlock:: - clone () const - { - return new deadlock (*this); - } - - const char* connection_lost:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "connection to database lost"; - } - - connection_lost* connection_lost:: - clone () const - { - return new connection_lost (*this); - } - - const char* timeout:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "database operation timeout"; - } - - timeout* timeout:: - clone () const - { - return new timeout (*this); - } - - const char* object_not_persistent:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "object not persistent"; - } - - object_not_persistent* object_not_persistent:: - clone () const - { - return new object_not_persistent (*this); - } - - const char* object_already_persistent:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "object already persistent"; - } - - object_already_persistent* object_already_persistent:: - clone () const - { - return new object_already_persistent (*this); - } - - const char* object_changed:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "object changed concurrently"; - } - - object_changed* object_changed:: - clone () const - { - return new object_changed (*this); - } - - const char* result_not_cached:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "query result is not cached"; - } - - result_not_cached* result_not_cached:: - clone () const - { - return new result_not_cached (*this); - } - - const char* abstract_class:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "database operation on instance of abstract class"; - } - - abstract_class* abstract_class:: - clone () const - { - return new abstract_class (*this); - } - - const char* no_type_info:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "no type information"; - } - - no_type_info* no_type_info:: - clone () const - { - return new no_type_info (*this); - } - - prepared_already_cached:: - prepared_already_cached (const char* name) - : name_ (name) - { - what_ = "prepared query '"; - what_ += name; - what_ += "' is already cached"; - } - - prepared_already_cached:: - ~prepared_already_cached () ODB_NOTHROW_NOEXCEPT - { - } - - const char* prepared_already_cached:: - what () const ODB_NOTHROW_NOEXCEPT - { - return what_.c_str (); - } - - prepared_already_cached* prepared_already_cached:: - clone () const - { - return new prepared_already_cached (*this); - } - - prepared_type_mismatch:: - prepared_type_mismatch (const char* name) - : name_ (name) - { - what_ = "type mismatch while looking up prepared query '"; - what_ += name; - what_ += "'"; - } - - prepared_type_mismatch:: - ~prepared_type_mismatch () ODB_NOTHROW_NOEXCEPT - { - } - - const char* prepared_type_mismatch:: - what () const ODB_NOTHROW_NOEXCEPT - { - return what_.c_str (); - } - - prepared_type_mismatch* prepared_type_mismatch:: - clone () const - { - return new prepared_type_mismatch (*this); - } - - unknown_schema:: - unknown_schema (const string& name) - : name_ (name) - { - what_ = "unknown database schema '"; - what_ += name; - what_ += "'"; - } - - unknown_schema:: - ~unknown_schema () ODB_NOTHROW_NOEXCEPT - { - } - - const char* unknown_schema:: - what () const ODB_NOTHROW_NOEXCEPT - { - return what_.c_str (); - } - - unknown_schema* unknown_schema:: - clone () const - { - return new unknown_schema (*this); - } - - unknown_schema_version:: - unknown_schema_version (schema_version v) - : version_ (v) - { - ostringstream os; - os << v; - what_ = "unknown database schema version "; - what_ += os.str (); - } - - unknown_schema_version:: - ~unknown_schema_version () ODB_NOTHROW_NOEXCEPT - { - } - - const char* unknown_schema_version:: - what () const ODB_NOTHROW_NOEXCEPT - { - return what_.c_str (); - } - - unknown_schema_version* unknown_schema_version:: - clone () const - { - return new unknown_schema_version (*this); - } - - const char* section_not_loaded:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "section is not loaded"; - } - - section_not_loaded* section_not_loaded:: - clone () const - { - return new section_not_loaded (*this); - } - - const char* section_not_in_object:: - what () const ODB_NOTHROW_NOEXCEPT - { - return "section instance is not part of an object (section was copied?)"; - } - - section_not_in_object* section_not_in_object:: - clone () const - { - return new section_not_in_object (*this); - } - - // multiple_exceptions - // - multiple_exceptions:: - ~multiple_exceptions () ODB_NOTHROW_NOEXCEPT {} - - void multiple_exceptions:: - insert (size_t p, bool maybe, const odb::exception& e, bool fatal) - { - details::shared_ptr pe; - - if (common_exception_ti_ != typeid (e)) - pe.reset (e.clone ()); - else - { - if (common_exception_ == 0) - common_exception_.reset (e.clone ()); - - pe = common_exception_; - } - - set_.insert (value_type (delta_ + p, maybe, pe)); - fatal_ = fatal_ || fatal; - } - - const multiple_exceptions::value_type* multiple_exceptions:: - lookup (size_t p) const - { - p += delta_; // Called while populating multiple_exceptions. - - iterator i (set_.find (value_type (p))); - return i == set_.end () ? 0 : &*i; - } - - void multiple_exceptions:: - prepare () - { - current_ = 0; - delta_ = 0; - common_exception_.reset (); - - ostringstream os; - os << "multiple exceptions, " - << attempted_ << " element" << (attempted_ != 1 ? "s" : "") << - " attempted, " - << failed () << " failed" - << (fatal_ ? ", fatal" : "") << ":"; - - for (iterator i (begin ()); i != end ();) - { - size_t p (i->position ()); - const odb::exception& e (i->exception ()); - - os << '\n'; - - if (!i->maybe ()) - { - os << '[' << p << ']'; - ++i; - } - else - { - // In this case we will normally have a large number of maybe - // failures in a row (usually the whole batch). So let's try - // to represent them all as a single range. - // - size_t n (0); - for (++i; i != end () && i->maybe (); ++i) - { - assert (&e == &i->exception ()); // The same common exception. - n++; - } - - if (n == 0) - os << '[' << p << ']'; - else - os << '[' << p << '-' << (p + n) << "] (some)"; - } - - os << ' ' << e.what (); - } - - what_ = os.str (); - } - - const char* multiple_exceptions:: - what () const ODB_NOTHROW_NOEXCEPT - { - return what_.c_str (); - } - - multiple_exceptions* multiple_exceptions:: - clone () const - { - return new multiple_exceptions (*this); - } -} diff --git a/odb/exceptions.hxx b/odb/exceptions.hxx deleted file mode 100644 index d283010..0000000 --- a/odb/exceptions.hxx +++ /dev/null @@ -1,523 +0,0 @@ -// file : odb/exceptions.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_EXCEPTIONS_HXX -#define ODB_EXCEPTIONS_HXX - -#include - -#include -#include -#include // std::size_t -#include - -#include // schema_version, odb::core -#include - -#include // ODB_NOTHROW_NOEXCEPT -#include -#include - -namespace odb -{ - struct LIBODB_EXPORT null_pointer: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual null_pointer* - clone () const; - }; - - // Transaction exceptions. - // - struct LIBODB_EXPORT already_in_transaction: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual already_in_transaction* - clone () const; - }; - - struct LIBODB_EXPORT not_in_transaction: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual not_in_transaction* - clone () const; - }; - - struct LIBODB_EXPORT transaction_already_finalized: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual transaction_already_finalized* - clone () const; - }; - - // Session exceptions. - // - struct LIBODB_EXPORT already_in_session: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual already_in_session* - clone () const; - }; - - struct LIBODB_EXPORT not_in_session: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual not_in_session* - clone () const; - }; - - struct LIBODB_EXPORT session_required: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual session_required* - clone () const; - }; - - // Database operations exceptions. - // - struct LIBODB_EXPORT recoverable: odb::exception - { - // Abstract. - }; - - struct LIBODB_EXPORT connection_lost: recoverable - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual connection_lost* - clone () const; - }; - - struct LIBODB_EXPORT timeout: recoverable - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual timeout* - clone () const; - }; - - struct LIBODB_EXPORT deadlock: recoverable - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual deadlock* - clone () const; - }; - - struct LIBODB_EXPORT object_not_persistent: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual object_not_persistent* - clone () const; - }; - - struct LIBODB_EXPORT object_already_persistent: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual object_already_persistent* - clone () const; - }; - - struct LIBODB_EXPORT object_changed: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual object_changed* - clone () const; - }; - - struct LIBODB_EXPORT result_not_cached: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual result_not_cached* - clone () const; - }; - - struct LIBODB_EXPORT database_exception: odb::exception - { - // Abstract. - }; - - // Polymorphism support exceptions. - // - struct LIBODB_EXPORT abstract_class: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual abstract_class* - clone () const; - }; - - struct LIBODB_EXPORT no_type_info: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual no_type_info* - clone () const; - }; - - // Prepared query support exceptions. - // - struct LIBODB_EXPORT prepared_already_cached: odb::exception - { - prepared_already_cached (const char* name); - ~prepared_already_cached () ODB_NOTHROW_NOEXCEPT; - - const char* - name () const - { - return name_; - } - - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual prepared_already_cached* - clone () const; - - private: - const char* name_; - std::string what_; - }; - - struct LIBODB_EXPORT prepared_type_mismatch: odb::exception - { - prepared_type_mismatch (const char* name); - ~prepared_type_mismatch () ODB_NOTHROW_NOEXCEPT; - - const char* - name () const {return name_;} - - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual prepared_type_mismatch* - clone () const; - - private: - const char* name_; - std::string what_; - }; - - // Schema catalog exceptions. - // - struct LIBODB_EXPORT unknown_schema: odb::exception - { - unknown_schema (const std::string& name); - ~unknown_schema () ODB_NOTHROW_NOEXCEPT; - - const std::string& - name () const {return name_;} - - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual unknown_schema* - clone () const; - - private: - std::string name_; - std::string what_; - }; - - struct LIBODB_EXPORT unknown_schema_version: odb::exception - { - unknown_schema_version (schema_version); - ~unknown_schema_version () ODB_NOTHROW_NOEXCEPT; - - schema_version - version () const {return version_;} - - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual unknown_schema_version* - clone () const; - - private: - schema_version version_; - std::string what_; - }; - - // Section exceptions. - // - struct LIBODB_EXPORT section_not_loaded: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual section_not_loaded* - clone () const; - }; - - struct LIBODB_EXPORT section_not_in_object: odb::exception - { - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual section_not_in_object* - clone () const; - }; - - // Bulk operation exceptions. - // - struct LIBODB_EXPORT multiple_exceptions: odb::exception - { - struct value_type - { - std::size_t - position () const {return p_;} - - // If true, then this means that some positions in the batch have - // triggered the exception but it is not possible, due to the - // limitations of the underlying database API, to discern exactly - // which ones. As a result, all the positions in the batch are - // marked as "maybe failed". - // - bool - maybe () const {return m_;} - - const odb::exception& - exception () const {return *e_;} - - // Implementation details. - // - public: - value_type (std::size_t p, - bool maybe, - details::shared_ptr e) - : m_ (maybe), p_ (p), e_ (e) {} - - value_type (std::size_t p): p_ (p) {} // "Key" for set lookup. - - private: - bool m_; - std::size_t p_; - details::shared_ptr e_; - }; - - struct comparator_type - { - bool - operator() (const value_type& x, const value_type& y) const - { - return x.position () < y.position (); - } - }; - - typedef std::set set_type; - - // Iteration. - // - public: - typedef set_type::const_iterator iterator; - typedef set_type::const_iterator const_iterator; // For pedantic types. - - iterator - begin () const {return set_.begin ();} - - iterator - end () const {return set_.end ();} - - // Lookup. - // - public: - // Return NULL if the element at this position has no exception. Note - // that the returned value is value_type* and not odb::exception* in - // order to provide access to maybe(); see value_type::maybe() for - // details. - // - const value_type* - operator[] (std::size_t p) const - { - return set_.empty () ? 0 : lookup (p); - } - - // Severity, failed and attempt counts. - // - public: - // Return the number of elements for which the operation has been - // attempted. - // - std::size_t - attempted () const {return attempted_;} - - // Return the number of positions for which the operation has failed. - // Note that this count includes the maybe failed positions. - // - std::size_t - failed () const {return set_.size ();} - - // If fatal() returns true, then (some of) the exceptions were fatal. - // In this case, even for elements that were processed but did not - // cause the exception, no attempts were made to complete the bulk - // operation and the transaction must be aborted. - // - // If fatal() returns false, then the operation on the elements that - // don't have an exception has succeeded. The application can try to - // correct the errors and re-attempt the operation on the elements - // that did cause an exception. In either case, the transaction can - // be committed. - // - bool - fatal () const {return fatal_;} - - // Normally you shouldn't need to do this explicitly but you can - // "upgrade" an exception to fatal, for example, for specific - // database error codes. - // - void - fatal (bool f) {fatal_ = fatal_ || f;} - - // odb::exception interface. - // - public: - virtual const char* - what () const ODB_NOTHROW_NOEXCEPT; - - virtual multiple_exceptions* - clone () const; - - // Direct set access. - // - public: - const set_type& - set () const {return set_;} - - // Implementation details. - // - public: - ~multiple_exceptions () ODB_NOTHROW_NOEXCEPT; - - // All instances of the common exception must be equal since we are - // going to create and share just one. - // - multiple_exceptions (const std::type_info& common_exception_ti) - : common_exception_ti_ (common_exception_ti), - fatal_ (false), - delta_ (0), - current_ (0) {} - - // Set the attempted count as (delta + n). - // - void - attempted (std::size_t n) {attempted_ = delta_ + n;} - - // Increment the position of the current batch. Also resets the - // current position in the batch. - // - void - delta (std::size_t d) {delta_ += d; current_ = 0;} - - // Current position in the batch. - // - std::size_t - current () const {return current_;} - - void - current (std::size_t c) {current_ = c;} - - void - insert (std::size_t p, - bool maybe, - const odb::exception& e, - bool fatal = false); - - void - insert (std::size_t p, const odb::exception& e, bool fatal = false) - { - insert (p, false, e, fatal); - } - - void - insert (const odb::exception& e, bool fatal = false) - { - insert (current_, e, fatal); - } - - bool - empty () const {return set_.empty ();} - - void - prepare (); - - private: - const value_type* - lookup (std::size_t p) const; - - private: - const std::type_info& common_exception_ti_; - details::shared_ptr common_exception_; - - set_type set_; - bool fatal_; - std::size_t attempted_; - std::size_t delta_; // Position of the batch. - std::size_t current_; // Position in the batch. - std::string what_; - }; - - namespace common - { - using odb::null_pointer; - - using odb::already_in_transaction; - using odb::not_in_transaction; - using odb::transaction_already_finalized; - - using odb::already_in_session; - using odb::not_in_session; - using odb::session_required; - - using odb::recoverable; - using odb::deadlock; - using odb::connection_lost; - using odb::timeout; - using odb::object_not_persistent; - using odb::object_already_persistent; - using odb::object_changed; - using odb::result_not_cached; - using odb::database_exception; - - using odb::abstract_class; - using odb::no_type_info; - - using odb::unknown_schema; - using odb::unknown_schema_version; - - using odb::section_not_loaded; - using odb::section_not_in_object; - - using odb::multiple_exceptions; - } -} - -#include - -#endif // ODB_EXCEPTIONS_HXX diff --git a/odb/forward.hxx b/odb/forward.hxx deleted file mode 100644 index 6f1176d..0000000 --- a/odb/forward.hxx +++ /dev/null @@ -1,178 +0,0 @@ -// file : odb/forward.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_FORWARD_HXX -#define ODB_FORWARD_HXX - -#include - -#include // std::size_t - -#include -#include - -namespace odb -{ - // Common and core namespaces. The idea is that you can use the - // using directive to get database-independent (common) names or - // all core names (core). - // - namespace common {} - - namespace core - { - using namespace common; - } - - // - // - typedef unsigned long long schema_version; - struct schema_version_migration; - - class database; - class connection; - typedef details::shared_ptr connection_ptr; - class transaction; - class statement; - class session; - class section; - template class result; - - namespace common - { - using odb::schema_version; - using odb::schema_version_migration; - using odb::session; - using odb::section; - using odb::result; - } - - namespace core - { - using odb::database; - using odb::connection; - using odb::connection_ptr; - using odb::transaction; - using odb::statement; - } - - // Tracing. - // - class tracer; // Not in core. - extern LIBODB_EXPORT tracer& stderr_tracer; - extern LIBODB_EXPORT tracer& stderr_full_tracer; - - namespace common - { - using odb::stderr_tracer; - } - - // Implementation details. - // - - // Keep real databases first since their enumerators are used as array - // indexes. - // - enum database_id - { - id_mysql, - id_sqlite, - id_pgsql, - id_oracle, - id_mssql, - id_common - }; - - // Number of real databases (i.e., excluding default) in the database_id - // enum. - // - const std::size_t database_count = id_common; - - // Traits. - // - class access - { - public: - template - class object_traits; - - template - class object_traits_impl; - - template - class object_factory; - - template - class view_traits; - - template - class view_traits_impl; - - template - class view_factory; - - template - class pointer_factory; - - template - class composite_value_traits; - - template - class container_traits; - }; - - template - struct object_traits; - - template - struct object_traits_impl; - - template - struct view_traits; - - template - struct view_traits_impl; - - // Cache traits. - // - template struct no_id_pointer_cache_traits; - template struct no_op_pointer_cache_traits; - template struct pointer_cache_traits; - template struct no_id_reference_cache_traits; - template struct no_op_reference_cache_traits; - template struct reference_cache_traits; - - // - // - class query_base; - - template - struct query_column; - - // - // - class result_impl; - class prepared_query_impl; - - // - // - struct multiple_exceptions; - - // Polymorphism support. - // - template - struct polymorphic_map; - - namespace details - { - template <> - struct counter_type - { - typedef shared_base counter; - }; - } -} - -#include - -#endif // ODB_FORWARD_HXX diff --git a/odb/function-table.hxx b/odb/function-table.hxx deleted file mode 100644 index b1a5a94..0000000 --- a/odb/function-table.hxx +++ /dev/null @@ -1,50 +0,0 @@ -// file : odb/function-table.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_FUNCTION_TABLE_HXX -#define ODB_FUNCTION_TABLE_HXX - -#include - -#include - -namespace odb -{ - template - struct object_function_table_entry - { - typedef access::object_traits_impl common_traits; - - object_function_table_entry ( - const typename common_traits::function_table_type* t) - { - common_traits::function_table[DB] = t; - } - - ~object_function_table_entry () - { - common_traits::function_table[DB] = 0; - } - }; - - template - struct view_function_table_entry - { - typedef access::view_traits_impl common_traits; - - view_function_table_entry ( - const typename common_traits::function_table_type* t) - { - common_traits::function_table[DB] = t; - } - - ~view_function_table_entry () - { - common_traits::function_table[DB] = 0; - } - }; -} - -#include - -#endif // ODB_FUNCTION_TABLE_HXX diff --git a/odb/lazy-pointer-traits.hxx b/odb/lazy-pointer-traits.hxx deleted file mode 100644 index 2a6c8eb..0000000 --- a/odb/lazy-pointer-traits.hxx +++ /dev/null @@ -1,141 +0,0 @@ -// file : odb/lazy-pointer-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_LAZY_POINTER_TRAITS_HXX -#define ODB_LAZY_POINTER_TRAITS_HXX - -#include - -#include -#include -#include // ODB_CXX11 - -namespace odb -{ - template - class pointer_traits< lazy_ptr > - { - public: - static const pointer_kind kind = pk_raw; - static const bool lazy = true; - - typedef T element_type; - typedef lazy_ptr pointer_type; - typedef element_type* eager_pointer_type; - - static bool - null_ptr (const pointer_type& p) - { - return !p; - } - - template - static typename object_traits::id_type - object_id (const pointer_type& p) - { - return p.template object_id (); - } - }; - -#ifndef ODB_CXX11 - template - class pointer_traits< lazy_auto_ptr > - { - public: - static const pointer_kind kind = pk_unique; - static const bool lazy = true; - - typedef T element_type; - typedef lazy_auto_ptr pointer_type; - typedef std::auto_ptr eager_pointer_type; - - static bool - null_ptr (const pointer_type& p) - { - return !p; - } - - template - static typename object_traits::id_type - object_id (const pointer_type& p) - { - return p.template object_id (); - } - }; -#endif - -#ifdef ODB_CXX11 - template - class pointer_traits> - { - public: - static const pointer_kind kind = pk_unique; - static const bool lazy = true; - - typedef T element_type; - typedef lazy_unique_ptr pointer_type; - typedef std::unique_ptr eager_pointer_type; - - static bool - null_ptr (const pointer_type& p) - { - return !p; - } - - template - static typename object_traits::id_type - object_id (const pointer_type& p) - { - return p.template object_id (); - } - }; - - template - class pointer_traits> - { - public: - static const pointer_kind kind = pk_shared; - static const bool lazy = true; - - typedef T element_type; - typedef lazy_shared_ptr pointer_type; - typedef std::shared_ptr eager_pointer_type; - - static bool - null_ptr (const pointer_type& p) - { - return !p; - } - - template - static typename object_traits::id_type - object_id (const pointer_type& p) - { - return p.template object_id (); - } - }; - - template - class pointer_traits> - { - public: - static const pointer_kind kind = pk_weak; - static const bool lazy = true; - - typedef T element_type; - typedef lazy_weak_ptr pointer_type; - typedef lazy_shared_ptr strong_pointer_type; - typedef std::weak_ptr eager_pointer_type; - - static strong_pointer_type - lock (const pointer_type& p) - { - return p.lock (); - } - }; -#endif // ODB_CXX11 -} - -#include - -#endif // ODB_LAZY_POINTER_TRAITS_HXX diff --git a/odb/lazy-ptr-impl.hxx b/odb/lazy-ptr-impl.hxx deleted file mode 100644 index 89fe798..0000000 --- a/odb/lazy-ptr-impl.hxx +++ /dev/null @@ -1,188 +0,0 @@ -// file : odb/lazy-ptr-impl.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_LAZY_PTR_IMPL_HXX -#define ODB_LAZY_PTR_IMPL_HXX - -#include - -#include // std::move - -#include // odb::database -#include - -#include // ODB_CXX11 - -namespace odb -{ - struct lazy_ptr_impl_ref - { - void* id_; - database* db_; - void* loader_; - void (*free_) (void*); - void* (*copy_) (const void*); - }; - - class lazy_ptr_base - { - public: - typedef odb::database database_type; - - ~lazy_ptr_base (); - lazy_ptr_base (); - lazy_ptr_base (const lazy_ptr_base&); - lazy_ptr_base (const lazy_ptr_impl_ref&); - - lazy_ptr_base& - operator= (const lazy_ptr_base&); - - lazy_ptr_base& - operator= (const lazy_ptr_impl_ref&); - - // C++11 support. - // - public: -#ifdef ODB_CXX11 - lazy_ptr_base (lazy_ptr_base&&) noexcept; - - lazy_ptr_base& - operator= (lazy_ptr_base&&) noexcept; -#endif - - public: - // Reset both the id and database. - // - void - reset (); - - // Reset the id. - // - void - reset_id (); - - void - swap (lazy_ptr_base&); - - database_type* - database () const; - - typedef void* lazy_ptr_base::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return db_ != 0 ? &lazy_ptr_base::id_ : 0; - } - - operator lazy_ptr_impl_ref (); - - protected: - typedef void (*free_func) (void*); - typedef void* (*copy_func) (const void*); - - // Makes a copy of id. - // - void - reset_ (database_type*, - void* loader, - const void* id, - free_func, copy_func); - - template - static void - free (void*); - - template - static void* - copy (const void*); - - template - static typename object_traits::pointer_type - loader (database_type&, const typename object_traits::id_type&); - - protected: - void* id_; - database_type* db_; - void* loader_; - - private: - free_func free_; - copy_func copy_; - }; - - template - class lazy_ptr_impl: public lazy_ptr_base - { - public: - lazy_ptr_impl (); - - template - lazy_ptr_impl (DB&, const ID&); - - lazy_ptr_impl (const lazy_ptr_impl&); - - template - lazy_ptr_impl (const lazy_ptr_impl&); - - lazy_ptr_impl (const lazy_ptr_impl_ref&); - - lazy_ptr_impl& - operator= (const lazy_ptr_impl&); - - template - lazy_ptr_impl& - operator= (const lazy_ptr_impl&); - - lazy_ptr_impl& - operator= (const lazy_ptr_impl_ref&); - - // C++11 support. - // - public: -#ifdef ODB_CXX11 - lazy_ptr_impl (lazy_ptr_impl&&) noexcept; - - template - lazy_ptr_impl (lazy_ptr_impl&&); - - lazy_ptr_impl& - operator= (lazy_ptr_impl&&) noexcept; - - template - lazy_ptr_impl& - operator= (lazy_ptr_impl&&); -#endif - - public: - using lazy_ptr_base::reset; - using lazy_ptr_base::reset_id; - - template - void - reset (DB&, const ID&); - - // Reset the id and set the database to the new value. - // - template - void - reset_db (DB&); - - template - void - reset_id (const ID&); - - template - typename object_traits::pointer_type - load (bool reset_id); - - template - typename object_traits::id_type - object_id () const; - }; -} - -#include -#include - -#include - -#endif // ODB_LAZY_PTR_IMPL_HXX diff --git a/odb/lazy-ptr-impl.ixx b/odb/lazy-ptr-impl.ixx deleted file mode 100644 index 9ab0471..0000000 --- a/odb/lazy-ptr-impl.ixx +++ /dev/null @@ -1,397 +0,0 @@ -// file : odb/lazy-ptr-impl.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // lazy_ptr_base - // - - inline lazy_ptr_base:: - lazy_ptr_base () - : id_ (0), db_ (0), loader_ (0), free_ (0), copy_ (0) - { - } - - inline lazy_ptr_base:: - lazy_ptr_base (const lazy_ptr_base& r) - : id_ (0), db_ (r.db_), loader_ (r.loader_), - free_ (r.free_), copy_ (r.copy_) - { - if (r.id_) - id_ = copy_ (r.id_); - } - - inline lazy_ptr_base:: - lazy_ptr_base (const lazy_ptr_impl_ref& r) - : id_ (r.id_), db_ (r.db_), loader_ (r.loader_), - free_ (r.free_), copy_ (r.copy_) - { - } - -#ifdef ODB_CXX11 - inline lazy_ptr_base:: - lazy_ptr_base (lazy_ptr_base&& r) noexcept - : id_ (r.id_), db_ (r.db_), loader_ (r.loader_), - free_ (r.free_), copy_ (r.copy_) - { - r.id_ = 0; - } -#endif - - inline void lazy_ptr_base:: - reset_id () - { - if (id_) - free_ (id_); - - id_ = 0; - } - - inline void lazy_ptr_base:: - reset_ (database_type* db, - void* loader, - const void* id, - free_func free, - copy_func copy) - { - void* idc (id ? copy (id) : 0); - - if (id_) - free_ (id_); - - free_ = free; - copy_ = copy; - - id_ = idc; - db_ = db; - loader_ = loader; - } - - inline void lazy_ptr_base:: - reset () - { - reset_id (); - db_ = 0; - loader_ = 0; - } - -#ifdef ODB_CXX11 - inline lazy_ptr_base& lazy_ptr_base:: - operator= (lazy_ptr_base&& r) noexcept - { - if (id_ != r.id_) - { - reset_id (); - id_ = r.id_; - free_ = r.free_; - copy_ = r.copy_; - - r.id_ = 0; - } - - db_ = r.db_; - loader_ = r.loader_; - return *this; - } -#endif - - inline lazy_ptr_base& lazy_ptr_base:: - operator= (const lazy_ptr_base& r) - { - if (id_ != r.id_) - reset_ (r.db_, r.loader_, r.id_, r.free_, r.copy_); - else - { - db_ = r.db_; - loader_ = r.loader_; - } - - return *this; - } - - inline lazy_ptr_base& lazy_ptr_base:: - operator= (const lazy_ptr_impl_ref& r) - { - if (id_ != r.id_) - { - reset_id (); - id_ = r.id_; - free_ = r.free_; - copy_ = r.copy_; - } - - db_ = r.db_; - loader_ = r.loader_; - return *this; - } - - inline lazy_ptr_base:: - ~lazy_ptr_base () - { - if (id_) - free_ (id_); - } - - inline void lazy_ptr_base:: - swap (lazy_ptr_base& r) - { - void* id (id_); - database_type* db (db_); - void* l (loader_); - free_func f (free_); - copy_func c (copy_); - - id_ = r.id_; - db_ = r.db_; - loader_ = r.loader_; - free_ = r.free_; - copy_ = r.copy_; - - r.id_ = id; - r.db_ = db; - r.loader_ = l; - r.free_ = f; - r.copy_ = c; - } - - inline lazy_ptr_base::database_type* lazy_ptr_base:: - database () const - { - return db_; - } - - inline lazy_ptr_base:: - operator lazy_ptr_impl_ref () - { - lazy_ptr_impl_ref r; - r.id_ = id_; - r.db_ = db_; - r.loader_ = loader_; - r.free_ = free_; - r.copy_ = copy_; - id_ = 0; - db_ = 0; - loader_ = 0; - return r; - } - - // - // lazy_ptr_impl - // - - template - inline lazy_ptr_impl:: - lazy_ptr_impl () - { - } - - template - template - inline lazy_ptr_impl:: - lazy_ptr_impl (DB& db, const ID& id) - { - typedef typename object_traits::id_type id_type; - typedef typename object_traits::pointer_type pointer_type; - typedef pointer_type (*loader_type) (database_type&, const id_type&); - - // Make sure that ID and T's object id types are the same - // (or implicit-convertible). If you get a compile error - // pointing here, then you most likely used a wrong object - // id argument in the constructor call. - // - const id_type& r (id); - - // Compiler error pointing here? Perhaps db is not an - // odb::::database instance? - // - database_type& bdb (db); - - // For some reason GCC needs this statically-typed pointer in - // order to instantiate the functions. - // - loader_type ldr (&loader); - - reset_ (&bdb, - reinterpret_cast (ldr), - &r, - &free, - ©); - } - - template - inline lazy_ptr_impl:: - lazy_ptr_impl (const lazy_ptr_impl& r) - : lazy_ptr_base (r) - { - } - - template - template - inline lazy_ptr_impl:: - lazy_ptr_impl (const lazy_ptr_impl& r) - : lazy_ptr_base (r) - { - } - - template - inline lazy_ptr_impl:: - lazy_ptr_impl (const lazy_ptr_impl_ref& r) - : lazy_ptr_base (r) - { - } - - template - inline lazy_ptr_impl& lazy_ptr_impl:: - operator= (const lazy_ptr_impl& r) - { - lazy_ptr_base& b (*this); - b = r; - return *this; - } - - template - template - inline lazy_ptr_impl& lazy_ptr_impl:: - operator= (const lazy_ptr_impl& r) - { - lazy_ptr_base& b (*this); - b = r; - return *this; - } - - template - inline lazy_ptr_impl& lazy_ptr_impl:: - operator= (const lazy_ptr_impl_ref& r) - { - lazy_ptr_base& b (*this); - b = r; - return *this; - } - -#ifdef ODB_CXX11 - template - inline lazy_ptr_impl:: - lazy_ptr_impl (lazy_ptr_impl&& r) noexcept - : lazy_ptr_base (std::move (r)) - { - } - - template - template - inline lazy_ptr_impl:: - lazy_ptr_impl (lazy_ptr_impl&& r) - : lazy_ptr_base (std::move (r)) - { - } - - template - inline lazy_ptr_impl& lazy_ptr_impl:: - operator= (lazy_ptr_impl&& r) noexcept - { - lazy_ptr_base& b (*this); - b = std::move (r); - return *this; - } - - template - template - inline lazy_ptr_impl& lazy_ptr_impl:: - operator= (lazy_ptr_impl&& r) - { - lazy_ptr_base& b (*this); - b = std::move (r); - return *this; - } -#endif - - template - template - inline void lazy_ptr_impl:: - reset (DB& db, const ID& id) - { - typedef typename object_traits::id_type id_type; - typedef typename object_traits::pointer_type pointer_type; - typedef pointer_type (*loader_type) (database_type&, const id_type&); - - // Make sure that ID and T's object id types are the same - // (or implicit-convertible). If you get a compile error - // pointing here, then you most likely used a wrong object - // id argument in the constructor call. - // - const id_type& r (id); - - // Compiler error pointing here? Perhaps db is not an - // odb::::database instance? - // - database_type& bdb (db); - - // For some reason GCC needs this statically-typed pointer in - // order to instantiate the functions. - // - loader_type ldr (&loader); - - reset_ (&bdb, - reinterpret_cast (ldr), - &r, - &free, - ©); - } - - template - template - inline void lazy_ptr_impl:: - reset_db (DB& db) - { - typedef typename object_traits::id_type id_type; - typedef typename object_traits::pointer_type pointer_type; - typedef pointer_type (*loader_type) (database_type&, const id_type&); - - reset_id (); - - // Compiler error pointing here? Perhaps db is not an - // odb::::database instance? - // - db_ = &db; - - // For some reason GCC needs this statically-typed pointer in - // order to instantiate the functions. - // - loader_type ldr (&loader); - loader_ = reinterpret_cast (ldr); - } - - template - template - inline void lazy_ptr_impl:: - reset_id (const ID& id) - { - typedef typename object_traits::id_type id_type; - - // Make sure that ID and T's object id types are the same - // (or implicit-convertible). If you get a compile error - // pointing here, then you most likely used a wrong object - // id argument in the constructor call. - // - const id_type& r (id); - - reset_ (db_, loader_, &r, &free, ©); - } - - template - template - inline typename object_traits::id_type lazy_ptr_impl:: - object_id () const - { - typedef typename object_traits::id_type id_type; - const id_type& id (*static_cast (id_)); - - // Make sure that O' and T's object id types are the same - // (or implicit-convertible). If you get a compile error - // pointing here, then you most likely used a wrong type - // as a template argument in the object_id() call. - // - const typename object_traits::id_type& r (id); - return r; - } -} diff --git a/odb/lazy-ptr-impl.txx b/odb/lazy-ptr-impl.txx deleted file mode 100644 index 7aea9c3..0000000 --- a/odb/lazy-ptr-impl.txx +++ /dev/null @@ -1,60 +0,0 @@ -// file : odb/lazy-ptr-impl.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // lazy_ptr_base - // - - template - void lazy_ptr_base:: - free (void* p) - { - delete static_cast (p); - } - - template - void* lazy_ptr_base:: - copy (const void* p) - { - return new T (*static_cast (p)); - } - - template - typename object_traits::pointer_type lazy_ptr_base:: - loader (database_type& db, const typename object_traits::id_type& id) - { - // Compiler error pointing here? Perhaps you did not include - // ? - // - return static_cast (db).template load< - typename object_traits::object_type> (id); - } - - // - // lazy_ptr_impl - // - - template - template - inline typename object_traits::pointer_type lazy_ptr_impl:: - load (bool reset) - { - typedef typename object_traits::id_type id_type; - typedef typename object_traits::pointer_type pointer_type; - typedef pointer_type (*loader_type) (database_type&, const id_type&); - - loader_type loader (reinterpret_cast (loader_)); - const id_type& id (*static_cast (id_)); - pointer_type p (loader (*db_, id)); - - if (reset) - reset_id (); - - // If you get a compile error pointing here, then you most likely - // used a wrong type as a template argument in the load() call. - // - return p; - } -} diff --git a/odb/lazy-ptr.hxx b/odb/lazy-ptr.hxx deleted file mode 100644 index ab31dfc..0000000 --- a/odb/lazy-ptr.hxx +++ /dev/null @@ -1,681 +0,0 @@ -// file : odb/lazy-ptr.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_LAZY_PTR_HXX -#define ODB_LAZY_PTR_HXX - -#include - -#include // std::auto_ptr, std::shared_ptr/weak_ptr -#include // std::move - -#include // odb::core, odb::database -#include -#include -#include // ODB_CXX11 - -namespace odb -{ - // Raw pointer lazy version. - // - template - class lazy_ptr - { - // Pointer interface. - // - public: - typedef T element_type; - - lazy_ptr (); - template lazy_ptr (Y*); - - lazy_ptr (const lazy_ptr&); - template lazy_ptr (const lazy_ptr&); - - lazy_ptr& operator= (const lazy_ptr&); - template lazy_ptr& operator= (Y*); - template lazy_ptr& operator= (const lazy_ptr&); - - void swap (lazy_ptr&); - void reset (); - template void reset (Y*); - - T& operator* () const; - T* operator-> () const; - T* get () const; - - typedef T* lazy_ptr::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return (p_ || i_) ? &lazy_ptr::p_ : 0; - } - - // Lazy loading interface. - // - public: - typedef odb::database database_type; - - // NULL loaded() - // - // true true NULL pointer to transient object - // false true valid pointer to persistent object - // true false unloaded pointer to persistent object - // false false valid pointer to transient object - // - bool loaded () const; - - T* load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - T* get_eager () const; - - template lazy_ptr (DB&, const ID&); - template lazy_ptr (DB&, Y*); - - template void reset (DB&, const ID&); - template void reset (DB&, Y*); - -#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT - template -#else - template -#endif - typename object_traits::id_type object_id () const; - - database_type& database () const; - - // Helpers. - // - public: - template bool equal (const lazy_ptr&) const; - - private: - template friend class lazy_ptr; - - mutable T* p_; - mutable lazy_ptr_impl i_; - }; - - // operator< and operator<< are not provided. - // - template - bool operator== (const lazy_ptr&, const lazy_ptr&); - - template - bool operator!= (const lazy_ptr&, const lazy_ptr&); - - template void swap (lazy_ptr&, lazy_ptr&); - - // std::auto_ptr lazy version. - // -#ifndef ODB_CXX11 - template - struct lazy_auto_ptr_ref - { - explicit lazy_auto_ptr_ref (T*, const lazy_ptr_impl_ref&); - - T* p_; - lazy_ptr_impl_ref i_; - }; - - template - class lazy_auto_ptr - { - // Standard auto_ptr interface. - // - public: - typedef T element_type; - - explicit lazy_auto_ptr (T* = 0); - lazy_auto_ptr (lazy_auto_ptr&); - template lazy_auto_ptr (lazy_auto_ptr&); - - lazy_auto_ptr& operator= (lazy_auto_ptr&); - template lazy_auto_ptr& operator= (lazy_auto_ptr&); - - T& operator* () const; - T* operator-> () const; - T* get () const; - T* release (); - void reset (T* = 0); - - lazy_auto_ptr (const lazy_auto_ptr_ref&); - lazy_auto_ptr& operator= (const lazy_auto_ptr_ref&); - template operator lazy_auto_ptr_ref (); - template operator lazy_auto_ptr (); - - // Extension: conversion to bool. - // - public: - typedef std::auto_ptr lazy_auto_ptr::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return (p_.get () != 0 || i_) ? &lazy_auto_ptr::p_ : 0; - } - - // Initialization/assignment from auto_ptr. - // - public: - template lazy_auto_ptr (std::auto_ptr&); - lazy_auto_ptr (std::auto_ptr_ref); - - template lazy_auto_ptr& operator= (std::auto_ptr&); - lazy_auto_ptr& operator= (std::auto_ptr_ref); - - // Lazy loading interface. - // - public: - typedef odb::database database_type; - - // NULL loaded() - // - // true true NULL pointer to transient object - // false true valid pointer to persistent object - // true false unloaded pointer to persistent object - // false false valid pointer to transient object - // - bool loaded () const; - - std::auto_ptr& load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - std::auto_ptr& get_eager () const; - - template lazy_auto_ptr (DB&, const ID&); - template lazy_auto_ptr (DB&, T*); - template lazy_auto_ptr (DB&, std::auto_ptr&); - - template void reset (DB&, const ID&); - template void reset (DB&, T*); - template void reset (DB&, std::auto_ptr&); - - template - typename object_traits::id_type object_id () const; - - database_type& database () const; - - private: - template friend class lazy_auto_ptr; - - // Note that it is possible to have a situation where p_ is NULL, - // i_.id is NULL and i_.db is not NULL. This will happen if the - // auto_ptr reference returned by load() is transferred to another - // pointer or reset. - // - mutable std::auto_ptr p_; - mutable lazy_ptr_impl i_; - }; -#endif - -#ifdef ODB_CXX11 - - // C++11 std::unique_ptr lazy version. - // - template > - class lazy_unique_ptr - { - // Standard lazy_unique_ptr interface. - // - public: - typedef T* pointer; // For now assume it is T*. - typedef T element_type; - typedef D deleter_type; - - /*constexpr*/ lazy_unique_ptr () /*noexcept*/; -#ifdef ODB_CXX11_NULLPTR - /*constexpr*/ lazy_unique_ptr (std::nullptr_t) /*noexcept*/; -#endif - explicit lazy_unique_ptr (pointer) /*noexcept*/; - - // For now assume D is non-reference. - // - lazy_unique_ptr (pointer, const deleter_type&) /*noexcept*/; - lazy_unique_ptr (pointer, deleter_type&&) /*noexcept*/; - - lazy_unique_ptr (lazy_unique_ptr&&) noexcept; - template lazy_unique_ptr (lazy_unique_ptr&&) /*noexcept*/; - //template lazy_unique_ptr (std::auto_ptr&&) /*noexcept*/; - -#ifdef ODB_CXX11_NULLPTR - lazy_unique_ptr& operator= (std::nullptr_t) /*noexcept*/; -#endif - lazy_unique_ptr& operator= (lazy_unique_ptr&&) noexcept; - template lazy_unique_ptr& operator= (lazy_unique_ptr&&) /*noexcept*/; - - T& operator* () const; - pointer operator-> () const /*noexcept*/; - pointer get () const /*noexcept*/; -#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR - explicit operator bool() const /*noexcept*/; -#else - typedef std::unique_ptr lazy_unique_ptr::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return (p_ || i_) ? &lazy_unique_ptr::p_ : 0; - } -#endif - - pointer release () /*noexcept*/; - void reset (pointer = pointer ()) /*noexcept*/; - void swap (lazy_unique_ptr&) /*noexcept*/; - - deleter_type& get_deleter () /*noexcept*/; - const deleter_type& get_deleter () const /*noexcept*/; - -#ifdef ODB_CXX11_DELETED_FUNCTION - lazy_unique_ptr (const lazy_unique_ptr&) = delete; - lazy_unique_ptr& operator= (const lazy_unique_ptr&) = delete; -#else - private: - lazy_unique_ptr (const lazy_unique_ptr&); - lazy_unique_ptr& operator= (const lazy_unique_ptr&); -#endif - - // Initialization/assignment from unique_ptr. - // - public: - template lazy_unique_ptr (std::unique_ptr&&) /*noexcept*/; - template lazy_unique_ptr& operator= (std::unique_ptr&&) /*noexcept*/; - - // Lazy loading interface. - // - public: - typedef odb::database database_type; - - // NULL loaded() - // - // true true NULL pointer to transient object - // false true valid pointer to persistent object - // true false unloaded pointer to persistent object - // false false valid pointer to transient object - // - bool loaded () const; - - std::unique_ptr& load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - std::unique_ptr& get_eager () const; - - template lazy_unique_ptr (DB&, const ID&); - template lazy_unique_ptr (DB&, pointer); - template lazy_unique_ptr (DB&, pointer, const deleter_type&); - template lazy_unique_ptr (DB&, pointer, deleter_type&&); - template lazy_unique_ptr (DB&, std::unique_ptr&&); - //template lazy_unique_ptr (DB&, std::auto_ptr&&); - - template void reset (DB&, const ID&); - template void reset (DB&, pointer); - template void reset (DB&, std::unique_ptr&&); - //template void reset (DB&, std::auto_ptr&&); - -#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT - template -#else - template -#endif - typename object_traits::id_type object_id () const; - - database_type& database () const; - - // Helpers. - // - public: - template bool equal (const lazy_unique_ptr&) const; - - private: - template friend class lazy_unique_ptr; - - // Note that it is possible to have a situation where p_ is NULL, - // i_.id is NULL and i_.db is not NULL. This will happen if the - // unique_ptr reference returned by load() is transferred to - // another pointer or reset. - // - mutable std::unique_ptr p_; - mutable lazy_ptr_impl i_; - }; - - template void swap (lazy_unique_ptr&, lazy_unique_ptr&) /*noexcept*/; - - // operator< and operator<< are not provided. - // - template - bool operator== (const lazy_unique_ptr&, const lazy_unique_ptr&); - - template - bool operator!= (const lazy_unique_ptr&, const lazy_unique_ptr&); - -#ifdef ODB_CXX11_NULLPTR - template - bool operator== (const lazy_unique_ptr&, std::nullptr_t) /*noexcept*/; - - template - bool operator== (std::nullptr_t, const lazy_unique_ptr&) /*noexcept*/; - - template - bool operator!= (const lazy_unique_ptr&, std::nullptr_t) /*noexcept*/; - - template - bool operator!= (std::nullptr_t, const lazy_unique_ptr&) /*noexcept*/; -#endif - - // C++11 std::shared_ptr lazy version. - // - template - class lazy_weak_ptr; - - template - class lazy_shared_ptr - { - // The standard shared_ptr interface. - // - public: - typedef T element_type; - - /*constexpr*/ lazy_shared_ptr () /*noexcept*/; -#ifdef ODB_CXX11_NULLPTR - /*constexpr*/ lazy_shared_ptr (std::nullptr_t) /*noexcept*/; -#endif - template explicit lazy_shared_ptr (Y*); - template lazy_shared_ptr (Y*, D); - template lazy_shared_ptr (Y*, D, A); -#ifdef ODB_CXX11_NULLPTR - template lazy_shared_ptr (std::nullptr_t, D); - template lazy_shared_ptr (std::nullptr_t, D, A); -#endif - template lazy_shared_ptr (const lazy_shared_ptr&, T*) /*noexcept*/; - - lazy_shared_ptr (const lazy_shared_ptr&) /*noexcept*/; - template lazy_shared_ptr (const lazy_shared_ptr&) /*noexcept*/; - lazy_shared_ptr (lazy_shared_ptr&&) noexcept; - template lazy_shared_ptr (lazy_shared_ptr&&) /*noexcept*/; - template explicit lazy_shared_ptr (const lazy_weak_ptr&); - //template explicit lazy_shared_ptr (std::auto_ptr&&); - template lazy_shared_ptr (std::unique_ptr&&); - - ~lazy_shared_ptr (); - - lazy_shared_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; - template lazy_shared_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; - lazy_shared_ptr& operator= (lazy_shared_ptr&&) noexcept; - template lazy_shared_ptr& operator= (lazy_shared_ptr&&) /*noexcept*/; - //template lazy_shared_ptr& operator= (std::auto_ptr&&); - template lazy_shared_ptr& operator= (std::unique_ptr&&); - - void swap (lazy_shared_ptr&) /*noexcept*/; - void reset () /*noexcept*/; - template void reset (Y*); - template void reset (Y*, D); - template void reset (Y*, D, A); - - T* get () const /*noexcept*/; - T& operator* () const /*noexcept*/; - T* operator-> () const /*noexcept*/; - long use_count () const /*noexcept*/; - bool unique () const /*noexcept*/; -#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR - explicit operator bool () const /*noexcept*/; -#else - typedef std::shared_ptr lazy_shared_ptr::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return (p_ || i_) ? &lazy_shared_ptr::p_ : 0; - } -#endif - - // owner_before () is not provded. - - // Initialization/assignment from shared_ptr and weak_ptr. - // - public: - template lazy_shared_ptr (const std::shared_ptr&); - template lazy_shared_ptr (std::shared_ptr&&); - template explicit lazy_shared_ptr (const std::weak_ptr&); - - template lazy_shared_ptr& operator= (const std::shared_ptr&); - template lazy_shared_ptr& operator= (std::shared_ptr&&); - - // Lazy loading interface. - // - public: - typedef odb::database database_type; - - // NULL loaded() - // - // true true NULL pointer to transient object - // false true valid pointer to persistent object - // true false unloaded pointer to persistent object - // false false valid pointer to transient object - // - bool loaded () const; - - std::shared_ptr load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - std::shared_ptr get_eager () const; - - template lazy_shared_ptr (DB&, const ID&); - template lazy_shared_ptr (DB&, Y*); - template lazy_shared_ptr (DB&, Y*, D); - template lazy_shared_ptr (DB&, Y*, D, A); - //template lazy_shared_ptr (DB&, std::auto_ptr&&); - template lazy_shared_ptr (DB&, const std::shared_ptr&); - template lazy_shared_ptr (DB&, std::shared_ptr&&); - template lazy_shared_ptr (DB&, const std::weak_ptr&); - - template void reset (DB&, const ID&); - template void reset (DB&, Y*); - template void reset (DB&, Y*, D); - template void reset (DB&, Y*, D, A); - //template void reset (DB&, std::auto_ptr&&); - template void reset (DB&, const std::shared_ptr&); - template void reset (DB&, std::shared_ptr&&); - -#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT - template -#else - template -#endif - typename object_traits::id_type object_id () const; - - database_type& database () const; - - // Helpers. - // - public: - template bool equal (const lazy_shared_ptr&) const; - - private: - template friend class lazy_shared_ptr; - template friend class lazy_weak_ptr; - - // For lazy_weak_ptr::lock(). - // - lazy_shared_ptr (std::shared_ptr&& p, const lazy_ptr_impl& i) - : p_ (std::move (p)), i_ (i) {} - - private: - mutable std::shared_ptr p_; - mutable lazy_ptr_impl i_; - }; - - template void swap (lazy_shared_ptr&, lazy_shared_ptr&) /*noexcept*/; - - template - D* get_deleter (const lazy_shared_ptr&) /*noexcept*/; - - // operator< and operator<< are not provided. - // - template - bool operator== (const lazy_shared_ptr&, const lazy_shared_ptr&) /*noexcept*/; - - template - bool operator!= (const lazy_shared_ptr&, const lazy_shared_ptr&) /*noexcept*/; - -#ifdef ODB_CXX11_NULLPTR - template - bool operator== (const lazy_shared_ptr&, std::nullptr_t) /*noexcept*/; - - template - bool operator== (std::nullptr_t, const lazy_shared_ptr&) /*noexcept*/; - - template - bool operator!= (const lazy_shared_ptr&, std::nullptr_t) /*noexcept*/; - - template - bool operator!= (std::nullptr_t, const lazy_shared_ptr&) /*noexcept*/; -#endif - - // C++11 std::weak_ptr lazy version. - // - template - class lazy_weak_ptr - { - // The standard weak_ptr interface. - // - public: - typedef T element_type; - - /*constexpr*/ lazy_weak_ptr () /*noexcept*/; - template lazy_weak_ptr (const lazy_shared_ptr&) /*noexcept*/; - lazy_weak_ptr (const lazy_weak_ptr&) /*noexcept*/; - template lazy_weak_ptr (const lazy_weak_ptr&) /*noexcept*/; - - ~lazy_weak_ptr (); - - lazy_weak_ptr& operator= (const lazy_weak_ptr&) /*noexcept*/; - template lazy_weak_ptr& operator= (const lazy_weak_ptr&) /*noexcept*/; - template lazy_weak_ptr& operator= (const lazy_shared_ptr&) /*noexcept*/; - - void swap (lazy_weak_ptr&) /*noexcept*/; - void reset () /*noexcept*/; - - long use_count () const /*noexcept*/; - bool expired () const /*noexcept*/; - - lazy_shared_ptr lock () const /*noexcept*/; - - // owner_before () is not provded. - - // Initialization/assignment from shared_ptr and weak_ptr. - // - public: - template lazy_weak_ptr (const std::weak_ptr&); - template lazy_weak_ptr (const std::shared_ptr&); - - template lazy_weak_ptr& operator= (const std::weak_ptr&); - template lazy_weak_ptr& operator= (const std::shared_ptr&); - - // 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 transient object - // - bool loaded () const; - - // Performs both lock and load. - // - std::shared_ptr load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - std::weak_ptr get_eager () const; - - template lazy_weak_ptr (DB&, const ID&); - template lazy_weak_ptr (DB&, const std::shared_ptr&); - template lazy_weak_ptr (DB&, const std::weak_ptr&); - - template void reset (DB&, const ID&); - template void reset (DB&, const std::shared_ptr&); - template void reset (DB&, const std::weak_ptr&); - - // The object_id() function can only be called when the object is - // persistent, or: expired() XOR loaded() (can use != for XOR). - // -#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT - template -#else - template -#endif - typename object_traits::id_type object_id () const; - - database_type& database () const; - - private: - template friend class lazy_shared_ptr; - template friend class lazy_weak_ptr; - - mutable std::weak_ptr p_; - mutable lazy_ptr_impl i_; - }; - - // operator< is not provided. - // - template void swap (lazy_weak_ptr&, lazy_weak_ptr&); - -#endif // ODB_CXX11 - - namespace common - { - using odb::lazy_ptr; - -#ifndef ODB_CXX11 - using odb::lazy_auto_ptr; -#endif - -#ifdef ODB_CXX11 - using odb::lazy_unique_ptr; - using odb::lazy_shared_ptr; - using odb::lazy_weak_ptr; -#endif - } -} - -#include -#include - -#include - -#include - -#endif // ODB_LAZY_PTR_HXX diff --git a/odb/lazy-ptr.ixx b/odb/lazy-ptr.ixx deleted file mode 100644 index a2d72f5..0000000 --- a/odb/lazy-ptr.ixx +++ /dev/null @@ -1,1681 +0,0 @@ -// file : odb/lazy-ptr.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // lazy_ptr - // - - template - inline lazy_ptr:: - lazy_ptr (): p_ (0) {} - - template - template - inline lazy_ptr:: - lazy_ptr (Y* p): p_ (p) {} - - template - inline lazy_ptr:: - lazy_ptr (const lazy_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - template - inline lazy_ptr:: - lazy_ptr (const lazy_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_ptr& lazy_ptr:: - operator= (const lazy_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_ptr& lazy_ptr:: - operator= (Y* r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - template - inline lazy_ptr& lazy_ptr:: - operator= (const lazy_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - inline void lazy_ptr:: - swap (lazy_ptr& b) - { - T* p (p_); - p_ = b.p_; - b.p_ = p; - i_.swap (b.i_); - } - - template - inline void lazy_ptr:: - reset () - { - p_ = 0; - i_.reset (); - } - - template - template - inline void lazy_ptr:: - reset (Y* p) - { - p_ = p; - i_.reset (); - } - - template - inline T& lazy_ptr:: - operator* () const - { - return *p_; - } - - template - inline T* lazy_ptr:: - operator-> () const - { - return p_; - } - - template - inline T* lazy_ptr:: - get () const - { - return p_; - } - - template - inline bool lazy_ptr:: - loaded () const - { - bool i (i_); - return (p_ == 0) != i; // !p_ XOR i - } - - template - inline T* lazy_ptr:: - load () const - { - if (p_ == 0 && i_) - p_ = i_.template load (true); // Reset id. - - return p_; - } - - template - inline void lazy_ptr:: - unload () const - { - typedef typename object_traits::object_type object_type; - - if (p_) - { - if (i_.database () != 0) - i_.reset_id (object_traits::id (*p_)); - - p_ = 0; - } - } - - template - inline T* lazy_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_ptr:: - lazy_ptr (DB& db, const ID& id): p_ (0), i_ (db, id) {} - - template - template - inline lazy_ptr:: - lazy_ptr (DB& db, Y* r) - : p_ (r) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline void lazy_ptr:: - reset (DB& db, const ID& id) - { - p_ = 0; - i_.reset (db, id); - } - - template - template - inline void lazy_ptr:: - reset (DB& db, Y* r) - { - p_ = r; - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline typename object_traits::id_type lazy_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - return p_ - ? object_traits::id (*p_) - : i_.template object_id (); - } - - template - inline typename lazy_ptr::database_type& lazy_ptr:: - database () const - { - return *i_.database (); - } - - template - inline bool - operator== (const lazy_ptr& a, const lazy_ptr& b) - { - return a.equal (b); - } - - template - inline bool - operator!= (const lazy_ptr& a, const lazy_ptr& b) - { - return !a.equal (b); - } - - template - inline void - swap (lazy_ptr& a, lazy_ptr& b) - { - a.swap (b); - } - - // - // lazy_auto_ptr_ref - // -#ifndef ODB_CXX11 - - template - inline lazy_auto_ptr_ref:: - lazy_auto_ptr_ref (T* p, const lazy_ptr_impl_ref& i): p_ (p), i_ (i) {} - - // - // lazy_auto_ptr - // - - template - inline lazy_auto_ptr:: - lazy_auto_ptr (T* p): p_ (p) {} - - template - inline lazy_auto_ptr:: - lazy_auto_ptr (lazy_auto_ptr& r) - : p_ (r.p_), i_ (static_cast (r.i_)) - { - } - - template - template - inline lazy_auto_ptr:: - lazy_auto_ptr (lazy_auto_ptr& r) - : p_ (r.p_), i_ (static_cast (r.i_)) - { - } - - template - inline lazy_auto_ptr& lazy_auto_ptr:: - operator= (lazy_auto_ptr& r) - { - p_ = r.p_; - i_ = static_cast (r.i_); - return *this; - } - - template - template - inline lazy_auto_ptr& lazy_auto_ptr:: - operator= (lazy_auto_ptr& r) - { - p_ = r.p_; - i_ = static_cast (r.i_); - return *this; - } - - template - inline T& lazy_auto_ptr:: - operator* () const - { - return *p_; - } - - template - inline T* lazy_auto_ptr:: - operator-> () const - { - return p_.operator-> (); - } - - template - inline T* lazy_auto_ptr:: - get () const - { - return p_.get (); - } - - template - inline T* lazy_auto_ptr:: - release () - { - i_.reset (); - return p_.release (); - } - - template - inline void lazy_auto_ptr:: - reset (T* p) - { - i_.reset (); - p_.reset (p); - } - - template - inline lazy_auto_ptr:: - lazy_auto_ptr (const lazy_auto_ptr_ref& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_auto_ptr& lazy_auto_ptr:: - operator= (const lazy_auto_ptr_ref& r) - { - if (p_.get () != r.p_) - p_.reset (r.p_); - - i_ = r.i_; - return *this; - } - - template - template - inline lazy_auto_ptr:: - operator lazy_auto_ptr_ref () - { - return lazy_auto_ptr_ref (p_.release (), i_); - } - - template - template - inline lazy_auto_ptr:: - operator lazy_auto_ptr () - { - return lazy_auto_ptr (*this); - } - - template - template - inline lazy_auto_ptr:: - lazy_auto_ptr (std::auto_ptr& r): p_ (r) {} - - template - inline lazy_auto_ptr:: - lazy_auto_ptr (std::auto_ptr_ref r): p_ (r) {} - - template - template - inline lazy_auto_ptr& lazy_auto_ptr:: - operator= (std::auto_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - inline lazy_auto_ptr& lazy_auto_ptr:: - operator= (std::auto_ptr_ref r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - inline bool lazy_auto_ptr:: - loaded () const - { - bool i (i_); - return (p_.get () == 0) != i; // XOR - } - - template - inline std::auto_ptr& lazy_auto_ptr:: - load () const - { - if (p_.get () == 0 && i_) - { - std::auto_ptr tmp (i_.template load (true)); // Reset id. - p_ = tmp; - } - - return p_; - } - - template - inline void lazy_auto_ptr:: - unload () const - { - typedef typename object_traits::object_type object_type; - - if (p_.get () != 0) - { - if (i_.database () != 0) - i_.reset_id (object_traits::id (*p_)); - - p_.reset (); - } - } - - template - inline std::auto_ptr& lazy_auto_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_auto_ptr:: - lazy_auto_ptr (DB& db, const ID& id): i_ (db, id) {} - - template - template - inline lazy_auto_ptr:: - lazy_auto_ptr (DB& db, T* p) - : p_ (p) - { - if (p) - i_.reset_db (db); - } - - template - template - inline lazy_auto_ptr:: - lazy_auto_ptr (DB& db, std::auto_ptr& p) - : p_ (p) - { - if (p_.get () != 0) - i_.reset_db (db); - } - - template - template - inline void lazy_auto_ptr:: - reset (DB& db, const ID& id) - { - p_.reset (); - i_.reset (db, id); - } - - template - template - inline void lazy_auto_ptr:: - reset (DB& db, T* p) - { - p_.reset (p); - - if (p) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_auto_ptr:: - reset (DB& db, std::auto_ptr& p) - { - p_ = p; - - if (p_.get () != 0) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline typename object_traits::id_type lazy_auto_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - return p_.get () != 0 - ? object_traits::id (*p_) - : i_.template object_id (); - } - - template - inline typename lazy_auto_ptr::database_type& lazy_auto_ptr:: - database () const - { - return *i_.database (); - } -#endif - -#ifdef ODB_CXX11 - - // - // lazy_unique_ptr - // - - template - lazy_unique_ptr:: - lazy_unique_ptr () {} - -#ifdef ODB_CXX11_NULLPTR - template - lazy_unique_ptr:: - lazy_unique_ptr (std::nullptr_t) {} -#endif - - template - lazy_unique_ptr:: - lazy_unique_ptr (pointer p): p_ (p) {} - - template - lazy_unique_ptr:: - lazy_unique_ptr (pointer p, const deleter_type& d): p_ (p, d) {} - - template - lazy_unique_ptr:: - lazy_unique_ptr (pointer p, deleter_type&& d): p_ (p, std::move (d)) {} - - template - lazy_unique_ptr:: - lazy_unique_ptr (lazy_unique_ptr&& r) noexcept - : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} - - template - template - lazy_unique_ptr:: - lazy_unique_ptr (lazy_unique_ptr&& r) - : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} - - // template - // template - // lazy_unique_ptr:: - // lazy_unique_ptr (std::auto_ptr&& r): p_ (std::move (r)) {} - -#ifdef ODB_CXX11_NULLPTR - template - lazy_unique_ptr& lazy_unique_ptr:: - operator= (std::nullptr_t) - { - reset (); - return *this; - } -#endif - - template - lazy_unique_ptr& lazy_unique_ptr:: - operator= (lazy_unique_ptr&& r) noexcept - { - p_ = std::move (r.p_); - i_ = std::move (r.i_); - return *this; - } - - template - template - lazy_unique_ptr& lazy_unique_ptr:: - operator= (lazy_unique_ptr&& r) - { - p_ = std::move (r.p_); - i_ = std::move (r.i_); - return *this; - } - - template - T& lazy_unique_ptr:: - operator* () const - { - return *p_; - } - - template - typename lazy_unique_ptr::pointer lazy_unique_ptr:: - operator-> () const - { - return p_.operator-> (); - } - - template - typename lazy_unique_ptr::pointer lazy_unique_ptr:: - get () const - { - return p_.get (); - } - -#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR - template - lazy_unique_ptr:: - operator bool() const - { - return p_ || i_; - } -#endif - - template - typename lazy_unique_ptr::pointer lazy_unique_ptr:: - release () - { - i_.reset (); - return p_.release (); - } - - template - void lazy_unique_ptr:: - reset (pointer p) - { - p_.reset (p); - i_.reset (); - } - - template - void lazy_unique_ptr:: - swap (lazy_unique_ptr& b) - { - p_.swap (b.p_); - i_.swap (b.i_); - } - - template - typename lazy_unique_ptr::deleter_type& lazy_unique_ptr:: - get_deleter () - { - return p_.get_deleter (); - } - - template - const typename lazy_unique_ptr::deleter_type& lazy_unique_ptr:: - get_deleter () const - { - return p_.get_deleter (); - } - - template - template - inline lazy_unique_ptr:: - lazy_unique_ptr (std::unique_ptr&& p) - : p_ (std::move (p)) - { - } - - template - template - inline lazy_unique_ptr& lazy_unique_ptr:: - operator= (std::unique_ptr&& p) - { - p_ = std::move (p); - i_.reset (); - return *this; - } - - template - inline bool lazy_unique_ptr:: - loaded () const - { - bool i (i_); - return !p_ != i; // !p_ XOR i_ - } - - template - inline std::unique_ptr& lazy_unique_ptr:: - load () const - { - if (!p_ && i_) - p_ = std::unique_ptr (i_.template load (true)); // Reset id. - - return p_; - } - - template - inline void lazy_unique_ptr:: - unload () const - { - typedef typename object_traits::object_type object_type; - - if (p_) - { - if (i_.database () != 0) - i_.reset_id (object_traits::id (*p_)); - - p_.reset (); - } - } - - template - inline std::unique_ptr& lazy_unique_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_unique_ptr:: - lazy_unique_ptr (DB& db, const ID& id): i_ (db, id) {} - - template - template - inline lazy_unique_ptr:: - lazy_unique_ptr (DB& db, T* p) - : p_ (p) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_unique_ptr:: - lazy_unique_ptr (DB& db, T* p, const deleter_type& d) - : p_ (p, d) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_unique_ptr:: - lazy_unique_ptr (DB& db, T* p, deleter_type&& d) - : p_ (p, std::move (d)) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_unique_ptr:: - lazy_unique_ptr (DB& db, std::unique_ptr&& p) - : p_ (std::move (p)) - { - if (p_) - i_.reset_db (db); - } - - // template - // template - // inline lazy_unique_ptr:: - // lazy_unique_ptr (DB& db, std::auto_ptr&& p) - // : p_ (std::move (p)) - // { - // if (p_) - // i_.reset_db (db); - // } - - template - template - inline void lazy_unique_ptr:: - reset (DB& db, const ID& id) - { - p_.reset (); - i_.reset (db, id); - } - - template - template - inline void lazy_unique_ptr:: - reset (DB& db, T* p) - { - p_.reset (p); - - if (p) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_unique_ptr:: - reset (DB& db, std::unique_ptr&& p) - { - p_ = std::move (p); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - // template - // template - // inline void lazy_unique_ptr:: - // reset (DB& db, std::auto_ptr&& p) - // { - // p_ = std::unique_ptr (std::move (p)); - // - // if (p_) - // i_.reset_db (db); - // else - // i_.reset (); - // } - - template - template - inline typename object_traits::id_type lazy_unique_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - return p_ - ? object_traits::id (*p_) - : i_.template object_id (); - } - - template - inline typename lazy_unique_ptr::database_type& lazy_unique_ptr:: - database () const - { - return *i_.database (); - } - - template - inline void - swap (lazy_unique_ptr& a, lazy_unique_ptr& b) - { - a.swap (b); - } - - template - inline bool - operator== (const lazy_unique_ptr& a, - const lazy_unique_ptr& b) - { - return a.equal (b); - } - - template - inline bool - operator!= (const lazy_unique_ptr& a, - const lazy_unique_ptr& b) - { - return !a.equal (b); - } - -#ifdef ODB_CXX11_NULLPTR - template - inline bool - operator== (const lazy_unique_ptr& a, std::nullptr_t) - { - return !a; - } - - template - inline bool - operator== (std::nullptr_t, const lazy_unique_ptr& b) - { - return !b; - } - - template - inline bool - operator!= (const lazy_unique_ptr& a, std::nullptr_t) - { - return bool (a); // Explicit to-bool conversion. - } - - template - inline bool - operator!= (std::nullptr_t, const lazy_unique_ptr& b) - { - return bool (b); // Explicit to-bool conversion. - } -#endif - - // - // lazy_shared_ptr - // - - template - inline lazy_shared_ptr:: - lazy_shared_ptr () {} - -#ifdef ODB_CXX11_NULLPTR - template - inline lazy_shared_ptr:: - lazy_shared_ptr (std::nullptr_t) {} -#endif - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (Y* p): p_ (p) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (Y* p, D d): p_ (p, d) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (Y* p, D d, A a): p_ (p, d, a) {} - -#ifdef ODB_CXX11_NULLPTR - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (std::nullptr_t p, D d): p_ (p, d) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (std::nullptr_t p, D d, A a): p_ (p, d, a) {} -#endif - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_shared_ptr& r, T* p) - // r.p_ has to be loaded - : p_ (r.p_, p) {} - - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_shared_ptr:: - lazy_shared_ptr (lazy_shared_ptr&& r) noexcept - : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (lazy_shared_ptr&& r) - : p_ (std::move (r.p_)), i_ (std::move (r.i_)) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_weak_ptr& r): i_ (r.i_) - { - // If the pointer has expired but can be re-loaded, then don't throw. - // - p_ = r.lock ().get_eager (); - - if (!p_ && !i_) - throw std::bad_weak_ptr (); - } - - // template - // template - // inline lazy_shared_ptr:: - // lazy_shared_ptr (std::auto_ptr&& r): p_ (std::move (r)) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (std::unique_ptr&& r): p_ (std::move (r)) {} - - template - inline lazy_shared_ptr:: - ~lazy_shared_ptr () {} - - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (const lazy_shared_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (const lazy_shared_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (lazy_shared_ptr&& r) noexcept - { - p_ = std::move (r.p_); - i_ = std::move (r.i_); - return *this; - } - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (lazy_shared_ptr&& r) - { - p_ = std::move (r.p_); - i_ = std::move (r.i_); - return *this; - } - - // template - // template - // inline lazy_shared_ptr& lazy_shared_ptr:: - // operator= (std::auto_ptr&& r) - // { - // p_ = std::move (r); - // i_.reset (); - // return *this; - // } - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (std::unique_ptr&& r) - { - p_ = std::move (r); - i_.reset (); - return *this; - } - - template - inline void lazy_shared_ptr:: - swap (lazy_shared_ptr& b) - { - p_.swap (b.p_); - i_.swap (b.i_); - } - - template - inline void lazy_shared_ptr:: - reset () - { - p_.reset (); - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (Y* p) - { - p_.reset (p); - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (Y* p, D d) - { - p_.reset (p, d); - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (Y* p, D d, A a) - { - p_.reset (p, d, a); - i_.reset (); - } - - template - inline T& lazy_shared_ptr:: - operator* () const - { - return *p_; - } - - template - inline T* lazy_shared_ptr:: - operator-> () const - { - return p_.operator-> (); - } - - template - inline T* lazy_shared_ptr:: - get () const - { - return p_.get (); - } - - template - inline bool lazy_shared_ptr:: - unique () const - { - return p_.unique (); - } - - template - inline long lazy_shared_ptr:: - use_count () const - { - return p_.use_count (); - } - -#ifdef ODB_CXX11_EXPLICIT_CONVERSION_OPERATOR - template - inline lazy_shared_ptr:: - operator bool () const - { - return p_ || i_; - } -#endif - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const std::shared_ptr& r): p_ (r) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (std::shared_ptr&& r): p_ (std::move (r)) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const std::weak_ptr& r): p_ (r) {} - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (const std::shared_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (std::shared_ptr&& r) - { - p_ = std::move (r); - i_.reset (); - return *this; - } - - template - inline bool lazy_shared_ptr:: - loaded () const - { - bool i (i_); - return !p_ != i; // !p_ XOR i_ - } - - template - inline std::shared_ptr lazy_shared_ptr:: - load () const - { - if (!p_ && i_) - p_ = i_.template load (true); // Reset id. - - return p_; - } - - template - inline void lazy_shared_ptr:: - unload () const - { - typedef typename object_traits::object_type object_type; - - if (p_) - { - if (i_.database () != 0) - i_.reset_id (object_traits::id (*p_)); - - p_.reset (); - } - } - - template - inline std::shared_ptr lazy_shared_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, const ID& id): i_ (db, id) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, Y* p) - : p_ (p) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, Y* p, D d) - : p_ (p, d) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, Y* p, D d, A a) - : p_ (p, d, a) - { - if (p_) - i_.reset_db (db); - } - - // template - // template - // inline lazy_shared_ptr:: - // lazy_shared_ptr (DB& db, std::auto_ptr&& r) - // : p_ (std::move (r)) - // { - // if (p_) - // i_.reset_db (db); - // } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, const std::shared_ptr& r) - : p_ (r) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, std::shared_ptr&& r) - : p_ (std::move (r)) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, const std::weak_ptr& r) - : p_ (r) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, const ID& id) - { - p_.reset (); - i_.reset (db, id); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, Y* p) - { - p_.reset (p); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, Y* p, D d) - { - p_.reset (p, d); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, Y* p, D d, A a) - { - p_.reset (p, d, a); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - // template - // template - // inline void lazy_shared_ptr:: - // reset (DB& db, std::auto_ptr&& r) - // { - // p_ = std::move (r); - // - // if (p_) - // i_.reset_db (db); - // else - // i_.reset (); - // } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, const std::shared_ptr& r) - { - p_ = r; - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, std::shared_ptr&& r) - { - p_ = std::move (r); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline typename object_traits::id_type lazy_shared_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - return p_ - ? object_traits::id (*p_) - : i_.template object_id (); - } - - template - inline typename lazy_shared_ptr::database_type& lazy_shared_ptr:: - database () const - { - return *i_.database (); - } - - template - inline bool - operator== (const lazy_shared_ptr& a, const lazy_shared_ptr& b) - { - return a.equal (b); - } - - template - inline bool - operator!= (const lazy_shared_ptr& a, const lazy_shared_ptr& b) - { - return !a.equal (b); - } - -#ifdef ODB_CXX11_NULLPTR - template - inline bool - operator== (const lazy_shared_ptr& p, std::nullptr_t) - { - return !p; - } - - template - inline bool - operator== (std::nullptr_t, const lazy_shared_ptr& p) - { - return !p; - } - - template - inline bool - operator!= (const lazy_shared_ptr& p, std::nullptr_t) - { - return bool (p); // Explicit to-bool conversion. - } - - template - inline bool - operator!= (std::nullptr_t, const lazy_shared_ptr& p) - { - return bool (p); // Explicit to-bool conversion. - } -#endif - - template - inline void - swap (lazy_shared_ptr& a, lazy_shared_ptr& b) - { - a.swap (b); - } - - template - inline D* - get_deleter (const lazy_shared_ptr& p) - { - return std::get_deleter (p.p_); - } - - // - // lazy_weak_ptr - // - - template - inline lazy_weak_ptr:: - lazy_weak_ptr () {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_weak_ptr:: - ~lazy_weak_ptr () {} - - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const lazy_weak_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const lazy_weak_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const lazy_shared_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - inline void lazy_weak_ptr:: - swap (lazy_weak_ptr& r) - { - p_.swap (r.p_); - i_.swap (r.i_); - } - - template - inline void lazy_weak_ptr:: - reset () - { - p_.reset (); - i_.reset (); - } - - template - inline long lazy_weak_ptr:: - use_count () const - { - return p_.use_count (); - } - - template - inline bool lazy_weak_ptr:: - expired () const - { - return p_.expired (); - } - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const std::weak_ptr& r): p_ (r) {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const std::shared_ptr& r): p_ (r) {} - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const std::weak_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const std::shared_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - inline bool lazy_weak_ptr:: - loaded () const - { - bool i (i_); - return expired () != i; // expired () XOR i_ - } - - template - inline lazy_shared_ptr lazy_weak_ptr:: - lock () const - { - return lazy_shared_ptr (p_.lock (), i_); - } - - template - inline std::shared_ptr lazy_weak_ptr:: - load () const - { - std::shared_ptr r (p_.lock ()); - - if (!r && i_) - { - r = i_.template load (false); // Keep id. - p_ = r; - } - - return r; - } - - template - inline void lazy_weak_ptr:: - unload () const - { - // With weak pointer we always keep i_ up to date. - // - p_.reset (); - } - - template - inline std::weak_ptr lazy_weak_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (DB& db, const ID& id): i_ (db, id) {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (DB& db, const std::shared_ptr& r) - : p_ (r) - { - typedef typename object_traits::object_type object_type; - - if (r) - i_.reset (db, object_traits::id (*r)); - } - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (DB& db, const std::weak_ptr& r) - : p_ (r) - { - typedef typename object_traits::object_type object_type; - - std::shared_ptr sp (p_.lock ()); - - if (sp) - i_.reset (db, object_traits::id (*sp)); - } - - template - template - inline void lazy_weak_ptr:: - reset (DB& db, const ID& id) - { - p_.reset (); - i_.reset (db, id); - } - - template - template - inline void lazy_weak_ptr:: - reset (DB& db, const std::shared_ptr& r) - { - typedef typename object_traits::object_type object_type; - - p_ = r; - - if (r) - i_.reset (db, object_traits::id (*r)); - else - i_.reset (); - } - - template - template - inline void lazy_weak_ptr:: - reset (DB& db, const std::weak_ptr& r) - { - typedef typename object_traits::object_type object_type; - - p_ = r; - std::shared_ptr sp (p_.lock ()); - - if (sp) - i_.reset (db, object_traits::id (*sp)); - else - i_.reset (); - } - - template - template - inline typename object_traits::id_type lazy_weak_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - std::shared_ptr sp (p_.lock ()); - return sp - ? object_traits::id (*sp) - : i_.template object_id (); - } - - template - inline typename lazy_weak_ptr::database_type& lazy_weak_ptr:: - database () const - { - return *i_.database (); - } - - template - inline void - swap (lazy_weak_ptr& a, lazy_weak_ptr& b) - { - a.swap (b); - } - -#endif // ODB_CXX11 - -} diff --git a/odb/lazy-ptr.txx b/odb/lazy-ptr.txx deleted file mode 100644 index 17a7405..0000000 --- a/odb/lazy-ptr.txx +++ /dev/null @@ -1,114 +0,0 @@ -// file : odb/lazy-ptr.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // lazy_ptr - // - - template - template - bool lazy_ptr:: - equal (const lazy_ptr& r) const - { - bool t1 ((p_ == 0) == loaded ()); - bool t2 ((r.p_ == 0) == r.loaded ()); - - // If both are transient, then compare the underlying pointers. - // - if (t1 && t2) - return p_ == r.p_; - - // If one is transient and the other is persistent, then compare - // the underlying pointers but only if they are non NULL. Note - // that an unloaded persistent object is always unequal to a - // transient object. - // - if (t1 || t2) - return p_ == r.p_ && p_ != 0; - - // If both objects are persistent, then we compare databases and - // object ids. - // - typedef typename object_traits::object_type object_type1; - typedef typename object_traits::object_type object_type2; - - return i_.database () == r.i_.database () && - object_id () == r.template object_id (); - } - -#ifdef ODB_CXX11 - - // - // lazy_unique_ptr - // - - template - template - bool lazy_unique_ptr:: - equal (const lazy_unique_ptr& r) const - { - bool t1 (!p_ == loaded ()); - bool t2 (!r.p_ == r.loaded ()); - - // If both are transient, then compare the underlying pointers. - // - if (t1 && t2) - return p_ == r.p_; - - // If one is transient and the other is persistent, then compare - // the underlying pointers but only if they are non NULL. Note - // that an unloaded persistent object is always unequal to a - // transient object. - // - if (t1 || t2) - return p_ == r.p_ && p_; - - // If both objects are persistent, then we compare databases and - // object ids. - // - typedef typename object_traits::object_type object_type1; - typedef typename object_traits::object_type object_type2; - - return i_.database () == r.i_.database () && - object_id () == r.template object_id (); - } - - // - // lazy_shared_ptr - // - - template - template - bool lazy_shared_ptr:: - equal (const lazy_shared_ptr& r) const - { - bool t1 (!p_ == loaded ()); - bool t2 (!r.p_ == r.loaded ()); - - // If both are transient, then compare the underlying pointers. - // - if (t1 && t2) - return p_ == r.p_; - - // If one is transient and the other is persistent, then compare - // the underlying pointers but only if they are non NULL. Note - // that an unloaded persistent object is always unequal to a - // transient object. - // - if (t1 || t2) - return p_ == r.p_ && p_; - - // If both objects are persistent, then we compare databases and - // object ids. - // - typedef typename object_traits::object_type object_type1; - typedef typename object_traits::object_type object_type2; - - return i_.database () == r.i_.database () && - object_id () == r.template object_id (); - } -#endif // ODB_CXX11 - -} diff --git a/odb/libodb-vc10.vcxproj b/odb/libodb-vc10.vcxproj deleted file mode 100644 index d3e2889..0000000 --- a/odb/libodb-vc10.vcxproj +++ /dev/null @@ -1,173 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E} - Win32Proj - libodb - - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - true - Unicode - - - DynamicLibrary - false - true - Unicode - - - DynamicLibrary - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - ..\bin\ - odb-d-__value__(interface_version)-vc10 - - - true - ..\bin64\ - odb-d-__value__(interface_version)-vc10 - - - false - ..\bin\ - odb-__value__(interface_version)-vc10 - - - false - ..\bin64\ - odb-__value__(interface_version)-vc10 - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - $(TargetPath) - ..\lib\odb-d.lib - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - $(TargetPath) - ..\lib64\odb-d.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - true - true - $(TargetPath) - ..\lib\odb.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - true - true - $(TargetPath) - ..\lib64\odb.lib - - - -__header_entries__(headers) -__header_entry__(details\config-vc.h) - - -__source_entries__(sources) -__source_entries__(win32_threads_sources) -__source_entries__(win32_dll_sources) - - - - - diff --git a/odb/libodb-vc10.vcxproj.filters b/odb/libodb-vc10.vcxproj.filters deleted file mode 100644 index da1d6b2..0000000 --- a/odb/libodb-vc10.vcxproj.filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cxx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hxx;ixx;txx - - - -__header_filter_entries__(headers) -__header_filter_entry__(details\config-vc.h) - - -__source_filter_entries__(sources) -__source_filter_entries__(win32_threads_sources) - - diff --git a/odb/libodb-vc11.vcxproj b/odb/libodb-vc11.vcxproj deleted file mode 100644 index 7da5af7..0000000 --- a/odb/libodb-vc11.vcxproj +++ /dev/null @@ -1,177 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E} - Win32Proj - libodb - - - - DynamicLibrary - true - v110 - Unicode - - - DynamicLibrary - true - v110 - Unicode - - - DynamicLibrary - false - v110 - true - Unicode - - - DynamicLibrary - false - v110 - true - Unicode - - - - - - - - - - - - - - - - - - - true - ..\bin\ - odb-d-__value__(interface_version)-vc11 - - - true - ..\bin64\ - odb-d-__value__(interface_version)-vc11 - - - false - ..\bin\ - odb-__value__(interface_version)-vc11 - - - false - ..\bin64\ - odb-__value__(interface_version)-vc11 - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - $(TargetPath) - ..\lib\odb-d.lib - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - $(TargetPath) - ..\lib64\odb-d.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - true - true - $(TargetPath) - ..\lib\odb.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - - - Windows - true - true - true - $(TargetPath) - ..\lib64\odb.lib - - - -__header_entries__(headers) -__header_entry__(details\config-vc.h) - - -__source_entries__(sources) -__source_entries__(win32_threads_sources) -__source_entries__(win32_dll_sources) - - - - - diff --git a/odb/libodb-vc11.vcxproj.filters b/odb/libodb-vc11.vcxproj.filters deleted file mode 100644 index da1d6b2..0000000 --- a/odb/libodb-vc11.vcxproj.filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cxx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hxx;ixx;txx - - - -__header_filter_entries__(headers) -__header_filter_entry__(details\config-vc.h) - - -__source_filter_entries__(sources) -__source_filter_entries__(win32_threads_sources) - - diff --git a/odb/libodb-vc12.vcxproj b/odb/libodb-vc12.vcxproj deleted file mode 100644 index e9e2698..0000000 --- a/odb/libodb-vc12.vcxproj +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {1C53C543-8038-4C8A-8AB1-65E74FD7DE2E} - Win32Proj - libodb - - - - DynamicLibrary - true - v120 - Unicode - - - DynamicLibrary - true - v120 - Unicode - - - DynamicLibrary - false - v120 - true - Unicode - - - DynamicLibrary - false - v120 - true - Unicode - - - - - - - - - - - - - - - - - - - true - ..\bin\ - odb-d-__value__(interface_version)-vc12 - - - true - ..\bin64\ - odb-d-__value__(interface_version)-vc12 - - - false - ..\bin\ - odb-__value__(interface_version)-vc12 - - - false - ..\bin64\ - odb-__value__(interface_version)-vc12 - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - true - - - Windows - true - $(TargetPath) - ..\lib\odb-d.lib - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - true - - - Windows - true - $(TargetPath) - ..\lib64\odb-d.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - true - - - Windows - true - true - true - $(TargetPath) - ..\lib\odb.lib - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBODB_DYNAMIC_LIB;%(PreprocessorDefinitions) - .. - 4355;4800;4290;4251;%(DisableSpecificWarnings) - true - - - Windows - true - true - true - $(TargetPath) - ..\lib64\odb.lib - - - -__header_entries__(headers) -__header_entry__(details\config-vc.h) - - -__source_entries__(sources) -__source_entries__(win32_threads_sources) -__source_entries__(win32_dll_sources) - - - - - diff --git a/odb/libodb-vc12.vcxproj.filters b/odb/libodb-vc12.vcxproj.filters deleted file mode 100644 index da1d6b2..0000000 --- a/odb/libodb-vc12.vcxproj.filters +++ /dev/null @@ -1,21 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cxx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hxx;ixx;txx - - - -__header_filter_entries__(headers) -__header_filter_entry__(details\config-vc.h) - - -__source_filter_entries__(sources) -__source_filter_entries__(win32_threads_sources) - - diff --git a/odb/libodb-vc8.vcproj b/odb/libodb-vc8.vcproj deleted file mode 100644 index 00a668e..0000000 --- a/odb/libodb-vc8.vcproj +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -__source_entries__(sources) -__source_entries__(win32_threads_sources) -__source_entries__(win32_dll_sources) - - -__file_entries__(headers) -__file_entry__(details\config-vc.h) - - - - - diff --git a/odb/libodb-vc9.vcproj b/odb/libodb-vc9.vcproj deleted file mode 100644 index 011e4f0..0000000 --- a/odb/libodb-vc9.vcproj +++ /dev/null @@ -1,358 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -__source_entries__(sources) -__source_entries__(win32_threads_sources) -__source_entries__(win32_dll_sources) - - -__file_entries__(headers) -__file_entry__(details\config-vc.h) - - - - - diff --git a/odb/makefile b/odb/makefile deleted file mode 100644 index 01b395e..0000000 --- a/odb/makefile +++ /dev/null @@ -1,184 +0,0 @@ -# file : odb/makefile -# license : GNU GPL v2; see accompanying LICENSE file - -include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make - -cxx := \ -exceptions.cxx \ -database.cxx \ -vector-impl.cxx \ -connection.cxx \ -prepared-query.cxx \ -query-dynamic.cxx \ -result.cxx \ -schema-catalog.cxx \ -section.cxx \ -session.cxx \ -statement.cxx \ -statement-processing.cxx \ -tracer.cxx \ -transaction.cxx - -# Implementation details. -# -cxx += \ -details/buffer.cxx \ -details/condition.cxx \ -details/lock.cxx \ -details/mutex.cxx \ -details/shared-ptr/base.cxx - -# POSIX-based implementation details. -# -posix_thr_cxx := \ -details/posix/exceptions.cxx \ -details/posix/thread.cxx - -# Win32-based implementation details. -# -win32_thr_cxx := \ -details/win32/init.cxx \ -details/win32/once.cxx \ -details/win32/tls.cxx \ -details/win32/condition.cxx \ -details/win32/thread.cxx \ -details/win32/exceptions.cxx - -win32_dll_cxx := details/win32/dll.cxx - -cxx_tun := $(cxx) - -ifeq ($(libodb_threads),posix) -cxx_tun += $(posix_thr_cxx) -endif - -ifeq ($(libodb_threads),win32) -cxx_tun += $(win32_thr_cxx) - -$(call include,$(bld_root)/ld/configuration-lib.make) # ld_lib_type - -ifeq ($(ld_lib_type),shared) -cxx_tun += $(win32_dll_cxx) -endif -endif - -cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o)) -cxx_od := $(cxx_obj:.o=.o.d) - -odb.l := $(out_base)/odb.l -odb.l.cpp-options := $(out_base)/odb.l.cpp-options - -default := $(out_base)/ -dist := $(out_base)/.dist -clean := $(out_base)/.clean - -# Build. -# -$(odb.l): $(cxx_obj) - -ifeq ($(libodb_threads),posix) -$(odb.l): -lpthread -endif - -$(cxx_obj) $(cxx_od): $(odb.l.cpp-options) $(out_base)/details/config.h -$(odb.l.cpp-options): value := -I$(out_root) -I$(src_root) - -ifdef libodb_threads -$(out_base)/details/config.h: | $(out_base)/details/. - @echo '/* file : odb/details/config.h' >$@ - @echo ' * note : automatically generated' >>$@ - @echo ' */' >>$@ - @echo '' >>$@ - @echo '#ifndef ODB_DETAILS_CONFIG_H' >>$@ - @echo '#define ODB_DETAILS_CONFIG_H' >>$@ - @echo '' >>$@ -ifeq ($(libodb_threads),posix) - @echo '#define ODB_THREADS_POSIX 1' >>$@ -endif -ifeq ($(libodb_threads),win32) - @echo '#define ODB_THREADS_WIN32 1' >>$@ -endif -ifeq ($(libodb_threads),none) - @echo '#define ODB_THREADS_NONE 1' >>$@ -endif - @echo '' >>$@ - @echo '#endif /* ODB_DETAILS_CONFIG_H */' >>$@ -endif - -$(call include-dep,$(cxx_od),$(cxx_obj),$(out_base)/details/config.h) - -# Convenience alias for default target. -# -$(out_base)/: $(odb.l) - -# Dist. -# -$(dist): export sources := $(cxx) -$(dist): export posix_threads_sources := $(posix_thr_cxx) -$(dist): export win32_threads_sources := $(win32_thr_cxx) -$(dist): export win32_dll_sources := $(win32_dll_cxx) - -$(dist): export headers := $(subst $(src_base)/,,$(shell find $(src_base) \ --path $(src_base)/details/posix -a -prune -a -false -o \ --path $(src_base)/details/win32 -a -prune -a -false -o \ --name '*.hxx' -o -name '*.ixx' -o -name '*.txx')) -$(dist): export posix_threads_headers := $(subst $(src_base)/,,$(shell find \ -$(src_base)/details/posix -name '*.hxx' -o -name '*.ixx' -o -name '*.txx')) -$(dist): export win32_headers := details/win32/windows.hxx -$(dist): export win32_threads_headers := $(foreach \ -h,$(win32_headers),$(filter-out $h,$(subst $(src_base)/,,$(shell find \ -$(src_base)/details/win32 -name '*.hxx' -o -name '*.ixx' -o -name '*.txx')))) - -$(dist): data_dist := details/config.h.in details/config-vc.h -$(dist): export extra_dist := $(data_dist) \ -libodb-vc8.vcproj libodb-vc9.vcproj \ -libodb-vc10.vcxproj libodb-vc10.vcxproj.filters \ -libodb-vc11.vcxproj libodb-vc11.vcxproj.filters \ -libodb-vc12.vcxproj libodb-vc12.vcxproj.filters -$(dist): export interface_version = $(shell sed -e \ -'s/^\([0-9]*\.[0-9]*\).*/\1/' $(src_root)/version.txt) - -$(dist): - $(call dist-data,$(sources) $(posix_threads_sources) \ -$(win32_threads_sources) $(win32_dll_sources) $(headers) \ -$(posix_threads_headers) $(win32_headers) $(win32_threads_headers) \ -$(data_dist)) - $(call meta-vc8proj,$(src_base)/libodb-vc8.vcproj) - $(call meta-vc9proj,$(src_base)/libodb-vc9.vcproj) - $(call meta-vc10proj,$(src_base)/libodb-vc10.vcxproj) - $(call meta-vc11proj,$(src_base)/libodb-vc11.vcxproj) - $(call meta-vc12proj,$(src_base)/libodb-vc12.vcxproj) - $(call meta-automake) - -# Clean. -# -$(clean): $(odb.l).o.clean \ - $(odb.l.cpp-options).clean \ - $(addsuffix .cxx.clean,$(cxx_obj)) \ - $(addsuffix .cxx.clean,$(cxx_od)) - $(call message,rm $$1,rm -f $$1,$(out_base)/details/config.h) - -# Generated .gitignore. -# -ifeq ($(out_base),$(src_base)) -$(odb.l): | $(out_base)/.gitignore - -$(out_base)/.gitignore: files := details/config.h -$(clean): $(out_base)/.gitignore.clean - -$(call include,$(bld_root)/git/gitignore.make) -endif - -# How to. -# -$(call include,$(bld_root)/dist.make) -$(call include,$(bld_root)/meta/vc8proj.make) -$(call include,$(bld_root)/meta/vc9proj.make) -$(call include,$(bld_root)/meta/vc10proj.make) -$(call include,$(bld_root)/meta/vc11proj.make) -$(call include,$(bld_root)/meta/vc12proj.make) -$(call include,$(bld_root)/meta/automake.make) - -$(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/odb/nested-container.hxx b/odb/nested-container.hxx deleted file mode 100644 index d7e4ec1..0000000 --- a/odb/nested-container.hxx +++ /dev/null @@ -1,218 +0,0 @@ -// file : odb/nested-container.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_NESTED_CONTAINER_HXX -#define ODB_NESTED_CONTAINER_HXX - -#include - -#include // size_t - -#include -#include // ODB_CXX11 - -#ifndef ODB_CXX11 -# error nested container support is only available in C++11 -#endif - -namespace odb -{ - // Nested container emulation support for ODB. - // - // In a nutshell, the idea is to represent a nested container, for example, - // vector>, as map where nested_key is a composite - // key consisting of the outer and inner container indexes. - // - // Note that with this approach the empty trailing entries of the outer - // container will not be added on load. It is assumed that the user handles - // that on their own, for example, by pre-loading the outer container entry - // members if there are any. - // - // Also note that the outer key in the inner container should strictly - // speaking be a foreign key pointing to the key of the outer container. The - // only way to achieve this currently is to manually add the constraint via - // ALTER TABLE ADD CONSTRAINT. Note, however, that as long as we only modify - // these tables via the ODB container interface, not having the foreign key - // (and not having ON DELETE CASCADE) should be harmless (since we have a - // foreign key pointing to the object id). - - // Map key that is used to emulate 1-level nested container mapping (for - // example, vector>). Template parameter IC is a tag that allows - // us to distinguish keys for unrelated containers in order to assign column - // names, etc. Use the inner container type (for example, vector) for IC. - // - template - struct nested_key - { - using outer_type = O; - using inner_type = I; - - outer_type outer; - inner_type inner; - - nested_key () = default; - nested_key (outer_type o, inner_type i): outer (o), inner (i) {} - - bool - operator< (const nested_key& v) const - { - return outer < v.outer || (outer == v.outer && inner < v.inner); - } - }; - - // Map key that is used to emulate 2-level nested container mapping (for - // example, vector>>>). Use the middle container type for - // MC (for example, vector>). - // - template - struct nested2_key - { - using outer_type = O; - using middle_type = M; - using inner_type = I; - - outer_type outer; - middle_type middle; - inner_type inner; - - nested2_key () = default; - nested2_key (outer_type o, middle_type m, inner_type i) - : outer (o), middle (m), inner (i) {} - - bool - operator< (const nested2_key& v) const - { - return outer != v.outer ? outer < v.outer : - middle != v.middle ? middle < v.middle : - inner < v.inner ; - } - }; -} - -#include -#include // size_t -#include // move(), declval() -#include -#include // remove_reference - -namespace odb -{ - template - struct nested1_type: - std::remove_reference ()[0])> {}; - - template - struct nested2_type: - std::remove_reference ()[0][0])> {}; - - template - struct nested3_type: - std::remove_reference ()[0][0][0])> {}; - - // 1-level nesting. - // - template // For example, OC = vector>. - std::map::type>, - typename nested2_type::type> - nested_get (const OC& oc) - { - using namespace std; - - using IC = typename nested1_type::type; - using V = typename nested2_type::type; - using K = nested_key; - - map r; - for (size_t o (0); o != oc.size (); ++o) - { - const IC& ic (oc[o]); - for (size_t i (0); i != ic.size (); ++i) - r.emplace (K (o, i), ic[i]); - } - return r; - } - - template - void - nested_set (OC& oc, std::map&& r) - { - using namespace std; - - for (auto& p: r) - { - size_t o (p.first.outer); - size_t i (p.first.inner); - V& v (p.second); - - if (o >= oc.size ()) - oc.resize (o + 1); - - assert (i == oc[o].size ()); - - oc[o].push_back (move (v)); - } - } - - // 2-level nesting. - // - template // For example, OC = vector>>. - std::map::type>, - typename nested3_type::type> - nested2_get (const OC& oc) - { - using namespace std; - - using MC = typename nested1_type::type; - using V = typename nested3_type::type; - using K = nested2_key; - - map r; - for (size_t o (0); o != oc.size (); ++o) - { - const auto& mc (oc[o]); - for (size_t m (0); m != mc.size (); ++m) - { - const auto& ic (mc[m]); - for (size_t i (0); i != ic.size (); ++i) - r.emplace (K (o, m, i), ic[i]); - } - } - return r; - } - - template - void - nested2_set (OC& oc, std::map&& r) - { - using namespace std; - - for (auto& p: r) - { - size_t o (p.first.outer); - size_t m (p.first.middle); - size_t i (p.first.inner); - V& v (p.second); - - if (o >= oc.size ()) - oc.resize (o + 1); - - auto& mc (oc[o]); - - if (m >= mc.size ()) - mc.resize (m + 1); - - assert (i == mc[m].size ()); - - mc[m].push_back (move (v)); - } - } -} - -#include - -#endif // ODB_NESTED_CONTAINER_HXX diff --git a/odb/no-id-object-result.hxx b/odb/no-id-object-result.hxx deleted file mode 100644 index 556065b..0000000 --- a/odb/no-id-object-result.hxx +++ /dev/null @@ -1,182 +0,0 @@ -// file : odb/no-id-object-result.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_NO_ID_OBJECT_RESULT_HXX -#define ODB_NO_ID_OBJECT_RESULT_HXX - -#include - -#include // std::size_t -#include // std::move - -#include -#include -#include -#include -#include - -#include // ODB_CXX11 - -namespace odb -{ - // Implementation for objects without object id (always non-polymorphic). - // - template - class no_id_object_result_impl: public result_impl - { - protected: - // In result_impl, T is always non-const and the same as object_type. - // - typedef T object_type; - typedef odb::object_traits object_traits; - - typedef typename object_traits::pointer_type pointer_type; - typedef odb::pointer_traits pointer_traits; - - friend class result; - friend class result; - friend class result_iterator; - friend class result_iterator; - friend class object_result_iterator; - friend class object_result_iterator; - - protected: - no_id_object_result_impl (odb::connection& conn) - : result_impl (conn), begin_ (true), end_ (false), current_ () - { - } - - // To make this work with all kinds of pointers (raw, std::auto_ptr, - // shared), we need to make sure we don't make any copies of the - // pointer on the return path. - // - pointer_type& - current () - { - if (pointer_traits::null_ptr (current_) && !end_) - load (); - - return current_; - } - - void - release () - { - current_ = pointer_type (); - guard_.release (); - } - - void - begin () - { - if (begin_) - { - next (); - begin_ = false; - } - } - - bool - end () const - { - return end_; - } - - protected: - virtual void - load (object_type&) = 0; - - virtual void - next () = 0; - - virtual void - cache () = 0; - - virtual std::size_t - size () = 0; - - protected: -#ifdef ODB_CXX11 - void - current (pointer_type& p) - { - current_ = std::move (p); - guard_.reset (current_); - } - - void - current (pointer_type&& p) - { - current (p); - } -#else - void - current (pointer_type p) - { - current_ = p; - guard_.reset (current_); - } -#endif - - bool begin_; - bool end_; - - private: - void - load (); - - private: - pointer_type current_; - typename pointer_traits::guard guard_; - }; - - template - class object_result_iterator - { - public: - // T can be const T while object_type is always non-const. - // - typedef typename object_traits::object_type object_type; - - typedef no_id_object_result_impl result_impl_type; - - public: - object_result_iterator (result_impl_type* res) - : res_ (res) - { - } - - public: - typedef typename object_traits::pointer_type pointer_type; - - pointer_type - load () - { -#ifdef ODB_CXX11 - pointer_type r (std::move (res_->current ())); -#else - pointer_type r (res_->current ()); -#endif - res_->release (); - return r; - } - - void - load (object_type& obj) - { - // Objects without ids are not stored in session cache. - // - if (!res_->end ()) - res_->load (obj); - } - - protected: - result_impl_type* res_; - }; -} - -#include - -#include - -#endif // ODB_NO_ID_OBJECT_RESULT_HXX diff --git a/odb/no-id-object-result.txx b/odb/no-id-object-result.txx deleted file mode 100644 index 886fe4b..0000000 --- a/odb/no-id-object-result.txx +++ /dev/null @@ -1,21 +0,0 @@ -// file : odb/no-id-object-result.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // object_result_impl - // - - template - void no_id_object_result_impl:: - load () - { - // Objects without ids are not stored in session cache. - // - pointer_type p (object_traits::create ()); - object_type& obj (pointer_traits::get_ref (p)); - current (p); - load (obj); - } -} diff --git a/odb/no-op-cache-traits.hxx b/odb/no-op-cache-traits.hxx deleted file mode 100644 index b6d0518..0000000 --- a/odb/no-op-cache-traits.hxx +++ /dev/null @@ -1,236 +0,0 @@ -// file : odb/no-op-cache-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_NO_OP_CACHE_TRAITS_HXX -#define ODB_NO_OP_CACHE_TRAITS_HXX - -#include - -#include -#include -#include - -namespace odb -{ - // pointer_cache_type - // - // Used to convert an object pointer to the canonical form (non-const), - // suitable for insertion into the cache. - // - template ::element_type, - typename O = typename object_traits::object_type, - pointer_kind pk = pointer_traits

::kind> - struct pointer_cache_type - { - typedef typename object_traits::pointer_type pointer_type; - - static pointer_type - convert (const P& p) - { - return pointer_traits

::const_pointer_cast (p); - } - }; - - template - struct pointer_cache_type - { - // If element_type and object_type are the same, then it is already - // the canonical pointer. - // - static const P& - convert (const P& p) {return p;} - }; - - template - struct pointer_cache_type - { - // If the pointer is unique, then casting it can transfer ownership. - // In this case we return NULL void*, which will be ignored down the - // chain. - // - static void* - convert (const P&) {return 0;} - }; - - template - struct pointer_cache_type - { - static void* - convert (const P&) {return 0;} - }; - - // reference_cache_type - // - // Used to convert an object reference to the canonical form (non-const), - // suitable for insertion into the cache. - // - template ::object_type> - struct reference_cache_type - { - static O& - convert (T& r) - { - return const_cast (r); - } - }; - - template - struct reference_cache_type - { - // If the types are the same, then it is already the canonical form. - // - static T& - convert (T& r) {return r;} - }; - - // pointer_cache_traits - // - // Caching traits for objects passed by pointer. P should be the canonical - // pointer (non-const). - // - template - struct no_op_pointer_cache_traits - { - typedef P pointer_type; - typedef typename pointer_traits::element_type object_type; - typedef typename object_traits::id_type id_type; - struct position_type {}; - - struct insert_guard - { - insert_guard () {} - insert_guard (const position_type&) {} - - position_type - position () const {return position_type ();} - - void - release () {} - - void - reset (const position_type&) {} - }; - - // Cache management. - // - static position_type - insert (odb::database&, const id_type&, const pointer_type&) - { - return position_type (); - } - - static position_type - insert (odb::database&, const pointer_type&) {return position_type ();} - - // Special signature for unique pointers. - // - static position_type - insert (odb::database&, void*) {return position_type ();} - - static pointer_type - find (odb::database&, const id_type&) {return pointer_type ();} - - static void - erase (const position_type&) {} - - // Notifications. - // - static void - persist (const position_type&) {} - - static void - load (const position_type&) {} - - static void - update (odb::database&, const object_type&) {} - - static void - erase (odb::database&, const id_type&) {} - }; - - template - struct no_id_pointer_cache_traits - { - typedef P pointer_type; - struct position_type {}; - - static position_type - insert (odb::database&, const pointer_type&) {return position_type ();} - - // Special signature for unique pointers. - // - static position_type - insert (odb::database&, void*) {return position_type ();} - - static void - persist (const position_type&) {} - - static void - load (const position_type&) {} - }; - - // reference_cache_traits - // - // Caching traits for objects passed by reference. T should be the - // canonical object type (non-const). - // - template - struct no_op_reference_cache_traits - { - typedef T object_type; - typedef typename object_traits::id_type id_type; - struct position_type {}; - - struct insert_guard - { - insert_guard () {} - insert_guard (const position_type&) {} - - position_type - position () const {return position_type ();} - - void - release () {} - - void - reset () {} - }; - - static position_type - insert (odb::database&, const id_type&, object_type&) - { - return position_type (); - } - - static position_type - insert (odb::database&, object_type&) {return position_type ();} - - static void - persist (const position_type&) {} - - static void - load (const position_type&) {} - }; - - template - struct no_id_reference_cache_traits - { - typedef T object_type; - struct position_type {}; - - static position_type - insert (odb::database&, object_type&) {return position_type ();} - - static void - persist (const position_type&) {} - - static void - load (const position_type&) {} - }; -} - -#include - -#endif // ODB_NO_OP_CACHE_TRAITS_HXX diff --git a/odb/nullable.hxx b/odb/nullable.hxx deleted file mode 100644 index d13f0c9..0000000 --- a/odb/nullable.hxx +++ /dev/null @@ -1,229 +0,0 @@ -// file : odb/nullable.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_NULLABLE_HXX -#define ODB_NULLABLE_HXX - -#include - -#include // odb::core - -namespace odb -{ - template - class nullable - { - public: - typedef T value_type; - - nullable (); - nullable (const T&); - nullable (const nullable&); - template explicit nullable (const nullable&); - - nullable& operator= (const T&); - nullable& operator= (const nullable&); - template nullable& operator= (const nullable&); - - void swap (nullable&); - - bool null () const; - - T& get (); - const T& get () const; - - T* operator-> (); - const T* operator-> () const; - - T& operator* (); - const T& operator* () const; - - typedef void (nullable::*bool_convertible) (); - operator bool_convertible () const - { - return null_ ? 0 : &nullable::true_value; - } - - void reset (); - - private: - void true_value () {}; - - T value_; - bool null_; - }; - - namespace common - { - using odb::nullable; - } - - template - inline bool - operator== (const nullable& x, const nullable& y) - { - return x.null () == y.null () && (x.null () || *x == *y); - } - - template - inline bool - operator!= (const nullable& x, const nullable& y) {return !(x == y);} - - template - inline bool - operator< (const nullable& x, const nullable& y) - { - return x.null () > y.null () || (!x.null () && !y.null () && *x < *y); - } - - template - inline bool - operator> (const nullable& x, const nullable& y) - { - return x.null () < y.null () || (!x.null () && !y.null () && *x > *y); - } - - template - inline bool - operator<= (const nullable& x, const nullable& y) {return !(x > y);} - - template - inline bool - operator>= (const nullable& x, const nullable& y) {return !(x < y);} - - template - inline nullable:: - nullable () - : null_ (true) - { - } - - template - inline nullable:: - nullable (const T& v) - : value_ (v), null_ (false) - { - } - - template - inline nullable:: - nullable (const nullable& y) - : value_ (y.value_), null_ (y.null_) - { - } - - template - template - inline nullable:: - nullable (const nullable& y) - : value_ (y.value_), null_ (y.null_) - { - } - - template - inline nullable& nullable:: - operator= (const T& v) - { - value_ = v; - null_ = false; - return *this; - } - - template - inline nullable& nullable:: - operator= (const nullable& y) - { - if (this != &y) - { - value_ = y.value_; - null_ = y.null_; - } - - return *this; - } - - template - template - inline nullable& nullable:: - operator= (const nullable& y) - { - value_ = y.value_; - null_ = y.null_; - return *this; - } - - template - inline void nullable:: - swap (nullable& y) - { - T v (value_); - bool n (null_); - - value_ = y.value_; - null_ = y.null_; - - y.value_ = v; - y.null_ = n; - } - - template - inline bool nullable:: - null () const - { - return null_; - } - - template - inline T& nullable:: - get () - { - return value_; - } - - template - inline const T& nullable:: - get () const - { - return value_; - } - - template - inline T* nullable:: - operator-> () - { - return null_ ? 0 : &value_; - } - - template - inline const T* nullable:: - operator-> () const - { - return null_ ? 0 : &value_; - } - - template - inline T& nullable:: - operator* () - { - return value_; - } - - template - inline const T& nullable:: - operator* () const - { - return value_; - } - - template - inline void nullable:: - reset () - { - value_ = T (); - null_ = true; - } -} - -#include - -#endif // ODB_NULLABLE_HXX diff --git a/odb/object-result.hxx b/odb/object-result.hxx deleted file mode 100644 index 056d518..0000000 --- a/odb/object-result.hxx +++ /dev/null @@ -1,164 +0,0 @@ -// file : odb/object-result.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_OBJECT_RESULT_HXX -#define ODB_OBJECT_RESULT_HXX - -#include - -#include // std::ptrdiff_t -#include // iterator categories - -#include -#include -#include -#include - -namespace odb -{ - // - // object_result_impl - // - template - class object_result_impl; - - template - class polymorphic_object_result_impl; - - template - class no_id_object_result_impl; - - // - // object_result_impl_selector - // - template ::id_type, - bool polymorphic = object_traits::polymorphic> - struct object_result_impl_selector; - - template - struct object_result_impl_selector - { - typedef object_result_impl type; - }; - - template - struct object_result_impl_selector - { - typedef polymorphic_object_result_impl type; - }; - - template - struct object_result_impl_selector - { - typedef no_id_object_result_impl type; - }; - - // - // result_iterator - // - - template - class object_result_iterator; - - template - class result_iterator: public object_result_iterator< - T, - typename object_traits::id_type, - object_traits::polymorphic> - { - public: - typedef T value_type; - typedef value_type& reference; - typedef value_type* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::input_iterator_tag iterator_category; - - // T can be const T while object_type is always non-const. - // - typedef - object_result_iterator::id_type, - object_traits::polymorphic> base_type; - - public: - explicit - result_iterator (typename base_type::result_impl_type* res = 0) - : base_type (res) - { - } - - // Input iterator requirements. - // - public: - reference - operator* () const - { - return pointer_traits::get_ref (this->res_->current ()); - } - - // Our value_type is already a pointer so return it instead of - // a pointer to it (operator-> will just have to go one deeper - // in the latter case). - // - pointer - operator-> () const - { - return pointer_traits::get_ptr (this->res_->current ()); - } - - result_iterator& - operator++ () - { - this->res_->next (); - return *this; - } - - result_iterator - operator++ (int) - { - // All non-end iterators for a result object move together. - // - this->res_->next (); - return *this; - } - - public: - bool - equal (result_iterator j) const - { - return (this->res_ ? this->res_->end () : true) == - (j.res_ ? j.res_->end () : true); - } - - private: - // Use unrestricted pointer traits since that's what is returned by - // result_impl. - // - typedef - odb::pointer_traits< - typename object_traits< - typename base_type::object_type>::pointer_type> - pointer_traits; - }; - - // - // - template - class result_base - { - public: - typedef typename object_traits::pointer_type value_type; - - // T can be const T while object_type is always non-const. - // - typedef typename object_traits::object_type object_type; - typedef - typename object_result_impl_selector::type - result_impl_type; - }; -} - -#include - -#endif // ODB_OBJECT_RESULT_HXX diff --git a/odb/pointer-traits.hxx b/odb/pointer-traits.hxx deleted file mode 100644 index a0baa21..0000000 --- a/odb/pointer-traits.hxx +++ /dev/null @@ -1,405 +0,0 @@ -// file : odb/pointer-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_POINTER_TRAITS_HXX -#define ODB_POINTER_TRAITS_HXX - -#include - -#include // operators new/delete -#include // std::auto_ptr, std::unique_ptr, std::shared_ptr/weak_ptr -#include // std::size_t - -#include // ODB_CXX11 -#include - -namespace odb -{ - enum pointer_kind - { - pk_raw, // Raw pointer or equivalent (i.e., unmanaged). - pk_unique, // Smart pointer that doesn't support sharing. - pk_shared, // Smart pointer that supports sharing. - pk_weak // Weak counterpart for shared pointer. - }; - - template - class pointer_traits; - - // - // Standard pointer guards. - // - - // Raw pointer guard. - // - template - class raw_ptr_guard - { - public: - ~raw_ptr_guard () {delete p_;} - raw_ptr_guard (): p_ (0) {} - - explicit - raw_ptr_guard (P p): p_ (p) {} - - void - release () {p_ = 0;} - - void - reset (P p = 0) {delete p_; p_ = p;} - - private: - P p_; - }; - - // No-op pointer guard for smart pointers. - // - template - class smart_ptr_guard - { - public: - smart_ptr_guard () {} - - explicit - smart_ptr_guard (const P&) {} - - void - release () {} - - void - reset () {} - - void - reset (const P&) {} - }; - - // Specialization for raw pointers. - // - template - class pointer_traits - { - public: - static const pointer_kind kind = pk_raw; - static const bool lazy = false; - - typedef T element_type; - typedef T* pointer_type; - typedef const T* const_pointer_type; - typedef typename odb::details::meta::remove_const::result* - unrestricted_pointer_type; - typedef raw_ptr_guard guard; - - // Return raw pointer to the pointed-to element, including NULL. - // - static element_type* - get_ptr (pointer_type p) - { - return p; - } - - // Return reference to the pointed-to element. - // - static element_type& - get_ref (pointer_type p) - { - return *p; - } - - // Return true if the pointer is NULL. - // - static bool - null_ptr (pointer_type p) - { - return p == 0; - } - - // Casts. - // - static unrestricted_pointer_type - const_pointer_cast (pointer_type p) - { - return const_cast (p); - } - - template - static T1* - static_pointer_cast (pointer_type p) - { - return static_cast (p); - } - - template - static T1* - dynamic_pointer_cast (pointer_type p) - { - return dynamic_cast (p); - } - - public: - // Allocate memory for an element that will be managed by this - // pointer. - // - static void* - allocate (std::size_t n) - { - return operator new (n); - } - - // Free memory allocated for an element. This functions is only - // called if the constructor of the element being created fails. - // Otherwise, the pointer (or guard) is used to delete the object - // and free the memory. This behavior is identical to the one - // used by operator delete overloading. - // - static void - free (void* p) - { - operator delete (p); - } - }; - - // Specialization for std::auto_ptr. - // -#ifndef ODB_CXX11 - template - class pointer_traits< std::auto_ptr > - { - public: - static const pointer_kind kind = pk_unique; - static const bool lazy = false; - - typedef T element_type; - typedef std::auto_ptr pointer_type; - typedef std::auto_ptr const_pointer_type; - typedef smart_ptr_guard 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.get () == 0; - } - - // const_pointer_cast() is not provided. - // - - // Note: transfers ownership. - // - template - static std::auto_ptr - static_pointer_cast (pointer_type& p) - { - return std::auto_ptr (static_cast (p.release ())); - } - - // Note: transfers ownership if successful. - // - template - static std::auto_ptr - dynamic_pointer_cast (pointer_type& p) - { - T1* p1 (dynamic_cast (p.get ())); - - if (p1 != 0) - p.release (); - - return std::auto_ptr (p1); - } - - public: - static void* - allocate (std::size_t n) - { - return operator new (n); - } - - static void - free (void* p) - { - operator delete (p); - } - }; -#endif - -#ifdef ODB_CXX11 - - // Specialization for C++11 std::unique_ptr. - // - template class D> - class pointer_traits>> - { - public: - static const pointer_kind kind = pk_unique; - static const bool lazy = false; - - typedef T element_type; - typedef std::unique_ptr> pointer_type; - typedef std::unique_ptr> const_pointer_type; - typedef smart_ptr_guard 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; - } - - // const_pointer_cast() is not provided. - // - - // Note: transfers ownership. - // - template - static std::unique_ptr> - static_pointer_cast (pointer_type& p) - { - return std::unique_ptr> (static_cast (p.release ())); - } - - // Note: transfers ownership if successful. - // - template - static std::unique_ptr> - dynamic_pointer_cast (pointer_type& p) - { - T1* p1 (dynamic_cast (p.get ())); - - if (p1 != 0) - p.release (); - - return std::unique_ptr> (p1); - } - - public: - static void* - allocate (std::size_t n) - { - return operator new (n); - } - - static void - free (void* p) - { - operator delete (p); - } - }; - - // Specialization for C++11 std::shared_ptr. - // - template - class pointer_traits> - { - public: - static const pointer_kind kind = pk_shared; - static const bool lazy = false; - - typedef T element_type; - typedef std::shared_ptr pointer_type; - typedef std::shared_ptr const_pointer_type; - typedef typename odb::details::meta::remove_const::result - unrestricted_element_type; - typedef std::shared_ptr - unrestricted_pointer_type; - typedef smart_ptr_guard 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; - } - - static unrestricted_pointer_type - const_pointer_cast (const pointer_type& p) - { - return std::const_pointer_cast (p); - } - - template - static std::shared_ptr - static_pointer_cast (const pointer_type& p) - { - return std::static_pointer_cast (p); - } - - template - static std::shared_ptr - dynamic_pointer_cast (const pointer_type& p) - { - return std::dynamic_pointer_cast (p); - } - - public: - static void* - allocate (std::size_t n) - { - return operator new (n); - } - - static void - free (void* p) - { - operator delete (p); - } - }; - - // Specialization for C++11 std::weak_ptr. - // - template - class pointer_traits> - { - public: - static const pointer_kind kind = pk_weak; - static const bool lazy = false; - - typedef T element_type; - typedef std::weak_ptr pointer_type; - typedef std::shared_ptr strong_pointer_type; - - static strong_pointer_type - lock (const pointer_type& p) - { - return p.lock (); - } - }; - -#endif // ODB_CXX11 - -} - -#include - -#endif // ODB_POINTER_TRAITS_HXX diff --git a/odb/polymorphic-info.hxx b/odb/polymorphic-info.hxx deleted file mode 100644 index 0f410d5..0000000 --- a/odb/polymorphic-info.hxx +++ /dev/null @@ -1,188 +0,0 @@ -// file : odb/polymorphic-info.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_POLYMORPHIC_INFO_HXX -#define ODB_POLYMORPHIC_INFO_HXX - -#include - -#include // std::size_t -#include - -#include // database, connection -#include -#include - -namespace odb -{ - template - struct polymorphic_abstract_info - { - typedef void (*section_load) (odb::connection&, R&, bool top); - typedef void (*section_update) (odb::connection&, const R&); - - struct section_functions - { - section_load load; - section_update update; - }; - - struct section_list - { - std::size_t count; - const section_functions* functions; - }; - - public: - polymorphic_abstract_info (const std::type_info& t, - const polymorphic_abstract_info* b, - const section_list* s) - : type (t), base (b), sections (s) {} - - bool - derived (const polymorphic_abstract_info& b) const - { - for (const polymorphic_abstract_info* p (base); p != 0; p = p->base) - if (&b == p) - return true; - - return false; - } - - // Find the "most overridden" section functions. - // - section_load - find_section_load (std::size_t index) const - { - for (const polymorphic_abstract_info* b (this); b != 0; b = b->base) - if (b->sections != 0 && - index < b->sections->count && - b->sections->functions[index].load != 0) - return b->sections->functions[index].load; - - return 0; - } - - section_update - find_section_update (std::size_t index) const - { - for (const polymorphic_abstract_info* b (this); b != 0; b = b->base) - if (b->sections != 0 && - index < b->sections->count && - b->sections->functions[index].update != 0) - return b->sections->functions[index].update; - - return 0; - } - - bool - final_section_update (const polymorphic_abstract_info& i, - std::size_t index) const - { - return i.sections != 0 && - index < i.sections->count && - i.sections->functions[index].update != 0 && - i.sections->functions[index].update == find_section_update (index); - } - - public: - const std::type_info& type; - const polymorphic_abstract_info* base; - - // Sections. - // - // There could be "concrete" (i.e., not overridden) section in an - // abstract class. Which means the section table has to be in - // abstract_info. - // - const section_list* sections; - }; - - template - struct polymorphic_concrete_info: polymorphic_abstract_info - { - // Have to use access::object_traits directly because of VC10. - // - typedef R root_type; - typedef access::object_traits root_traits; - typedef typename root_traits::id_type id_type; - typedef typename root_traits::pointer_type pointer_type; - typedef typename root_traits::discriminator_type discriminator_type; - - typedef typename polymorphic_abstract_info::section_list section_list; - - enum call_type - { - call_callback, // arg points to callback event. - call_persist, // arg is not used. - call_update, // arg is not used. - call_find, // arg points to object id. - call_reload, // arg is not used. - call_load, // arg points to depth. - call_erase // arg points to object id. - }; - - typedef pointer_type (*create_function) (); - typedef bool (*dispatch_function) ( - call_type, odb::database&, const root_type*, const void* arg); - typedef void (*delayed_loader_function) ( - odb::database&, - const id_type&, - root_type&, - const schema_version_migration*); - - public: - polymorphic_concrete_info (const std::type_info& t, - const polymorphic_abstract_info* b, - const section_list* s, - const discriminator_type& d, - create_function cf, - dispatch_function df, - delayed_loader_function dlf) - : polymorphic_abstract_info (t, b, s), - discriminator (d), - create (cf), dispatch (df), delayed_loader (dlf) - { - } - - public: - discriminator_type discriminator; - create_function create; - dispatch_function dispatch; - delayed_loader_function delayed_loader; - }; - - // Register concrete type T in the root's map. - // - template - struct polymorphic_entry - { - typedef T object_type; - typedef object_traits_impl object_traits; - typedef typename object_traits::root_type root_type; - - polymorphic_entry (); - ~polymorphic_entry (); - }; - - // Helper functions that either return the concrete info or NULL - // depending on what kind of info we pass (used in query support). - // - template - inline const polymorphic_concrete_info* - polymorphic_info (const polymorphic_concrete_info& i) - { - return &i; - } - - template - inline const polymorphic_concrete_info* - polymorphic_info (const polymorphic_abstract_info&) - { - return 0; - } -} - -#include - -#endif // ODB_POLYMORPHIC_INFO_HXX diff --git a/odb/polymorphic-map.hxx b/odb/polymorphic-map.hxx deleted file mode 100644 index 2e61314..0000000 --- a/odb/polymorphic-map.hxx +++ /dev/null @@ -1,276 +0,0 @@ -// file : odb/polymorphic-map.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_POLYMORPHIC_MAP_HXX -#define ODB_POLYMORPHIC_MAP_HXX - -#include - -#include -#include // std::move -#include // std::size_t -#include -#include - -#include - -#include // ODB_CXX11 -#include - -#include - -namespace odb -{ - template - struct polymorphic_map - { - typedef R root_type; - typedef polymorphic_concrete_info info_type; - typedef typename info_type::discriminator_type discriminator_type; - - polymorphic_map (): ref_count_ (1) {} - - const info_type& - find (const std::type_info& t) const; - - const info_type& - find (const discriminator_type& d) const; - - public: - typedef - std::map // VC bug. - type_map; - - struct discriminator_comparator - { - bool - operator() (const discriminator_type* x, - const discriminator_type* y) const - { - return *x < *y; - } - }; - - typedef - std::map - discriminator_map; - - public: - std::size_t ref_count_; - type_map type_map_; - discriminator_map discriminator_map_; - }; - - template - struct polymorphic_entry_impl - { - typedef R root_type; - typedef object_traits_impl root_traits; - typedef polymorphic_concrete_info info_type; - - static void - insert (const info_type&); - - static void - erase (const info_type&); - }; - - template - typename object_traits::root_type>::pointer_type - create_impl () - { - typedef object_traits derived_traits; - typedef object_traits root_traits; - - typedef typename derived_traits::pointer_type derived_pointer_type; - typedef typename root_traits::pointer_type root_pointer_type; - - derived_pointer_type p ( - access::object_factory::create ()); - - // Implicit downcast. - // -#ifdef ODB_CXX11 - root_pointer_type r (std::move (p)); -#else - root_pointer_type r (p); -#endif - return r; - } - - template - struct dispatch_load - { - static void - call (database& db, T& obj, std::size_t d) - { - object_traits_impl::load_ (db, obj, d); - } - }; - - template - struct dispatch_load - { - static void - call (database&, R&, std::size_t) - { - assert (false); - } - }; - - template - struct dispatch_persist - { - static void - call (database& db, const T& obj) - { - // Top-level call, no dynamic type checking. - // - object_traits_impl::persist (db, obj, true, false); - } - }; - - template - struct dispatch_persist - { - static void - call (database& db, const T& obj) - { - // Top-level call, no dynamic type checking. - // - object_traits_impl::persist ( - db, const_cast (obj), true, false); - } - }; - - template - bool - dispatch_impl ( - typename polymorphic_concrete_info< - typename object_traits::root_type>::call_type c, - database& db, - const typename object_traits::root_type* pobj, - const void* arg) - { - typedef object_traits_impl derived_traits; - typedef typename derived_traits::root_type root_type; - typedef object_traits_impl root_traits; - typedef typename root_traits::id_type id_type; - typedef polymorphic_concrete_info info_type; - - bool r (false); - - switch (c) - { - case info_type::call_callback: - { - derived_traits::callback ( - db, - *const_cast (static_cast (pobj)), - *static_cast (arg)); - break; - } - case info_type::call_persist: - { - dispatch_persist::call ( - db, - *static_cast (pobj)); - break; - } - case info_type::call_update: - { - derived_traits::update ( - db, - *static_cast (pobj), - true, // Top-level call. - false); // No dynamic type checking. - break; - } - case info_type::call_find: - { - r = derived_traits::find ( - db, - *static_cast (arg), - *const_cast (static_cast (pobj)), - false); // No dynamic type checking. - break; - } - case info_type::call_reload: - { - r = derived_traits::reload ( - db, - *const_cast (static_cast (pobj)), - false); // No dynamic type checking. - break; - } - case info_type::call_load: - { - dispatch_load::call ( - db, - *const_cast (static_cast (pobj)), - *static_cast (arg)); - break; - } - case info_type::call_erase: - { - if (pobj != 0) - derived_traits::erase ( - db, - *static_cast (pobj), - true, // Top-level call. - false); // No dynamic type checking. - else - derived_traits::erase ( - db, - *static_cast (arg), - true, // Top-level call. - false); // No dynamic type checking. - break; - } - } - - return r; - } - - template - void - section_load_impl (odb::connection& conn, - typename object_traits::root_type& obj, - bool top) - { - typedef object_traits_impl derived_traits; - typedef typename derived_traits::statements_type statements_type; - typedef typename statements_type::connection_type connection_type; - - connection_type& c (static_cast (conn)); - statements_type& sts (c.statement_cache ().template find_object ()); - - ST::load (sts.extra_statement_cache (), static_cast (obj), top); - } - - template - void - section_update_impl (odb::connection& conn, - const typename object_traits::root_type& obj) - { - typedef object_traits_impl derived_traits; - typedef typename derived_traits::statements_type statements_type; - typedef typename statements_type::connection_type connection_type; - - connection_type& c (static_cast (conn)); - statements_type& sts (c.statement_cache ().template find_object ()); - - ST::update (sts.extra_statement_cache (), static_cast (obj)); - } -} - -#include -#include - -#include - -#endif // ODB_POLYMORPHIC_MAP_HXX diff --git a/odb/polymorphic-map.ixx b/odb/polymorphic-map.ixx deleted file mode 100644 index 4e00c46..0000000 --- a/odb/polymorphic-map.ixx +++ /dev/null @@ -1,19 +0,0 @@ -// file : odb/polymorphic-map.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - template - inline polymorphic_entry:: - polymorphic_entry () - { - polymorphic_entry_impl::insert (object_traits::info); - } - - template - inline polymorphic_entry:: - ~polymorphic_entry () - { - polymorphic_entry_impl::erase (object_traits::info); - } -} diff --git a/odb/polymorphic-map.txx b/odb/polymorphic-map.txx deleted file mode 100644 index 9e0c0f0..0000000 --- a/odb/polymorphic-map.txx +++ /dev/null @@ -1,75 +0,0 @@ -// file : odb/polymorphic-map.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include // no_type_info - -namespace odb -{ - // - // polymorphic_map - // - - template - const typename polymorphic_map::info_type& polymorphic_map:: - find (const std::type_info& t) const - { - typename type_map::const_iterator i (type_map_.find (&t)); - - if (i != type_map_.end ()) - return *i->second; - else - throw no_type_info (); - } - - template - const typename polymorphic_map::info_type& polymorphic_map:: - find (const discriminator_type& d) const - { - typename discriminator_map::const_iterator i ( - discriminator_map_.find (&d)); - - if (i != discriminator_map_.end ()) - return *i->second; - else - throw no_type_info (); - } - - // - // polymorphic_entry_impl - // - - template - void polymorphic_entry_impl:: - insert (const info_type& i) - { - // VC10 cannot grok constructor call syntax here. - // - polymorphic_map*& pm = root_traits::map; - - if (pm == 0) - pm = new polymorphic_map; - else - pm->ref_count_++; - - pm->type_map_[&i.type] = &i; - pm->discriminator_map_[&i.discriminator] = &i; - } - - template - void polymorphic_entry_impl:: - erase (const info_type& i) - { - // VC10 cannot grok constructor call syntax here. - // - polymorphic_map*& pm = root_traits::map; - - pm->discriminator_map_.erase (&i.discriminator); - pm->type_map_.erase (&i.type); - - if (--pm->ref_count_ == 0) - { - delete pm; - pm = 0; - } - } -} diff --git a/odb/polymorphic-object-result.hxx b/odb/polymorphic-object-result.hxx deleted file mode 100644 index 5498856..0000000 --- a/odb/polymorphic-object-result.hxx +++ /dev/null @@ -1,224 +0,0 @@ -// file : odb/polymorphic-object-result.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_POLYMORPHIC_OBJECT_RESULT_HXX -#define ODB_POLYMORPHIC_OBJECT_RESULT_HXX - -#include - -#include // std::size_t -#include // std::move - -#include -#include -#include -#include -#include - -#include // ODB_CXX11 - -namespace odb -{ - // Implementation for polymorphic objects with object id. - // - template - class polymorphic_object_result_impl: public result_impl - { - protected: - // In result_impl, T is always non-const and the same as object_type. - // - typedef T object_type; - typedef odb::object_traits object_traits; - typedef typename object_traits::id_type id_type; - - typedef typename object_traits::pointer_type pointer_type; - typedef odb::pointer_traits pointer_traits; - - typedef typename object_traits::root_type root_type; - typedef odb::object_traits root_traits; - typedef typename root_traits::discriminator_type discriminator_type; - - friend class result; - friend class result; - friend class result_iterator; - friend class result_iterator; - friend class object_result_iterator; - friend class object_result_iterator; - - protected: - polymorphic_object_result_impl (odb::connection& conn) - : result_impl (conn), begin_ (true), end_ (false), current_ () - { - } - - // To make this work with all kinds of pointers (raw, std::auto_ptr, - // shared), we need to make sure we don't make any copies of the - // pointer on the return path. - // - pointer_type& - current () - { - if (pointer_traits::null_ptr (current_) && !end_) - load (); - - return current_; - } - - void - release () - { - current_ = pointer_type (); - guard_.release (); - } - - void - begin () - { - if (begin_) - { - next (); - begin_ = false; - } - } - - bool - end () const - { - return end_; - } - - protected: - // The fetch argument is a hint to the implementation. If it is - // false then it means load_id() was already called (and presumably - // fetched the data into the object image) and the object image - // is still valid (so the implementation doesn't need to fetch - // the data again). - // - // The load() signature differs from the non-polymorphic cases in - // that we pass a pointer to object instead of a reference. The - // object is only passed if the user requests loading into an - // existing instance. Otherwise, we pass NULL and load() is - // responsible for creating the object of a correct dynamic - // type and managing the object cache insertion. - // - virtual void - load (object_type*, bool fetch = true) = 0; - - virtual id_type - load_id () = 0; - - virtual discriminator_type - load_discriminator () = 0; - - virtual void - next () = 0; - - virtual void - cache () = 0; - - virtual std::size_t - size () = 0; - - protected: -#ifdef ODB_CXX11 - void - current (pointer_type& p, bool guard = true) - { - current_ = std::move (p); - - if (guard) - guard_.reset (current_); - else - guard_.reset (); - } - - void - current (pointer_type&& p, bool guard = true) - { - current (p, guard); - } -#else - void - current (pointer_type p, bool guard = true) - { - current_ = p; - - if (guard) - guard_.reset (current_); - else - guard_.reset (); - } -#endif - - bool begin_; - bool end_; - - private: - void - load (); - - private: - pointer_type current_; - typename pointer_traits::guard guard_; - }; - - template - class object_result_iterator - { - public: - // T can be const T while object_type is always non-const. - // - typedef typename object_traits::object_type object_type; - typedef typename object_traits::id_type id_type; - typedef typename object_traits::root_type root_type; - typedef typename object_traits::discriminator_type - discriminator_type; - - typedef polymorphic_object_result_impl result_impl_type; - - public: - object_result_iterator (result_impl_type* res) - : res_ (res) - { - } - - public: - typedef typename object_traits::pointer_type pointer_type; - - pointer_type - load () - { -#ifdef ODB_CXX11 - pointer_type r (std::move (res_->current ())); -#else - pointer_type r (res_->current ()); -#endif - res_->release (); - return r; - } - - void - load (object_type&); - - id_type - id () - { - return res_->load_id (); - } - - discriminator_type - discriminator () - { - return res_->load_discriminator (); - } - - protected: - result_impl_type* res_; - }; -} - -#include - -#include - -#endif // ODB_POLYMORPHIC_OBJECT_RESULT_HXX diff --git a/odb/polymorphic-object-result.txx b/odb/polymorphic-object-result.txx deleted file mode 100644 index d9252e9..0000000 --- a/odb/polymorphic-object-result.txx +++ /dev/null @@ -1,70 +0,0 @@ -// file : odb/polymorphic-object-result.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - // - // polymorphic_object_result_impl - // - - template - void polymorphic_object_result_impl:: - load () - { - typedef typename root_traits::pointer_type root_pointer_type; - typedef typename root_traits::pointer_traits root_pointer_traits; - - // First check the session. - // - const id_type& id (load_id ()); - - root_pointer_type rp ( - object_traits::pointer_cache_traits::find (this->db_, id)); - - if (!root_pointer_traits::null_ptr (rp)) - { - // Check if the types match. - // - pointer_type p ( - root_pointer_traits::template dynamic_pointer_cast< - object_type> (rp)); - - if (!pointer_traits::null_ptr (p)) - current (p, false); // Pointer from cache should not be guarded. - else - // We have an object in session that has a different type - // compared to the one in the database. - // - throw object_not_persistent (); // @@ type_mismatch? - } - else - // load() is responsible for creating the object of a correct - // dynamic type and for object cache insertion. - // - load (0, false); - } - - // - // object_result_iterator - // - - template - void object_result_iterator:: - load (object_type& obj) - { - if (res_->end ()) - return; - - typedef odb::object_traits object_traits; - - typename object_traits::reference_cache_traits::position_type p ( - object_traits::reference_cache_traits::insert ( - res_->db_, res_->load_id (), obj)); - typename object_traits::reference_cache_traits::insert_guard ig (p); - res_->load (&obj, false); - object_traits::reference_cache_traits::load (p); - ig.release (); - } -} diff --git a/odb/post.hxx b/odb/post.hxx deleted file mode 100644 index 3cdfd94..0000000 --- a/odb/post.hxx +++ /dev/null @@ -1,6 +0,0 @@ -// file : odb/post.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifdef _MSC_VER -# pragma warning (pop) -#endif diff --git a/odb/pre.hxx b/odb/pre.hxx deleted file mode 100644 index 088f172..0000000 --- a/odb/pre.hxx +++ /dev/null @@ -1,23 +0,0 @@ -// file : odb/pre.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifdef _MSC_VER - // Push warning state. - // -# pragma warning (push, 3) - - // Disabled warnings. - // -# pragma warning (disable:4068) // unknown pragma -# pragma warning (disable:4251) // needs to have DLL-interface -# pragma warning (disable:4290) // exception specification ignored -# pragma warning (disable:4355) // passing 'this' to a member -# pragma warning (disable:4800) // forcing value to bool -# pragma warning (disable:4231) // non-standard extension (extern template) -# pragma warning (disable:4275) // "C4251 is essentially noise and can be - // silenced" - Stephan T. Lavavej [And C4275 - // is essentially the same thing.] - // Elevated warnings. - // -# pragma warning (2:4239) // standard doesn't allow this conversion -#endif diff --git a/odb/prepared-query.cxx b/odb/prepared-query.cxx deleted file mode 100644 index 70bcaa1..0000000 --- a/odb/prepared-query.cxx +++ /dev/null @@ -1,47 +0,0 @@ -// file : odb/prepared-query.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include - -namespace odb -{ - prepared_query_impl:: - ~prepared_query_impl () - { - if (next_ != this) - list_remove (); - } - - prepared_query_impl:: - prepared_query_impl (connection& c) - : cached (false), conn (c), prev_ (0), next_ (this) - { - // Add to the list. - // - next_ = conn.prepared_queries_; - conn.prepared_queries_ = this; - - if (next_ != 0) - next_->prev_ = this; - } - - bool prepared_query_impl:: - verify_connection (transaction& t) - { - return &t.connection () == &stmt->connection (); - } - - void prepared_query_impl:: - list_remove () - { - (prev_ == 0 ? conn.prepared_queries_ : prev_->next_) = next_; - - if (next_ != 0) - next_->prev_ = prev_; - - prev_ = 0; - next_ = this; - } -} diff --git a/odb/prepared-query.hxx b/odb/prepared-query.hxx deleted file mode 100644 index 7cac6da..0000000 --- a/odb/prepared-query.hxx +++ /dev/null @@ -1,201 +0,0 @@ -// file : odb/prepared-query.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_PREPARED_QUERY_HXX -#define ODB_PREPARED_QUERY_HXX - -#include - -#include // odb::core -#include -#include -#include - -#include -#include - -namespace odb -{ - class LIBODB_EXPORT prepared_query_impl: public details::shared_base - { - public: - virtual - ~prepared_query_impl (); - - prepared_query_impl (connection&); - - // Verify this prepared query and the specified transaction use the - // same connection. - // - virtual bool - verify_connection (transaction&); - - bool cached; - connection& conn; - const char* name; - details::shared_ptr stmt; - details::shared_ptr (*execute) (prepared_query_impl&); - - private: - prepared_query_impl (const prepared_query_impl&); - prepared_query_impl& operator= (const prepared_query_impl&); - - // Doubly-linked list of results. - // - // prev_ == 0 means we are the first element. - // next_ == 0 means we are the last element. - // next_ == this means we are not on the list. - // - protected: - friend class connection; - - void - list_remove (); - - prepared_query_impl* prev_; - prepared_query_impl* next_; - }; - - template - struct prepared_query - { - // Cached version. - // - explicit - prepared_query (prepared_query_impl* impl = 0): impl_ (impl) {} - - // Uncached version. - // - explicit - prepared_query (const details::shared_ptr& impl) - : impl_ (impl.get ()) - { - impl_->_inc_ref (); - } - - result - execute (bool cache = true) - { - typedef - typename result_base::kind>::result_impl_type - derived_type; - - details::shared_ptr ri (impl_->execute (*impl_)); - result r ( - details::shared_ptr ( - static_cast (ri.release ()))); - - if (cache) - r.cache (); - - return r; - } - - typename object_traits::pointer_type - execute_one () - { - return execute (false).one (); - } - - bool - execute_one (T& object) - { - return execute (false).one (object); - } - - T - execute_value () - { - // Compiler error pointing here? The object must be default- - // constructible in order to use the return-by-value API. - // - T o; - execute (false).value (o); - return o; - } - - const char* - name () const - { - return impl_->name; - } - - typedef odb::statement statement_type; - - statement_type& - statement () const - { - return *impl_->stmt; - } - - typedef prepared_query_impl* prepared_query::*unspecified_bool_type; - operator unspecified_bool_type () const - { - return impl_ ? &prepared_query::impl_ : 0; - } - - public: - ~prepared_query () - { - if (impl_ != 0 && !impl_->cached && impl_->_dec_ref ()) - delete impl_; - } - - prepared_query (const prepared_query& x) - : impl_ (x.impl_) - { - if (!impl_->cached) - impl_->_inc_ref (); - } - - prepared_query& - operator= (const prepared_query& x) - { - if (impl_ != x.impl_) - { - if (impl_ != 0 && !impl_->cached && impl_->_dec_ref ()) - delete impl_; - - impl_ = x.impl_; - - if (!impl_->cached) - impl_->_inc_ref (); - } - - return *this; - } - - private: - // Ideally, we would just use shared_ptr to manage the impl object. - // However, there is a problem if the prepared query is cached on - // the connection and the connection is released early when the - // transaction is committed or rolled back. In this case, the - // prepared_query object might still be around pointing to impl. If - // this connection and the prepared query are then used by another - // thread while we release the impl object, then we have a race - // condition. - // - // To work around this problem we will simply "reference" the impl - // object without counting if the prepared query is cached. For - // transition from pointer to reference, see cache_query_() in - // connection.cxx. - // - // You may also observe that in order to know whether this is a - // cached prepared query or not, we have to read the cached data - // member in the impl object. This does not cause a race because, - // unlike the reference count, this member is immutable once set - // to true. - // - friend class connection; - prepared_query_impl* impl_; - }; - - namespace common - { - using odb::prepared_query; - } -} - -#include - -#endif // ODB_PREPARED_QUERY_HXX diff --git a/odb/query-dynamic.cxx b/odb/query-dynamic.cxx deleted file mode 100644 index bf9fd9c..0000000 --- a/odb/query-dynamic.cxx +++ /dev/null @@ -1,200 +0,0 @@ -// file : odb/query-dynamic.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -using namespace std; - -namespace odb -{ - // query_param - // - query_param:: - ~query_param () - { - } - - // query_base - // - void query_base:: - clear () - { - for (clause_type::iterator i (clause_.begin ()); i != clause_.end (); ++i) - { - if (i->kind == clause_part::kind_param_val || - i->kind == clause_part::kind_param_ref) - { - query_param* qp (reinterpret_cast (i->data)); - - if (qp != 0 && qp->_dec_ref ()) - delete qp; - } - } - - clause_.clear (); - strings_.clear (); - } - - void query_base:: - append (const string& native) - { - strings_.push_back (native); - clause_.push_back (clause_part ()); - clause_.back ().kind = clause_part::kind_native; - clause_.back ().data = strings_.size () - 1; - } - - void query_base:: - append (const query_base& x) - { - size_t i (clause_.size ()), delta (i); - size_t n (i + x.clause_.size ()); - clause_.resize (n); - - for (size_t j (0); i < n; ++i, ++j) - { - const clause_part& s (x.clause_[j]); - clause_part& d (clause_[i]); - - d = s; - - // We need to increment the param references, update pointers - // to strings and update argument positions. - // - switch (s.kind) - { - case clause_part::kind_param_val: - case clause_part::kind_param_ref: - { - reinterpret_cast (d.data)->_inc_ref (); - break; - } - case clause_part::kind_native: - { - strings_.push_back (x.strings_[s.data]); - d.data = strings_.size () - 1; - break; - } - case clause_part::op_add: - - case clause_part::op_and: - case clause_part::op_or: - - case clause_part::op_eq: - case clause_part::op_ne: - case clause_part::op_lt: - case clause_part::op_gt: - case clause_part::op_le: - case clause_part::op_ge: - { - d.data += delta; - break; - } - // Do not use default here to remember to handle new op codes. - // - case clause_part::kind_column: - case clause_part::kind_true: - case clause_part::kind_false: - case clause_part::op_not: - case clause_part::op_null: - case clause_part::op_not_null: - case clause_part::op_in: - case clause_part::op_like: - case clause_part::op_like_escape: - break; - } - } - } - - void query_base:: - append_ref (const void* ref, const native_column_info* c) - { - clause_.push_back (clause_part ()); - clause_part& p (clause_.back ()); - - p.kind = clause_part::kind_param_ref; - p.data = 0; // In case new below throws. - p.native_info = c; - - p.data = reinterpret_cast ( - new (details::shared) query_param (ref)); - } - - query_base& query_base:: - operator+= (const std::string& native) - { - if (!native.empty ()) - { - size_t p (clause_.size ()); - append (native); - - if (p != 0) - append (clause_part::op_add, p - 1); - } - - return *this; - } - - query_base& query_base:: - operator+= (const query_base& x) - { - if (!x.empty ()) - { - size_t p (clause_.size ()); - append (x); - - if (p != 0) - append (clause_part::op_add, p - 1); - } - - return *this; - } - - query_base - operator&& (const query_base& x, const query_base& y) - { - // Optimize cases where one or both sides are constant truth. - // - bool xt (x.const_true ()), yt (y.const_true ()); - - if (xt && yt) - return x; - - if (xt || x.empty ()) - return y; - - if (yt || y.empty ()) - return x; - - query_base r (x); - r.append (y); - r.append (query_base::clause_part::op_and, x.clause ().size () - 1); - return r; - } - - query_base - operator|| (const query_base& x, const query_base& y) - { - if (x.empty ()) - return y; - - if (y.empty ()) - return x; - - query_base r (x); - r.append (y); - r.append (query_base::clause_part::op_or, x.clause ().size () - 1); - return r; - } - - query_base - operator! (const query_base& x) - { - if (x.empty ()) - return x; - - query_base r (x); - r.append (query_base::clause_part::op_not, 0); - return r; - } -} diff --git a/odb/query-dynamic.hxx b/odb/query-dynamic.hxx deleted file mode 100644 index cd0ce05..0000000 --- a/odb/query-dynamic.hxx +++ /dev/null @@ -1,1067 +0,0 @@ -// file : odb/query-dynamic.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_QUERY_DYNAMIC_HXX -#define ODB_QUERY_DYNAMIC_HXX - -#include - -#include -#include -#include // std::size_t - -#include -#include - -#include -#include - -namespace odb -{ - struct native_column_info; - - template - struct val_bind - { - typedef const T& type; - - explicit - val_bind (type v): val (v) {} - - type val; - }; - - // Passing arrays by value in dynamic queries is not supported. - // Pass by reference instead. - // - template - struct val_bind; - - template - struct ref_bind - { - typedef const T& type; - - explicit - ref_bind (type r): ref (r) {} - - const void* - ptr () const {return &ref;} - - type ref; - }; - - template - struct ref_bind - { - typedef const T* type; - - explicit - ref_bind (type r): ref (r) {} - - // Allow implicit conversion from decayed ref_bind's. - // - ref_bind (ref_bind r): ref (r.ref) {} - ref_bind (ref_bind r): ref (r.ref) {} - - const void* - ptr () const {return ref;} - - type ref; - }; - - // - // - struct LIBODB_EXPORT query_param: details::shared_base - { - virtual ~query_param (); - query_param (const void* v): value (v) {} - - const void* value; - }; - - // For by-value parameters we have to make a copy since the original - // can be gone by the time we translate to native query. - // - template - struct val_query_param: query_param - { - val_query_param (const T& v): query_param (©), copy (v) {} - - T copy; - }; - - // - // - class LIBODB_EXPORT query_base - { - public: - // Internally the query clause is stored in a Reverse Polish Notation- - // like representation which also allows us to traverse it as a syntax - // tree. - // - // Let's keep this class POD so that std::vector can do more - // efficient copying, etc. - // - struct clause_part - { - // Note that the order of enumerators is important (used as indexes). - // - enum kind_type - { - kind_column, // native_info points to the native_column_info array. - - kind_param_val, // data points to query_param while native_info points - kind_param_ref, // to the native_column_info array. - - kind_native, // data is the index in the strings vector. - - kind_true, // true literal. - kind_false, // false literal. - - // Operators. - // - // For binary operators, data is the index of the last element - // belonging to the left hand side sub-expression. - // - op_add, // + (concatenation of two sub-expressions) - - op_and, // && - op_or, // || - op_not, // ! - - op_null, // is_null () - op_not_null, // is_not_null () - - op_in, // in(), data is the number of arguments - op_like, // like(pattern) - op_like_escape, // like(pattern, escape) - - op_eq, // == - op_ne, // != - op_lt, // < - op_gt, // > - op_le, // <= - op_ge // >= - }; - - kind_type kind; - std::size_t data; - const native_column_info* native_info; - }; - - public: - ~query_base () - { - clear (); - } - - query_base () {} - - // True or false literal. - // - explicit - query_base (bool v) - { - append (v ? clause_part::kind_true : clause_part::kind_false, 0); - } - - explicit - query_base (const char* native) - { - append (native); - } - - explicit - query_base (const std::string& native) - { - append (native); - } - - query_base (const query_column&); - - query_base (const query_base& x) - { - append (x); - } - - query_base& - operator= (const query_base& x) - { - if (this != &x) - { - clear (); - append (x); - } - - return *this; - } - - public: - template - static val_bind - _val (const T& x) - { - return val_bind (x); - } - - template - static ref_bind - _ref (const T& x) - { - return ref_bind (x); - } - - // Some compilers (notably VC++), when deducing const T& from const - // array do not strip const from the array type. As a result, in the - // above signatures we get, for example, T = const char[4] instead - // of T = char[4], which is what we want. So to "fix" such compilers, - // we will have to provide the following specialization of the above - // _ref() function (we don't need _val() since we don't support passing - // arrays by value; see val_bind definition). - // - template - static ref_bind - _ref (const T (&x) [N]) - { - return ref_bind (x); - } - - public: - query_base& - operator+= (const query_base&); - - query_base& - operator+= (const std::string& native); - - public: - bool - empty () const - { - return clause_.empty (); - } - - bool - const_true () const - { - return clause_.size () == 1 && - clause_.front ().kind == clause_part::kind_true; - } - - // Implementation details. - // - public: - explicit - query_base (const native_column_info* c) - { - append (c); - } - - // Native. - // - void - append (const std::string&); - - // Query fragment. - // - void - append (const query_base&); - - // Operator. - // - void - append (clause_part::kind_type k, std::size_t data) - { - clause_.push_back (clause_part ()); - clause_.back ().kind = k; - clause_.back ().data = data; - } - - // Column. - // - void - append (const native_column_info* c) - { - clause_.push_back (clause_part ()); - clause_.back ().kind = clause_part::kind_column; - clause_.back ().native_info = c; - } - - // Parameter. - // - void - append_ref (const void* ref, const native_column_info*); - - template - void - append_val (const T& val, const native_column_info*); - - void - clear (); - - public: - typedef std::vector clause_type; - typedef std::vector strings_type; - - const clause_type& - clause () const - { - return clause_; - } - - const strings_type& - strings () const - { - return strings_; - } - - private: - clause_type clause_; - strings_type strings_; - }; - - inline query_base - operator+ (const query_base& x, const query_base& y) - { - query_base r (x); - r += y; - return r; - } - - inline query_base - operator+ (const query_base& q, const std::string& s) - { - query_base r (q); - r += s; - return r; - } - - inline query_base - operator+ (const std::string& s, const query_base& q) - { - query_base r (s); - r += q; - return r; - } - - LIBODB_EXPORT query_base - operator&& (const query_base&, const query_base&); - - LIBODB_EXPORT query_base - operator|| (const query_base&, const query_base&); - - LIBODB_EXPORT query_base - operator! (const query_base&); - - // - // - struct native_column_info - { - const void* column; - void* param_factory; - }; - - template - const T& - type_instance (); - - // This class template has to remain POD since we rely on it being - // 0-initialized before any dynamic initialization takes place in - // any other translation unit. - // - template - struct query_column - { - // Array of pointers to database-specific columns. It will be - // automatically zero-initialized since query_column instances - // are always static. - // - native_column_info native_info[database_count]; - - // is_null, is_not_null - // - public: - query_base - is_null () const - { - query_base q (native_info); - q.append (query_base::clause_part::op_null, 0); - return q; - } - - query_base - is_not_null () const - { - query_base q (native_info); - q.append (query_base::clause_part::op_not_null, 0); - return q; - } - - // in - // - public: - query_base - in (const T&, const T&) const; - - query_base - in (const T&, const T&, const T&) const; - - query_base - in (const T&, const T&, const T&, const T&) const; - - query_base - in (const T&, const T&, const T&, const T&, const T&) const; - - template - query_base - in_range (I begin, I end) const; - - // like - // - public: - query_base - like (const T& pattern) const - { - return like (val_bind (pattern)); - } - - query_base - like (val_bind pattern) const; - - template - query_base - like (val_bind pattern) const - { - return like (val_bind (T (pattern.val))); - } - - query_base - like (ref_bind pattern) const; - - query_base - like (const T& pattern, const T& escape) const - { - return like (val_bind (pattern), escape); - } - - query_base - like (val_bind pattern, const T& escape) const; - - template - query_base - like (val_bind pattern, const T& escape) const - { - return like (val_bind (T (pattern.val)), escape); - } - - query_base - like (ref_bind pattern, const T& escape) const; - - // == - // - public: - query_base - equal (val_bind v) const - { - query_base q (native_info); - q.append_val (v.val, native_info); - q.append (query_base::clause_part::op_eq, 0); - return q; - } - - query_base - equal (ref_bind r) const - { - query_base q (native_info); - q.append_ref (r.ptr (), native_info); - q.append (query_base::clause_part::op_eq, 0); - return q; - } - - friend query_base - operator== (const query_column& c, const T& v) - { - return c.equal (val_bind (v)); - } - - friend query_base - operator== (const T& v, const query_column& c) - { - return c.equal (val_bind (v)); - } - - friend query_base - operator== (const query_column& c, val_bind v) - { - return c.equal (v); - } - - friend query_base - operator== (val_bind v, const query_column& c) - { - return c.equal (v); - } - - template - friend query_base - operator== (const query_column& c, val_bind v) - { - return c.equal (val_bind (T (v.val))); - } - - template - friend query_base - operator== (val_bind v, const query_column& c) - { - return c.equal (val_bind (T (v.val))); - } - - friend query_base - operator== (const query_column& c, ref_bind r) - { - return c.equal (r); - } - - friend query_base - operator== (ref_bind r, const query_column& c) - { - return c.equal (r); - } - - // != - // - public: - query_base - unequal (val_bind v) const - { - query_base q (native_info); - q.append_val (v.val, native_info); - q.append (query_base::clause_part::op_ne, 0); - return q; - } - - query_base - unequal (ref_bind r) const - { - query_base q (native_info); - q.append_ref (r.ptr (), native_info); - q.append (query_base::clause_part::op_ne, 0); - return q; - } - - friend query_base - operator!= (const query_column& c, const T& v) - { - return c.unequal (val_bind (v)); - } - - friend query_base - operator!= (const T& v, const query_column& c) - { - return c.unequal (val_bind (v)); - } - - friend query_base - operator!= (const query_column& c, val_bind v) - { - return c.unequal (v); - } - - friend query_base - operator!= (val_bind v, const query_column& c) - { - return c.unequal (v); - } - - template - friend query_base - operator!= (const query_column& c, val_bind v) - { - return c.unequal (val_bind (T (v.val))); - } - - template - friend query_base - operator!= (val_bind v, const query_column& c) - { - return c.unequal (val_bind (T (v.val))); - } - - friend query_base - operator!= (const query_column& c, ref_bind r) - { - return c.unequal (r); - } - - friend query_base - operator!= (ref_bind r, const query_column& c) - { - return c.unequal (r); - } - - // < - // - public: - query_base - less (val_bind v) const - { - query_base q (native_info); - q.append_val (v.val, native_info); - q.append (query_base::clause_part::op_lt, 0); - return q; - } - - query_base - less (ref_bind r) const - { - query_base q (native_info); - q.append_ref (r.ptr (), native_info); - q.append (query_base::clause_part::op_lt, 0); - return q; - } - - friend query_base - operator< (const query_column& c, const T& v) - { - return c.less (val_bind (v)); - } - - friend query_base - operator< (const T& v, const query_column& c) - { - return c.greater (val_bind (v)); - } - - friend query_base - operator< (const query_column& c, val_bind v) - { - return c.less (v); - } - - friend query_base - operator< (val_bind v, const query_column& c) - { - return c.greater (v); - } - - template - friend query_base - operator< (const query_column& c, val_bind v) - { - return c.less (val_bind (T (v.val))); - } - - template - friend query_base - operator< (val_bind v, const query_column& c) - { - return c.greater (val_bind (T (v.val))); - } - - friend query_base - operator< (const query_column& c, ref_bind r) - { - return c.less (r); - } - - friend query_base - operator< (ref_bind r, const query_column& c) - { - return c.greater (r); - } - - // > - // - public: - query_base - greater (val_bind v) const - { - query_base q (native_info); - q.append_val (v.val, native_info); - q.append (query_base::clause_part::op_gt, 0); - return q; - } - - query_base - greater (ref_bind r) const - { - query_base q (native_info); - q.append_ref (r.ptr (), native_info); - q.append (query_base::clause_part::op_gt, 0); - return q; - } - - friend query_base - operator> (const query_column& c, const T& v) - { - return c.greater (val_bind (v)); - } - - friend query_base - operator> (const T& v, const query_column& c) - { - return c.less (val_bind (v)); - } - - friend query_base - operator> (const query_column& c, val_bind v) - { - return c.greater (v); - } - - friend query_base - operator> (val_bind v, const query_column& c) - { - return c.less (v); - } - - template - friend query_base - operator> (const query_column& c, val_bind v) - { - return c.greater (val_bind (T (v.val))); - } - - template - friend query_base - operator> (val_bind v, const query_column& c) - { - return c.less (val_bind (T (v.val))); - } - - friend query_base - operator> (const query_column& c, ref_bind r) - { - return c.greater (r); - } - - friend query_base - operator> (ref_bind r, const query_column& c) - { - return c.less (r); - } - - // <= - // - public: - query_base - less_equal (val_bind v) const - { - query_base q (native_info); - q.append_val (v.val, native_info); - q.append (query_base::clause_part::op_le, 0); - return q; - } - - query_base - less_equal (ref_bind r) const - { - query_base q (native_info); - q.append_ref (r.ptr (), native_info); - q.append (query_base::clause_part::op_le, 0); - return q; - } - - friend query_base - operator<= (const query_column& c, const T& v) - { - return c.less_equal (val_bind (v)); - } - - friend query_base - operator<= (const T& v, const query_column& c) - { - return c.greater_equal (val_bind (v)); - } - - friend query_base - operator<= (const query_column& c, val_bind v) - { - return c.less_equal (v); - } - - friend query_base - operator<= (val_bind v, const query_column& c) - { - return c.greater_equal (v); - } - - template - friend query_base - operator<= (const query_column& c, val_bind v) - { - return c.less_equal (val_bind (T (v.val))); - } - - template - friend query_base - operator<= (val_bind v, const query_column& c) - { - return c.greater_equal (val_bind (T (v.val))); - } - - friend query_base - operator<= (const query_column& c, ref_bind r) - { - return c.less_equal (r); - } - - friend query_base - operator<= (ref_bind r, const query_column& c) - { - return c.greater_equal (r); - } - - // >= - // - public: - query_base - greater_equal (val_bind v) const - { - query_base q (native_info); - q.append_val (v.val, native_info); - q.append (query_base::clause_part::op_ge, 0); - return q; - } - - query_base - greater_equal (ref_bind r) const - { - query_base q (native_info); - q.append_ref (r.ptr (), native_info); - q.append (query_base::clause_part::op_ge, 0); - return q; - } - - friend query_base - operator>= (const query_column& c, const T& v) - { - return c.greater_equal (val_bind (v)); - } - - friend query_base - operator>= (const T& v, const query_column& c) - { - return c.less_equal (val_bind (v)); - } - - friend query_base - operator>= (const query_column& c, val_bind v) - { - return c.greater_equal (v); - } - - friend query_base - operator>= (val_bind v, const query_column& c) - { - return c.less_equal (v); - } - - template - friend query_base - operator>= (const query_column& c, val_bind v) - { - return c.greater_equal (val_bind (T (v.val))); - } - - template - friend query_base - operator>= (val_bind v, const query_column& c) - { - return c.less_equal (val_bind (T (v.val))); - } - - friend query_base - operator>= (const query_column& c, ref_bind r) - { - return c.greater_equal (r); - } - - friend query_base - operator>= (ref_bind r, const query_column& c) - { - return c.less_equal (r); - } - - // Column comparison. - // - public: - template - query_base - operator== (const query_column& c) const - { - // We can compare columns only if we can compare their C++ types. - // - (void) (sizeof (type_instance () == type_instance ())); - - query_base q (native_info); - q.append (c.native_info); - q.append (query_base::clause_part::op_eq, 0); - return q; - } - - template - query_base - operator!= (const query_column& c) const - { - // We can compare columns only if we can compare their C++ types. - // - (void) (sizeof (type_instance () != type_instance ())); - - query_base q (native_info); - q.append (c.native_info); - q.append (query_base::clause_part::op_ne, 0); - return q; - } - - template - query_base - operator< (const query_column& c) const - { - // We can compare columns only if we can compare their C++ types. - // - (void) (sizeof (type_instance () < type_instance ())); - - query_base q (native_info); - q.append (c.native_info); - q.append (query_base::clause_part::op_lt, 0); - return q; - } - - template - query_base - operator> (const query_column& c) const - { - // We can compare columns only if we can compare their C++ types. - // - (void) (sizeof (type_instance () > type_instance ())); - - query_base q (native_info); - q.append (c.native_info); - q.append (query_base::clause_part::op_gt, 0); - return q; - } - - template - query_base - operator<= (const query_column& c) const - { - // We can compare columns only if we can compare their C++ types. - // - (void) (sizeof (type_instance () <= type_instance ())); - - query_base q (native_info); - q.append (c.native_info); - q.append (query_base::clause_part::op_le, 0); - return q; - } - - template - query_base - operator>= (const query_column& c) const - { - // We can compare columns only if we can compare their C++ types. - // - (void) (sizeof (type_instance () >= type_instance ())); - - query_base q (native_info); - q.append (c.native_info); - q.append (query_base::clause_part::op_ge, 0); - return q; - } - }; - - // Provide operator+() for using columns to construct native - // query fragments (e.g., ORDER BY). - // - template - inline query_base - operator+ (const query_column& c, const std::string& s) - { - query_base q (c.native_info); - q.append (s); - q.append (query_base::clause_part::op_add, 0); - return q; - } - - template - inline query_base - operator+ (const std::string& s, const query_column& c) - { - query_base q (s); - q.append (c.native_info); - q.append (query_base::clause_part::op_add, 0); - return q; - } - - template - inline query_base - operator+ (const query_column& c, const query_base& q) - { - query_base r (c.native_info); - r.append (q); - r.append (query_base::clause_part::op_add, 0); - return r; - } - - template - inline query_base - operator+ (const query_base& q, const query_column& c) - { - query_base r (q); - r.append (c.native_info); - r.append (query_base::clause_part::op_add, q.clause ().size () - 1); - return r; - } - - // - // - template - class query: public query_base, - public query_selector::columns_type - { - public: - // We don't define any typedefs here since they may clash with - // column names defined by our base type. - // - - query () - { - } - - explicit - query (bool v) - : query_base (v) - { - } - - explicit - query (const char* q) - : query_base (q) - { - } - - explicit - query (const std::string& q) - : query_base (q) - { - } - - query (const query_base& q) - : query_base (q) - { - } - - query (const query_column& qc) - : query_base (qc) - { - } - }; -} - -#include -#include - -#include - -#endif // ODB_QUERY_DYNAMIC_HXX diff --git a/odb/query-dynamic.ixx b/odb/query-dynamic.ixx deleted file mode 100644 index 8de7b8e..0000000 --- a/odb/query-dynamic.ixx +++ /dev/null @@ -1,18 +0,0 @@ -// file : odb/query-dynamic.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // query_base - // - inline query_base:: - query_base (const query_column& c) - { - // Some databases provide the IS TRUE operator. However, we cannot - // use it since the column type might now be SQL boolean type. - // - append (c.native_info); - append_val (true, c.native_info); - append (query_base::clause_part::op_eq, 0); - } -} diff --git a/odb/query-dynamic.txx b/odb/query-dynamic.txx deleted file mode 100644 index 9ea16d2..0000000 --- a/odb/query-dynamic.txx +++ /dev/null @@ -1,139 +0,0 @@ -// file : odb/query-dynamic.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // query_base - // - - template - void query_base:: - append_val (const T& val, const native_column_info* c) - { - clause_.push_back (clause_part ()); - clause_part& p (clause_.back ()); - - p.kind = clause_part::kind_param_val; - p.data = 0; // In case new below throws. - p.native_info = c; - - query_param* qp (new (details::shared) val_query_param (val)); - p.data = reinterpret_cast (qp); - } - - // - // query_column - // - - // in - // - template - query_base query_column:: - in (const T& v1, const T& v2) const - { - query_base q (native_info); - q.append_val (v1, native_info); - q.append_val (v2, native_info); - q.append (query_base::clause_part::op_in, 2); - return q; - } - - template - query_base query_column:: - in (const T& v1, const T& v2, const T& v3) const - { - query_base q (native_info); - q.append_val (v1, native_info); - q.append_val (v2, native_info); - q.append_val (v3, native_info); - q.append (query_base::clause_part::op_in, 3); - return q; - } - - template - query_base query_column:: - in (const T& v1, const T& v2, const T& v3, const T& v4) const - { - query_base q (native_info); - q.append_val (v1, native_info); - q.append_val (v2, native_info); - q.append_val (v3, native_info); - q.append_val (v4, native_info); - q.append (query_base::clause_part::op_in, 4); - return q; - } - - template - query_base query_column:: - in (const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) const - { - query_base q (native_info); - q.append_val (v1, native_info); - q.append_val (v2, native_info); - q.append_val (v3, native_info); - q.append_val (v4, native_info); - q.append_val (v5, native_info); - q.append (query_base::clause_part::op_in, 5); - return q; - } - - template - template - query_base query_column:: - in_range (I i, I end) const - { - query_base q (native_info); - - std::size_t n (0); - for (; i != end; ++i, ++n) - q.append_val (*i, native_info); // Force implicit conversion. - - q.append (query_base::clause_part::op_in, n); - return q; - } - - // like - // - template - query_base query_column:: - like (val_bind p) const - { - query_base q (native_info); - q.append_val (p.val, native_info); - q.append (query_base::clause_part::op_like, 0); - return q; - } - - template - query_base query_column:: - like (ref_bind p) const - { - query_base q (native_info); - q.append_ref (p.ptr (), native_info); - q.append (query_base::clause_part::op_like, 0); - return q; - } - - template - query_base query_column:: - like (val_bind p, const T& e) const - { - query_base q (native_info); - q.append_val (p.val, native_info); - q.append_val (e, native_info); - q.append (query_base::clause_part::op_like_escape, 0); - return q; - } - - template - query_base query_column:: - like (ref_bind p, const T& e) const - { - query_base q (native_info); - q.append_ref (p.ptr (), native_info); - q.append_val (e, native_info); - q.append (query_base::clause_part::op_like_escape, 0); - return q; - } -} diff --git a/odb/query.hxx b/odb/query.hxx deleted file mode 100644 index 9375738..0000000 --- a/odb/query.hxx +++ /dev/null @@ -1,119 +0,0 @@ -// file : odb/query.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_QUERY_HXX -#define ODB_QUERY_HXX - -#include - -#include -#include - -namespace odb -{ - // Table alias for type T and tag Tag. - // - // The alias_traits interface consists of two things: the table_name - // static variable containing the name and, in case of a derived type - // in a polymorphic hierarchy, the base_traits typedef. Note that the - // same interface is exposed by object_traits, which is used when - // we need straight tables instead of aliases. - // - // - template - struct alias_traits; - - template - struct query_columns_base; - - template - struct query_columns; - - template - struct pointer_query_columns; - - // Object pointer syntax wrapper. - // - template - struct query_pointer - { - query_pointer () - { - // For some reason GCC needs this dummy c-tor if we make a static - // data member of this type const. - } - - T* - operator-> () const - { - return 0; // All members in T are static. - } - }; - - // Query parameter decay traits. - // - template - struct decay_traits - { - typedef const T& type; - - static type - instance (); - }; - - template - struct decay_traits - { - typedef const T* type; - - // Use the pointer comparability as a proxy for data comparability. - // Note that it is stricter than using element comparability (i.e., - // one can compare int to char but not int* to char*). - // - static type - instance (); - }; - - // VC9 cannot handle certain cases of non-type arguments with default - // values in template functions (e.g., database::query()). As a result, - // we have to use the impl trick below instead of simply having kind - // as a second template argument with a default value. - // - template - struct query_selector_impl; - - template - struct query_selector_impl - { - typedef typename object_traits_impl::query_base_type base_type; - - typedef - query_columns > - columns_type; - }; - - template - struct query_selector_impl - { - typedef typename view_traits_impl::query_base_type base_type; - typedef typename view_traits_impl::query_columns columns_type; - }; - - template - struct query_selector: query_selector_impl::kind> - { - }; - - template ::base_type> - class query; - - namespace core - { - using odb::query; - } -} - -#include - -#endif // ODB_QUERY_HXX diff --git a/odb/result.cxx b/odb/result.cxx deleted file mode 100644 index e9393ca..0000000 --- a/odb/result.cxx +++ /dev/null @@ -1,40 +0,0 @@ -// file : odb/result.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -namespace odb -{ - result_impl:: - ~result_impl () - { - if (next_ != this) - list_remove (); - } - - result_impl:: - result_impl (connection& c) - : db_ (c.database ()), conn_ (c), prev_ (0), next_ (this) - { - // Add to the list. - // - next_ = conn_.results_; - conn_.results_ = this; - - if (next_ != 0) - next_->prev_ = this; - } - - void result_impl:: - list_remove () - { - (prev_ == 0 ? conn_.results_ : prev_->next_) = next_; - - if (next_ != 0) - next_->prev_ = prev_; - - prev_ = 0; - next_ = this; - } -} diff --git a/odb/result.hxx b/odb/result.hxx deleted file mode 100644 index 87a6869..0000000 --- a/odb/result.hxx +++ /dev/null @@ -1,247 +0,0 @@ -// file : odb/result.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_RESULT_HXX -#define ODB_RESULT_HXX - -#include - -#include // std::ptrdiff_t, std::size_t - -#include // odb::core -#include - -#include -#include - -namespace odb -{ - class LIBODB_EXPORT result_impl: public details::shared_base - { - public: - virtual - ~result_impl (); - - virtual void - invalidate () = 0; - - protected: - result_impl (connection&); - - protected: - database& db_; - connection& conn_; - - // Doubly-linked list of results. - // - // prev_ == 0 means we are the first element. - // next_ == 0 means we are the last element. - // next_ == this means we are not on the list. - // - protected: - friend class connection; - - void - list_remove (); - - result_impl* prev_; - result_impl* next_; - }; - - template - class result_base; - - template ::kind> - class result_iterator; - - // Input iterator requirements. - // - template - inline bool - operator== (result_iterator i, result_iterator j) - { - return i.equal (j); - } - - template - inline bool - operator!= (result_iterator i, result_iterator j) - { - return !i.equal (j); - } - - template - class result: result_base::kind> - { - public: - static const class_kind kind = class_traits::kind; - - typedef result_base base; - - typedef typename base::value_type value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - - typedef result_iterator iterator; - - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - - typedef typename base::result_impl_type result_impl_type; - - public: - result () - { - } - - explicit - result (details::shared_ptr impl) - : impl_ (impl) - { - } - - // Copying or assignment of a result instance leads to one instance - // being an alias for another. Think of copying a result as copying - // a file handle -- the file you access through either of them is - // still the same. - // - public: - result (const result& r) - : impl_ (r.impl_) - { - } - - result& - operator= (const result& r) - { - if (impl_ != r.impl_) - impl_ = r.impl_; - - return *this; - } - - // Conversion from result to result. - // - template - result (const result& r) - // - // If you get a compiler error pointing to the line below saying - // that the impl_ member is inaccessible, then you are most likely - // trying to perform an illegal result conversion, for example, - // from result to result. - // - : impl_ (r.impl_) - { - } - - template - result& - operator= (const result& r) - { - // If you get a compiler error pointing to the line below saying - // that the impl_ member is inaccessible, then you are most likely - // trying to perform an illegal result conversion, for example, - // from result to result. - // - if (impl_ != r.impl_) - impl_ = r.impl_; - - return *this; - } - - void - swap (result& r) - { - // @@ add swap() to shared_ptr. - // - details::shared_ptr p (impl_); - impl_ = r.impl_; - r.impl_ = p; - } - - public: - iterator - begin () - { - if (impl_) - impl_->begin (); - - return iterator (impl_.get ()); - } - - iterator - end () - { - return iterator (); - } - - // Cache the result instead of fetching the data from the database - // one row at a time. This is necessary if you plan on performing - // database operations while iterating over the result. - // - public: - void - cache () - { - if (impl_) - impl_->cache (); - } - - public: - bool - empty () const - { - if (impl_ == 0) - return true; - - impl_->begin (); - return impl_->end (); - } - - // Size is only known in cached results. - // - size_type - size () const - { - return impl_ ? impl_->size () : 0; - } - - // query_one() and query_value() implementation details. - // - public: - typedef typename iterator::pointer_type pointer_type; - - pointer_type - one (); - - bool - one (T&); - - // We cannot return by value here since result can be instantiated - // for an abstract type (polymorphic abstract base) and it seems - // the signature must be valid to the point being able to call the - // necessary constructors. - // - void - value (T&); - - private: - friend class result; - - details::shared_ptr impl_; - }; - - namespace common - { - using odb::result; - using odb::result_iterator; - } -} - -#include - -#include - -#endif // ODB_RESULT_HXX diff --git a/odb/result.txx b/odb/result.txx deleted file mode 100644 index b69d92a..0000000 --- a/odb/result.txx +++ /dev/null @@ -1,49 +0,0 @@ -// file : odb/result.txx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - template - typename result::pointer_type result:: - one () - { - iterator i (begin ()); - - if (i != end ()) - { - pointer_type o (i.load ()); - assert (++i == end ()); // More than one element in query_one() result. - return o; - } - - return pointer_type (); - } - - template - bool result:: - one (T& o) - { - iterator i (begin ()); - - if (i != end ()) - { - i.load (o); - assert (++i == end ()); // More than one element in query_one() result. - return true; - } - - return false; - } - - template - void result:: - value (T& o) - { - iterator i (begin ()); - assert (i != end ()); // Zero elements in query_value() result. - i.load (o); - assert (++i == end ()); // More than one element in query_value() result. - } -} diff --git a/odb/schema-catalog-impl.hxx b/odb/schema-catalog-impl.hxx deleted file mode 100644 index dd729db..0000000 --- a/odb/schema-catalog-impl.hxx +++ /dev/null @@ -1,54 +0,0 @@ -// file : odb/schema-catalog-impl.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_SCHEMA_CATALOG_IMPL_HXX -#define ODB_SCHEMA_CATALOG_IMPL_HXX - -#include - -#include - -#include // schema_version - -#include - -namespace odb -{ - struct schema_catalog_impl; - - // Translation unit initializer. - // - struct LIBODB_EXPORT schema_catalog_init - { - static schema_catalog_impl* catalog; - static std::size_t count; - - schema_catalog_init (); - ~schema_catalog_init (); - }; - - static const schema_catalog_init schema_catalog_init_; - - // Catalog entry registration. - // - struct LIBODB_EXPORT schema_catalog_create_entry - { - schema_catalog_create_entry ( - database_id, - const char* name, - bool (*create_function) (database&, unsigned short pass, bool drop)); - }; - - struct LIBODB_EXPORT schema_catalog_migrate_entry - { - schema_catalog_migrate_entry ( - database_id, - const char* name, - schema_version, - bool (*migrate_function) (database&, unsigned short pass, bool pre)); - }; -} - -#include - -#endif // ODB_SCHEMA_CATALOG_IMPL_HXX diff --git a/odb/schema-catalog.cxx b/odb/schema-catalog.cxx deleted file mode 100644 index 1bdc112..0000000 --- a/odb/schema-catalog.cxx +++ /dev/null @@ -1,387 +0,0 @@ -// file : odb/schema-catalog.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include -#include - -#include -#include -#include - -using namespace std; - -namespace odb -{ - // Schema. - // - typedef bool (*create_function) (database&, unsigned short pass, bool drop); - typedef bool (*migrate_function) (database&, unsigned short pass, bool pre); - - typedef pair key; - typedef vector create_functions; - typedef vector migrate_functions; - typedef map version_map; - - struct schema_functions - { - create_functions create; - version_map migrate; - }; - typedef map schema_map; - - // Data. Normally the code would be database-independent, though there - // could be database-specific migration steps. - // - typedef pair data_key; - - struct data_function - { - typedef schema_catalog::data_migration_function_wrapper - function_wrapper_type; - - data_function () {} - data_function (database_id i, function_wrapper_type m) - : id (i), migrate (m) {} - - database_id id; - function_wrapper_type migrate; - }; - typedef vector data_functions; - typedef map data_map; - - struct schema_catalog_impl - { - schema_map schema; - data_map data; - }; - - // Static initialization. - // - schema_catalog_impl* schema_catalog_init::catalog = 0; - size_t schema_catalog_init::count = 0; - - struct schema_catalog_init_extra - { - bool initialized; - - schema_catalog_init_extra (): initialized (false) {} - ~schema_catalog_init_extra () - { - if (initialized && --schema_catalog_init::count == 0) - delete schema_catalog_init::catalog; - } - }; - - static schema_catalog_init_extra schema_catalog_init_extra_; - - bool schema_catalog:: - exists (database_id id, const string& name) - { - const schema_catalog_impl& c (*schema_catalog_init::catalog); - return c.schema.find (key (id, name)) != c.schema.end (); - } - - void schema_catalog:: - create_schema (database& db, const string& name, bool drop) - { - const schema_catalog_impl& c (*schema_catalog_init::catalog); - schema_map::const_iterator i (c.schema.find (key (db.id (), name))); - - if (i == c.schema.end ()) - throw unknown_schema (name); - - const create_functions& fs (i->second.create); - - if (drop) - drop_schema (db, name); - - // Run the passes until we ran them all or all the functions - // return false, which means no more passes necessary. - // - for (unsigned short pass (1); pass < 3; ++pass) - { - bool done (true); - - for (create_functions::const_iterator j (fs.begin ()), e (fs.end ()); - j != e; ++j) - { - if ((*j) (db, pass, false)) - done = false; - } - - if (done) - break; - } - } - - void schema_catalog:: - drop_schema (database& db, const string& name) - { - const schema_catalog_impl& c (*schema_catalog_init::catalog); - schema_map::const_iterator i (c.schema.find (key (db.id (), name))); - - if (i == c.schema.end ()) - throw unknown_schema (name); - - const create_functions& fs (i->second.create); - - // Run the passes until we ran them all or all the functions - // return false, which means no more passes necessary. - // - for (unsigned short pass (1); pass < 3; ++pass) - { - bool done (true); - - for (create_functions::const_iterator j (fs.begin ()), e (fs.end ()); - j != e; ++j) - { - if ((*j) (db, pass, true)) - done = false; - } - - if (done) - break; - } - } - - void schema_catalog:: - migrate_schema_impl (database& db, - schema_version v, - const string& name, - migrate_mode m) - { - const schema_catalog_impl& c (*schema_catalog_init::catalog); - schema_map::const_iterator i (c.schema.find (key (db.id (), name))); - - if (i == c.schema.end ()) - throw unknown_schema (name); - - const version_map& vm (i->second.migrate); - version_map::const_iterator j (vm.find (v)); - - if (j == vm.end ()) - throw unknown_schema_version (v); - - const migrate_functions& fs (j->second); - - // Run the passes until we ran them all or all the functions - // return false, which means no more passes necessary. - // - for (bool pre (m != migrate_post);; pre = false) - { - for (unsigned short pass (1); pass < 3; ++pass) - { - bool done (true); - - for (migrate_functions::const_iterator i (fs.begin ()), e (fs.end ()); - i != e; ++i) - { - if ((*i) (db, pass, pre)) - done = false; - } - - if (done) - break; - } - - if (!pre || m != migrate_both) - break; - } - - // Update the schema version on the database instance. - // - db.schema_version_migration (v, m == migrate_pre, name); - } - - size_t schema_catalog:: - migrate_data (database& db, schema_version v, const string& name) - { - if (v == 0) - { - if (!db.schema_migration ()) - return 0; - - v = db.schema_version (); - } - - const schema_catalog_impl& c (*schema_catalog_init::catalog); - data_map::const_iterator i (c.data.find (data_key (name, v))); - - if (i == c.data.end ()) - return 0; // No data migration for this schema/version. - - size_t r (0); - - const data_functions& df (i->second); - for (data_functions::const_iterator i (df.begin ()), e (df.end ()); - i != e; ++i) - { - if (i->id == id_common || i->id == db.id ()) - { - const data_migration_function_wrapper &m = i->migrate; - - if (m.std_function == 0) - m.function (db); - else - { - typedef void (*caller) (const void*, database&); - m.cast () (m.std_function, db); - } - r++; - } - } - - return r; - } - - void schema_catalog:: - data_migration_function (database_id id, - schema_version v, - data_migration_function_wrapper f, - const string& name) - { - // This function can be called from a static initializer in which - // case the catalog might not have yet been created. - // - if (schema_catalog_init::count == 0) - { - schema_catalog_init::catalog = new schema_catalog_impl; - ++schema_catalog_init::count; - schema_catalog_init_extra_.initialized = true; - } - - schema_catalog_impl& c (*schema_catalog_init::catalog); - c.data[data_key (name, v)].push_back (data_function (id, f)); - } - - void schema_catalog:: - migrate (database& db, schema_version v, const string& name) - { - schema_version cur (current_version (db, name)); - - if (v == 0) - v = cur; - else if (v > cur) - throw unknown_schema_version (v); - - schema_version i (db.schema_version (name)); - - if (i > v) - throw unknown_schema_version (i); // Database too new. - - // If there is no schema, then "migrate" by creating it. - // - if (i == 0) - { - // Schema creation can only "migrate" straight to current. - // - if (v != cur) - throw unknown_schema_version (v); - - create_schema (db, name, false); - return; - } - - for (i = next_version (db, i, name); - i <= v; - i = next_version (db, i, name)) - { - migrate_schema_pre (db, i, name); - migrate_data (db, i, name); - migrate_schema_post (db, i, name); - } - } - - schema_version schema_catalog:: - base_version (database_id id, const string& name) - { - const schema_catalog_impl& c (*schema_catalog_init::catalog); - schema_map::const_iterator i (c.schema.find (key (id, name))); - - if (i == c.schema.end ()) - throw unknown_schema (name); - - const version_map& vm (i->second.migrate); - assert (!vm.empty ()); - return vm.begin ()->first; - } - - schema_version schema_catalog:: - current_version (database_id id, const string& name) - { - const schema_catalog_impl& c (*schema_catalog_init::catalog); - schema_map::const_iterator i (c.schema.find (key (id, name))); - - if (i == c.schema.end ()) - throw unknown_schema (name); - - const version_map& vm (i->second.migrate); - assert (!vm.empty ()); - return vm.rbegin ()->first; - } - - schema_version schema_catalog:: - next_version (database_id id, schema_version v, const string& name) - { - const schema_catalog_impl& sc (*schema_catalog_init::catalog); - schema_map::const_iterator i (sc.schema.find (key (id, name))); - - if (i == sc.schema.end ()) - throw unknown_schema (name); - - const version_map& vm (i->second.migrate); // Cannot be empty. - - schema_version b (vm.begin ()->first); - schema_version c (vm.rbegin ()->first); - - if (v == 0) - return c; // "Migration" to the current via schema creation. - else if (v < b) - throw unknown_schema_version (v); // Unsupported migration. - - version_map::const_iterator j (vm.upper_bound (v)); - return j != vm.end () ? j->first : c + 1; - } - - // schema_catalog_init - // - schema_catalog_init:: - schema_catalog_init () - { - if (count == 0) - catalog = new schema_catalog_impl; - - ++count; - } - - schema_catalog_init:: - ~schema_catalog_init () - { - if (--count == 0) - delete catalog; - } - - // schema_catalog_create_entry - // - schema_catalog_create_entry:: - schema_catalog_create_entry (database_id id, - const char* name, - create_function cf) - { - schema_catalog_impl& c (*schema_catalog_init::catalog); - c.schema[key(id, name)].create.push_back (cf); - } - - // schema_catalog_migrate_entry - // - schema_catalog_migrate_entry:: - schema_catalog_migrate_entry (database_id id, - const char* name, - schema_version v, - migrate_function mf) - { - schema_catalog_impl& c (*schema_catalog_init::catalog); - c.schema[key(id, name)].migrate[v].push_back (mf); - } -} diff --git a/odb/schema-catalog.hxx b/odb/schema-catalog.hxx deleted file mode 100644 index c38cd4f..0000000 --- a/odb/schema-catalog.hxx +++ /dev/null @@ -1,392 +0,0 @@ -// file : odb/schema-catalog.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_SCHEMA_CATALOG_HXX -#define ODB_SCHEMA_CATALOG_HXX - -#include - -#include // ODB_CXX11 - -#include -#include // std::size_t - -#ifdef ODB_CXX11 -# include // std::move -# include // std::function -# include // std::enable_if, std::is_convertible -#endif - -#include // schema_version, odb::core -#include - -#include -#include -#include - -namespace odb -{ - class LIBODB_EXPORT schema_catalog - { - public: - // Schema creation. - // - static void - create_schema (database&, const std::string& name = "", bool drop = true); - - static void - drop_schema (database&, const std::string& name = ""); - - // Schema migration. - // - public: - static void - migrate_schema_pre (database& db, - schema_version v, - const std::string& name = "") - { - migrate_schema_impl (db, v, name, migrate_pre); - } - - static void - migrate_schema_post (database& db, - schema_version v, - const std::string& name = "") - { - migrate_schema_impl (db, v, name, migrate_post); - } - - static void - migrate_schema (database& db, - schema_version v, - const std::string& name = "") - { - migrate_schema_impl (db, v, name, migrate_both); - } - - // Data migration. - // - public: - // If version is 0, then use the current database version and also - // check whether we are in migration. Returns the number of calls made. - // - static std::size_t - migrate_data (database&, - schema_version = 0, - const std::string& name = ""); - - typedef void data_migration_function_type (database&); - typedef data_migration_function_type* data_migration_function_ptr; - - typedef details::function_wrapper - data_migration_function_wrapper; - - // The following three variants of the registration functions make - // sure that the version is greater that the base model version. - // This helps with identifying and removing data migration function - // that are no longer required. - // - // Data migration functions are called in the order of registration. - // -#ifndef ODB_CXX11 - template - static void - data_migration_function (data_migration_function_ptr f, - const std::string& name = "") - { - data_migration_function (id_common, f, name); - } - -#else - template - static typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - data_migration_function (F f, const std::string& name = "") - { - data_migration_function (id_common, std::move (f), name); - } -#endif - - // Database-specific data migration. - // -#ifndef ODB_CXX11 - template - static void - data_migration_function (database& db, - data_migration_function_ptr f, - const std::string& name = "") - { - data_migration_function (db.id (), f, name); - } -#else - template - static typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - data_migration_function (database& db, F f, const std::string& name = "") - { - data_migration_function (db.id (), std::move (f), name); - } -#endif - -#ifndef ODB_CXX11 - template - static void - data_migration_function (database_id id, - data_migration_function_ptr f, - const std::string& name = "") - { - // If the data migration version is below the base model version - // then it will never be called. - // - - // Poor man's static_assert. - // - typedef details::meta::static_assert_test<(v > base || base == 0)> - data_migration_function_is_no_longer_necessary; - - char sa [sizeof (data_migration_function_is_no_longer_necessary)]; - ODB_POTENTIALLY_UNUSED (sa); - - data_migration_function (id, v, f, name); - } -#else - template - static typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - data_migration_function (database_id id, F f, const std::string& name = "") - { - // If the data migration version is below the base model version - // then it will never be called. - // - static_assert (v > base || base == 0, - "data migration function is no longer necessary"); - - data_migration_function (id, v, std::move (f), name); - } -#endif - - // The same as above but take the version as an argument and do - // not check whether it is greater than the base model version. - // -#ifndef ODB_CXX11 - static void - data_migration_function (schema_version v, - data_migration_function_ptr f, - const std::string& name = "") - { - data_migration_function (id_common, v, f, name); - } -#else - template - static typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - data_migration_function (schema_version v, - F f, - const std::string& name = "") - { - data_migration_function (id_common, v, std::move (f), name); - } -#endif - -#ifndef ODB_CXX11 - static void - data_migration_function (database& db, - schema_version v, - data_migration_function_ptr f, - const std::string& name = "") - { - data_migration_function (db.id (), v, f, name); - } -#else - template - static typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - data_migration_function (database& db, - schema_version v, - F f, - const std::string& name = "") - { - data_migration_function (db.id (), v, std::move (f), name); - } -#endif - -#ifndef ODB_CXX11 - static void - data_migration_function (database_id i, - schema_version v, - data_migration_function_ptr f, - const std::string& name = "") - { - data_migration_function (i, - v, - data_migration_function_wrapper (f), - name); - } -#else - template - static typename std::enable_if< - std::is_convertible< - F, std::function>::value, void>::type - data_migration_function (database_id i, - schema_version v, - F f, - const std::string& name = "") - { - data_migration_function ( - i, - v, - data_migration_function_wrapper (std::move (f)), - name); - } -#endif - - private: - static void - data_migration_function (database_id, - schema_version, - data_migration_function_wrapper, - const std::string& name); - - // Combined schema and data migration. - // - public: - // Migrate both schema and data to the specified version. If version - // is not specified, then migrate to the current model version. - // - static void - migrate (database&, schema_version = 0, const std::string& name = ""); - - // Schema version information. - // - public: - // Return the base model version. - // - static schema_version - base_version (const database& db, const std::string& name = "") - { - return base_version (db.id (), name); - } - - static schema_version - base_version (database_id, const std::string& name = ""); - - // Return the current model version. - // - static schema_version - current_version (const database& db, const std::string& name = "") - { - return current_version (db.id (), name); - } - - static schema_version - current_version (database_id, const std::string& name = ""); - - // Return current model version + 1 (that is, one past current) if - // the passed version is equal to or greater than current. If the - // version is not specified, then use the current database version. - // - static schema_version - next_version (const database& db, - schema_version v = 0, - const std::string& name = "") - { - return next_version (db.id (), v == 0 ? db.schema_version () : v, name); - } - - static schema_version - next_version (database_id, - schema_version, - const std::string& name = ""); - - // Schema existence. - // - public: - // Test for presence of a schema with a specific name. - // - static bool - exists (const database& db, const std::string& name = "") - { - return exists (db.id (), name); - } - - static bool - exists (database_id, const std::string& name = ""); - - private: - enum migrate_mode - { - migrate_pre, - migrate_post, - migrate_both - }; - - static void - migrate_schema_impl (database&, - schema_version, - const std::string& name, - migrate_mode); - }; - - // Static data migration function registration. - // - template - struct data_migration_entry - { - typedef schema_catalog::data_migration_function_type function_type; - -#ifndef ODB_CXX11 - data_migration_entry (function_type* f, const std::string& name = "") - { - schema_catalog::data_migration_function (f, name); - } -#else - template - data_migration_entry (F f, - const std::string& name = "", - typename std::enable_if>::value> - ::type* = 0) - { - schema_catalog::data_migration_function (std::move (f), name); - } -#endif - -#ifndef ODB_CXX11 - data_migration_entry (database_id id, - function_type *f, - const std::string& name = "") - { - schema_catalog::data_migration_function (id, v, f, name); - } -#else - template - data_migration_entry (database_id id, - F f, - const std::string& name = "", - typename std::enable_if>::value> - ::type* = 0) - { - schema_catalog::data_migration_function (id, - v, - std::move (f), - name); - } -#endif - }; - - namespace common - { - using odb::schema_catalog; - using odb::data_migration_entry; - } -} - -#include - -#endif // ODB_SCHEMA_CATALOG_HXX diff --git a/odb/schema-version.hxx b/odb/schema-version.hxx deleted file mode 100644 index 1f047a4..0000000 --- a/odb/schema-version.hxx +++ /dev/null @@ -1,71 +0,0 @@ -// file : odb/schema-version.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_SCHEMA_VERSION_HXX -#define ODB_SCHEMA_VERSION_HXX - -#include - -#include // schema_version - -namespace odb -{ - struct schema_version_migration - { - schema_version_migration (schema_version v = 0, bool m = false) - : version (v), migration (m) {} - - schema_version version; - bool migration; - }; - - // Version ordering is as follows: {1,f} < {2,t} < {2,f} < {3,t} - // - inline bool - operator== (const schema_version_migration& x, - const schema_version_migration& y) - { - return x.version == y.version && x.migration == y.migration; - } - - inline bool - operator!= (const schema_version_migration& x, - const schema_version_migration& y) - { - return !(x == y); - } - - inline bool - operator< (const schema_version_migration& x, - const schema_version_migration& y) - { - return x.version < y.version || - (x.version == y.version && x.migration && !y.migration); - } - - inline bool - operator> (const schema_version_migration& x, - const schema_version_migration& y) - { - return x.version > y.version || - (x.version == y.version && !x.migration && y.migration); - } - - inline bool - operator<= (const schema_version_migration& x, - const schema_version_migration& y) - { - return !(x > y); - } - - inline bool - operator>= (const schema_version_migration& x, - const schema_version_migration& y) - { - return !(x < y); - } -} - -#include - -#endif // ODB_SCHEMA_VERSION_HXX diff --git a/odb/section.cxx b/odb/section.cxx deleted file mode 100644 index 0fe5211..0000000 --- a/odb/section.cxx +++ /dev/null @@ -1,27 +0,0 @@ -// file : odb/section.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - void section:: - disarm () - { - transaction& t (transaction::current ()); - t.callback_unregister (this); - state_.armed = 0; - } - - void section:: - transacion_callback (unsigned short event, void* key, unsigned long long) - { - section& s (*static_cast (key)); - - if (event == transaction::event_rollback && s.state_.restore) - s.state_.changed = 1; - - s.state_.armed = 0; - s.state_.restore = 0; - } -} diff --git a/odb/section.hxx b/odb/section.hxx deleted file mode 100644 index 98b98cf..0000000 --- a/odb/section.hxx +++ /dev/null @@ -1,122 +0,0 @@ -// file : odb/section.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_SECTION_HXX -#define ODB_SECTION_HXX - -#include - -#include -#include - -namespace odb -{ - class LIBODB_EXPORT section - { - public: - // Load state. - // - bool - loaded () const {return state_.loaded;} - - // Mark a loaded section as not loaded. This, for example, can be - // useful if you don't want the section to be reloaded during the - // object reload. - // - void - unload () - { - state_.loaded = 0; - state_.changed = 0; - state_.restore = 0; - } - - // Mark an unloaded section as loaded. This, for example, can be useful if - // you don't want to load the old data before overwriting it with update(). - // - void - load () - { - state_.loaded = 1; - } - - // Change state. - // - bool - changed () const {return state_.changed;} - - // Mark the section as changed. - // - void - change () - { - state_.changed = 1; - state_.restore = 0; - } - - // User data. 4 bits of custom state. - // - unsigned char - user_data () const {return state_.user;} - - void - user_data (unsigned char u) {state_.user = u;} - - public: - section () - { - state_.loaded = 0; - state_.changed = 0; - state_.armed = 0; - state_.restore = 0; - } - - ~section () - { - if (state_.armed) - disarm (); - } - - // Implementation details. - // - public: - // Arm the callback and set the restore flag if transaction is not NULL. - // - void - reset (bool l = false, bool c = false, transaction* t = 0) const - { - state_.loaded = l; - state_.changed = c; - - if (t != 0 && !state_.armed) - { - t->callback_register (&transacion_callback, - const_cast (this)); - state_.armed = 1; - } - - state_.restore = (t != 0); - } - - private: - void - disarm (); - - static void - transacion_callback (unsigned short, void* key, unsigned long long); - - private: - mutable struct - { - unsigned char loaded : 1; - unsigned char changed : 1; - unsigned char armed : 1; // Transaction callback is armed. - unsigned char restore: 1; // Restore changed flag on rollback. - unsigned char user : 4; // User data. - } state_; - }; -} - -#include - -#endif // ODB_SECTION_HXX diff --git a/odb/session.cxx b/odb/session.cxx deleted file mode 100644 index bc0e854..0000000 --- a/odb/session.cxx +++ /dev/null @@ -1,66 +0,0 @@ -// file : odb/session.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -#include - -namespace odb -{ - using namespace details; - - static ODB_TLS_POINTER (session) current_session; - - session:: - session (bool make_current) - { - if (make_current) - { - if (has_current ()) - throw already_in_session (); - - current_pointer (this); - } - } - - session:: - ~session () - { - // If we are the current thread's session, reset it. - // - if (current_pointer () == this) - reset_current (); - } - - session* session:: - current_pointer () - { - return tls_get (current_session); - } - - void session:: - current_pointer (session* s) - { - tls_set (current_session, s); - } - - session& session:: - current () - { - session* cur (tls_get (current_session)); - - if (cur == 0) - throw not_in_session (); - - return *cur; - } - - // - // object_map_base - // - session::object_map_base:: - ~object_map_base () - { - } -} diff --git a/odb/session.hxx b/odb/session.hxx deleted file mode 100644 index a14c42f..0000000 --- a/odb/session.hxx +++ /dev/null @@ -1,217 +0,0 @@ -// file : odb/session.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_SESSION_HXX -#define ODB_SESSION_HXX - -#include - -#include -#include - -#include -#include - -#include -#include - -#include - -namespace odb -{ - class LIBODB_EXPORT session - { - public: - typedef odb::database database_type; - - // If the make_current argument is true, then set the current thread's - // session to this session. If another session is already in effect, - // throw the already_in_session exception. - // - session (bool make_current = true); - - // Reset the current thread's session if it is this session. - // - ~session (); - - // Current session. - // - public: - // Return true if there is a session in effect in the current - // thread. - // - static bool - has_current () {return current_pointer () != 0;} - - // Get current thread's session. Throw if no session is in effect. - // - static session& - current (); - - // Set current thread's session. - // - static void - current (session& s) {current_pointer (&s);} - - // Revert to the no session in effect state for the current thread. - // - static void - reset_current () {current_pointer (0);} - - // Pointer versions. - // - static session* - current_pointer (); - - static void - current_pointer (session*); - - // Copying or assignment of sessions is not supported. - // - private: - session (const session&); - session& operator= (const session&); - - public: - struct LIBODB_EXPORT object_map_base: details::shared_base - { - virtual - ~object_map_base (); - }; - - template - struct object_map: object_map_base, - std::map::id_type, - typename object_traits::pointer_type> - { - }; - - // Object cache. - // - public: - // Position in the cache of the inserted element. - // - template - struct cache_position; - - template - cache_position - cache_insert (database_type&, - const typename object_traits::id_type&, - const typename object_traits::pointer_type&); - - template - typename object_traits::pointer_type - cache_find (database_type&, - const typename object_traits::id_type&) const; - - template - void - cache_erase (const cache_position&); - - template - void - cache_erase (database_type&, const typename object_traits::id_type&); - - // Low-level object cache access (iteration, etc). - // - public: - typedef std::map, - details::type_info_comparator> type_map; - - typedef std::map database_map; - - database_map& - map () {return db_map_;} - - const database_map& - map () const {return db_map_;} - - // Static cache API as expected by the rest of ODB. - // - public: - static bool - _has_cache () {return has_current ();} - - // Position in the cache of the inserted element. The requirements - // for this class template are: default and copy-constructible as - // well as copy-assignable. The default constructor creates an - // empty/NULL position. - // - template - struct cache_position - { - typedef object_map map; - typedef typename map::iterator iterator; - - cache_position (): map_ (0) {} - cache_position (map& m, const iterator& p): map_ (&m), pos_ (p) {} - - cache_position (const cache_position& p) - : map_ (p.map_), pos_ (p.pos_) {} - - cache_position& - operator= (const cache_position& p) - { - // It might not be ok to use an uninitialized iterator on the rhs. - // - if (p.map_ != 0) - pos_ = p.pos_; - map_ = p.map_; - return *this; - } - - map* map_; - iterator pos_; - }; - - // The following cache management functions are all static to - // allow for a custom notion of a current session. The erase() - // function is called to remove the object if the operation - // that caused it to be inserted (e.g., load) failed. - // - template - static cache_position - _cache_insert (database_type&, - const typename object_traits::id_type&, - const typename object_traits::pointer_type&); - - template - static typename object_traits::pointer_type - _cache_find (database_type&, const typename object_traits::id_type&); - - template - static void - _cache_erase (const cache_position&); - - // Notifications. These are called after per-object callbacks for - // post_{persist, load, update, erase} events. - // - template - static void - _cache_persist (const cache_position&) {} - - template - static void - _cache_load (const cache_position&) {} - - template - static void - _cache_update (database_type&, const T&) {} - - template - static void - _cache_erase (database_type&, const typename object_traits::id_type&); - - protected: - database_map db_map_; - }; -} - -#include -#include - -#include - -#endif // ODB_SESSION_HXX diff --git a/odb/session.ixx b/odb/session.ixx deleted file mode 100644 index 4acdc1b..0000000 --- a/odb/session.ixx +++ /dev/null @@ -1,60 +0,0 @@ -// file : odb/session.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - template - inline void session:: - cache_erase (const cache_position& p) - { - // @@ Empty maps are not cleaned up by this version of erase. - // - if (p.map_ != 0) - p.map_->erase (p.pos_); - } - - template - inline typename session::cache_position session:: - _cache_insert (database_type& db, - const typename object_traits::id_type& id, - const typename object_traits::pointer_type& obj) - { - if (session* s = current_pointer ()) - return s->cache_insert (db, id, obj); - else - return cache_position (); - } - - template - inline typename object_traits::pointer_type session:: - _cache_find (database_type& db, const typename object_traits::id_type& id) - { - typedef typename object_traits::pointer_type pointer_type; - - if (const session* s = current_pointer ()) - return s->cache_find (db, id); - else - return pointer_type (); - } - - template - inline void session:: - _cache_erase (const cache_position& p) - { - // @@ Empty maps are not cleaned up by this version of erase. - // - if (p.map_ != 0) - p.map_->erase (p.pos_); - } - - template - inline void session:: - _cache_erase (database_type& db, - const typename object_traits::id_type& id) - { - if (session* s = current_pointer ()) - s->cache_erase (db, id); - } -} diff --git a/odb/session.txx b/odb/session.txx deleted file mode 100644 index d74fe0f..0000000 --- a/odb/session.txx +++ /dev/null @@ -1,90 +0,0 @@ -// file : odb/session.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - template - typename session::cache_position session:: - cache_insert (database_type& db, - const typename object_traits::id_type& id, - const typename object_traits::pointer_type& obj) - { - type_map& tm (db_map_[&db]); - details::shared_ptr& pom (tm[&typeid (T)]); - - if (!pom) - pom.reset (new (details::shared) object_map); - - object_map& om (static_cast&> (*pom)); - - typename object_map::value_type vt (id, obj); - std::pair::iterator, bool> r (om.insert (vt)); - - // In what situation may we possibly attempt to reinsert the object? - // For example, when the user loads the same object in two different - // instances (i.e., load into a pre-allocated object). In this case - // we should probably update our entries accordingly. - // - if (!r.second) - r.first->second = obj; - - return cache_position (om, r.first); - } - - template - typename object_traits::pointer_type session:: - cache_find (database_type& db, - const typename object_traits::id_type& id) const - { - typedef typename object_traits::pointer_type pointer_type; - - database_map::const_iterator di (db_map_.find (&db)); - - if (di == db_map_.end ()) - return pointer_type (); - - const type_map& tm (di->second); - type_map::const_iterator ti (tm.find (&typeid (T))); - - if (ti == tm.end ()) - return pointer_type (); - - const object_map& om (static_cast&> (*ti->second)); - typename object_map::const_iterator oi (om.find (id)); - - if (oi == om.end ()) - return pointer_type (); - - return oi->second; - } - - template - void session:: - cache_erase (database_type& db, const typename object_traits::id_type& id) - { - database_map::iterator di (db_map_.find (&db)); - - if (di == db_map_.end ()) - return; - - type_map& tm (di->second); - type_map::iterator ti (tm.find (&typeid (T))); - - if (ti == tm.end ()) - return; - - object_map& om (static_cast&> (*ti->second)); - typename object_map::iterator oi (om.find (id)); - - if (oi == om.end ()) - return; - - om.erase (oi); - - if (om.empty ()) - tm.erase (ti); - - if (tm.empty ()) - db_map_.erase (di); - } -} diff --git a/odb/simple-object-result.hxx b/odb/simple-object-result.hxx deleted file mode 100644 index 53c0cb2..0000000 --- a/odb/simple-object-result.hxx +++ /dev/null @@ -1,201 +0,0 @@ -// file : odb/simple-object-result.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_SIMPLE_OBJECT_RESULT_HXX -#define ODB_SIMPLE_OBJECT_RESULT_HXX - -#include - -#include // std::size_t -#include // std::move - -#include -#include -#include -#include -#include - -#include // ODB_CXX11 - -namespace odb -{ - // Implementation for non-polymorphic objects with object id. - // - template - class object_result_impl: public result_impl - { - protected: - // In result_impl, T is always non-const and the same as object_type. - // - typedef T object_type; - typedef odb::object_traits object_traits; - typedef typename object_traits::id_type id_type; - - typedef typename object_traits::pointer_type pointer_type; - typedef odb::pointer_traits pointer_traits; - - friend class result; - friend class result; - friend class result_iterator; - friend class result_iterator; - friend class object_result_iterator; - friend class object_result_iterator; - - protected: - object_result_impl (odb::connection& conn) - : result_impl (conn), begin_ (true), end_ (false), current_ () - { - } - - // To make this work with all kinds of pointers (raw, std::auto_ptr, - // shared), we need to make sure we don't make any copies of the - // pointer on the return path. - // - pointer_type& - current () - { - if (pointer_traits::null_ptr (current_) && !end_) - load (); - - return current_; - } - - void - release () - { - current_ = pointer_type (); - guard_.release (); - } - - void - begin () - { - if (begin_) - { - next (); - begin_ = false; - } - } - - bool - end () const - { - return end_; - } - - protected: - // The fetch argument is a hint to the implementation. If it is - // false then it means load_id() was already called (and presumably - // fetched the data into the object image) and the object image - // is still valid (so the implementation doesn't need to fetch - // the data again). - // - virtual void - load (object_type&, bool fetch = true) = 0; - - virtual id_type - load_id () = 0; - - virtual void - next () = 0; - - virtual void - cache () = 0; - - virtual std::size_t - size () = 0; - - protected: -#ifdef ODB_CXX11 - void - current (pointer_type& p, bool guard = true) - { - current_ = std::move (p); - - if (guard) - guard_.reset (current_); - else - guard_.reset (); - } - - void - current (pointer_type&& p, bool guard = true) - { - current (p, guard); - } -#else - void - current (pointer_type p, bool guard = true) - { - current_ = p; - - if (guard) - guard_.reset (current_); - else - guard_.reset (); - } -#endif - - bool begin_; - bool end_; - - private: - void - load (); - - private: - pointer_type current_; - typename pointer_traits::guard guard_; - }; - - template - class object_result_iterator - { - public: - // T can be const T while object_type is always non-const. - // - typedef typename object_traits::object_type object_type; - typedef typename object_traits::id_type id_type; - - typedef object_result_impl result_impl_type; - - public: - object_result_iterator (result_impl_type* res) - : res_ (res) - { - } - - public: - typedef typename object_traits::pointer_type pointer_type; - - pointer_type - load () - { -#ifdef ODB_CXX11 - pointer_type r (std::move (res_->current ())); -#else - pointer_type r (res_->current ()); -#endif - res_->release (); - return r; - } - - void - load (object_type&); - - id_type - id () - { - return res_->load_id (); - } - - protected: - result_impl_type* res_; - }; -} - -#include - -#include - -#endif // ODB_SIMPLE_OBJECT_RESULT_HXX diff --git a/odb/simple-object-result.txx b/odb/simple-object-result.txx deleted file mode 100644 index 00521f8..0000000 --- a/odb/simple-object-result.txx +++ /dev/null @@ -1,58 +0,0 @@ -// file : odb/simple-object-result.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // object_result_impl - // - - template - void object_result_impl:: - load () - { - // First check the session. - // - const id_type& id (load_id ()); - - pointer_type p (object_traits::pointer_cache_traits::find (db_, id)); - - if (!pointer_traits::null_ptr (p)) - current (p, false); // Pointer from cache should not be guarded. - else - { - p = object_traits::create (); - - typename object_traits::pointer_cache_traits::insert_guard ig ( - object_traits::pointer_cache_traits::insert (db_, id, p)); - - object_type& obj (pointer_traits::get_ref (p)); - current (p); - load (obj, false); - object_traits::pointer_cache_traits::load (ig.position ()); - ig.release (); - } - } - - // - // object_result_iterator - // - - template - void object_result_iterator:: - load (object_type& obj) - { - if (res_->end ()) - return; - - typedef odb::object_traits object_traits; - - typename object_traits::reference_cache_traits::position_type p ( - object_traits::reference_cache_traits::insert ( - res_->db_, res_->load_id (), obj)); - typename object_traits::reference_cache_traits::insert_guard ig (p); - res_->load (obj, false); - object_traits::reference_cache_traits::load (p); - ig.release (); - } -} diff --git a/odb/statement-processing-common.hxx b/odb/statement-processing-common.hxx deleted file mode 100644 index 23661fc..0000000 --- a/odb/statement-processing-common.hxx +++ /dev/null @@ -1,214 +0,0 @@ -// file : odb/statement-processingc-common.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STATEMENT_PROCESSING_COMMON_HXX -#define ODB_STATEMENT_PROCESSING_COMMON_HXX - -#include - -//#define LIBODB_DEBUG_STATEMENT_PROCESSING 1 -//#define LIBODB_TRACE_STATEMENT_PROCESSING 1 - -#include -#include // std::size_t - -namespace odb -{ - typedef std::char_traits traits; - - static inline const char* - find (const char* b, const char* e, char c) - { - return traits::find (b, e - b, c); - } - - static inline const char* - rfind (const char* b, const char* e, char c) - { - for (--e; b != e; --e) - if (*e == c) - return e; - - return 0; - } - - static inline const char* - find (const char* b, const char* e, const char* s, std::size_t n) - { - for (; b != e; ++b) - { - if (*b == *s && - static_cast (e - b) >= n && - traits::compare (b, s, n) == 0) - return b; - } - - return 0; - } - - // Iterate over INSERT column/value list, UPDATE SET expression list, - // or SELECT column/join list. - // - // for (const char* b (columns_begin), *e (begin (b, end)); - // e != 0; - // next (b, e, end)) - // { - // // b points to the beginning of the value (i.e., one past '('). - // // e points one past the end of the value (i.e., to ',', ')', or '\n'). - // } - // - // // b points one past the last value. - // - static inline const char* - paren_begin (const char*& b, const char* end) - { - // Note that the list may not end with '\n'. - - b++; // Skip '('. - const char* e (find (b, end, '\n')); - return (e != 0 ? e : end) - 1; // Skip ',' or ')'. - } - - static inline void - paren_next (const char*& b, const char*& e, const char* end) - { - if (*e == ',') - { - b = e + 2; // Skip past '\n'. - e = find (b, end, '\n'); - e = (e != 0 ? e : end) - 1; // Skip ',' or ')'. - } - else - { - b = (e + 1 != end ? e + 2 : end); // Skip past '\n'. - e = 0; - } - } - - static inline const char* - comma_begin (const char* b, const char* end) - { - // Note that the list may not end with '\n'. - - const char* e (find (b, end, '\n')); - return e != 0 ? e - (*(e - 1) == ',' ? 1 : 0) : end; // Skip ','. - } - - static inline void - comma_next (const char*& b, const char*& e, const char* end) - { - if (*e == ',') - { - b = e + 2; // Skip past '\n'. - e = find (b, end, '\n'); - e = (e != 0 ? e - (*(e - 1) == ',' ? 1 : 0) : end); // Skip ','. - } - else - { - b = (e != end ? e + 1 : end); // Skip past '\n'. - e = 0; - } - } - - // Only allows A-Z and spaces before prefix (e.g., JOIN in LEFT OUTER JOIN). - // - static inline bool - fuzzy_prefix (const char* b, - const char* end, - const char* prefix, - std::size_t prefix_size) - { - for (; b != end; ++b) - { - char c (*b); - - if ((c < 'A' || c > 'Z') && c != ' ') - break; - - if (c == *prefix && - static_cast (end - b) > prefix_size && - traits::compare (b, prefix, prefix_size) == 0) - return true; - } - - return false; - } - - static inline const char* - newline_begin (const char* b, const char* end) - { - // Note that the list may not end with '\n'. - - const char* e (find (b, end, '\n')); - return e != 0 ? e : end; - } - - static inline void - newline_next (const char*& b, - const char*& e, - const char* end, - const char* prefix, - std::size_t prefix_size, - bool prefix_fuzzy = false) - { - if (e != end) - e++; // Skip past '\n'. - - b = e; - - // Do we have another element? - // - if (static_cast (end - b) > prefix_size && - (prefix_fuzzy - ? fuzzy_prefix (b, end, prefix, prefix_size) - : traits::compare (b, prefix, prefix_size) == 0)) - { - e = find (b, end, '\n'); - if (e == 0) - e = end; - } - else - e = 0; - } - - // Note that end must point to the beginning of the list. - // - static inline const char* - newline_rbegin (const char* e, const char* end) - { - const char* b (rfind (end, e - 1, '\n')); - return b != 0 ? b + 1 : end; // Skip past '\n'. - } - - static inline void - newline_rnext (const char*& b, const char*& e, const char* end) - { - if (b != end) - { - e = b - 1; // Skip to previous '\n'. - b = rfind (end, e - 1, '\n'); - b = (b != 0 ? b + 1 : end); // Skip past '\n'. - } - else - { - e = end - 1; // One before the first element. - b = 0; - } - } - - // Fast path: just remove the "structure". - // - static inline void - process_fast (const char* s, std::string& r) - { - r = s; - for (std::size_t i (r.find ('\n')); - i != std::string::npos; - i = r.find ('\n', i)) - r[i++] = ' '; - } -} - -#include - -#endif // ODB_STATEMENT_PROCESSING_COMMON_HXX diff --git a/odb/statement-processing.cxx b/odb/statement-processing.cxx deleted file mode 100644 index 708c9ab..0000000 --- a/odb/statement-processing.cxx +++ /dev/null @@ -1,685 +0,0 @@ -// file : odb/statement-processing.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -#include - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING -# include -#endif - -#include - -using namespace std; - -namespace odb -{ - typedef const void* const* bind_type; - - static inline const void* - bind_at (size_t i, bind_type bind, size_t bind_skip) - { - const char* b (reinterpret_cast (bind)); - return *reinterpret_cast (b + i * bind_skip); - } - - void statement:: - process_insert (string& r, - const char* s, - bind_type bind, - size_t bind_size, - size_t bind_skip, - char param_symbol, - char param_symbol2) - { -#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING - assert (bind_size != 0); // Cannot be versioned. -#endif - - bool fast (true); // Fast case (if all present). - for (size_t i (0); i != bind_size && fast; ++i) - { - if (bind_at (i, bind, bind_skip) == 0) - fast = false; - } - - // Fast path: just remove the "structure". - // -#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING - if (fast) - { - process_fast (s, r); - return; - } -#endif - - // Scan the statement and store the positions of various parts. - // - size_t n (traits::length (s)); - const char* e (s + n); - - // Header. - // - const char* p (find (s, e, '\n')); - assert (p != 0); - size_t header_size (p - s); - p++; - - // Column list. - // - const char* columns_begin (0); - if (*p == '(') - { - columns_begin = p; - - // Find the end of the column list. - // - for (const char* ce (paren_begin (p, e)); ce != 0; paren_next (p, ce, e)) - ; - } - - // OUTPUT - // - const char* output_begin (0); - size_t output_size (0); - if (e - p > 7 && traits::compare (p, "OUTPUT ", 7) == 0) - { - output_begin = p; - p += 7; - p = find (p, e, '\n'); - assert (p != 0); - output_size = p - output_begin; - p++; - } - - // VALUES or DEFAULT VALUES - // - bool empty (true); // DEFAULT VALUES case (if none present). - const char* values_begin (0); - if (e - p > 7 && traits::compare (p, "VALUES\n", 7) == 0) - { - p += 7; - values_begin = p; - - size_t bi (0); - for (const char* ve (paren_begin (p, e)); ve != 0; paren_next (p, ve, e)) - { - // We cannot be empty if we have a non-parameterized value, e.g., - // INSERT ... VALUES(1,?). We also cannot be empty if this value - // is present in the bind array. - // - if ((find (p, ve, param_symbol) == 0 && - (param_symbol2 == '\0' || find (p, ve, param_symbol2) == 0)) || - bind_at (bi++, bind, bind_skip) != 0) - empty = false; - } - } - else - { - // Must be DEFAULT VALUES. - // - assert (traits::compare (p, "DEFAULT VALUES", 14) == 0); - p += 14; - - if (*p == '\n') - p++; - } - - // Trailer. - // - const char* trailer_begin (0); - size_t trailer_size (0); - if (e - p != 0) - { - trailer_begin = p; - trailer_size = e - p; - } - - // Empty case. - // - if (empty) - { - r.reserve (header_size + - (output_size == 0 ? 0 : output_size + 1) + - 15 + // For " DEFAULT VALUES" - (trailer_size == 0 ? 0 : trailer_size + 1)); - - r.assign (s, header_size); - - if (output_size != 0) - { - r += ' '; - r.append (output_begin, output_size); - } - - r += " DEFAULT VALUES"; - - if (trailer_size != 0) - { - r += ' '; - r.append (trailer_begin, trailer_size); - } - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING - if (r.size () != n) - cerr << endl - << "old: '" << s << "'" << endl << endl - << "new: '" << r << "'" << endl << endl; -#endif - - return; - } - - // Assume the same size as the original. It can only shrink, and in - // most cases only slightly. So this is a good approximation. - // - r.reserve (n); - r.assign (s, header_size); - - // Column list. - // - { - r += ' '; - - size_t i (0), bi (0); - - for (const char *c (columns_begin), *ce (paren_begin (c, e)), - *v (values_begin), *ve (paren_begin (v, e)); - ce != 0; paren_next (c, ce, e), paren_next (v, ve, e)) - { - // See if the value contains the parameter symbol and, if so, - // whether it is present in the bind array. - // - if ((find (v, ve, param_symbol) != 0 || - (param_symbol2 != '\0' && find (v, ve, param_symbol2) != 0)) && - bind_at (bi++, bind, bind_skip) == 0) - continue; - - // Append the column. - // - if (i++ == 0) - r += '('; - else - r += ", "; // Add the space for consistency with the fast path. - - r.append (c, ce - c); - } - - r += ')'; - } - - // OUTPUT - // - if (output_size != 0) - { - r += ' '; - r.append (output_begin, output_size); - } - - // Value list. - // - { - r += " VALUES "; - - size_t i (0), bi (0); - - for (const char* v (values_begin), *ve (paren_begin (v, e)); - ve != 0; paren_next (v, ve, e)) - { - // See if the value contains the parameter symbol and, if so, - // whether it is present in the bind array. - // - if ((find (v, ve, param_symbol) != 0 || - (param_symbol2 != '\0' && find (v, ve, param_symbol2) != 0)) && - bind_at (bi++, bind, bind_skip) == 0) - continue; - - // Append the value. - // - if (i++ == 0) - r += '('; - else - r += ", "; // Add the space for consistency with the fast path. - - r.append (v, ve - v); - } - - r += ')'; - } - - // Trailer. - // - if (trailer_size != 0) - { - r += ' '; - r.append (trailer_begin, trailer_size); - } - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING - if (r.size () != n) - cerr << endl - << "old: '" << s << "'" << endl << endl - << "new: '" << r << "'" << endl << endl; -#endif - } - - void statement:: - process_update (string& r, - const char* s, - bind_type bind, - size_t bind_size, - size_t bind_skip, - char param_symbol, - char param_symbol2) - { - bool fast (true); // Fast case (if all present). - for (size_t i (0); i != bind_size && fast; ++i) - { - if (bind_at (i, bind, bind_skip) == 0) - fast = false; - } - - // Fast path: just remove the "structure". - // -#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING - if (fast) - { - process_fast (s, r); - return; - } -#endif - - // Scan the statement and store the positions of various parts. - // - size_t n (traits::length (s)); - const char* e (s + n); - - // Header. - // - const char* p (find (s, e, '\n')); - assert (p != 0); - size_t header_size (p - s); - p++; - - // SET - // - bool empty (true); // Empty SET case. - const char* set_begin (0); - if (e - p > 4 && traits::compare (p, "SET\n", 4) == 0) - { - p += 4; - set_begin = p; - - // Scan the SET list. - // - size_t bi (0); - for (const char* pe (comma_begin (p, e)); pe != 0; comma_next (p, pe, e)) - { - if (empty) - { - // We cannot be empty if we have a non-parameterized set expression, - // e.g., UPDATE ... SET ver=ver+1 ... We also cannot be empty if - // this expression is present in the bind array. - // - if ((find (p, pe, param_symbol) == 0 && - (param_symbol2 == '\0' || find (p, pe, param_symbol2) == 0)) || - bind_at (bi++, bind, bind_skip) != 0) - empty = false; - } - } - } - - // Empty case. - // - if (empty) - { - r.clear (); - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING - if (n != 0) - cerr << endl - << "old: '" << s << "'" << endl << endl - << "new: '" << r << "'" << endl << endl; -#endif - - return; - } - - // Trailer. - // - const char* trailer_begin (0); - size_t trailer_size (0); - if (e - p != 0) - { - trailer_begin = p; - trailer_size = e - p; - } - - // Assume the same size as the original. It can only shrink, and in - // most cases only slightly. So this is a good approximation. - // - r.reserve (n); - r.assign (s, header_size); - - // SET list. - // - { - r += " SET "; - - size_t i (0), bi (0); - - for (const char* p (set_begin), *pe (comma_begin (p, e)); - pe != 0; comma_next (p, pe, e)) - { - // See if the value contains the parameter symbol and, if so, - // whether it is present in the bind array. - // - if ((find (p, pe, param_symbol) != 0 || - (param_symbol2 != '\0' && find (p, pe, param_symbol2) != 0)) && - bind_at (bi++, bind, bind_skip) == 0) - continue; - - // Append the expression. - // - if (i++ != 0) - r += ", "; // Add the space for consistency with the fast path. - - r.append (p, pe - p); - } - } - - // Trailer. - // - if (trailer_size != 0) - { - r += ' '; - r.append (trailer_begin, trailer_size); - } - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING - if (r.size () != n) - cerr << endl - << "old: '" << s << "'" << endl << endl - << "new: '" << r << "'" << endl << endl; -#endif - } - - void statement:: - process_select (string& r, - const char* s, - bind_type bind, - size_t bind_size, - size_t bind_skip, - char quote_open, - char quote_close, -#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING - bool optimize, -#else - bool, -#endif - bool as) - { - bool empty (true); // Empty case (if none present). - bool fast (true); // Fast case (if all present). - for (size_t i (0); i != bind_size && (empty || fast); ++i) - { - if (bind_at (i, bind, bind_skip) != 0) - empty = false; - else - fast = false; - } - - // Empty. - // - if (empty) - { - r.clear (); - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING - if (*s != '\0') - cerr << endl - << "old: '" << s << "'" << endl << endl - << "new: '" << r << "'" << endl << endl; -#endif - return; - } - - // Fast path: just remove the "structure". - // -#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING - if (fast && !optimize) - { - process_fast (s, r); - return; - } -#endif - - // Scan the statement and store the positions of various parts. - // - size_t n (traits::length (s)); - const char* e (s + n); - - // Header. - // - const char* p (find (s, e, '\n')); - assert (p != 0); - size_t header_size (p - s); - p++; - - // Column list. - // - const char* columns_begin (p); - for (const char* ce (comma_begin (p, e)); ce != 0; comma_next (p, ce, e)) - ; - - // FROM. - assert (traits::compare (p, "FROM ", 5) == 0); - const char* from_begin (p); - p = find (p, e, '\n'); // May not end with '\n'. - if (p == 0) - p = e; - size_t from_size (p - from_begin); - if (p != e) - p++; - - // JOIN list. - // - const char* joins_begin (0), *joins_end (0); - if (e - p > 5 && fuzzy_prefix (p, e, "JOIN ", 5)) - { - joins_begin = p; - - // Find the end of the JOIN list. - // - for (const char* je (newline_begin (p, e)); - je != 0; newline_next (p, je, e, "JOIN ", 5, true)) - ; - - joins_end = (p != e ? p - 1 : p); - } - -#ifndef LIBODB_DEBUG_STATEMENT_PROCESSING - if (fast && joins_begin == 0) - { - // No JOINs to optimize so can still take the fast path. - // - process_fast (s, r); - return; - } -#endif - - // Trailer (WHERE, ORDER BY, etc). - // - const char* trailer_begin (0); - size_t trailer_size (0); - if (e - p != 0) - { - trailer_begin = p; - trailer_size = e - p; - } - - // Assume the same size as the original. It can only shrink, and in - // most cases only slightly. So this is a good approximation. - // - r.reserve (n); - r.assign (s, header_size); - - // Column list. - // - { - r += ' '; - - size_t i (0), bi (0); - - for (const char *c (columns_begin), *ce (comma_begin (c, e)); - ce != 0; comma_next (c, ce, e)) - { - // See if the column is present in the bind array. - // - if (bind_at (bi++, bind, bind_skip) == 0) - continue; - - // Append the column. - // - if (i++ != 0) - r += ", "; // Add the space for consistency with the fast path. - - r.append (c, ce - c); - } - } - - // From. - // - r += ' '; - r.append (from_begin, from_size); - - // JOIN list, pass 1. - // - size_t join_pos (0); - if (joins_begin != 0) - { - // Fill in the JOIN "area" with spaces. - // - r.resize (r.size () + joins_end - joins_begin + 1, ' '); - join_pos = r.size () + 1; // End of the last JOIN. - } - - // Trailer. - // - if (trailer_size != 0) - { - r += ' '; - r.append (trailer_begin, trailer_size); - } - - // JOIN list, pass 2. - // - if (joins_begin != 0) - { - // Splice the JOINs into the pre-allocated area. - // - for (const char* je (joins_end), *j (newline_rbegin (je, joins_begin)); - j != 0; newline_rnext (j, je, joins_begin)) - { - size_t n (je - j); - - // Get the alias or, if none used, the table name. - // - p = find (j, je, "JOIN ", 5) + 5; // Skip past "JOIN ". - const char* table_begin (p); - p = find (p, je, ' '); // End of the table name. - const char* table_end (p); - p++; // Skip space. - - // We may or may not have the AS keyword. - // - const char* alias_begin (0); - size_t alias_size (0); - - if (p != je && // Not the end. - (je - p < 4 || traits::compare (p, "ON ", 3) != 0)) - { - // Something other than "ON ", so got to be an alias. - // - if (as) - p += 3; - - alias_begin = p; - p = find (p, je, ' '); // There might be no ON (CROSS JOIN). - alias_size = (p != 0 ? p : je) - alias_begin; - } - else - { - // Just the table. - // - alias_begin = table_begin; - alias_size = table_end - alias_begin; - } - - // The alias must be quoted. - // - assert (*alias_begin == quote_open && - *(alias_begin + alias_size - 1) == quote_close); - - // We now need to see if the alias is used in either the SELECT - // list, the WHERE conditions, or the ON condition of any of the - // JOINs that we have already processed and decided to keep. - // - // Instead of re-parsing the whole thing again, we are going to - // take a shortcut and simply search for the alias in the statement - // we have constructed so far (that's why we have added the - // trailer before filling in the JOINs). To make it more robust, - // we are going to do a few extra sanity checks, specifically, - // that the alias is a top level identifier and is followed by - // only a single identifer (column). This will catch cases like - // [s].[t].[c] where [s] is also used as an alias or LEFT JOIN [t] - // where [t] is also used as an alias in another JOIN. - // - bool found (false); - for (size_t p (r.find (alias_begin, 0, alias_size)); - p != string::npos; - p = r.find (alias_begin, p + alias_size, alias_size)) - { - size_t e (p + alias_size); - - // If we are not a top-level qualifier or not a bottom-level, - // then we are done (3 is for at least "[a]"). - // - if ((p != 0 && r[p - 1] == '.') || - (e + 3 >= r.size () || (r[e] != '.' || r[e + 1] != quote_open))) - continue; - - // The only way to distinguish the [a].[c] from FROM [a].[c] or - // JOIN [a].[c] is by checking the prefix. - // - if ((p > 5 && r.compare (p - 5, 5, "FROM ") == 0) || - (p > 5 && r.compare (p - 5, 5, "JOIN ") == 0)) - continue; - - // Check that we are followed by a single identifier. - // - e = r.find (quote_close, e + 2); - if (e == string::npos || (e + 1 != r.size () && r[e + 1] == '.')) - continue; - - found = true; - break; - } - - join_pos -= n + 1; // Extra one for space. - if (found) - r.replace (join_pos, n, j, n); - else - r.erase (join_pos - 1, n + 1); // Extra one for space. - } - } - -#ifdef LIBODB_TRACE_STATEMENT_PROCESSING - if (r.size () != n) - cerr << endl - << "old: '" << s << "'" << endl << endl - << "new: '" << r << "'" << endl << endl; -#endif - } -} diff --git a/odb/statement.cxx b/odb/statement.cxx deleted file mode 100644 index 35e7b77..0000000 --- a/odb/statement.cxx +++ /dev/null @@ -1,12 +0,0 @@ -// file : odb/statement.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - statement:: - ~statement () - { - } -} diff --git a/odb/statement.hxx b/odb/statement.hxx deleted file mode 100644 index 83513c0..0000000 --- a/odb/statement.hxx +++ /dev/null @@ -1,108 +0,0 @@ -// file : odb/statement.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STATEMENT_HXX -#define ODB_STATEMENT_HXX - -#include - -#include -#include // std::size_t - -#include // connection - -#include -#include - -namespace odb -{ - class LIBODB_EXPORT statement: public details::shared_base - { - private: - statement (const statement&); - statement& operator= (const statement&); - - public: - typedef odb::connection connection_type; - - virtual const char* - text () const = 0; - - virtual connection_type& - connection () = 0; - - virtual - ~statement () = 0; - - protected: - statement () {} - - // Statement processing. Kept public only for testing. - // - public: - // Expected statement structure: - // - // INSERT INTO table\n - // [(a,\n - // b)\n] - // [OUTPUT ...\n] - // [VALUES\n - // ($1,\n - // $2)[\n]] - // [DEFAULT VALUES[\n]] - // [RETURNING ...] - // [; SELECT ...] - // - static void - process_insert (std::string& result, - const char* statement, - const void* const* bind, // Array of bind buffer pointers. - std::size_t bind_size, // Number of bind elements. - std::size_t bind_skip, // Offset to the next bind. - char param_symbol, // $, ?, :, etc. - char param_symbol2 = '\0'); - - // Expected statement structure: - // - // UPDATE table\n - // SET\n - // a=$1,\n - // b=$2[\n] - // [OUTPUT ...] - // [WHERE ...] - // - static void - process_update (std::string& result, - const char* statement, - const void* const* bind, // Array of bind buffer pointers. - std::size_t bind_size, // Number of bind elements. - std::size_t bind_skip, // Offset to the next bind. - char param_symbol, // $, ?, :, etc. - char param_symbol2 = '\0'); - - - // Expected statement structure: - // - // SELECT\n - // [schema.]table.a [AS b],\n - // alias.b\n - // FROM [schema.]table[\n] - // [{A-Z }* JOIN [schema.]table [AS alias][ ON ...][\n]]* - // [WHERE ...] - // - static void - process_select (std::string& result, - const char* statement, - const void* const* bind, // Array of bind buffer pointers. - std::size_t bind_size, // Number of bind elements. - std::size_t bind_skip, // Offset to the next bind. - char quote_open, // Identifier opening quote. - char quote_close, // Identifier closing quote. - bool optimize, // Remove unused JOINs. - bool as = true); // JOINs use AS keyword. - }; -} - -#include - -#endif // ODB_STATEMENT_HXX diff --git a/odb/std-array-traits.hxx b/odb/std-array-traits.hxx deleted file mode 100644 index 1d0f1a1..0000000 --- a/odb/std-array-traits.hxx +++ /dev/null @@ -1,72 +0,0 @@ -// file : odb/std-array-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_ARRAY_TRAITS_HXX -#define ODB_STD_ARRAY_TRAITS_HXX - -#include - -#include -#include // std::size_t -#include - -#include - -namespace odb -{ - template - class access::container_traits> - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef std::array container_type; - - typedef V value_type; - typedef typename container_type::size_type index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - for (index_type i (0); i < N; ++i) - f.insert (i, c[i]); - } - - static void - load (container_type& c, bool more, const functions& f) - { - index_type i (0); - - for (; more && i < N; ++i) - { - index_type dummy; - more = f.select (dummy, c[i]); - } - - assert (!more && i == N); - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (index_type i (0); i < N; ++i) - f.insert (i, c[i]); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_ARRAY_TRAITS_HXX diff --git a/odb/std-deque-traits.hxx b/odb/std-deque-traits.hxx deleted file mode 100644 index 351c6db..0000000 --- a/odb/std-deque-traits.hxx +++ /dev/null @@ -1,69 +0,0 @@ -// file : odb/std-deque-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_DEQUE_TRAITS_HXX -#define ODB_STD_DEQUE_TRAITS_HXX - -#include - -#include - -#include - -namespace odb -{ - template - class access::container_traits > - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef std::deque container_type; - - typedef V value_type; - typedef typename container_type::size_type index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - index_type dummy; - c.push_back (value_type ()); - more = f.select (dummy, c.back ()); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_DEQUE_TRAITS_HXX diff --git a/odb/std-forward-list-traits.hxx b/odb/std-forward-list-traits.hxx deleted file mode 100644 index 7978b1c..0000000 --- a/odb/std-forward-list-traits.hxx +++ /dev/null @@ -1,73 +0,0 @@ -// file : odb/std-forward-list-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_FORWARD_LIST_TRAITS_HXX -#define ODB_STD_FORWARD_LIST_TRAITS_HXX - -#include - -#include - -#include - -namespace odb -{ - template - class access::container_traits> - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef std::forward_list container_type; - - typedef V value_type; - typedef typename container_type::size_type index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - index_type i (0); - for (typename container_type::const_iterator j (c.begin ()), - e (c.end ()); j != e; ++j) - f.insert (i++, *j); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - for (typename container_type::iterator i (c.before_begin ()); more; ) - { - index_type dummy; - i = c.insert_after (i, value_type ()); - more = f.select (dummy, *i); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - index_type i (0); - for (typename container_type::const_iterator j (c.begin ()), - e (c.end ()); j != e; ++j) - f.insert (i++, *j); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_FORWARD_LIST_TRAITS_HXX diff --git a/odb/std-list-traits.hxx b/odb/std-list-traits.hxx deleted file mode 100644 index f349079..0000000 --- a/odb/std-list-traits.hxx +++ /dev/null @@ -1,73 +0,0 @@ -// file : odb/std-list-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_LIST_TRAITS_HXX -#define ODB_STD_LIST_TRAITS_HXX - -#include - -#include - -#include - -namespace odb -{ - template - class access::container_traits > - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef std::list container_type; - - typedef V value_type; - typedef typename container_type::size_type index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - index_type i (0); - for (typename container_type::const_iterator j (c.begin ()), - e (c.end ()); j != e; ++j) - f.insert (i++, *j); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - index_type dummy; - c.push_back (value_type ()); - more = f.select (dummy, c.back ()); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - index_type i (0); - for (typename container_type::const_iterator j (c.begin ()), - e (c.end ()); j != e; ++j) - f.insert (i++, *j); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_LIST_TRAITS_HXX diff --git a/odb/std-map-traits.hxx b/odb/std-map-traits.hxx deleted file mode 100644 index 2b9bf7d..0000000 --- a/odb/std-map-traits.hxx +++ /dev/null @@ -1,142 +0,0 @@ -// file : odb/std-map-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_MAP_TRAITS_HXX -#define ODB_STD_MAP_TRAITS_HXX - -#include - -#include -#include // std::move - -#include -#include // ODB_CXX11 - -namespace odb -{ - template - class access::container_traits > - { - public: - static const container_kind kind = ck_map; - static const bool smart = false; - - typedef std::map container_type; - - typedef K key_type; - typedef V value_type; - typedef typename container_type::value_type pair_type; - - typedef map_functions 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 (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.select (k, v); -#ifdef ODB_CXX11 - c.insert (pair_type (std::move (k), std::move (v))); -#else - c.insert (pair_type (k, v)); -#endif - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (i->first, i->second); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; - - // C++03 does not guarantee insertion order of equal values but C++11 - // changes that. The current implementation in the generated code does - // not guarantee this either. - // - template - class access::container_traits > - { - public: - static const container_kind kind = ck_multimap; - static const bool smart = false; - - typedef std::multimap container_type; - - typedef K key_type; - typedef V value_type; - typedef typename container_type::value_type pair_type; - - typedef map_functions 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 (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.select (k, v); -#ifdef ODB_CXX11 - c.insert (pair_type (std::move (k), std::move (v))); -#else - c.insert (pair_type (k, v)); -#endif - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (i->first, i->second); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_MAP_TRAITS_HXX diff --git a/odb/std-set-traits.hxx b/odb/std-set-traits.hxx deleted file mode 100644 index 45a5dcc..0000000 --- a/odb/std-set-traits.hxx +++ /dev/null @@ -1,134 +0,0 @@ -// file : odb/std-set-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_SET_TRAITS_HXX -#define ODB_STD_SET_TRAITS_HXX - -#include - -#include -#include // std::move - -#include -#include // ODB_CXX11 - -namespace odb -{ - template - class access::container_traits > - { - public: - static const container_kind kind = ck_set; - static const bool smart = false; - - typedef std::set container_type; - typedef V value_type; - - typedef set_functions 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 (*i); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - value_type v; - more = f.select (v); -#ifdef ODB_CXX11 - c.insert (std::move (v)); -#else - c.insert (v); -#endif - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (*i); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; - - // C++03 does not guarantee insertion order of equal values but C++11 - // changes that. The current implementation in the generated code does - // not guarantee this either. - // - template - class access::container_traits > - { - public: - static const container_kind kind = ck_multiset; - static const bool smart = false; - - typedef std::multiset container_type; - typedef V value_type; - - typedef set_functions 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 (*i); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - value_type v; - more = f.select (v); -#ifdef ODB_CXX11 - c.insert (std::move (v)); -#else - c.insert (v); -#endif - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (*i); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_SET_TRAITS_HXX diff --git a/odb/std-unordered-map-traits.hxx b/odb/std-unordered-map-traits.hxx deleted file mode 100644 index 461eb06..0000000 --- a/odb/std-unordered-map-traits.hxx +++ /dev/null @@ -1,133 +0,0 @@ -// file : odb/std-unordered-map-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_UNORDERED_MAP_TRAITS_HXX -#define ODB_STD_UNORDERED_MAP_TRAITS_HXX - -#include - -#include // std::move -#include - -#include - -namespace odb -{ - template - class access::container_traits> - { - public: - static const container_kind kind = ck_map; - static const bool smart = false; - - typedef std::unordered_map container_type; - - typedef K key_type; - typedef V value_type; - typedef typename container_type::value_type pair_type; - - typedef map_functions 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 (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.select (k, v); - c.insert (pair_type (std::move (k), std::move (v))); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (i->first, i->second); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; - - // @@ Does multimap preserve insertion order of equal elements? The - // current implementation in the generated code does not guarantee - // this. - // - template - class access::container_traits> - { - public: - static const container_kind kind = ck_multimap; - static const bool smart = false; - - typedef std::unordered_multimap container_type; - - typedef K key_type; - typedef V value_type; - typedef typename container_type::value_type pair_type; - - typedef map_functions 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 (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.select (k, v); - c.insert (pair_type (std::move (k), std::move (v))); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (i->first, i->second); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_UNORDERED_MAP_TRAITS_HXX diff --git a/odb/std-unordered-set-traits.hxx b/odb/std-unordered-set-traits.hxx deleted file mode 100644 index f590665..0000000 --- a/odb/std-unordered-set-traits.hxx +++ /dev/null @@ -1,125 +0,0 @@ -// file : odb/std-unordered-set-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_UNORDERED_SET_TRAITS_HXX -#define ODB_STD_UNORDERED_SET_TRAITS_HXX - -#include - -#include // std::move -#include - -#include - -namespace odb -{ - template - class access::container_traits> - { - public: - static const container_kind kind = ck_set; - static const bool smart = false; - - typedef std::unordered_set container_type; - typedef V value_type; - - typedef set_functions 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 (*i); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - value_type v; - more = f.select (v); - c.insert (std::move (v)); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (*i); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; - - // @@ Does multiset preserve insertion order of equal elements? The - // current implementation in the generated code does not guarantee - // this. - // - template - class access::container_traits> - { - public: - static const container_kind kind = ck_multiset; - static const bool smart = false; - - typedef std::unordered_multiset container_type; - typedef V value_type; - - typedef set_functions 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 (*i); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - value_type v; - more = f.select (v); - c.insert (std::move (v)); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (typename container_type::const_iterator i (c.begin ()), - e (c.end ()); i != e; ++i) - f.insert (*i); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_UNORDERED_SET_TRAITS_HXX diff --git a/odb/std-vector-traits.hxx b/odb/std-vector-traits.hxx deleted file mode 100644 index c6bb39e..0000000 --- a/odb/std-vector-traits.hxx +++ /dev/null @@ -1,123 +0,0 @@ -// file : odb/std-vector-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_STD_VECTOR_TRAITS_HXX -#define ODB_STD_VECTOR_TRAITS_HXX - -#include - -#include - -#include - -namespace odb -{ - template - class access::container_traits > - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef std::vector container_type; - - typedef V value_type; - typedef typename container_type::size_type index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - index_type dummy; - c.push_back (value_type ()); - more = f.select (dummy, c.back ()); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; - - // std::vector is special. - // - template - class access::container_traits > - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = false; - - typedef std::vector container_type; - - typedef bool value_type; - typedef typename container_type::size_type index_type; - - typedef ordered_functions functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - } - - static void - load (container_type& c, bool more, const functions& f) - { - c.clear (); - - while (more) - { - index_type dummy; - value_type value; - more = f.select (dummy, value); - c.push_back (value); - } - } - - static void - update (const container_type& c, const functions& f) - { - f.delete_ (); - - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - } - - static void - erase (const functions& f) - { - f.delete_ (); - } - }; -} - -#include - -#endif // ODB_STD_VECTOR_TRAITS_HXX diff --git a/odb/tr1/lazy-pointer-traits.hxx b/odb/tr1/lazy-pointer-traits.hxx deleted file mode 100644 index 7adf957..0000000 --- a/odb/tr1/lazy-pointer-traits.hxx +++ /dev/null @@ -1,61 +0,0 @@ -// file : odb/tr1/lazy-pointer-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TR1_LAZY_POINTER_TRAITS_HXX -#define ODB_TR1_LAZY_POINTER_TRAITS_HXX - -#include - -#include -#include - -namespace odb -{ - template - class pointer_traits > - { - public: - static const pointer_kind kind = pk_shared; - static const bool lazy = true; - - typedef T element_type; - typedef tr1::lazy_shared_ptr pointer_type; - typedef std::tr1::shared_ptr eager_pointer_type; - - static bool - null_ptr (const pointer_type& p) - { - return !p; - } - - template - static typename object_traits::id_type - object_id (const pointer_type& p) - { - return p.template object_id (); - } - }; - - template - class pointer_traits > - { - public: - static const pointer_kind kind = pk_weak; - static const bool lazy = true; - - typedef T element_type; - typedef tr1::lazy_weak_ptr pointer_type; - typedef tr1::lazy_shared_ptr strong_pointer_type; - typedef std::tr1::weak_ptr eager_pointer_type; - - static strong_pointer_type - lock (const pointer_type& p) - { - return p.lock (); - } - }; -} - -#include - -#endif // ODB_TR1_LAZY_POINTER_TRAITS_HXX diff --git a/odb/tr1/lazy-ptr.hxx b/odb/tr1/lazy-ptr.hxx deleted file mode 100644 index b4946ec..0000000 --- a/odb/tr1/lazy-ptr.hxx +++ /dev/null @@ -1,267 +0,0 @@ -// file : odb/tr1/lazy-ptr.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TR1_LAZY_PTR_HXX -#define ODB_TR1_LAZY_PTR_HXX - -#include - -// -// This header assumes that the necessary TR1 header has already -// been included. -// - -#include // std::auto_ptr - -#include // odb::database -#include -#include -#include // ODB_CXX11 - -namespace odb -{ - namespace tr1 - { - template - class lazy_weak_ptr; - - // - // - template - class lazy_shared_ptr - { - // The standard shared_ptr interface. - // - public: - typedef T element_type; - - lazy_shared_ptr (); - template explicit lazy_shared_ptr (Y*); - template lazy_shared_ptr (Y*, D); - - lazy_shared_ptr (const lazy_shared_ptr&); - template lazy_shared_ptr (const lazy_shared_ptr&); - template explicit lazy_shared_ptr (const lazy_weak_ptr&); - template explicit lazy_shared_ptr (std::auto_ptr&); - - ~lazy_shared_ptr (); - - lazy_shared_ptr& operator= (const lazy_shared_ptr&); - template lazy_shared_ptr& operator= (const lazy_shared_ptr&); - template lazy_shared_ptr& operator= (std::auto_ptr&); - - void swap (lazy_shared_ptr&); - void reset (); - template void reset (Y*); - template void reset (Y*, D); - - T& operator* () const; - T* operator-> () const; - T* get () const; - - bool unique () const; - long use_count () const; - - typedef std::tr1::shared_ptr 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 lazy_shared_ptr (const std::tr1::shared_ptr&); - template explicit lazy_shared_ptr (const std::tr1::weak_ptr&); - - template lazy_shared_ptr& operator= (const std::tr1::shared_ptr&); - - // Lazy loading interface. - // - public: - typedef odb::database database_type; - - // NULL loaded() - // - // true true NULL pointer to transient object - // false true valid pointer to persistent object - // true false unloaded pointer to persistent object - // false false valid pointer to transient object - // - bool loaded () const; - - std::tr1::shared_ptr load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - std::tr1::shared_ptr get_eager () const; - - template lazy_shared_ptr (DB&, const ID&); - template lazy_shared_ptr (DB&, Y*); - template lazy_shared_ptr (DB&, Y*, D); - template lazy_shared_ptr (DB&, std::auto_ptr&); - template lazy_shared_ptr (DB&, const std::tr1::shared_ptr&); - template lazy_shared_ptr (DB&, const std::tr1::weak_ptr&); - - template void reset (DB&, const ID&); - template void reset (DB&, Y*); - template void reset (DB&, Y*, D); - template void reset (DB&, std::auto_ptr&); - template void reset (DB&, const std::tr1::shared_ptr&); - -#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT - template -#else - template -#endif - typename object_traits::id_type object_id () const; - - database_type& database () const; - - // Helpers. - // - public: - template bool equal (const lazy_shared_ptr&) const; - - private: - template friend class lazy_shared_ptr; - template friend class lazy_weak_ptr; - - // For lazy_weak_ptr::lock(). - // - lazy_shared_ptr (const std::tr1::shared_ptr& p, - const lazy_ptr_impl& i) - : p_ (p), i_ (i) {} - - private: - mutable std::tr1::shared_ptr p_; - mutable lazy_ptr_impl i_; - }; - - // operator< and operator<< are not provided. - // - template - bool operator== (const lazy_shared_ptr&, const lazy_shared_ptr&); - - template - bool operator!= (const lazy_shared_ptr&, const lazy_shared_ptr&); - - template void swap (lazy_shared_ptr&, lazy_shared_ptr&); - - template - D* get_deleter (const lazy_shared_ptr&); - - // - // - template - class lazy_weak_ptr - { - // The standard weak_ptr interface. - // - public: - typedef T element_type; - - lazy_weak_ptr (); - template lazy_weak_ptr (const lazy_shared_ptr&); - lazy_weak_ptr (const lazy_weak_ptr&); - template lazy_weak_ptr (const lazy_weak_ptr&); - - ~lazy_weak_ptr (); - - lazy_weak_ptr& operator= (const lazy_weak_ptr&); - template lazy_weak_ptr& operator= (const lazy_weak_ptr&); - template lazy_weak_ptr& operator= (const lazy_shared_ptr&); - - void swap (lazy_weak_ptr&); - void reset (); - - long use_count () const; - bool expired () const; - - lazy_shared_ptr lock () const; - - // Initialization/assignment from shared_ptr and weak_ptr. - // - public: - template lazy_weak_ptr (const std::tr1::weak_ptr&); - template lazy_weak_ptr (const std::tr1::shared_ptr&); - - template lazy_weak_ptr& operator= (const std::tr1::weak_ptr&); - template lazy_weak_ptr& operator= (const std::tr1::shared_ptr&); - - // 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 transient object - // - bool loaded () const; - - // Performs both lock and load. - // - std::tr1::shared_ptr load () const; - - // Unload the pointer. For transient objects this function is - // equivalent to reset(). - // - void unload () const; - - // Get the underlying eager pointer. If this is an unloaded pointer - // to a persistent object, then the returned pointer will be NULL. - // - std::tr1::weak_ptr get_eager () const; - - template lazy_weak_ptr (DB&, const ID&); - template lazy_weak_ptr (DB&, const std::tr1::shared_ptr&); - template lazy_weak_ptr (DB&, const std::tr1::weak_ptr&); - - template void reset (DB&, const ID&); - template void reset (DB&, const std::tr1::shared_ptr&); - template void reset (DB&, const std::tr1::weak_ptr&); - - // The object_id() function can only be called when the object is - // persistent, or: expired() XOR loaded() (can use != for XOR). - // -#ifdef ODB_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGUMENT - template -#else - template -#endif - typename object_traits::id_type object_id () const; - - database_type& database () const; - - private: - template friend class lazy_shared_ptr; - template friend class lazy_weak_ptr; - - mutable std::tr1::weak_ptr p_; - mutable lazy_ptr_impl i_; - }; - - // operator< is not provided. - // - template void swap (lazy_weak_ptr&, lazy_weak_ptr&); - } -} - -#include -#include - -#include - -#include - -#endif // ODB_TR1_LAZY_PTR_HXX diff --git a/odb/tr1/lazy-ptr.ixx b/odb/tr1/lazy-ptr.ixx deleted file mode 100644 index dc5000f..0000000 --- a/odb/tr1/lazy-ptr.ixx +++ /dev/null @@ -1,638 +0,0 @@ -// file : odb/tr1/lazy-ptr.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace tr1 - { - // - // lazy_shared_ptr - // - - template - inline lazy_shared_ptr:: - lazy_shared_ptr () {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (Y* p): p_ (p) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (Y* p, D d): p_ (p, d) {} - - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const lazy_weak_ptr& 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 std::tr1::bad_weak_ptr (); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (std::auto_ptr& r): p_ (r) {} - - template - inline lazy_shared_ptr:: - ~lazy_shared_ptr () {} - - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (const lazy_shared_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (const lazy_shared_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (std::auto_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - inline void lazy_shared_ptr:: - swap (lazy_shared_ptr& b) - { - p_.swap (b.p_); - i_.swap (b.i_); - } - - template - inline void lazy_shared_ptr:: - reset () - { - p_.reset (); - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (Y* p) - { - p_.reset (p); - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (Y* p, D d) - { - p_.reset (p, d); - i_.reset (); - } - - template - inline T& lazy_shared_ptr:: - operator* () const - { - return *p_; - } - - template - inline T* lazy_shared_ptr:: - operator-> () const - { - return p_.operator-> (); - } - - template - inline T* lazy_shared_ptr:: - get () const - { - return p_.get (); - } - - template - inline bool lazy_shared_ptr:: - unique () const - { - return p_.unique (); - } - - template - inline long lazy_shared_ptr:: - use_count () const - { - return p_.use_count (); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const std::tr1::shared_ptr& r): p_ (r) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (const std::tr1::weak_ptr& r): p_ (r) {} - - template - template - inline lazy_shared_ptr& lazy_shared_ptr:: - operator= (const std::tr1::shared_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - inline bool lazy_shared_ptr:: - loaded () const - { - bool i (i_); - return !p_ != i; // !p_ XOR i_ - } - - template - inline std::tr1::shared_ptr lazy_shared_ptr:: - load () const - { - if (!p_ && i_) - p_ = i_.template load (true); // Reset id. - - return p_; - } - - template - inline void lazy_shared_ptr:: - unload () const - { - typedef typename object_traits::object_type object_type; - - if (p_) - { - if (i_.database () != 0) - i_.reset_id (object_traits::id (*p_)); - - p_.reset (); - } - } - - template - inline std::tr1::shared_ptr lazy_shared_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, const ID& id): i_ (db, id) {} - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, Y* p) - : p_ (p) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, Y* p, D d) - : p_ (p, d) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, std::auto_ptr& r) - : p_ (r) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, const std::tr1::shared_ptr& r) - : p_ (r) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline lazy_shared_ptr:: - lazy_shared_ptr (DB& db, const std::tr1::weak_ptr& r) - : p_ (r) - { - if (p_) - i_.reset_db (db); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, const ID& id) - { - p_.reset (); - i_.reset (db, id); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, Y* p) - { - p_.reset (p); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, Y* p, D d) - { - p_.reset (p, d); - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, std::auto_ptr& r) - { - p_ = r; - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline void lazy_shared_ptr:: - reset (DB& db, const std::tr1::shared_ptr& r) - { - p_ = r; - - if (p_) - i_.reset_db (db); - else - i_.reset (); - } - - template - template - inline typename object_traits::id_type lazy_shared_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - return p_ - ? object_traits::id (*p_) - : i_.template object_id (); - } - - template - inline typename lazy_shared_ptr::database_type& lazy_shared_ptr:: - database () const - { - return *i_.database (); - } - - template - inline bool - operator== (const lazy_shared_ptr& a, const lazy_shared_ptr& b) - { - return a.equal (b); - } - - template - inline bool - operator!= (const lazy_shared_ptr& a, const lazy_shared_ptr& b) - { - return !a.equal (b); - } - - template - inline void - swap (lazy_shared_ptr& a, lazy_shared_ptr& b) - { - a.swap (b); - } - - template - inline D* - get_deleter (const lazy_shared_ptr& p) - { - return std::tr1::get_deleter (p.p_); - } - - - // - // lazy_weak_ptr - // - - template - inline lazy_weak_ptr:: - lazy_weak_ptr () {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const lazy_shared_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const lazy_weak_ptr& r): p_ (r.p_), i_ (r.i_) {} - - template - inline lazy_weak_ptr:: - ~lazy_weak_ptr () {} - - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const lazy_weak_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const lazy_weak_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const lazy_shared_ptr& r) - { - p_ = r.p_; - i_ = r.i_; - return *this; - } - - template - inline void lazy_weak_ptr:: - swap (lazy_weak_ptr& r) - { - p_.swap (r.p_); - i_.swap (r.i_); - } - - template - inline void lazy_weak_ptr:: - reset () - { - p_.reset (); - i_.reset (); - } - - template - inline long lazy_weak_ptr:: - use_count () const - { - return p_.use_count (); - } - - template - inline bool lazy_weak_ptr:: - expired () const - { - return p_.expired (); - } - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const std::tr1::weak_ptr& r): p_ (r) {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (const std::tr1::shared_ptr& r): p_ (r) {} - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const std::tr1::weak_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - template - inline lazy_weak_ptr& lazy_weak_ptr:: - operator= (const std::tr1::shared_ptr& r) - { - p_ = r; - i_.reset (); - return *this; - } - - template - inline bool lazy_weak_ptr:: - loaded () const - { - bool i (i_); - return expired () != i; // expired () XOR i_ - } - - template - inline lazy_shared_ptr lazy_weak_ptr:: - lock () const - { - return lazy_shared_ptr (p_.lock (), i_); - } - - template - inline std::tr1::shared_ptr lazy_weak_ptr:: - load () const - { - std::tr1::shared_ptr r (p_.lock ()); - - if (!r && i_) - { - r = i_.template load (false); // Keep id. - p_ = r; - } - - return r; - } - - template - inline void lazy_weak_ptr:: - unload () const - { - // With weak pointer we always keep i_ up to date. - // - p_.reset (); - } - - template - inline std::tr1::weak_ptr lazy_weak_ptr:: - get_eager () const - { - return p_; - } - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (DB& db, const ID& id): i_ (db, id) {} - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (DB& db, const std::tr1::shared_ptr& r) - : p_ (r) - { - typedef typename object_traits::object_type object_type; - - if (r) - i_.reset (db, object_traits::id (*r)); - } - - template - template - inline lazy_weak_ptr:: - lazy_weak_ptr (DB& db, const std::tr1::weak_ptr& r) - : p_ (r) - { - typedef typename object_traits::object_type object_type; - - std::tr1::shared_ptr sp (p_.lock ()); - - if (sp) - i_.reset (db, object_traits::id (*sp)); - } - - template - template - inline void lazy_weak_ptr:: - reset (DB& db, const ID& id) - { - p_.reset (); - i_.reset (db, id); - } - - template - template - inline void lazy_weak_ptr:: - reset (DB& db, const std::tr1::shared_ptr& r) - { - typedef typename object_traits::object_type object_type; - - p_ = r; - - if (r) - i_.reset (db, object_traits::id (*r)); - else - i_.reset (); - } - - template - template - inline void lazy_weak_ptr:: - reset (DB& db, const std::tr1::weak_ptr& r) - { - typedef typename object_traits::object_type object_type; - - p_ = r; - std::tr1::shared_ptr sp (p_.lock ()); - - if (sp) - i_.reset (db, object_traits::id (*sp)); - else - i_.reset (); - } - - template - template - inline typename object_traits::id_type lazy_weak_ptr:: - object_id () const - { - typedef typename object_traits::object_type object_type; - - std::tr1::shared_ptr sp (p_.lock ()); - return sp - ? object_traits::id (*sp) - : i_.template object_id (); - } - - template - inline typename lazy_weak_ptr::database_type& lazy_weak_ptr:: - database () const - { - return *i_.database (); - } - - template - inline void - swap (lazy_weak_ptr& a, lazy_weak_ptr& b) - { - a.swap (b); - } - } -} diff --git a/odb/tr1/lazy-ptr.txx b/odb/tr1/lazy-ptr.txx deleted file mode 100644 index 7e36cd9..0000000 --- a/odb/tr1/lazy-ptr.txx +++ /dev/null @@ -1,43 +0,0 @@ -// file : odb/tr1/lazy-ptr.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - namespace tr1 - { - // - // lazy_shared_ptr - // - - template - template - bool lazy_shared_ptr:: - equal (const lazy_shared_ptr& r) const - { - bool t1 (!p_ == loaded ()); - bool t2 (!r.p_ == r.loaded ()); - - // If both are transient, then compare the underlying pointers. - // - if (t1 && t2) - return p_ == r.p_; - - // If one is transient and the other is persistent, then compare - // the underlying pointers but only if they are non NULL. Note - // that an unloaded persistent object is always unequal to a - // transient object. - // - if (t1 || t2) - return p_ == r.p_ && p_; - - // If both objects are persistent, then we compare databases and - // object ids. - // - typedef typename object_traits::object_type object_type1; - typedef typename object_traits::object_type object_type2; - - return i_.database () == r.i_.database () && - object_id () == r.template object_id (); - } - } -} diff --git a/odb/tr1/memory.hxx b/odb/tr1/memory.hxx deleted file mode 100644 index b9e9f45..0000000 --- a/odb/tr1/memory.hxx +++ /dev/null @@ -1,37 +0,0 @@ -// file : odb/tr1/memory.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TR1_MEMORY_HXX -#define ODB_TR1_MEMORY_HXX - -// -// Try to include TR1 in a compiler-specific manner. Fall back -// on the Boost TR1 implementation if the compiler does not support TR1. -// - -#include // __GLIBCXX__, _HAS_TR1 - -// GNU C++ or Intel C++ using libstd++. -// -#if defined (__GNUC__) && __GNUC__ >= 4 && defined (__GLIBCXX__) -# include -// -// IBM XL C++. -// -#elif defined (__xlC__) && __xlC__ >= 0x0900 -# define __IBMCPP_TR1__ -# include -// -// VC++ or Intel C++ using VC++ standard library. -// -#elif defined (_MSC_VER) && \ - (_MSC_VER == 1500 && defined (_HAS_TR1) || _MSC_VER > 1500) -# include -// -// Boost fall-back. -// -#else -# include -#endif - -#endif // ODB_TR1_MEMORY_HXX diff --git a/odb/tr1/pointer-traits.hxx b/odb/tr1/pointer-traits.hxx deleted file mode 100644 index df4f25f..0000000 --- a/odb/tr1/pointer-traits.hxx +++ /dev/null @@ -1,121 +0,0 @@ -// file : odb/tr1/pointer-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TR1_POINTER_TRAITS_HXX -#define ODB_TR1_POINTER_TRAITS_HXX - -#include - -#include // ODB_CXX11 - -// In VC++ std::shared_ptr and std::tr1::shared_ptr is the same class -// template. One is just a using-declaration for the other. -// -#if !(defined(ODB_CXX11) && defined(_MSC_VER)) - -// -// This header assumes that the necessary TR1 header has already -// been included. -// - -#include -#include - -namespace odb -{ - // Specialization for std::tr1::shared_ptr. - // - template - class pointer_traits > - { - public: - static const pointer_kind kind = pk_shared; - static const bool lazy = false; - - typedef T element_type; - typedef std::tr1::shared_ptr pointer_type; - typedef std::tr1::shared_ptr const_pointer_type; - typedef typename odb::details::meta::remove_const::result - unrestricted_element_type; - typedef std::tr1::shared_ptr - unrestricted_pointer_type; - typedef smart_ptr_guard 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; - } - - static unrestricted_pointer_type - const_pointer_cast (const pointer_type& p) - { - return std::tr1::const_pointer_cast (p); - } - - template - static std::tr1::shared_ptr - static_pointer_cast (const pointer_type& p) - { - return std::tr1::static_pointer_cast (p); - } - - template - static std::tr1::shared_ptr - dynamic_pointer_cast (const pointer_type& p) - { - return std::tr1::dynamic_pointer_cast (p); - } - - public: - static void* - allocate (std::size_t n) - { - return operator new (n); - } - - static void - free (void* p) - { - operator delete (p); - } - }; - - // Specialization for std::tr1::weak_ptr. - // - template - class pointer_traits > - { - public: - static const pointer_kind kind = pk_weak; - static const bool lazy = false; - - typedef T element_type; - typedef std::tr1::weak_ptr pointer_type; - typedef std::tr1::shared_ptr strong_pointer_type; - - static strong_pointer_type - lock (const pointer_type& p) - { - return p.lock (); - } - }; -} - -#endif // !(ODB_CXX11 && _MSC_VER) - -#include - -#endif // ODB_TR1_POINTER_TRAITS_HXX diff --git a/odb/tr1/wrapper-traits.hxx b/odb/tr1/wrapper-traits.hxx deleted file mode 100644 index f878ef6..0000000 --- a/odb/tr1/wrapper-traits.hxx +++ /dev/null @@ -1,76 +0,0 @@ -// file : odb/tr1/wrapper-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TR1_WRAPPER_TRAITS_HXX -#define ODB_TR1_WRAPPER_TRAITS_HXX - -#include - -#include // ODB_CXX11 - -// In VC++ std::shared_ptr and std::tr1::shared_ptr is the same class -// template. One is just a using-declaration for the other. -// -#if !(defined(ODB_CXX11) && defined(_MSC_VER)) - -// -// This header assumes that the necessary TR1 header has already -// been included. -// - -#include - -namespace odb -{ - // Specialization for std::tr1::shared_ptr. - // - template - class wrapper_traits< std::tr1::shared_ptr > - { - public: - typedef T wrapped_type; - typedef std::tr1::shared_ptr wrapper_type; - - // T can be const. - // - typedef - typename odb::details::meta::remove_const::result - unrestricted_wrapped_type; - - static const bool null_handler = true; - static const bool null_default = false; - - static bool - get_null (const wrapper_type& p) - { - return !p; - } - - static void - set_null (wrapper_type& p) - { - p.reset (); - } - - static const wrapped_type& - get_ref (const wrapper_type& p) - { - return *p; - } - - static unrestricted_wrapped_type& - set_ref (wrapper_type& p) - { - if (!p) - p.reset (new unrestricted_wrapped_type); - - return const_cast (*p); - } - }; -} - -#endif // !(ODB_CXX11 && _MSC_VER) - -#include - -#endif // ODB_TR1_WRAPPER_TRAITS_HXX diff --git a/odb/tracer.cxx b/odb/tracer.cxx deleted file mode 100644 index 1e636a7..0000000 --- a/odb/tracer.cxx +++ /dev/null @@ -1,95 +0,0 @@ -// file : odb/tracer.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -#include -#include - -using namespace std; - -namespace odb -{ - // - // tracer - // - - tracer:: - ~tracer () - { - } - - void tracer:: - prepare (connection&, const statement&) - { - } - - void tracer:: - execute (connection& c, const statement& s) - { - execute (c, s.text ()); - } - - void tracer:: - deallocate (connection&, const statement&) - { - } - - // - // stderr_tracer - // - - class stderr_tracer_type: public tracer - { - public: - stderr_tracer_type (bool full): full_ (full) {} - - virtual void - prepare (connection&, const statement&); - - virtual void - execute (connection&, const char* statement); - - virtual void - deallocate (connection&, const statement&); - - // Override the other version to get rid of a Sun CC warning. - // - virtual void - execute (connection&, const statement&); - - private: - bool full_; - }; - - void stderr_tracer_type:: - prepare (connection&, const statement& s) - { - if (full_) - cerr << "PREPARE " << s.text () << endl; - } - - void stderr_tracer_type:: - execute (connection&, const char* s) - { - cerr << s << endl; - } - - void stderr_tracer_type:: - deallocate (connection&, const statement& s) - { - if (full_) - cerr << "DEALLOCATE " << s.text () << endl; - } - - void stderr_tracer_type:: - execute (connection& c, const statement& s) - { - execute (c, s.text ()); - } - - static stderr_tracer_type stderr_tracer_ (false); - static stderr_tracer_type stderr_full_tracer_ (true); - tracer& stderr_tracer = stderr_tracer_; - tracer& stderr_full_tracer = stderr_full_tracer_; -} diff --git a/odb/tracer.hxx b/odb/tracer.hxx deleted file mode 100644 index 11e4e76..0000000 --- a/odb/tracer.hxx +++ /dev/null @@ -1,36 +0,0 @@ -// file : odb/tracer.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TRACER_HXX -#define ODB_TRACER_HXX - -#include - -#include -#include - -namespace odb -{ - class LIBODB_EXPORT tracer - { - public: - virtual - ~tracer (); - - virtual void - prepare (connection&, const statement&); - - virtual void - execute (connection&, const statement&); - - virtual void - execute (connection&, const char* statement) = 0; - - virtual void - deallocate (connection&, const statement&); - }; -} - -#include - -#endif // ODB_TRACER_HXX diff --git a/odb/traits.hxx b/odb/traits.hxx deleted file mode 100644 index 2c6f5d6..0000000 --- a/odb/traits.hxx +++ /dev/null @@ -1,317 +0,0 @@ -// file : odb/traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TRAITS_HXX -#define ODB_TRAITS_HXX - -#include - -#include -#include - -namespace odb -{ - // Fallback dummy for non-persistent classes. It is necessary to allow - // the C++ compiler to instantiate persist(), etc., signatures in class - // database when T is a pointer (raw, smart). The overloads that use - // these dummy would never actually be selected by the compiler. - // - template - class access::object_traits - { - // If a C++ compiler issues an error pointing to this class and saying - // that it is missing some declaration, then you are most likely trying - // to perform a database operation on a C++ type that is not a persistent - // object. Or you forgot to include the corresponding -odb.hxx file. - // - public: - struct id_type {}; - typedef T object_type; - typedef T* pointer_type; - - static const bool polymorphic = false; - }; - - template - class access::object_factory - { - public: - typedef T object_type; - typedef P pointer_type; - - static P - create () - { - // By default use pointer-specific construction. - // - return pointer_factory::create (); - } - }; - - template - class access::view_factory - { - public: - typedef T view_type; - typedef P pointer_type; - - static P - create () - { - // By default use pointer-specific construction. - // - return pointer_factory::create (); - } - }; - - template - class access::pointer_factory - { - public: - typedef T value_type; - typedef P pointer_type; - - - // Suppress bogus use-after-free introduced in GCC 12 (GCC bug #105327). - // -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuse-after-free" -#endif - - static P - create () - { - void* v (pointer_traits

::allocate (sizeof (T))); - mem_guard g (v); - P p (new (v) T); - g.release (); - return p; - } - -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12 -#pragma GCC diagnostic pop -#endif - - private: - struct mem_guard - { - mem_guard (void* p): p_ (p) {} - ~mem_guard () {if (p_) pointer_traits

::free (p_);} - void release () {p_ = 0;} - void* p_; - }; - }; - - // - // class_traits - // - enum class_kind - { - class_object, - class_view, - class_other - }; - - template - struct class_traits - { - static const class_kind kind = class_other; - }; - - template - struct class_traits - { - static const class_kind kind = class_traits::kind; - }; - - // - // object_traits - // - - template - // - // If a C++ compiler issues an error pointing to this struct and - // saying that it is incomplete, then you are most likely trying to - // perform a database operation on a C++ type that is not a persistent - // object. Or you forgot to include the corresponding -odb.hxx file. - // - struct object_traits: - access::object_traits, - access::object_factory::pointer_type> - { - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - typedef typename access::object_traits::object_type object_type; - typedef typename access::object_traits::pointer_type pointer_type; - typedef typename pointer_traits::const_pointer_type const_pointer_type; - }; - - // Specialization for const objects. It only defines the id, object, - // pointer, and const_pointer types with pointer and const_pointer - // being the same. The idea is to only use this specialization in the - // interfaces, with the implementations detecting this situation and - // using the non-const object_traits version. - // - template - struct object_traits - { - private: - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - public: - typedef typename access::object_traits::id_type id_type; - typedef typename access::object_traits::object_type object_type; - typedef typename pointer_traits::const_pointer_type const_pointer_type; - typedef const_pointer_type pointer_type; - - static const bool polymorphic = access::object_traits::polymorphic; - }; - - // Specialization for section to allow instantiation of all the load() - // signature. - // - template <> - struct object_traits

{}; - - template - // - // If a C++ compiler issues an error pointing to this struct and - // saying that it is incomplete, then you are most likely trying to - // perform a database operation on a C++ type that is not a persistent - // object. Or you forgot to include the corresponding -odb.hxx file. - // - struct object_traits_impl: - access::object_traits_impl, - access::object_factory::pointer_type> - { - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - typedef typename access::object_traits::object_type object_type; - typedef typename access::object_traits::pointer_type pointer_type; - typedef typename pointer_traits::const_pointer_type const_pointer_type; - }; - - // - // view_traits - // - - template - // - // If a C++ compiler issues an error pointing to this struct and - // saying that it is incomplete, then you are most likely trying to - // perform a database operation on a C++ type that is not a view - // Or you forgot to include the corresponding -odb.hxx file. - // - struct view_traits: - access::view_traits, - access::view_factory::pointer_type> - { - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - typedef typename access::view_traits::view_type view_type; - typedef typename access::view_traits::pointer_type pointer_type; - }; - - // Specialization for const views. It only defines the view, pointer, - // and const_pointer types with pointer and const_pointer being the - // same. Similar to objects, the idea is to only use this specialization - // in the interfaces, with the implementations detecting this situation - // and using the non-const view_traits version. - // - template - struct view_traits - { - private: - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - public: - typedef typename access::view_traits::view_type view_type; - typedef typename pointer_traits::const_pointer_type const_pointer_type; - typedef const_pointer_type pointer_type; - }; - - template - // - // If a C++ compiler issues an error pointing to this struct and - // saying that it is incomplete, then you are most likely trying to - // perform a database operation on a C++ type that is not a view - // Or you forgot to include the corresponding -odb.hxx file. - // - struct view_traits_impl: - access::view_traits_impl, - access::view_factory::pointer_type> - { - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - typedef typename access::view_traits::view_type view_type; - typedef typename access::view_traits::pointer_type pointer_type; - }; - - // - // composite_value_traits - // - - template - struct composite_value_traits: access::composite_value_traits - { - }; - - // - // Get root image from a polymorphic image chain. - // - - template - struct root_image_impl - { - typedef root_image_impl base_type; - typedef typename base_type::image_type image_type; - - static image_type& - get (typename T::image_type& i) {return base_type::get (*i.base);} - }; - - template - struct root_image_impl - { - typedef typename T::image_type image_type; - - static image_type& - get (image_type& i) {return i;} - }; - - template - struct root_image - { - typedef root_image_impl impl_type; - typedef typename impl_type::image_type image_type; - - static image_type& - get (typename T::image_type& i) {return impl_type::get (i);} - }; - - template - struct root_image - { - typedef typename T::image_type image_type; - - static image_type& - get (image_type& i) {return i;} - }; -} - -#include - -#endif // ODB_TRAITS_HXX diff --git a/odb/transaction.cxx b/odb/transaction.cxx deleted file mode 100644 index f75cf32..0000000 --- a/odb/transaction.cxx +++ /dev/null @@ -1,356 +0,0 @@ -// file : odb/transaction.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include -#include - -#include - -using namespace std; - -namespace odb -{ - using namespace details; - - // - // transaction - // - - static ODB_TLS_POINTER (transaction) current_transaction; - - transaction:: - ~transaction () - { - if (!finalized_) - try {rollback ();} catch (...) {} - } - - void transaction:: - reset (transaction_impl* impl, bool make_current) - { - details::unique_ptr i (impl); - - if (!finalized_) - rollback (); - - impl_.reset (i.release ()); - - if (make_current && tls_get (current_transaction) != 0) - throw already_in_transaction (); - - impl_->start (); - finalized_ = false; - - if (make_current) - tls_set (current_transaction, this); - } - - bool transaction:: - has_current () - { - return tls_get (current_transaction) != 0; - } - - transaction& transaction:: - current () - { - transaction* cur (tls_get (current_transaction)); - - if (cur == 0) - throw not_in_transaction (); - - return *cur; - } - - void transaction:: - current (transaction& t) - { - tls_set (current_transaction, &t); - } - - void transaction:: - reset_current () - { - transaction* t (0); - tls_set (current_transaction, t); - } - - struct rollback_guard - { - rollback_guard (transaction& t): t_ (&t) {} - ~rollback_guard () - {if (t_ != 0) t_->callback_call (transaction::event_rollback);} - void release () {t_ = 0;} - private: - transaction* t_; - }; - - void transaction:: - commit () - { - if (finalized_) - throw transaction_already_finalized (); - - finalized_ = true; - rollback_guard rg (*this); - - impl_->tracer (0); - - if (tls_get (current_transaction) == this) - { - transaction* t (0); - tls_set (current_transaction, t); - } - - impl_->commit (); - rg.release (); - - if (callback_count_ != 0) - callback_call (event_commit); - } - - void transaction:: - rollback () - { - if (finalized_) - throw transaction_already_finalized (); - - finalized_ = true; - rollback_guard rg (*this); - - impl_->tracer (0); - - if (tls_get (current_transaction) == this) - { - transaction* t (0); - tls_set (current_transaction, t); - } - - impl_->rollback (); - rg.release (); - - if (callback_count_ != 0) - callback_call (event_rollback); - } - - void transaction:: - callback_call (unsigned short event) - { - size_t stack_count (callback_count_ < stack_callback_count - ? callback_count_ : stack_callback_count); - size_t dyn_count (callback_count_ - stack_count); - - // We need to be careful with the situation where a callback - // throws and we neither call the rest of the callbacks nor - // reset their states. To make sure this doesn't happen, we - // do a first pass and reset all the states. - // - for (size_t i (0); i < stack_count; ++i) - { - callback_data& d (stack_callbacks_[i]); - if (d.event != 0 && d.state != 0) - *d.state = 0; - } - - for (size_t i (0); i < dyn_count; ++i) - { - callback_data& d (dyn_callbacks_[i]); - if (d.event != 0 && d.state != 0) - *d.state = 0; - } - - // Now do the actual calls. - // - for (size_t i (0); i < stack_count; ++i) - { - callback_data& d (stack_callbacks_[i]); - if (d.event & event) - d.func (event, d.key, d.data); - } - - for (size_t i (0); i < dyn_count; ++i) - { - callback_data& d (dyn_callbacks_[i]); - if (d.event & event) - d.func (event, d.key, d.data); - } - - // Clean things up in case this instance is going to be reused. - // - if (dyn_count != 0) - dyn_callbacks_.clear (); - - free_callback_ = max_callback_count; - callback_count_ = 0; - } - - void transaction:: - callback_register (callback_type func, - void* key, - unsigned short event, - unsigned long long data, - transaction** state) - { - callback_data* s; - - // If we have a free slot, use it. - // - if (free_callback_ != max_callback_count) - { - s = (free_callback_ < stack_callback_count) - ? stack_callbacks_ + free_callback_ - : &dyn_callbacks_[free_callback_ - stack_callback_count]; - - free_callback_ = reinterpret_cast (s->key); - } - // If we have space in the stack, grab that. - // - else if (callback_count_ < stack_callback_count) - { - s = stack_callbacks_ + callback_count_; - callback_count_++; - } - // Otherwise use the dynamic storage. - // - else - { - dyn_callbacks_.push_back (callback_data ()); - s = &dyn_callbacks_.back (); - callback_count_++; - } - - s->func = func; - s->key = key; - s->event = event; - s->data = data; - s->state = state; - } - - size_t transaction:: - callback_find (void* key) - { - if (callback_count_ == 0) - return 0; - - size_t stack_count; - - // See if this is the last slot registered. This will be a fast path if, - // for example, things are going to be unregistered from destructors. - // - if (callback_count_ <= stack_callback_count) - { - if (stack_callbacks_[callback_count_ - 1].key == key) - return callback_count_ - 1; - - stack_count = callback_count_; - } - else - { - if (dyn_callbacks_.back ().key == key) - return callback_count_ - 1; - - stack_count = stack_callback_count; - } - - // Otherwise do a linear search. - // - for (size_t i (0); i < stack_count; ++i) - if (stack_callbacks_[i].key == key) - return i; - - for (size_t i (0), dyn_count (callback_count_ - stack_count); - i < dyn_count; ++i) - if (dyn_callbacks_[i].key == key) - return i + stack_callback_count; - - return callback_count_; - } - - void transaction:: - callback_unregister (void* key) - { - size_t i (callback_find (key)); - - // It is ok for this function not to find the key. - // - if (i == callback_count_) - return; - - // See if this is the last slot registered. - // - if (i == callback_count_ - 1) - { - if (i >= stack_callback_count) - dyn_callbacks_.pop_back (); - - callback_count_--; - } - else - { - callback_data& d ( - i < stack_callback_count - ? stack_callbacks_[i] - : dyn_callbacks_[i - stack_callback_count]); - - // Add to the free list. - // - d.event = 0; - d.key = reinterpret_cast (free_callback_); - free_callback_ = i; - } - } - - void transaction:: - callback_update (void* key, - unsigned short event, - unsigned long long data, - transaction** state) - { - size_t i (callback_find (key)); - - // It is ok for this function not to find the key. - // - if (i == callback_count_) - return; - - callback_data& d ( - i < stack_callback_count - ? stack_callbacks_[i] - : dyn_callbacks_[i - stack_callback_count]); - - d.event = event; - d.data = data; - d.state = state; - } - - // - // transaction_impl - // - - transaction_impl:: - ~transaction_impl () - { - } - - connection& transaction_impl:: - connection (database_type* db) - { - assert (db == 0 || db == &database_); - return *connection_; - } - - // The transaction-specific tracer is stored in the connection. See the - // connection class for the reason. - // - void transaction_impl:: - tracer (tracer_type* t) - { - connection_->transaction_tracer_ = t; - } - - tracer* transaction_impl:: - tracer () const - { - return connection_->transaction_tracer_; - } -} diff --git a/odb/transaction.hxx b/odb/transaction.hxx deleted file mode 100644 index 1958df3..0000000 --- a/odb/transaction.hxx +++ /dev/null @@ -1,278 +0,0 @@ -// file : odb/transaction.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_TRANSACTION_HXX -#define ODB_TRANSACTION_HXX - -#include - -#include -#include // std::size_t - -#include - -#include -#include - -namespace odb -{ - class transaction_impl; - - class LIBODB_EXPORT transaction - { - public: - typedef odb::database database_type; - typedef odb::connection connection_type; - - // If the second argument is false, then this transaction is not made - // the current transaction of the thread. - // - explicit - transaction (transaction_impl*, bool make_current = true); - - // Create a finalized transaction instance which can later be initialized - // with reset(). - // - transaction (); - - // Unless the transaction has already been finalized (explicitly - // committed or rolled back), the destructor will roll it back. - // - ~transaction (); - - // Unless the current transaction has already been finalized (explicitly - // committed or rolled back), reset will roll it back. If the second - // argument is false, then this transaction is not made the current - // transaction of the thread. - // - void - reset (transaction_impl*, bool make_current = true); - - void - commit (); - - void - rollback (); - - // Return the database this transaction is on. - // - database_type& - database (); - - // Return the connection this transaction is on. - // - // The second version verifies the connection is to the specified - // database. For database implementations that support attaching multiple - // databases it may also select the connection corresponding to the - // specified database. - // - connection_type& - connection (); - - connection_type& - connection (database_type&); - - bool - finalized () const {return finalized_;} - - public: - // Return true if there is a transaction in effect. - // - static bool - has_current (); - - // Return current transaction or throw if there is no transaction - // in effect. - // - static transaction& - current (); - - // Set the current thread's transaction. - // - static void - current (transaction&); - - // Revert to the no transaction in effect state for the current thread. - // - static void - reset_current (); - - // SQL statement tracing. - // - public: - typedef odb::tracer tracer_type; - - void - tracer (tracer_type&); - - void - tracer (tracer_type*); - - tracer_type* - tracer () const; - - // Post-commit/rollback callbacks. - // - public: - static const unsigned short event_commit = 0x01; - static const unsigned short event_rollback = 0x02; - static const unsigned short event_all = event_commit | event_rollback; - - typedef void (*callback_type) ( - unsigned short event, void* key, unsigned long long data); - - // Register a post-commit/rollback callback. The data argument - // can be used to store any user data that does not exceed 8 - // bytes and doesn't require alignment greater than unsigned - // long long, such as an old value that needs to be restored - // in case of a rollback. - // - // The state argument can be used to indicate to the caller - // that the callback has been unregistered because the - // transaction has terminated. In this case the transaction - // resets the passed pointer to 0. - // - // Note that the order in which the callbacks are called is - // unspecified. - // - void - callback_register (callback_type, - void* key, - unsigned short event = event_all, - unsigned long long data = 0, - transaction** state = 0); - - // Unregister a post-commit/rollback callback. Note that this is a - // potentially slow operation. You also don't need to unregister - // a callback that has been called or auto-reset using the state - // argument passed to register(). This function does nothing if - // the key is not found. - // - void - callback_unregister (void* key); - - // Update the event, data, and state values for a callback. Note - // that just like unregister(), this is a potentially slow operation. - // - void - callback_update (void* key, - unsigned short event, - unsigned long long data = 0, - transaction** state = 0); - - public: - transaction_impl& - implementation (); - - // Copying or assignment of transactions is not supported. - // - private: - transaction (const transaction&); - transaction& operator= (const transaction&); - - protected: - friend struct rollback_guard; - - std::size_t - callback_find (void* key); - - void - callback_call (unsigned short event); - - protected: - bool finalized_; - details::unique_ptr impl_; - - // Callbacks. - // - struct callback_data - { - unsigned short event; - callback_type func; - void* key; - unsigned long long data; - transaction** state; - }; - - // Slots for the first 20 callback are pre-allocated on the stack. - // For the rest they are allocated dynamically as needed. - // - // Note, if you change stack_callback_count, make sure you also - // update the common/transaction/callback test accordingly. - // - static const std::size_t stack_callback_count = 20; - static const std::size_t max_callback_count = ~(std::size_t (0)); - - callback_data stack_callbacks_[stack_callback_count]; - std::vector dyn_callbacks_; - - // When a callback is unregistered, the free slot from the stack is - // added to the linked list of free slots which is organized by - // re-using the key data member to store the slot's index (we cannot - // store a pointer because std::vector may move slots on expansion). - // The value equal to max_callback_count indicates no free slots are - // available. - // - std::size_t free_callback_; - - // Total number of used slots, both registered and in the free list. - // - std::size_t callback_count_; - }; - - class LIBODB_EXPORT transaction_impl - { - public: - typedef odb::tracer tracer_type; - typedef odb::database database_type; - typedef odb::connection connection_type; - - virtual - ~transaction_impl (); - - virtual void - start () = 0; - - virtual void - commit () = 0; - - virtual void - rollback () = 0; - - database_type& - database () - { - return database_; - } - - virtual connection_type& - connection (database_type*); - - virtual void - tracer (tracer_type*); - - virtual tracer_type* - tracer () const; - - protected: - transaction_impl (database_type& db) - : database_ (db), connection_ (0) - { - } - - transaction_impl (database_type& db, connection_type& c) - : database_ (db), connection_ (&c) - { - } - - protected: - database_type& database_; - connection_type* connection_; - }; -} - -#include - -#include - -#endif // ODB_TRANSACTION_HXX diff --git a/odb/transaction.ixx b/odb/transaction.ixx deleted file mode 100644 index cc1ce5e..0000000 --- a/odb/transaction.ixx +++ /dev/null @@ -1,68 +0,0 @@ -// file : odb/transaction.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -namespace odb -{ - inline transaction:: - transaction () - : finalized_ (true), - impl_ (0), - free_callback_ (max_callback_count), - callback_count_ (0) - { - } - - inline transaction:: - transaction (transaction_impl* impl, bool make_current) - : finalized_ (true), - impl_ (0), - free_callback_ (max_callback_count), - callback_count_ (0) - { - reset (impl, make_current); - } - - inline transaction::database_type& transaction:: - database () - { - return impl_->database (); - } - - inline transaction::connection_type& transaction:: - connection () - { - return impl_->connection (0); - } - - inline transaction::connection_type& transaction:: - connection (database_type& db) - { - return impl_->connection (&db); - } - - inline transaction_impl& transaction:: - implementation () - { - return *impl_; - } - - inline void transaction:: - tracer (tracer_type& t) - { - impl_->tracer (&t); - } - - inline void transaction:: - tracer (tracer_type* t) - { - impl_->tracer (t); - } - - inline transaction::tracer_type* transaction:: - tracer () const - { - return impl_->tracer (); - } -} diff --git a/odb/vector-impl.cxx b/odb/vector-impl.cxx deleted file mode 100644 index ca30f8d..0000000 --- a/odb/vector-impl.cxx +++ /dev/null @@ -1,208 +0,0 @@ -// file : odb/vector-impl.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include - -#include // std::memcpy, std::memset -#include // std::swap - -using namespace std; - -namespace odb -{ - // vector_impl - // - const unsigned char vector_impl::mask_[4] = {0x3, 0xC, 0x30, 0xC0}; - const unsigned char vector_impl::shift_[4] = {0, 2, 4, 6}; - - vector_impl:: - vector_impl (const vector_impl& x) - : state_ (x.state_), size_ (0), tail_ (0), capacity_ (0), data_ (0) - { - // Copy the data over if we are tracking. - // - if (state_ == state_tracking && x.size_ != 0) - { - realloc (x.size_ < 1024 ? 1024 : x.size_); - memcpy (data_, x.data_, x.size_ / 4 + (x.size_ % 4 == 0 ? 0 : 1)); - size_ = x.size_; - tail_ = x.tail_; - } - } - - void vector_impl:: - realloc (size_t n) - { - // The new capacity can be less or greater than the old one, but - // it cannot be less than size. - // - size_t b (n / 4 + (n % 4 == 0 ? 0 : 1)); - - if (b != capacity_ * 4) - { - unsigned char* d (static_cast (operator new (b))); - - if (size_ != 0) - memcpy (d, data_, size_ / 4 + (size_ % 4 == 0 ? 0 : 1)); - - if (data_ != 0) - operator delete (data_); - - data_ = d; - capacity_ = b * 4; - } - } - - void vector_impl:: - shrink_to_fit () - { - if (size_ != capacity_) - { - if (size_ != 0) - realloc (size_); - else - { - operator delete (data_); - data_ = 0; - capacity_ = 0; - } - } - } - - void vector_impl:: - start (size_t n) - { - if (n != 0) - { - if (capacity_ < n) - { - size_ = 0; - realloc (n < 1024 ? 1024 : n); - } - - memset (data_, 0, n / 4 + (n % 4 == 0 ? 0 : 1)); - } - - state_ = state_tracking; - size_ = tail_ = n; - } - - void vector_impl:: - push_back (size_t n) - { - for (; n != 0; --n) - { - size_t i (tail_); - - element_state_type s; - if (i != size_) - // We have an erased element we can reuse. - // - s = state_updated; - else - { - if (size_ == capacity_) - { - size_t c (capacity_ == 0 ? 1024 : capacity_ * 2); - if (c < size_ + n) - c = size_ + n; - realloc (c); - } - - s = state_inserted; - size_++; - } - - set (i, s); - tail_++; - } - } - - void vector_impl:: - pop_back (size_t n) - { - for (; n != 0; --n) - { - size_t i (tail_ - 1); - - if (state (i) != state_inserted) - set (i, state_erased); - else - size_--; // tail_ == size_ - - tail_--; - } - } - - void vector_impl:: - insert (size_t i, size_t n) - { - for (; i != tail_; ++i) - if (state (i) != state_inserted) - set (i, state_updated); - - push_back (n); - } - - void vector_impl:: - erase (size_t i, size_t n) - { - pop_back (n); - - for (; i != tail_; ++i) - if (state (i) != state_inserted) - set (i, state_updated); - } - - void vector_impl:: - clear () - { - // The idea is to drop any inserted elements from the back and - // set everything else to erased. - // - if (tail_ == size_) - { - while (size_ != 0 && state (size_ - 1) == state_inserted) - size_--; - - tail_ = size_; - } - - if (tail_ != 0) - memset (data_, 0xFF, tail_ / 4 + (tail_ % 4 == 0 ? 0 : 1)); - - tail_ = 0; - } - - // vector_base - // - void vector_base:: - rollback (unsigned short, void* key, unsigned long long) - { - // Mark as changed. - // - static_cast (key)->impl_.change (); - } - - void vector_base:: - swap_tran (vector_base& x) - { - // If either instance is armed, then we need to update the - // callback registration. - // - transaction* t (x.tran_); - if (tran_ != 0) - { - tran_->callback_unregister (this); - x._arm (*tran_); - } - - if (t != 0) - { - t->callback_unregister (&x); - _arm (*t); - } - - std::swap (tran_, x.tran_); - } -} diff --git a/odb/vector-impl.hxx b/odb/vector-impl.hxx deleted file mode 100644 index 9f2ea7c..0000000 --- a/odb/vector-impl.hxx +++ /dev/null @@ -1,221 +0,0 @@ -// file : odb/vector-impl.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_VECTOR_IMPL_HXX -#define ODB_VECTOR_IMPL_HXX - -#include -#include // ODB_CXX11 - -#include -#include // std::size_t - -#include -#include - -namespace odb -{ - // Change tracking vector implementation details. - // - class LIBODB_EXPORT vector_impl - { - public: - enum element_state_type - { - state_unchanged, - state_inserted, - state_updated, - state_erased - }; - - enum container_state_type - { - state_tracking, - state_not_tracking, - state_changed // Container has changed but individual changes - // were not tracked. - }; - - vector_impl (); - ~vector_impl (); - - // The copy constructor will copy the state. The idea is that the - // copy keeps tracking changes, just like the original. - // - vector_impl (const vector_impl&); - -#ifdef ODB_CXX11 - vector_impl (vector_impl&&) noexcept; -#endif - - void - swap (vector_impl& x); - - // Allocate enough memory to store the specified number of - // elements. - // - void - reserve (std::size_t); - - // Reduce capacity to size. - // - void - shrink_to_fit (); - - // Capacity (each entry takes 2 bits). - // - std::size_t - capacity () const; - - // (Re)start tracking changes for a vector with n elements. - // - void - start (std::size_t); - - // Stop tracking changes. - // - void - stop (); - - // Mark the container as changed without tracking the changes. - // This state is useful as a fallback mechnism for situations - // where the change information has been discarded (e.g., after - // its state has been updated in the database) but the container - // should remain changed (e.g., after the transaction is rolled - // back). - // - void - change (); - - // Get the state of the container. - // - container_state_type - state () const; - - // Shortcut for state() == state_tracking. - // - bool - tracking () const; - - // Note that the returned size can be greater than the actual, - // parallel vector size. In this case the difference is the - // erased elements at the back. - // - std::size_t - size () const; - - // Get the change state of the specified element. - // - element_state_type - state (std::size_t) const; - - // Change notifications. - // - void - push_back (std::size_t n = 1); - - void - pop_back (std::size_t n = 1); - - void - insert (std::size_t, std::size_t n = 1); - - void - erase (std::size_t, std::size_t n = 1); - - void - modify (std::size_t, std::size_t n = 1); - - void - clear (); - - void - assign (std::size_t n); - - void - resize (std::size_t n); - - private: - // Assignment does not make sense (it is changing of the content). - // - vector_impl& operator= (const vector_impl&); - - private: - void - realloc (std::size_t); - - void - set (std::size_t, element_state_type); - - static const unsigned char mask_[4]; - static const unsigned char shift_[4]; - - container_state_type state_; - - // Size, tail, and capacity are in 2-bit blocks. Size is the number - // of elements we have in data. Tail is the position of the first - // erased element at the back. If there are no erased elements, then - // tail is equal size. Capacity is the number of elements we can - // store in data. - // - std::size_t size_; - std::size_t tail_; - std::size_t capacity_; - unsigned char* data_; - }; - - // Base class that provides a change tracking interface and - // handles the rollback callback. The only function that's - // missing is _start() which needs to know the number of - // elements currently in the vector. - // - class LIBODB_EXPORT vector_base - { - public: - void - _stop () const; - - bool - _tracking () const; - - void - _arm (transaction& t) const; - - vector_impl& - _impl () const {return impl_;} - - private: - // Assignment is changing of the content. - // - vector_base& operator= (const vector_base&); - - protected: - ~vector_base (); - vector_base (); - vector_base (const vector_base&); - -#ifdef ODB_CXX11 - vector_base (vector_base&&) noexcept; -#endif - - void - swap (vector_base&); - - static void - rollback (unsigned short, void* key, unsigned long long); - - private: - void - swap_tran (vector_base&); - - protected: - mutable vector_impl impl_; - mutable transaction* tran_; - }; -} - -#include - -#include - -#endif // ODB_VECTOR_IMPL_HXX diff --git a/odb/vector-impl.ixx b/odb/vector-impl.ixx deleted file mode 100644 index 21999d5..0000000 --- a/odb/vector-impl.ixx +++ /dev/null @@ -1,210 +0,0 @@ -// file : odb/vector-impl.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifdef ODB_CXX11 -# include // std::swap, std::move -#else -# include // std::swap -#endif - -namespace odb -{ - // vector_impl - // - inline vector_impl:: - vector_impl () - : state_ (state_not_tracking), - size_ (0), tail_ (0), capacity_ (0), data_ (0) - { - } - - inline void vector_impl:: - swap (vector_impl& x) - { - std::swap (state_, x.state_); - std::swap (size_, x.size_); - std::swap (tail_, x.tail_); - std::swap (capacity_, x.capacity_); - std::swap (data_, x.data_); - } - -#ifdef ODB_CXX11 - inline vector_impl:: - vector_impl (vector_impl&& x) noexcept - : state_ (state_not_tracking), - size_ (0), tail_ (0), capacity_ (0), data_ (0) - { - swap (x); - } -#endif - - inline vector_impl:: - ~vector_impl () - { - if (data_ != 0) - operator delete (data_); - } - - inline void vector_impl:: - reserve (std::size_t n) - { - if (n > capacity_) - realloc (n); - } - - inline void vector_impl:: - stop () - { - state_ = state_not_tracking; - size_ = tail_ = 0; - } - - inline void vector_impl:: - change () - { - state_ = state_changed; - size_ = tail_ = 0; - } - - inline vector_impl::container_state_type vector_impl:: - state () const - { - return state_; - } - - inline bool vector_impl:: - tracking () const - { - return state_ == state_tracking; - } - - inline std::size_t vector_impl:: - size () const - { - return size_; - } - - inline std::size_t vector_impl:: - capacity () const - { - return capacity_; - } - - inline vector_impl::element_state_type vector_impl:: - state (std::size_t i) const - { - std::size_t r (i % 4); - unsigned char v (data_[i / 4]); - return static_cast ((v & mask_[r]) >> shift_[r]); - } - - inline void vector_impl:: - set (std::size_t i, element_state_type s) - { - std::size_t r (i % 4); - i /= 4; - unsigned char v (static_cast (s)); - v <<= shift_[r]; - data_[i] = (data_[i] & ~mask_[r]) | v; - } - - inline void vector_impl:: - modify (std::size_t i, std::size_t n) - { - for (; n != 0; --n, ++i) - if (state (i) != state_inserted) - set (i, state_updated); - } - - inline void vector_impl:: - assign (std::size_t n) - { - if (tail_ != 0) - clear (); - - push_back (n); - } - - inline void vector_impl:: - resize (size_t n) - { - if (n < tail_) - pop_back (tail_ - n); - else if (n > tail_) - push_back (n - tail_); - } - - // vector_base - // - inline vector_base:: - ~vector_base () - { - if (tran_ != 0) - tran_->callback_unregister (this); - } - - inline vector_base:: - vector_base (): tran_ (0) {} - - inline void vector_base:: - _arm (transaction& t) const - { - tran_ = &t; - t.callback_register (&rollback, - const_cast (this), - transaction::event_rollback, - 0, - &tran_); - } - - inline vector_base:: - vector_base (const vector_base& x) - : impl_ (x.impl_), tran_ (0) - { - // If the original is armed, then arm ourselves as well. - // - if (x.tran_ != 0) - _arm (*x.tran_); - } - - inline void vector_base:: - swap (vector_base& x) - { - impl_.swap (x.impl_); - - if (tran_ != 0 || x.tran_ != 0) - swap_tran (x); - } - -#ifdef ODB_CXX11 - inline vector_base:: - vector_base (vector_base&& x) noexcept - : impl_ (std::move (x.impl_)), tran_ (0) - { - if (x.tran_ != 0) - { - x.tran_->callback_unregister (&x); - - // Note that _arm() can potentially throw bad_alloc while adding a new - // callback to the callbacks list of the transaction object. However, we - // assume that this will not happen since the new callback should be - // saved into an existing slot, freed by the above callback_unregister() - // call. - // - _arm (*x.tran_); - } - } -#endif - - inline void vector_base:: - _stop () const - { - impl_.stop (); - } - - inline bool vector_base:: - _tracking () const - { - return impl_.tracking (); - } -} diff --git a/odb/vector-traits.hxx b/odb/vector-traits.hxx deleted file mode 100644 index 5e6cf14..0000000 --- a/odb/vector-traits.hxx +++ /dev/null @@ -1,106 +0,0 @@ -// file : odb/vector-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_VECTOR_TRAITS_HXX -#define ODB_VECTOR_TRAITS_HXX - -#include - -#include -#include -#include -#include - -namespace odb -{ - template - class access::container_traits > - { - public: - static const container_kind kind = ck_ordered; - static const bool smart = true; - - typedef vector container_type; - - typedef V value_type; - typedef typename container_type::size_type index_type; - - typedef smart_ordered_functions functions; - typedef ordered_functions dumb_functions; - - public: - static void - persist (const container_type& c, const functions& f) - { - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - - // Now that this container is persistent, start tracking changes. - // - c._start (); - } - - static void - load (container_type& c, bool more, const functions& f) - { - // Stop tracking changes. - // - c._stop (); - - // Load. - // - c.clear (); - while (more) - { - index_type dummy; - c.push_back (value_type ()); - more = f.select (dummy, c.modify_back ()); - } - - // Start tracking changes. - // - c._start (); - } - - static bool - changed (const container_type&); - - static void - update (const container_type&, const functions&); - - static void - erase (const container_type* c, const functions& f) - { - f.delete_ (0); - - // Stop tracking changes. - // - if (c != 0) - c->_stop (); - } - - // Version of load() for dumb functions. Used to support - // inverse members of the container type. The implementation - // is identical to the smart one except we don't turn off/on - // change tracking. - // - static void - load (container_type& c, bool more, const dumb_functions& f) - { - c.clear (); - - while (more) - { - index_type dummy; - c.push_back (value_type ()); - more = f.select (dummy, c.modify_back ()); - } - } - }; -} - -#include - -#include - -#endif // ODB_VECTOR_TRAITS_HXX diff --git a/odb/vector-traits.txx b/odb/vector-traits.txx deleted file mode 100644 index 6c33876..0000000 --- a/odb/vector-traits.txx +++ /dev/null @@ -1,100 +0,0 @@ -// file : odb/vector-traits.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - template - bool access::container_traits >:: - changed (const container_type& c) - { - // Because modifications can cancel each other (e.g., push and pop), - // it is tricky to keep track of whether there are any changes in - // the container. Instead, we are just going to examine each element - // just like update(). - // - - // We should either be tracking or summarily changed. - // - if (c._tracking ()) - { - const vector_impl& impl (c._impl ()); - - for (std::size_t i (0), n (impl.size ()); i < n; ++i) - { - if (impl.state (i) != vector_impl::state_unchanged) - return true; - } - } - else - return true; - - return false; - } - - template - void access::container_traits >:: - update (const container_type& c, const functions& f) - { - bool u (false); // Updated flag. - - if (c._tracking ()) - { - const vector_impl& impl (c._impl ()); - - for (std::size_t i (0), n (impl.size ()); i < n; ++i) - { - vector_impl::element_state_type s (impl.state (i)); - - switch (s) - { - case vector_impl::state_unchanged: - { - break; - } - case vector_impl::state_inserted: - { - f.insert (i, c[static_cast (i)]); - u = u || true; - break; - } - case vector_impl::state_updated: - { - f.update (i, c[static_cast (i)]); - u = u || true; - break; - } - case vector_impl::state_erased: - { - f.delete_ (i); // Delete from i onwards. - u = u || true; - break; - } - } - - // We delete all trailing elements in one go. - // - if (s == vector_impl::state_erased) - break; - } - } - else - { - // Fall back to delete all/insert all. - // - f.delete_ (0); - - for (index_type i (0), n (c.size ()); i < n; ++i) - f.insert (i, c[i]); - - u = true; - } - - // Arm the rollback callback and (re)start change tracking. - // - if (u) - { - c._arm (transaction::current ()); - c._start (); - } - } -} diff --git a/odb/vector.hxx b/odb/vector.hxx deleted file mode 100644 index 3fe7d8a..0000000 --- a/odb/vector.hxx +++ /dev/null @@ -1,635 +0,0 @@ -// file : odb/vector.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_VECTOR_HXX -#define ODB_VECTOR_HXX - -#include -#include // ODB_CXX11 - -#include -#include -#include // std::ptrdiff_t - -#ifdef ODB_CXX11 -# include // std::move, std::forward -# ifdef ODB_CXX11_INITIALIZER_LIST -# include -# endif -#endif - -#include - -// Because both std::vector and odb::vector are called 'vector' (who -// cares about namespace qualifications, right?), Sun CC complains -// with a bogus "Ambiguous partial specialization" error. A really -// hideous workaround for this bug is to to add a dummy third template -// argument (with a default value). -// -#ifdef __SUNPRO_CC -# define LIBODB_VECTOR_ARG_DEFAULT ,int = 0 -# define LIBODB_VECTOR_ARG_DECL ,int DUMMY -# define LIBODB_VECTOR_ARG_USE ,DUMMY -#else -# define LIBODB_VECTOR_ARG_DEFAULT -# define LIBODB_VECTOR_ARG_DECL -# define LIBODB_VECTOR_ARG_USE -#endif - -namespace odb -{ - // An std::vector-like container that keeps track of changes. - // - // Note that the style and order of definitions is as appears - // in the standard. - // - template - class vector_iterator; - - template LIBODB_VECTOR_ARG_DEFAULT> - class vector: public vector_base - { - public: - typedef std::vector base_vector_type; - typedef typename base_vector_type::iterator base_iterator_type; - typedef typename base_vector_type::reverse_iterator - base_reverse_iterator_type; - // types: - // - typedef typename base_vector_type::reference reference; - typedef typename base_vector_type::const_reference const_reference; - typedef vector_iterator iterator; - typedef typename base_vector_type::const_iterator const_iterator; - typedef typename base_vector_type::size_type size_type; - typedef typename base_vector_type::difference_type difference_type; - typedef T value_type; - typedef A allocator_type; - typedef typename base_vector_type::pointer pointer; - typedef typename base_vector_type::const_pointer const_pointer; - // No non-const reverse iterator support for Sun CC with non-standard STL. - // -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - typedef vector_iterator - reverse_iterator; -#endif - typedef typename base_vector_type::const_reverse_iterator - const_reverse_iterator; - // construct/copy/destroy: - // - explicit vector(const A& a = A()): v_ (a) {} - explicit vector(size_type n): v_ (n) {} // C++11 - vector(size_type n, const T& v, const A& a = A()): v_ (n, v, a) {} - template - vector(I f, I l, const A& a = A()) : v_ (f, l, a) {} - vector(const vector& x): vector_base (x), v_ (x.v_) {} - // ~vector() {} - vector& operator=(const vector&); - template - void assign(I f, I l); - void assign(size_type n, const T& u); - allocator_type get_allocator() const /*noexcept*/ - {return v_.get_allocator ();} - -#ifdef ODB_CXX11 - vector(vector&& x) noexcept - : vector_base (std::move (x)), v_ (std::move (x.v_)) {} - - vector(const vector& x, const A& a): vector_base (x), v_ (x.v_, a) {} - vector(vector&& x, const A& a) - : vector_base (std::move (x)), v_ (std::move (x.v_), a) {} - - // Note: noexcept is not specified since it can throw while reallocating - // impl_. - // - vector& operator=(vector&&); -#ifdef ODB_CXX11_INITIALIZER_LIST - vector(std::initializer_list il, const A& a = A()): v_ (il, a) {} - vector& operator=(std::initializer_list); - void assign(std::initializer_list); -#endif -#endif - - // iterators: (all /*noexcept*/) - // - iterator begin() {return iterator (this, v_.begin ());} - iterator end() {return iterator (this, v_.end ());} - const_iterator begin() const {return v_.begin ();} - const_iterator end() const {return v_.end ();} -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - reverse_iterator rbegin() {return reverse_iterator (this, v_.rbegin ());} - reverse_iterator rend() {return reverse_iterator (this, v_.rend ());} -#endif - const_reverse_iterator rbegin() const {return v_.rbegin ();} - const_reverse_iterator rend() const {return v_.rend ();} - - // Return standard vector iterators. The begin() functions mark all - // the elements as modified. - // - base_iterator_type mbegin (); - base_iterator_type mend () {return v_.end ();} - base_reverse_iterator_type mrbegin (); - base_reverse_iterator_type mrend () {return v_.rend ();} - -#ifdef ODB_CXX11 - const_iterator cbegin() const {return v_.cbegin ();} - const_iterator cend() const {return v_.cend ();} - const_reverse_iterator crbegin() const {return v_.crbegin ();} - const_reverse_iterator crend() const {return v_.crend ();} -#endif - - // capacity: - // - size_type size() const /*noexcept*/ {return v_.size ();} - size_type max_size() const /*noexcept*/ {return v_.max_size ();} - void resize(size_type); // C++11 - void resize(size_type, const T&); - size_type capacity() const /*noexcept*/ {return v_.capacity ();} - bool empty() const /*noexcept*/ {return v_.empty ();} - void reserve(size_type); - -#ifdef ODB_CXX11 - void shrink_to_fit(); -#endif - - // element access: - // - //reference operator[](size_type n); - reference modify(size_type n); - const_reference operator[](size_type n) const {return v_[n];} - //reference at(size_type n); - reference modify_at(size_type n); - const_reference at(size_type n) const {return v_.at (n);} - //reference front(); - reference modify_front(); - const_reference front() const {return v_.front ();} - //reference back(); - reference modify_back(); - const_reference back() const {return v_.back ();} - - // data access: - // -#ifdef ODB_CXX11 - //T* data() noexcept; - T* modify_data() /*noexcept*/; - const T* data() const /*noexcept*/ {return v_.data ();} -#endif - - // modifiers: - // - void push_back(const T& x); - void pop_back(); - iterator insert(iterator position, const T& x); - void insert(iterator position, size_type n, const T& x); - template - void insert(iterator position, I first, I last); - iterator erase(iterator position); - iterator erase(iterator first, iterator last); - void swap(vector&); - void clear() /*noexcept*/; - -#ifdef ODB_CXX11 - // In C++11 all modifiers use const_iterator instead of iterator - // to represent position. However, some standard libraries (notably - // GCC's) still use iterator and so we will do that as well, for now. - // - void push_back(T&& x); - iterator insert(iterator position, T&& x); - -#ifdef ODB_CXX11_VARIADIC_TEMPLATE - template - void emplace_back(Args&&... args); - template - iterator emplace(iterator position, Args&&... args); -#endif -#endif - - // Interfacing with the base vector. - // - vector (const base_vector_type& x): v_ (x) {} - vector& operator= (const base_vector_type&); - operator const base_vector_type& () const {return v_;} - base_vector_type& base () {return v_;} - const base_vector_type& base () const {return v_;} - -#ifdef ODB_CXX11 - vector (base_vector_type&& x): v_ (std::move (x)) {} - vector& operator= (base_vector_type&&); -#endif - - // Change tracking (the rest comes from vector_base). - // - public: - void - _start () const {impl_.start (v_.size ());} - - private: - base_vector_type v_; - }; - - namespace core - { - using odb::vector; - } - - template - inline bool operator==(const vector& x, - const vector& y) - {return x.base () == y.base ();} - - template - inline bool operator==(const vector& x, - const std::vector& y) - {return x.base () == y;} - - template - inline bool operator==(const std::vector& x, - const vector& y) - {return x == y.base ();} - - template - inline bool operator< (const vector& x, - const vector& y) - {return x.base () < y.base ();} - - template - inline bool operator<(const vector& x, - const std::vector& y) - {return x.base () < y;} - - template - inline bool operator<(const std::vector& x, - const vector& y) - {return x < y.base ();} - - template - inline bool operator!=(const vector& x, - const vector& y) - {return x.base () != y.base ();} - - template - inline bool operator!=(const vector& x, - const std::vector& y) - {return x.base () != y;} - - template - inline bool operator!=(const std::vector& x, - const vector& y) - {return x != y.base ();} - - template - inline bool operator> (const vector& x, - const vector& y) - {return x.base () > y.base ();} - - template - inline bool operator>=(const vector& x, - const vector& y) - {return x.base () >= y.base ();} - - template - inline bool operator>=(const vector& x, - const std::vector& y) - {return x.base () >= y;} - - template - inline bool operator>=(const std::vector& x, - const vector& y) - {return x >= y.base ();} - - template - inline bool operator<=(const vector& x, - const vector& y) - {return x.base () <= y.base ();} - - template - inline bool operator<=(const vector& x, - const std::vector& y) - {return x.base () <= y;} - - template - inline bool operator<=(const std::vector& x, - const vector& y) - {return x <= y.base ();} - - template - class vector_iterator - { - public: - typedef V vector_type; - typedef I base_iterator_type; - typedef typename vector_type::const_iterator const_iterator_type; - - // Sun CC with non-standard STL does not have iterator_traits. - // -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - typedef std::iterator_traits base_iterator_traits; - - typedef typename base_iterator_traits::value_type value_type; - typedef typename base_iterator_traits::difference_type difference_type; - typedef typename base_iterator_traits::pointer pointer; - typedef typename base_iterator_traits::reference reference; - typedef typename base_iterator_traits::iterator_category iterator_category; -#else - // Base iterator is just a pointer. - // - typedef typename vector_type::value_type value_type; - typedef typename vector_type::pointer pointer; - typedef typename vector_type::reference reference; - typedef std::random_access_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; -#endif - - typedef typename vector_type::size_type size_type; - typedef typename vector_type::const_reference const_reference; - typedef typename vector_type::const_pointer const_pointer; - - vector_iterator (): v_ (0), i_ () {} - vector_iterator (vector_type* v, const base_iterator_type& i) - : v_ (v), i_ (i) {} - operator const_iterator_type () const {return i_;} - base_iterator_type base () const {return i_;} - vector_type* vector () const {return v_;} - - // Note: const_{reference,pointer}. - // - const_reference operator* () const {return *i_;} - const_pointer operator-> () const {return i_.operator -> ();} - const_reference operator[] (difference_type n) const {return i_[n];} - - // Modifiers. - // - // Buggy Sun CC cannot have them out of class. - // - reference modify () const - { - if (v_->_tracking ()) - v_->_impl ().modify ( - static_cast (i_ - v_->base ().begin ())); - return *i_; - } - - reference modify (difference_type n) const - { - if (v_->_tracking ()) - v_->_impl ().modify ( - static_cast (i_ - v_->base ().begin () + n)); - return i_[n]; - } - - vector_iterator& operator++ () {++i_; return *this;} - vector_iterator operator++ (int) {return vector_iterator (v_, i_++);} - vector_iterator& operator-- () {--i_; return *this;} - vector_iterator operator-- (int) {return vector_iterator (v_, i_--);} - - vector_iterator operator+ (difference_type n) const - {return vector_iterator (v_, i_ + n);} - vector_iterator& operator+= (difference_type n) {i_ += n; return *this;} - vector_iterator operator- (difference_type n) const - {return vector_iterator (v_, i_ - n);} - vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;} - - // Implementation details. - // - public: - base_iterator_type _base () const {return i_;} // Same as base (). - - private: - vector_type* v_; - base_iterator_type i_; - }; - -#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC - template - class vector_iterator > - { - public: - typedef V vector_type; - typedef std::reverse_iterator base_iterator_type; - typedef typename vector_type::const_reverse_iterator const_iterator_type; - typedef std::iterator_traits base_iterator_traits; - - typedef typename vector_type::iterator iterator_type; - typedef typename base_iterator_traits::value_type value_type; - typedef typename base_iterator_traits::difference_type difference_type; - typedef typename base_iterator_traits::pointer pointer; - typedef typename base_iterator_traits::reference reference; - typedef typename base_iterator_traits::iterator_category iterator_category; - - typedef typename vector_type::size_type size_type; - typedef typename vector_type::const_reference const_reference; - typedef typename vector_type::const_pointer const_pointer; - - vector_iterator (): v_ (0), i_ () {} - explicit vector_iterator (const iterator_type& i) - : v_ (i.vector ()), i_ (i.base ()) {} - vector_iterator (vector_type* v, const base_iterator_type& i) - : v_ (v), i_ (i) {} - operator const_iterator_type () const {return i_;} - iterator_type base () const {return iterator_type (v_, i_.base ());} - base_iterator_type rbase () const {return i_;} - vector_type* vector () const {return v_;} - - // Note: const_{reference,pointer}. - // - const_reference operator* () const {return *i_;} - const_pointer operator-> () const {return i_.operator -> ();} - const_reference operator[] (difference_type n) const {return i_[n];} - - // Modifiers. - // - reference modify () const - { - if (v_->_tracking ()) - v_->_impl ().modify ( - static_cast (v_->base ().rend () - i_ - 1)); - return *i_; - } - - reference modify (difference_type n) const - { - if (v_->_tracking ()) - // Note: going in the opposite direction. - v_->_impl ().modify ( - static_cast (v_->base ().rend () - i_ - 1 - n)); - return i_[n]; - } - - vector_iterator& operator++ () {++i_; return *this;} - vector_iterator operator++ (int) {return vector_iterator (v_, i_++);} - vector_iterator& operator-- () {--i_; return *this;} - vector_iterator operator-- (int) {return vector_iterator (v_, i_--);} - - vector_iterator operator+ (difference_type n) const - {return vector_iterator (v_, i_ + n);} - vector_iterator& operator+= (difference_type n) {i_ += n; return *this;} - vector_iterator operator- (difference_type n) const - {return vector_iterator (v_, i_ - n);} - vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;} - - // Implementation details. - // - public: - base_iterator_type _base () const {return i_;} // Same as rbase(). - - private: - vector_type* v_; - base_iterator_type i_; - }; -#endif // _RWSTD_NO_CLASS_PARTIAL_SPEC - - // operator== - // - template - inline bool - operator== (const vector_iterator& x, const vector_iterator& y) - {return x._base () == y._base ();} - - template - inline bool - operator== (const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () == y;} - - template - inline bool - operator== (const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x == y._base ();} - - // operator< - // - template - inline bool - operator< (const vector_iterator& x, const vector_iterator& y) - {return x._base () < y._base ();} - - template - inline bool - operator< (const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () < y;} - - template - inline bool - operator< (const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x < y._base ();} - - // operator!= - // - template - inline bool - operator!= (const vector_iterator& x, const vector_iterator& y) - {return x._base () != y._base ();} - - template - inline bool - operator!= (const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () != y;} - - template - inline bool - operator!= (const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x != y._base ();} - - // operator> - // - template - inline bool - operator> (const vector_iterator& x, const vector_iterator& y) - {return x._base () > y._base ();} - - template - inline bool - operator> (const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () > y;} - - template - inline bool - operator> (const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x > y._base ();} - - // operator>= - // - template - inline bool - operator>= (const vector_iterator& x, const vector_iterator& y) - {return x._base () >= y._base ();} - - template - inline bool - operator>= (const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () >= y;} - - template - inline bool - operator>= (const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x >= y._base ();} - - // operator<= - // - template - inline bool - operator<= (const vector_iterator& x, const vector_iterator& y) - {return x._base () <= y._base ();} - - template - inline bool - operator<= (const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () <= y;} - - template - inline bool - operator<= (const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x <= y._base ();} - - // operator- - // - template - inline typename vector_iterator::difference_type - operator-(const vector_iterator& x, const vector_iterator& y) - {return x._base () - y._base ();} - - template - inline typename vector_iterator::difference_type - operator-(const vector_iterator& x, - const typename vector_iterator::const_iterator_type& y) - {return x._base () - y;} - - template - inline typename vector_iterator::difference_type - operator-(const typename vector_iterator::const_iterator_type& x, - const vector_iterator& y) - {return x - y._base ();} - - // operator+ - // - template - inline vector_iterator - operator+(typename vector_iterator::difference_type n, - const vector_iterator& x) - {return vector_iterator (x.vector (), n + x._base ());} -} - -namespace std -{ - template - inline void swap(odb::vector& x, - odb::vector& y) {x.swap (y);} -} - -#include - -#include - -#include - -#endif // ODB_VECTOR_HXX diff --git a/odb/vector.ixx b/odb/vector.ixx deleted file mode 100644 index 230b187..0000000 --- a/odb/vector.ixx +++ /dev/null @@ -1,359 +0,0 @@ -// file : odb/vector.ixx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // construct/copy/destroy: - // - template - inline vector& - vector:: - operator= (const vector& x) - { - v_ = x.v_; - if (_tracking ()) - impl_.assign (v_.size ()); - return *this; - } - - template - template - inline void vector:: - assign (I f, I l) - { - v_.assign (f, l); - if (_tracking ()) - impl_.assign (v_.size ()); - } - - template - inline void vector:: - assign (size_type n, const T& u) - { - v_.assign (n, u); - if (_tracking ()) - impl_.assign (n); - } - -#ifdef ODB_CXX11 - template - inline vector& - vector:: - operator=(vector&& x) - { - v_ = std::move (x.v_); - if (_tracking ()) - impl_.assign (v_.size ()); - return *this; - } - -#ifdef ODB_CXX11_INITIALIZER_LIST - template - inline vector& - vector:: - operator= (std::initializer_list il) - { - v_ = il; - if (_tracking ()) - impl_.assign (v_.size ()); - return *this; - } - - template - inline void vector:: - assign (std::initializer_list il) - { - v_.assign (il); - if (_tracking ()) - impl_.assign (v_.size ()); - } -#endif -#endif - - // iterators: - // - template - inline typename vector::base_iterator_type - vector:: - mbegin () - { - if (_tracking ()) - impl_.modify (0, v_.size ()); - return v_.begin (); - } - - template - inline - typename vector::base_reverse_iterator_type - vector:: - mrbegin () - { - if (_tracking ()) - impl_.modify (0, v_.size ()); - return v_.rbegin (); - } - - // capacity: - // - template - inline void vector:: - resize (size_type n) - { - v_.resize (n); - if (_tracking ()) - impl_.resize (n); - } - - template - inline void vector:: - resize (size_type n, const T& c) - { - v_.resize (n, c); - if (_tracking ()) - impl_.resize (n); - } - - template - inline void vector:: - reserve (size_type n) - { - v_.reserve (n); - if (_tracking ()) - impl_.reserve (n); - } - -#ifdef ODB_CXX11 - template - inline void vector:: - shrink_to_fit () - { - v_.shrink_to_fit (); - impl_.shrink_to_fit (); - } -#endif - - // element access: - // - template - inline typename vector::reference - vector:: - modify (size_type n) - { - reference r (v_[n]); - if (_tracking ()) - impl_.modify (n); - return r; - } - - template - inline typename vector::reference - vector:: - modify_at (size_type n) - { - reference r (v_.at (n)); - if (_tracking ()) - impl_.modify (n); - return r; - } - - template - inline typename vector::reference - vector:: - modify_front () - { - reference r (v_.front ()); - if (_tracking ()) - impl_.modify (0); - return r; - } - - template - inline typename vector::reference - vector:: - modify_back () - { - reference r (v_.back ()); - if (_tracking ()) - impl_.modify (v_.size () - 1); - return r; - } - -#ifdef ODB_CXX11 - template - inline T* vector:: - modify_data() /*noexcept*/ - { - if (_tracking ()) - impl_.modify (0, v_.size ()); - return v_.data (); - } -#endif - - // modifiers: - // - template - inline void vector:: - push_back (const T& x) - { - v_.push_back (x); - if (_tracking ()) - impl_.push_back (); - } - - template - inline void vector:: - pop_back () - { - v_.pop_back (); - if (_tracking ()) - impl_.pop_back (); - } - - template - inline typename vector::iterator - vector:: - insert (iterator p, const T& x) - { - if (_tracking ()) - impl_.insert (static_cast (p.base () - v_.begin ())); - return iterator (this, v_.insert (p.base (), x)); - } - - template - inline void vector:: - insert (iterator p, size_type n, const T& x) - { - if (_tracking ()) - impl_.insert (static_cast (p.base () - v_.begin ()), n); - v_.insert (p.base (), n, x); - } - - template - template - inline void vector:: - insert (iterator p, I f, I l) - { - size_type i, n; - if (_tracking ()) - { - i = static_cast (p.base () - v_.begin ()); - n = v_.size (); - } - - v_.insert (p.base (), f, l); - - if (_tracking ()) - impl_.insert (i, v_.size () - n); - } - - template - inline typename vector::iterator - vector:: - erase (iterator p) - { - if (_tracking ()) - impl_.erase (static_cast (p.base () - v_.begin ())); - return iterator (this, v_.erase (p.base ())); - } - - template - inline typename vector::iterator - vector:: - erase (iterator f, iterator l) - { - if (_tracking ()) - impl_.erase (static_cast (f.base () - v_.begin ()), - static_cast (l - f)); - return iterator (this, v_.erase (f.base (), l.base ())); - } - - template - inline void vector:: - swap (vector& x) - { - v_.swap (x.v_); - vector_base::swap (x); - } - - template - inline void vector:: - clear () - { - v_.clear (); - if (_tracking ()) - impl_.clear (); - } - -#ifdef ODB_CXX11 - template - inline void vector:: - push_back(T&& x) - { - v_.push_back (std::move (x)); - if (_tracking ()) - impl_.push_back (); - } - - template - inline typename vector::iterator - vector:: - insert (iterator p, T&& x) - { - base_iterator_type r (v_.insert (p.base (), std::move (x))); - if (_tracking ()) - impl_.insert (static_cast (r - v_.begin ())); - return iterator (this, r); - } - -#ifdef ODB_CXX11_VARIADIC_TEMPLATE - template - template - inline void vector:: - emplace_back (Args&&... args) - { - v_.push_back (std::forward (args)...); - if (_tracking ()) - impl_.push_back (); - } - - template - template - inline typename vector::iterator - vector:: - emplace (iterator p, Args&&... args) - { - base_iterator_type r ( - v_.emplace (p.base (), std::forward (args)...)); - if (_tracking ()) - impl_.insert (static_cast (r - v_.begin ())); - return iterator (this, r); - } -#endif -#endif - - // Interfacing with base vector. - // - template - inline vector& - vector:: - operator= (const base_vector_type& x) - { - v_ = x; - if (_tracking ()) - impl_.assign (v_.size ()); - return *this; - } - -#ifdef ODB_CXX11 - template - inline vector& - vector:: - operator= (base_vector_type&& x) - { - v_ = std::move (x); - if (_tracking ()) - impl_.assign (v_.size ()); - return *this; - } -#endif -} diff --git a/odb/version-build2-stub.hxx b/odb/version-build2-stub.hxx deleted file mode 100644 index f4c7937..0000000 --- a/odb/version-build2-stub.hxx +++ /dev/null @@ -1,4 +0,0 @@ -// file : odb/version-build2-stub.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#include diff --git a/odb/version-build2.hxx b/odb/version-build2.hxx deleted file mode 100644 index e69de29..0000000 diff --git a/odb/version-build2.hxx.in b/odb/version-build2.hxx.in deleted file mode 100644 index 3672585..0000000 --- a/odb/version-build2.hxx.in +++ /dev/null @@ -1,42 +0,0 @@ -// file : odb/version-build2.hxx.in -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef LIBODB_VERSION // Note: using the version macro itself. - -// For the ODB compiler (temporary). -// -#define ODB_VERSION 20476 - -// The numeric version format is AAAAABBBBBCCCCCDDDE where: -// -// AAAAA - major version number -// BBBBB - minor version number -// CCCCC - bugfix version number -// DDD - alpha / beta (DDD + 500) version number -// E - final (0) / snapshot (1) -// -// When DDDE is not 0, 1 is subtracted from AAAAABBBBBCCCCC. For example: -// -// Version AAAAABBBBBCCCCCDDDE -// -// 0.1.0 0000000001000000000 -// 0.1.2 0000000001000020000 -// 1.2.3 0000100002000030000 -// 2.2.0-a.1 0000200001999990010 -// 3.0.0-b.2 0000299999999995020 -// 2.2.0-a.1.z 0000200001999990011 -// -#define LIBODB_VERSION $libodb.version.project_number$ULL -#define LIBODB_VERSION_STR "$libodb.version.project$" -#define LIBODB_VERSION_ID "$libodb.version.project_id$" - -#define LIBODB_VERSION_MAJOR $libodb.version.major$ -#define LIBODB_VERSION_MINOR $libodb.version.minor$ -#define LIBODB_VERSION_PATCH $libodb.version.patch$ - -#define LIBODB_PRE_RELEASE $libodb.version.pre_release$ - -#define LIBODB_SNAPSHOT $libodb.version.snapshot_sn$ULL -#define LIBODB_SNAPSHOT_ID "$libodb.version.snapshot_id$" - -#endif // LIBODB_VERSION diff --git a/odb/version.hxx b/odb/version.hxx deleted file mode 100644 index 4961e1a..0000000 --- a/odb/version.hxx +++ /dev/null @@ -1,43 +0,0 @@ -// file : odb/version.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifdef LIBODB_BUILD2 -# include -#else - -#ifndef ODB_VERSION_HXX -#define ODB_VERSION_HXX - -#include - -// Version format is AABBCCDD where -// -// AA - major version number -// BB - minor version number -// CC - bugfix version number -// DD - alpha / beta (DD + 50) version number -// -// When DD is not 00, 1 is subtracted from AABBCC. For example: -// -// Version AABBCCDD -// 2.0.0 02000000 -// 2.1.0 02010000 -// 2.1.1 02010100 -// 2.2.0.a1 02019901 -// 3.0.0.b2 02999952 -// - -// ODB interface version: minor, major, and alpha/beta versions. -// -#define ODB_VERSION 20476 -#define ODB_VERSION_STR "2.5-b.26" - -// libodb version: interface version plus the bugfix version. -// -#define LIBODB_VERSION 2049976 -#define LIBODB_VERSION_STR "2.5.0-b.26" - -#include - -#endif // ODB_VERSION_HXX -#endif // LIBODB_BUILD2 diff --git a/odb/view-image.hxx b/odb/view-image.hxx deleted file mode 100644 index 51f7cc0..0000000 --- a/odb/view-image.hxx +++ /dev/null @@ -1,36 +0,0 @@ -// file : odb/view-image.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_VIEW_IMAGE_HXX -#define ODB_VIEW_IMAGE_HXX - -#include - -#include -#include - -namespace odb -{ - // Helper to create a complete image chain for a polymorphic - // object hierarchy. - // - template - struct view_object_image: object_traits_impl::image_type - { - view_object_image () {this->base = &base_;} - - private: - // Data member names in the generated image_type never end with - // an underscore, so this name shouldn't clash. - // - view_object_image::base_type, R, DB> - base_; - }; - - template - struct view_object_image: object_traits_impl::image_type {}; -} - -#include - -#endif // ODB_VIEW_IMAGE_HXX diff --git a/odb/view-result.hxx b/odb/view-result.hxx deleted file mode 100644 index 601c3b4..0000000 --- a/odb/view-result.hxx +++ /dev/null @@ -1,231 +0,0 @@ -// file : odb/view-result.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_VIEW_RESULT_HXX -#define ODB_VIEW_RESULT_HXX - -#include - -#include // std::ptrdiff_t, std::size_t -#include // iterator categories -#include // std::move - -#include -#include -#include -#include - -#include // ODB_CXX11 - -namespace odb -{ - template - class view_result_impl: public result_impl - { - protected: - friend class result; - friend class result; - friend class result_iterator; - friend class result_iterator; - - // In result_impl, T is always non-const and the same as view_type. - // - typedef T view_type; - typedef odb::view_traits view_traits; - - typedef typename view_traits::pointer_type pointer_type; - typedef odb::pointer_traits pointer_traits; - - view_result_impl (odb::connection& conn) - : result_impl (conn), begin_ (true), end_ (false), current_ () - { - } - - // To make this work with all kinds of pointers (raw, std::auto_ptr, - // shared), we need to make sure we don't make any copies of the - // pointer on the return path. - // - pointer_type& - current (); - - void - release () - { - current_ = pointer_type (); - guard_.release (); - } - - void - begin () - { - if (begin_) - { - next (); - begin_ = false; - } - } - - bool - end () const - { - return end_; - } - - protected: - virtual void - load (view_type&) = 0; - - virtual void - next () = 0; - - virtual void - cache () = 0; - - virtual std::size_t - size () = 0; - - protected: -#ifdef ODB_CXX11 - void - current (pointer_type& p) - { - current_ = std::move (p); - guard_.reset (current_); - } - - void - current (pointer_type&& p) - { - current (p); - } -#else - void - current (pointer_type p) - { - current_ = p; - guard_.reset (current_); - } -#endif - - bool begin_; - bool end_; - - private: - pointer_type current_; - typename pointer_traits::guard guard_; - }; - - template - class result_iterator - { - public: - typedef T value_type; - typedef value_type& reference; - typedef value_type* pointer; - typedef std::ptrdiff_t difference_type; - typedef std::input_iterator_tag iterator_category; - - // T can be const T while view_type is always non-const. - // - typedef typename view_traits::view_type view_type; - - typedef view_result_impl result_impl_type; - - public: - explicit - result_iterator (result_impl_type* res = 0) - : res_ (res) - { - } - - // Input iterator requirements. - // - public: - reference - operator* () const - { - return pointer_traits::get_ref (res_->current ()); - } - - // Our value_type is already a pointer so return it instead of - // a pointer to it (operator-> will just have to go one deeper - // in the latter case). - // - pointer - operator-> () const - { - return pointer_traits::get_ptr (res_->current ()); - } - - result_iterator& - operator++ () - { - res_->next (); - return *this; - } - - result_iterator - operator++ (int) - { - // All non-end iterators for a result object move together. - // - res_->next (); - return *this; - } - - public: - typedef typename view_traits::pointer_type pointer_type; - - pointer_type - load () - { -#ifdef ODB_CXX11 - pointer_type r (std::move (res_->current ())); -#else - pointer_type r (res_->current ()); -#endif - res_->release (); - return r; - } - - void - load (view_type&); - - public: - bool - equal (result_iterator j) const - { - return (res_ ? res_->end () : true) == (j.res_ ? j.res_->end () : true); - } - - private: - // Use unrestricted pointer traits since that's what is returned by - // result_impl. - // - typedef - odb::pointer_traits::pointer_type> - pointer_traits; - - result_impl_type* res_; - }; - - // - // - template - class result_base - { - public: - typedef typename view_traits::pointer_type value_type; - - // T can be const T while view_type is always non-const. - // - typedef typename view_traits::view_type view_type; - typedef view_result_impl result_impl_type; - }; -} - -#include - -#include - -#endif // ODB_VIEW_RESULT_HXX diff --git a/odb/view-result.txx b/odb/view-result.txx deleted file mode 100644 index 5c62253..0000000 --- a/odb/view-result.txx +++ /dev/null @@ -1,39 +0,0 @@ -// file : odb/view-result.txx -// license : GNU GPL v2; see accompanying LICENSE file - -namespace odb -{ - // - // view_result_impl - // - - template - typename view_result_impl::pointer_type& - view_result_impl:: - current () - { - if (pointer_traits::null_ptr (current_) && !end_) - { - pointer_type p (view_traits::create ()); - view_type& view (pointer_traits::get_ref (p)); - current (p); - load (view); - } - - return current_; - } - - // - // result_iterator - // - - template - void result_iterator:: - load (view_type& view) - { - if (res_->end ()) - return; - - res_->load (view); - } -} diff --git a/odb/wrapper-traits.hxx b/odb/wrapper-traits.hxx deleted file mode 100644 index d31425d..0000000 --- a/odb/wrapper-traits.hxx +++ /dev/null @@ -1,276 +0,0 @@ -// file : odb/wrapper-traits.hxx -// license : GNU GPL v2; see accompanying LICENSE file - -#ifndef ODB_WRAPPER_TRAITS_HXX -#define ODB_WRAPPER_TRAITS_HXX - -#include - -#include // std::auto_ptr, std::unique_ptr, std::shared_ptr/weak_ptr - -#include - -#include // ODB_CXX11 -#include - -namespace odb -{ - template - class wrapper_traits; - - // Sample specialization for raw pointers. It is not enabled by default - // since it makes many assumptions that may not always hold true (such - // as that instances are allocated with new and freed with delete). - // This makes it too dangerous to be enabled unconditionally. If you - // need this functionality, you can copy the below code into your - // application. Also consider changing it to only specialize for - // specific types instead of for any pointer (it will almost always - // do the wrong thing for char*). - // -#if 0 - template - class wrapper_traits - { - public: - typedef T wrapped_type; - typedef T* wrapper_type; - - // T can be const. - // - typedef - typename details::meta::remove_const::result - unrestricted_wrapped_type; - - static const bool null_handler = true; - static const bool null_default = false; - - static bool - get_null (const wrapper_type& p) - { - return p == 0; - } - - static void - set_null (wrapper_type& p) - { - delete p; - p = 0; - } - - static const wrapped_type& - get_ref (const wrapper_type& p) - { - return *p; - } - - static unrestricted_wrapped_type& - set_ref (wrapper_type& p) - { - if (p == 0) - p = new unrestricted_wrapped_type; - - return const_cast (*p); - } - }; -#endif - - // Specialization for std::auto_ptr. - // -#ifndef ODB_CXX11 - template - class wrapper_traits< std::auto_ptr > - { - public: - // T can be const. - // - typedef T wrapped_type; - typedef std::auto_ptr wrapper_type; - - // T can be const. - // - typedef - typename odb::details::meta::remove_const::result - unrestricted_wrapped_type; - - static const bool null_handler = true; - static const bool null_default = false; - - static bool - get_null (const wrapper_type& p) - { - return p.get () == 0; - } - - static void - set_null (wrapper_type& p) - { - p.reset (); - } - - static const wrapped_type& - get_ref (const wrapper_type& p) - { - return *p; - } - - static unrestricted_wrapped_type& - set_ref (wrapper_type& p) - { - if (p.get () == 0) - p.reset (new unrestricted_wrapped_type ()); - - return const_cast (*p); - } - }; -#endif - -#ifdef ODB_CXX11 - - // Specialization for C++11 std::unique_ptr. - // - template - class wrapper_traits> - { - public: - // T can be const. - // - typedef T wrapped_type; - typedef std::unique_ptr wrapper_type; - - // T can be const. - // - typedef - typename odb::details::meta::remove_const::result - unrestricted_wrapped_type; - - static const bool null_handler = true; - static const bool null_default = false; - - static bool - get_null (const wrapper_type& p) - { - return !p; - } - - static void - set_null (wrapper_type& p) - { - p.reset (); - } - - static const wrapped_type& - get_ref (const wrapper_type& p) - { - return *p; - } - - static unrestricted_wrapped_type& - set_ref (wrapper_type& p) - { - if (!p) - p.reset (new unrestricted_wrapped_type ()); - - return const_cast (*p); - } - }; - - // Specialization for C++11 std::shared_ptr. - // - template - class wrapper_traits> - { - public: - typedef T wrapped_type; - typedef std::shared_ptr wrapper_type; - - // T can be const. - // - typedef - typename odb::details::meta::remove_const::result - unrestricted_wrapped_type; - - static const bool null_handler = true; - static const bool null_default = false; - - static bool - get_null (const wrapper_type& p) - { - return !p; - } - - static void - set_null (wrapper_type& p) - { - p.reset (); - } - - static const wrapped_type& - get_ref (const wrapper_type& p) - { - return *p; - } - - static unrestricted_wrapped_type& - set_ref (wrapper_type& p) - { - if (!p) - p.reset (new unrestricted_wrapped_type); - - return const_cast (*p); - } - }; - -#endif // ODB_CXX11 - - // Specialization for odb::nullable. - // - template - class wrapper_traits< nullable > - { - public: - // T can be const. - // - typedef T wrapped_type; - typedef nullable wrapper_type; - - // T can be const. - // - typedef - typename odb::details::meta::remove_const::result - unrestricted_wrapped_type; - - static const bool null_handler = true; - static const bool null_default = true; - - static bool - get_null (const wrapper_type& n) - { - return n.null (); - } - - static void - set_null (wrapper_type& n) - { - n.reset (); - } - - static const wrapped_type& - get_ref (const wrapper_type& n) - { - return *n; - } - - static unrestricted_wrapped_type& - set_ref (wrapper_type& n) - { - if (n.null ()) - n = unrestricted_wrapped_type (); - - return const_cast (*n); - } - }; -} - -#include - -#endif // ODB_WRAPPER_TRAITS_HXX diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index e54525b..0000000 --- a/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -driver diff --git a/tests/basics/buildfile b/tests/basics/buildfile deleted file mode 100644 index d568216..0000000 --- a/tests/basics/buildfile +++ /dev/null @@ -1,6 +0,0 @@ -# file : tests/basics/buildfile -# license : GNU GPL v2; see accompanying LICENSE file - -import libs = libodb%lib{odb} - -exe{driver}: {hxx cxx}{*} $libs diff --git a/tests/basics/driver.cxx b/tests/basics/driver.cxx deleted file mode 100644 index 57cec1c..0000000 --- a/tests/basics/driver.cxx +++ /dev/null @@ -1,29 +0,0 @@ -// file : tests/basics/driver.cxx -// license : GNU GPL v2; see accompanying LICENSE file - -// Basic test to make sure the library is usable. Functionality testing -// is done in the odb-tests package. - -#include - -#include -#include - -using namespace odb; - -int -main () -{ - // Transaction. - // - { - assert (!transaction::has_current ()); - - try - { - transaction::current (); - assert(false); - } - catch (const not_in_transaction&) {} - } -} diff --git a/tests/build/.gitignore b/tests/build/.gitignore deleted file mode 100644 index 4a730a3..0000000 --- a/tests/build/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -config.build -root/ -bootstrap/ diff --git a/tests/build/bootstrap.build b/tests/build/bootstrap.build deleted file mode 100644 index 6ee38db..0000000 --- a/tests/build/bootstrap.build +++ /dev/null @@ -1,8 +0,0 @@ -# file : tests/build/bootstrap.build -# license : GNU GPL v2; see accompanying LICENSE file - -project = # Unnamed subproject. - -using config -using dist -using test diff --git a/tests/build/root.build b/tests/build/root.build deleted file mode 100644 index 6c5a90b..0000000 --- a/tests/build/root.build +++ /dev/null @@ -1,23 +0,0 @@ -# file : tests/build/root.build -# license : GNU GPL v2; see accompanying LICENSE file - -cxx.std = latest - -using cxx - -hxx{*}: extension = hxx -cxx{*}: extension = cxx - -if ($cxx.target.system == 'win32-msvc') - cxx.poptions += -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS - -if ($cxx.class == 'msvc') - cxx.coptions += /wd4251 /wd4275 /wd4800 - -# Every exe{} in this subproject is by default a test. -# -exe{*}: test = true - -# Specify the test target for cross-testing. -# -test.target = $cxx.target diff --git a/tests/buildfile b/tests/buildfile deleted file mode 100644 index 57588a4..0000000 --- a/tests/buildfile +++ /dev/null @@ -1,4 +0,0 @@ -# file : tests/buildfile -# license : GNU GPL v2; see accompanying LICENSE file - -./: {*/ -build/} diff --git a/version.txt b/version.txt deleted file mode 100644 index 6bc2f39..0000000 --- a/version.txt +++ /dev/null @@ -1 +0,0 @@ -2.5.0-b.26 -- cgit v1.1