/* * OCILIB - C Driver for Oracle (C Wrapper for Oracle OCI) * * Website: http://www.ocilib.net * * Copyright (c) 2007-2023 Vincent ROGIER * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include "ocilibcpp/config.hpp" // ReSharper disable CppClangTidyCppcoreguidelinesMacroUsage // ReSharper disable CppClangTidyHicppSpecialMemberFunctions // ReSharper disable CppClangTidyCppcoreguidelinesSpecialMemberFunctions // ReSharper disable CppClangTidyModernizeUseNodiscard // ReSharper disable CppClangTidyHicppUseEqualsDefault // ReSharper disable CppClangTidyModernizeUseEqualsDefault namespace ocilib { /** * @namespace ocilib::core * @brief OCILIB internal core classes * */ namespace core { #ifdef OCILIBPP_HAS_ENABLEIF template using EnableIf = std::enable_if; template using IsSame = std::is_same; #else template struct EnableIf {}; template struct EnableIf { typedef T type; }; template struct BoolConstant { static const bool value = B; }; template struct IsSame : BoolConstant {}; template struct IsSame : BoolConstant {}; #endif #define ARG_NOT_USED(a) (a) = (a) /** * @brief Internal usage. * Checks if the last OCILIB function call has raised an error. * If so, it raises a C++ exception using the retrieved error handle */ template static T Check(T result); /** * @brief Internal usage. * Constructs a C++ string object from the given OCILIB string pointer */ ostring MakeString(const otext* result, int size = -1); /** * @brief Internal usage. * Constructs a C++ Raw object from the given OCILIB raw buffer */ Raw MakeRaw(AnyPointer result, unsigned int size); /** * @brief Internal usage. * Determine if the given type is a supported numeric type */ template struct SupportedNumeric { typedef EnableIf::value || IsSame::value || IsSame::value || IsSame::value || IsSame::value || IsSame::value || IsSame::value || IsSame::value || IsSame::value> Type; }; /** * @brief * Template Enumeration template class providing some type safety to some extends for manipulating enumerated variables */ template class Enum { public: typedef T Type; Enum(); Enum(T value); T GetValue(); operator T (); operator unsigned int() const; bool operator == (const Enum& other) const; bool operator != (const Enum& other) const; bool operator == (const T& other) const; bool operator != (const T& other) const; private: T _value; }; /** * @brief * Template Flags template class providing some type safety to some extends for manipulating flags set variables */ template class Flags { public: typedef T Type; Flags(); Flags(T flag); Flags(const Flags& other); Flags& operator = (const Flags& other) noexcept; Flags operator~ () const; Flags operator | (T other) const; Flags operator & (T other) const; Flags operator ^ (T other) const; Flags operator | (const Flags& other) const; Flags operator & (const Flags& other) const; Flags operator ^ (const Flags& other) const; Flags& operator |= (T other); Flags& operator &= (T other); Flags& operator ^= (T other); Flags& operator |= (const Flags& other); Flags& operator &= (const Flags& other); Flags& operator ^= (const Flags& other); bool operator == (T other) const; bool operator == (const Flags& other) const; unsigned int GetValues() const; bool IsSet(T other) const; private: Flags(unsigned int flags); unsigned int _flags; }; /** * @brief Internal usage. * Provide a buffer class with RAII capabilities */ template< typename T> class ManagedBuffer { public: ManagedBuffer(); ManagedBuffer(size_t size); ~ManagedBuffer() noexcept; operator T* (); private: T* _buffer; size_t _size; }; /** * @brief Internal usage. * Synchronization mode enumeration */ enum SynchronizationMode { Unsafe, Safe }; /** * @brief Internal usage. * SynchronizationGuard object */ class SynchronizationGuard { public: SynchronizationGuard(SynchronizationMode mode); virtual ~SynchronizationGuard() noexcept; void Acquire() const; void Release() const; void SetMode(SynchronizationMode mode); private: MutexHandle _mutex; }; /** * @brief Internal usage. * Base class for types that can be locked */ class Synchronizable { public: Synchronizable(); virtual ~Synchronizable() noexcept; void SetGuard(SynchronizationGuard* guard); void Acquire() const; void Release() const; private: SynchronizationGuard* _guard; }; /** * @brief Internal usage. * Map supporting concurrent access from multiple threads */ template class ConcurrentMap : public Synchronizable { public: ConcurrentMap(); virtual ~ConcurrentMap() noexcept; void Remove(K key); V Get(K key); void Set(K key, V value); void Clear(); size_t GetSize(); private: std::map _map; }; /** * @brief Internal usage. * List supporting concurrent access from multiple threads */ template class ConcurrentList : public Synchronizable { public: ConcurrentList(); virtual ~ConcurrentList() noexcept; void Add(T value); void Remove(T value); void Clear(); size_t GetSize(); bool Exists(const T& value); template bool FindIf(P predicate, T& value); template void ForEach(A action); private: std::list _list; }; /* Forward declaration */ class HandleStore; /** * @brief Internal usage. * Interface for handling ownership and relationship of a C API handle */ class Handle { public: virtual ~Handle() noexcept {} virtual ConcurrentList& GetChildren() = 0; virtual void DetachFromHolders() = 0; virtual void DetachFromParent() = 0; virtual HandleStore* GetStore() = 0; }; /** * @brief Internal usage. * Provide a store for C Handles to C++ Handles mapping */ class HandleStore { public: HandleStore(SynchronizationGuard * guard); template T Get(AnyPointer ptr); template void Set(AnyPointer ptr, T handle); static HandleStore& GetStoreForHandle(Handle*); template static HandleStore& CreateStore(); private: static HandleStore& GetDefaultStore(); ConcurrentMap _handles; }; /** * @brief Internal usage. * Smart pointer class with reference counting for managing OCILIB object handles */ template class HandleHolder { public: bool IsNull() const; operator bool(); operator bool() const; operator T(); operator T() const; protected: class SmartHandle; HandleHolder(const HandleHolder& other); HandleHolder(); ~HandleHolder() noexcept; HandleHolder& operator= (const HandleHolder& other) noexcept; typedef void(*SmartHandleFreeNotifyFunc)(SmartHandle* smartHandle); Handle* GetHandle() const; void AcquireAllocated(T handle, Handle* parent); void AcquireTransient(T handle, Handle* parent); void AcquireAllocatedWithNotification(T handle, Handle* parent, SmartHandleFreeNotifyFunc freeNotifyFunc); void Acquire(HandleHolder& other); void Acquire(T handle, bool allocated, SmartHandleFreeNotifyFunc freeNotifyFunc, Handle* parent); void Release(); class SmartHandle : public Handle { public: SmartHandle(HandleHolder* holder, T handle, bool allocated, SmartHandleFreeNotifyFunc freeNotifyFunc, Handle* parent); virtual ~SmartHandle() noexcept; void Acquire(HandleHolder* holder); void Release(HandleHolder* holder); void Destroy(); T GetHandle() const; Handle* GetParent() const; AnyPointer GetExtraInfos() const; void SetExtraInfos(AnyPointer extraInfo); ConcurrentList& GetChildren() override; void DetachFromHolders() override; void DetachFromParent() override; HandleStore* GetStore() override; private: static void DeleteHandle(Handle* handle); static void ResetHolder(HandleHolder* holder); static SynchronizationMode GetSynchronizationMode(); ConcurrentList _holders; ConcurrentList _children; SynchronizationGuard _guard; T _handle; bool _allocated; SmartHandleFreeNotifyFunc _freeNotifyFunc; Handle* _parent; AnyPointer _extraInfo; HandleStore* _store; }; SmartHandle* _smartHandle; }; /** * @brief * Abstract class allowing derived classes to be compatible * with any type supporting the operator << ocilib::ostring */ class Streamable { public: virtual ~Streamable() noexcept {} operator ostring() const { return ToString(); } virtual ostring ToString() const = 0; template friend T& operator << (T& lhs, const Streamable& rhs) { lhs << static_cast(rhs); return lhs; } }; } }