From 2ad98a025eb263d97b1942fc468937b4719becd8 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 19 Oct 2013 15:54:21 -0700 Subject: [PATCH] Squashed 'src/beast/' changes from 43e6d34..0e7bac9 0e7bac9 Fix include path e5bb90f Fix constness of Proxy ac0142a Use template cast ef6e381 Add missing Url.h include 206e65c Fix constness of operator[] 695cc38 Use template instantiation for friend declaration 7b1e03a Add BaseFromMember 49bc04f Make List<>::Node not uncopyable d5954ff Add Journal to UnitTest 58da106 Temporarily disable ServiceQueue dtor precondition asserts fe58c1a Add missing #include 2c02580 Add PropertyStream for server state introspection 24c2315 Add ScopedWrapperContext a3845f5 Add RelativeTime::value_type typedef 7442932 Fix missing PropertyStream members ed5a98f More PropertyStream output for PeerFinder fcfa10d Add PropertyStream 3cf0729 Tidy up AbstractHandler usage in HTTPClient 55171f4 Remove obsolete source files 1311ca3 Increase arity of SharedFunction 67d807d Add IPEndpoint::key_equal ebf395e Add ErrorCode and boost library 2c3ead3 Add ServiceQueue::wrap 6c7f5d0 Move many Thread related classes 93e9d86 Measure CPU utilization in ServiceQueue ca47d72 Move ServiceQueue, ThreadLocalValue, SpinLock c864e4d Move WaitableEvent ff305e6 Add CPUMeter and ScopedTimeInterval 01fd05c Add RecursiveMutex, UnlockGuard, TryLockGuard 5831a53 Remove Journal from most Stoppable overrides b60a7f3 Add Request and Response HTTP parsers 44445ff Refactor net buffers classes ac37c38 Beast class refactor 8b7056b Fix eof on HTTP client get 228b664 Remove obsolete beast container classes 1dfd655 Use RelativeTime from startup in DeadlineTimer ae22d5d Add more methods to RelativeTime c67929e Remove unhandled exception catcher 2472a90 Add 64 bit output for MurmurHash f3d97c7 Add RelativeTime::fromStartup b0b8660 IPEndpoint better parsing ae551cd Add alternate form string parsing to IPEndpoint d0a0dbf Don't break on Throw 0e46762 Add hasher functors for IPEndpoint a1ec423 Add Thread::stopThreadAsync 4f7dca3 Add compiler, stdlib, and platform skeleton to beast/config 4394594 Tidy up some use of Error for throw e5e0f52 Journal console output improvements f07515e Add Stoppable prepare and start interfaces d37dd46 Move RelativeTime to chrono, add ostream support 3f6e7aa Add console feature to Journal ad0064a Journal option to write to Output window (MSVC) 0b7574b Add compilation test script cc05ce1 Add ServiceQueue e132aab Use boost for functional when the config is set 026b926 Fix is_continuation for boost version c807a4e Fix invoked_type type reference 2ff781b Remove LockFreeStack::size 3acb474 Add SharedData::ConstAccess 7e4c834 Add LockFreeStack::empty 9c61a6d Added AbstractHandler, WrapHandler. HTTPClient Fixes. 94e40dc Fix unittest, by removing recursive call. 38bf408 Fix nonstandard C++ extension in getNullSink 1ef044d Build fixes d5d3746 Fix missing include for Gentoo 5f231d3 Update copyright notice and licenses 7b89bf6 Add FixedArray, IntrusiveArray, Crypto 5c5de57 Reorganize beast modules and files 9e18bb3 Merge commit '43deaaa5cf0d0178a4a6c3cb69c02a2a9a43ec7d' as 'src/beast/beast/http/impl/http-parser' 57703ac Fix BeforeBoost.h include fbc247b Add Stoppable to beast 56496d8 IPEndpoint comparisons 9d9c822 Migrate some headers and general tidying 1a3cddc Add SharedArg and AsyncObject 373ca9c Add HTTPRequest and improvements to HTTPMessage parsing 9534516 Add some thread classes and fix SharedData with a simple mutex adapter 755ab36 Make CallQueue unit test runManual c0ca037 Remove Beast version printing on startup 7efb6a3 Reorganize some MPL and Utility classes and files 69c26a1 Fix missing BeastConfig.h include in Net.cpp 40aa552 Disable Beast version printing in Ripple BeastConfig.h 7b1352d Add InterruptibleThread unit test 68cf759 ThreadWithCallQueue unit test adjustment 6501dea IPEndpoint parsing and tidying 72fc42b Move and add some template metaprogramming classes 2a164f0 Change filname capitalization (end) 6a14f25 Change filename capitalization 92fd417 Move integer types to beast/CStdInt.h ebbd9ff Move TargetPlatform.h to beast/Config.h 874b524 Add IPEndpoint 14b34fc Tidy up some zlib macro undefines 34fffca Rename beast sources for consistency 4e59ab2 Add CallQueue unit test 327d7a6 Fixes for consolidated beast unity includes d5ece4e Remove unused and broken classes 39f13be Remove unused ConcurrentObject 37624a7 Add ThreadWithCallQueue unit test e82ec68 Remove obsolete beast_Function 90551a6 Temporarily leave sqlite3 in whatever threading mode it was already in. 43ebbb1 Fix SharedSingleton to use memoryBarrier f343941 Tidy up SharedSingleton doc comments 001997e Fix leak on exit from Singleton dependency cycle 83b9d22 Rename to DeadlineTimer::cancel() 77874ee Use new instead of ::new for placement 2a04dcc Journal improvements 50965ca SharedFunction improvements 277e32b Add LockFreeStack iterators d94e4c2 Fix undefined behavior in UnsignedIntegerCalc (again) 2dc25ce Fix DeadlineTimer, callback while holding lock 207ffde Fix undefined behavior in UnsignedIntegerCalc 1ad8ff9 Fix UnsignedInteger::isZero 1dd2836 Add support for multiprecision integer arithmetic and binary data encoding a45fc47 Update .gitignore 962a95d Tidy up UnsignedInteger ca695fa Add Time::isNull() e96ce99 Better random number facilities in UnitTest 550b8e5 Fine tune UnsignedInteger declaration 8e7e3b7 Allow negative relative expirations in DeadlineTimer f3dc7ce Add generic Journal class for logging bfdda32 Make ChildProcess UnitTest manual since it malfunctions 02acf7d General refactoring of beast framework classes 84ef06e Fix ExitHook to derive from AtExitHook f0acc9c Reduce the max threads in the Workers unit test 55447b0 New SharedSingleton, resolves destruction of objects with static storage duration. 41eb8a1 Remove deprecated SharedPtr::getObject 9eda4bc Make SharedObject members const, the counter mutable 6eda777 Remove deprecated createOnDemandOnce SingletonLifetime option 8c522aa Fix off by one in pending i/o count on HTTPClient 057344e Add HTTPMessage::toString and family ee728e3 Add UniformResourceLocator::empty ae324fb Move ./modules to ./src git-subtree-dir: src/beast git-subtree-split: 0e7bac945fae0e88ec60c1057a78d8ff6c4d17ca --- .gitignore | 2 + Builds/VisualStudio2012/Beast.props | 14 +- Builds/VisualStudio2012/beast.vcxproj | 963 ++++++------ Builds/VisualStudio2012/beast.vcxproj.filters | 1368 ++++++++++------- LICENSE_1_0.txt | 23 + TODO.txt | 13 - .../Arithmetic.h | 101 +- .../memory/beast_Atomic.h => beast/Atomic.h | 24 +- beast/Boost.h | 31 + .../beast_ByteOrder.h => beast/ByteOrder.h | 114 +- beast/CStdInt.h | 88 ++ beast/Chrono.h | 27 + beast/Config.h | 60 + beast/Crypto.h | 26 + beast/FixedArray.h | 165 ++ beast/HTTP.h | 26 + .../beast_HeapBlock.h => beast/HeapBlock.h | 60 +- beast/Intrusive.h | 28 + beast/{mpl.h => MPL.h} | 2 + .../memory/beast_Memory.h => beast/Memory.h | 26 +- beast/Net.h | 28 + .../beast_SafeBool.h => beast/SafeBool.h | 42 +- beast/SmartPtr.h | 30 + .../StaticAssert.h | 42 +- beast/Strings.h | 27 + .../beast_FifoFreeStore.h => beast/Threads.h | 31 +- beast/TypeTraits.h | 28 + .../beast_Uncopyable.h => beast/Uncopyable.h | 11 +- beast/Utility.h | 33 + beast/Version.h | 40 + beast/boost/Boost.cpp | 22 + beast/boost/ErrorCode.h | 35 + beast/chrono/CPUMeter.h | 158 ++ beast/chrono/Chrono.cpp | 23 + .../chrono/RelativeTime.h | 101 +- .../chrono/ScopedTimeInterval.h | 47 +- beast/chrono/impl/CPUMeter.cpp | 21 + beast/chrono/impl/RelativeTime.cpp | 326 ++++ .../config/CompilerConfig.h | 56 +- .../config/ConfigCheck.h | 12 +- .../config}/ContractChecks.h | 14 +- .../config/PlatformConfig.h | 7 +- beast/config/SelectCompilerConfig.h | 44 + .../config/SelectPlatformConfig.h | 65 +- beast/config/SelectStdlibConfig.h | 21 + .../config/StandardConfig.h | 70 +- beast/config/Suffix.h | 25 + beast/config/compiler/Clang.h | 20 + beast/config/compiler/Gcc.h | 20 + beast/config/compiler/Intel.h | 20 + beast/config/compiler/VisualC.h | 20 + beast/config/platform/Android.h | 26 + beast/config/platform/Bsd.h | 20 + beast/config/platform/Linux.h | 21 + beast/config/platform/MacOS.h | 21 + beast/config/platform/Win32.h | 21 + beast/crypto/Crypto.cpp | 22 + beast/crypto/Sha256.h | 156 ++ beast/crypto/impl/Sha256.cpp | 144 ++ beast/crypto/impl/sha2/README | 277 ++++ beast/crypto/impl/sha2/sha2.c | 1067 +++++++++++++ beast/crypto/impl/sha2/sha2.h | 117 ++ beast/crypto/impl/sha2/sha2prog.c | 132 ++ beast/crypto/impl/sha2/sha2speed.c | 174 +++ beast/crypto/impl/sha2/sha2test.pl | 358 +++++ beast/http/HTTP.cpp | 24 + beast/http/ParsedURL.h | 51 + .../http/URL.h | 45 +- .../http/impl/ParsedURL.cpp | 137 +- beast/http/impl/README.md | 3 + beast/http/impl/URL.cpp | 158 ++ .../http/impl/http-parser}/.gitignore | 0 .../http/impl/http-parser}/.mailmap | 0 .../http/impl/http-parser}/.travis.yml | 0 .../http/impl/http-parser}/AUTHORS | 0 .../http/impl/http-parser}/CONTRIBUTIONS | 0 .../http/impl/http-parser}/LICENSE-MIT | 0 .../http/impl/http-parser}/Makefile | 0 .../http/impl/http-parser}/README.md | 0 .../impl/http-parser}/contrib/parsertrace.c | 0 .../impl/http-parser}/contrib/url_parser.c | 0 .../http/impl/http-parser}/http_parser.c | 0 .../http/impl/http-parser}/http_parser.gyp | 0 .../http/impl/http-parser}/http_parser.h | 0 .../http/impl/http-parser}/test.c | 0 beast/http/impl/http_parser.cpp | 36 + beast/intrusive/ForwardList.h | 7 +- beast/intrusive/IntrusiveArray.h | 187 +++ .../containers => beast/intrusive}/List.h | 201 +-- beast/intrusive/LockFreeStack.h | 285 ++++ beast/intrusive/PointerTraits.h | 2 + beast/mpl/AddConst.h | 6 +- .../copyconst.h => beast/mpl/CopyConst.h | 23 +- beast/mpl/IfCond.h | 6 +- beast/mpl/IsCallPossible.h | 270 ++++ beast/mpl/PointerToOther.h | 4 +- beast/mpl/RemoveConst.h | 6 +- beast/mpl/RemoveConstVolatile.h | 2 +- beast/mpl/RemoveReference.h | 6 +- beast/mpl/RemoveVolatile.h | 6 +- .../basics => beast/net}/BufferType.h | 14 +- beast/net/DynamicBuffer.h | 125 ++ beast/net/IPEndpoint.h | 378 +++++ beast/net/Net.cpp | 27 + beast/net/impl/DynamicBuffer.cpp | 91 ++ beast/net/impl/IPEndpoint.cpp | 717 +++++++++ .../smart_ptr/ContainerDeletePolicy.h | 8 +- .../smart_ptr/ScopedPointer.h | 45 +- .../memory => beast/smart_ptr}/SharedObject.h | 18 +- .../memory => beast/smart_ptr}/SharedPtr.h | 77 +- beast/smart_ptr/SmartPtr.cpp | 25 + .../strings/CharPointer_ASCII.h | 12 +- .../strings/CharPointer_UTF16.h | 12 +- .../strings/CharPointer_UTF32.h | 12 +- .../strings/CharPointer_UTF8.h | 12 + .../strings/CharacterFunctions.h | 22 +- .../strings/NewLine.h | 13 +- .../beast_String.h => beast/strings/String.h | 41 +- .../strings}/StringCharPointerType.h | 13 +- .../text => beast/strings}/StringFromNumber.h | 19 +- beast/strings/Strings.cpp | 23 + .../strings/impl/CharacterFunctions.cpp | 10 +- .../strings/impl/String.cpp | 45 +- beast/threads/LockGuard.h | 50 + beast/threads/RecursiveMutex.h | 84 + beast/threads/ScopedWrapperContext.h | 93 ++ beast/threads/ServiceQueue.h | 631 ++++++++ beast/threads/SharedData.h | 272 ++++ beast/threads/SharedLockGuard.h | 52 + .../threads/SharedMutexAdapter.h | 50 +- .../threads/SpinLock.h | 40 +- beast/threads/Stoppable.h | 327 ++++ .../beast_Thread.h => beast/threads/Thread.h | 22 +- .../threads/ThreadLocalValue.h | 13 +- beast/threads/Threads.cpp | 27 + beast/threads/TryLockGuard.h | 55 + beast/threads/UnlockGuard.h | 50 + .../threads/WaitableEvent.h | 50 +- beast/threads/detail/BindHandler.h | 276 ++++ beast/threads/detail/DispatchedHandler.h | 173 +++ beast/threads/impl/Atomic.cpp | 133 ++ beast/threads/impl/RecursiveMutex.cpp | 111 ++ beast/threads/impl/ServiceQueue.cpp | 465 ++++++ beast/threads/impl/Stoppable.cpp | 198 +++ beast/threads/impl/Thread.cpp | 599 ++++++++ beast/threads/impl/WaitableEvent.cpp | 168 ++ beast/type_traits/IntegralConstant.h | 40 + beast/type_traits/IsIntegral.h | 42 + beast/type_traits/IsSigned.h | 40 + beast/type_traits/RemoveSigned.h | 45 + beast/utility/BaseFromMember.h | 71 + .../beast_Debug.h => beast/utility/Debug.h | 10 +- beast/utility/EnableIf.h | 48 + .../beast_Error.h => beast/utility/Error.h | 17 +- beast/utility/Journal.h | 193 +++ .../utility/LeakChecked.h | 86 +- beast/utility/PropertyStream.h | 297 ++++ beast/utility/StaticObject.h | 113 ++ beast/utility/Utility.cpp | 31 + .../utility/impl/Debug.cpp | 47 +- .../utility/impl/Error.cpp | 21 + beast/utility/impl/Journal.cpp | 205 +++ .../utility/impl/LeakChecked.cpp | 22 +- beast/utility/impl/PropertyStream.cpp | 422 +++++ beast/utility/impl/StaticObject.cpp | 41 + config/BeastConfig.h | 144 ++ modules/beast_asio/async/AbstractHandler.h | 712 +++++++++ modules/beast_asio/async/AsyncObject.h | 72 + .../beast_asio/async/ComposedAsyncOperation.h | 2 +- modules/beast_asio/async/SharedHandler.h | 12 +- .../beast_asio/async/SharedHandlerAllocator.h | 2 +- modules/beast_asio/async/SharedHandlerPtr.h | 27 +- modules/beast_asio/async/SharedHandlerType.h | 23 +- modules/beast_asio/async/WrapHandler.h | 209 +++ modules/beast_asio/basics/BuffersType.h | 2 - modules/beast_asio/basics/SharedArg.h | 161 ++ modules/beast_asio/beast_asio.cpp | 24 +- modules/beast_asio/beast_asio.h | 24 +- modules/beast_asio/http/HTTPClientType.cpp | 825 ++++------ modules/beast_asio/http/HTTPClientType.h | 58 +- modules/beast_asio/http/HTTPHeaders.cpp | 12 + modules/beast_asio/http/HTTPHeaders.h | 3 + modules/beast_asio/http/HTTPMessage.cpp | 12 +- modules/beast_asio/http/HTTPMessage.h | 9 +- modules/beast_asio/http/HTTPParser.cpp | 33 +- modules/beast_asio/http/HTTPParser.h | 25 +- modules/beast_asio/http/HTTPParserImpl.h | 17 +- modules/beast_asio/http/HTTPRequest.cpp | 42 + modules/beast_asio/http/HTTPRequest.h | 45 + .../http/HTTPRequestParser.cpp} | 22 +- modules/beast_asio/http/HTTPRequestParser.h | 46 + modules/beast_asio/http/HTTPResponse.cpp | 11 +- modules/beast_asio/http/HTTPResponse.h | 5 +- .../beast_asio/http/HTTPResponseParser.cpp | 38 + modules/beast_asio/http/HTTPResponseParser.h | 46 + modules/beast_asio/http/HTTPVersion.cpp | 8 +- modules/beast_asio/http/HTTPVersion.h | 6 +- modules/beast_asio/sockets/SocketWrapper.h | 168 +- modules/beast_core/beast_core.cpp | 246 ++- modules/beast_core/beast_core.h | 512 ++---- ...east_AbstractFifo.cpp => AbstractFifo.cpp} | 0 .../{beast_AbstractFifo.h => AbstractFifo.h} | 0 .../containers/{beast_Array.h => Array.h} | 0 ...AllocationBase.h => ArrayAllocationBase.h} | 0 .../beast_core/containers/DynamicArray.cpp | 175 --- modules/beast_core/containers/DynamicArray.h | 728 --------- modules/beast_core/containers/DynamicList.cpp | 327 ---- modules/beast_core/containers/DynamicList.h | 473 ------ ...st_DynamicObject.cpp => DynamicObject.cpp} | 0 ...{beast_DynamicObject.h => DynamicObject.h} | 0 ...lementComparator.h => ElementComparator.h} | 0 modules/beast_core/containers/HashMap.cpp | 154 -- modules/beast_core/containers/HashMap.h | 856 ----------- ...inkedListPointer.h => LinkedListPointer.h} | 0 ...{beast_LockFreeQueue.h => LockFreeQueue.h} | 12 +- ...st_NamedValueSet.cpp => NamedValueSet.cpp} | 0 ...{beast_NamedValueSet.h => NamedValueSet.h} | 0 .../{beast_OwnedArray.h => OwnedArray.h} | 0 ...{beast_PropertySet.cpp => PropertySet.cpp} | 0 .../{beast_PropertySet.h => PropertySet.h} | 0 ...copedValueSetter.h => ScopedValueSetter.h} | 0 ...haredObjectArray.h => SharedObjectArray.h} | 0 .../{beast_SortedSet.h => SortedSet.h} | 0 .../{beast_SparseSet.h => SparseSet.h} | 0 .../{beast_Variant.cpp => Variant.cpp} | 0 .../containers/{beast_Variant.h => Variant.h} | 0 .../containers/beast_LockFreeStack.h | 165 -- .../beast_core/containers/beast_SharedTable.h | 212 --- .../containers/beast_SortedLookupTable.h | 154 -- .../{beast_FPUFlags.cpp => FPUFlags.cpp} | 0 .../{beast_FPUFlags.h => FPUFlags.h} | 0 .../{beast_FatalError.cpp => FatalError.cpp} | 23 +- .../{beast_FatalError.h => FatalError.h} | 27 +- ...emanticVersion.cpp => SemanticVersion.cpp} | 0 ...st_SemanticVersion.h => SemanticVersion.h} | 0 .../diagnostic/{beast_Throw.h => Throw.h} | 4 +- .../{beast_UnitTest.cpp => UnitTest.cpp} | 58 +- .../{beast_UnitTest.h => UnitTest.h} | 36 +- ...estUtilities.cpp => UnitTestUtilities.cpp} | 0 ...nitTestUtilities.h => UnitTestUtilities.h} | 0 .../diagnostic/beast_ProtectedCall.cpp | 360 ----- .../diagnostic/beast_ProtectedCall.h | 147 -- ...toryIterator.cpp => DirectoryIterator.cpp} | 0 ...irectoryIterator.h => DirectoryIterator.h} | 0 .../files/{beast_File.cpp => File.cpp} | 13 +- .../beast_core/files/{beast_File.h => File.h} | 0 ...ileInputStream.cpp => FileInputStream.cpp} | 0 ...st_FileInputStream.h => FileInputStream.h} | 0 ...eOutputStream.cpp => FileOutputStream.cpp} | 0 ..._FileOutputStream.h => FileOutputStream.h} | 0 ..._FileSearchPath.cpp => FileSearchPath.cpp} | 0 ...east_FileSearchPath.h => FileSearchPath.h} | 0 ..._MemoryMappedFile.h => MemoryMappedFile.h} | 0 ...domAccessFile.cpp => RandomAccessFile.cpp} | 0 ..._RandomAccessFile.h => RandomAccessFile.h} | 0 ...st_TemporaryFile.cpp => TemporaryFile.cpp} | 0 ...{beast_TemporaryFile.h => TemporaryFile.h} | 0 .../beast_core/functional/SharedFunction.h | 99 -- .../beast_core/functional/beast_Function.h | 266 ---- .../json/{beast_JSON.cpp => JSON.cpp} | 0 .../beast_core/json/{beast_JSON.h => JSON.h} | 0 .../{beast_FileLogger.cpp => FileLogger.cpp} | 0 .../{beast_FileLogger.h => FileLogger.h} | 0 .../logging/{beast_Logger.cpp => Logger.cpp} | 2 +- .../logging/{beast_Logger.h => Logger.h} | 2 +- .../{beast_BigInteger.cpp => BigInteger.cpp} | 0 .../{beast_BigInteger.h => BigInteger.h} | 0 .../{beast_Expression.cpp => Expression.cpp} | 0 .../{beast_Expression.h => Expression.h} | 0 .../maths/{beast_Interval.h => Interval.h} | 0 .../beast_core/maths/{beast_Math.h => Math.h} | 0 .../{beast_MurmurHash.cpp => MurmurHash.cpp} | 0 .../{beast_MurmurHash.h => MurmurHash.h} | 16 + .../maths/{beast_Random.cpp => Random.cpp} | 0 .../maths/{beast_Random.h => Random.h} | 2 +- .../maths/{beast_Range.h => Range.h} | 0 .../maths/{beast_uint24.h => uint24.h} | 0 ...{beast_AtomicCounter.h => AtomicCounter.h} | 0 .../{beast_AtomicFlag.h => AtomicFlag.h} | 0 ...{beast_AtomicPointer.h => AtomicPointer.h} | 0 .../{beast_AtomicState.h => AtomicState.h} | 0 .../memory/{beast_CacheLine.h => CacheLine.h} | 184 +-- ...st_MemoryAlignment.h => MemoryAlignment.h} | 0 ...{beast_MemoryBlock.cpp => MemoryBlock.cpp} | 0 .../{beast_MemoryBlock.h => MemoryBlock.h} | 0 ...copedPointer.h => OptionalScopedPointer.h} | 0 ...ycledObjectPool.h => RecycledObjectPool.h} | 0 modules/beast_core/memory/SharedFunction.h | 334 ++++ ...st_SharedSingleton.h => SharedSingleton.h} | 183 +-- ...{beast_WeakReference.h => WeakReference.h} | 0 modules/beast_core/memory/beast_AllocatedBy.h | 63 - modules/beast_core/memory/beast_ByteSwap.h | 126 -- .../memory/beast_FifoFreeStoreWithTLS.cpp | 198 --- .../memory/beast_FifoFreeStoreWithTLS.h | 69 - .../memory/beast_FifoFreeStoreWithoutTLS.cpp | 241 --- .../memory/beast_FifoFreeStoreWithoutTLS.h | 65 - .../memory/beast_PagedFreeStore.cpp | 229 --- .../beast_core/memory/beast_PagedFreeStore.h | 94 -- .../beast_core/memory/beast_StaticObject.h | 172 --- .../misc/{beast_Main.cpp => Main.cpp} | 33 +- .../beast_core/misc/{beast_Main.h => Main.h} | 13 +- .../misc/{beast_Result.cpp => Result.cpp} | 2 +- .../misc/{beast_Result.h => Result.h} | 0 .../misc/{beast_Uuid.cpp => Uuid.cpp} | 0 .../beast_core/misc/{beast_Uuid.h => Uuid.h} | 0 ...st_WindowsRegistry.h => WindowsRegistry.h} | 0 ...icNativeHeaders.h => BasicNativeHeaders.h} | 3 +- ...st_android_Files.cpp => android_Files.cpp} | 0 ...roid_JNIHelpers.h => android_JNIHelpers.h} | 0 ...east_android_Misc.cpp => android_Misc.cpp} | 0 modules/beast_core/native/android_Network.cpp | 59 + ...ystemStats.cpp => android_SystemStats.cpp} | 0 ...ndroid_Threads.cpp => android_Threads.cpp} | 2 +- .../native/beast_android_Network.cpp | 170 -- .../beast_core/native/beast_bsd_Network.cpp | 455 ------ .../beast_core/native/beast_linux_Network.cpp | 457 ------ .../beast_core/native/beast_win32_Network.cpp | 464 ------ .../{beast_bsd_Files.cpp => bsd_Files.cpp} | 4 +- modules/beast_core/native/bsd_Network.cpp | 59 + ...sd_SystemStats.cpp => bsd_SystemStats.cpp} | 0 ...{beast_bsd_Threads.cpp => bsd_Threads.cpp} | 4 +- ...{beast_linux_Files.cpp => linux_Files.cpp} | 4 +- modules/beast_core/native/linux_Network.cpp | 61 + ..._SystemStats.cpp => linux_SystemStats.cpp} | 0 ...st_linux_Threads.cpp => linux_Threads.cpp} | 2 +- .../{beast_mac_Files.mm => mac_Files.mm} | 0 .../{beast_mac_Network.mm => mac_Network.mm} | 134 +- .../{beast_mac_Strings.mm => mac_Strings.mm} | 0 ..._mac_SystemStats.mm => mac_SystemStats.mm} | 0 .../{beast_mac_Threads.mm => mac_Threads.mm} | 2 +- ...st_osx_ObjCHelpers.h => osx_ObjCHelpers.h} | 0 ..._posix_FPUFlags.cpp => posix_FPUFlags.cpp} | 0 ...osix_NamedPipe.cpp => posix_NamedPipe.cpp} | 0 ..._posix_SharedCode.h => posix_SharedCode.h} | 232 --- ...in32_ComSmartPtr.h => win32_ComSmartPtr.h} | 0 ..._win32_FPUFlags.cpp => win32_FPUFlags.cpp} | 0 ...{beast_win32_Files.cpp => win32_Files.cpp} | 0 modules/beast_core/native/win32_Network.cpp | 172 +++ ..._win32_Registry.cpp => win32_Registry.cpp} | 0 ..._SystemStats.cpp => win32_SystemStats.cpp} | 0 ...st_win32_Threads.cpp => win32_Threads.cpp} | 156 +- .../{beast_IPAddress.cpp => IPAddress.cpp} | 0 .../{beast_IPAddress.h => IPAddress.h} | 0 .../{beast_MACAddress.cpp => MACAddress.cpp} | 0 .../{beast_MACAddress.h => MACAddress.h} | 0 .../{beast_NamedPipe.cpp => NamedPipe.cpp} | 0 .../{beast_NamedPipe.h => NamedPipe.h} | 0 .../network/{beast_Socket.cpp => Socket.cpp} | 0 .../network/{beast_Socket.h => Socket.h} | 0 .../network/{beast_URL.cpp => URL.cpp} | 0 .../beast_core/network/{beast_URL.h => URL.h} | 0 ...nputStream.cpp => BufferedInputStream.cpp} | 0 ...redInputStream.h => BufferedInputStream.h} | 0 ...ileInputSource.cpp => FileInputSource.cpp} | 0 ...st_FileInputSource.h => FileInputSource.h} | 0 .../{beast_InputSource.h => InputSource.h} | 0 ...{beast_InputStream.cpp => InputStream.cpp} | 0 .../{beast_InputStream.h => InputStream.h} | 0 ...yInputStream.cpp => MemoryInputStream.cpp} | 0 ...emoryInputStream.h => MemoryInputStream.h} | 0 ...utputStream.cpp => MemoryOutputStream.cpp} | 0 ...oryOutputStream.h => MemoryOutputStream.h} | 0 ...east_OutputStream.cpp => OutputStream.cpp} | 17 + .../{beast_OutputStream.h => OutputStream.h} | 3 + ...ubregionStream.cpp => SubregionStream.cpp} | 0 ...st_SubregionStream.h => SubregionStream.h} | 0 modules/beast_core/system/BeforeBoost.h | 58 +- modules/beast_core/system/BoostIncludes.h | 4 +- modules/beast_core/system/Functional.h | 242 --- .../beast_core/system/FunctionalIncludes.h | 4 +- modules/beast_core/system/StandardIncludes.h | 78 + modules/beast_core/system/SystemStats.cpp | 16 - .../{beast_Identifier.cpp => Identifier.cpp} | 0 .../text/{beast_Identifier.h => Identifier.h} | 0 ...{beast_LexicalCast.cpp => LexicalCast.cpp} | 0 .../{beast_LexicalCast.h => LexicalCast.h} | 0 ...alisedStrings.cpp => LocalisedStrings.cpp} | 0 ..._LocalisedStrings.h => LocalisedStrings.h} | 0 ...{beast_StringArray.cpp => StringArray.cpp} | 0 .../{beast_StringArray.h => StringArray.h} | 0 ...tringPairArray.cpp => StringPairArray.cpp} | 0 ...st_StringPairArray.h => StringPairArray.h} | 0 .../{beast_StringPool.cpp => StringPool.cpp} | 0 .../text/{beast_StringPool.h => StringPool.h} | 0 .../text/{beast_TextDiff.cpp => TextDiff.cpp} | 0 .../text/{beast_TextDiff.h => TextDiff.h} | 0 ...st_DeadlineTimer.cpp => DeadlineTimer.cpp} | 58 +- ...{beast_DeadlineTimer.h => DeadlineTimer.h} | 51 +- .../{beast_Semaphore.cpp => Semaphore.cpp} | 0 .../thread/{beast_Semaphore.h => Semaphore.h} | 0 .../thread/{beast_Workers.cpp => Workers.cpp} | 3 - .../thread/{beast_Workers.h => Workers.h} | 0 modules/beast_core/thread/beast_CallQueue.cpp | 153 -- modules/beast_core/thread/beast_CallQueue.h | 506 ------ .../thread/beast_ConcurrentObject.cpp | 76 - .../thread/beast_ConcurrentObject.h | 79 - .../thread/beast_InterruptibleThread.cpp | 202 --- .../thread/beast_InterruptibleThread.h | 174 --- modules/beast_core/thread/beast_Listeners.cpp | 758 --------- modules/beast_core/thread/beast_Listeners.h | 797 ---------- .../thread/beast_ManualCallQueue.cpp | 54 - .../beast_core/thread/beast_ManualCallQueue.h | 108 -- .../beast_core/thread/beast_OncePerSecond.cpp | 111 -- .../beast_core/thread/beast_OncePerSecond.h | 62 - .../beast_core/thread/beast_ParallelFor.cpp | 63 - modules/beast_core/thread/beast_ParallelFor.h | 251 --- modules/beast_core/thread/beast_SerialFor.h | 71 - .../beast_core/thread/beast_ThreadGroup.cpp | 105 -- modules/beast_core/thread/beast_ThreadGroup.h | 215 --- .../thread/beast_ThreadWithCallQueue.cpp | 152 -- .../thread/beast_ThreadWithCallQueue.h | 155 -- .../beast_core/thread/impl/TrackedMutex.cpp | 16 +- ...east_ChildProcess.cpp => ChildProcess.cpp} | 17 +- .../{beast_ChildProcess.h => ChildProcess.h} | 0 ...st_CriticalSection.h => CriticalSection.h} | 1 - ...east_DynamicLibrary.h => DynamicLibrary.h} | 0 ...utionTimer.cpp => HighResolutionTimer.cpp} | 0 ...esolutionTimer.h => HighResolutionTimer.h} | 0 ..._InterProcessLock.h => InterProcessLock.h} | 0 .../threads/{beast_Process.h => Process.h} | 0 ...st_ReadWriteLock.cpp => ReadWriteLock.cpp} | 0 ...{beast_ReadWriteLock.h => ReadWriteLock.h} | 0 .../{beast_ScopedLock.h => ScopedLock.h} | 0 ...east_ScopedReadLock.h => ScopedReadLock.h} | 0 ...st_ScopedWriteLock.h => ScopedWriteLock.h} | 0 .../{beast_SpinDelay.cpp => SpinDelay.cpp} | 0 .../{beast_SpinDelay.h => SpinDelay.h} | 0 .../threads/beast_ReadWriteMutex.cpp | 98 -- .../beast_core/threads/beast_ReadWriteMutex.h | 150 -- modules/beast_core/threads/beast_SharedData.h | 295 ---- modules/beast_core/threads/beast_Thread.cpp | 365 ----- .../beast_core/threads/beast_ThreadPool.cpp | 371 ----- modules/beast_core/threads/beast_ThreadPool.h | 304 ---- .../threads/beast_TimeSliceThread.cpp | 166 -- .../threads/beast_TimeSliceThread.h | 143 -- modules/beast_core/time/AtExitHook.cpp | 135 ++ modules/beast_core/time/AtExitHook.h | 88 ++ ...anceCounter.cpp => PerformanceCounter.cpp} | 0 ...formanceCounter.h => PerformanceCounter.h} | 0 .../time/{beast_Time.cpp => Time.cpp} | 0 .../beast_core/time/{beast_Time.h => Time.h} | 15 + .../beast_core/time/beast_PerformedAtExit.cpp | 74 - .../beast_core/time/beast_PerformedAtExit.h | 52 - .../beast_core/time/beast_RelativeTime.cpp | 134 -- ...{beast_XmlDocument.cpp => XmlDocument.cpp} | 0 .../{beast_XmlDocument.h => XmlDocument.h} | 0 .../{beast_XmlElement.cpp => XmlElement.cpp} | 0 .../xml/{beast_XmlElement.h => XmlElement.h} | 0 ...eam.cpp => GZIPCompressorOutputStream.cpp} | 0 ...tStream.h => GZIPCompressorOutputStream.h} | 0 ...am.cpp => GZIPDecompressorInputStream.cpp} | 4 + ...Stream.h => GZIPDecompressorInputStream.h} | 0 .../zip/{beast_ZipFile.cpp => ZipFile.cpp} | 0 .../zip/{beast_ZipFile.h => ZipFile.h} | 0 modules/beast_crypto/beast_crypto.cpp | 3 +- modules/beast_crypto/beast_crypto.h | 4 +- modules/beast_crypto/math/BinaryEncoding.cpp | 395 +++++ modules/beast_crypto/math/BinaryEncoding.h | 24 + modules/beast_crypto/math/UnsignedInteger.cpp | 396 +++++ modules/beast_crypto/math/UnsignedInteger.h | 299 ++++ .../beast_crypto/math/UnsignedIntegerCalc.h | 430 ++++++ .../math/beast_UnsignedInteger.cpp | 85 - .../beast_crypto/math/beast_UnsignedInteger.h | 378 ----- modules/beast_db/beast_db.cpp | 2 +- modules/beast_db/beast_db.h | 2 +- .../{beast_KeyvaDB.cpp => KeyvaDB.cpp} | 22 +- .../keyvalue/{beast_KeyvaDB.h => KeyvaDB.h} | 0 modules/beast_extras/beast_extras.h | 2 +- ...LockableTraits.h => BoostLockableTraits.h} | 0 modules/beast_sqdb/api/session.h | 2 +- .../beast_sqdb/api/type_conversion_traits.h | 4 +- modules/beast_sqdb/source/error_codes.cpp | 4 + modules/beast_sqdb/source/into_type.cpp | 15 +- modules/beast_sqdb/source/session.cpp | 63 +- modules/beast_sqdb/source/statement_imp.cpp | 5 +- modules/beast_sqdb/source/transaction.cpp | 6 +- modules/beast_sqdb/source/use_type.cpp | 5 +- modules/beast_sqlite/beast_sqlite.h | 2 +- .../BeastConfig.h | 7 - scripts/compile.sh | 29 + 480 files changed, 19599 insertions(+), 18109 deletions(-) create mode 100644 LICENSE_1_0.txt rename modules/beast_core/maths/beast_MathsFunctions.h => beast/Arithmetic.h (79%) rename modules/beast_core/memory/beast_Atomic.h => beast/Atomic.h (97%) create mode 100644 beast/Boost.h rename modules/beast_core/memory/beast_ByteOrder.h => beast/ByteOrder.h (78%) create mode 100644 beast/CStdInt.h create mode 100644 beast/Chrono.h create mode 100644 beast/Config.h create mode 100644 beast/Crypto.h create mode 100644 beast/FixedArray.h create mode 100644 beast/HTTP.h rename modules/beast_core/memory/beast_HeapBlock.h => beast/HeapBlock.h (88%) create mode 100644 beast/Intrusive.h rename beast/{mpl.h => MPL.h} (95%) rename modules/beast_core/memory/beast_Memory.h => beast/Memory.h (86%) create mode 100644 beast/Net.h rename modules/beast_core/diagnostic/beast_SafeBool.h => beast/SafeBool.h (93%) create mode 100644 beast/SmartPtr.h rename modules/beast_core/thread/beast_GlobalThreadGroup.h => beast/StaticAssert.h (62%) create mode 100644 beast/Strings.h rename modules/beast_core/memory/beast_FifoFreeStore.h => beast/Threads.h (67%) create mode 100644 beast/TypeTraits.h rename modules/beast_core/memory/beast_Uncopyable.h => beast/Uncopyable.h (95%) create mode 100644 beast/Utility.h create mode 100644 beast/Version.h create mode 100644 beast/boost/Boost.cpp create mode 100644 beast/boost/ErrorCode.h create mode 100644 beast/chrono/CPUMeter.h create mode 100644 beast/chrono/Chrono.cpp rename modules/beast_core/time/beast_RelativeTime.h => beast/chrono/RelativeTime.h (71%) rename modules/beast_core/memory/beast_GlobalPagedFreeStore.h => beast/chrono/ScopedTimeInterval.h (55%) create mode 100644 beast/chrono/impl/CPUMeter.cpp create mode 100644 beast/chrono/impl/RelativeTime.cpp rename modules/beast_core/system/PlatformDefs.h => beast/config/CompilerConfig.h (91%) rename modules/beast_core/system/BeastConfigCheck.h => beast/config/ConfigCheck.h (91%) rename {modules/beast_core/diagnostic => beast/config}/ContractChecks.h (92%) rename modules/beast_core/system/TargetPlatform.h => beast/config/PlatformConfig.h (98%) create mode 100644 beast/config/SelectCompilerConfig.h rename modules/beast_core/containers/detail/removecv.h => beast/config/SelectPlatformConfig.h (53%) create mode 100644 beast/config/SelectStdlibConfig.h rename modules/beast_core/system/StandardHeader.h => beast/config/StandardConfig.h (66%) create mode 100644 beast/config/Suffix.h create mode 100644 beast/config/compiler/Clang.h create mode 100644 beast/config/compiler/Gcc.h create mode 100644 beast/config/compiler/Intel.h create mode 100644 beast/config/compiler/VisualC.h create mode 100644 beast/config/platform/Android.h create mode 100644 beast/config/platform/Bsd.h create mode 100644 beast/config/platform/Linux.h create mode 100644 beast/config/platform/MacOS.h create mode 100644 beast/config/platform/Win32.h create mode 100644 beast/crypto/Crypto.cpp create mode 100644 beast/crypto/Sha256.h create mode 100644 beast/crypto/impl/Sha256.cpp create mode 100644 beast/crypto/impl/sha2/README create mode 100644 beast/crypto/impl/sha2/sha2.c create mode 100644 beast/crypto/impl/sha2/sha2.h create mode 100644 beast/crypto/impl/sha2/sha2prog.c create mode 100644 beast/crypto/impl/sha2/sha2speed.c create mode 100644 beast/crypto/impl/sha2/sha2test.pl create mode 100644 beast/http/HTTP.cpp create mode 100644 beast/http/ParsedURL.h rename modules/beast_asio/http/UniformResourceLocator.h => beast/http/URL.h (74%) rename modules/beast_asio/http/UniformResourceLocator.cpp => beast/http/impl/ParsedURL.cpp (59%) create mode 100644 beast/http/impl/README.md create mode 100644 beast/http/impl/URL.cpp rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/.gitignore (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/.mailmap (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/.travis.yml (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/AUTHORS (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/CONTRIBUTIONS (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/LICENSE-MIT (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/Makefile (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/README.md (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/contrib/parsertrace.c (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/contrib/url_parser.c (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/http_parser.c (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/http_parser.gyp (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/http_parser.h (100%) rename {modules/beast_asio/parsehttp => beast/http/impl/http-parser}/test.c (100%) create mode 100644 beast/http/impl/http_parser.cpp create mode 100644 beast/intrusive/IntrusiveArray.h rename {modules/beast_core/containers => beast/intrusive}/List.h (71%) create mode 100644 beast/intrusive/LockFreeStack.h rename modules/beast_core/containers/detail/copyconst.h => beast/mpl/CopyConst.h (75%) create mode 100644 beast/mpl/IsCallPossible.h rename {modules/beast_asio/basics => beast/net}/BufferType.h (91%) create mode 100644 beast/net/DynamicBuffer.h create mode 100644 beast/net/IPEndpoint.h create mode 100644 beast/net/Net.cpp create mode 100644 beast/net/impl/DynamicBuffer.cpp create mode 100644 beast/net/impl/IPEndpoint.cpp rename modules/beast_core/memory/beast_ContainerDeletePolicy.h => beast/smart_ptr/ContainerDeletePolicy.h (92%) rename modules/beast_core/memory/beast_ScopedPointer.h => beast/smart_ptr/ScopedPointer.h (89%) rename {modules/beast_core/memory => beast/smart_ptr}/SharedObject.h (95%) rename {modules/beast_core/memory => beast/smart_ptr}/SharedPtr.h (87%) create mode 100644 beast/smart_ptr/SmartPtr.cpp rename modules/beast_core/text/beast_CharPointer_ASCII.h => beast/strings/CharPointer_ASCII.h (99%) rename modules/beast_core/text/beast_CharPointer_UTF16.h => beast/strings/CharPointer_UTF16.h (99%) rename modules/beast_core/text/beast_CharPointer_UTF32.h => beast/strings/CharPointer_UTF32.h (99%) rename modules/beast_core/text/beast_CharPointer_UTF8.h => beast/strings/CharPointer_UTF8.h (99%) rename modules/beast_core/text/beast_CharacterFunctions.h => beast/strings/CharacterFunctions.h (97%) rename modules/beast_core/text/beast_NewLine.h => beast/strings/NewLine.h (94%) rename modules/beast_core/text/beast_String.h => beast/strings/String.h (98%) rename {modules/beast_core/text => beast/strings}/StringCharPointerType.h (90%) rename {modules/beast_core/text => beast/strings}/StringFromNumber.h (94%) create mode 100644 beast/strings/Strings.cpp rename modules/beast_core/text/beast_CharacterFunctions.cpp => beast/strings/impl/CharacterFunctions.cpp (97%) rename modules/beast_core/text/beast_String.cpp => beast/strings/impl/String.cpp (98%) create mode 100644 beast/threads/LockGuard.h create mode 100644 beast/threads/RecursiveMutex.h create mode 100644 beast/threads/ScopedWrapperContext.h create mode 100644 beast/threads/ServiceQueue.h create mode 100644 beast/threads/SharedData.h create mode 100644 beast/threads/SharedLockGuard.h rename modules/beast_core/memory/beast_GlobalFifoFreeStore.h => beast/threads/SharedMutexAdapter.h (56%) rename modules/beast_core/threads/beast_SpinLock.h => beast/threads/SpinLock.h (82%) create mode 100644 beast/threads/Stoppable.h rename modules/beast_core/threads/beast_Thread.h => beast/threads/Thread.h (96%) rename modules/beast_core/threads/beast_ThreadLocalValue.h => beast/threads/ThreadLocalValue.h (97%) create mode 100644 beast/threads/Threads.cpp create mode 100644 beast/threads/TryLockGuard.h create mode 100644 beast/threads/UnlockGuard.h rename modules/beast_core/threads/beast_WaitableEvent.h => beast/threads/WaitableEvent.h (81%) create mode 100644 beast/threads/detail/BindHandler.h create mode 100644 beast/threads/detail/DispatchedHandler.h create mode 100644 beast/threads/impl/Atomic.cpp create mode 100644 beast/threads/impl/RecursiveMutex.cpp create mode 100644 beast/threads/impl/ServiceQueue.cpp create mode 100644 beast/threads/impl/Stoppable.cpp create mode 100644 beast/threads/impl/Thread.cpp create mode 100644 beast/threads/impl/WaitableEvent.cpp create mode 100644 beast/type_traits/IntegralConstant.h create mode 100644 beast/type_traits/IsIntegral.h create mode 100644 beast/type_traits/IsSigned.h create mode 100644 beast/type_traits/RemoveSigned.h create mode 100644 beast/utility/BaseFromMember.h rename modules/beast_core/diagnostic/beast_Debug.h => beast/utility/Debug.h (95%) create mode 100644 beast/utility/EnableIf.h rename modules/beast_core/diagnostic/beast_Error.h => beast/utility/Error.h (95%) create mode 100644 beast/utility/Journal.h rename modules/beast_core/diagnostic/beast_LeakChecked.h => beast/utility/LeakChecked.h (74%) create mode 100644 beast/utility/PropertyStream.h create mode 100644 beast/utility/StaticObject.h create mode 100644 beast/utility/Utility.cpp rename modules/beast_core/diagnostic/beast_Debug.cpp => beast/utility/impl/Debug.cpp (86%) rename modules/beast_core/diagnostic/beast_Error.cpp => beast/utility/impl/Error.cpp (96%) create mode 100644 beast/utility/impl/Journal.cpp rename modules/beast_core/diagnostic/beast_LeakChecked.cpp => beast/utility/impl/LeakChecked.cpp (88%) create mode 100644 beast/utility/impl/PropertyStream.cpp create mode 100644 beast/utility/impl/StaticObject.cpp create mode 100644 config/BeastConfig.h create mode 100644 modules/beast_asio/async/AbstractHandler.h create mode 100644 modules/beast_asio/async/AsyncObject.h create mode 100644 modules/beast_asio/async/WrapHandler.h create mode 100644 modules/beast_asio/basics/SharedArg.h create mode 100644 modules/beast_asio/http/HTTPRequest.cpp create mode 100644 modules/beast_asio/http/HTTPRequest.h rename modules/{beast_core/memory/beast_GlobalPagedFreeStore.cpp => beast_asio/http/HTTPRequestParser.cpp} (73%) create mode 100644 modules/beast_asio/http/HTTPRequestParser.h create mode 100644 modules/beast_asio/http/HTTPResponseParser.cpp create mode 100644 modules/beast_asio/http/HTTPResponseParser.h rename modules/beast_core/containers/{beast_AbstractFifo.cpp => AbstractFifo.cpp} (100%) rename modules/beast_core/containers/{beast_AbstractFifo.h => AbstractFifo.h} (100%) rename modules/beast_core/containers/{beast_Array.h => Array.h} (100%) rename modules/beast_core/containers/{beast_ArrayAllocationBase.h => ArrayAllocationBase.h} (100%) delete mode 100644 modules/beast_core/containers/DynamicArray.cpp delete mode 100644 modules/beast_core/containers/DynamicArray.h delete mode 100644 modules/beast_core/containers/DynamicList.cpp delete mode 100644 modules/beast_core/containers/DynamicList.h rename modules/beast_core/containers/{beast_DynamicObject.cpp => DynamicObject.cpp} (100%) rename modules/beast_core/containers/{beast_DynamicObject.h => DynamicObject.h} (100%) rename modules/beast_core/containers/{beast_ElementComparator.h => ElementComparator.h} (100%) delete mode 100644 modules/beast_core/containers/HashMap.cpp delete mode 100644 modules/beast_core/containers/HashMap.h rename modules/beast_core/containers/{beast_LinkedListPointer.h => LinkedListPointer.h} (100%) rename modules/beast_core/containers/{beast_LockFreeQueue.h => LockFreeQueue.h} (95%) rename modules/beast_core/containers/{beast_NamedValueSet.cpp => NamedValueSet.cpp} (100%) rename modules/beast_core/containers/{beast_NamedValueSet.h => NamedValueSet.h} (100%) rename modules/beast_core/containers/{beast_OwnedArray.h => OwnedArray.h} (100%) rename modules/beast_core/containers/{beast_PropertySet.cpp => PropertySet.cpp} (100%) rename modules/beast_core/containers/{beast_PropertySet.h => PropertySet.h} (100%) rename modules/beast_core/containers/{beast_ScopedValueSetter.h => ScopedValueSetter.h} (100%) rename modules/beast_core/containers/{beast_SharedObjectArray.h => SharedObjectArray.h} (100%) rename modules/beast_core/containers/{beast_SortedSet.h => SortedSet.h} (100%) rename modules/beast_core/containers/{beast_SparseSet.h => SparseSet.h} (100%) rename modules/beast_core/containers/{beast_Variant.cpp => Variant.cpp} (100%) rename modules/beast_core/containers/{beast_Variant.h => Variant.h} (100%) delete mode 100644 modules/beast_core/containers/beast_LockFreeStack.h delete mode 100644 modules/beast_core/containers/beast_SharedTable.h delete mode 100644 modules/beast_core/containers/beast_SortedLookupTable.h rename modules/beast_core/diagnostic/{beast_FPUFlags.cpp => FPUFlags.cpp} (100%) rename modules/beast_core/diagnostic/{beast_FPUFlags.h => FPUFlags.h} (100%) rename modules/beast_core/diagnostic/{beast_FatalError.cpp => FatalError.cpp} (86%) rename modules/beast_core/diagnostic/{beast_FatalError.h => FatalError.h} (89%) rename modules/beast_core/diagnostic/{beast_SemanticVersion.cpp => SemanticVersion.cpp} (100%) rename modules/beast_core/diagnostic/{beast_SemanticVersion.h => SemanticVersion.h} (100%) rename modules/beast_core/diagnostic/{beast_Throw.h => Throw.h} (93%) rename modules/beast_core/diagnostic/{beast_UnitTest.cpp => UnitTest.cpp} (90%) rename modules/beast_core/diagnostic/{beast_UnitTest.h => UnitTest.h} (94%) rename modules/beast_core/diagnostic/{beast_UnitTestUtilities.cpp => UnitTestUtilities.cpp} (100%) rename modules/beast_core/diagnostic/{beast_UnitTestUtilities.h => UnitTestUtilities.h} (100%) delete mode 100644 modules/beast_core/diagnostic/beast_ProtectedCall.cpp delete mode 100644 modules/beast_core/diagnostic/beast_ProtectedCall.h rename modules/beast_core/files/{beast_DirectoryIterator.cpp => DirectoryIterator.cpp} (100%) rename modules/beast_core/files/{beast_DirectoryIterator.h => DirectoryIterator.h} (100%) rename modules/beast_core/files/{beast_File.cpp => File.cpp} (99%) rename modules/beast_core/files/{beast_File.h => File.h} (100%) rename modules/beast_core/files/{beast_FileInputStream.cpp => FileInputStream.cpp} (100%) rename modules/beast_core/files/{beast_FileInputStream.h => FileInputStream.h} (100%) rename modules/beast_core/files/{beast_FileOutputStream.cpp => FileOutputStream.cpp} (100%) rename modules/beast_core/files/{beast_FileOutputStream.h => FileOutputStream.h} (100%) rename modules/beast_core/files/{beast_FileSearchPath.cpp => FileSearchPath.cpp} (100%) rename modules/beast_core/files/{beast_FileSearchPath.h => FileSearchPath.h} (100%) rename modules/beast_core/files/{beast_MemoryMappedFile.h => MemoryMappedFile.h} (100%) rename modules/beast_core/files/{beast_RandomAccessFile.cpp => RandomAccessFile.cpp} (100%) rename modules/beast_core/files/{beast_RandomAccessFile.h => RandomAccessFile.h} (100%) rename modules/beast_core/files/{beast_TemporaryFile.cpp => TemporaryFile.cpp} (100%) rename modules/beast_core/files/{beast_TemporaryFile.h => TemporaryFile.h} (100%) delete mode 100644 modules/beast_core/functional/SharedFunction.h delete mode 100644 modules/beast_core/functional/beast_Function.h rename modules/beast_core/json/{beast_JSON.cpp => JSON.cpp} (100%) rename modules/beast_core/json/{beast_JSON.h => JSON.h} (100%) rename modules/beast_core/logging/{beast_FileLogger.cpp => FileLogger.cpp} (100%) rename modules/beast_core/logging/{beast_FileLogger.h => FileLogger.h} (100%) rename modules/beast_core/logging/{beast_Logger.cpp => Logger.cpp} (95%) rename modules/beast_core/logging/{beast_Logger.h => Logger.h} (97%) rename modules/beast_core/maths/{beast_BigInteger.cpp => BigInteger.cpp} (100%) rename modules/beast_core/maths/{beast_BigInteger.h => BigInteger.h} (100%) rename modules/beast_core/maths/{beast_Expression.cpp => Expression.cpp} (100%) rename modules/beast_core/maths/{beast_Expression.h => Expression.h} (100%) rename modules/beast_core/maths/{beast_Interval.h => Interval.h} (100%) rename modules/beast_core/maths/{beast_Math.h => Math.h} (100%) rename modules/beast_core/maths/{beast_MurmurHash.cpp => MurmurHash.cpp} (100%) rename modules/beast_core/maths/{beast_MurmurHash.h => MurmurHash.h} (86%) rename modules/beast_core/maths/{beast_Random.cpp => Random.cpp} (100%) rename modules/beast_core/maths/{beast_Random.h => Random.h} (99%) rename modules/beast_core/maths/{beast_Range.h => Range.h} (100%) rename modules/beast_core/maths/{beast_uint24.h => uint24.h} (100%) rename modules/beast_core/memory/{beast_AtomicCounter.h => AtomicCounter.h} (100%) rename modules/beast_core/memory/{beast_AtomicFlag.h => AtomicFlag.h} (100%) rename modules/beast_core/memory/{beast_AtomicPointer.h => AtomicPointer.h} (100%) rename modules/beast_core/memory/{beast_AtomicState.h => AtomicState.h} (100%) rename modules/beast_core/memory/{beast_CacheLine.h => CacheLine.h} (73%) rename modules/beast_core/memory/{beast_MemoryAlignment.h => MemoryAlignment.h} (100%) rename modules/beast_core/memory/{beast_MemoryBlock.cpp => MemoryBlock.cpp} (100%) rename modules/beast_core/memory/{beast_MemoryBlock.h => MemoryBlock.h} (100%) rename modules/beast_core/memory/{beast_OptionalScopedPointer.h => OptionalScopedPointer.h} (100%) rename modules/beast_core/memory/{beast_RecycledObjectPool.h => RecycledObjectPool.h} (100%) create mode 100644 modules/beast_core/memory/SharedFunction.h rename modules/beast_core/memory/{beast_SharedSingleton.h => SharedSingleton.h} (51%) rename modules/beast_core/memory/{beast_WeakReference.h => WeakReference.h} (100%) delete mode 100644 modules/beast_core/memory/beast_AllocatedBy.h delete mode 100644 modules/beast_core/memory/beast_ByteSwap.h delete mode 100644 modules/beast_core/memory/beast_FifoFreeStoreWithTLS.cpp delete mode 100644 modules/beast_core/memory/beast_FifoFreeStoreWithTLS.h delete mode 100644 modules/beast_core/memory/beast_FifoFreeStoreWithoutTLS.cpp delete mode 100644 modules/beast_core/memory/beast_FifoFreeStoreWithoutTLS.h delete mode 100644 modules/beast_core/memory/beast_PagedFreeStore.cpp delete mode 100644 modules/beast_core/memory/beast_PagedFreeStore.h delete mode 100644 modules/beast_core/memory/beast_StaticObject.h rename modules/beast_core/misc/{beast_Main.cpp => Main.cpp} (85%) rename modules/beast_core/misc/{beast_Main.h => Main.h} (89%) rename modules/beast_core/misc/{beast_Result.cpp => Result.cpp} (97%) rename modules/beast_core/misc/{beast_Result.h => Result.h} (100%) rename modules/beast_core/misc/{beast_Uuid.cpp => Uuid.cpp} (100%) rename modules/beast_core/misc/{beast_Uuid.h => Uuid.h} (100%) rename modules/beast_core/misc/{beast_WindowsRegistry.h => WindowsRegistry.h} (100%) rename modules/beast_core/native/{beast_BasicNativeHeaders.h => BasicNativeHeaders.h} (99%) rename modules/beast_core/native/{beast_android_Files.cpp => android_Files.cpp} (100%) rename modules/beast_core/native/{beast_android_JNIHelpers.h => android_JNIHelpers.h} (100%) rename modules/beast_core/native/{beast_android_Misc.cpp => android_Misc.cpp} (100%) create mode 100644 modules/beast_core/native/android_Network.cpp rename modules/beast_core/native/{beast_android_SystemStats.cpp => android_SystemStats.cpp} (100%) rename modules/beast_core/native/{beast_android_Threads.cpp => android_Threads.cpp} (97%) delete mode 100644 modules/beast_core/native/beast_android_Network.cpp delete mode 100644 modules/beast_core/native/beast_bsd_Network.cpp delete mode 100644 modules/beast_core/native/beast_linux_Network.cpp delete mode 100644 modules/beast_core/native/beast_win32_Network.cpp rename modules/beast_core/native/{beast_bsd_Files.cpp => bsd_Files.cpp} (98%) create mode 100644 modules/beast_core/native/bsd_Network.cpp rename modules/beast_core/native/{beast_bsd_SystemStats.cpp => bsd_SystemStats.cpp} (100%) rename modules/beast_core/native/{beast_bsd_Threads.cpp => bsd_Threads.cpp} (95%) rename modules/beast_core/native/{beast_linux_Files.cpp => linux_Files.cpp} (98%) create mode 100644 modules/beast_core/native/linux_Network.cpp rename modules/beast_core/native/{beast_linux_SystemStats.cpp => linux_SystemStats.cpp} (100%) rename modules/beast_core/native/{beast_linux_Threads.cpp => linux_Threads.cpp} (97%) rename modules/beast_core/native/{beast_mac_Files.mm => mac_Files.mm} (100%) rename modules/beast_core/native/{beast_mac_Network.mm => mac_Network.mm} (66%) rename modules/beast_core/native/{beast_mac_Strings.mm => mac_Strings.mm} (100%) rename modules/beast_core/native/{beast_mac_SystemStats.mm => mac_SystemStats.mm} (100%) rename modules/beast_core/native/{beast_mac_Threads.mm => mac_Threads.mm} (97%) rename modules/beast_core/native/{beast_osx_ObjCHelpers.h => osx_ObjCHelpers.h} (100%) rename modules/beast_core/native/{beast_posix_FPUFlags.cpp => posix_FPUFlags.cpp} (100%) rename modules/beast_core/native/{beast_posix_NamedPipe.cpp => posix_NamedPipe.cpp} (100%) rename modules/beast_core/native/{beast_posix_SharedCode.h => posix_SharedCode.h} (83%) rename modules/beast_core/native/{beast_win32_ComSmartPtr.h => win32_ComSmartPtr.h} (100%) rename modules/beast_core/native/{beast_win32_FPUFlags.cpp => win32_FPUFlags.cpp} (100%) rename modules/beast_core/native/{beast_win32_Files.cpp => win32_Files.cpp} (100%) create mode 100644 modules/beast_core/native/win32_Network.cpp rename modules/beast_core/native/{beast_win32_Registry.cpp => win32_Registry.cpp} (100%) rename modules/beast_core/native/{beast_win32_SystemStats.cpp => win32_SystemStats.cpp} (100%) rename modules/beast_core/native/{beast_win32_Threads.cpp => win32_Threads.cpp} (75%) rename modules/beast_core/network/{beast_IPAddress.cpp => IPAddress.cpp} (100%) rename modules/beast_core/network/{beast_IPAddress.h => IPAddress.h} (100%) rename modules/beast_core/network/{beast_MACAddress.cpp => MACAddress.cpp} (100%) rename modules/beast_core/network/{beast_MACAddress.h => MACAddress.h} (100%) rename modules/beast_core/network/{beast_NamedPipe.cpp => NamedPipe.cpp} (100%) rename modules/beast_core/network/{beast_NamedPipe.h => NamedPipe.h} (100%) rename modules/beast_core/network/{beast_Socket.cpp => Socket.cpp} (100%) rename modules/beast_core/network/{beast_Socket.h => Socket.h} (100%) rename modules/beast_core/network/{beast_URL.cpp => URL.cpp} (100%) rename modules/beast_core/network/{beast_URL.h => URL.h} (100%) rename modules/beast_core/streams/{beast_BufferedInputStream.cpp => BufferedInputStream.cpp} (100%) rename modules/beast_core/streams/{beast_BufferedInputStream.h => BufferedInputStream.h} (100%) rename modules/beast_core/streams/{beast_FileInputSource.cpp => FileInputSource.cpp} (100%) rename modules/beast_core/streams/{beast_FileInputSource.h => FileInputSource.h} (100%) rename modules/beast_core/streams/{beast_InputSource.h => InputSource.h} (100%) rename modules/beast_core/streams/{beast_InputStream.cpp => InputStream.cpp} (100%) rename modules/beast_core/streams/{beast_InputStream.h => InputStream.h} (100%) rename modules/beast_core/streams/{beast_MemoryInputStream.cpp => MemoryInputStream.cpp} (100%) rename modules/beast_core/streams/{beast_MemoryInputStream.h => MemoryInputStream.h} (100%) rename modules/beast_core/streams/{beast_MemoryOutputStream.cpp => MemoryOutputStream.cpp} (100%) rename modules/beast_core/streams/{beast_MemoryOutputStream.h => MemoryOutputStream.h} (100%) rename modules/beast_core/streams/{beast_OutputStream.cpp => OutputStream.cpp} (95%) rename modules/beast_core/streams/{beast_OutputStream.h => OutputStream.h} (98%) rename modules/beast_core/streams/{beast_SubregionStream.cpp => SubregionStream.cpp} (100%) rename modules/beast_core/streams/{beast_SubregionStream.h => SubregionStream.h} (100%) create mode 100644 modules/beast_core/system/StandardIncludes.h rename modules/beast_core/text/{beast_Identifier.cpp => Identifier.cpp} (100%) rename modules/beast_core/text/{beast_Identifier.h => Identifier.h} (100%) rename modules/beast_core/text/{beast_LexicalCast.cpp => LexicalCast.cpp} (100%) rename modules/beast_core/text/{beast_LexicalCast.h => LexicalCast.h} (100%) rename modules/beast_core/text/{beast_LocalisedStrings.cpp => LocalisedStrings.cpp} (100%) rename modules/beast_core/text/{beast_LocalisedStrings.h => LocalisedStrings.h} (100%) rename modules/beast_core/text/{beast_StringArray.cpp => StringArray.cpp} (100%) rename modules/beast_core/text/{beast_StringArray.h => StringArray.h} (100%) rename modules/beast_core/text/{beast_StringPairArray.cpp => StringPairArray.cpp} (100%) rename modules/beast_core/text/{beast_StringPairArray.h => StringPairArray.h} (100%) rename modules/beast_core/text/{beast_StringPool.cpp => StringPool.cpp} (100%) rename modules/beast_core/text/{beast_StringPool.h => StringPool.h} (100%) rename modules/beast_core/text/{beast_TextDiff.cpp => TextDiff.cpp} (100%) rename modules/beast_core/text/{beast_TextDiff.h => TextDiff.h} (100%) rename modules/beast_core/thread/{beast_DeadlineTimer.cpp => DeadlineTimer.cpp} (83%) rename modules/beast_core/thread/{beast_DeadlineTimer.h => DeadlineTimer.h} (81%) rename modules/beast_core/thread/{beast_Semaphore.cpp => Semaphore.cpp} (100%) rename modules/beast_core/thread/{beast_Semaphore.h => Semaphore.h} (100%) rename modules/beast_core/thread/{beast_Workers.cpp => Workers.cpp} (98%) rename modules/beast_core/thread/{beast_Workers.h => Workers.h} (100%) delete mode 100644 modules/beast_core/thread/beast_CallQueue.cpp delete mode 100644 modules/beast_core/thread/beast_CallQueue.h delete mode 100644 modules/beast_core/thread/beast_ConcurrentObject.cpp delete mode 100644 modules/beast_core/thread/beast_ConcurrentObject.h delete mode 100644 modules/beast_core/thread/beast_InterruptibleThread.cpp delete mode 100644 modules/beast_core/thread/beast_InterruptibleThread.h delete mode 100644 modules/beast_core/thread/beast_Listeners.cpp delete mode 100644 modules/beast_core/thread/beast_Listeners.h delete mode 100644 modules/beast_core/thread/beast_ManualCallQueue.cpp delete mode 100644 modules/beast_core/thread/beast_ManualCallQueue.h delete mode 100644 modules/beast_core/thread/beast_OncePerSecond.cpp delete mode 100644 modules/beast_core/thread/beast_OncePerSecond.h delete mode 100644 modules/beast_core/thread/beast_ParallelFor.cpp delete mode 100644 modules/beast_core/thread/beast_ParallelFor.h delete mode 100644 modules/beast_core/thread/beast_SerialFor.h delete mode 100644 modules/beast_core/thread/beast_ThreadGroup.cpp delete mode 100644 modules/beast_core/thread/beast_ThreadGroup.h delete mode 100644 modules/beast_core/thread/beast_ThreadWithCallQueue.cpp delete mode 100644 modules/beast_core/thread/beast_ThreadWithCallQueue.h rename modules/beast_core/threads/{beast_ChildProcess.cpp => ChildProcess.cpp} (82%) rename modules/beast_core/threads/{beast_ChildProcess.h => ChildProcess.h} (100%) rename modules/beast_core/threads/{beast_CriticalSection.h => CriticalSection.h} (99%) rename modules/beast_core/threads/{beast_DynamicLibrary.h => DynamicLibrary.h} (100%) rename modules/beast_core/threads/{beast_HighResolutionTimer.cpp => HighResolutionTimer.cpp} (100%) rename modules/beast_core/threads/{beast_HighResolutionTimer.h => HighResolutionTimer.h} (100%) rename modules/beast_core/threads/{beast_InterProcessLock.h => InterProcessLock.h} (100%) rename modules/beast_core/threads/{beast_Process.h => Process.h} (100%) rename modules/beast_core/threads/{beast_ReadWriteLock.cpp => ReadWriteLock.cpp} (100%) rename modules/beast_core/threads/{beast_ReadWriteLock.h => ReadWriteLock.h} (100%) rename modules/beast_core/threads/{beast_ScopedLock.h => ScopedLock.h} (100%) rename modules/beast_core/threads/{beast_ScopedReadLock.h => ScopedReadLock.h} (100%) rename modules/beast_core/threads/{beast_ScopedWriteLock.h => ScopedWriteLock.h} (100%) rename modules/beast_core/threads/{beast_SpinDelay.cpp => SpinDelay.cpp} (100%) rename modules/beast_core/threads/{beast_SpinDelay.h => SpinDelay.h} (100%) delete mode 100644 modules/beast_core/threads/beast_ReadWriteMutex.cpp delete mode 100644 modules/beast_core/threads/beast_ReadWriteMutex.h delete mode 100644 modules/beast_core/threads/beast_SharedData.h delete mode 100644 modules/beast_core/threads/beast_Thread.cpp delete mode 100644 modules/beast_core/threads/beast_ThreadPool.cpp delete mode 100644 modules/beast_core/threads/beast_ThreadPool.h delete mode 100644 modules/beast_core/threads/beast_TimeSliceThread.cpp delete mode 100644 modules/beast_core/threads/beast_TimeSliceThread.h create mode 100644 modules/beast_core/time/AtExitHook.cpp create mode 100644 modules/beast_core/time/AtExitHook.h rename modules/beast_core/time/{beast_PerformanceCounter.cpp => PerformanceCounter.cpp} (100%) rename modules/beast_core/time/{beast_PerformanceCounter.h => PerformanceCounter.h} (100%) rename modules/beast_core/time/{beast_Time.cpp => Time.cpp} (100%) rename modules/beast_core/time/{beast_Time.h => Time.h} (97%) delete mode 100644 modules/beast_core/time/beast_PerformedAtExit.cpp delete mode 100644 modules/beast_core/time/beast_PerformedAtExit.h delete mode 100644 modules/beast_core/time/beast_RelativeTime.cpp rename modules/beast_core/xml/{beast_XmlDocument.cpp => XmlDocument.cpp} (100%) rename modules/beast_core/xml/{beast_XmlDocument.h => XmlDocument.h} (100%) rename modules/beast_core/xml/{beast_XmlElement.cpp => XmlElement.cpp} (100%) rename modules/beast_core/xml/{beast_XmlElement.h => XmlElement.h} (100%) rename modules/beast_core/zip/{beast_GZIPCompressorOutputStream.cpp => GZIPCompressorOutputStream.cpp} (100%) rename modules/beast_core/zip/{beast_GZIPCompressorOutputStream.h => GZIPCompressorOutputStream.h} (100%) rename modules/beast_core/zip/{beast_GZIPDecompressorInputStream.cpp => GZIPDecompressorInputStream.cpp} (99%) rename modules/beast_core/zip/{beast_GZIPDecompressorInputStream.h => GZIPDecompressorInputStream.h} (100%) rename modules/beast_core/zip/{beast_ZipFile.cpp => ZipFile.cpp} (100%) rename modules/beast_core/zip/{beast_ZipFile.h => ZipFile.h} (100%) create mode 100644 modules/beast_crypto/math/BinaryEncoding.cpp create mode 100644 modules/beast_crypto/math/BinaryEncoding.h create mode 100644 modules/beast_crypto/math/UnsignedInteger.cpp create mode 100644 modules/beast_crypto/math/UnsignedInteger.h create mode 100644 modules/beast_crypto/math/UnsignedIntegerCalc.h delete mode 100644 modules/beast_crypto/math/beast_UnsignedInteger.cpp delete mode 100644 modules/beast_crypto/math/beast_UnsignedInteger.h rename modules/beast_db/keyvalue/{beast_KeyvaDB.cpp => KeyvaDB.cpp} (97%) rename modules/beast_db/keyvalue/{beast_KeyvaDB.h => KeyvaDB.h} (100%) rename modules/beast_extras/traits/{beast_BoostLockableTraits.h => BoostLockableTraits.h} (100%) rename {Builds/VisualStudio2012 => scripts}/BeastConfig.h (96%) create mode 100755 scripts/compile.sh diff --git a/.gitignore b/.gitignore index d5acdb6154..1a834f299e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ contents.xcworkspacedata profile Builds/VisualStudio2012/Debug Builds/VisualStudio2012/Release + +modules/beast_cryptopp diff --git a/Builds/VisualStudio2012/Beast.props b/Builds/VisualStudio2012/Beast.props index 2428672bea..792f3409ca 100644 --- a/Builds/VisualStudio2012/Beast.props +++ b/Builds/VisualStudio2012/Beast.props @@ -1,16 +1,22 @@  - + + ..\.. + Level4 - _CRTDBG_MAP_ALLOC;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + BEAST_COMPILING_STATIC_LIBARARY=1;_CRTDBG_MAP_ALLOC;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) true false - %(AdditionalIncludeDirectories) + $(RepoDir)\config;%(AdditionalIncludeDirectories) - + + + $(RepoDir) + + \ No newline at end of file diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj index 422e763b14..455746b304 100644 --- a/Builds/VisualStudio2012/beast.vcxproj +++ b/Builds/VisualStudio2012/beast.vcxproj @@ -21,6 +21,17 @@ + + + + + + + + + + + @@ -29,31 +40,31 @@ true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true @@ -67,28 +78,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + @@ -97,10 +210,11 @@ + + + - - @@ -127,174 +241,108 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -302,15 +350,14 @@ - - - - - - - - - + + + + + + + + @@ -323,11 +370,13 @@ - + + + - + - + @@ -351,16 +400,192 @@ - - + + + true true true true - + + true + true + true + true + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + + true + true + true + true + + + true + true + true + true + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true + true + true + true + + + true true true @@ -407,30 +632,36 @@ true true + + true + true + true + true + + + true + true + true + true + true true true true + + true + true + true + true + true true true true - - true - true - true - true - - - true - true - true - true - true true @@ -510,431 +741,359 @@ true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - - - true - true - true - true - + true true true true - + true true true true - + true true true true - - true - true - true - true - - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - - true - true - true - true - - - true - true - true - true - - + true true true true - + true true true true - + true - true true - true - - - true true - true true - + true true true true - + true true true true - - true - true - true - true - - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - - true - true - true - true - - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true @@ -952,169 +1111,85 @@ true true - + true true true true - - true - true - true - true - - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - - true - true - true - true - - + true true true true - + true true true true - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - + true true true true - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - - true - true - true - true - - + true true true @@ -1126,55 +1201,49 @@ true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - + true true true true - - true - true - true - true - - + true true true @@ -1247,14 +1316,20 @@ true - + + true + true + true + true + + true true true true - + true true true diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters index a10f8600c3..077df7635a 100644 --- a/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Builds/VisualStudio2012/beast.vcxproj.filters @@ -1,24 +1,19 @@  - - - - beast_core - - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native @@ -27,9 +22,60 @@ beast_core\native\java - - - + + _meta + + + _meta + + + _meta + + + _meta + + + _meta + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast_core + + + beast\crypto\impl\sha2 + + + beast\crypto\impl\sha2 + + + scripts + @@ -149,17 +195,20 @@ {91538dcf-b219-4c80-9861-bb4949089775} - - {5df65855-1ccd-4997-97c1-f9788924ee2b} - {2f5b95a8-1adf-4319-8464-ddc2b2e03f0b} {bf498396-2e1f-4903-be68-3053ba439af5} - - {08ec13ba-4058-4ad7-afbb-cbb1c6e2fc4a} + + {c0724499-ab69-40c3-90e2-65242dbd2eaa} + + + {f7252567-a5bb-4be2-bbd0-c9d9b62298de} + + + {27052a76-e315-4725-9d9a-1233c7d71aba} {92d1bb42-289a-4444-85c7-cb87540f2fff} @@ -170,300 +219,306 @@ {5904368f-a0f2-4d26-a031-8cbe4448dc3f} - - {ac367054-ddbf-4118-a41a-07bea34d32c8} + + {5faa76ea-5691-4e63-8833-577f92991356} - - {c0724499-ab69-40c3-90e2-65242dbd2eaa} + + {93670bc9-a748-42bd-8118-8de30c468b16} - - {f7252567-a5bb-4be2-bbd0-c9d9b62298de} + + {85158eb2-9340-4b3d-a136-f7631c7f1b7c} + + + {56d34c67-7027-44ba-9f09-4591ce4afb36} + + + {775ab0d6-aa5f-43d7-ab3b-3c01652a9ef1} + + + {56ef157f-ad92-4da7-8fbf-00723f769732} + + + {565f012b-42b7-42c9-81b7-9e93aa378000} + + + {7eead15d-f9dc-4b4d-a653-57d9c090e697} + + + {233e3c4d-e398-4c11-a42c-3483107eb8e9} + + + {8d80e304-a42d-411a-9528-811eddff3191} + + + {eabf472c-e198-409a-a65b-7c087ae911d0} + + + {1fff3bd8-44ae-41df-8dd4-8bb6f07b2908} + + + {9c1ef4c4-5623-4500-859f-12d6ce5ae362} + + + {fc3d3f14-9ba1-43e4-b086-cbbd2f63b944} + + + {44489531-f44a-439a-a6ea-d32c252b1e8b} + + + {57dc7059-cbb2-437c-9c52-79825d9a4cf5} + + + {39886e0f-1607-4b7a-81cf-011d83dadee3} + + + {c65af439-8c23-46c3-9b95-7da15651e5f6} + + + {8d88283b-24ec-49ca-a94b-cb6271bc14f9} + + + {38c81e1f-f831-4632-af45-6340683f3346} + + + {7243e5e5-ad7e-4d81-8444-d545919e850c} + + + {4e9c54da-1581-41d7-ac75-48140e4a13d4} + + + {f864ff58-1055-4c56-805f-9f181c4f0aa1} + + + {386a8cd8-6be3-4cac-9bca-7a01fdb5327a} + + + {b116764e-1ad5-4854-a549-73c5beb5ae37} + + + {d7ec873a-d1e7-4341-9d20-a1be8f8ddd88} beast_core - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\json - + beast_core\logging - + beast_core\logging - + beast_core\maths - + beast_core\maths - + beast_core\maths - + beast_core\maths - - beast_core\maths - - + beast_core\memory - + beast_core\memory - + beast_core\memory - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - + beast_core\misc - + beast_core\misc - + beast_core\misc - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\network - + beast_core\network - + beast_core\network - + beast_core\network - - beast_core\network - - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\text - + beast_core\text - + beast_core\text - + beast_core\text - + beast_core\text - + beast_core\text - - beast_core\text - - - beast_core\text - - - beast_core\text - - - beast_core\text - - - beast_core\text - - - beast_core\text - - - beast_core\text - - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - + beast_core\threads - - beast_core\threads - - - beast_core\threads - - - beast_core\threads - - - beast_core\threads - - - beast_core\threads - - - beast_core\threads - - + beast_core\time - + beast_core\time - - beast_core\time - - + beast_core\xml - + beast_core\xml - + beast_core\zip - + beast_core\zip - + beast_core\zip @@ -499,98 +554,61 @@ beast_core\zip\zlib - - + beast_core\memory - + beast_core\memory - + beast_core\memory - + beast_core\memory - + beast_core\memory - + beast_core\memory - + beast_core\containers - - beast_core\containers - - + beast_core\threads - - beast_core\memory - - - beast_core\containers - - - beast_core\containers - - + beast_core\diagnostic - + beast_core\diagnostic - - beast_core\diagnostic - - - beast_core\diagnostic - - - beast_core\diagnostic - - - beast_core\diagnostic - - - beast_core\memory - - - beast_core\memory - - + beast_core\maths - - beast_core\time - - + beast_core\diagnostic - - beast_crypto\math - beast_crypto - + beast_core\containers - + beast_core\files - + beast_core\diagnostic - + beast_core\memory beast_db - + beast_db\keyvalue @@ -662,42 +680,21 @@ beast_sqdb\detail - + beast_core\maths - - beast_core\diagnostic - - - beast_core\misc - - + beast_core\text - + beast_core\diagnostic - - beast_core\diagnostic - - + beast_core\maths - - beast_core\memory - - - beast_core\memory - beast_core\diagnostic - - beast_core\threads - - - beast_core\threads - beast_core\thread @@ -719,72 +716,18 @@ beast_core\thread\impl - + beast_core\thread - + beast_core\thread - + beast_core\thread - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - + beast_core\maths - - beast_core\functional - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - beast_asio\sockets @@ -797,7 +740,7 @@ beast_asio\system - + beast_extras\traits @@ -812,51 +755,15 @@ beast_core\system - - beast_core\system - beast_core\system - - beast_core\system - - - beast_core\system - beast_core\system beast_core\system - - beast_core\system - - - beast_core\containers - - - beast_core\containers - - - beast_core\containers - - - beast_core\containers - - - beast_core\containers\detail - - - beast_core\containers\detail - - - beast_core\text - - - beast_core\text - beast\intrusive @@ -878,24 +785,9 @@ beast\mpl - - beast - beast\mpl - - beast_core\memory - - - beast_core\memory - - - beast_core\diagnostic - - - beast_asio\parsehttp - beast_asio\async @@ -986,12 +878,6 @@ beast_asio\protocol - - beast_core\functional - - - beast_asio\basics - beast_asio\http @@ -1016,228 +902,544 @@ beast_asio\http - - beast_asio\http - beast\mpl beast_asio\basics - + + beast_core\memory + + + beast_core\time + + + beast_core\misc + + + beast_core\diagnostic + + + beast_crypto\math + + + beast_crypto\math + + + beast_crypto\math + + + beast_core\memory + + + beast\net + + + beast + + + beast + + + beast + + + beast + + + beast + + + beast\type_traits + + + beast\type_traits + + + beast\type_traits + + + beast\type_traits + + + beast\utility + + + beast\utility + + + beast + + + beast\mpl + + + beast + + + beast_asio\http + + + beast_asio\async + + beast_asio\basics + + beast + + + beast + + + beast\intrusive + + + beast\intrusive + + + beast\mpl + + + beast\http\impl\http-parser + + + beast + + + beast\strings + + + beast\strings + + + beast\strings + + + beast\strings + + + beast\strings + + + beast\strings + + + beast\strings + + + beast\strings + + + beast\strings + + + beast + + + beast\config + + + beast\config + + + beast\config + + + beast + + + beast\config + + + beast\config + + + beast + + + beast + + + beast + + + beast + + + beast + + + beast_core\system + + + beast\http + + + beast\http + + + beast + + + beast\intrusive + + + beast + + + beast\crypto\impl\sha2 + + + beast\crypto + + + beast_asio\async + + + beast_asio\async + + + beast + + + beast\chrono + + + beast + + + + beast\utility + + + beast\utility + + + beast\config\compiler + + + beast\config\compiler + + + beast\config\compiler + + + beast\config\compiler + + + beast\config\platform + + + beast\config\platform + + + beast\config\platform + + + beast\config\platform + + + beast\config\platform + + + beast\config + + + beast\config + + + beast\config + + + beast\smart_ptr + + + beast\smart_ptr + + + beast + + + beast\net + + + beast\net + + + beast_asio\http + + + beast_asio\http + + + beast\chrono + + + beast\chrono + + + beast\smart_ptr + + + beast\smart_ptr + + + beast + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\threads + + + beast\utility + + + beast\utility + + + beast\threads + + + beast\threads\detail + + + beast\threads\detail + + + beast\boost + + + beast + + + beast\utility + + + beast\threads + + + beast\utility + - - beast_core - - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\containers - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\files - + beast_core\json - + beast_core\logging - + beast_core\logging - + beast_core\maths - + beast_core\maths - + beast_core\maths - + beast_core\memory - + beast_core\misc - + beast_core\misc - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\network - + beast_core\network - + beast_core\network - + beast_core\network - - beast_core\network - - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\streams - + beast_core\text - + beast_core\text - + beast_core\text - + beast_core\text - + beast_core\text - + beast_core\text - - beast_core\text - - - beast_core\text - - + beast_core\threads - + beast_core\threads - + beast_core\threads - - beast_core\threads - - - beast_core\threads - - - beast_core\threads - - + beast_core\time - + beast_core\time - - beast_core\time - - + beast_core\xml - + beast_core\xml - + beast_core\zip - + beast_core\zip - + beast_core\zip @@ -1273,61 +1475,43 @@ beast_core\zip\zlib - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\native - + beast_core\diagnostic - - beast_core\diagnostic - - - beast_core\diagnostic - - - beast_core\diagnostic - - + beast_core\threads - + beast_core\native - + beast_core\native - - beast_core\time - - + beast_core\diagnostic - - beast_crypto - - - beast_crypto\math - - + beast_core\files - + beast_core\diagnostic beast_db - + beast_db\keyvalue @@ -1375,102 +1559,36 @@ beast_sqdb\source - + beast_core\maths - - beast_core\diagnostic - - - beast_core\misc - - + beast_core\text - + beast_core\diagnostic - - beast_core\diagnostic - - - beast_asio - - - beast_core\threads - beast_core\thread\impl - + beast_core\thread - + beast_core\thread - + beast_core\thread - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\thread - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - - - beast_core\memory - beast_asio\basics - - beast_extras - beast_core\system beast_core\system - - beast_core\containers - - - beast_core\containers - - - beast_core\containers - - - beast_asio\parsehttp - beast_asio\async @@ -1516,9 +1634,6 @@ beast_asio\protocol - - beast_asio\basics - beast_asio\http @@ -1540,11 +1655,160 @@ beast_asio\http - + + beast_crypto + + + beast_core + + + beast_asio + + + beast_core\time + + + beast_core\misc + + + beast_core\diagnostic + + + beast_crypto\math + + + beast_crypto\math + + + beast_extras + + + beast\net\impl + + + beast\net + + + beast\utility + + + beast\utility\impl + + beast_asio\http + + beast\http\impl\http-parser + + + beast\http\impl\http-parser + + + beast\http\impl\http-parser\contrib + + + beast\http\impl\http-parser\contrib + + + beast\http + + + beast\http\impl + + + beast\strings\impl + + + beast\strings\impl + + + beast\strings + + + beast\http\impl + + + beast\http\impl + + + beast\crypto\impl\sha2 + + + beast\crypto\impl\sha2 + + + beast\crypto\impl\sha2 + + + beast\crypto + + + beast\crypto\impl + + + beast\chrono\impl + + + beast\chrono + + + beast\utility\impl + + + beast\utility\impl + + + beast\net\impl + + + beast_asio\http + + + beast_asio\http + + + beast\chrono\impl + + + beast\smart_ptr + + + beast\threads\impl + + + beast\threads\impl + + + beast\threads\impl + + + beast\threads\impl + + + beast\threads + + + beast\threads\impl + + + beast\utility\impl + + + beast\utility\impl + + + beast\threads\impl + + + beast\boost + + + beast\utility\impl + - + + _meta + \ No newline at end of file diff --git a/LICENSE_1_0.txt b/LICENSE_1_0.txt new file mode 100644 index 0000000000..36b7cd93cd --- /dev/null +++ b/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/TODO.txt b/TODO.txt index bf1437e8e0..965d1721e4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,10 +2,6 @@ BEAST TODO -------------------------------------------------------------------------------- -- Use new file naming convention - -- Rename ReadWriteMutex to SharedMutex - - Use SemanticVersion for beast version numbers to replace BEAST_VERSION - add support for a __PRETTY_FUNCTION__ equivalent for all environments @@ -14,13 +10,6 @@ BEAST TODO - Import secp256k1 from sipa -- HashMap work: - - Add unit test - - Return size_t from hash function, take out upperLimit, move mod % to caller - - Make hash function a functor using operator() - - Implement HardenedHashFunctions - - Fix problem with assigning to the result of operator[] maybe use a proxy? - - Set sqlite thread safety model to '2' in beast_sqlite - Document and rename all the sqdb files and classes @@ -57,8 +46,6 @@ BEAST TODO - Rename malloc/calloc JUCE members that conflict with the debug CRT from MSVC -- Make beast::HashMap support assignment via operator[] - - Reformat every Doxygen comment - Fix Doxygen metatags - update Beast Doxyfile diff --git a/modules/beast_core/maths/beast_MathsFunctions.h b/beast/Arithmetic.h similarity index 79% rename from modules/beast_core/maths/beast_MathsFunctions.h rename to beast/Arithmetic.h index 6532951c4b..8aba10345d 100644 --- a/modules/beast_core/maths/beast_MathsFunctions.h +++ b/beast/Arithmetic.h @@ -21,104 +21,48 @@ */ //============================================================================== -#ifndef BEAST_MATHSFUNCTIONS_H_INCLUDED -#define BEAST_MATHSFUNCTIONS_H_INCLUDED +#ifndef BEAST_ARITHMETIC_H_INCLUDED +#define BEAST_ARITHMETIC_H_INCLUDED -//============================================================================== -/* - This file sets up some handy mathematical typdefs and functions. -*/ +#include "Config.h" +#include "CStdInt.h" -//============================================================================== -// Definitions for the int8, int16, int32, int64 and pointer_sized_int types. +#include +#include -/** A platform-independent 8-bit signed integer type. */ -typedef signed char int8; -/** A platform-independent 8-bit unsigned integer type. */ -typedef unsigned char uint8; -/** A platform-independent 16-bit signed integer type. */ -typedef signed short int16; -/** A platform-independent 16-bit unsigned integer type. */ -typedef unsigned short uint16; -/** A platform-independent 32-bit signed integer type. */ -typedef signed int int32; -/** A platform-independent 32-bit unsigned integer type. */ -typedef unsigned int uint32; +namespace beast { -#if BEAST_MSVC - /** A platform-independent 64-bit integer type. */ - typedef __int64 int64; - /** A platform-independent 64-bit unsigned integer type. */ - typedef unsigned __int64 uint64; - /** A platform-independent macro for writing 64-bit literals, needed because - different compilers have different syntaxes for this. - - E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for - GCC, or 0x1000000000 for MSVC. - */ - #define literal64bit(longLiteral) ((__int64) longLiteral) -#else - /** A platform-independent 64-bit integer type. */ - typedef long long int64; - /** A platform-independent 64-bit unsigned integer type. */ - typedef unsigned long long uint64; - /** A platform-independent macro for writing 64-bit literals, needed because - different compilers have different syntaxes for this. - - E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for - GCC, or 0x1000000000 for MSVC. - */ - #define literal64bit(longLiteral) (longLiteral##LL) -#endif - - -#if BEAST_64BIT - /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef int64 pointer_sized_int; - /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef uint64 pointer_sized_uint; -#elif BEAST_MSVC - /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef _W64 int pointer_sized_int; - /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef _W64 unsigned int pointer_sized_uint; -#else - /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef int pointer_sized_int; - /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ - typedef unsigned int pointer_sized_uint; -#endif - -#if BEAST_MSVC - typedef pointer_sized_int ssize_t; -#endif - -//============================================================================== // Some indispensible min/max functions /** Returns the larger of two values. */ template -inline Type bmax (const Type a, const Type b) { return (a < b) ? b : a; } +inline Type bmax (const Type a, const Type b) + { return (a < b) ? b : a; } /** Returns the larger of three values. */ template -inline Type bmax (const Type a, const Type b, const Type c) { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } +inline Type bmax (const Type a, const Type b, const Type c) + { return (a < b) ? ((b < c) ? c : b) : ((a < c) ? c : a); } /** Returns the larger of four values. */ template -inline Type bmax (const Type a, const Type b, const Type c, const Type d) { return bmax (a, bmax (b, c, d)); } +inline Type bmax (const Type a, const Type b, const Type c, const Type d) + { return bmax (a, bmax (b, c, d)); } /** Returns the smaller of two values. */ template -inline Type bmin (const Type a, const Type b) { return (b < a) ? b : a; } +inline Type bmin (const Type a, const Type b) + { return (b < a) ? b : a; } /** Returns the smaller of three values. */ template -inline Type bmin (const Type a, const Type b, const Type c) { return (b < a) ? ((c < b) ? c : b) : ((c < a) ? c : a); } +inline Type bmin (const Type a, const Type b, const Type c) + { return (b < a) ? ((c < b) ? c : b) : ((c < a) ? c : a); } /** Returns the smaller of four values. */ template -inline Type bmin (const Type a, const Type b, const Type c, const Type d) { return bmin (a, bmin (b, c, d)); } +inline Type bmin (const Type a, const Type b, const Type c, const Type d) + { return bmin (a, bmin (b, c, d)); } /** Scans an array of values, returning the minimum value that it contains. */ template @@ -183,7 +127,6 @@ void findMinAndMax (const Type* values, int numValues, Type& lowest, Type& highe } } - //============================================================================== /** Constrains a value to keep it within a given range. @@ -268,7 +211,7 @@ inline void swapVariables (Type& variable1, Type& variable2) @endcode */ template -inline int numElementsInArray (Type (&array)[N]) +int numElementsInArray (Type (&array)[N]) { (void) array; // (required to avoid a spurious warning in MS compilers) (void) sizeof (0[array]); // This line should cause an error if you pass an object with a user-defined subscript operator @@ -509,7 +452,7 @@ namespace TypeHelpers template <> struct SmallestFloatType { typedef double type; }; } +} -//============================================================================== +#endif -#endif // BEAST_MATHSFUNCTIONS_H_INCLUDED diff --git a/modules/beast_core/memory/beast_Atomic.h b/beast/Atomic.h similarity index 97% rename from modules/beast_core/memory/beast_Atomic.h rename to beast/Atomic.h index 9fcc92fcfa..cd54d75ad0 100644 --- a/modules/beast_core/memory/beast_Atomic.h +++ b/beast/Atomic.h @@ -24,6 +24,11 @@ #ifndef BEAST_ATOMIC_H_INCLUDED #define BEAST_ATOMIC_H_INCLUDED +#include "Config.h" +#include "CStdInt.h" +#include "StaticAssert.h" + +namespace beast { //============================================================================== /** @@ -65,13 +70,16 @@ public: Type get() const noexcept; /** Copies another value onto this one (atomically). */ - inline Atomic& operator= (const Atomic& other) noexcept { exchange (other.get()); return *this; } + Atomic& operator= (const Atomic& other) noexcept + { exchange (other.get()); return *this; } /** Copies another value onto this one (atomically). */ - inline Atomic& operator= (const Type newValue) noexcept { exchange (newValue); return *this; } + Atomic& operator= (const Type newValue) noexcept + { exchange (newValue); return *this; } /** Atomically sets the current value. */ - void set (Type newValue) noexcept { exchange (newValue); } + void set (Type newValue) noexcept + { exchange (newValue); } /** Atomically sets the current value, returning the value that was replaced. */ Type exchange (Type value) noexcept; @@ -131,9 +139,6 @@ public: */ Type compareAndSetValue (Type newValue, Type valueToCompare) noexcept; - /** Implements a memory read/write barrier. */ - static void memoryBarrier() noexcept; - //============================================================================== #if BEAST_64BIT BEAST_ALIGN (8) @@ -373,8 +378,7 @@ inline Type Atomic::compareAndSetValue (const Type newValue, const Type va #endif } -template -inline void Atomic::memoryBarrier() noexcept +inline void memoryBarrier() noexcept { #if BEAST_ATOMICS_MAC OSMemoryBarrier(); @@ -389,4 +393,6 @@ inline void Atomic::memoryBarrier() noexcept #pragma warning (pop) #endif -#endif // BEAST_ATOMIC_H_INCLUDED +} + +#endif diff --git a/beast/Boost.h b/beast/Boost.h new file mode 100644 index 0000000000..295eca5a58 --- /dev/null +++ b/beast/Boost.h @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_BOOST_H_INCLUDED +#define BEAST_BOOST_H_INCLUDED + +// These classes require boost in order to be used. + +#include "boost/ErrorCode.h" + +#endif diff --git a/modules/beast_core/memory/beast_ByteOrder.h b/beast/ByteOrder.h similarity index 78% rename from modules/beast_core/memory/beast_ByteOrder.h rename to beast/ByteOrder.h index 191de0d943..0e40616e7d 100644 --- a/modules/beast_core/memory/beast_ByteOrder.h +++ b/beast/ByteOrder.h @@ -24,11 +24,17 @@ #ifndef BEAST_BYTEORDER_H_INCLUDED #define BEAST_BYTEORDER_H_INCLUDED +#include "Config.h" +#include "CStdInt.h" +#include "Uncopyable.h" + +namespace beast { + //============================================================================== /** Contains static methods for converting the byte order between different endiannesses. */ -class BEAST_API ByteOrder : public Uncopyable +class ByteOrder : public Uncopyable { public: //============================================================================== @@ -182,5 +188,109 @@ inline int ByteOrder::bigEndian24Bit (const char* const bytes) inline void ByteOrder::littleEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destBytes) { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } -#endif +namespace detail +{ +/** Specialized helper class template for swapping bytes. + + Normally you won't use this directly, use the helper function + byteSwap instead. You can specialize this class for your + own user defined types, as was done for uint24. + + @see swapBytes, uint24 +*/ +template +struct SwapBytes +{ + inline IntegralType operator() (IntegralType value) const noexcept + { + return ByteOrder::swap (value); + } +}; + +// Specializations for signed integers + +template <> +struct SwapBytes +{ + inline int16 operator() (int16 value) const noexcept + { + return static_cast (ByteOrder::swap (static_cast (value))); + } +}; + +template <> +struct SwapBytes +{ + inline int32 operator() (int32 value) const noexcept + { + return static_cast (ByteOrder::swap (static_cast (value))); + } +}; + +template <> +struct SwapBytes +{ + inline int64 operator() (int64 value) const noexcept + { + return static_cast (ByteOrder::swap (static_cast (value))); + } +}; + +} + +//------------------------------------------------------------------------------ + +/** Returns a type with the bytes swapped. + Little endian becomes big endian and vice versa. The underlying + type must be an integral type or behave like one. +*/ +template +inline IntegralType swapBytes (IntegralType value) noexcept +{ + return detail::SwapBytes () (value); +} + +/** Returns the machine byte-order value to little-endian byte order. */ +template +inline IntegralType toLittleEndian (IntegralType value) noexcept +{ +#if BEAST_LITTLE_ENDIAN + return value; +#else + return swapBytes (value); +#endif +} + +/** Returns the machine byte-order value to big-endian byte order. */ +template +inline IntegralType toBigEndian (IntegralType value) noexcept +{ +#if BEAST_LITTLE_ENDIAN + return swapBytes (value); +#else + return value; +#endif +} + +/** Returns the machine byte-order value to network byte order. */ +template +inline IntegralType toNetworkByteOrder (IntegralType value) noexcept +{ + return toBigEndian (value); +} + +/** Converts from network byte order to machine byte order. */ +template +inline IntegralType fromNetworkByteOrder (IntegralType value) noexcept +{ +#if BEAST_LITTLE_ENDIAN + return swapBytes (value); +#else + return value; +#endif +} + +} + +#endif diff --git a/beast/CStdInt.h b/beast/CStdInt.h new file mode 100644 index 0000000000..265f3d9f19 --- /dev/null +++ b/beast/CStdInt.h @@ -0,0 +1,88 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CSTDINT_H_INCLUDED +#define BEAST_CSTDINT_H_INCLUDED + +#include "Config.h" + +namespace beast { + +typedef signed char int8; +typedef signed short int16; +typedef signed int int32; +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; + +#if BEAST_MSVC + typedef __int64 int64; + typedef unsigned __int64 uint64; + + /** A platform-independent macro for writing 64-bit literals, needed because + different compilers have different syntaxes for this. + + E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for + GCC, or 0x1000000000 for MSVC. + */ + #define literal64bit(longLiteral) ((__int64) longLiteral) + +#else + /** A platform-independent 64-bit integer type. */ + typedef long long int64; + /** A platform-independent 64-bit unsigned integer type. */ + typedef unsigned long long uint64; + /** A platform-independent macro for writing 64-bit literals, needed because + different compilers have different syntaxes for this. + + E.g. writing literal64bit (0x1000000000) will translate to 0x1000000000LL for + GCC, or 0x1000000000 for MSVC. + */ + #define literal64bit(longLiteral) (longLiteral##LL) + +#endif + +#if BEAST_64BIT + /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ + typedef int64 pointer_sized_int; + /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ + typedef uint64 pointer_sized_uint; +#elif BEAST_MSVC + /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ + typedef _W64 int pointer_sized_int; + /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ + typedef _W64 unsigned int pointer_sized_uint; +#else + /** A signed integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ + typedef int pointer_sized_int; + /** An unsigned integer type that's guaranteed to be large enough to hold a pointer without truncating it. */ + typedef unsigned int pointer_sized_uint; +#endif + +#if BEAST_MSVC + typedef pointer_sized_int ssize_t; +#endif + +} + +#endif diff --git a/beast/Chrono.h b/beast/Chrono.h new file mode 100644 index 0000000000..027b1f5f32 --- /dev/null +++ b/beast/Chrono.h @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CHRONO_H_INCLUDED +#define BEAST_CHRONO_H_INCLUDED + +#include "chrono/CPUMeter.h" +#include "chrono/RelativeTime.h" +#include "chrono/ScopedTimeInterval.h" + +#endif diff --git a/beast/Config.h b/beast/Config.h new file mode 100644 index 0000000000..32164e7103 --- /dev/null +++ b/beast/Config.h @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CONFIG_H_INCLUDED +#define BEAST_CONFIG_H_INCLUDED + +// VFALCO NOTE this is analogous to + +#if !defined(BEAST_COMPILER_CONFIG) && !defined(BEAST_NO_COMPILER_CONFIG) && !defined(BEAST_NO_CONFIG) +#include "config/SelectCompilerConfig.h" +#endif +#ifdef BEAST_COMPILER_CONFIG +#include BEAST_COMPILER_CONFIG +#endif + +#if !defined(BEAST_STDLIB_CONFIG) && !defined(BEAST_NO_STDLIB_CONFIG) && !defined(BEAST_NO_CONFIG) && defined(__cplusplus) +#include "config/SelectStdlibConfig.h" +#endif +#ifdef BEAST_STDLIB_CONFIG +#include BEAST_STDLIB_CONFIG +#endif + +#if !defined(BEAST_PLATFORM_CONFIG) && !defined(BEAST_NO_PLATFORM_CONFIG) && !defined(BEAST_NO_CONFIG) +#include "config/SelectCompilerConfig.h" +#endif +#ifdef BEAST_PLATFORM_CONFIG +#include BEAST_PLATFORM_CONFIG +#endif + +// Legacy +#include "Version.h" +#include "config/PlatformConfig.h" +#include "config/CompilerConfig.h" +#include "config/StandardConfig.h" +#include "config/ConfigCheck.h" + +// Suffix +#include "config/Suffix.h" + +#endif diff --git a/beast/Crypto.h b/beast/Crypto.h new file mode 100644 index 0000000000..50d8204661 --- /dev/null +++ b/beast/Crypto.h @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CRYPTO_H_INCLUDED +#define BEAST_CRYPTO_H_INCLUDED + +#include "crypto/Sha256.h" + +#endif + diff --git a/beast/FixedArray.h b/beast/FixedArray.h new file mode 100644 index 0000000000..e9d50488af --- /dev/null +++ b/beast/FixedArray.h @@ -0,0 +1,165 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_FIXEDARRAY_H_INCLUDED +#define BEAST_FIXEDARRAY_H_INCLUDED + +#include "Config.h" + +#include +#include +#include + +namespace beast { + +// Ideas from Boost + +/** An array whose size is determined at compile-time. + The interface tries to follow std::vector as closely as possible within + the limitations of having a fixed size. +*/ +template +class FixedArray +{ +public: + T values [N]; + + typedef T value_type; + typedef T* iterator; + typedef T const* const_iterator; + typedef T& reference; + typedef T const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterators + iterator begin() { return values; } + const_iterator begin() const { return values; } + const_iterator cbegin() const { return values; } + iterator end() { return values+N; } + const_iterator end() const { return values+N; } + const_iterator cend() const { return values+N; } + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } + + reference operator[](size_type i) + { + bassert (i < N); + return values[i]; + } + + const_reference operator[](size_type i) const + { + bassert (i < N); + return values[i]; + } + + reference at(size_type i) { rangecheck(i); return values[i]; } + const_reference at(size_type i) const { rangecheck(i); return values[i]; } + + reference front() { return values[0]; } + reference back() { return values[N-1]; } + const_reference front () const { return values[0]; } + const_reference back() const { return values[N-1]; } + + static size_type size() { return N; } + static bool empty() { return false; } + static size_type max_size() { return N; } + + enum { static_size = N }; + + T const* data() const { return values; } + T* data() { return values; } + T* c_array() { return values; } + + template + FixedArray& operator= (FixedArray const& rhs) + { + std::copy (rhs.begin(), rhs.end(), begin()); + return *this; + } + + void assign (T const& value) { fill (value); } + + void fill (T const& value) + { + std::fill_n (begin(), size(), value); + } + + void clear () + { + fill (T ()); + } + + static void rangecheck (size_type i) + { + if (i >= size()) + throw std::out_of_range ("FixedArray<>: index out of range"); + } +}; + +//------------------------------------------------------------------------------ + +template +bool operator== (FixedArray const& lhs, FixedArray const& rhs) +{ + return std::equal (lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator!= (FixedArray const& lhs, FixedArray const& rhs) +{ + return !(lhs==rhs); +} + +template +bool operator< (FixedArray const& lhs, FixedArray const& rhs) +{ + return std::lexicographical_compare (lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +template +bool operator> (FixedArray const& lhs, FixedArray const& rhs) +{ + return rhs +bool operator<= (FixedArray const& lhs, FixedArray const& rhs) +{ + return !(rhs +bool operator>= (FixedArray const& lhs, FixedArray const& rhs) +{ + return !(lhs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HTTP_H_INCLUDED +#define BEAST_HTTP_H_INCLUDED + +#include "http/URL.h" +#include "http/ParsedURL.h" + +#endif diff --git a/modules/beast_core/memory/beast_HeapBlock.h b/beast/HeapBlock.h similarity index 88% rename from modules/beast_core/memory/beast_HeapBlock.h rename to beast/HeapBlock.h index 8d4dfc92f8..875dae0e47 100644 --- a/modules/beast_core/memory/beast_HeapBlock.h +++ b/beast/HeapBlock.h @@ -24,6 +24,46 @@ #ifndef BEAST_HEAPBLOCK_H_INCLUDED #define BEAST_HEAPBLOCK_H_INCLUDED +#include +#include +#include + +#include "Memory.h" +#include "Uncopyable.h" + +// If the MSVC debug heap headers were included, disable +// the macros during the juce include since they conflict. +#ifdef _CRTDBG_MAP_ALLOC +#pragma push_macro("calloc") +#pragma push_macro("free") +#pragma push_macro("malloc") +#pragma push_macro("realloc") +#pragma push_macro("_recalloc") +#pragma push_macro("_aligned_free") +#pragma push_macro("_aligned_malloc") +#pragma push_macro("_aligned_offset_malloc") +#pragma push_macro("_aligned_realloc") +#pragma push_macro("_aligned_recalloc") +#pragma push_macro("_aligned_offset_realloc") +#pragma push_macro("_aligned_offset_recalloc") +#pragma push_macro("_aligned_msize") +#undef calloc +#undef free +#undef malloc +#undef realloc +#undef _recalloc +#undef _aligned_free +#undef _aligned_malloc +#undef _aligned_offset_malloc +#undef _aligned_realloc +#undef _aligned_recalloc +#undef _aligned_offset_realloc +#undef _aligned_offset_recalloc +#undef _aligned_msize +#endif + +namespace beast { + #ifndef DOXYGEN namespace HeapBlockHelper { @@ -305,5 +345,23 @@ private: #endif }; +} + +#ifdef _CRTDBG_MAP_ALLOC +#pragma pop_macro("_aligned_msize") +#pragma pop_macro("_aligned_offset_recalloc") +#pragma pop_macro("_aligned_offset_realloc") +#pragma pop_macro("_aligned_recalloc") +#pragma pop_macro("_aligned_realloc") +#pragma pop_macro("_aligned_offset_malloc") +#pragma pop_macro("_aligned_malloc") +#pragma pop_macro("_aligned_free") +#pragma pop_macro("_recalloc") +#pragma pop_macro("realloc") +#pragma pop_macro("malloc") +#pragma pop_macro("free") +#pragma pop_macro("calloc") +#endif + +#endif -#endif // BEAST_HEAPBLOCK_H_INCLUDED diff --git a/beast/Intrusive.h b/beast/Intrusive.h new file mode 100644 index 0000000000..065b92c9dd --- /dev/null +++ b/beast/Intrusive.h @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INTRUSIVE_H_INCLUDED +#define BEAST_INTRUSIVE_H_INCLUDED + +#include "intrusive/ForwardList.h" +#include "intrusive/IntrusiveArray.h" +#include "intrusive/List.h" +#include "intrusive/LockFreeStack.h" + +#endif diff --git a/beast/mpl.h b/beast/MPL.h similarity index 95% rename from beast/mpl.h rename to beast/MPL.h index 051931e688..3be24c673a 100644 --- a/beast/mpl.h +++ b/beast/MPL.h @@ -21,7 +21,9 @@ #define BEAST_MPL_H_INCLUDED #include "mpl/AddConst.h" +#include "mpl/CopyConst.h" #include "mpl/IfCond.h" +#include "mpl/IsCallPossible.h" #include "mpl/PointerToOther.h" #include "mpl/RemoveConst.h" #include "mpl/RemoveConstVolatile.h" diff --git a/modules/beast_core/memory/beast_Memory.h b/beast/Memory.h similarity index 86% rename from modules/beast_core/memory/beast_Memory.h rename to beast/Memory.h index b67ec0cd7a..538e82e5a0 100644 --- a/modules/beast_core/memory/beast_Memory.h +++ b/beast/Memory.h @@ -24,13 +24,21 @@ #ifndef BEAST_MEMORY_H_INCLUDED #define BEAST_MEMORY_H_INCLUDED +#include + +#include "Config.h" + +namespace beast { + //============================================================================== /** Fills a block of memory with zeros. */ -inline void zeromem (void* memory, size_t numBytes) noexcept { memset (memory, 0, numBytes); } +inline void zeromem (void* memory, size_t numBytes) noexcept + { memset (memory, 0, numBytes); } /** Overwrites a structure or object with zeros. */ template -inline void zerostruct (Type& structure) noexcept { memset (&structure, 0, sizeof (structure)); } +void zerostruct (Type& structure) noexcept + { memset (&structure, 0, sizeof (structure)); } /** Delete an object pointer, and sets the pointer to null. @@ -38,26 +46,30 @@ inline void zerostruct (Type& structure) noexcept { memset (&s or other automatic lifetime-management system rather than resorting to deleting raw pointers! */ template -inline void deleteAndZero (Type& pointer) { delete pointer; pointer = nullptr; } +void deleteAndZero (Type& pointer) + { delete pointer; pointer = nullptr; } /** A handy function which adds a number of bytes to any type of pointer and returns the result. This can be useful to avoid casting pointers to a char* and back when you want to move them by a specific number of bytes, */ template -inline Type* addBytesToPointer (Type* pointer, IntegerType bytes) noexcept { return (Type*) (((char*) pointer) + bytes); } +Type* addBytesToPointer (Type* pointer, IntegerType bytes) noexcept + { return (Type*) (((char*) pointer) + bytes); } /** A handy function which returns the difference between any two pointers, in bytes. The address of the second pointer is subtracted from the first, and the difference in bytes is returned. */ template -inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { return (int) (((const char*) pointer1) - (const char*) pointer2); } +int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept + { return (int) (((const char*) pointer1) - (const char*) pointer2); } /** If a pointer is non-null, this returns a new copy of the object that it points to, or safely returns nullptr if the pointer is null. */ template -inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != nullptr ? new Type (*pointer) : nullptr; } +Type* createCopyIfNotNull (const Type* pointer) + { return pointer != nullptr ? new Type (*pointer) : nullptr; } //============================================================================== #if BEAST_MAC || BEAST_IOS || DOXYGEN @@ -90,5 +102,7 @@ inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != n #define BEAST_AUTORELEASEPOOL #endif +} + #endif diff --git a/beast/Net.h b/beast/Net.h new file mode 100644 index 0000000000..091c940f05 --- /dev/null +++ b/beast/Net.h @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_NET_H_INCLUDED +#define BEAST_NET_H_INCLUDED + +#include "net/BufferType.h" +#include "net/DynamicBuffer.h" + +#include "net/IPEndpoint.h" + +#endif diff --git a/modules/beast_core/diagnostic/beast_SafeBool.h b/beast/SafeBool.h similarity index 93% rename from modules/beast_core/diagnostic/beast_SafeBool.h rename to beast/SafeBool.h index 1b6dfad0e3..fbae195923 100644 --- a/modules/beast_core/diagnostic/beast_SafeBool.h +++ b/beast/SafeBool.h @@ -20,23 +20,11 @@ #ifndef BEAST_SAFEBOOL_H_INCLUDED #define BEAST_SAFEBOOL_H_INCLUDED -/** Safe evaluation of class as `bool`. +namespace beast { - This allows a class to be safely evaluated as a bool without the usual - harmful side effects of the straightforward operator conversion approach. - To use it, derive your class from SafeBool and implement `asBoolean()` as: +namespace detail { - @code - - bool asBoolean () const; - - @endcode - - Ideas from http://www.artima.com/cppsource/safebool.html - - @class SafeBool -*/ -class BEAST_API SafeBoolBase +class SafeBoolBase { private: void disallowed () const { } @@ -56,11 +44,29 @@ protected: ~SafeBoolBase () { } }; +} + +/** Safe evaluation of class as `bool`. + + This allows a class to be safely evaluated as a bool without the usual + harmful side effects of the straightforward operator conversion approach. + To use it, derive your class from SafeBool and implement `asBoolean()` as: + + @code + + bool asBoolean () const; + + @endcode + + Ideas from http://www.artima.com/cppsource/safebool.html + + @class SafeBool +*/ template -class SafeBool : public SafeBoolBase +class SafeBool : public detail::SafeBoolBase { public: - operator boolean_t () const + operator detail::SafeBoolBase::boolean_t () const { return (static_cast (this))->asBoolean () ? &SafeBoolBase::allowed : 0; @@ -82,6 +88,8 @@ void operator!= (SafeBool const& lhs, SafeBool const& rhs) lhs.disallowed (); } +} + #endif diff --git a/beast/SmartPtr.h b/beast/SmartPtr.h new file mode 100644 index 0000000000..13aab726a8 --- /dev/null +++ b/beast/SmartPtr.h @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_SMARTPTR_H_INCLUDED +#define BEAST_SMARTPTR_H_INCLUDED + +#include "Config.h" + +#include "smart_ptr/ContainerDeletePolicy.h" +#include "smart_ptr/SharedObject.h" +#include "smart_ptr/SharedPtr.h" +#include "smart_ptr/ScopedPointer.h" + +#endif diff --git a/modules/beast_core/thread/beast_GlobalThreadGroup.h b/beast/StaticAssert.h similarity index 62% rename from modules/beast_core/thread/beast_GlobalThreadGroup.h rename to beast/StaticAssert.h index 689b258b9c..1c36d0bd1c 100644 --- a/modules/beast_core/thread/beast_GlobalThreadGroup.h +++ b/beast/StaticAssert.h @@ -17,33 +17,29 @@ */ //============================================================================== -#ifndef BEAST_GLOBALTHREADGROUP_H_INCLUDED -#define BEAST_GLOBALTHREADGROUP_H_INCLUDED +#ifndef BEAST_STATICASSERT_H_INCLUDED +#define BEAST_STATICASSERT_H_INCLUDED -/*============================================================================*/ -/** - A ThreadGroup singleton. - - @see ThreadGroup - - @ingroup beast_concurrent -*/ -class BEAST_API GlobalThreadGroup : public ThreadGroup, - public SharedSingleton +#ifndef DOXYGEN +namespace beast { -private: - friend class SharedSingleton ; + template + struct BeastStaticAssert; - GlobalThreadGroup () - : SharedSingleton ( - SingletonLifetime::persistAfterCreation) + template <> + struct BeastStaticAssert { - } + static void dummy() {} + }; +} +#endif - static GlobalThreadGroup* createInstance () - { - return new GlobalThreadGroup; - } -}; +/** A compile-time assertion macro. + If the expression parameter is false, the macro will cause a compile error. + (The actual error message that the compiler generates may be completely + bizarre and seem to have no relation to the place where you put the + static_assert though!) +*/ +#define static_bassert(expression) beast::BeastStaticAssert::dummy(); #endif diff --git a/beast/Strings.h b/beast/Strings.h new file mode 100644 index 0000000000..5b76162400 --- /dev/null +++ b/beast/Strings.h @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_STRINGS_H_INCLUDED +#define BEAST_STRINGS_H_INCLUDED + +#include "strings/String.h" +#include "strings/NewLine.h" + +#endif + diff --git a/modules/beast_core/memory/beast_FifoFreeStore.h b/beast/Threads.h similarity index 67% rename from modules/beast_core/memory/beast_FifoFreeStore.h rename to beast/Threads.h index 1acbbf79d9..6c3859d9a6 100644 --- a/modules/beast_core/memory/beast_FifoFreeStore.h +++ b/beast/Threads.h @@ -17,22 +17,21 @@ */ //============================================================================== -#ifndef BEAST_FIFOFREESTORE_H_INCLUDED -#define BEAST_FIFOFREESTORE_H_INCLUDED +#ifndef BEAST_THREADS_H_INCLUDED +#define BEAST_THREADS_H_INCLUDED -/** Selected free store based on compilation settings. - - @ingroup beast_concurrent -*/ -// VFALCO NOTE Disabled this because it seems that the TLS -// implementation has a leak. Although the other -// one also seems to have a leak. -// -//#if BEAST_USE_BOOST_FEATURES -#if 0 -typedef FifoFreeStoreWithTLS FifoFreeStoreType; -#else -typedef FifoFreeStoreWithoutTLS FifoFreeStoreType; -#endif +#include "threads/LockGuard.h" +#include "threads/UnlockGuard.h" +#include "threads/TryLockGuard.h" +#include "threads/SharedLockGuard.h" +#include "threads/SharedMutexAdapter.h" +#include "threads/SharedData.h" +#include "threads/ServiceQueue.h" +#include "threads/SpinLock.h" +#include "threads/Stoppable.h" +#include "threads/Thread.h" +#include "threads/ThreadLocalValue.h" +#include "threads/WaitableEvent.h" +#include "threads/ScopedWrapperContext.h" #endif diff --git a/beast/TypeTraits.h b/beast/TypeTraits.h new file mode 100644 index 0000000000..6af5fedc1a --- /dev/null +++ b/beast/TypeTraits.h @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_TYPETRAITS_H_INCLUDED +#define BEAST_TYPETRAITS_H_INCLUDED + +#include "type_traits/IntegralConstant.h" +#include "type_traits/IsIntegral.h" +#include "type_traits/IsSigned.h" +#include "type_traits/RemoveSigned.h" + +#endif diff --git a/modules/beast_core/memory/beast_Uncopyable.h b/beast/Uncopyable.h similarity index 95% rename from modules/beast_core/memory/beast_Uncopyable.h rename to beast/Uncopyable.h index 0ddf154c4e..20a41770ba 100644 --- a/modules/beast_core/memory/beast_Uncopyable.h +++ b/beast/Uncopyable.h @@ -20,6 +20,11 @@ #ifndef BEAST_UNCOPYABLE_H_INCLUDED #define BEAST_UNCOPYABLE_H_INCLUDED +namespace beast +{ + +// Ideas from boost + /** Prevent copy construction and assignment. This is used to suppress warnings and prevent unsafe operations on @@ -59,12 +64,14 @@ class Uncopyable { protected: - inline Uncopyable () { } - inline ~Uncopyable () { } + Uncopyable () { } + ~Uncopyable () { } private: Uncopyable (Uncopyable const&); Uncopyable const& operator= (Uncopyable const&); }; +} + #endif diff --git a/beast/Utility.h b/beast/Utility.h new file mode 100644 index 0000000000..b7cd0854ce --- /dev/null +++ b/beast/Utility.h @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_H_INCLUDED +#define BEAST_UTILITY_H_INCLUDED + +#include "utility/BaseFromMember.h" +#include "utility/Debug.h" +#include "utility/EnableIf.h" +#include "utility/Error.h" +#include "utility/Journal.h" +#include "utility/LeakChecked.h" +#include "utility/PropertyStream.h" +#include "utility/StaticObject.h" + +#endif + diff --git a/beast/Version.h b/beast/Version.h new file mode 100644 index 0000000000..e409692fb6 --- /dev/null +++ b/beast/Version.h @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_VERSION_H_INCLUDED +#define BEAST_VERSION_H_INCLUDED + +/** Current BEAST version number. + See also SystemStats::getBeastVersion() for a string version. +*/ +// VFALCO TODO Replace this with SemanticVerson +#define BEAST_MAJOR_VERSION 1 +#define BEAST_MINOR_VERSION 0 +#define BEAST_BUILDNUMBER 0 + +/** Current Beast version number. + Bits 16 to 32 = major version. + Bits 8 to 16 = minor version. + Bits 0 to 8 = point release. + See also SystemStats::getBeastVersion() for a string version. +*/ +#define BEAST_VERSION ((BEAST_MAJOR_VERSION << 16) + (BEAST_MINOR_VERSION << 8) + BEAST_BUILDNUMBER) + +#endif + diff --git a/beast/boost/Boost.cpp b/beast/boost/Boost.cpp new file mode 100644 index 0000000000..7e26631060 --- /dev/null +++ b/beast/boost/Boost.cpp @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "ErrorCode.h" diff --git a/beast/boost/ErrorCode.h b/beast/boost/ErrorCode.h new file mode 100644 index 0000000000..ea2fb8436b --- /dev/null +++ b/beast/boost/ErrorCode.h @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_BOOST_ERRORCODE_H_INCLUDED +#define BEAST_BOOST_ERRORCODE_H_INCLUDED + +#include + +namespace beast { + +// Lift this into our namespace. For now we will +// use boost, and then switch to std::error_code when +// it is available on all our supported platforms. +// +typedef boost::system::error_code ErrorCode; + +} + +#endif diff --git a/beast/chrono/CPUMeter.h b/beast/chrono/CPUMeter.h new file mode 100644 index 0000000000..b78da25d74 --- /dev/null +++ b/beast/chrono/CPUMeter.h @@ -0,0 +1,158 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CHRONO_CPUMETER_H_INCLUDED +#define BEAST_CHRONO_CPUMETER_H_INCLUDED + +#include "RelativeTime.h" +#include "ScopedTimeInterval.h" +#include "../threads/SharedData.h" +#include "../Atomic.h" + +namespace beast { + +/** Measurements of CPU utilization. */ +class CPUMeter +{ +private: + struct MeasureIdle + { + explicit MeasureIdle (CPUMeter& meter) + : m_meter (&meter) + { } + void operator() (RelativeTime const& interval) const + { m_meter->addIdleTime (interval); } + CPUMeter* m_meter; + }; + + struct MeasureActive + { + explicit MeasureActive (CPUMeter& meter) + : m_meter (&meter) + { } + void operator() (RelativeTime const& interval) const + { m_meter->addActiveTime (interval); } + CPUMeter* m_meter; + }; + + enum + { + // The amount of time an aggregate must accrue before a swap + secondsPerAggregate = 3 + + // The number of aggregates in the rolling history buffer + ,numberOfAggregates = 20 + }; + + // Aggregated sample data + struct Aggregate + { + RelativeTime idle; + RelativeTime active; + + // Returns the total number of seconds in the aggregate + double seconds () const + { return idle.inSeconds() + active.inSeconds(); } + + // Reset the accumulated times + void clear () + { idle = RelativeTime (0); active = RelativeTime (0); } + + Aggregate& operator+= (Aggregate const& other) + { idle += other.idle; active += other.active; return *this; } + + Aggregate& operator-= (Aggregate const& other) + { idle -= other.idle; active -= other.active; return *this; } + }; + + struct State + { + State () : index (0) + { + } + + // Returns a reference to the current aggregate + Aggregate& front () + { + return history [index]; + } + + // Checks the current aggregate to see if we should advance + void update() + { + if (front().seconds() >= secondsPerAggregate) + advance(); + } + + // Advance the index in the rolling history + void advance () + { + usage += history [index]; + index = (index+1) % numberOfAggregates; + usage -= history [index]; + history [index].clear (); + } + + // Index of the current aggregate we are accumulating + int index; + + // Delta summed usage over the entire history buffer + Aggregate usage; + + // The rolling history buffer + Aggregate history [numberOfAggregates]; + }; + + typedef SharedData SharedState; + + SharedState m_state; + + void addIdleTime (RelativeTime const& interval) + { + SharedState::Access state (m_state); + state->front().idle += interval; + state->update(); + } + + void addActiveTime (RelativeTime const& interval) + { + SharedState::Access state (m_state); + state->front().active += interval; + state->update(); + } + +public: + /** The type of container that measures idle time. */ + typedef ScopedTimeInterval ScopedIdleTime; + typedef ScopedTimeInterval ScopedActiveTime; + + /** Returns the fraction of time that the CPU is being used. */ + double getUtilizaton () const + { + SharedState::ConstAccess state (m_state); + double const seconds (state->usage.seconds()); + if (seconds > 0) + return (state->usage.active.inSeconds() / seconds); + return 0; + } +}; + +} + +#endif diff --git a/beast/chrono/Chrono.cpp b/beast/chrono/Chrono.cpp new file mode 100644 index 0000000000..5ce5772e66 --- /dev/null +++ b/beast/chrono/Chrono.cpp @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "impl/CPUMeter.cpp" +#include "impl/RelativeTime.cpp" diff --git a/modules/beast_core/time/beast_RelativeTime.h b/beast/chrono/RelativeTime.h similarity index 71% rename from modules/beast_core/time/beast_RelativeTime.h rename to beast/chrono/RelativeTime.h index ed8c1f3ff2..41a65df625 100644 --- a/modules/beast_core/time/beast_RelativeTime.h +++ b/beast/chrono/RelativeTime.h @@ -21,8 +21,16 @@ */ //============================================================================== -#ifndef BEAST_RELATIVETIME_H_INCLUDED -#define BEAST_RELATIVETIME_H_INCLUDED +#ifndef BEAST_CHRONO_RELATIVETIME_H_INCLUDED +#define BEAST_CHRONO_RELATIVETIME_H_INCLUDED + +#include "../Config.h" +#include "../strings/String.h" + +#include +#include + +namespace beast { //============================================================================== /** A relative measure of time. @@ -35,13 +43,22 @@ class BEAST_API RelativeTime { public: + //============================================================================== + /** The underlying data type used by RelativeTime. + + If you need to get to the underlying time and manipulate it + you can use this to declare a type that is guaranteed to + work cleanly. + */ + typedef double value_type; + //============================================================================== /** Creates a RelativeTime. @param seconds the number of seconds, which may be +ve or -ve. @see milliseconds, minutes, hours, days, weeks */ - explicit RelativeTime (double seconds = 0.0) noexcept; + explicit RelativeTime (value_type seconds = 0.0) noexcept; /** Copies another relative time. */ RelativeTime (const RelativeTime& other) noexcept; @@ -52,6 +69,15 @@ public: /** Destructor. */ ~RelativeTime() noexcept; + bool isZero() const + { return numSeconds == 0; } + + bool isNotZero() const + { return numSeconds != 0; } + + /** Returns the amount of time since the process was started. */ + static RelativeTime fromStartup (); + //============================================================================== /** Creates a new RelativeTime object representing a number of milliseconds. @see seconds, minutes, hours, days, weeks @@ -66,27 +92,27 @@ public: /** Creates a new RelativeTime object representing a number of seconds. @see milliseconds, minutes, hours, days, weeks */ - static RelativeTime seconds (double seconds) noexcept; + static RelativeTime seconds (value_type seconds) noexcept; /** Creates a new RelativeTime object representing a number of minutes. @see milliseconds, hours, days, weeks */ - static RelativeTime minutes (double numberOfMinutes) noexcept; + static RelativeTime minutes (value_type numberOfMinutes) noexcept; /** Creates a new RelativeTime object representing a number of hours. @see milliseconds, minutes, days, weeks */ - static RelativeTime hours (double numberOfHours) noexcept; + static RelativeTime hours (value_type numberOfHours) noexcept; /** Creates a new RelativeTime object representing a number of days. @see milliseconds, minutes, hours, weeks */ - static RelativeTime days (double numberOfDays) noexcept; + static RelativeTime days (value_type numberOfDays) noexcept; /** Creates a new RelativeTime object representing a number of weeks. @see milliseconds, minutes, hours, days */ - static RelativeTime weeks (double numberOfWeeks) noexcept; + static RelativeTime weeks (value_type numberOfWeeks) noexcept; //============================================================================== /** Returns the number of milliseconds this time represents. @@ -97,27 +123,27 @@ public: /** Returns the number of seconds this time represents. @see inMilliseconds, inMinutes, inHours, inDays, inWeeks */ - double inSeconds() const noexcept { return numSeconds; } + value_type inSeconds() const noexcept { return numSeconds; } /** Returns the number of minutes this time represents. @see inMilliseconds, inSeconds, inHours, inDays, inWeeks */ - double inMinutes() const noexcept; + value_type inMinutes() const noexcept; /** Returns the number of hours this time represents. @see inMilliseconds, inSeconds, inMinutes, inDays, inWeeks */ - double inHours() const noexcept; + value_type inHours() const noexcept; /** Returns the number of days this time represents. @see inMilliseconds, inSeconds, inMinutes, inHours, inWeeks */ - double inDays() const noexcept; + value_type inDays() const noexcept; /** Returns the number of weeks this time represents. @see inMilliseconds, inSeconds, inMinutes, inHours, inDays */ - double inWeeks() const noexcept; + value_type inWeeks() const noexcept; /** Returns a readable textual description of the time. @@ -135,42 +161,55 @@ public: @see inMilliseconds, inSeconds, inMinutes, inHours, inDays, inWeeks */ String getDescription (const String& returnValueForZeroTime = "0") const; + std::string to_string () const; + template + RelativeTime operator+ (Number seconds) const noexcept + { return RelativeTime (numSeconds + seconds); } + + template + RelativeTime operator- (Number seconds) const noexcept + { return RelativeTime (numSeconds - seconds); } - //============================================================================== /** Adds another RelativeTime to this one. */ RelativeTime operator+= (RelativeTime timeToAdd) noexcept; + /** Subtracts another RelativeTime from this one. */ RelativeTime operator-= (RelativeTime timeToSubtract) noexcept; /** Adds a number of seconds to this time. */ - RelativeTime operator+= (double secondsToAdd) noexcept; + RelativeTime operator+= (value_type secondsToAdd) noexcept; + /** Subtracts a number of seconds from this time. */ - RelativeTime operator-= (double secondsToSubtract) noexcept; + RelativeTime operator-= (value_type secondsToSubtract) noexcept; private: - //============================================================================== - double numSeconds; + value_type numSeconds; }; -//============================================================================== -/** Compares two RelativeTimes. */ +//------------------------------------------------------------------------------ + bool operator== (RelativeTime t1, RelativeTime t2) noexcept; -/** Compares two RelativeTimes. */ bool operator!= (RelativeTime t1, RelativeTime t2) noexcept; -/** Compares two RelativeTimes. */ bool operator> (RelativeTime t1, RelativeTime t2) noexcept; -/** Compares two RelativeTimes. */ bool operator< (RelativeTime t1, RelativeTime t2) noexcept; -/** Compares two RelativeTimes. */ bool operator>= (RelativeTime t1, RelativeTime t2) noexcept; -/** Compares two RelativeTimes. */ bool operator<= (RelativeTime t1, RelativeTime t2) noexcept; -//============================================================================== -/** Adds two RelativeTimes together. */ -RelativeTime operator+ (RelativeTime t1, RelativeTime t2) noexcept; -/** Subtracts two RelativeTimes. */ -RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept; +//------------------------------------------------------------------------------ -#endif // BEAST_RELATIVETIME_H_INCLUDED +/** Adds two RelativeTimes together. */ +RelativeTime operator+ (RelativeTime t1, RelativeTime t2) noexcept; + +/** Subtracts two RelativeTimes. */ +RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept; + +inline std::ostream& operator<< (std::ostream& os, RelativeTime const& diff) +{ + os << diff.to_string(); + return os; +} + +} + +#endif diff --git a/modules/beast_core/memory/beast_GlobalPagedFreeStore.h b/beast/chrono/ScopedTimeInterval.h similarity index 55% rename from modules/beast_core/memory/beast_GlobalPagedFreeStore.h rename to beast/chrono/ScopedTimeInterval.h index 5e2d4e3ca4..53b85b7427 100644 --- a/modules/beast_core/memory/beast_GlobalPagedFreeStore.h +++ b/beast/chrono/ScopedTimeInterval.h @@ -17,43 +17,46 @@ */ //============================================================================== -#ifndef BEAST_GLOBALPAGEDFREESTORE_H_INCLUDED -#define BEAST_GLOBALPAGEDFREESTORE_H_INCLUDED +#ifndef BEAST_CHRONO_SCOPEDTIMEINTERVAL_H_INCLUDED +#define BEAST_CHRONO_SCOPEDTIMEINTERVAL_H_INCLUDED -/*============================================================================*/ -/** - A PagedFreeStore singleton. +#include "../Uncopyable.h" +#include "RelativeTime.h" - @ingroup beast_concurrent +namespace beast { + +/** Time measurement using scoped RAII container. + UnaryFunction will be called with this signature: + void (RelativeTime const& interval); */ -class BEAST_API GlobalPagedFreeStore - : public SharedSingleton - , LeakChecked +template +class ScopedTimeInterval : public Uncopyable { public: - GlobalPagedFreeStore (); - ~GlobalPagedFreeStore (); - -public: - inline size_t getPageBytes () + /** Create the measurement with a default-constructed UnaryFunction. */ + ScopedTimeInterval () + : m_start (RelativeTime::fromStartup()) { - return m_allocator.getPageBytes (); } - inline void* allocate () + /** Create the measurement with UnaryFunction constructed from one argument. */ + template + explicit ScopedTimeInterval (Arg& arg) + : m_func (arg) + , m_start (RelativeTime::fromStartup ()) { - return m_allocator.allocate (); } - static inline void deallocate (void* const p) + ~ScopedTimeInterval () { - PagedFreeStore::deallocate (p); + m_func (RelativeTime::fromStartup() - m_start); } - static GlobalPagedFreeStore* createInstance (); - private: - PagedFreeStore m_allocator; + UnaryFunction m_func; + RelativeTime m_start; }; +} + #endif diff --git a/beast/chrono/impl/CPUMeter.cpp b/beast/chrono/impl/CPUMeter.cpp new file mode 100644 index 0000000000..b5a67f4d1b --- /dev/null +++ b/beast/chrono/impl/CPUMeter.cpp @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../CPUMeter.h" + diff --git a/beast/chrono/impl/RelativeTime.cpp b/beast/chrono/impl/RelativeTime.cpp new file mode 100644 index 0000000000..c18bc8f864 --- /dev/null +++ b/beast/chrono/impl/RelativeTime.cpp @@ -0,0 +1,326 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../RelativeTime.h" + +// VFALCO TODO Migrate the localizable strings interfaces for this file + +#ifndef NEEDS_TRANS +#define NEEDS_TRANS(s) (s) +#endif + +#ifndef TRANS +#define TRANS(s) (s) +#endif + +namespace beast { + +RelativeTime::RelativeTime (const RelativeTime::value_type secs) noexcept + : numSeconds (secs) +{ +} + +RelativeTime::RelativeTime (const RelativeTime& other) noexcept + : numSeconds (other.numSeconds) +{ +} + +RelativeTime::~RelativeTime() noexcept {} + +//============================================================================== + +RelativeTime RelativeTime::milliseconds (const int milliseconds) noexcept +{ + return RelativeTime (milliseconds * 0.001); +} + +RelativeTime RelativeTime::milliseconds (const int64 milliseconds) noexcept +{ + return RelativeTime (milliseconds * 0.001); +} + +RelativeTime RelativeTime::seconds (RelativeTime::value_type s) noexcept +{ + return RelativeTime (s); +} + +RelativeTime RelativeTime::minutes (const RelativeTime::value_type numberOfMinutes) noexcept +{ + return RelativeTime (numberOfMinutes * 60.0); +} + +RelativeTime RelativeTime::hours (const RelativeTime::value_type numberOfHours) noexcept +{ + return RelativeTime (numberOfHours * (60.0 * 60.0)); +} + +RelativeTime RelativeTime::days (const RelativeTime::value_type numberOfDays) noexcept +{ + return RelativeTime (numberOfDays * (60.0 * 60.0 * 24.0)); +} + +RelativeTime RelativeTime::weeks (const RelativeTime::value_type numberOfWeeks) noexcept +{ + return RelativeTime (numberOfWeeks * (60.0 * 60.0 * 24.0 * 7.0)); +} + +//============================================================================== + +int64 RelativeTime::inMilliseconds() const noexcept +{ + return (int64) (numSeconds * 1000.0); +} + +RelativeTime::value_type RelativeTime::inMinutes() const noexcept +{ + return numSeconds / 60.0; +} + +RelativeTime::value_type RelativeTime::inHours() const noexcept +{ + return numSeconds / (60.0 * 60.0); +} + +RelativeTime::value_type RelativeTime::inDays() const noexcept +{ + return numSeconds / (60.0 * 60.0 * 24.0); +} + +RelativeTime::value_type RelativeTime::inWeeks() const noexcept +{ + return numSeconds / (60.0 * 60.0 * 24.0 * 7.0); +} + +//============================================================================== + +RelativeTime& RelativeTime::operator= (const RelativeTime& other) noexcept { numSeconds = other.numSeconds; return *this; } + +RelativeTime RelativeTime::operator+= (RelativeTime t) noexcept +{ + numSeconds += t.numSeconds; return *this; +} + +RelativeTime RelativeTime::operator-= (RelativeTime t) noexcept +{ + numSeconds -= t.numSeconds; return *this; +} + +RelativeTime RelativeTime::operator+= (const RelativeTime::value_type secs) noexcept +{ + numSeconds += secs; return *this; +} + +RelativeTime RelativeTime::operator-= (const RelativeTime::value_type secs) noexcept +{ + numSeconds -= secs; return *this; +} + +RelativeTime operator+ (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1 += t2; +} + +RelativeTime operator- (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1 -= t2; +} + +bool operator== (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1.inSeconds() == t2.inSeconds(); +} + +bool operator!= (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1.inSeconds() != t2.inSeconds(); +} + +bool operator> (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1.inSeconds() > t2.inSeconds(); +} + +bool operator< (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1.inSeconds() < t2.inSeconds(); +} + +bool operator>= (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1.inSeconds() >= t2.inSeconds(); +} + +bool operator<= (RelativeTime t1, RelativeTime t2) noexcept +{ + return t1.inSeconds() <= t2.inSeconds(); +} + +//============================================================================== + +static void translateTimeField (String& result, int n, const char* singular, const char* plural) +{ + result << TRANS (String((n == 1) ? singular : plural)) + .replace (n == 1 ? "1" : "2", String (n)) + << ' '; +} + +String RelativeTime::getDescription (const String& returnValueForZeroTime) const +{ + if (numSeconds < 0.001 && numSeconds > -0.001) + return returnValueForZeroTime; + + String result; + result.preallocateBytes (32); + + if (numSeconds < 0) + result << '-'; + + int fieldsShown = 0; + int n = std::abs ((int) inWeeks()); + if (n > 0) + { + translateTimeField (result, n, NEEDS_TRANS("1 week"), NEEDS_TRANS("2 weeks")); + ++fieldsShown; + } + + n = std::abs ((int) inDays()) % 7; + if (n > 0) + { + translateTimeField (result, n, NEEDS_TRANS("1 day"), NEEDS_TRANS("2 days")); + ++fieldsShown; + } + + if (fieldsShown < 2) + { + n = std::abs ((int) inHours()) % 24; + if (n > 0) + { + translateTimeField (result, n, NEEDS_TRANS("1 hour"), NEEDS_TRANS("2 hours")); + ++fieldsShown; + } + + if (fieldsShown < 2) + { + n = std::abs ((int) inMinutes()) % 60; + if (n > 0) + { + translateTimeField (result, n, NEEDS_TRANS("1 minute"), NEEDS_TRANS("2 minutes")); + ++fieldsShown; + } + + if (fieldsShown < 2) + { + n = std::abs ((int) inSeconds()) % 60; + if (n > 0) + { + translateTimeField (result, n, NEEDS_TRANS("1 seconds"), NEEDS_TRANS("2 seconds")); + ++fieldsShown; + } + + if (fieldsShown == 0) + { + n = std::abs ((int) inMilliseconds()) % 1000; + if (n > 0) + result << n << ' ' << TRANS ("ms"); + } + } + } + } + + return result.trimEnd(); +} + +std::string RelativeTime::to_string () const +{ + return getDescription ().toStdString(); +} + +} + +#if BEAST_WINDOWS + +#include + +namespace beast { + +RelativeTime RelativeTime::fromStartup () +{ + ULONGLONG ticks (GetTickCount64()); + + return RelativeTime (ticks / 1000.0); +} + +} + +#else + +#include + +namespace beast { + +namespace detail { + +// Converts a timespec to a RelativeTme +static RelativeTime toRelativeTime (timespec const& ts) +{ + return RelativeTime (ts.tv_sec + + ts.tv_nsec / 1000000000.0); +} + +// Records and returns the time from process startup +static RelativeTime getStartupTime() +{ + struct StartupTime + { + StartupTime () + { clock_gettime (CLOCK_MONOTONIC, &ts); } + timespec ts; + }; + + static StartupTime startupTime; + + return toRelativeTime (startupTime.ts); +} + +// Used to call getStartupTime as early as possible +struct StartupTimeStaticInitializer +{ + StartupTimeStaticInitializer () + { getStartupTime(); } +}; + +static StartupTimeStaticInitializer startupTimeStaticInitializer; + +} + +RelativeTime RelativeTime::fromStartup () +{ + timespec ts; + clock_gettime (CLOCK_MONOTONIC, &ts); + + return detail::toRelativeTime (ts) - detail::getStartupTime(); +} + +} + +#endif diff --git a/modules/beast_core/system/PlatformDefs.h b/beast/config/CompilerConfig.h similarity index 91% rename from modules/beast_core/system/PlatformDefs.h rename to beast/config/CompilerConfig.h index f9bd910a1d..46e3afbfa5 100644 --- a/modules/beast_core/system/PlatformDefs.h +++ b/beast/config/CompilerConfig.h @@ -21,16 +21,20 @@ */ //============================================================================== -#ifndef BEAST_PLATFORMDEFS_H_INCLUDED -#define BEAST_PLATFORMDEFS_H_INCLUDED +#ifndef BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED +#define BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED + +// This file has to work when included in a C source file. + +#ifndef BEAST_CONFIG_PLATFORMCONFIG_H_INCLUDED +#error "PlatformConfig.h must come first!" +#endif // This file defines miscellaneous macros for debugging, assertions, etc. -#ifdef BEAST_FORCE_DEBUG +#if BEAST_FORCE_DEBUG # undef BEAST_DEBUG -# if BEAST_FORCE_DEBUG -# define BEAST_DEBUG 1 -# endif +# define BEAST_DEBUG 1 #endif /** This macro defines the C calling convention used as the standard for Beast calls. @@ -86,6 +90,17 @@ //------------------------------------------------------------------------------ +#ifdef __cplusplus +extern "C" { +#endif +/** Report a fatal error message and terminate the application. + Normally you won't call this directly. +*/ +extern void beast_reportFatalError (char const* message, char const* fileName, int lineNumber); +#ifdef __cplusplus +} +#endif + #if BEAST_DEBUG || DOXYGEN /** Writes a string to the standard error stream. @@ -101,17 +116,12 @@ #define bassertfalse { beast_LogCurrentAssertion; if (beast::beast_isRunningUnderDebugger()) beast_breakDebugger; BEAST_ANALYZER_NORETURN } /** Platform-independent assertion macro. - This macro gets turned into a no-op when you're building with debugging turned off, so be careful that the expression you pass to it doesn't perform any actions that are vital for the correct behaviour of your program! @see bassertfalse */ -#if 0 -#define bassert(expression) { if (! (expression)) bassertfalse; } -#else -#define bassert(expression) { if (! (expression)) fatal_error(#expression); } -#endif +#define bassert(expression) { if (! (expression)) beast_reportFatalError(#expression,__FILE__,__LINE__); } #else @@ -130,21 +140,6 @@ //------------------------------------------------------------------------------ -#ifndef DOXYGEN -namespace beast -{ -template struct BeastStaticAssert; -template <> struct BeastStaticAssert { static void dummy() {} }; -} -#endif - -/** A compile-time assertion macro. - If the expression parameter is false, the macro will cause a compile error. (The actual error - message that the compiler generates may be completely bizarre and seem to have no relation to - the place where you put the static_assert though!) -*/ -#define static_bassert(expression) beast::BeastStaticAssert::dummy(); - /** This macro can be added to class definitions to disable the use of new/delete to allocate the object on the heap, forcing it to only be used as a stack or member variable. */ @@ -300,4 +295,11 @@ template <> struct BeastStaticAssert { static void dummy() {} }; #define override #endif +#ifdef __cplusplus +namespace beast { +bool beast_isRunningUnderDebugger(); +void logAssertion (char const* file, int line) noexcept; +} +#endif + #endif diff --git a/modules/beast_core/system/BeastConfigCheck.h b/beast/config/ConfigCheck.h similarity index 91% rename from modules/beast_core/system/BeastConfigCheck.h rename to beast/config/ConfigCheck.h index 2ce310578d..7ee5955762 100644 --- a/modules/beast_core/system/BeastConfigCheck.h +++ b/beast/config/ConfigCheck.h @@ -17,8 +17,8 @@ */ //============================================================================== -#ifndef BEAST_CORE_SYSTEM_BEASTCONFIGCHECK_H_INCLUDED -#define BEAST_CORE_SYSTEM_BEASTCONFIGCHECK_H_INCLUDED +#ifndef BEAST_CONFIG_CONFIGCHECK_H_INCLUDED +#define BEAST_CONFIG_CONFIGCHECK_H_INCLUDED // This file makes sure that BeastConfig.h was included. // It also sets defaults for all config options. @@ -55,10 +55,6 @@ # endif #endif -#ifndef BEAST_CATCH_UNHANDLED_EXCEPTIONS -#define BEAST_CATCH_UNHANDLED_EXCEPTIONS 0 -#endif - #if BEAST_DEBUG && ! defined (BEAST_CHECK_MEMORY_LEAKS) #define BEAST_CHECK_MEMORY_LEAKS 1 #endif @@ -73,10 +69,6 @@ //------------------------------------------------------------------------------ -#ifndef BEAST_DISABLE_BEAST_VERSION_PRINTING -#define BEAST_DISABLE_BEAST_VERSION_PRINTING 0 -#endif - #ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES #define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 0 #endif diff --git a/modules/beast_core/diagnostic/ContractChecks.h b/beast/config/ContractChecks.h similarity index 92% rename from modules/beast_core/diagnostic/ContractChecks.h rename to beast/config/ContractChecks.h index b7d9e09a0f..59cad4231c 100644 --- a/modules/beast_core/diagnostic/ContractChecks.h +++ b/beast/config/ContractChecks.h @@ -17,8 +17,10 @@ */ //============================================================================== -#ifndef BEAST_CONTRACTCHECKS_H_INCLUDED -#define BEAST_CONTRACTCHECKS_H_INCLUDED +#ifndef BEAST_CONFIG_CONTRACTCHECKS_H_INCLUDED +#define BEAST_CONFIG_CONTRACTCHECKS_H_INCLUDED + +// This file has to work when included in a C source file. #if defined (fatal_error) || \ defined (fatal_condition) || \ @@ -33,15 +35,13 @@ #error "Programming by contract macros cannot be overriden!" #endif -extern void reportFatalError (char const* message, char const* fileName, int lineNumber); - /** Report a fatal error message and terminate the application. This macro automatically fills in the file and line number Meets this declaration syntax: @code inline void fatal_error (char const* message); @endif @see FatalError */ -#define fatal_error(message) reportFatalError (message, __FILE__, __LINE__) +#define fatal_error(message) beast_reportFatalError (message, __FILE__, __LINE__) /** Reports a fatal error message type if the condition is false The condition is always evaluated regardless of settings. @@ -49,7 +49,7 @@ extern void reportFatalError (char const* message, char const* fileName, int lin @code inline void fatal_condition (bool condition, char const* category); @endcode */ #define fatal_condition(condition,category) static_cast \ - (((!!(condition)) || (reportFatalError ( \ + (((!!(condition)) || (beast_reportFatalError ( \ category " '" BEAST_STRINGIFY(condition) "' failed.", __FILE__, __LINE__), 0))) /** Replacement for assert which generates a fatal error if the condition is false. @@ -65,7 +65,7 @@ extern void reportFatalError (char const* message, char const* fileName, int lin @code inline void fatal_condition (bool condition, char const* category); @endcode */ #define meets_condition(condition,category) static_cast \ - (((!!(condition)) || (reportFatalError ( \ + (((!!(condition)) || (beast_reportFatalError ( \ category " '" BEAST_STRINGIFY(condition) "' failed.", __FILE__, __LINE__), false))) /** Condition tests for programming by contract. diff --git a/modules/beast_core/system/TargetPlatform.h b/beast/config/PlatformConfig.h similarity index 98% rename from modules/beast_core/system/TargetPlatform.h rename to beast/config/PlatformConfig.h index 4e60bf1d6d..ec59dab8d7 100644 --- a/modules/beast_core/system/TargetPlatform.h +++ b/beast/config/PlatformConfig.h @@ -21,8 +21,8 @@ */ //============================================================================== -#ifndef BEAST_TARGETPLATFORM_H_INCLUDED -#define BEAST_TARGETPLATFORM_H_INCLUDED +#ifndef BEAST_CONFIG_PLATFORMCONFIG_H_INCLUDED +#define BEAST_CONFIG_PLATFORMCONFIG_H_INCLUDED //============================================================================== /* This file figures out which platform is being built, and defines some macros @@ -213,4 +213,5 @@ #define BEAST_PP_STR1_(x) BEAST_PP_STR2_(x) #define BEAST_FILEANDLINE_ __FILE__ "(" BEAST_PP_STR1_(__LINE__) "): warning:" -#endif // BEAST_TARGETPLATFORM_H_INCLUDED +#endif + diff --git a/beast/config/SelectCompilerConfig.h b/beast/config/SelectCompilerConfig.h new file mode 100644 index 0000000000..addf083bbe --- /dev/null +++ b/beast/config/SelectCompilerConfig.h @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Ideas from boost + +// Intel +#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) +#define BEAST_COMPILER_CONFIG "config/compiler/Intel.h" + +// Clang C++ emulates GCC, so it has to appear early. +#elif defined __clang__ +#define BEAST_COMPILER_CONFIG "config/compiler/Clang.h" + +// GNU C++: +#elif defined __GNUC__ +#define BEAST_COMPILER_CONFIG "config/compiler/Gcc.h" + +// Microsoft Visual C++ +// +// Must remain the last #elif since some other vendors (Metrowerks, for +// example) also #define _MSC_VER +#elif defined _MSC_VER +#define BEAST_COMPILER_CONFIG "config/compiler/VisualC.h" + +#else +#error "Unsupported compiler." +#endif + diff --git a/modules/beast_core/containers/detail/removecv.h b/beast/config/SelectPlatformConfig.h similarity index 53% rename from modules/beast_core/containers/detail/removecv.h rename to beast/config/SelectPlatformConfig.h index 19b3d3bc45..eb00e630bc 100644 --- a/modules/beast_core/containers/detail/removecv.h +++ b/beast/config/SelectPlatformConfig.h @@ -17,57 +17,28 @@ */ //============================================================================== -#ifndef BEAST_CORE_CONTAINERS_DETAIL_REMOVECV_H_INCLUDED -#define BEAST_CORE_CONTAINERS_DETAIL_REMOVECV_H_INCLUDED +// Ideas from boost -namespace detail -{ +// Android, which must be manually set by defining BEAST_ANDROID +#if defined(BEAST_ANDROID) +#define BEAST_PLATFORM_CONFIG "config/platform/Android.h" -// Strip all cv qualifiers from T -template -struct removecv -{ - typedef T type; -}; +// linux, also other platforms (Hurd etc) that use GLIBC +#elif (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC) +#define BEAST_PLATFORM_CONFIG "config/platform/Linux.h" -template -struct removecv -{ - typedef typename removecv ::type type; -}; +// BSD +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +#define BEAST_PLATFORM_CONFIG "config/platform/Bsd.h" -template -struct removecv -{ - typedef typename removecv ::type type; -}; +// win32 +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(_WIN64) +#define BEAST_PLATFORM_CONFIG "config/platform/Win32.h" -template -struct removecv -{ - typedef typename removecv ::type type; -}; - -template -struct removecv -{ - typedef typename removecv ::type type; -}; - -template -struct removecv -{ - typedef typename removecv ::type type; -}; - -#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS -template -struct removecv -{ - typedef typename removecv ::type type; -}; -#endif - -} +// MacOS +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) || defined(__APPLE_CPP__) +#define BEAST_PLATFORM_CONFIG "config/platform/MacOS.h" +#else +#error "Unsupported platform." #endif diff --git a/beast/config/SelectStdlibConfig.h b/beast/config/SelectStdlibConfig.h new file mode 100644 index 0000000000..ccc99a2a56 --- /dev/null +++ b/beast/config/SelectStdlibConfig.h @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Ideas from boost + diff --git a/modules/beast_core/system/StandardHeader.h b/beast/config/StandardConfig.h similarity index 66% rename from modules/beast_core/system/StandardHeader.h rename to beast/config/StandardConfig.h index 43415b9659..6f2a67c875 100644 --- a/modules/beast_core/system/StandardHeader.h +++ b/beast/config/StandardConfig.h @@ -21,33 +21,12 @@ */ //============================================================================== -#ifndef BEAST_STANDARDHEADER_H_INCLUDED -#define BEAST_STANDARDHEADER_H_INCLUDED +#ifndef BEAST_CONFIG_STANDARDCONFIG_H_INCLUDED +#define BEAST_CONFIG_STANDARDCONFIG_H_INCLUDED -//------------------------------------------------------------------------------ - -/** Current BEAST version number. - - See also SystemStats::getBeastVersion() for a string version. -*/ -// VFALCO TODO Replace this with SemanticVerson -#define BEAST_MAJOR_VERSION 1 -#define BEAST_MINOR_VERSION 0 -#define BEAST_BUILDNUMBER 0 - -/** Current Beast version number. - - Bits 16 to 32 = major version. - Bits 8 to 16 = minor version. - Bits 0 to 8 = point release. - - See also SystemStats::getBeastVersion() for a string version. -*/ -#define BEAST_VERSION ((BEAST_MAJOR_VERSION << 16) + (BEAST_MINOR_VERSION << 8) + BEAST_BUILDNUMBER) - -//------------------------------------------------------------------------------ - -#include "PlatformDefs.h" +#ifndef BEAST_CONFIG_COMPILERCONFIG_H_INCLUDED +#error "CompilerConfig.h must be included first" +#endif // Now we'll include some common OS headers.. #if BEAST_MSVC @@ -55,45 +34,6 @@ #pragma warning (disable: 4514 4245 4100) #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #if BEAST_USE_INTRINSICS # include #endif diff --git a/beast/config/Suffix.h b/beast/config/Suffix.h new file mode 100644 index 0000000000..1a85d4b63e --- /dev/null +++ b/beast/config/Suffix.h @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CONFIG_SUFFIX_H_INCLUDED +#define BEAST_CONFIG_SUFFIX_H_INCLUDED + +// Included at the end of Config.h + +#endif diff --git a/beast/config/compiler/Clang.h b/beast/config/compiler/Clang.h new file mode 100644 index 0000000000..25896af5b7 --- /dev/null +++ b/beast/config/compiler/Clang.h @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Clang compiler configuration diff --git a/beast/config/compiler/Gcc.h b/beast/config/compiler/Gcc.h new file mode 100644 index 0000000000..7b594b0858 --- /dev/null +++ b/beast/config/compiler/Gcc.h @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// GNU C++ compiler configuration diff --git a/beast/config/compiler/Intel.h b/beast/config/compiler/Intel.h new file mode 100644 index 0000000000..3e5d3cdbc7 --- /dev/null +++ b/beast/config/compiler/Intel.h @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Intel compiler configuration diff --git a/beast/config/compiler/VisualC.h b/beast/config/compiler/VisualC.h new file mode 100644 index 0000000000..1a238f0607 --- /dev/null +++ b/beast/config/compiler/VisualC.h @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Microsoft Visual C++ compiler configuration diff --git a/beast/config/platform/Android.h b/beast/config/platform/Android.h new file mode 100644 index 0000000000..9c61ebe105 --- /dev/null +++ b/beast/config/platform/Android.h @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Android platform configuration + +#ifdef BEAST_ANDROID +#undef BEAST_ANDROID +#endif +#define BEAST_ANDROID 1 + diff --git a/beast/config/platform/Bsd.h b/beast/config/platform/Bsd.h new file mode 100644 index 0000000000..af96cfdba8 --- /dev/null +++ b/beast/config/platform/Bsd.h @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// BSD, FreeBSD platform configuration diff --git a/beast/config/platform/Linux.h b/beast/config/platform/Linux.h new file mode 100644 index 0000000000..3d38e9164e --- /dev/null +++ b/beast/config/platform/Linux.h @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Linux-compatible platform configuration + diff --git a/beast/config/platform/MacOS.h b/beast/config/platform/MacOS.h new file mode 100644 index 0000000000..a9243f983a --- /dev/null +++ b/beast/config/platform/MacOS.h @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// MacOS and iOS platform configuration + diff --git a/beast/config/platform/Win32.h b/beast/config/platform/Win32.h new file mode 100644 index 0000000000..912613df4c --- /dev/null +++ b/beast/config/platform/Win32.h @@ -0,0 +1,21 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +// Win32 platform configuration + diff --git a/beast/crypto/Crypto.cpp b/beast/crypto/Crypto.cpp new file mode 100644 index 0000000000..e2b5228a7e --- /dev/null +++ b/beast/crypto/Crypto.cpp @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "impl/Sha256.cpp" diff --git a/beast/crypto/Sha256.h b/beast/crypto/Sha256.h new file mode 100644 index 0000000000..a3f4c5c528 --- /dev/null +++ b/beast/crypto/Sha256.h @@ -0,0 +1,156 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_CRYPTO_SHA256_H_INCLUDED +#define BEAST_CRYPTO_SHA256_H_INCLUDED + +#include "../Config.h" +#include "../CStdInt.h" +#include "../FixedArray.h" + +//------------------------------------------------------------------------------ + +namespace beast { +namespace Sha256 { + +enum +{ + digestLength = 32, + blockLength = 64 +}; + +/** A container suitable for holding the resulting hash. */ +typedef FixedArray digest_type; + +namespace detail { +struct Context +{ + beast::uint32 state[8]; + beast::uint64 bitcount; + beast::uint8 buffer[Sha256::blockLength]; +}; +} + +/** Computes the Sha256 hash of data. */ +class Context +{ +public: + /** Create a new hasher prepared for input. */ + Context(); + + /** Update the hashing context with the input sequence. */ + /** @{ */ + void update (void const* buffer, std::size_t bytes); + + void update (int8 const* begin, int8 const* end) + { + update (begin, end - begin); + } + + void update (uint8 const* begin, uint8 const* end) + { + update (begin, end - begin); + } + + template + void update (T const& t) + { + update (&t, sizeof(T)); + } + /** @} */ + + /** Finalize the hash process and store the digest. + The memory pointed to by `digest` must be at least digestLength + bytes. This object may not be re-used after calling finish. + @return A pointer to the passed hash buffer. + */ + /** @{ */ + void* finish (void* digest); + + digest_type& finish (digest_type& digest) + { + finish (digest.c_array()); + return digest; + } + + digest_type finish () + { + digest_type digest; + finish (digest); + return digest; + } + /** @} */ + +private: + detail::Context m_context; +}; + +//------------------------------------------------------------------------------ + +/** Returns the hash produced by a single octet equal to zero. */ +digest_type const& empty_digest(); + +/** Performs an entire hashing operation in a single step. + A zero length input sequence produces the empty_digest(). + @return The resulting digest depending on the arguments. +*/ +/** @{ */ +void* hash (void const* buffer, std::size_t bytes, void* digest); +digest_type& hash ( void const* buffer, std::size_t bytes, digest_type& digest); +digest_type hash (void const* buffer, std::size_t bytes); +void* hash (int8 const* begin, int8 const* end, void* digest); +void* hash (uint8 const* begin, uint8 const* end, void* digest); +digest_type hash (int8 const* begin, int8 const* end); +digest_type hash (uint8 const* begin, uint8 const* end); + +template +void* hash (T const& t, void* digest) +{ + return hash (&t, sizeof(T), digest); +} + +template +digest_type& hash (T const& t, digest_type& digest) +{ + return hash (&t, sizeof(T), digest); +} + +template +digest_type hash (T const& t) +{ + digest_type digest; + hash (&t, sizeof(T), digest); + return digest; +} +/** @} */ + +/** Calculate the hash of a hash in one step. + The memory pointed to by source_digest must be at + least digestLength bytes or undefined behavior results. +*/ +/** @{ */ +void* hash (void const* source_digest, void* digest); +digest_type& hash (void const* source_digest, digest_type& digest); +digest_type hash (void const* source_digest);; +/** @} */ + +} +} + +#endif diff --git a/beast/crypto/impl/Sha256.cpp b/beast/crypto/impl/Sha256.cpp new file mode 100644 index 0000000000..7542c189d1 --- /dev/null +++ b/beast/crypto/impl/Sha256.cpp @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../Sha256.h" + +namespace beast { +namespace Sha256 { + +#ifndef LITTLE_ENDIAN +# define LITTLE_ENDIAN 1234 +#endif +#ifndef BIG_ENDIAN +# define BIG_ENDIAN 4321 +#endif +#if !defined(BYTE_ORDER) +# if BEAST_BIG_ENDIAN +# define BYTE_ORDER BIG_ENDIAN +# else +# define BYTE_ORDER LITTLE_ENDIAN +# endif +#endif + +//#define SHA2_USE_INTTYPES_H + +namespace detail { +#include "sha2/sha2.c" +} + +Context::Context () +{ + detail::SHA256_Init (&m_context); +} + +void Context::update (void const* buffer, std::size_t bytes) +{ + detail::SHA256_Update (&m_context, static_cast (buffer), bytes); +} + +void* Context::finish (void* hash) +{ + detail::SHA256_Final (static_cast (hash), &m_context); + return hash; +} + +//------------------------------------------------------------------------------ + +digest_type const& empty_digest() +{ + struct Holder + { + Holder () + { + uint8 zero (0); + hash (zero, digest); + } + + digest_type digest; + }; + + static Holder const holder; + + return holder.digest; +} + +void* hash (void const* buffer, std::size_t bytes, void* digest) +{ + Context h; + h.update (buffer, bytes); + h.finish (digest); + return digest; +} + +digest_type& hash (void const* buffer, std::size_t bytes, digest_type& digest) +{ + hash (buffer, bytes, digest.c_array()); + return digest; +} + +digest_type hash (void const* buffer, std::size_t bytes) +{ + digest_type digest; + hash (buffer, bytes, digest); + return digest; +} + +void* hash (int8 const* begin, int8 const* end, void* digest) +{ + return hash (begin, end - begin, digest); +} + +void* hash (uint8 const* begin, uint8 const* end, void* digest) +{ + return hash (begin, end - begin, digest); +} + +digest_type hash (int8 const* begin, int8 const* end) +{ + digest_type digest; + hash (begin, end - begin, digest); + return digest; +} + +digest_type hash (uint8 const* begin, uint8 const* end) +{ + digest_type digest; + hash (begin, end - begin, digest); + return digest; +} + +void* hash (void const* source_digest, void* digest) +{ + return hash (source_digest, digestLength, digest); +} + +digest_type& hash (void const* source_digest, digest_type& digest) +{ + return hash (source_digest, digestLength, digest); +} + +digest_type hash (void const* source_digest) +{ + digest_type digest; + hash (source_digest, digestLength, digest); + return digest; +} + +} +} diff --git a/beast/crypto/impl/sha2/README b/beast/crypto/impl/sha2/README new file mode 100644 index 0000000000..a1b684d1e0 --- /dev/null +++ b/beast/crypto/impl/sha2/README @@ -0,0 +1,277 @@ +VERSION: + +This is version 1.0.1 RELEASE + +While this is my "release" version, due to lack of additional +official test vectors against which to verify this implementation's +correctness, beware that there may be implementation bugs. Also, +it has not yet been tested on very many other architectures, +big-endian machines in particular. + + +LICENSE: + +This implementation is released freely under an open-source BSD +license which appears at the top of each source code file. + + +WHAT IT IS: + +The files sha2.h and sha2.c implement the SHA-256, SHA-384, and SHA-512 +hash algorithms as described in the PDF document found at the following +web address: + + http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf + +The interface is similar to the interface to SHA-1 found in the OpenSSL +library. + +The file sha2prog.c is a simple program that accepts input from either +STDIN or reads one or more files specified on the command line, and then +generates the specified hash (either SHA-256, SHA-384, SHA-512, or any +combination thereof, including all three at once). + + +LIMITATIONS: + +This implementation has several limitations: + + * Input data is only accepted in octet-length increments. No sub-byte + data is handled. The NIST document describes how to handle sub-byte + input data, but for ease of implementation this version will only + accept message data in multiples of bytes. + * This implementation utilizes 64-bit integer data types. If your + system and compiler does not have a 64-bit integer data type, this + implementation will not work. + * Because of the use of 64-bit operations, many 32-bit architectures + that do have 64-bit data types but do operations most efficiently + on 32-bit words, this implementation may be slower than an + implementation designed to use only 32-bit words (emulating the + 64-bit operations). + * On platforms with 128-bit integer data types, the SHA-384 and SHA-512 + bit counters used by this implementation might be better off using + the 128-bit type instead of simulating it with two 64-bit integers. + * This implementation was written in C in hopes of portability and for + the fun of it during my spare time. It is probably not the most + efficient or fastest C implementation. I welcome suggestions, + however, that suggest ways to speed things up without breaking + portability. I also welcome suggestions to improve portability. + * As mentioned above, this code has NOT been thoroughly tested. + This is perhaps the most severe limitation. + + +BEFORE YOU COMPILE (OPTIONS): + +Each of the options described below may either be defined in the sha2.h +header file (or in the sha2.c file in some cases), or on the command +line at compile time if your compiler supports such things. For +example: + + #define SHA2_USE_INTTYPES_H + #define SHA2_UNROLL_TRANSFORM + +Or: + + cc -c -DSHA2_UNROLL_TRANSFORM sha2.c + cc -c -DBYTE_ORDER=4321 -DBIG_ENDIAN=4321 sha2.c + +Here are the available options. Read on below for a description of +each one: + + SHA2_USE_INTTYPES_H + SHA2_USE_MEMSET_MEMCPY/SHA2_USE_BZERO_BCOPY + SHA2_UNROLL_TRANSFORM + BYTE_ORDER (LITTLE_ENDIAN/BIG_ENDIAN) + +* SHA2_USE_INTTYPES_H option: +By default, this code uses u_intXX_t data types for 8 bit, 32 bit, and +64 bit unsigned integer type definitions. Most BSD systems define these, +as does Linux. However, some (like Compaq's Tru64 Unix) may instead +use uintXX_t data types as defined by recent ANSI C standards and as +included in the inttypes.h header file. Those wanting to use inttypes.h +need to define this either in sha.h or at compile time. + +On those systems where NEITHER definitions are available, you will need +to edit both sha2.h and sha2.c and define things by hand in the appropriate +sections. + +* BYTE_ORDER definitions: +This code assumes that BYTE_ORDER will be defined by the system during +compile to either equal LITTLE_ENDIAN or BIG_ENDIAN. If your system +does not define these, you may need to define them by hand in the sha.c +file according to the byte ordering conventions of your system. + +* SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY +The code in sha2.c can use either memset()/memcpy() for memory block +operations, or bzero()/mcopy(). If you define neither of these, the +code will default to memset()/memcpy(). You can define either at the +command line or in sha2.h or in sha2.c. + +* SHA2_UNROLL_TRANSFORM +By defining this either on the command line or in sha2.h or sha2.c, +the code will use macros to partially "unroll" the SHA transform +function. This usually generates bigger executables. It CAN (but +not necessarily WILL) generate faster code when you tell your compiler +to optimize things. For example, on the FreeBSD and Linux x86 systems +I tested things on (using gcc), when I optimized with just -O2 and +unrolled the transform, the hash transform was faster by 15-30%. On +these same systems, if I did NO optimization, the unrolled transform +was SLOWER, much slower (I'm guessing because the code was breaking +the cache, but I'm not sure). Your mileage may vary. + + +PORTABILITY: + +The code in sha2.c and sha2.h is intended to be portable. It may +require that you do a few #definitions in the .h file. I've successfully +compiled and tested the sha2.c and sha2.h code on Apple's OS X (on +a PPC), FreeBSD 4.1.1 on Intel, Linux on Intel, FreeBSD on the Alpha, +and even under Windows98SE using Metrowerks C. The utility/example +programs (sha2prog.c, sha2test.c, and sha2speed.c) will very likely +have more trouble in portability since they do I/O. + +To get sha2.c/sha2.h working under Windows, I had to define +SHA2_USE_INTTYPES_H, BYTE_ORDER, LITTLE_ENDIAN, and had to comment +out the include of in sha2.h. With a bit more work +I got the test program to run and verified that all the test +cases passed. + + +SUGGESTIONS/BUG FIXES: + +If you make changes to get it working on other architectures, if you fix +any bugs, or if you make changes that improve this implementation's +efficiency that would be relatively portable and you're willing to release +your changes under the same license, please send them to me for possible +inclusion in future versions. + +If you know where I can find some additional test vectors, please let me +know. + + +CHANGE HISTORY: + +0.8 to 0.9 - Fixed spelling errors, changed to u_intXX_t type usage, + removed names from prototypes, added prototypes to sha2.c, + and a few things I can't recall. + +0.9 to 0.9.5 - Add a new define in sha2.c that permits one to compile + it to either use memcpy()/memset() or bcopy()/bzero() + for memory block copying and zeroing. Added support + for unrolled SHA-256/384/512 transform loops. Just + compile with SHA2_UNROLL_TRANSFORM to enable. It takes + longer to compile, but I hope it is a bit faster. I + need to do some test to see whether or not it is. Oh, + in sha2.c, you either need to define SHA2_USE_BZERO_BCOPY + or SHA2_USE_MEMSET_MEMCPY to choose which way you want + to compile. *Whew* It's amazing how quickly something + simple starts to grow more complex even in the span of + just a few hours. I didn't really intend to do this much. +0.9.5 to 0.9.6 - Added a test program (sha2test) which tests against several + known test vectors. WARNING: Some of the test output + hashes are NOT from NIST's documentation and are the + output of this implementation and so may be incorrect. +0.9.6 to 0.9.7 - Fixed a bug that could cause invalid output in certain + cases and added an assumed scenario where zero-length + data is hashed. Also changed the rotation macros to use + a temporary variable as this reduces the number of operations. + When data is fed in blocks of the right length, copying of + data is reduced in this version. Added SHAYXZ_Data() + functions for ease of hashing a set of data. Added another + file sha2speed.c for doing speed testing. Added another test + vector with a larger data size (16KB). Fixed u_intXX_t and + uintXX_t handling by adding a define for SHA2_USE_INTTYPES_H + as well as made a few other minor changes to get rid of + warnings when compiling on Compaq's Tru64 Unix. +0.9.7 to 0.9.8 - The bug fix in 0.9.7 was incomplete and in some cases made + things worse. I believe that 0.9.8 fixes the bug completely + so that output is correct. I cannot verify this, however, + because of the lack of test vectors against which to do such + verification. All versions correctly matched the very few + NIST-provided vectors, but unfortunately the bug only + appeared in longer message data sets. +0.9.8 to 0.9.9 - Fixed some really bad typos and mistakes on my part that + only affected big-endian systems. I didn't have direct + access for testing before this version. Thanks to + Lucas Marshall for giving me access to his OS X system. +0.9.9 to 1.0.0b1 Added a few more test samples and made a few changes to + make things easier compiling on several other platforms. + Also I experimented with alternate macro definitions + in the SHA2_UNROLL_TRANSFORM version (see sha2.slower.c) + and eliminated the T1 temporary variable (the compiler + would of course still use internal temporary storage + during expression evaluation, but I'd hoped the compiler + would be more efficient), but unfortunately under FreeBSD + 4.1.1-STABLE on an x86 platform, the change slowed things + down. +1.0.0b1 to 1.0 RELEASE Fixed an off-by-one implementation bug that affected + SHA-256 when hashed data length L = 55 + 64 * X where X is + either zero or a positive integer, and another (basically + the same bug) bug in SHA-384 and SHA-512 that showed up when + hashed data lengths L = 111 + 128 * X. Thanks to Rogier + van de Pol for sending me test data that revealed the bug. + The fix was very simple (just two tiny changes). Also, + I finally put the files into RCS so future changes will be + easier to manage. The sha2prog.c file was rewritten to + be more useful to me, and I got rid of the old C testing + program and now use a perl script with a subdirectory full + of test data. It's a more flexible test system. + +1.0 to 1.0.1 - Specified the specific *_CTX structure in the MEMSET_BZERO + macro doing clean-up after hashing. This should eliminate + some warnings using Clang in version 3.0 (trunk 135348). + Thanks, Stephane Leon for reporting this. + + +LATEST VERSION: + +The latest version and documentation (if any ;) should always be available +on the web at: + + http://www.aarongifford.com/computers/sha.html + + +CONTACT ME: + +I can be reached via email at: + + Aaron Gifford + +Please don't send support questions. I don't have the time to answer and +they'll probably be ignored. Bug fixes, or patches that add something useful +will be gratefully accepted, however. + +If you use this implementation, I would enjoy getting a brief email message +letting me know who you are and what use to which it is being put. There +is no requirement to do so. I just think it would be fun. + + +EXAMPLES: + +Here's an example of compiling and using the sha2 program (in this example +I build it using the unrolled transform version with -O2 optimizations), +and then running the perl testing script: + + cc -O2 -DSHA2_UNROLL_TRANSFORM -Wall -o sha2 sha2prog.c sha2.c + % ./sha2test.pl + + [most of the perl script output deleted for brevity] + + ===== RESULTS (18 VECTOR DATA FILES HASHED) ===== + + HASH TYPE NO. OF TESTS PASSED FAILED + --------- ------------ ------ ------ + SHA-256 18 18 0 + SHA-384 18 18 0 + SHA-512 18 18 0 + ---------------------------------------------- + TOTAL: 54 54 0 + + NO ERRORS! ALL TESTS WERE SUCCESSFUL! + + ALL TEST VECTORS PASSED! + +That's all folks! Have fun! + +Aaron out. + diff --git a/beast/crypto/impl/sha2/sha2.c b/beast/crypto/impl/sha2/sha2.c new file mode 100644 index 0000000000..125aae2cae --- /dev/null +++ b/beast/crypto/impl/sha2/sha2.c @@ -0,0 +1,1067 @@ +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include /* memcpy()/memset() or bcopy()/bzero() */ +#include /* assert() */ +#include "sha2.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivilent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including (which in turn includes + * where the appropriate definitions are actually + * made). + */ +#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) +#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN +#endif + +/* + * Define the followingsha2_* types to types of the correct length on + * the native archtecture. Most BSD systems and Linux define u_intXX_t + * types. Machines with very recent ANSI C headers, can use the + * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H + * during compile or in the sha.h header file. + * + * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t + * will need to define these three typedefs below (and the appropriate + * ones in sha.h too) by hand according to their system architecture. + * + * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t + * types and pointing out recent ANSI C support for uintXX_t in inttypes.h. + */ + +typedef uint8 sha2_byte; /* Exactly 1 byte */ +typedef uint32 sha2_word32; /* Exactly 4 bytes */ +typedef uint64 sha2_word64; /* Exactly 8 bytes */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA256_SHORT_BLOCK_LENGTH (Sha256::blockLength - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#if BYTE_ORDER == LITTLE_ENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ +} +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) + +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +void SHA512_Last(SHA512_CTX*); +void SHA256_Transform(Sha256::detail::Context*, const sha2_word32*); +void SHA512_Transform(SHA512_CTX*, const sha2_word64*); + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +const static sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +const static sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +const static sha2_word64 K512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +/* Initial hash value H for SHA-384 */ +const static sha2_word64 sha384_initial_hash_value[8] = { + 0xcbbb9d5dc1059ed8ULL, + 0x629a292a367cd507ULL, + 0x9159015a3070dd17ULL, + 0x152fecd8f70e5939ULL, + 0x67332667ffc00b31ULL, + 0x8eb44a8768581511ULL, + 0xdb0c2e0d64f98fa7ULL, + 0x47b5481dbefa4fa4ULL +}; + +/* Initial hash value H for SHA-512 */ +const static sha2_word64 sha512_initial_hash_value[8] = { + 0x6a09e667f3bcc908ULL, + 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, + 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, + 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, + 0x5be0cd19137e2179ULL +}; + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char *sha2_hex_digits = "0123456789abcdef"; + + +/*** SHA-256: *********************************************************/ +void SHA256_Init(Sha256::detail::Context* context) { + if (context == (Sha256::detail::Context*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, Sha256::digestLength); + MEMSET_BZERO(context->buffer, Sha256::blockLength); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE32(*data++, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void SHA256_Transform(Sha256::detail::Context* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Transform(Sha256::detail::Context* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Update(Sha256::detail::Context* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (Sha256::detail::Context*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount >> 3) % Sha256::blockLength; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = Sha256::blockLength - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= Sha256::blockLength) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context, (sha2_word32*)data); + context->bitcount += Sha256::blockLength << 3; + len -= Sha256::blockLength; + data += Sha256::blockLength; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA256_Final(sha2_byte digest[], Sha256::detail::Context* context) { + sha2_word32 *d = (sha2_word32*)digest; + unsigned int usedspace; + + /* Sanity check: */ + assert(context != (Sha256::detail::Context*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (context->bitcount >> 3) % Sha256::blockLength; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < Sha256::blockLength) { + MEMSET_BZERO(&context->buffer[usedspace], Sha256::blockLength - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, Sha256::digestLength); +#endif + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(Sha256::detail::Context)); + usedspace = 0; +} + +char *SHA256_End(Sha256::detail::Context* context, char buffer[]) { + sha2_byte digest[Sha256::digestLength], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (Sha256::detail::Context*)0); + + if (buffer != (char*)0) { + SHA256_Final(digest, context); + + for (i = 0; i < Sha256::digestLength; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(Sha256::detail::Context)); + } + MEMSET_BZERO(digest, Sha256::digestLength); + return buffer; +} + +char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { + Sha256::detail::Context context; + + SHA256_Init(&context); + SHA256_Update(&context, data, len); + return SHA256_End(&context, digest); +} + + +/*** SHA-512: *********************************************************/ +void SHA512_Init(SHA512_CTX* context) { + if (context == (SHA512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#if BYTE_ORDER == LITTLE_ENDIAN + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE64(*data++, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + + +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert TO host byte order */ + REVERSE64(*data++, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context, (sha2_word64*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA512_Transform(context, (sha2_word64*)data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA512_Last(SHA512_CTX* context) { + unsigned int usedspace; + + usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH; +#if BYTE_ORDER == LITTLE_ENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount[0],context->bitcount[0]); + REVERSE64(context->bitcount[1],context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; + + /* Final transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); +} + +void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last(context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(SHA512_CTX)); +} + +char *SHA512_End(SHA512_CTX* context, char buffer[]) { + sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + if (buffer != (char*)0) { + SHA512_Final(digest, context); + + for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(SHA512_CTX)); + } + MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); + return buffer; +} + +char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { + SHA512_CTX context; + + SHA512_Init(&context); + SHA512_Update(&context, data, len); + return SHA512_End(&context, digest); +} + + +/*** SHA-384: *********************************************************/ +void SHA384_Init(SHA384_CTX* context) { + if (context == (SHA384_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { + SHA512_Update((SHA512_CTX*)context, data, len); +} + +void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last((SHA512_CTX*)context); + + /* Save the hash data for output: */ +#if BYTE_ORDER == LITTLE_ENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); +#endif + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(SHA384_CTX)); +} + +char *SHA384_End(SHA384_CTX* context, char buffer[]) { + sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + if (buffer != (char*)0) { + SHA384_Final(digest, context); + + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(SHA384_CTX)); + } + MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); + return buffer; +} + +char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { + SHA384_CTX context; + + SHA384_Init(&context); + SHA384_Update(&context, data, len); + return SHA384_End(&context, digest); +} + +#undef R +#undef S32 +#undef S64 +#undef Ch +#undef Maj +#undef Sigma0_256 +#undef Sigma1_256 +#undef sigma0_256 +#undef sigma1_256 +#undef Sigma0_512 +#undef Sigma1_512 +#undef sigma0_512 +#undef sigma1_512 diff --git a/beast/crypto/impl/sha2/sha2.h b/beast/crypto/impl/sha2/sha2.h new file mode 100644 index 0000000000..1728d86306 --- /dev/null +++ b/beast/crypto/impl/sha2/sha2.h @@ -0,0 +1,117 @@ +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $ + */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +//#ifdef __cplusplus +//extern "C" { +//#endif + +/* + * Import u_intXX_t size_t type definitions from system headers. You + * may need to change this, or define these things yourself in this + * file. + */ +#include + + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_DIGEST_STRING_LENGTH (Sha256::digestLength * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + +/*** SHA-256/384/512 Context Structures *******************************/ +typedef struct _SHA512_CTX { + uint64 state[8]; + uint64 bitcount[2]; + uint8 buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +typedef SHA512_CTX SHA384_CTX; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ +#ifndef NOPROTO + +void SHA256_Init(Sha256::detail::Context *); +void SHA256_Update(Sha256::detail::Context*, const uint8*, size_t); +void SHA256_Final(uint8[Sha256::digestLength], Sha256::detail::Context*); +char* SHA256_End(Sha256::detail::Context*, char[SHA256_DIGEST_STRING_LENGTH]); +char* SHA256_Data(const uint8*, size_t, char[SHA256_DIGEST_STRING_LENGTH]); + +void SHA384_Init(SHA384_CTX*); +void SHA384_Update(SHA384_CTX*, const uint8*, size_t); +void SHA384_Final(uint8[SHA384_DIGEST_LENGTH], SHA384_CTX*); +char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]); +char* SHA384_Data(const uint8*, size_t, char[SHA384_DIGEST_STRING_LENGTH]); + +void SHA512_Init(SHA512_CTX*); +void SHA512_Update(SHA512_CTX*, const uint8*, size_t); +void SHA512_Final(uint8[SHA512_DIGEST_LENGTH], SHA512_CTX*); +char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]); +char* SHA512_Data(const uint8*, size_t, char[SHA512_DIGEST_STRING_LENGTH]); + +#else /* NOPROTO */ + +void SHA256_Init(); +void SHA256_Update(); +void SHA256_Final(); +char* SHA256_End(); +char* SHA256_Data(); + +void SHA384_Init(); +void SHA384_Update(); +void SHA384_Final(); +char* SHA384_End(); +char* SHA384_Data(); + +void SHA512_Init(); +void SHA512_Update(); +void SHA512_Final(); +char* SHA512_End(); +char* SHA512_Data(); + +#endif /* NOPROTO */ + +//#ifdef __cplusplus +//} +//#endif /* __cplusplus */ + +#endif /* __SHA2_H__ */ + diff --git a/beast/crypto/impl/sha2/sha2prog.c b/beast/crypto/impl/sha2/sha2prog.c new file mode 100644 index 0000000000..012701e898 --- /dev/null +++ b/beast/crypto/impl/sha2/sha2prog.c @@ -0,0 +1,132 @@ +/* + * FILE: sha2prog.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "sha2.h" + +void usage(char *prog, char *msg) { + fprintf(stderr, "%s\nUsage:\t%s [options] []\nOptions:\n\t-256\tGenerate SHA-256 hash\n\t-384\tGenerate SHA-284 hash\n\t-512\tGenerate SHA-512 hash\n\t-ALL\tGenerate all three hashes\n\t-q\tQuiet mode - only output hexadecimal hashes, one per line\n\n", msg, prog); + exit(-1); +} + +#define BUFLEN 16384 + +int main(int argc, char **argv) { + int kl, l, fd, ac; + int quiet = 0, hash = 0; + char *av, *file = (char*)0; + FILE *IN = (FILE*)0; + SHA256_CTX ctx256; + SHA384_CTX ctx384; + SHA512_CTX ctx512; + unsigned char buf[BUFLEN]; + + SHA256_Init(&ctx256); + SHA384_Init(&ctx384); + SHA512_Init(&ctx512); + + /* Read data from STDIN by default */ + fd = fileno(stdin); + + ac = 1; + while (ac < argc) { + if (*argv[ac] == '-') { + av = argv[ac] + 1; + if (!strcmp(av, "q")) { + quiet = 1; + } else if (!strcmp(av, "256")) { + hash |= 1; + } else if (!strcmp(av, "384")) { + hash |= 2; + } else if (!strcmp(av, "512")) { + hash |= 4; + } else if (!strcmp(av, "ALL")) { + hash = 7; + } else { + usage(argv[0], "Invalid option."); + } + ac++; + } else { + file = argv[ac++]; + if (ac != argc) { + usage(argv[0], "Too many arguments."); + } + if ((IN = fopen(file, "r")) == NULL) { + perror(argv[0]); + exit(-1); + } + fd = fileno(IN); + } + } + if (hash == 0) + hash = 7; /* Default to ALL */ + + kl = 0; + while ((l = read(fd,buf,BUFLEN)) > 0) { + kl += l; + SHA256_Update(&ctx256, (unsigned char*)buf, l); + SHA384_Update(&ctx384, (unsigned char*)buf, l); + SHA512_Update(&ctx512, (unsigned char*)buf, l); + } + if (file) { + fclose(IN); + } + + if (hash & 1) { + SHA256_End(&ctx256, buf); + if (!quiet) + printf("SHA-256 (%s) = ", file); + printf("%s\n", buf); + } + if (hash & 2) { + SHA384_End(&ctx384, buf); + if (!quiet) + printf("SHA-384 (%s) = ", file); + printf("%s\n", buf); + } + if (hash & 4) { + SHA512_End(&ctx512, buf); + if (!quiet) + printf("SHA-512 (%s) = ", file); + printf("%s\n", buf); + } + + return 1; +} + diff --git a/beast/crypto/impl/sha2/sha2speed.c b/beast/crypto/impl/sha2/sha2speed.c new file mode 100644 index 0000000000..2e135750fa --- /dev/null +++ b/beast/crypto/impl/sha2/sha2speed.c @@ -0,0 +1,174 @@ +/* + * FILE: sha2speed.c + * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ + * + * Copyright (c) 2000-2001, Aaron D. Gifford + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sha2speed.c,v 1.1 2001/11/08 00:02:23 adg Exp adg $ + */ + +#include +#include +#include +#include + +#include "sha2.h" + +#define BUFSIZE 16384 + +void usage(char *prog) { + fprintf(stderr, "Usage:\t%s [] [] []\n", prog); + exit(-1); +} + +void printspeed(char *caption, unsigned long bytes, double time) { + if (bytes / 1073741824UL > 0) { + printf("%s %.4f sec (%.3f GBps)\n", caption, time, (double)bytes/1073741824UL/time); + } else if (bytes / 1048576 > 0) { + printf("%s %.4f (%.3f MBps)\n", caption, time, (double)bytes/1048576/time); + } else if (bytes / 1024 > 0) { + printf("%s %.4f (%.3f KBps)\n", caption, time, (double)bytes/1024/time); + } else { + printf("%s %.4f (%f Bps)\n", caption, time, (double)bytes/time); + } +} + + +int main(int argc, char **argv) { + SHA256_CTX c256; + SHA384_CTX c384; + SHA512_CTX c512; + char buf[BUFSIZE]; + char md[SHA512_DIGEST_STRING_LENGTH]; + int bytes, blocks, rep, i, j; + struct timeval start, end; + double t, ave256, ave384, ave512; + double best256, best384, best512; + + if (argc > 4) { + usage(argv[0]); + } + + /* Default to 1024 16K blocks (16 MB) */ + bytes = 1024 * 1024 * 16; + if (argc > 1) { + blocks = atoi(argv[1]); + } + blocks = bytes / BUFSIZE; + + /* Default to 10 repetitions */ + rep = 10; + if (argc > 2) { + rep = atoi(argv[2]); + } + + /* Set up the input data */ + if (argc > 3) { + memset(buf, atoi(argv[2]), BUFSIZE); + } else { + memset(buf, 0xb7, BUFSIZE); + } + + ave256 = ave384 = ave512 = 0; + best256 = best384 = best512 = 100000; + for (i = 0; i < rep; i++) { + SHA256_Init(&c256); + SHA384_Init(&c384); + SHA512_Init(&c512); + + gettimeofday(&start, (struct timezone*)0); + for (j = 0; j < blocks; j++) { + SHA256_Update(&c256, (unsigned char*)buf, BUFSIZE); + } + if (bytes % BUFSIZE) { + SHA256_Update(&c256, (unsigned char*)buf, bytes % BUFSIZE); + } + SHA256_End(&c256, md); + gettimeofday(&end, (struct timezone*)0); + t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0; + ave256 += t; + if (t < best256) { + best256 = t; + } + printf("SHA-256[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave256/(i+1), best256, md); + + gettimeofday(&start, (struct timezone*)0); + for (j = 0; j < blocks; j++) { + SHA384_Update(&c384, (unsigned char*)buf, BUFSIZE); + } + if (bytes % BUFSIZE) { + SHA384_Update(&c384, (unsigned char*)buf, bytes % BUFSIZE); + } + SHA384_End(&c384, md); + gettimeofday(&end, (struct timezone*)0); + t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0; + ave384 += t; + if (t < best384) { + best384 = t; + } + printf("SHA-384[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave384/(i+1), best384, md); + + gettimeofday(&start, (struct timezone*)0); + for (j = 0; j < blocks; j++) { + SHA512_Update(&c512, (unsigned char*)buf, BUFSIZE); + } + if (bytes % BUFSIZE) { + SHA512_Update(&c512, (unsigned char*)buf, bytes % BUFSIZE); + } + SHA512_End(&c512, md); + gettimeofday(&end, (struct timezone*)0); + t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0; + ave512 += t; + if (t < best512) { + best512 = t; + } + printf("SHA-512[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave512/(i+1), best512, md); + } + ave256 /= rep; + ave384 /= rep; + ave512 /= rep; + printf("\nTEST RESULTS SUMMARY:\nTEST REPETITIONS: %d\n", rep); + if (bytes / 1073741824UL > 0) { + printf("TEST SET SIZE: %.3f GB\n", (double)bytes/1073741824UL); + } else if (bytes / 1048576 > 0) { + printf("TEST SET SIZE: %.3f MB\n", (double)bytes/1048576); + } else if (bytes /1024 > 0) { + printf("TEST SET SIZE: %.3f KB\n", (double)bytes/1024); + } else { + printf("TEST SET SIZE: %d B\n", bytes); + } + printspeed("SHA-256 average:", bytes, ave256); + printspeed("SHA-256 best: ", bytes, best256); + printspeed("SHA-384 average:", bytes, ave384); + printspeed("SHA-384 best: ", bytes, best384); + printspeed("SHA-512 average:", bytes, ave512); + printspeed("SHA-512 best: ", bytes, best512); + + return 1; +} + diff --git a/beast/crypto/impl/sha2/sha2test.pl b/beast/crypto/impl/sha2/sha2test.pl new file mode 100644 index 0000000000..dc884d8c17 --- /dev/null +++ b/beast/crypto/impl/sha2/sha2test.pl @@ -0,0 +1,358 @@ +#!/usr/bin/perl +# +# FILE: sha2test.pl +# AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/ +# +# Copyright (c) 2001, Aaron D. Gifford +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id: sha2test.pl,v 1.1 2001/11/08 00:02:37 adg Exp adg $ +# + +sub usage { + my ($err) = shift(@_); + + print <] [ [ ...]] + +Options: + -256 Use SHA-256 hashes during testing + -384 Use SHA-384 hashes during testing + -512 Use SHA-512 hashes during testing + -ALL Use all three hashes during testing + -c256 Specify a command to execute to generate a + SHA-256 hash. Be sure to include a '%' + character which will be replaced by the + test vector data filename containing the + data to be hashed. This command implies + the -256 option. + -c384 Specify a command to execute to generate a + SHA-384 hash. See above. Implies -384. + -c512 Specify a command to execute to generate a + SHA-512 hash. See above. Implies -512. + -cALL Specify a command to execute that will + generate all three hashes at once and output + the data in hexadecimal. See above for + information about the . + This option implies the -ALL option, and + also overrides any other command options if + present. + +By default, this program expects to execute the command ./sha2 within the +current working directory to generate all hashes. If no test vector +information files are specified, this program expects to read a series of +files ending in ".info" within a subdirectory of the current working +directory called "testvectors". + +EOM + exit(-1); +} + +$c256 = $c384 = $c512 = $cALL = ""; +$hashes = 0; +@FILES = (); + +# Read all command-line options and files: +while ($opt = shift(@ARGV)) { + if ($opt =~ s/^\-//) { + if ($opt eq "256") { + $hashes |= 1; + } elsif ($opt eq "384") { + $hashes |= 2; + } elsif ($opt eq "512") { + $hashes |= 4; + } elsif ($opt =~ /^ALL$/i) { + $hashes = 7; + } elsif ($opt =~ /^c256$/i) { + $hashes |= 1; + $opt = $c256 = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$c256 || $c256 !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -c256: $opt\n"); + } + } elsif ($opt =~ /^c384$/i) { + $hashes |= 2; + $opt = $c384 = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$c384 || $c384 !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -c384: $opt\n"); + } + } elsif ($opt =~ /^c512$/i) { + $hashes |= 4; + $opt = $c512 = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$c512 || $c512 !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -c512: $opt\n"); + } + } elsif ($opt =~ /^cALL$/i) { + $hashes = 7; + $opt = $cALL = shift(@ARGV); + $opt =~ s/\s+.*$//; + if (!$cALL || $cALL !~ /\%/ || !-x $opt) { + usage("Missing or invalid command specification for option -cALL: $opt\n"); + } + } else { + usage("Unknown/invalid option '$opt'\n"); + } + } else { + usage("Invalid, nonexistent, or unreadable file '$opt': $!\n") if (!-f $opt); + push(@FILES, $opt); + } +} + +# Set up defaults: +if (!$cALL && !$c256 && !$c384 && !$c512) { + $cALL = "./sha2 -ALL %"; + usage("Required ./sha2 binary executable not found.\n") if (!-x "./sha2"); +} +$hashes = 7 if (!$hashes); + +# Do some sanity checks: +usage("No command was supplied to generate SHA-256 hashes.\n") if ($hashes & 1 == 1 && !$cALL && !$c256); +usage("No command was supplied to generate SHA-384 hashes.\n") if ($hashes & 2 == 2 && !$cALL && !$c384); +usage("No command was supplied to generate SHA-512 hashes.\n") if ($hashes & 4 == 4 && !$cALL && !$c512); + +# Default .info files: +if (scalar(@FILES) < 1) { + opendir(DIR, "testvectors") || usage("Unable to scan directory 'testvectors' for vector information files: $!\n"); + @FILES = grep(/\.info$/, readdir(DIR)); + closedir(DIR); + @FILES = map { s/^/testvectors\//; $_; } @FILES; + @FILES = sort(@FILES); +} + +# Now read in each test vector information file: +foreach $file (@FILES) { + $dir = $file; + if ($file !~ /\//) { + $dir = "./"; + } else { + $dir =~ s/\/[^\/]+$//; + $dir .= "/"; + } + open(FILE, "<" . $file) || + usage("Unable to open test vector information file '$file' for reading: $!\n"); + $vec = { desc => "", file => "", sha256 => "", sha384 => "", sha512 => "" }; + $data = $field = ""; + $line = 0; + while() { + $line++; + s/\s*[\r\n]+$//; + next if ($field && $field ne "DESCRIPTION" && !$_); + if (/^(DESCRIPTION|FILE|SHA256|SHA384|SHA512):$/) { + if ($field eq "DESCRIPTION") { + $vec->{desc} = $data; + } elsif ($field eq "FILE") { + $data = $dir . $data if ($data !~ /^\//); + $vec->{file} = $data; + } elsif ($field eq "SHA256") { + $vec->{sha256} = $data; + } elsif ($field eq "SHA384") { + $vec->{sha384} = $data; + } elsif ($field eq "SHA512") { + $vec->{sha512} = $data; + } + $data = ""; + $field = $1; + } elsif ($field eq "DESCRIPTION") { + s/^ //; + $data .= $_ . "\n"; + } elsif ($field =~ /^SHA\d\d\d$/) { + s/^\s+//; + if (!/^([a-f0-9]{32}|[a-f0-9]{64})$/) { + usage("Invalid SHA-256/384/512 test vector information " . + "file format at line $line of file '$file'\n"); + } + $data .= $_; + } elsif ($field eq "FILE") { + s/^ //; + $data .= $_; + } else { + usage("Invalid SHA-256/384/512 test vector information file " . + "format at line $line of file '$file'\n"); + } + } + if ($field eq "DESCRIPTION") { + $data = $dir . $data if ($data !~ /^\//); + $vec->{desc} = $data; + } elsif ($field eq "FILE") { + $vec->{file} = $data; + } elsif ($field eq "SHA256") { + $vec->{sha256} = $data; + } elsif ($field eq "SHA384") { + $vec->{sha384} = $data; + } elsif ($field eq "SHA512") { + $vec->{sha512} = $data; + } else { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. Missing required fields in file '$file'\n"); + } + + # Sanity check all entries: + if (!$vec->{desc}) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. Missing required DESCRIPTION field in file '$file'\n"); + } + if (!$vec->{file}) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. Missing required FILE field in file '$file'\n"); + } + if (! -f $vec->{file}) { + usage("The test vector data file (field FILE) name " . + "'$vec->{file}' is not a readable file. Check the FILE filed in " . + "file '$file'.\n"); + } + if (!($vec->{sha256} || $vec->{sha384} || $vec->{sha512})) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. There must be at least one SHA256, SHA384, or SHA512 " . + "field specified in file '$file'.\n"); + } + if ($vec->{sha256} !~ /^(|[a-f0-9]{64})$/) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. The SHA256 field is invalid in file '$file'.\n"); + } + if ($vec->{sha384} !~ /^(|[a-f0-9]{96})$/) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. The SHA384 field is invalid in file '$file'.\n"); + } + if ($vec->{sha512} !~ /^(|[a-f0-9]{128})$/) { + usage("Invalid SHA-256/384/512 test vector information file " . + "format. The SHA512 field is invalid in file '$file'.\n"); + } + close(FILE); + if ($hashes & (($vec->{sha256} ? 1 : 0) | ($vec->{sha384} ? 2 : 0) | ($vec->{sha512} ? 4 : 0))) { + push(@VECTORS, $vec); + } +} + +usage("There were no test vectors for the specified hash(es) in any of the test vector information files you specified.\n") if (scalar(@VECTORS) < 1); + +$num = $errors = $error256 = $error384 = $error512 = $tests = $test256 = $test384 = $test512 = 0; +foreach $vec (@VECTORS) { + $num++; + print "TEST VECTOR #$num:\n"; + print "\t" . join("\n\t", split(/\n/, $vec->{desc})) . "\n"; + print "VECTOR DATA FILE:\n\t$vec->{file}\n"; + $sha256 = $sha384 = $sha512 = ""; + if ($cALL) { + $prog = $cALL; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha256) = grep(/(^[a-fA-F0-9]{64}$|^[a-fA-F0-9]{64}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{64}$|[^a-fA-F0-9][a-fA-F0-9]{64}[^a-fA-F0-9])/, @SHA); + ($sha384) = grep(/(^[a-fA-F0-9]{96}$|^[a-fA-F0-9]{96}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{96}$|[^a-fA-F0-9][a-fA-F0-9]{96}[^a-fA-F0-9])/, @SHA); + ($sha512) = grep(/(^[a-fA-F0-9]{128}$|^[a-fA-F0-9]{128}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{128}$|[^a-fA-F0-9][a-fA-F0-9]{128}[^a-fA-F0-9])/, @SHA); + } else { + if ($c256) { + $prog = $c256; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha256) = grep(/(^[a-fA-F0-9]{64}$|^[a-fA-F0-9]{64}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{64}$|[^a-fA-F0-9][a-fA-F0-9]{64}[^a-fA-F0-9])/, @SHA); + } + if ($c384) { + $prog = $c384; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha384) = grep(/(^[a-fA-F0-9]{96}$|^[a-fA-F0-9]{96}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{96}$|[^a-fA-F0-9][a-fA-F0-9]{96}[^a-fA-F0-9])/, @SHA); + } + if ($c512) { + $prog = $c512; + $prog =~ s/\%/'$vec->{file}'/g; + @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`)); + ($sha512) = grep(/(^[a-fA-F0-9]{128}$|^[a-fA-F0-9]{128}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{128}$|[^a-fA-F0-9][a-fA-F0-9]{128}[^a-fA-F0-9])/, @SHA); + } + } + usage("Unable to generate any hashes for file '$vec->{file}'!\n") if (!$sha256 && !$sha384 && $sha512); + $sha256 =~ tr/A-F/a-f/; + $sha384 =~ tr/A-F/a-f/; + $sha512 =~ tr/A-F/a-f/; + $sha256 =~ s/^.*([a-f0-9]{64}).*$/$1/; + $sha384 =~ s/^.*([a-f0-9]{96}).*$/$1/; + $sha512 =~ s/^.*([a-f0-9]{128}).*$/$1/; + + if ($sha256 && $hashes & 1 == 1) { + if ($vec->{sha256} eq $sha256) { + print "SHA256 MATCHES:\n\t$sha256\n" + } else { + print "SHA256 DOES NOT MATCH:\n\tEXPECTED:\n\t\t$vec->{sha256}\n" . + "\tGOT:\n\t\t$sha256\n\n"; + $error256++; + } + $test256++; + } + if ($sha384 && $hashes & 2 == 2) { + if ($vec->{sha384} eq $sha384) { + print "SHA384 MATCHES:\n\t" . substr($sha384, 0, 64) . "\n\t" . + substr($sha384, -32) . "\n"; + } else { + print "SHA384 DOES NOT MATCH:\n\tEXPECTED:\n\t\t" . + substr($vec->{sha384}, 0, 64) . "\n\t\t" . + substr($vec->{sha384}, -32) . "\n\tGOT:\n\t\t" . + substr($sha384, 0, 64) . "\n\t\t" . substr($sha384, -32) . "\n\n"; + $error384++; + } + $test384++; + } + if ($sha512 && $hashes & 4 == 4) { + if ($vec->{sha512} eq $sha512) { + print "SHA512 MATCHES:\n\t" . substr($sha512, 0, 64) . "\n\t" . + substr($sha512, -64) . "\n"; + } else { + print "SHA512 DOES NOT MATCH:\n\tEXPECTED:\n\t\t" . + substr($vec->{sha512}, 0, 64) . "\n\t\t" . + substr($vec->{sha512}, -32) . "\n\tGOT:\n\t\t" . + substr($sha512, 0, 64) . "\n\t\t" . substr($sha512, -64) . "\n\n"; + $error512++; + } + $test512++; + } +} + +$errors = $error256 + $error384 + $error512; +$tests = $test256 + $test384 + $test512; +print "\n\n===== RESULTS ($num VECTOR DATA FILES HASHED) =====\n\n"; +print "HASH TYPE\tNO. OF TESTS\tPASSED\tFAILED\n"; +print "---------\t------------\t------\t------\n"; +if ($test256) { + $pass = $test256 - $error256; + print "SHA-256\t\t".substr(" $test256", -12)."\t".substr(" $pass", -6)."\t".substr(" $error256", -6)."\n"; +} +if ($test384) { + $pass = $test384 - $error384; + print "SHA-384\t\t".substr(" $test384", -12)."\t".substr(" $pass", -6)."\t".substr(" $error384", -6)."\n"; +} +if ($test512) { + $pass = $test512 - $error512; + print "SHA-512\t\t".substr(" $test512", -12)."\t".substr(" $pass", -6)."\t".substr(" $error512", -6)."\n"; +} +print "----------------------------------------------\n"; +$pass = $tests - $errors; +print "TOTAL: ".substr(" $tests", -12)."\t".substr(" $pass", -6)."\t".substr(" $errors", -6)."\n\n"; +print "NO ERRORS! ALL TESTS WERE SUCCESSFUL!\n\n" if (!$errors); + diff --git a/beast/http/HTTP.cpp b/beast/http/HTTP.cpp new file mode 100644 index 0000000000..a4913b0381 --- /dev/null +++ b/beast/http/HTTP.cpp @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "impl/URL.cpp" +#include "impl/ParsedURL.cpp" +#include "impl/http_parser.cpp" diff --git a/beast/http/ParsedURL.h b/beast/http/ParsedURL.h new file mode 100644 index 0000000000..69ca4a0746 --- /dev/null +++ b/beast/http/ParsedURL.h @@ -0,0 +1,51 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HTTP_PARSEDURL_H_INCLUDED +#define BEAST_HTTP_PARSEDURL_H_INCLUDED + +#include "../Strings.h" +#include "URL.h" + +namespace beast { + +/** Parses a String containing a URL. */ +class ParsedURL +{ +public: + ParsedURL (); + explicit ParsedURL (String const& url); + ParsedURL (int error, URL const& url); + ParsedURL (ParsedURL const& other); + ParsedURL& operator= (ParsedURL const& other); + + /** Zero for success, else a non zero value indicating failure. */ + int error () const; + + /** The parsed URL if there was no error. */ + URL url () const; + +private: + int m_error; + URL m_url; +}; + +} + +#endif diff --git a/modules/beast_asio/http/UniformResourceLocator.h b/beast/http/URL.h similarity index 74% rename from modules/beast_asio/http/UniformResourceLocator.h rename to beast/http/URL.h index 557cadfb86..5d80bd809c 100644 --- a/modules/beast_asio/http/UniformResourceLocator.h +++ b/beast/http/URL.h @@ -17,20 +17,24 @@ */ //============================================================================== -#ifndef BEAST_ASIO_PROTOCOL_UNIFORMRESOURCELOCATOR_H_INCLUDED -#define BEAST_ASIO_PROTOCOL_UNIFORMRESOURCELOCATOR_H_INCLUDED +#ifndef BEAST_HTTP_URL_H_INCLUDED +#define BEAST_HTTP_URL_H_INCLUDED + +#include "../strings/String.h" + +namespace beast { /** A URL. The accompanying robust parser is hardened against all forms of attack. */ -class UniformResourceLocator +class URL { public: /** Construct an empty URL. */ - explicit UniformResourceLocator (); + explicit URL (); /** Construct a URL from it's components. */ - UniformResourceLocator ( + URL ( String schema_, String host_, uint16 port_, @@ -41,10 +45,13 @@ public: String userinfo_ = ""); /** Copy construct a URL. */ - UniformResourceLocator (UniformResourceLocator const& other); + URL (URL const& other); /** Copy assign a URL. */ - UniformResourceLocator& operator= (UniformResourceLocator const& other); + URL& operator= (URL const& other); + + /** Returns `true` if this is an empty URL. */ + bool empty () const; /** Returns the scheme of the URL. If no scheme was specified, the string will be empty. @@ -96,28 +103,6 @@ private: String m_userinfo; }; -//------------------------------------------------------------------------------ - -/** Parses a String containing a URL. -*/ -class ParsedURL -{ -public: - ParsedURL (); - explicit ParsedURL (String const& url); - ParsedURL (int error, UniformResourceLocator const& url); - ParsedURL (ParsedURL const& other); - ParsedURL& operator= (ParsedURL const& other); - - /** Zero for success, else a non zero value indicating failure. */ - int error () const; - - /** The parsed URL if there was no error. */ - UniformResourceLocator url () const; - -private: - int m_error; - UniformResourceLocator m_url; -}; +} #endif diff --git a/modules/beast_asio/http/UniformResourceLocator.cpp b/beast/http/impl/ParsedURL.cpp similarity index 59% rename from modules/beast_asio/http/UniformResourceLocator.cpp rename to beast/http/impl/ParsedURL.cpp index 7324c0c297..b76f1df676 100644 --- a/modules/beast_asio/http/UniformResourceLocator.cpp +++ b/beast/http/impl/ParsedURL.cpp @@ -17,134 +17,13 @@ */ //============================================================================== -UniformResourceLocator::UniformResourceLocator () - : m_port (0) -{ -} +#include "../ParsedURL.h" -UniformResourceLocator::UniformResourceLocator ( - String scheme_, - String host_, - uint16 port_, - String port_string_, - String path_, - String query_, - String fragment_, - String userinfo_) - : m_scheme (scheme_) - , m_host (host_) - , m_port (port_) - , m_port_string (port_string_) - , m_path (path_) - , m_query (query_) - , m_fragment (fragment_) - , m_userinfo (userinfo_) -{ -} +#include "http-parser/http_parser.h" -UniformResourceLocator::UniformResourceLocator (UniformResourceLocator const& other) - : m_scheme (other.m_scheme) - , m_host (other.m_host) - , m_port (other.m_port) - , m_port_string (other.m_port_string) - , m_path (other.m_path) - , m_query (other.m_query) - , m_fragment (other.m_fragment) - , m_userinfo (other.m_userinfo) -{ -} +#include "../../../modules/beast_core/beast_core.h" // for UnitTest -UniformResourceLocator& UniformResourceLocator::operator= (UniformResourceLocator const& other) -{ - m_scheme = other.m_scheme; - m_host = other.m_host; - m_port = other.m_port; - m_port_string = other.m_port_string; - m_path = other.m_path; - m_query = other.m_query; - m_fragment = other.m_fragment; - m_userinfo = other.m_userinfo; - return *this; -} - -//------------------------------------------------------------------------------ - -String UniformResourceLocator::scheme () const -{ - return m_scheme; -} - -String UniformResourceLocator::host () const -{ - return m_host; -} - -String UniformResourceLocator::port_string () const -{ - return m_port_string; -} - -uint16 UniformResourceLocator::port () const -{ - return m_port; -} - -String UniformResourceLocator::path () const -{ - return m_path; -} - -String UniformResourceLocator::query () const -{ - return m_query; -} - -String UniformResourceLocator::fragment () const -{ - return m_fragment; -} - -String UniformResourceLocator::userinfo () const -{ - return m_userinfo; -} - -//------------------------------------------------------------------------------ -/* - From - http://en.wikipedia.org/wiki/URI_scheme - - : [ ? ] [ # ] - - e.g. - - foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose -*/ -String UniformResourceLocator::full () const -{ - String s; - - s = scheme () + "://"; - - if (userinfo () != String::empty) - s = userinfo () + "@"; - - s = s + host (); - - if (port () != 0) - s = s + ":" + String::fromNumber (port ()); - - s = s + path (); - - if (query () != String::empty) - s = "?" + query (); - - if (fragment () != String::empty) - s = "#" + fragment (); - - return s; -} -//------------------------------------------------------------------------------ +namespace beast { ParsedURL::ParsedURL () : m_error (0) @@ -226,7 +105,7 @@ ParsedURL::ParsedURL (String const& url) u.field_data [UF_USERINFO].len); } - m_url = UniformResourceLocator ( + m_url = URL ( scheme_, host_, port_, @@ -238,7 +117,7 @@ ParsedURL::ParsedURL (String const& url) } } -ParsedURL::ParsedURL (int error, UniformResourceLocator const& url) +ParsedURL::ParsedURL (int error, URL const& url) : m_error (error) , m_url (url) { @@ -262,7 +141,7 @@ int ParsedURL::error () const return m_error; } -UniformResourceLocator ParsedURL::url () const +URL ParsedURL::url () const { return m_url; } @@ -297,3 +176,5 @@ public: }; static ParsedURLTests parsedURLTests; + +} diff --git a/beast/http/impl/README.md b/beast/http/impl/README.md new file mode 100644 index 0000000000..ab82bbba99 --- /dev/null +++ b/beast/http/impl/README.md @@ -0,0 +1,3 @@ +git-subtree: "http-parser" +remote: https://github.com/joyent/http-parser.git +branch: master diff --git a/beast/http/impl/URL.cpp b/beast/http/impl/URL.cpp new file mode 100644 index 0000000000..d0ddfe74a0 --- /dev/null +++ b/beast/http/impl/URL.cpp @@ -0,0 +1,158 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../URL.h" + +namespace beast { + +URL::URL () + : m_port (0) +{ +} + +URL::URL ( + String scheme_, + String host_, + uint16 port_, + String port_string_, + String path_, + String query_, + String fragment_, + String userinfo_) + : m_scheme (scheme_) + , m_host (host_) + , m_port (port_) + , m_port_string (port_string_) + , m_path (path_) + , m_query (query_) + , m_fragment (fragment_) + , m_userinfo (userinfo_) +{ +} + +URL::URL (URL const& other) + : m_scheme (other.m_scheme) + , m_host (other.m_host) + , m_port (other.m_port) + , m_port_string (other.m_port_string) + , m_path (other.m_path) + , m_query (other.m_query) + , m_fragment (other.m_fragment) + , m_userinfo (other.m_userinfo) +{ +} + +URL& URL::operator= (URL const& other) +{ + m_scheme = other.m_scheme; + m_host = other.m_host; + m_port = other.m_port; + m_port_string = other.m_port_string; + m_path = other.m_path; + m_query = other.m_query; + m_fragment = other.m_fragment; + m_userinfo = other.m_userinfo; + return *this; +} + +//------------------------------------------------------------------------------ + +bool URL::empty () const +{ + return m_scheme == String::empty; +} + +String URL::scheme () const +{ + return m_scheme; +} + +String URL::host () const +{ + return m_host; +} + +String URL::port_string () const +{ + return m_port_string; +} + +uint16 URL::port () const +{ + return m_port; +} + +String URL::path () const +{ + return m_path; +} + +String URL::query () const +{ + return m_query; +} + +String URL::fragment () const +{ + return m_fragment; +} + +String URL::userinfo () const +{ + return m_userinfo; +} + +//------------------------------------------------------------------------------ +/* + From + http://en.wikipedia.org/wiki/URI_scheme + + : [ ? ] [ # ] + + e.g. + + foo://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose +*/ +String URL::full () const +{ + String s; + + s = scheme () + "://"; + + if (userinfo () != String::empty) + s = userinfo () + "@"; + + s = s + host (); + + if (port () != 0) + s = s + ":" + String::fromNumber (port ()); + + s = s + path (); + + if (query () != String::empty) + s = "?" + query (); + + if (fragment () != String::empty) + s = "#" + fragment (); + + return s; +} + +} + diff --git a/modules/beast_asio/parsehttp/.gitignore b/beast/http/impl/http-parser/.gitignore similarity index 100% rename from modules/beast_asio/parsehttp/.gitignore rename to beast/http/impl/http-parser/.gitignore diff --git a/modules/beast_asio/parsehttp/.mailmap b/beast/http/impl/http-parser/.mailmap similarity index 100% rename from modules/beast_asio/parsehttp/.mailmap rename to beast/http/impl/http-parser/.mailmap diff --git a/modules/beast_asio/parsehttp/.travis.yml b/beast/http/impl/http-parser/.travis.yml similarity index 100% rename from modules/beast_asio/parsehttp/.travis.yml rename to beast/http/impl/http-parser/.travis.yml diff --git a/modules/beast_asio/parsehttp/AUTHORS b/beast/http/impl/http-parser/AUTHORS similarity index 100% rename from modules/beast_asio/parsehttp/AUTHORS rename to beast/http/impl/http-parser/AUTHORS diff --git a/modules/beast_asio/parsehttp/CONTRIBUTIONS b/beast/http/impl/http-parser/CONTRIBUTIONS similarity index 100% rename from modules/beast_asio/parsehttp/CONTRIBUTIONS rename to beast/http/impl/http-parser/CONTRIBUTIONS diff --git a/modules/beast_asio/parsehttp/LICENSE-MIT b/beast/http/impl/http-parser/LICENSE-MIT similarity index 100% rename from modules/beast_asio/parsehttp/LICENSE-MIT rename to beast/http/impl/http-parser/LICENSE-MIT diff --git a/modules/beast_asio/parsehttp/Makefile b/beast/http/impl/http-parser/Makefile similarity index 100% rename from modules/beast_asio/parsehttp/Makefile rename to beast/http/impl/http-parser/Makefile diff --git a/modules/beast_asio/parsehttp/README.md b/beast/http/impl/http-parser/README.md similarity index 100% rename from modules/beast_asio/parsehttp/README.md rename to beast/http/impl/http-parser/README.md diff --git a/modules/beast_asio/parsehttp/contrib/parsertrace.c b/beast/http/impl/http-parser/contrib/parsertrace.c similarity index 100% rename from modules/beast_asio/parsehttp/contrib/parsertrace.c rename to beast/http/impl/http-parser/contrib/parsertrace.c diff --git a/modules/beast_asio/parsehttp/contrib/url_parser.c b/beast/http/impl/http-parser/contrib/url_parser.c similarity index 100% rename from modules/beast_asio/parsehttp/contrib/url_parser.c rename to beast/http/impl/http-parser/contrib/url_parser.c diff --git a/modules/beast_asio/parsehttp/http_parser.c b/beast/http/impl/http-parser/http_parser.c similarity index 100% rename from modules/beast_asio/parsehttp/http_parser.c rename to beast/http/impl/http-parser/http_parser.c diff --git a/modules/beast_asio/parsehttp/http_parser.gyp b/beast/http/impl/http-parser/http_parser.gyp similarity index 100% rename from modules/beast_asio/parsehttp/http_parser.gyp rename to beast/http/impl/http-parser/http_parser.gyp diff --git a/modules/beast_asio/parsehttp/http_parser.h b/beast/http/impl/http-parser/http_parser.h similarity index 100% rename from modules/beast_asio/parsehttp/http_parser.h rename to beast/http/impl/http-parser/http_parser.h diff --git a/modules/beast_asio/parsehttp/test.c b/beast/http/impl/http-parser/test.c similarity index 100% rename from modules/beast_asio/parsehttp/test.c rename to beast/http/impl/http-parser/test.c diff --git a/beast/http/impl/http_parser.cpp b/beast/http/impl/http_parser.cpp new file mode 100644 index 0000000000..42b5b8eb24 --- /dev/null +++ b/beast/http/impl/http_parser.cpp @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "../../Config.h" + +namespace beast { + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable: 4127) // conditional expression is constant +#pragma warning (disable: 4244) // integer conversion, possible loss of data +#endif +#include "http-parser/http_parser.c" +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +} diff --git a/beast/intrusive/ForwardList.h b/beast/intrusive/ForwardList.h index 2a88225b97..86264d0d2f 100644 --- a/beast/intrusive/ForwardList.h +++ b/beast/intrusive/ForwardList.h @@ -20,10 +20,13 @@ #ifndef BEAST_INTRUSIVE_FORWARDLIST_H_INCLUDED #define BEAST_INTRUSIVE_FORWARDLIST_H_INCLUDED -#include +#include "../Config.h" #include "PointerTraits.h" -#include "../mpl.h" + +#include "../MPL.h" + +#include // Ideas based on boost diff --git a/beast/intrusive/IntrusiveArray.h b/beast/intrusive/IntrusiveArray.h new file mode 100644 index 0000000000..53fbe0b057 --- /dev/null +++ b/beast/intrusive/IntrusiveArray.h @@ -0,0 +1,187 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INTRUSIVE_INTRUSIVEARRAY_H_INCLUDED +#define BEAST_INTRUSIVE_INTRUSIVEARRAY_H_INCLUDED + +#include "../Config.h" + +#include +#include +#include +#include + +namespace beast { + +/** A run-time fixed size array that references outside storage. + The interface tries to follow std::vector as closely as possible within + the limitations of a fixed size and unowned storage. +*/ +template +class IntrusiveArray +{ +private: + T* m_begin; + T* m_end; + +public: + typedef T value_type; + typedef T* iterator; + typedef T const* const_iterator; + typedef T& reference; + typedef T const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // Calling methods on a default constructed + // array results in undefined behavior! + // + IntrusiveArray () + : m_begin (nullptr), m_end (nullptr) + { } + IntrusiveArray (T* begin, T* end) + : m_begin (begin), m_end (end) + { } + IntrusiveArray (IntrusiveArray const& other) + : m_begin (other.m_begin), m_end (other.m_end) + { } + IntrusiveArray (std::vector const& v) + : m_begin (&v.front()), m_end (&v.back()+1) + { } + IntrusiveArray (std::vector & v) + : m_begin (&v.front()), m_end (&v.back()+1) + { } + IntrusiveArray& operator= (IntrusiveArray const& other) + { + m_begin = other.m_begin; + m_end = other.m_end; + return *this; + } + + // iterators + iterator begin() { return m_begin; } + const_iterator begin() const { return m_begin; } + const_iterator cbegin() const { return m_begin; } + iterator end() { return m_end; } + const_iterator end() const { return m_end; } + const_iterator cend() const { return m_end; } + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + const_reverse_iterator crend() const { return const_reverse_iterator(begin()); } + + reference operator[](size_type i) + { + bassert (i < size()); + return m_begin[i]; + } + + const_reference operator[](size_type i) const + { + bassert (i < size()); + return m_begin[i]; + } + + reference at(size_type i) { rangecheck(i); return m_begin[i]; } + const_reference at(size_type i) const { rangecheck(i); return m_begin[i]; } + + reference front() { return m_begin[0]; } + reference back() { return m_end[-1]; } + const_reference front () const { return m_begin; } + const_reference back() const { return m_end[-1]; } + + size_type size() const { return std::distance (m_begin, m_end); } + bool empty() const { return m_begin == m_end; } + + T const* data() const { return m_begin; } + T* data() { return m_begin; } + T* c_array() { return m_begin; } + + void assign (T const& value) { fill (value); } + + void fill (T const& value) + { + std::fill_n (begin(), size(), value); + } + + void clear () + { + fill (T ()); + } + + void rangecheck (size_type i) + { + if (i >= size()) + throw std::out_of_range ("IntrusiveArray<>: index out of range"); + } +}; + +//------------------------------------------------------------------------------ + +template +bool operator== (IntrusiveArray const& lhs, IntrusiveArray const& rhs) +{ + if ((lhs.begin() == rhs.begin()) && (lhs.end() == rhs.end())) + return true; + if (lhs.size() != rhs.size()) + return false; + return std::equal (lhs.begin(), lhs.end(), rhs.begin()); +} + +template +bool operator!= (IntrusiveArray const& lhs, IntrusiveArray const& rhs) +{ + return !(lhs==rhs); +} + +template +bool operator< (IntrusiveArray const& lhs, IntrusiveArray const& rhs) +{ + if ((lhs.begin() == rhs.begin()) && (lhs.end() == rhs.end())) + return false; + return std::lexicographical_compare (lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +template +bool operator> (IntrusiveArray const& lhs, IntrusiveArray const& rhs) +{ + return rhs +bool operator<= (IntrusiveArray const& lhs, IntrusiveArray const& rhs) +{ + return !(rhs +bool operator>= (IntrusiveArray const& lhs, IntrusiveArray const& rhs) +{ + return !(lhs - # Interface - - The interface for intrusive elements in this library is unified for all - containers. Unlike STL containers, objects placed into intrusive containers - are not copied. Instead, a pointer to the object is stored. All - responsibility for object lifetime is the responsibility of the caller; - the intrusive container just keeps track of what is in it. - - Summary of intrusive container differences: - - - Holds pointers to existing objects instead of copies. - - - Does not allocate or free any objects. - - - Requires a element's class declaration to be modified. - - - Methods never throw exceptions when called with valid arguments. - - # Usage - - Like STL containers, intrusive containers are all template based, where the - template argument specifies the type of object that the container will hold. - These declarations specify a doubly linked list where each element points - to a user defined class: - - @code - - struct Object; // Forward declaration - - List list; // Doubly-linked list of Object - - @endcode - - Because intrusive containers allocate no memory, allowing objects to be - placed inside requires a modification to their class declaration. Each - intrusive container declares a nested class `Node` which elements must be - derived from, using the Curiously Recurring Template Pattern (CRTP). We - will continue to fully declare the Object type from the previous example - to support emplacement into an intrusive container: - - @code - - struct Object : public List ::Node // Required for List - { - void performAction (); - }; - - @endcode - - Usage of a typedef eliminates redundant specification of the template - arguments but requires a forward declaration. The following code is - equivalent. - - @code - - struct Object; // Forward declaration - - // Specify template parameters just once - typedef List ListType; - - struct Object : public ListType::Node - { - void performAction (); - }; - - ListType::Node list; - - @endcode - - With these declarations we may proceed to create our objects, add them to - the list, and perform operations: - - @code - - // Create a few objects and put them in the list - for (i = 0; i < 5; ++i) - list.push_back (*new Object); - - // Call a method on each list - for (ListType::iterator iter = list.begin(); iter != list.end (); ++iter) - iter->performAction (); - - @endcode - - Unlike regular STL containers, an object derived from an intrusive container - node cannot exist in more than one instance of that list at a time. This is - because the bookkeeping information for maintaining the list is kept in - the object rather than the list. - - To support objects existing in multiple containers, templates variations - are instantiated by distinguishing them with an empty structure, called a - tag. The object is derived from multiple instances of Node, where each - instance specifies a unique tag. The tag is passed as the second template - argument. When the second argument is unspecified, the default tag is used. - - This declaration example shows the usage of tags to allow an object to exist - simultaneously in two separate lists: - - @code - - struct GlobalListTag { }; // list of all objects - struct ActiveListTag { }; // subset of all objects that are active - - class Object : public List - , public List - { - public: - Object () : m_isActive (false) - { - // Add ourselves to the global list - s_globalList.push_front (*this); - } - - ~Object () - { - deactivate (); - } - - void becomeActive () - { - // Add ourselves to the active list - if (!m_isActive) - { - s_activeList.push_front (*this); - m_isActive = true; - } - } - - void deactivate () - { - if (m_isActive) - { - // Doesn't delete the object - s_activeList.erase (s_activeList.iterator_to (this)); - - m_isActive = false; - } - } - - private: - bool m_isActive; - - static List s_globalList; - static List s_activeList; - } - - @endcode - - @defgroup intrusive intrusive - @ingroup beast_core -*/ - -//------------------------------------------------------------------------------ +namespace beast { template class List; @@ -203,13 +41,12 @@ namespace detail // concurrently is required. // template -class ListNode : public Uncopyable +class ListNode { private: typedef T value_type; - template - friend class List; + friend class List; template friend class ListIterator; @@ -225,8 +62,7 @@ class ListIterator : public std::iterator < std::bidirectional_iterator_tag, std::size_t> { public: - typedef typename copyconst ::type - + typedef typename mpl::CopyConst::type value_type; typedef value_type* pointer; typedef value_type& reference; @@ -243,14 +79,6 @@ public: { } -#if 0 - template - ListIterator& operator= (ListIterator const& other) noexcept - { - m_node = other.m_node; - return *this; - } -#endif template bool operator== (ListIterator const& other) const noexcept { @@ -307,14 +135,11 @@ private: void increment () noexcept { - bassert (m_node->m_next); m_node = m_node->m_next; } void decrement () noexcept { - bassert (m_node->m_prev && - m_node->m_prev->m_prev != nullptr); m_node = m_node->m_prev; } @@ -323,8 +148,7 @@ private: } -/** - Intrusive doubly linked list. +/** Intrusive doubly linked list. This intrusive List is a container similar in operation to std::list in the Standard Template Library (STL). Like all @ref intrusive containers, List @@ -583,7 +407,6 @@ public: @param pos The location to insert after. @param other The list to insert. */ - void insert (iterator pos, List& other) noexcept { if (!other.empty ()) @@ -717,4 +540,6 @@ private: Node m_tail; }; +} + #endif diff --git a/beast/intrusive/LockFreeStack.h b/beast/intrusive/LockFreeStack.h new file mode 100644 index 0000000000..9d64662e54 --- /dev/null +++ b/beast/intrusive/LockFreeStack.h @@ -0,0 +1,285 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED +#define BEAST_INTRUSIVE_LOCKFREESTACK_H_INCLUDED + +#include +#include "../mpl/IfCond.h" +#include "../Atomic.h" +#include "../Uncopyable.h" + +namespace beast { + +//------------------------------------------------------------------------------ + +template +class LockFreeStackIterator + : public std::iterator < + std::forward_iterator_tag, + typename Container::value_type, + typename Container::difference_type, + typename mpl::IfCond ::type, + typename mpl::IfCond ::type> +{ +protected: + typedef typename Container::Node Node; + typedef typename mpl::IfCond ::type NodePtr; + +public: + typedef typename Container::value_type value_type; + typedef typename mpl::IfCond ::type pointer; + typedef typename mpl::IfCond ::type reference; + + LockFreeStackIterator () + : m_node () + { + } + + LockFreeStackIterator (NodePtr node) + : m_node (node) + { + } + + template + explicit LockFreeStackIterator (LockFreeStackIterator const& other) + : m_node (other.m_node) + { + } + + LockFreeStackIterator& operator= (NodePtr node) + { + m_node = node; + return static_cast (*this); + } + + LockFreeStackIterator& operator++ () + { + m_node = m_node->m_next.get(); + return static_cast (*this); + } + + LockFreeStackIterator operator++ (int) + { + LockFreeStackIterator result (*this); + m_node = m_node->m_next; + return result; + } + + NodePtr node() const + { + return m_node; + } + + reference operator* () const + { + return *this->operator-> (); + } + + pointer operator-> () const + { + return static_cast (m_node); + } + +private: + NodePtr m_node; +}; + +//------------------------------------------------------------------------------ + +template +bool operator== (LockFreeStackIterator const& lhs, + LockFreeStackIterator const& rhs) +{ + return lhs.node() == rhs.node(); +} + +template +bool operator!= (LockFreeStackIterator const& lhs, + LockFreeStackIterator const& rhs) +{ + return lhs.node() != rhs.node(); +} + +//------------------------------------------------------------------------------ + +/** Multiple Producer, Multiple Consumer (MPMC) intrusive stack. + + This stack is implemented using the same intrusive interface as List. + All mutations are lock-free. + + The caller is responsible for preventing the "ABA" problem: + http://en.wikipedia.org/wiki/ABA_problem + + @param Tag A type name used to distinguish lists and nodes, for + putting objects in multiple lists. If this parameter is + omitted, the default tag is used. +*/ +template +class LockFreeStack : public Uncopyable +{ +public: + class Node : public Uncopyable + { + public: + Node () + { + } + + explicit Node (Node* next) : m_next (next) + { + } + + private: + friend class LockFreeStack; + + template + friend class LockFreeStackIterator; + + Atomic m_next; + }; + +public: + typedef Element value_type; + typedef Element* pointer; + typedef Element& reference; + typedef Element const* const_pointer; + typedef Element const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef LockFreeStackIterator < + LockFreeStack , false> iterator; + typedef LockFreeStackIterator < + LockFreeStack , true> const_iterator; + + LockFreeStack () + : m_end (nullptr) + , m_head (&m_end) + { + } + + /** Returns true if the stack is empty. */ + bool empty() const + { + return m_head.get() == &m_end; + } + + /** Push a node onto the stack. + The caller is responsible for preventing the ABA problem. + This operation is lock-free. + Thread safety: + Safe to call from any thread. + + @param node The node to push. + + @return `true` if the stack was previously empty. If multiple threads + are attempting to push, only one will receive `true`. + */ + bool push_front (Node* node) + { + bool first; + Node* head; + do + { + head = m_head.get (); + first = head == &m_end; + node->m_next = head; + } + while (!m_head.compareAndSetBool (node, head)); + return first; + } + + /** Pop an element off the stack. + The caller is responsible for preventing the ABA problem. + This operation is lock-free. + Thread safety: + Safe to call from any thread. + + @return The element that was popped, or `nullptr` if the stack + was empty. + */ + Element* pop_front () + { + Node* node; + Node* head; + do + { + node = m_head.get (); + if (node == &m_end) + return nullptr; + head = node->m_next.get (); + } + while (!m_head.compareAndSetBool (head, node)); + return static_cast (node); + } + + /** Return a forward iterator to the beginning or end of the stack. + Undefined behavior results if push_front or pop_front is called + while an iteration is in progress. + Thread safety: + Caller is responsible for synchronization. + */ + /** @{ */ + iterator begin () + { + return iterator (m_head.get ()); + } + + iterator end () + { + return iterator (&m_end); + } + + const_iterator begin () const + { + return const_iterator (m_head.get ()); + } + + const_iterator end () const + { + return const_iterator (&m_end); + } + + const_iterator cbegin () const + { + return const_iterator (m_head.get ()); + } + + const_iterator cend () const + { + return const_iterator (&m_end); + } + /** @} */ + +private: + Node m_end; + Atomic m_head; +}; + +} + +#endif diff --git a/beast/intrusive/PointerTraits.h b/beast/intrusive/PointerTraits.h index e4e733e38b..ccba95f91e 100644 --- a/beast/intrusive/PointerTraits.h +++ b/beast/intrusive/PointerTraits.h @@ -20,6 +20,8 @@ #ifndef BEAST_INTRUSIVE_POINTERTRAITS_H_INCLUDED #define BEAST_INTRUSIVE_POINTERTRAITS_H_INCLUDED +#include + namespace beast { namespace intrusive { diff --git a/beast/mpl/AddConst.h b/beast/mpl/AddConst.h index 4b25ecd0bd..3ab16e6b7d 100644 --- a/beast/mpl/AddConst.h +++ b/beast/mpl/AddConst.h @@ -20,16 +20,18 @@ #ifndef BEAST_MPL_ADDCONST_H_INCLUDED #define BEAST_MPL_ADDCONST_H_INCLUDED +#include "RemoveConst.h" + // Ideas based on boost namespace beast { namespace mpl { -/// Add the `const` qualifier to a type. +/** Add the `const` qualifier to a type. */ template struct AddConst { - typedef T const type; + typedef typename RemoveConst::type const type; }; } diff --git a/modules/beast_core/containers/detail/copyconst.h b/beast/mpl/CopyConst.h similarity index 75% rename from modules/beast_core/containers/detail/copyconst.h rename to beast/mpl/CopyConst.h index ac8d74d5c0..a733ded884 100644 --- a/modules/beast_core/containers/detail/copyconst.h +++ b/beast/mpl/CopyConst.h @@ -17,25 +17,30 @@ */ //============================================================================== -#ifndef BEAST_CORE_CONTAINERS_DETAIL_COPYCONST_H_INCLUDED -#define BEAST_CORE_CONTAINERS_DETAIL_COPYCONST_H_INCLUDED +#ifndef BEAST_MPL_COPYCONST_H_INCLUDED +#define BEAST_MPL_COPYCONST_H_INCLUDED -namespace detail -{ +#include "RemoveConst.h" -// Copy const attribute from T to U if present +namespace beast { +namespace mpl { + +/** Copy `const` attribute from T to U if present. */ +/** @{ */ template -struct copyconst +struct CopyConst { - typedef typename removecv ::type type; + typedef typename RemoveConst::type type; }; template -struct copyconst +struct CopyConst { - typedef typename removecv ::type const type; + typedef typename RemoveConst::type const type; }; +/** @} */ +} } #endif diff --git a/beast/mpl/IfCond.h b/beast/mpl/IfCond.h index 499dfced76..44aad16137 100644 --- a/beast/mpl/IfCond.h +++ b/beast/mpl/IfCond.h @@ -25,8 +25,8 @@ namespace mpl { // Ideas based on boost -/// Select between T1 or T2 depending on Condition. -/// @{ +/** Select between T1 or T2 depending on Condition. */ +/** @{ */ template struct IfCond { @@ -38,7 +38,7 @@ struct IfCond { typedef T2 type; }; -/// @} +/** @} */ } } diff --git a/beast/mpl/IsCallPossible.h b/beast/mpl/IsCallPossible.h new file mode 100644 index 0000000000..d6a6ffb108 --- /dev/null +++ b/beast/mpl/IsCallPossible.h @@ -0,0 +1,270 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_MPL_ISCALLPOSSIBLE_H_INCLUDED +#define BEAST_MPL_ISCALLPOSSIBLE_H_INCLUDED + +namespace beast { +namespace mpl { + +// inspired by Roman Perepelitsa's presentation from comp.lang.c++.moderated +// based on the implementation here: http://www.rsdn.ru/forum/cpp/2759773.1.aspx +// +namespace is_call_possible_detail +{ + template + struct add_reference + { + typedef T& type; + }; + + template + struct add_reference + { + typedef T& type; + }; + + template class void_exp_result {}; + + template + U const& operator,(U const&, void_exp_result); + + template + U& operator,(U&, void_exp_result); + + template + struct clone_constness + { + typedef dest_type type; + }; + + template + struct clone_constness + { + typedef const dest_type type; + }; +} + +#define BEAST_DEFINE_HAS_MEMBER_FUNCTION(trait_name, member_function_name) \ +template class trait_name; \ + \ +template \ +class trait_name \ +{ \ + class yes { char m; }; \ + class no { yes m[2]; }; \ + struct base_mixin \ + { \ + Result member_function_name(); \ + }; \ + struct base : public T, public base_mixin { private: base(); }; \ + template class helper{}; \ + template \ + static no deduce(U*, helper* = 0); \ + static yes deduce(...); \ +public: \ + static const bool value = sizeof(yes) == sizeof(deduce(static_cast(0))); \ +}; \ + \ +template \ +class trait_name \ +{ \ + class yes { char m; }; \ + class no { yes m[2]; }; \ + struct base_mixin \ + { \ + Result member_function_name(Arg); \ + }; \ + struct base : public T, public base_mixin { private: base(); }; \ + template class helper{}; \ + template \ + static no deduce(U*, helper* = 0); \ + static yes deduce(...); \ +public: \ + static const bool value = sizeof(yes) == sizeof(deduce(static_cast(0))); \ +}; \ + \ +template \ +class trait_name \ +{ \ + class yes { char m; }; \ + class no { yes m[2]; }; \ + struct base_mixin \ + { \ + Result member_function_name(Arg1,Arg2); \ + }; \ + struct base : public T, public base_mixin { private: base(); }; \ + template class helper{}; \ + template \ + static no deduce(U*, helper* = 0); \ + static yes deduce(...); \ +public: \ + static const bool value = sizeof(yes) == sizeof(deduce(static_cast(0))); \ +}; \ + \ +template \ +class trait_name \ +{ \ + class yes { char m; }; \ + class no { yes m[2]; }; \ + struct base_mixin \ + { \ + Result member_function_name(Arg1,Arg2,Arg3); \ + }; \ + struct base : public T, public base_mixin { private: base(); }; \ + template class helper{}; \ + template \ + static no deduce(U*, helper* = 0); \ + static yes deduce(...); \ +public: \ + static const bool value = sizeof(yes) == sizeof(deduce(static_cast(0))); \ +}; \ + \ +template \ +class trait_name \ +{ \ + class yes { char m; }; \ + class no { yes m[2]; }; \ + struct base_mixin \ + { \ + Result member_function_name(Arg1,Arg2,Arg3,Arg4); \ + }; \ + struct base : public T, public base_mixin { private: base(); }; \ + template class helper{}; \ + template \ + static no deduce(U*, helper* = 0); \ + static yes deduce(...); \ +public: \ + static const bool value = sizeof(yes) == sizeof(deduce(static_cast(0))); \ +} + +#define BEAST_DEFINE_IS_CALL_POSSIBLE(trait_name, member_function_name) \ +struct trait_name##_detail \ +{ \ +BEAST_DEFINE_HAS_MEMBER_FUNCTION(has_member, member_function_name); \ +}; \ + \ +template \ +struct trait_name \ +{ \ + private: \ + class yes {}; \ + class no { yes m[2]; }; \ + struct derived : public T \ + { \ + using T::member_function_name; \ + no member_function_name(...) const; \ + private: derived (); \ + }; \ + \ + typedef typename beast::mpl::is_call_possible_detail::clone_constness::type derived_type; \ + \ + template \ + struct return_value_check \ + { \ + static yes deduce(Result); \ + static no deduce(...); \ + static no deduce(no); \ + static no deduce(beast::mpl::is_call_possible_detail::void_exp_result); \ + }; \ + \ + template \ + struct return_value_check \ + { \ + static yes deduce(...); \ + static no deduce(no); \ + }; \ + \ + template \ + struct impl \ + { \ + static const bool value = false; \ + }; \ + \ + template \ + struct impl \ + { \ + static typename beast::mpl::is_call_possible_detail::add_reference::type test_me; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg; \ + \ + static const bool value = \ + sizeof( \ + return_value_check::deduce( \ + (test_me.member_function_name(arg), beast::mpl::is_call_possible_detail::void_exp_result()) \ + ) \ + ) == sizeof(yes); \ + }; \ + \ + template \ + struct impl \ + { \ + static typename beast::mpl::is_call_possible_detail::add_reference::type test_me; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg1; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg2; \ + \ + static const bool value = \ + sizeof( \ + return_value_check::deduce( \ + (test_me.member_function_name(arg1,arg2), beast::mpl::is_call_possible_detail::void_exp_result()) \ + ) \ + ) == sizeof(yes); \ + }; \ + \ + template \ + struct impl \ + { \ + static typename beast::mpl::is_call_possible_detail::add_reference::type test_me; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg1; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg2; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg3; \ + \ + static const bool value = \ + sizeof( \ + return_value_check::deduce( \ + (test_me.member_function_name(arg1,arg2,arg3), beast::mpl::is_call_possible_detail::void_exp_result()) \ + ) \ + ) == sizeof(yes); \ + }; \ + \ + template \ + struct impl \ + { \ + static typename beast::mpl::is_call_possible_detail::add_reference::type test_me; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg1; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg2; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg3; \ + static typename beast::mpl::is_call_possible_detail::add_reference::type arg4; \ + \ + static const bool value = \ + sizeof( \ + return_value_check::deduce( \ + (test_me.member_function_name(arg1,arg2,arg3,arg4), \ + beast::mpl::is_call_possible_detail::void_exp_result()) \ + ) \ + ) == sizeof(yes); \ + }; \ + \ + public: \ + static const bool value = impl::value, Signature>::value; \ +} + +} +} + +#endif diff --git a/beast/mpl/PointerToOther.h b/beast/mpl/PointerToOther.h index 868d46bb0f..8a82274f30 100644 --- a/beast/mpl/PointerToOther.h +++ b/beast/mpl/PointerToOther.h @@ -30,7 +30,7 @@ namespace mpl { parameters. More specializations can be added for containers with more than three template parameters. */ -/// @{ +/** @{ */ template struct PointerToOther; @@ -60,7 +60,7 @@ struct PointerToOther { typedef U* type; }; -/// @} +/** @} */ } } diff --git a/beast/mpl/RemoveConst.h b/beast/mpl/RemoveConst.h index 4f555f26a8..86f58b9f36 100644 --- a/beast/mpl/RemoveConst.h +++ b/beast/mpl/RemoveConst.h @@ -25,8 +25,8 @@ namespace beast { namespace mpl { -/// Remove the `const` qualifier from a type. -/// @{ +/** Remove the `const` qualifier from a type. */ +/** @{ */ template struct RemoveConst { @@ -38,7 +38,7 @@ struct RemoveConst { typedef T type; }; -/// @} +/** @} */ } } diff --git a/beast/mpl/RemoveConstVolatile.h b/beast/mpl/RemoveConstVolatile.h index 361f0255ac..b320d507b6 100644 --- a/beast/mpl/RemoveConstVolatile.h +++ b/beast/mpl/RemoveConstVolatile.h @@ -28,7 +28,7 @@ namespace beast { namespace mpl { -/// Remove both the `const` and `volatile` qualifiers from a type. +/** Remove both the `const` and `volatile` qualifiers from a type. */ template struct RemoveConstVolatile { diff --git a/beast/mpl/RemoveReference.h b/beast/mpl/RemoveReference.h index 239addcca7..c7b8d6d651 100644 --- a/beast/mpl/RemoveReference.h +++ b/beast/mpl/RemoveReference.h @@ -25,8 +25,8 @@ namespace mpl { // Ideas based on boost -/// Remove the reference qualifier from a type. -/// @{ +/** Remove the reference qualifier from a type. */ +/** @{ */ template struct RemoveReference { @@ -38,7 +38,7 @@ struct RemoveReference { typedef T type; }; -/// @} +/** @} */ } } diff --git a/beast/mpl/RemoveVolatile.h b/beast/mpl/RemoveVolatile.h index 26a848724e..5057a16bdd 100644 --- a/beast/mpl/RemoveVolatile.h +++ b/beast/mpl/RemoveVolatile.h @@ -25,8 +25,8 @@ namespace beast { namespace mpl { -/// Remove the `volatile` qualifier from a type. -/// @{ +/** Remove the `volatile` qualifier from a type. */ +/** @{ */ template struct RemoveVolatile { @@ -38,7 +38,7 @@ struct RemoveVolatile { typedef T type; }; -/// @} +/** @} */ } } diff --git a/modules/beast_asio/basics/BufferType.h b/beast/net/BufferType.h similarity index 91% rename from modules/beast_asio/basics/BufferType.h rename to beast/net/BufferType.h index 722fe4befc..a94990a3bf 100644 --- a/modules/beast_asio/basics/BufferType.h +++ b/beast/net/BufferType.h @@ -17,8 +17,12 @@ */ //============================================================================== -#ifndef BEAST_ASIO_BASICS_BUFFERTYPE_H_INCLUDED -#define BEAST_ASIO_BASICS_BUFFERTYPE_H_INCLUDED +#ifndef BEAST_NET_BASICS_BUFFERTYPE_H_INCLUDED +#define BEAST_NET_BASICS_BUFFERTYPE_H_INCLUDED + +#include "../mpl/IfCond.h" + +namespace beast { /** General linear memory buffer. This wraps the underlying buffer type and provides additional methods @@ -49,7 +53,7 @@ public: template BufferType (BufferType const& other) - : m_data (other.cast ()) + : m_data (other.template cast ()) , m_size (other.size ()) { } @@ -71,7 +75,7 @@ public: BufferType& operator= ( BufferType const& other) noexcept { - m_data = other.cast (); + m_data = other.template cast (); m_size = other.size (); return *this; } @@ -99,4 +103,6 @@ private: }; /** @} */ +} + #endif diff --git a/beast/net/DynamicBuffer.h b/beast/net/DynamicBuffer.h new file mode 100644 index 0000000000..34d2a6d749 --- /dev/null +++ b/beast/net/DynamicBuffer.h @@ -0,0 +1,125 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_NET_DYNAMICBUFFER_H_INCLUDED +#define BEAST_NET_DYNAMICBUFFER_H_INCLUDED + +#include + +namespace beast { + +/** Disjoint, but efficient buffer storage for network operations. + This is designed to not require asio in order to compile. +*/ +class DynamicBuffer +{ +public: + enum + { + defaultBlocksize = 32 * 1024 + }; + + typedef std::size_t size_type; + + /** Create the dynamic buffer with the specified block size. */ + explicit DynamicBuffer (size_type blocksize = defaultBlocksize); + + DynamicBuffer (DynamicBuffer const& other); + + ~DynamicBuffer (); + + DynamicBuffer& operator= (DynamicBuffer const& other); + + /** Swap the contents of this buffer with another. + This is the preferred way to transfer ownership. + */ + void swapWith (DynamicBuffer& other); + + /** Returns the size of the input sequence. */ + size_type size () const; + + /** Returns a buffer to the input sequence. + ConstBufferType must be constructible with this signature: + ConstBufferType (void const* buffer, size_type bytes); + */ + template + std::vector data () const + { + std::vector buffers; + buffers.reserve (m_buffers.size()); + size_type amount (m_size); + for (typename Buffers::const_iterator iter (m_buffers.begin()); + amount > 0 && iter != m_buffers.end(); ++iter) + { + size_type const n (std::min (amount, m_blocksize)); + buffers.push_back (ConstBufferType (*iter, n)); + amount -= n; + } + return buffers; + } + + /** Reserve space in the output sequence. + This also returns a buffer suitable for writing. + MutableBufferType must be constructible with this signature: + MutableBufferType (void* buffer, size_type bytes); + */ + template + std::vector prepare (size_type amount) + { + std::vector buffers; + buffers.reserve (m_buffers.size()); + reserve (amount); + size_type offset (m_size % m_blocksize); + for (Buffers::iterator iter = m_buffers.begin () + (m_size / m_blocksize); + amount > 0 && iter != m_buffers.end (); ++iter) + { + size_type const n (std::min (amount, m_blocksize - offset)); + buffers.push_back (MutableBufferType ( + ((static_cast (*iter)) + offset), n)); + amount -= n; + offset = 0; + } + return buffers; + } + + /** Reserve space in the output sequence. */ + void reserve (size_type n); + + /** Move bytes from the output to the input sequence. */ + void commit (size_type n); + + /** Release memory while preserving the input sequence. */ + void shrink_to_fit (); + + /** Convert the entire buffer into a single string. + This is mostly for diagnostics, it defeats the purpose of the class! + */ + std::string to_string () const; + +private: + typedef std::vector Buffers; + + size_type m_blocksize; + size_type m_size; + Buffers m_buffers; +}; + +} + +#endif diff --git a/beast/net/IPEndpoint.h b/beast/net/IPEndpoint.h new file mode 100644 index 0000000000..1852297179 --- /dev/null +++ b/beast/net/IPEndpoint.h @@ -0,0 +1,378 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_NET_IPENDPOINT_H_INCLUDED +#define BEAST_NET_IPENDPOINT_H_INCLUDED + +#include +#include +#include + +#include "../CStdInt.h" +#include "../mpl/IfCond.h" + +namespace beast +{ + +/** Represents an IP address (v4 or v6) and port combination. */ +class IPEndpoint +{ +public: + enum Type + { + none, + ipv4, + ipv6 + }; + + template + static std::string numberToString (Number n) + { + std::ostringstream os; + os << std::dec << n; + return std::string (os.str()); + } + + //-------------------------------------------------------------------------- + + /** Used for IPv4 formats. */ + struct V4 + { + /** Construct the "any" address. */ + V4 (); + + /** Construct from a 32-bit unsigned. + @note Octets are formed in order from the MSB to the LSB. + */ + explicit V4 (uint32 value_); + + /** Construct from four individual octets.. + @note The resulting address is a.b.c.d + */ + V4 (uint8 a, uint8 b, uint8 c, uint8 d); + + /** Construct a copy of another address. */ + V4 (V4 const& other); + + /** Assign a copy of another address. */ + V4& operator= (V4 const& other); + + /** Returns a V4 address representing the local broadcast address. */ + static V4 localBroadcastAddress (); + + /** Returns the directed broadcast address for the network implied by this address. */ + V4 broadcastAddress () const; + + /** Returns the IPv4 address class as 'A', 'B', 'C', or 'D'. + @note Class 'D' represents multicast addresses (224.*.*.*). + */ + char getClass () const; + + /** Returns `true` if this is a public routable address. */ + bool isPublic () const; + + /** Returns `true` if this is a private, non-routable address. */ + bool isPrivate () const; + + /** Returns `true` if this is a broadcast address. */ + bool isBroadcast () const; + + /** Returns `true` if this is a multicast address. */ + bool isMulticast () const; + + /** Returns `true` if this refers to any loopback adapter address. */ + bool isLoopback () const; + + /** Supports access via operator[]. */ + template + class Proxy + { + public: + typedef typename mpl::IfCond ::type Pointer; + + Proxy (int shift, Pointer value) + : m_shift (shift) + , m_value (value) + { + } + + operator uint8() const + { + return ((*m_value)>>m_shift)&0xff; + } + + template + Proxy& operator= (IntegralType v) + { + (*m_value)= + (*m_value)&(!((0xff)< operator[] (std::size_t index) const; + + /** Provides read/write access to individual octets of the IPv4 address. */ + Proxy operator[] (std::size_t index); + + /** Convert the address to a human readable string. */ + /** @{ */ + std::string to_string () const; + operator std::string () const; + /** @} */ + + struct hasher + { + std::size_t operator() (V4 const& v) const + { + return v.value; + } + }; + + /** The value as a 32 bit unsigned. */ + uint32 value; + }; + + //-------------------------------------------------------------------------- + + /** Used for IPv6 formats. */ + struct V6 + { + /** Returns `true` if this is a public routable address. */ + bool isPublic () const + { + return false; + } + + /** Returns `true` if this is a private, non-routable address. */ + bool isPrivate () const + { + return false; + } + + /** Returns `true` if this is a broadcast address. */ + bool isBroadcast () const + { + return false; + } + + /** Returns `true` if this is a multicast address. */ + bool isMulticast () const + { + return false; + } + + /** Returns `true` if this refers to any loopback adapter address. */ + bool isLoopback () const + { + return false; + } + + /** Convert the address to a human readable string. */ + /** @{ */ + std::string to_string () const + { + return std::string(); + } + + operator std::string () const + { + return to_string(); + } + /** @} */ + + struct hasher + { + std::size_t operator() (V6 const&) const + { + return 0; + } + }; + }; + + //-------------------------------------------------------------------------- + + /** Create an empty address. */ + IPEndpoint (); + + /** Create an IPv4 address with optional port. */ + IPEndpoint (V4 const& v4, uint16 port = 0); + + /** Create an IPv6 address with optional port. */ + IPEndpoint (V6 const& v6, uint16 port = 0); + + /** Create a copy of another IPEndpoint. */ + IPEndpoint (IPEndpoint const& other); + + /** Copy assign another IPEndpoint. */ + IPEndpoint& operator= (IPEndpoint const& other); + + /** Create an IPEndpoint from a string. + If a parsing error occurs, the endpoint will be empty. + */ + static IPEndpoint from_string (std::string const& s); + + /** Create an IPEndpoint from a string. + If a parsing error occurs, the endpoint will be empty. + This recognizes an alternate form of the text. Instead of a colon + separating the optional port specification, any amount of whitespace + is allowed. + */ + static IPEndpoint from_string_altform (std::string const& s); + + /** Copy assign an IPv4 address. + The port is set to zero. + */ + IPEndpoint& operator= (V4 const& address); + + /** Copy assign an IPv6 address. + The port is set to zero. + */ + IPEndpoint& operator= (V6 const& address); + + /** Returns a new IPEndpoint with this address, and the given port. */ + IPEndpoint withPort (uint16 port) const; + + /** Returns `true` if this IPEndpoint refers to nothing. */ + bool empty () const; + + /** Returns `true` if this IPEndpoint refers to nothing. */ + bool isNull () const; + + /** Returns `true` if this IPEndpoint refers to something. */ + bool isNotNull () const; + + /** Returns the type of this IPEndpoint. */ + Type type () const; + + /** Returns `true` if this IPEndpoint represents an IPv4 address. */ + bool isV4 () const; + + /** Returns `true` if this IPEndpoint represents an IPv6 address. */ + bool isV6 () const; + + /** Returns the IPv4 address. + Undefined behavior results if type() != ipv4. + */ + V4 const& v4 () const; + + /** Returns the IPv6 address. + Undefined behavior results if type() != ipv4. + */ + V6 const& v6 () const; + + /** Returns the port number. + Undefined if type() == none. + */ + uint16 port () const; + + /** Returns `true` if this is a public routable address. */ + bool isPublic () const; + + /** Returns `true` if this is a private, non-routable address. */ + bool isPrivate () const; + + /** Returns `true` if this is a broadcast address. */ + bool isBroadcast () const; + + /** Returns `true` if this is a multicast address. */ + bool isMulticast () const; + + /** Returns `true` if this refers to any loopback adapter address. */ + bool isLoopback () const; + + /** Convert the address to a human readable string. */ + /** @{ */ + std::string to_string () const; + operator std::string () const; + /** @} */ + + struct hasher + { + std::size_t operator() (IPEndpoint const& value) const + { + std::size_t hash (0); + if (value.isV4()) + hash = V4::hasher() (value.v4()); + else if (value.isV6()) + hash = V6::hasher() (value.v6()); + hash += value.port(); + return hash; + } + }; + + struct key_equal; + +private: + Type m_type; + uint16 m_port; + V4 m_v4; + V6 m_v6; +}; + +/** Comparison. */ +/** @{ */ +int compare (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); +bool operator== (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); +bool operator!= (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); +bool operator< (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); +bool operator<= (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); +bool operator> (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); +bool operator>= (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs); + +int compare (IPEndpoint const& lhs, IPEndpoint const& rhs); +bool operator== (IPEndpoint const& lhs, IPEndpoint const& rhs); +bool operator!= (IPEndpoint const& lhs, IPEndpoint const& rhs); +bool operator< (IPEndpoint const& lhs, IPEndpoint const& rhs); +bool operator<= (IPEndpoint const& lhs, IPEndpoint const& rhs); +bool operator> (IPEndpoint const& lhs, IPEndpoint const& rhs); +bool operator>= (IPEndpoint const& lhs, IPEndpoint const& rhs); + +/** Output stream conversions. */ +/** @{ */ +std::ostream& operator<< (std::ostream& os, IPEndpoint::V4 const& addr); +std::ostream& operator<< (std::ostream& os, IPEndpoint::V6 const& addr); +std::ostream& operator<< (std::ostream& os, IPEndpoint const& ep); +/** @} */ + +/** Input stream conversions. */ +/** @{ */ +std::istream& operator>> (std::istream& is, IPEndpoint::V4& addr); +std::istream& operator>> (std::istream& is, IPEndpoint& ep); +//std::istream& operator>> (std::istream &is, IPEndpoint::V6&); +/** @} */ + +struct IPEndpoint::key_equal +{ + bool operator() (IPEndpoint const& lhs, IPEndpoint const& rhs) const + { + return lhs == rhs; + } +}; + +} + +#endif diff --git a/beast/net/Net.cpp b/beast/net/Net.cpp new file mode 100644 index 0000000000..6a84e21858 --- /dev/null +++ b/beast/net/Net.cpp @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "../Config.h" + +#include "../../modules/beast_core/beast_core.h" // for UnitTest + +#include "impl/DynamicBuffer.cpp" +#include "impl/IPEndpoint.cpp" diff --git a/beast/net/impl/DynamicBuffer.cpp b/beast/net/impl/DynamicBuffer.cpp new file mode 100644 index 0000000000..4dec2d5dfb --- /dev/null +++ b/beast/net/impl/DynamicBuffer.cpp @@ -0,0 +1,91 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include + +#include "../DynamicBuffer.h" + +namespace beast { + +DynamicBuffer::DynamicBuffer (size_type blocksize) + : m_blocksize (blocksize) + , m_size (0) +{ +} + +DynamicBuffer::~DynamicBuffer () +{ + for (Buffers::iterator iter (m_buffers.begin()); + iter != m_buffers.end(); ++iter) + free (*iter); +} + +void DynamicBuffer::swapWith (DynamicBuffer& other) +{ + std::swap (m_blocksize, other.m_blocksize); + std::swap (m_size, other.m_size); + m_buffers.swap (other.m_buffers); +} + +void DynamicBuffer::commit (size_type n) +{ + m_size += n; + bassert (m_size <= m_buffers.size () * m_blocksize); +} + +DynamicBuffer::size_type DynamicBuffer::size () const +{ + return m_size; +} + +void DynamicBuffer::reserve (size_type n) +{ + size_type count ((m_size + n + m_blocksize - 1) / m_blocksize); + if (count > m_buffers.size ()) + for (count -= m_buffers.size (); count-- > 0;) + m_buffers.push_back (malloc (m_blocksize)); +} + +void DynamicBuffer::shrink_to_fit () +{ + size_type const count ((m_size + m_blocksize - 1) / m_blocksize); + while (m_buffers.size () > count) + { + free (m_buffers.back ()); + m_buffers.erase (m_buffers.end () - 1); + } +} + +std::string DynamicBuffer::to_string () const +{ + std::string (s); + s.reserve (m_size); + std::size_t amount (m_size); + for (Buffers::const_iterator iter (m_buffers.begin()); + amount > 0 && iter != m_buffers.end(); ++iter) + { + char const* p (static_cast (*iter)); + size_type const n (std::min (amount, m_blocksize)); + s.append (p, p + n); + amount -= n; + } + return s; +} + +} diff --git a/beast/net/impl/IPEndpoint.cpp b/beast/net/impl/IPEndpoint.cpp new file mode 100644 index 0000000000..ffa2bf77bf --- /dev/null +++ b/beast/net/impl/IPEndpoint.cpp @@ -0,0 +1,717 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../IPEndpoint.h" + +namespace beast +{ + +IPEndpoint::V4::V4 () + : value (0) +{ +} + +IPEndpoint::V4::V4 (uint32 value_) + : value (value_) +{ +} + +IPEndpoint::V4::V4 (uint8 a, uint8 b, uint8 c, uint8 d) + : value ((a<<24)|(b<<16)|(c<<8)|d) +{ +} + +IPEndpoint::V4::V4 (V4 const& other) + : value (other.value) +{ +} + +IPEndpoint::V4& IPEndpoint::V4::operator= (V4 const& other) +{ + value = other.value; + return *this; +} + +IPEndpoint::V4 IPEndpoint::V4::localBroadcastAddress () +{ + return V4 (0xffffffff); +} + +IPEndpoint::V4 IPEndpoint::V4::broadcastAddress () const +{ + switch (getClass()) + { + case 'A': return V4 ((value&0xff000000)|0x00ffffff); + case 'B': return V4 ((value&0xffff0000)|0x0000ffff); + case 'C': return V4 ((value&0xffffff00)|0x000000ff); + default: + case 'D': + bassertfalse; + break; + } + return V4(); +} + +char IPEndpoint::V4::getClass () const +{ + static char const* table = "AAAABBCD"; + return table[(value&0xE0000000)>>29]; +} + +bool IPEndpoint::V4::isPublic () const +{ + return !isPrivate() && !isBroadcast() && !isMulticast(); +} + +bool IPEndpoint::V4::isPrivate () const +{ + return + ((value&0xff000000)==0x0a000000) || // Prefix /8, 10.##.#.# + ((value&0xfff00000)==0xac100000) || // Prefix /12 172.16.#.# - 172.31.#.# + ((value&0xffff0000)==0xc0a80000) || // Prefix /16 192.168.#.# + isLoopback(); +} + +bool IPEndpoint::V4::isBroadcast () const +{ + return (value == broadcastAddress().value); +} + +bool IPEndpoint::V4::isMulticast () const +{ + return getClass() == 'D'; +} + +bool IPEndpoint::V4::isLoopback () const +{ + return (value&0xff000000)==0x7f000000; +} + +IPEndpoint::V4::Proxy IPEndpoint::V4::operator[] (std::size_t index) const +{ + switch (index) + { + default: + bassertfalse; + case 0: return Proxy (24, &value); + case 1: return Proxy (16, &value); + case 2: return Proxy ( 8, &value); + case 3: return Proxy ( 0, &value); + }; +}; + +IPEndpoint::V4::Proxy IPEndpoint::V4::operator[] (std::size_t index) +{ + switch (index) + { + default: + bassertfalse; + case 0: return Proxy (24, &value); + case 1: return Proxy (16, &value); + case 2: return Proxy ( 8, &value); + case 3: return Proxy ( 0, &value); + }; +}; + +std::string IPEndpoint::V4::to_string () const +{ + std::string s; + s.reserve (15); + s.append (numberToString ((int)((*this)[0]))); s.push_back ('.'); + s.append (numberToString ((int)((*this)[1]))); s.push_back ('.'); + s.append (numberToString ((int)((*this)[2]))); s.push_back ('.'); + s.append (numberToString ((int)((*this)[3]))); + return s; +} + +IPEndpoint::V4::operator std::string () const +{ + return to_string(); +} + +//------------------------------------------------------------------------------ + +IPEndpoint::IPEndpoint () + : m_type (none) +{ +} + +IPEndpoint::IPEndpoint (V4 const& v4, uint16 port) + : m_type (ipv4) + , m_port (port) + , m_v4 (v4) +{ +} + +IPEndpoint::IPEndpoint (V6 const& v6, uint16 port) + : m_type (ipv6) + , m_port (port) + , m_v6 (v6) +{ +} + +IPEndpoint::IPEndpoint (IPEndpoint const& other) + : m_type (other.m_type) + , m_port (other.m_port) +{ + switch (m_type) + { + case ipv4: m_v4 = other.m_v4; break; + case ipv6: m_v6 = other.m_v6; break; + default: + case none: + break; + }; +} + +IPEndpoint& IPEndpoint::operator= (IPEndpoint const& other) +{ + m_type = other.m_type; + m_port = other.m_port; + switch (m_type) + { + case ipv4: m_v4 = other.m_v4; break; + case ipv6: m_v6 = other.m_v6; break; + default: + case none: + break; + }; + return *this; +} + +IPEndpoint IPEndpoint::from_string (std::string const& s) +{ + std::stringstream is (s); + IPEndpoint ep; + is >> ep; + if (! is.fail() && is.rdbuf()->in_avail() == 0) + return ep; + return IPEndpoint(); +} + +IPEndpoint& IPEndpoint::operator= (V4 const& address) +{ + m_type = ipv4; + m_port = 0; + m_v4 = address; + return *this; +} + +IPEndpoint& IPEndpoint::operator= (V6 const& address) +{ + m_type = ipv6; + m_port = 0; + m_v6 = address; + return *this; +} + +IPEndpoint IPEndpoint::withPort (uint16 port) const +{ + switch (m_type) + { + case ipv4: return IPEndpoint (m_v4, port); + case ipv6: return IPEndpoint (m_v6, port); + default: + case none: + bassertfalse; + break; + }; + return IPEndpoint(); +} + +bool IPEndpoint::empty () const +{ + return m_type == none; +} + +bool IPEndpoint::isNull () const +{ + return empty (); +} + +bool IPEndpoint::isNotNull () const +{ + return ! empty (); +} + +IPEndpoint::Type IPEndpoint::type () const +{ + return m_type; +} + +bool IPEndpoint::isV4 () const +{ + return m_type == ipv4; +} + +bool IPEndpoint::isV6 () const +{ + return m_type == ipv6; +} + +IPEndpoint::V4 const& IPEndpoint::v4 () const +{ + return m_v4; +} + +IPEndpoint::V6 const& IPEndpoint::v6 () const +{ + return m_v6; +} + +uint16 IPEndpoint::port () const +{ + return m_port; +} + +bool IPEndpoint::isPublic () const +{ + switch (m_type) + { + case ipv4: return m_v4.isPublic(); + case ipv6: return m_v6.isPublic(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isPrivate () const +{ + switch (m_type) + { + case ipv4: return m_v4.isPrivate(); + case ipv6: return m_v6.isPrivate(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isBroadcast () const +{ + switch (m_type) + { + case ipv4: return m_v4.isBroadcast(); + case ipv6: return m_v6.isBroadcast(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isMulticast () const +{ + switch (m_type) + { + case ipv4: return m_v4.isMulticast(); + case ipv6: return m_v6.isMulticast(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +bool IPEndpoint::isLoopback () const +{ + switch (m_type) + { + case ipv4: return m_v4.isLoopback(); + case ipv6: return m_v6.isLoopback(); + default: + bassertfalse; + case none: + break; + }; + return false; +} + +std::string IPEndpoint::to_string () const +{ + switch (m_type) + { + case ipv4: + { + std::string s (m_v4.to_string()); + if (m_port != 0) + { + s.append (":"); + s.append (numberToString (m_port)); + } + return s; + } + + case ipv6: + return m_v6.to_string(); + + default: + case none: + bassertfalse; + break; + }; + return std::string(); +} + +IPEndpoint::operator std::string () const +{ + return to_string(); +} + +//------------------------------------------------------------------------------ + +namespace parse +{ + +/** Require and consume the specified character from the input. + @return `true` if the character matched. +*/ +bool expect (std::istream& is, char v) +{ + char c; + if (is.get(c) && v == c) + return true; + + is.unget(); + is.setstate (std::ios_base::failbit); + return false; +} + +namespace detail +{ + +/** Used to disambiguate 8-bit integers from characters. */ +template +struct integer_holder +{ + IntType* pi; + explicit integer_holder (IntType& i) + : pi (&i) + { + } + template + IntType& operator= (OtherIntType o) const + { + *pi = o; + return *pi; + } +}; + +/** Parse 8-bit unsigned integer. */ +std::istream& operator>> (std::istream& is, integer_holder const& i) +{ + uint16 v; + is >> v; + if (! (v>=0 && v<=255)) + { + is.setstate (std::ios_base::failbit); + return is; + } + i = uint8(v); + return is; +} + +} + +/** Free function for template argument deduction. */ +template +detail::integer_holder integer (IntType& i) +{ + return detail::integer_holder (i); +} + +} + +/** Parse IPv4 address. */ +std::istream& operator>> (std::istream &is, IPEndpoint::V4& addr) +{ + uint8 octets [4]; + is >> parse::integer (octets [0]); + for (int i = 1; i < 4; ++i) + { + if (!is || !parse::expect (is, '.')) + return is; + is >> parse::integer (octets [i]); + if (!is) + return is; + } + addr = IPEndpoint::V4 (octets[0], octets[1], octets[2], octets[3]); + return is; +} + +/** Parse an IPEndpoint. + @note Currently only IPv4 addresses are supported. +*/ +std::istream& operator>> (std::istream &is, IPEndpoint& ep) +{ + IPEndpoint::V4 v4; + is >> v4; + if (is.fail()) + return is; + + if (is.rdbuf()->in_avail()>0) + { + char c; + is.get(c); + if (c != ':') + { + is.unget(); + ep = IPEndpoint (v4); + return is; + } + + uint16 port; + is >> port; + if (is.fail()) + return is; + + ep = IPEndpoint (v4, port); + } + else + { + ep = IPEndpoint (v4); + } + + return is; +} + +//------------------------------------------------------------------------------ + +IPEndpoint IPEndpoint::from_string_altform (std::string const& s) +{ + // Accept the regular form if it parses + { + IPEndpoint ep (IPEndpoint::from_string (s)); + if (! ep.empty()) + return ep; + } + + // Now try the alt form + std::stringstream is (s); + + IPEndpoint::V4 v4; + is >> v4; + if (! is.fail()) + { + IPEndpoint ep (v4); + + if (is.rdbuf()->in_avail()>0) + { + if (! parse::expect (is, ' ')) + return IPEndpoint(); + + while (is.rdbuf()->in_avail()>0) + { + char c; + is.get(c); + if (c != ' ') + { + is.unget(); + break; + } + } + + uint16 port; + is >> port; + if (is.fail()) + return IPEndpoint(); + + return ep.withPort (port); + } + else + { + // Just an address with no port + return ep; + } + } + + // Could be V6 here... + + return IPEndpoint(); +} + +//------------------------------------------------------------------------------ + +int compare (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) +{ + if (lhs.value < rhs.value) + return -1; + else if (lhs.value > rhs.value) + return 1; + return 0; +} + +bool operator== (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) { return compare (lhs, rhs) == 0; } +bool operator!= (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) { return compare (lhs, rhs) != 0; } +bool operator< (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) { return compare (lhs, rhs) < 0; } +bool operator<= (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) { return compare (lhs, rhs) <= 0; } +bool operator> (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) { return compare (lhs, rhs) > 0; } +bool operator>= (IPEndpoint::V4 const& lhs, IPEndpoint::V4 const& rhs) { return compare (lhs, rhs) >= 0; } + +static int type_compare (IPEndpoint const& lhs, IPEndpoint const& rhs) +{ + if (lhs.type() < rhs.type()) + return -1; + else if (lhs.type() > rhs.type()) + return 1; + return 0; +} + +int compare (IPEndpoint const& lhs, IPEndpoint const& rhs) +{ + int const tc (type_compare (lhs, rhs)); + + if (tc < 0) + return -1; + else if (tc > 0) + return 1; + + switch (lhs.type()) + { + case IPEndpoint::none: return 0; + case IPEndpoint::ipv4: return compare (lhs.v4(), rhs.v4()); + default: + case IPEndpoint::ipv6: + break; + }; + bassertfalse; + return 0; +} + +bool operator== (IPEndpoint const& lhs, IPEndpoint const& rhs) { return compare (lhs, rhs) == 0; } +bool operator!= (IPEndpoint const& lhs, IPEndpoint const& rhs) { return compare (lhs, rhs) != 0; } +bool operator< (IPEndpoint const& lhs, IPEndpoint const& rhs) { return compare (lhs, rhs) < 0; } +bool operator<= (IPEndpoint const& lhs, IPEndpoint const& rhs) { return compare (lhs, rhs) <= 0; } +bool operator> (IPEndpoint const& lhs, IPEndpoint const& rhs) { return compare (lhs, rhs) > 0; } +bool operator>= (IPEndpoint const& lhs, IPEndpoint const& rhs) { return compare (lhs, rhs) >= 0; } + +std::ostream& operator<< (std::ostream &os, IPEndpoint::V4 const& addr) +{ + os << addr.to_string(); + return os; +} + +std::ostream& operator<< (std::ostream &os, IPEndpoint::V6 const& addr) +{ + os << addr.to_string(); + return os; +} + +std::ostream& operator<< (std::ostream &os, IPEndpoint const& ep) +{ + os << ep.to_string(); + return os; +} + +//------------------------------------------------------------------------------ + +class IPEndpointTests : public UnitTest +{ +public: + bool parse (char const* text, IPEndpoint& ep) + { + std::string input (text); + std::istringstream stream (input); + stream >> ep; + return !stream.fail(); + } + + void shouldPass (char const* text) + { + IPEndpoint ep; + expect (parse (text, ep)); + expect (ep.to_string() == std::string(text)); + } + + void shouldFail (char const* text) + { + IPEndpoint ep; + unexpected (parse (text, ep)); + } + + void testParse () + { + beginTestCase ("parse"); + + shouldPass ("0.0.0.0"); + shouldPass ("192.168.0.1"); + shouldPass ("168.127.149.132"); + shouldPass ("168.127.149.132:80"); + shouldPass ("168.127.149.132:54321"); + + shouldFail (""); + shouldFail ("255"); + shouldFail ("512"); + shouldFail ("1.2.3.256"); + shouldFail ("1.2.3:80"); + } + + void testPrint () + { + beginTestCase ("addresses"); + + IPEndpoint ep; + + ep = IPEndpoint(IPEndpoint::V4(127,0,0,1)).withPort (80); + expect (!ep.isPublic()); + expect ( ep.isPrivate()); + expect (!ep.isBroadcast()); + expect (!ep.isMulticast()); + expect ( ep.isLoopback()); + expect (ep.to_string() == "127.0.0.1:80"); + + ep = IPEndpoint::V4(10,0,0,1); + expect ( ep.v4().getClass() == 'A'); + expect (!ep.isPublic()); + expect ( ep.isPrivate()); + expect (!ep.isBroadcast()); + expect (!ep.isMulticast()); + expect (!ep.isLoopback()); + expect (ep.to_string() == "10.0.0.1"); + + ep = IPEndpoint::V4(166,78,151,147); + expect ( ep.isPublic()); + expect (!ep.isPrivate()); + expect (!ep.isBroadcast()); + expect (!ep.isMulticast()); + expect (!ep.isLoopback()); + expect (ep.to_string() == "166.78.151.147"); + } + + void runTest () + { + testPrint(); + testParse(); + } + + IPEndpointTests () : UnitTest ("IPEndpoint", "beast") + { + } +}; + +static IPEndpointTests ipEndpointTests; + +} diff --git a/modules/beast_core/memory/beast_ContainerDeletePolicy.h b/beast/smart_ptr/ContainerDeletePolicy.h similarity index 92% rename from modules/beast_core/memory/beast_ContainerDeletePolicy.h rename to beast/smart_ptr/ContainerDeletePolicy.h index 2a282b2940..9d65bf11af 100644 --- a/modules/beast_core/memory/beast_ContainerDeletePolicy.h +++ b/beast/smart_ptr/ContainerDeletePolicy.h @@ -17,8 +17,10 @@ */ //============================================================================== -#ifndef BEAST_CONTAINERDELETEPOLICY_H_INCLUDED -#define BEAST_CONTAINERDELETEPOLICY_H_INCLUDED +#ifndef BEAST_SMARTPTR_CONTAINERDELETEPOLICY_H_INCLUDED +#define BEAST_SMARTPTR_CONTAINERDELETEPOLICY_H_INCLUDED + +namespace beast { /** The DeletePolicy provides a way to destroy objects stored in containers. @@ -45,4 +47,6 @@ struct ContainerDeletePolicy } }; +} + #endif diff --git a/modules/beast_core/memory/beast_ScopedPointer.h b/beast/smart_ptr/ScopedPointer.h similarity index 89% rename from modules/beast_core/memory/beast_ScopedPointer.h rename to beast/smart_ptr/ScopedPointer.h index 09906874cb..5e16c64511 100644 --- a/modules/beast_core/memory/beast_ScopedPointer.h +++ b/beast/smart_ptr/ScopedPointer.h @@ -21,8 +21,16 @@ */ //============================================================================== -#ifndef BEAST_SCOPEDPOINTER_H_INCLUDED -#define BEAST_SCOPEDPOINTER_H_INCLUDED +#ifndef BEAST_SMARTPTR_SCOPEDPOINTER_H_INCLUDED +#define BEAST_SMARTPTR_SCOPEDPOINTER_H_INCLUDED + +#include "../Config.h" +#include "../Uncopyable.h" +#include "../StaticAssert.h" + +#include "ContainerDeletePolicy.h" + +namespace beast { //============================================================================== /** @@ -67,13 +75,13 @@ class ScopedPointer : public Uncopyable public: //============================================================================== /** Creates a ScopedPointer containing a null pointer. */ - inline ScopedPointer() noexcept + inline ScopedPointer() : object (nullptr) { } /** Creates a ScopedPointer that owns the specified object. */ - inline ScopedPointer (ObjectType* const objectToTakePossessionOf) noexcept + inline ScopedPointer (ObjectType* const objectToTakePossessionOf) : object (objectToTakePossessionOf) { } @@ -84,7 +92,7 @@ public: the pointer from the other object to this one, and the other object is reset to be a null pointer. */ - ScopedPointer (ScopedPointer& objectToTransferFrom) noexcept + ScopedPointer (ScopedPointer& objectToTransferFrom) : object (objectToTransferFrom.object) { objectToTransferFrom.object = nullptr; @@ -144,13 +152,13 @@ public: } #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - ScopedPointer (ScopedPointer&& other) noexcept + ScopedPointer (ScopedPointer&& other) : object (other.object) { other.object = nullptr; } - ScopedPointer& operator= (ScopedPointer&& other) noexcept + ScopedPointer& operator= (ScopedPointer&& other) { object = other.object; other.object = nullptr; @@ -160,28 +168,28 @@ public: //============================================================================== /** Returns the object that this ScopedPointer refers to. */ - inline operator ObjectType*() const noexcept { return object; } + inline operator ObjectType*() const { return object; } /** Returns the object that this ScopedPointer refers to. */ - inline ObjectType* get() const noexcept { return object; } + inline ObjectType* get() const { return object; } /** Returns the object that this ScopedPointer refers to. */ - inline ObjectType& operator*() const noexcept { return *object; } + inline ObjectType& operator*() const { return *object; } /** Lets you access methods and properties of the object that this ScopedPointer refers to. */ - inline ObjectType* operator->() const noexcept { return object; } + inline ObjectType* operator->() const { return object; } //============================================================================== /** Removes the current object from this ScopedPointer without deleting it. This will return the current object, and set the ScopedPointer to a null pointer. */ - ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; } + ObjectType* release() { ObjectType* const o = object; object = nullptr; return o; } //============================================================================== /** Swaps this object with that of another ScopedPointer. The two objects simply exchange their pointers. */ - void swapWith (ScopedPointer & other) noexcept + void swapWith (ScopedPointer & other) { // Two ScopedPointers should never be able to refer to the same object - if // this happens, you must have done something dodgy! @@ -200,7 +208,7 @@ private: ObjectType* object; // (Required as an alternative to the overloaded & operator). - const ScopedPointer* getAddress() const noexcept { return this; } + const ScopedPointer* getAddress() const { return this; } #if ! BEAST_MSVC // (MSVC can't deal with multiple copy constructors) /* The copy constructors are private to stop people accidentally copying a const ScopedPointer @@ -227,7 +235,7 @@ private: This can be handy for checking whether this is a null pointer. */ template -bool operator== (const ScopedPointer& pointer1, ObjectType* const pointer2) noexcept +bool operator== (const ScopedPointer& pointer1, ObjectType* const pointer2) { return static_cast (pointer1) == pointer2; } @@ -236,7 +244,7 @@ bool operator== (const ScopedPointer& pointer1, ObjectType* const po This can be handy for checking whether this is a null pointer. */ template -bool operator!= (const ScopedPointer& pointer1, ObjectType* const pointer2) noexcept +bool operator!= (const ScopedPointer& pointer1, ObjectType* const pointer2) { return static_cast (pointer1) != pointer2; } @@ -248,4 +256,7 @@ template void deleteAndZero (ScopedPointer&) { static_bassert (sizeof (Type) == 12345); } #endif -#endif // BEAST_SCOPEDPOINTER_H_INCLUDED +} + +#endif + diff --git a/modules/beast_core/memory/SharedObject.h b/beast/smart_ptr/SharedObject.h similarity index 95% rename from modules/beast_core/memory/SharedObject.h rename to beast/smart_ptr/SharedObject.h index c2853db0a6..53de02c7a7 100644 --- a/modules/beast_core/memory/SharedObject.h +++ b/beast/smart_ptr/SharedObject.h @@ -24,6 +24,12 @@ #ifndef BEAST_SHAREDOBJECT_H_INCLUDED #define BEAST_SHAREDOBJECT_H_INCLUDED +#include "../Config.h" +#include "../Atomic.h" +#include "../Uncopyable.h" + +namespace beast { + //============================================================================== /** Adds reference-counting to an object. @@ -65,7 +71,7 @@ public: This is done automatically by the smart pointer, but is public just in case it's needed for nefarious purposes. */ - inline void incReferenceCount() noexcept + inline void incReferenceCount() const noexcept { ++refCount; } @@ -79,7 +85,7 @@ public: The return value indicates if the reference count dropped to zero, so callers who know the derived type can use the ContainerDeletePolicy. */ - void decReferenceCount () + void decReferenceCount () const { bassert (getReferenceCount() > 0); if (--refCount == 0) @@ -109,7 +115,7 @@ protected: /** Destroy the object. Derived classes can override this for different behaviors. */ - virtual void destroy () + virtual void destroy () const { delete this; } @@ -124,7 +130,7 @@ protected: private: //============================================================================== - Atomic refCount; + Atomic mutable refCount; }; //============================================================================== @@ -184,7 +190,7 @@ protected: bassert (getReferenceCount() == 0); } - virtual void destroy () + virtual void destroy () const { delete this; } @@ -194,4 +200,6 @@ private: int refCount; }; +} + #endif diff --git a/modules/beast_core/memory/SharedPtr.h b/beast/smart_ptr/SharedPtr.h similarity index 87% rename from modules/beast_core/memory/SharedPtr.h rename to beast/smart_ptr/SharedPtr.h index 68333e93c4..36370897f6 100644 --- a/modules/beast_core/memory/SharedPtr.h +++ b/beast/smart_ptr/SharedPtr.h @@ -21,8 +21,13 @@ */ //============================================================================== -#ifndef BEAST_CORE_SHAREDPTR_H_INCLUDED -#define BEAST_CORE_SHAREDPTR_H_INCLUDED +#ifndef BEAST_SMARTPTR_SHAREDPTR_H_INCLUDED +#define BEAST_SMARTPTR_SHAREDPTR_H_INCLUDED + +#include "../Config.h" +#include "SharedObject.h" + +namespace beast { // Visual Studio doesn't seem to do very well when it comes // to templated constructors and assignments so we provide @@ -74,7 +79,7 @@ public: Requirement: U* must be convertible to T* */ - /// @{ + /** @{ */ SharedPtr (T* t) noexcept : m_p (acquire (t)) { @@ -85,14 +90,14 @@ public: : m_p (acquire (u)) { } - /// @} + /** @} */ /** Construct a container holding an object from another container. This will increment the object's reference-count (if it is non-null). Requirement: U* must be convertible to T* */ - /// @{ + /** @{ */ #if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS SharedPtr (SharedPtr const& sp) noexcept : m_p (acquire (sp.get ())) @@ -105,7 +110,7 @@ public: : m_p (acquire (sp.get ())) { } - /// @} + /** @} */ /** Assign a different object to the container. The previous object beind held, if any, loses a reference count and @@ -113,7 +118,7 @@ public: Requirement: U* must be convertible to T* */ - /// @{ + /** @{ */ #if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS SharedPtr& operator= (T* t) { @@ -126,10 +131,10 @@ public: { return assign (u); } - /// @} + /** @} */ /** Assign an object from another container to this one. */ - /// @{ + /** @{ */ SharedPtr& operator= (SharedPtr const& sp) { return assign (sp.get ()); @@ -141,7 +146,7 @@ public: { return assign (sp.get ()); } - /// @} + /** @} */ #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS /** Construct a container with an object transferred from another container. @@ -149,7 +154,7 @@ public: Requires: U* must be convertible to T* */ - /// @{ + /** @{ */ #if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS SharedPtr (SharedPtr && sp) noexcept : m_p (sp.swap (nullptr)) @@ -159,17 +164,17 @@ public: template SharedPtr (SharedPtr && sp) noexcept - : m_p (sp.swap (nullptr)) + : m_p (sp.template swap (nullptr)) { } - /// @} + /** @} */ /** Transfer ownership of another object to this container. The originating container loses its reference to the object. Requires: U* must be convertible to T* */ - /// @{ + /** @{ */ #if BEAST_SHAREDPTR_PROVIDE_COMPILER_WORKAROUNDS SharedPtr& operator= (SharedPtr && sp) { @@ -180,9 +185,9 @@ public: template SharedPtr& operator= (SharedPtr && sp) { - return assign (sp.swap (nullptr)); + return assign (sp.template swap (nullptr)); } - /// @} + /** @} */ #endif /** Destroy the container and release the held reference, if any. @@ -216,14 +221,6 @@ public: return m_p; } - /** Returns the object that this pointer references if any, else nullptr. - DEPRECATED - */ - T* getObject () const noexcept - { - return m_p; - } - private: // Acquire a reference to u for the caller. // @@ -270,8 +267,24 @@ private: //------------------------------------------------------------------------------ -/// SharedPtr comparisons. -/// @{ +// bind() helpers for pointer to member function + +template +const T* get_pointer (SharedPtr const& ptr) +{ + return ptr.get(); +} + +template +T* get_pointer (SharedPtr& ptr) +{ + return ptr.get(); +} + +//------------------------------------------------------------------------------ + +/** SharedPtr comparisons. */ +/** @{ */ template bool operator== (SharedPtr const& lhs, U* const rhs) noexcept { @@ -285,28 +298,30 @@ bool operator== (SharedPtr const& lhs, SharedPtr const& rhs) noexcept } template -bool operator== (T const* lhs, SharedPtr const& rhs) noexcept +bool operator== (T const* lhs, SharedPtr const& rhs) noexcept { return lhs == rhs.get(); } template -bool operator!= (SharedPtr const& lhs, T const* rhs) noexcept +bool operator!= (SharedPtr const& lhs, U const* rhs) noexcept { return lhs.get() != rhs; } template -bool operator!= (SharedPtr const& lhs, SharedPtr const& rhs) noexcept +bool operator!= (SharedPtr const& lhs, SharedPtr const& rhs) noexcept { return lhs.get() != rhs.get(); } template -bool operator!= (T const* lhs, SharedPtr const& rhs) noexcept +bool operator!= (T const* lhs, SharedPtr const& rhs) noexcept { return lhs != rhs.get(); } -/// @} +/** @} */ + +} #endif diff --git a/beast/smart_ptr/SmartPtr.cpp b/beast/smart_ptr/SmartPtr.cpp new file mode 100644 index 0000000000..02700c5642 --- /dev/null +++ b/beast/smart_ptr/SmartPtr.cpp @@ -0,0 +1,25 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "ContainerDeletePolicy.h" +#include "ScopedPointer.h" +#include "SharedObject.h" +#include "SharedPtr.h" diff --git a/modules/beast_core/text/beast_CharPointer_ASCII.h b/beast/strings/CharPointer_ASCII.h similarity index 99% rename from modules/beast_core/text/beast_CharPointer_ASCII.h rename to beast/strings/CharPointer_ASCII.h index 7fc76609d2..4275471140 100644 --- a/modules/beast_core/text/beast_CharPointer_ASCII.h +++ b/beast/strings/CharPointer_ASCII.h @@ -24,6 +24,14 @@ #ifndef BEAST_CHARPOINTER_ASCII_H_INCLUDED #define BEAST_CHARPOINTER_ASCII_H_INCLUDED +#include "../Config.h" + +#include "CharacterFunctions.h" + +#include +#include + +namespace beast { //============================================================================== /** @@ -378,5 +386,7 @@ private: CharType* data; }; +} + +#endif -#endif // BEAST_CHARPOINTER_ASCII_H_INCLUDED diff --git a/modules/beast_core/text/beast_CharPointer_UTF16.h b/beast/strings/CharPointer_UTF16.h similarity index 99% rename from modules/beast_core/text/beast_CharPointer_UTF16.h rename to beast/strings/CharPointer_UTF16.h index 6279e48c61..b34ed4e9e0 100644 --- a/modules/beast_core/text/beast_CharPointer_UTF16.h +++ b/beast/strings/CharPointer_UTF16.h @@ -24,6 +24,13 @@ #ifndef BEAST_CHARPOINTER_UTF16_H_INCLUDED #define BEAST_CHARPOINTER_UTF16_H_INCLUDED +#include "../Config.h" +#include "../Atomic.h" +#include "../CStdInt.h" + +#include "CharacterFunctions.h" + +namespace beast { //============================================================================== /** @@ -516,4 +523,7 @@ private: } }; -#endif // BEAST_CHARPOINTER_UTF16_H_INCLUDED +} + +#endif + diff --git a/modules/beast_core/text/beast_CharPointer_UTF32.h b/beast/strings/CharPointer_UTF32.h similarity index 99% rename from modules/beast_core/text/beast_CharPointer_UTF32.h rename to beast/strings/CharPointer_UTF32.h index 879d9e22cc..d5dfa082d0 100644 --- a/modules/beast_core/text/beast_CharPointer_UTF32.h +++ b/beast/strings/CharPointer_UTF32.h @@ -24,6 +24,14 @@ #ifndef BEAST_CHARPOINTER_UTF32_H_INCLUDED #define BEAST_CHARPOINTER_UTF32_H_INCLUDED +#include "../Config.h" +#include "../Atomic.h" + +#include "CharacterFunctions.h" + +#include + +namespace beast { //============================================================================== /** @@ -369,5 +377,7 @@ private: CharType* data; }; +} + +#endif -#endif // BEAST_CHARPOINTER_UTF32_H_INCLUDED diff --git a/modules/beast_core/text/beast_CharPointer_UTF8.h b/beast/strings/CharPointer_UTF8.h similarity index 99% rename from modules/beast_core/text/beast_CharPointer_UTF8.h rename to beast/strings/CharPointer_UTF8.h index 99ef9a03d9..f729c984b1 100644 --- a/modules/beast_core/text/beast_CharPointer_UTF8.h +++ b/beast/strings/CharPointer_UTF8.h @@ -24,6 +24,16 @@ #ifndef BEAST_CHARPOINTER_UTF8_H_INCLUDED #define BEAST_CHARPOINTER_UTF8_H_INCLUDED +#include "../Config.h" +#include "../Atomic.h" + +#include "CharacterFunctions.h" + +#include +#include + +namespace beast { + //============================================================================== /** Wraps a pointer to a null-terminated UTF-8 character string, and provides @@ -570,5 +580,7 @@ private: CharType* data; }; +} + #endif diff --git a/modules/beast_core/text/beast_CharacterFunctions.h b/beast/strings/CharacterFunctions.h similarity index 97% rename from modules/beast_core/text/beast_CharacterFunctions.h rename to beast/strings/CharacterFunctions.h index 2ce3139fca..4c17e44633 100644 --- a/modules/beast_core/text/beast_CharacterFunctions.h +++ b/beast/strings/CharacterFunctions.h @@ -21,9 +21,16 @@ */ //============================================================================== -#ifndef BEAST_CHARACTERFUNCTIONS_H_INCLUDED -#define BEAST_CHARACTERFUNCTIONS_H_INCLUDED +#ifndef BEAST_STRINGS_CHARACTERFUNCTIONS_H_INCLUDED +#define BEAST_STRINGS_CHARACTERFUNCTIONS_H_INCLUDED +#include + +#include "../Config.h" +#include "../CStdInt.h" +#include "../Memory.h" + +namespace beast { //============================================================================== #if BEAST_WINDOWS && ! DOXYGEN @@ -325,8 +332,11 @@ public: static size_t copyWithDestByteLimit (DestCharPointerType& dest, SrcCharPointerType src, size_t maxBytesToWrite) noexcept { typename DestCharPointerType::CharType const* const startAddress = dest.getAddress(); - ssize_t maxBytes = (ssize_t) maxBytesToWrite; - maxBytes -= sizeof (typename DestCharPointerType::CharType); // (allow for a terminating null) + size_t maxBytes = maxBytesToWrite; + if (maxBytes >= sizeof (typename DestCharPointerType::CharType)) + maxBytes -= sizeof (typename DestCharPointerType::CharType); // (allow for a terminating null) + else + maxBytes = 0; for (;;) { @@ -581,5 +591,7 @@ private: static double mulexp10 (const double value, int exponent) noexcept; }; +} + +#endif -#endif // BEAST_CHARACTERFUNCTIONS_H_INCLUDED diff --git a/modules/beast_core/text/beast_NewLine.h b/beast/strings/NewLine.h similarity index 94% rename from modules/beast_core/text/beast_NewLine.h rename to beast/strings/NewLine.h index d5cf0fae39..23dfb0c058 100644 --- a/modules/beast_core/text/beast_NewLine.h +++ b/beast/strings/NewLine.h @@ -21,9 +21,14 @@ */ //============================================================================== -#ifndef BEAST_NEWLINE_H_INCLUDED -#define BEAST_NEWLINE_H_INCLUDED +#ifndef BEAST_STRINGS_NEWLINE_H_INCLUDED +#define BEAST_STRINGS_NEWLINE_H_INCLUDED +#include "../Config.h" + +#include "String.h" + +namespace beast { //============================================================================== /** This class is used for represent a new-line character sequence. @@ -69,5 +74,7 @@ extern NewLine newLine; */ BEAST_API String& BEAST_CALLTYPE operator<< (String& string1, const NewLine&); +} + +#endif -#endif // BEAST_NEWLINE_H_INCLUDED diff --git a/modules/beast_core/text/beast_String.h b/beast/strings/String.h similarity index 98% rename from modules/beast_core/text/beast_String.h rename to beast/strings/String.h index cda3173fee..03d26ca77c 100644 --- a/modules/beast_core/text/beast_String.h +++ b/beast/strings/String.h @@ -21,8 +21,40 @@ */ //============================================================================== -#ifndef BEAST_STRING_H_INCLUDED -#define BEAST_STRING_H_INCLUDED +#ifndef BEAST_STRINGS_STRING_H_INCLUDED +#define BEAST_STRINGS_STRING_H_INCLUDED + +#include "../Config.h" +#include "../CStdInt.h" +#include "../Memory.h" + +#include "CharacterFunctions.h" +#if BEAST_MSVC +# pragma warning (push) +# pragma warning (disable: 4514 4996) +#endif +#include "CharPointer_UTF8.h" +#include "CharPointer_UTF16.h" +#include "CharPointer_UTF32.h" +#include "CharPointer_ASCII.h" +#if BEAST_MSVC +# pragma warning (pop) +#endif +#include "StringCharPointerType.h" +#include "StringFromNumber.h" +#include "String.h" + +#include + +namespace beast { + +#if BEAST_NATIVE_WCHAR_IS_UTF8 + typedef CharPointer_UTF8 CharPointer_wchar_t; +#elif BEAST_NATIVE_WCHAR_IS_UTF16 + typedef CharPointer_UTF16 CharPointer_wchar_t; +#else + typedef CharPointer_UTF32 CharPointer_wchar_t; +#endif //============================================================================== /** @@ -1348,8 +1380,7 @@ std::basic_ostream & BEAST_CALLTYPE operator<< (std::basic_ostr return stream << stringToWrite.toWideCharPointer(); } -/** Writes a string to an OutputStream as UTF8. */ -BEAST_API OutputStream& BEAST_CALLTYPE operator<< (OutputStream& stream, const String& stringToWrite); +} +#endif -#endif // BEAST_STRING_H_INCLUDED diff --git a/modules/beast_core/text/StringCharPointerType.h b/beast/strings/StringCharPointerType.h similarity index 90% rename from modules/beast_core/text/StringCharPointerType.h rename to beast/strings/StringCharPointerType.h index 37e82b7b25..ef2de5ec32 100644 --- a/modules/beast_core/text/StringCharPointerType.h +++ b/beast/strings/StringCharPointerType.h @@ -21,8 +21,15 @@ */ //============================================================================== -#ifndef BEAST_STRINGCHARPOINTERTYPE_H_INCLUDED -#define BEAST_STRINGCHARPOINTERTYPE_H_INCLUDED +#ifndef BEAST_STRINGS_STRINGCHARPOINTERTYPE_H_INCLUDED +#define BEAST_STRINGS_STRINGCHARPOINTERTYPE_H_INCLUDED + +#include "../Config.h" +#include "CharPointer_UTF8.h" +#include "CharPointer_UTF16.h" +#include "CharPointer_UTF32.h" + +namespace beast { /** This is the character encoding type used internally to store the string. @@ -50,5 +57,7 @@ typedef CharPointer_UTF8 StringCharPointerType; #endif +} + #endif diff --git a/modules/beast_core/text/StringFromNumber.h b/beast/strings/StringFromNumber.h similarity index 94% rename from modules/beast_core/text/StringFromNumber.h rename to beast/strings/StringFromNumber.h index b5f58fca81..3534f27b02 100644 --- a/modules/beast_core/text/StringFromNumber.h +++ b/beast/strings/StringFromNumber.h @@ -21,10 +21,21 @@ */ //============================================================================== -#ifndef BEAST_CORE_STRINGFROMNUMBER_H_INCLUDED -#define BEAST_CORE_STRINGFROMNUMBER_H_INCLUDED +#ifndef BEAST_STRINGS_STRINGFROMNUMBER_H_INCLUDED +#define BEAST_STRINGS_STRINGFROMNUMBER_H_INCLUDED -// This is private! +#include "../Config.h" +#include "../Arithmetic.h" + +#include "StringCharPointerType.h" + +#include +#include +#include + +namespace beast { + +// VFALCO TODO Put this in namespace detail // class NumberToStringConverters { @@ -156,4 +167,6 @@ public: } }; +} + #endif diff --git a/beast/strings/Strings.cpp b/beast/strings/Strings.cpp new file mode 100644 index 0000000000..d76435f800 --- /dev/null +++ b/beast/strings/Strings.cpp @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "impl/CharacterFunctions.cpp" +#include "impl/String.cpp" diff --git a/modules/beast_core/text/beast_CharacterFunctions.cpp b/beast/strings/impl/CharacterFunctions.cpp similarity index 97% rename from modules/beast_core/text/beast_CharacterFunctions.cpp rename to beast/strings/impl/CharacterFunctions.cpp index 0f70a0a9b8..6158f70ae9 100644 --- a/modules/beast_core/text/beast_CharacterFunctions.cpp +++ b/beast/strings/impl/CharacterFunctions.cpp @@ -21,7 +21,13 @@ */ //============================================================================== -//============================================================================== +#include "../CharacterFunctions.h" + +#include +#include + +namespace beast { + #if BEAST_MSVC #pragma warning (push) #pragma warning (disable: 4514 4996) @@ -147,3 +153,5 @@ double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept return negative ? (value / result) : (value * result); } + +} diff --git a/modules/beast_core/text/beast_String.cpp b/beast/strings/impl/String.cpp similarity index 98% rename from modules/beast_core/text/beast_String.cpp rename to beast/strings/impl/String.cpp index 5b667b14f5..5f281dcaa9 100644 --- a/modules/beast_core/text/beast_String.cpp +++ b/beast/strings/impl/String.cpp @@ -21,6 +21,21 @@ */ //============================================================================== +#include + +#include "../String.h" +#include "../NewLine.h" + +#include "../../ByteOrder.h" +#include "../../Memory.h" +#include "../../StaticAssert.h" +#include "../../Arithmetic.h" +#include "../../HeapBlock.h" + +#include "../../../modules/beast_core/beast_core.h" // for UnitTest + +namespace beast { + #if BEAST_MSVC #pragma warning (push) #pragma warning (disable: 4514 4996) @@ -32,14 +47,6 @@ NewLine newLine; #error "BEAST_STRINGS_ARE_UNICODE is deprecated! All strings are now unicode by default." #endif -#if BEAST_NATIVE_WCHAR_IS_UTF8 - typedef CharPointer_UTF8 CharPointer_wchar_t; -#elif BEAST_NATIVE_WCHAR_IS_UTF16 - typedef CharPointer_UTF16 CharPointer_wchar_t; -#else - typedef CharPointer_UTF32 CharPointer_wchar_t; -#endif - static inline CharPointer_wchar_t castToCharPointer_wchar_t (const void* t) noexcept { return CharPointer_wchar_t (static_cast (t)); @@ -632,23 +639,6 @@ BEAST_API String& BEAST_CALLTYPE operator<< (String& s1, const int64 number) BEAST_API String& BEAST_CALLTYPE operator<< (String& s1, const float number) { return s1 += String (number); } BEAST_API String& BEAST_CALLTYPE operator<< (String& s1, const double number) { return s1 += String (number); } -BEAST_API OutputStream& BEAST_CALLTYPE operator<< (OutputStream& stream, const String& text) -{ - const size_t numBytes = text.getNumBytesAsUTF8(); - - #if (BEAST_STRING_UTF_TYPE == 8) - stream.write (text.getCharPointer().getAddress(), numBytes); - #else - // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind - // if lots of large, persistent strings were to be written to streams). - HeapBlock temp (numBytes + 1); - CharPointer_UTF8 (temp).writeAll (text.getCharPointer()); - stream.write (temp, numBytes); - #endif - - return stream; -} - BEAST_API String& BEAST_CALLTYPE operator<< (String& string1, const NewLine&) { return string1 += NewLine::getDefault(); @@ -1973,6 +1963,8 @@ String String::fromUTF8 (const char* const buffer, int bufferSizeBytes) //============================================================================== //============================================================================== +#ifdef BEAST_UNITTEST_H_INCLUDED + class StringTests : public UnitTest { public: @@ -2326,3 +2318,6 @@ public: static StringTests stringUnitTests; +#endif + +} diff --git a/beast/threads/LockGuard.h b/beast/threads/LockGuard.h new file mode 100644 index 0000000000..a90895ae05 --- /dev/null +++ b/beast/threads/LockGuard.h @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_LOCKGUARD_H_INCLUDED +#define BEAST_THREADS_LOCKGUARD_H_INCLUDED + +#include "../Uncopyable.h" + +namespace beast { + +template +class LockGuard : public Uncopyable +{ +public: + typedef Mutex MutexType; + + explicit LockGuard (Mutex const& mutex) + : m_mutex (mutex) + { + m_mutex.lock(); + } + + ~LockGuard () + { + m_mutex.unlock(); + } + +private: + Mutex const& m_mutex; +}; + +} + +#endif diff --git a/beast/threads/RecursiveMutex.h b/beast/threads/RecursiveMutex.h new file mode 100644 index 0000000000..15a2330589 --- /dev/null +++ b/beast/threads/RecursiveMutex.h @@ -0,0 +1,84 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_RECURSIVEMUTEX_H_INCLUDED +#define BEAST_THREADS_RECURSIVEMUTEX_H_INCLUDED + +#include "../Config.h" +#include "LockGuard.h" +#include "UnlockGuard.h" +#include "TryLockGuard.h" + +#if ! BEAST_WINDOWS +#include +#endif + +namespace beast { + +class RecursiveMutex +{ +public: + typedef LockGuard ScopedLockType; + typedef UnlockGuard ScopedUnlockType; + typedef TryLockGuard ScopedTryLockType; + + /** Create the mutex. + The mutux is initially unowned. + */ + RecursiveMutex (); + + /** Destroy the mutex. + If the lock is owned, the result is undefined. + */ + ~RecursiveMutex (); + + // Boost concept compatibility: + // http://www.boost.org/doc/libs/1_54_0/doc/html/thread/synchronization.html#thread.synchronization.mutex_concepts + + /** BasicLockable */ + /** @{ */ + void lock () const; + void unlock () const; + /** @} */ + + /** Lockable */ + bool try_lock () const; + +private: +// To avoid including windows.h in the public Beast headers, we'll just +// reserve storage here that's big enough to be used internally as a windows +// CRITICAL_SECTION structure. +#if BEAST_WINDOWS +# if BEAST_64BIT + char section[44]; +# else + char section[24]; +# endif +#else + mutable pthread_mutex_t mutex; +#endif +}; + +} + +#endif diff --git a/beast/threads/ScopedWrapperContext.h b/beast/threads/ScopedWrapperContext.h new file mode 100644 index 0000000000..6a0b88324e --- /dev/null +++ b/beast/threads/ScopedWrapperContext.h @@ -0,0 +1,93 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_WRAPSCOPED_H_INCLUDED +#define BEAST_THREADS_WRAPSCOPED_H_INCLUDED + +namespace beast { + +/** Wraps a function object so invocation happens during a scoped container lifetime. */ +/** @{ */ +namespace detail { + +template +class ScopedWrapper +{ +public: + ScopedWrapper (Context const& context, Handler const& handler) + : m_context (context) + , m_handler (handler) + { } + + void operator() () + { + ScopedType const scope (m_context); + m_handler(); + } + +private: + Context const& m_context; + Handler m_handler; +}; + +} + +//------------------------------------------------------------------------------ + +/** Helper to eliminate the template argument at call sites. */ +template +class ScopedWrapperContext +{ +public: + typedef Context context_type; + typedef ScopedType scoped_type; + + class Scope + { + public: + explicit Scope (ScopedWrapperContext const& owner) + : m_scope (owner.m_context) + { } + private: + scoped_type m_scope; + }; + + ScopedWrapperContext () + { } + + template + explicit ScopedWrapperContext (Arg& arg) + : m_context (arg) + { } + + template + detail::ScopedWrapper wrap ( + Handler const& handler) + { + return detail::ScopedWrapper ( + m_context, handler); + } + +private: + Context m_context; +}; + +} + +#endif diff --git a/beast/threads/ServiceQueue.h b/beast/threads/ServiceQueue.h new file mode 100644 index 0000000000..2de4e44e04 --- /dev/null +++ b/beast/threads/ServiceQueue.h @@ -0,0 +1,631 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_SERVICEQUEUE_H_INCLUDED +#define BEAST_THREADS_SERVICEQUEUE_H_INCLUDED + +#include "../chrono/CPUMeter.h" +#include "../intrusive/List.h" +#include "../intrusive/LockFreeStack.h" +#include "SharedData.h" +#include "ThreadLocalValue.h" +#include "WaitableEvent.h" + +#include "detail/DispatchedHandler.h" + +namespace beast { + +namespace detail { + +//------------------------------------------------------------------------------ + +// VFALCO NOTE This allocator is a work in progress + +#if 0 + +class ServiceQueueAllocatorArena : public SharedObject +{ +public: + typedef std::size_t size_type; + + class Page : public LockFreeStack ::Node + { + public: + size_type const m_pageBytes; + Atomic m_refs; + char* m_pos; + bool m_full; + size_type m_count; + + static std::size_t overhead() + { return sizeof (Page); } + + static std::size_t pointer_overhead() + { return sizeof (Page*); } + + // pageBytes doesn't include the Page structure + explicit Page (size_type pageBytes) + : m_pageBytes (pageBytes) + , m_pos (begin()) + , m_full (false) + , m_count (0) + { + } + + ~Page () + { + // This means someone forgot to deallocate something + bassert (!m_full && m_refs.get() == 0); + } + + static Page* create (size_type pageBytes) + { + return new (new uint8[pageBytes + overhead()]) Page (pageBytes); + } + + static void destroy (Page* page) + { + page->~Page(); + delete[] ((uint8*)page); + } + + void reset () + { + m_refs.set (0); + m_pos = begin(); + m_full = false; + m_count = 0; + } + + bool full() const + { + return m_full; + } + + void* allocate (size_type n) + { + size_type const needed (n + pointer_overhead()); + char* pos = m_pos + needed; + if (pos > end()) + { + m_full = true; + return nullptr; + } + ++m_refs; + void* p (m_pos + pointer_overhead()); + get_page(p) = this; + m_pos = pos; + ++m_count; + return p; + } + + char* begin() const + { + return const_cast ( + reinterpret_cast (this) + overhead()); + } + + char const* end() const + { + return begin() + m_pageBytes; + } + + // Returns true if the page can be recycled + bool deallocate (void* p, size_type) + { + bool const unused ((--m_refs) == 0); + return unused && m_full; + } + + // Returns a reference to the per-allocation overhead area + static Page*& get_page (void* p) + { + return *reinterpret_cast ( + static_cast (p) - pointer_overhead()); + } + }; + + struct State + { + State() + { + } + + ~State() + { + // If this goes off, someone forgot to call deallocate! + bassert (full.get() == 0); + + destroy (active); + destroy (recycle); + } + + void destroy (LockFreeStack & stack) + { + for(;;) + { + Page* const page (stack.pop_front()); + if (page == nullptr) + break; + Page::destroy (page); + } + } + + Atomic full; + Atomic page_count; + LockFreeStack active; + LockFreeStack recycle; + }; + + typedef SharedData SharedState; + + size_type const m_maxBytes; + SharedState m_state; + + explicit ServiceQueueAllocatorArena (size_type maxBytes = 16 * 1024) + : m_maxBytes (maxBytes) + { + } + + ~ServiceQueueAllocatorArena() + { + } + + void* allocate (size_type n) + { + SharedState::UnlockedAccess state (m_state); + + // Loop until we satisfy the allocation from an + // active page, or we run out of active pages. + // + for (;;) + { + // Acquire ownership of an active page + // This prevents other threads from seeing it. + Page* page (state->active.pop_front()); + if (page == nullptr) + break; + + void* p = page->allocate (n); + if (p != nullptr) + { + // Put the page back so other threads can use it + state->active.push_front (page); + return p; + } + + // Page is full, count it for diagnostics + ++state->full; + } + + // No active page, get a recycled page or create a new page. + // + Page* page (state->recycle.pop_front()); + if (page == nullptr) + { + page = Page::create (std::max (m_maxBytes, n)); + ++state->page_count; + } + + void* p = page->allocate (n); + bassert (p != nullptr); + // Throw page into the active list so other threads can use it + state->active.push_front (page); + return p; + } + + void deallocate (void* p, size_type n) + { + SharedState::UnlockedAccess state (m_state); + Page* const page (Page::get_page(p)); + if (page->deallocate (p, n)) + { + --state->full; + page->reset(); + Page::destroy (page); + //state->recycle.push_front (page); + } + } +}; + +//------------------------------------------------------------------------------ + +template +struct ServiceQueueAllocator +{ + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef T const* const_pointer; + typedef T const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + ServiceQueueAllocator () + : m_arena (new ServiceQueueAllocatorArena) + { + } + + ServiceQueueAllocator (ServiceQueueAllocator const& other) + : m_arena (other.m_arena) + { + } + + template + ServiceQueueAllocator (ServiceQueueAllocator const& other) + : m_arena (other.m_arena) + { + } + + template + struct rebind + { + typedef ServiceQueueAllocator other; + }; + + pointer address (reference x) const + { + return &x; + } + + const_pointer address (const_reference x) const + { + return &x; + } + + pointer allocate (size_type n, + std::allocator::const_pointer = nullptr) const + { + size_type const bytes (n * sizeof (value_type)); + pointer const p (static_cast ( + m_arena->allocate (bytes))); + return p; + } + + void deallocate (pointer p, size_type n) const + { + size_type const bytes = (n * sizeof (value_type)); + m_arena->deallocate (p, bytes); + } + + size_type max_size () const + { + return std::numeric_limits ::max () / sizeof (value_type); + } + + void construct (pointer p, const_reference val) const + { + new ((void *)p) value_type (val); + } + + void destroy (pointer p) const + { + p->~value_type (); + } + +private: + template + friend struct ServiceQueueAllocator; + + SharedPtr m_arena; +}; + +#endif + +//------------------------------------------------------------------------------ + +class ServiceQueueBase +{ +public: + ServiceQueueBase(); + ~ServiceQueueBase(); + + std::size_t poll(); + std::size_t poll_one(); + std::size_t run(); + std::size_t run_one(); + void stop(); + bool stopped() const + { return m_stopped.get() != 0; } + void reset(); + +protected: + class Item; + class Waiter; + class ScopedServiceThread; + + void wait(); + void enqueue (Item* item); + + virtual std::size_t dequeue() = 0; + virtual Waiter* new_waiter() = 0; + + //-------------------------------------------------------------------------- + + class Item : public List ::Node + { + public: + virtual ~Item() { } + virtual void operator()() = 0; + virtual std::size_t size() const = 0; + }; + + //-------------------------------------------------------------------------- + + class Waiter : public LockFreeStack ::Node + { + public: + Waiter() + { } + void wait() + { m_event.wait(); } + void signal() + { m_event.signal(); } + private: + WaitableEvent m_event; + }; + + //-------------------------------------------------------------------------- + + struct State + { + // handlers + List handlers; + LockFreeStack waiting; + LockFreeStack unused; + }; + + typedef SharedData SharedState; + SharedState m_state; + CPUMeter m_cpuMeter; + Atomic m_stopped; + + static ThreadLocalValue s_service; +}; + +} + +//------------------------------------------------------------------------------ + +/** A queue for disatching function calls on other threads. + Handlers are guaranteed to be called only from threads that are currently + calling run, run_one, poll, or poll_one. +*/ +template > +class ServiceQueueType : public detail::ServiceQueueBase +{ +private: + using ServiceQueueBase::Item; + using ServiceQueueBase::Waiter; + + template + class ItemType : public Item + { + public: + explicit ItemType (BEAST_MOVE_ARG(Handler) handler) + : m_handler (BEAST_MOVE_CAST(Handler)(handler)) + { } + void operator() () + { m_handler(); } + std::size_t size() const + { return sizeof (*this); } + private: + Handler m_handler; + }; + +public: + typedef Allocator allocator_type; // for std::uses_allocator<> + + explicit ServiceQueueType (int expectedConcurrency = 1, + Allocator alloc = Allocator()) + : m_alloc (alloc) + { + typename Allocator::template rebind ::other a (m_alloc); + SharedState::Access state (m_state); + while (expectedConcurrency--) + { + state->unused.push_front (new (a.allocate (1)) Waiter); + } + } + + ~ServiceQueueType() + { + SharedState::Access state (m_state); + + // Must be empty + //bassert (state->handlers.empty()); + + // Cannot destroy while threads are waiting + bassert (state->waiting.empty()); + + typename Allocator::template rebind ::other a (m_alloc); + for(;;) + { + Waiter* const waiter (state->unused.pop_front()); + if (waiter == nullptr) + break; + a.destroy (waiter); + a.deallocate (waiter, 1); + } + } + + /** Returns the percentage of time the queue is using the CPU. */ + double getUtilizaton () const + { return m_cpuMeter.getUtilizaton(); } + + /** Returns the allocator associated with the container. */ + allocator_type get_allocator() const + { + return m_alloc; + } + + /** Returns `true` if the current thread is processing events. + If the current thread of execution is inside a call to run, + run_one, poll, or poll_one, this function returns `true`. + */ + bool is_service_thread() const + { return s_service.get() == this; } + + /** Run the handler on a service thread. + If the current thread of execution is a service thread then this + function wil dispatch the handler on the caller's thread before + returning. + The function signature of the handler must be: + @code + void handler(); + @endcode + */ + template + void dispatch (BEAST_MOVE_ARG(Handler) handler) + { + if (is_service_thread()) + { + handler(); + } + else + { + typename Allocator::template rebind >::other a (m_alloc); + enqueue (new (a.allocate (1)) + ItemType (BEAST_MOVE_CAST(Handler)(handler))); + } + } + + /** Request the handler to run on a service thread. + This returns immediately, even if the current thread of execution is + a service thread. + The function signature of the handler must be: + @code + void handler(); + @endcode + */ + template + void post (BEAST_MOVE_ARG(Handler) handler) + { + typename Allocator::template rebind >::other a (m_alloc); + enqueue (new (a.allocate (1)) + ItemType (BEAST_MOVE_CAST(Handler)(handler))); + } + + /** Return a new handler that dispatches the wrapped handler on the queue. */ + template + detail::DispatchedHandler wrap ( + BEAST_MOVE_ARG(Handler) handler) + { + return detail::DispatchedHandler ( + *this, BEAST_MOVE_CAST(Handler)(handler)); + } + + /** Run the event loop to execute ready handlers. + This runs handlers that are ready to run, without blocking, until + there are no more handlers ready or the service queue has been stopped. + @return The number of handlers that were executed. + */ + std::size_t poll () + { return ServiceQueueBase::poll(); } + + /** Run the event loop to execute at most one ready handler. + This will run zero or one handlers, without blocking, depending on + whether or not there is handler immediately ready to run. + @return The number of handlers that were executed. + */ + std::size_t poll_one () + { return ServiceQueueBase::poll_one(); } + + /** Runs the queue's processing loop. + The current thread of execution becomes a service thread. This call + blocks until there is no more work remaining. + @return The number of handlers that were executed. + */ + std::size_t run () + { return ServiceQueueBase::run(); } + + /** Runs the queue's processing loop to execute at most one handler. + @return The number of handlers that were executed. + */ + std::size_t run_one () + { return ServiceQueueBase::run_one(); } + + /** Stop the queue's processing loop. + All threads executing run or run_one will return as soon as possible. + Future calls to run, run_one, poll, or poll_one will return immediately + until reset is called. + @see reset + */ + void stop() + { return ServiceQueueBase::stop(); } + + /** Returns `true` if the queue has been stopped. + When a queue is stopped, calls to run, run_one, poll, or poll_one will + return immediately without invoking any handlers. + */ + bool stopped() const + { return ServiceQueueBase::stopped(); } + + /** Reset the queue after a stop. + This allows the event loop to be restarted. This may not be called while + there are any threads currently executing the run, run_one, poll, or + poll_one functions, or undefined behavior will result. + */ + void reset() + { return ServiceQueueBase::reset(); } + +private: + // Dispatch a single queued handler if possible. + // Returns the number of handlers dispatched (0 or 1) + // + std::size_t dequeue () + { + if (stopped()) + return 0; + + Item* item (nullptr); + + { + SharedState::Access state (m_state); + if (state->handlers.empty()) + return 0; + item = &state->handlers.front(); + state->handlers.erase ( + state->handlers.iterator_to (*item)); + } + + (*item)(); + + typename Allocator::template rebind ::other a (m_alloc); + std::size_t const size (item->size()); + item->~Item(); + a.deallocate (reinterpret_cast(item), size); + return 1; + } + + // Create a new Waiter + Waiter* new_waiter() + { + typename Allocator::template rebind ::other a (m_alloc); + return new (a.allocate (1)) Waiter; + } + + Allocator m_alloc; +}; + +typedef ServiceQueueType > ServiceQueue; + +} + +#endif diff --git a/beast/threads/SharedData.h b/beast/threads/SharedData.h new file mode 100644 index 0000000000..62e1defe72 --- /dev/null +++ b/beast/threads/SharedData.h @@ -0,0 +1,272 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_SHAREDDATA_H_INCLUDED +#define BEAST_THREADS_SHAREDDATA_H_INCLUDED + +#include "RecursiveMutex.h" +#include "SharedMutexAdapter.h" + +namespace beast { + +/** Structured, multi-threaded access to a shared state. + + This container combines locking semantics with data access semantics to + create an alternative to the typical synchronization method of first + acquiring a lock and then accessing data members. + + With this container, access to the underlying data is only possible after + first acquiring a lock. The steps of acquiring the lock and obtaining + a const or non-const reference to the data are combined into one + RAII style operation. + + There are three types of access: + + - Access + Provides access to the shared state via a non-const reference or pointer. + Access acquires a unique lock on the mutex associated with the + container. + + - ConstAccess + Provides access to the shared state via a const reference or pointer. + ConstAccess acquires a shared lock on the mutex associated with the + container. + + - ConstUnlockedAccess + Provides access to the shared state via a const reference or pointer. + No locking is performed. It is the callers responsibility to ensure that + the operation is synchronized. This can be useful for diagnostics or + assertions, or for when it is known that no other threads can access + the data. + + - UnlockedAccess + Provides access to the shared state via a reference or pointer. + No locking is performed. It is the callers responsibility to ensure that + the operation is synchronized. This can be useful for diagnostics or + assertions, or for when it is known that no other threads can access + the data. + + Usage example: + + @code + + struct State + { + int value1; + String value2; + }; + + typedef SharedData SharedState; + + SharedState m_state; + + void readExample () + { + SharedState::ConstAccess state (m_state); + + print (state->value1); // read access + print (state->value2); // read access + + state->value1 = 42; // write disallowed: compile error + } + + void writeExample () + { + SharedState::Access state (m_state); + + state->value2 = "Label"; // write access, allowed + } + + @endcode + + Requirements for Value: + Constructible + Destructible + + Requirements for SharedMutexType: + X is SharedMutexType, a is an instance of X: + X a; DefaultConstructible + X::LockGuardType Names a type that implements the LockGuard concept. + X::SharedLockGuardType Names a type that implements the SharedLockGuard concept. + + @tparam Value The type which the container holds. + @tparam SharedMutexType The type of shared mutex to use. +*/ +template > +class SharedData : public Uncopyable +{ +private: + typedef typename SharedMutexType::LockGuardType LockGuardType; + typedef typename SharedMutexType::SharedLockGuardType SharedLockGuardType; + +public: + typedef Value ValueType; + + class Access; + class ConstAccess; + class UnlockedAccess; + class ConstUnlockedAccess; + + /** Create a shared data container. + Up to 8 parameters can be specified in the constructor. These parameters + are forwarded to the corresponding constructor in Data. If no + constructor in Data matches the parameter list, a compile error is + generated. + */ + /** @{ */ + SharedData () { } + + template + explicit SharedData (T1 t1) + : m_value (t1) { } + + template + SharedData (T1 t1, T2 t2) + : m_value (t1, t2) { } + + template + SharedData (T1 t1, T2 t2, T3 t3) + : m_value (t1, t2, t3) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4) + : m_value (t1, t2, t3, t4) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) + : m_value (t1, t2, t3, t4, t5) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) + : m_value (t1, t2, t3, t4, t5, t6) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : m_value (t1, t2, t3, t4, t5, t6, t7) { } + + template + SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) + : m_value (t1, t2, t3, t4, t5, t6, t7, t8) { } + /** @} */ + +private: + Value m_value; + SharedMutexType m_mutex; +}; + +//------------------------------------------------------------------------------ + +/** Provides non-const access to the contents of a SharedData. + This acquires a unique lock on the underlying mutex. +*/ +template +class SharedData ::Access : public Uncopyable +{ +public: + explicit Access (SharedData& state) + : m_state (state) + , m_lock (m_state.m_mutex) + { } + + Data const& get () const { return m_state.m_value; } + Data const& operator* () const { return get (); } + Data const* operator-> () const { return &get (); } + Data& get () { return m_state.m_value; } + Data& operator* () { return get (); } + Data* operator-> () { return &get (); } + +private: + SharedData& m_state; + typename SharedData::LockGuardType m_lock; +}; + +//------------------------------------------------------------------------------ + +/** Provides const access to the contents of a SharedData. + This acquires a shared lock on the underlying mutex. +*/ +template +class SharedData ::ConstAccess : public Uncopyable +{ +public: + /** Create a ConstAccess from the specified SharedData */ + explicit ConstAccess (SharedData const volatile& state) + : m_state (const_cast (state)) + , m_lock (m_state.m_mutex) + { } + + Data const& get () const { return m_state.m_value; } + Data const& operator* () const { return get (); } + Data const* operator-> () const { return &get (); } + +private: + SharedData const& m_state; + typename SharedData::SharedLockGuardType m_lock; +}; + +//------------------------------------------------------------------------------ + +/** Provides const access to the contents of a SharedData. + This acquires a shared lock on the underlying mutex. +*/ +template +class SharedData ::ConstUnlockedAccess : public Uncopyable +{ +public: + /** Create an UnlockedAccess from the specified SharedData */ + explicit ConstUnlockedAccess (SharedData const volatile& state) + : m_state (const_cast (state)) + { } + + Data const& get () const { return m_state.m_value; } + Data const& operator* () const { return get (); } + Data const* operator-> () const { return &get (); } + +private: + SharedData const& m_state; +}; + +//------------------------------------------------------------------------------ + +/** Provides access to the contents of a SharedData. + This acquires a shared lock on the underlying mutex. +*/ +template +class SharedData ::UnlockedAccess : public Uncopyable +{ +public: + /** Create an UnlockedAccess from the specified SharedData */ + explicit UnlockedAccess (SharedData& state) + : m_state (state) + { } + + Data const& get () const { return m_state.m_value; } + Data const& operator* () const { return get (); } + Data const* operator-> () const { return &get (); } + Data& get () { return m_state.m_value; } + Data& operator* () { return get (); } + Data* operator-> () { return &get (); } + +private: + SharedData& m_state; +}; + +} + +#endif diff --git a/beast/threads/SharedLockGuard.h b/beast/threads/SharedLockGuard.h new file mode 100644 index 0000000000..82fdbd0812 --- /dev/null +++ b/beast/threads/SharedLockGuard.h @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_SHAREDLOCKGUARD_H_INCLUDED +#define BEAST_THREADS_SHAREDLOCKGUARD_H_INCLUDED + +#include "../Uncopyable.h" + +namespace beast +{ + +/** A scoped container that acquires a shared lock. */ +template +class SharedLockGuard : public Uncopyable +{ +public: + typedef Mutex MutexType; + + explicit SharedLockGuard (Mutex const& mutex) + : m_mutex (mutex) + { + m_mutex.lock_shared(); + } + + ~SharedLockGuard () + { + m_mutex.unlock_shared(); + } + +private: + Mutex const& m_mutex; +}; + +} + +#endif diff --git a/modules/beast_core/memory/beast_GlobalFifoFreeStore.h b/beast/threads/SharedMutexAdapter.h similarity index 56% rename from modules/beast_core/memory/beast_GlobalFifoFreeStore.h rename to beast/threads/SharedMutexAdapter.h index 1c43cc15e7..cb28ea51ab 100644 --- a/modules/beast_core/memory/beast_GlobalFifoFreeStore.h +++ b/beast/threads/SharedMutexAdapter.h @@ -17,47 +17,51 @@ */ //============================================================================== -#ifndef BEAST_GLOBALFIFOFREESTORE_H_INCLUDED -#define BEAST_GLOBALFIFOFREESTORE_H_INCLUDED +#ifndef BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED +#define BEAST_THREADS_SHAREDMUTEXADAPTER_H_INCLUDED -/*============================================================================*/ -/** - A @ref FifoFreeStoreType singleton. +#include "LockGuard.h" +#include "SharedLockGuard.h" - @ingroup beast_concurrent +namespace beast { + +/** Adapts a regular Lockable to conform to the SharedMutex concept. + Shared locks become unique locks with this interface. Two threads may not + simultaneously acquire ownership of the lock. Typically the Mutex template + parameter will be a CriticalSection. */ -template -class GlobalFifoFreeStore : public SharedSingleton > +template +class SharedMutexAdapter { public: - inline void* allocate (size_t bytes) + typedef Mutex MutexType; + typedef LockGuard LockGuardType; + typedef SharedLockGuard SharedLockGuardType; + + void lock() const { - return m_allocator.allocate (bytes); + m_mutex.lock(); } - static inline void deallocate (void* const p) + void unlock() const { - FifoFreeStoreType::deallocate (p); + m_mutex.unlock(); } - static GlobalFifoFreeStore* createInstance () + void lock_shared() const { - return new GlobalFifoFreeStore; + m_mutex.lock(); } -public: - GlobalFifoFreeStore () - : SharedSingleton > - (SingletonLifetime::persistAfterCreation) - { - } - - ~GlobalFifoFreeStore () + void unlock_shared() const { + m_mutex.unlock(); } private: - FifoFreeStoreType m_allocator; + Mutex mutable m_mutex; }; +} + #endif diff --git a/modules/beast_core/threads/beast_SpinLock.h b/beast/threads/SpinLock.h similarity index 82% rename from modules/beast_core/threads/beast_SpinLock.h rename to beast/threads/SpinLock.h index 87b9c2abd2..cbc6e0e959 100644 --- a/modules/beast_core/threads/beast_SpinLock.h +++ b/beast/threads/SpinLock.h @@ -21,8 +21,14 @@ */ //============================================================================== -#ifndef BEAST_SPINLOCK_H_INCLUDED -#define BEAST_SPINLOCK_H_INCLUDED +#ifndef BEAST_THREADS_SPINLOCK_H_INCLUDED +#define BEAST_THREADS_SPINLOCK_H_INCLUDED + +#include "../Atomic.h" +#include "LockGuard.h" +#include "UnlockGuard.h" + +namespace beast { //============================================================================== /** @@ -40,6 +46,12 @@ class BEAST_API SpinLock : public Uncopyable { public: + /** Provides the type of scoped lock to use for locking a SpinLock. */ + typedef LockGuard ScopedLockType; + + /** Provides the type of scoped unlocker to use with a SpinLock. */ + typedef UnlockGuard ScopedUnlockType; + inline SpinLock() noexcept {} inline ~SpinLock() noexcept {} @@ -57,27 +69,29 @@ public: /** Attempts to acquire the lock, returning true if this was successful. */ inline bool tryEnter() const noexcept { - return lock.compareAndSetBool (1, 0); + return m_lock.compareAndSetBool (1, 0); } /** Releases the lock. */ inline void exit() const noexcept { - bassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held! - lock = 0; + bassert (m_lock.value == 1); // Agh! Releasing a lock that isn't currently held! + m_lock = 0; } - //============================================================================== - /** Provides the type of scoped lock to use for locking a SpinLock. */ - typedef GenericScopedLock ScopedLockType; - - /** Provides the type of scoped unlocker to use with a SpinLock. */ - typedef GenericScopedUnlock ScopedUnlockType; + void lock () const + { enter(); } + void unlock () const + { exit(); } + bool try_lock () const + { return tryEnter(); } private: //============================================================================== - mutable Atomic lock; + mutable Atomic m_lock; }; +} + +#endif -#endif // BEAST_SPINLOCK_H_INCLUDED diff --git a/beast/threads/Stoppable.h b/beast/threads/Stoppable.h new file mode 100644 index 0000000000..637b078c0f --- /dev/null +++ b/beast/threads/Stoppable.h @@ -0,0 +1,327 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_STOPPABLE_H_INCLUDED +#define BEAST_THREADS_STOPPABLE_H_INCLUDED + +#include "../Atomic.h" +#include "../intrusive/LockFreeStack.h" +#include "../utility/Journal.h" + +#include "WaitableEvent.h" + +namespace beast { + +class RootStoppable; + +/** Provides an interface for starting and stopping. + + A common method of structuring server or peer to peer code is to isolate + conceptual portions of functionality into individual classes, aggregated + into some larger "application" or "core" object which holds all the parts. + Frequently, these components are dependent on each other in unavoidably + complex ways. They also often use threads and perform asynchronous i/o + operations involving sockets or other operating system objects. The process + of starting and stopping such a system can be complex. This interface + provides a set of behaviors for ensuring that the start and stop of a + composite application-style object is well defined. + + Upon the initialization of the composite object these steps are peformed: + + 1. Construct sub-components. + + These are all typically derived from Stoppable. There can be a deep + hierarchy: Stoppable objects may themselves have Stoppable child + objects. This captures the relationship of dependencies. + + 2. prepare() + + Because some components may depend on others, preparatory steps require + that all objects be first constructed. The prepare step calls all + Stoppable objects in the tree starting from the leaves and working up + to the root. In this stage we are guaranteed that all objects have been + constructed and are in a well-defined state. + + 3. onPrepare() + + This override is called for all Stoppable objects in the hierarchy + during the prepare stage. Objects are called from the bottom up. + It is guaranteed that all child Stoppable objects have already been + prepared when this is called. + + 4. start() + + At this point all sub-components have been constructed and prepared, + so it should be safe for them to be started. While some Stoppable + objects may do nothing in their start function, others will start + threads or call asynchronous i/o initiating functions like timers or + sockets. + + 5. onStart() + + This override is called for all Stoppable objects in the hierarchy + during the start stage. Objects are called from the bottom up. + It is guaranteed that all child Stoppable objects have already been + started when this is called. + + This is the sequence of events involved in stopping: + + 6. stopAsync() [optional] + + This notifies the root Stoppable and all its children that a stop is + requested. + + 7. stop() + + This first calls stopAsync(), and then blocks on each child Stoppable in + the in the tree from the bottom up, until the Stoppable indicates it has + stopped. This will usually be called from the main thread of execution + when some external signal indicates that the process should stop. For + example, an RPC 'stop' command, or a SIGINT POSIX signal. + + 8. onStop() + + This override is called for the root Stoppable and all its children when + stopAsync() is called. Derived classes should cancel pending I/O and + timers, signal that threads should exit, queue cleanup jobs, and perform + any other necessary final actions in preparation for exit. + + 9. onChildrenStopped() + + This override is called when all the children have stopped. This informs + the Stoppable that there should not be any more dependents making calls + into its member functions. A Stoppable that has no children will still + have this function called. + + 10. stopped() + + The derived class calls this function to inform the Stoppable API that + it has completed the stop. This unblocks the caller of stop(). + + For stoppables which are only considered stopped when all of their + children have stopped, and their own internal logic indicates a stop, it + will be necessary to perform special actions in onChildrenStopped(). The + funtion areChildrenStopped() can be used after children have stopped, + but before the Stoppable logic itself has stopped, to determine if the + stoppable's logic is a true stop. + + Pseudo code for this process is as follows: + + @code + + // Returns `true` if derived logic has stopped. + // + // When the logic stops, logicProcessingStop() is no longer called. + // If children are still active we need to wait until we get a + // notification that the children have stopped. + // + bool logicHasStopped (); + + // Called when children have stopped + void onChildrenStopped () + { + // We have stopped when the derived logic stops and children stop. + if (logicHasStopped) + stopped(); + } + + // derived-specific logic that executes periodically + void logicProcessingStep () + { + // process + // ... + + // now see if we've stopped + if (logicHasStopped() && areChildrenStopped()) + stopped(); + } + + @endcode + + Derived class that manage one or more threads should typically notify + those threads in onStop that they should exit. In the thread function, + when the last thread is about to exit it would call stopped(). + + @note A Stoppable may not be restarted. +*/ +/** @{ */ +class Stoppable +{ +protected: + Stoppable (char const* name, RootStoppable& root); + +public: + /** Create the Stoppable. */ + Stoppable (char const* name, Stoppable& parent); + + /** Destroy the Stoppable. */ + virtual ~Stoppable (); + + /** Returns `true` if the stoppable should stop. */ + bool isStopping () const; + + /** Returns `true` if the requested stop has completed. */ + bool isStopped () const; + + /** Returns `true` if all children have stopped. */ + bool areChildrenStopped () const; + + /** Called by derived classes to indicate that the stoppable has stopped. */ + void stopped (); + + /** Override called during preparation. + Since all other Stoppable objects in the tree have already been + constructed, this provides an opportunity to perform initialization which + depends on calling into other Stoppable objects. + This call is made on the same thread that called prepare(). + The default implementation does nothing. + Guaranteed to only be called once. + */ + virtual void onPrepare (); + + /** Override called during start. */ + virtual void onStart (); + + /** Override called when the stop notification is issued. + + The call is made on an unspecified, implementation-specific thread. + onStop and onChildrenStopped will never be called concurrently, across + all Stoppable objects descended from the same root, inclusive of the + root. + + It is safe to call isStopping, isStopped, and areChildrenStopped from + within this function; The values returned will always be valid and never + change during the callback. + + The default implementation simply calls stopped(). This is applicable + when the Stoppable has a trivial stop operation (or no stop operation), + and we are merely using the Stoppable API to position it as a dependency + of some parent service. + + Thread safety: + May not block for long periods. + Guaranteed only to be called once. + Must be safe to call from any thread at any time. + */ + virtual void onStop (); + + /** Override called when all children have stopped. + + The call is made on an unspecified, implementation-specific thread. + onStop and onChildrenStopped will never be called concurrently, across + all Stoppable objects descended from the same root, inclusive of the + root. + + It is safe to call isStopping, isStopped, and areChildrenStopped from + within this function; The values returned will always be valid and never + change during the callback. + + The default implementation does nothing. + + Thread safety: + May not block for long periods. + Guaranteed only to be called once. + Must be safe to call from any thread at any time. + */ + virtual void onChildrenStopped (); + +private: + friend class RootStoppable; + + struct Child; + typedef LockFreeStack Children; + + struct Child : Children::Node + { + Child (Stoppable* stoppable_) : stoppable (stoppable_) + { + } + + Stoppable* stoppable; + }; + + void prepareRecursive (); + void startRecursive (); + void stopAsyncRecursive (); + void stopRecursive (Journal journal); + +protected: + char const* m_name; + RootStoppable& m_root; + Child m_child; + bool volatile m_stopped; + bool volatile m_childrenStopped; + Children m_children; + WaitableEvent m_stoppedEvent; +}; + +//------------------------------------------------------------------------------ + +class RootStoppable : public Stoppable +{ +public: + explicit RootStoppable (char const* name); + + ~RootStoppable (); + + bool isStopping() const; + + /** Prepare all contained Stoppable objects. + This calls onPrepare for all Stoppable objects in the tree. + Calls made after the first have no effect. + Thread safety: + May be called from any thread. + */ + void prepare (); + + /** Start all contained Stoppable objects. + The default implementation does nothing. + Calls made after the first have no effect. + Thread safety: + May be called from any thread. + */ + void start (); + + /** Notify a root stoppable and children to stop, and block until stopped. + Has no effect if the stoppable was already notified. + This blocks until the stoppable and all of its children have stopped. + Thread safety: + Safe to call from any thread not associated with a Stoppable. + */ + void stop (Journal journal = Journal()); + + /** Notify a root stoppable and children to stop, without waiting. + Has no effect if the stoppable was already notified. + + Thread safety: + Safe to call from any thread at any time. + */ + void stopAsync (); + +private: + Atomic m_prepared; + Atomic m_started; + Atomic m_calledStop; + Atomic m_calledStopAsync; +}; +/** @} */ + +} + +#endif diff --git a/modules/beast_core/threads/beast_Thread.h b/beast/threads/Thread.h similarity index 96% rename from modules/beast_core/threads/beast_Thread.h rename to beast/threads/Thread.h index c1e7de8743..1ea34f7c14 100644 --- a/modules/beast_core/threads/beast_Thread.h +++ b/beast/threads/Thread.h @@ -21,8 +21,14 @@ */ //============================================================================== -#ifndef BEAST_THREAD_H_INCLUDED -#define BEAST_THREAD_H_INCLUDED +#ifndef BEAST_THREADS_THREAD_H_INCLUDED +#define BEAST_THREADS_THREAD_H_INCLUDED + +#include "../utility/LeakChecked.h" +#include "RecursiveMutex.h" +#include "WaitableEvent.h" + +namespace beast { //============================================================================== /** @@ -110,6 +116,11 @@ public: */ bool stopThread (int timeOutMilliseconds = -1); + /** Stop the thread without blocking. + This calls signalThreadShouldExit followed by notify. + */ + void stopThreadAsync (); + //============================================================================== /** Returns true if the thread is currently active */ bool isThreadRunning() const; @@ -260,7 +271,7 @@ private: const String threadName; void* volatile threadHandle; ThreadID threadId; - CriticalSection startStopLock; + RecursiveMutex startStopLock; WaitableEvent startSuspensionEvent, defaultEvent; int threadPriority; uint32 affinityMask; @@ -277,4 +288,7 @@ private: static bool setThreadPriority (void*, int); }; -#endif // BEAST_THREAD_H_INCLUDED +} + +#endif + diff --git a/modules/beast_core/threads/beast_ThreadLocalValue.h b/beast/threads/ThreadLocalValue.h similarity index 97% rename from modules/beast_core/threads/beast_ThreadLocalValue.h rename to beast/threads/ThreadLocalValue.h index af623adbed..751062efe4 100644 --- a/modules/beast_core/threads/beast_ThreadLocalValue.h +++ b/beast/threads/ThreadLocalValue.h @@ -21,8 +21,14 @@ */ //============================================================================== -#ifndef BEAST_THREADLOCALVALUE_H_INCLUDED -#define BEAST_THREADLOCALVALUE_H_INCLUDED +#ifndef BEAST_THREADS_THREADLOCALVALUE_H_INCLUDED +#define BEAST_THREADS_THREADLOCALVALUE_H_INCLUDED + +#include "../Config.h" +#include "SpinLock.h" +#include "Thread.h" + +namespace beast { // (NB: on win32, native thread-locals aren't possible in a dynamically loaded DLL in XP). #if ! ((BEAST_MSVC && (BEAST_64BIT || ! defined (BeastPlugin_PluginCode))) \ @@ -186,5 +192,6 @@ private: #endif }; +} -#endif // BEAST_THREADLOCALVALUE_H_INCLUDED +#endif diff --git a/beast/threads/Threads.cpp b/beast/threads/Threads.cpp new file mode 100644 index 0000000000..a941c1e848 --- /dev/null +++ b/beast/threads/Threads.cpp @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "impl/Atomic.cpp" +#include "impl/RecursiveMutex.cpp" +#include "impl/ServiceQueue.cpp" +#include "impl/Stoppable.cpp" +#include "impl/Thread.cpp" +#include "impl/WaitableEvent.cpp" diff --git a/beast/threads/TryLockGuard.h b/beast/threads/TryLockGuard.h new file mode 100644 index 0000000000..f61f8bb6e1 --- /dev/null +++ b/beast/threads/TryLockGuard.h @@ -0,0 +1,55 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_TRYLOCKGUARD_H_INCLUDED +#define BEAST_THREADS_TRYLOCKGUARD_H_INCLUDED + +#include "../Uncopyable.h" + +namespace beast { + +template +class TryLockGuard : public Uncopyable +{ +public: + typedef Mutex MutexType; + + explicit TryLockGuard (Mutex const& mutex) + : m_mutex (mutex) + , m_owns_lock (m_mutex.try_lock()) + { + } + + ~TryLockGuard () + { + if (m_owns_lock) + m_mutex.unlock(); + } + + bool owns_lock() const + { return m_owns_lock; } + +private: + Mutex const& m_mutex; + bool m_owns_lock; +}; + +} + +#endif diff --git a/beast/threads/UnlockGuard.h b/beast/threads/UnlockGuard.h new file mode 100644 index 0000000000..ea412765f6 --- /dev/null +++ b/beast/threads/UnlockGuard.h @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_UNLOCKGUARD_H_INCLUDED +#define BEAST_THREADS_UNLOCKGUARD_H_INCLUDED + +#include "../Uncopyable.h" + +namespace beast { + +template +class UnlockGuard : public Uncopyable +{ +public: + typedef Mutex MutexType; + + explicit UnlockGuard (Mutex const& mutex) + : m_mutex (mutex) + { + m_mutex.unlock(); + } + + ~UnlockGuard () + { + m_mutex.lock(); + } + +private: + Mutex const& m_mutex; +}; + +} + +#endif diff --git a/modules/beast_core/threads/beast_WaitableEvent.h b/beast/threads/WaitableEvent.h similarity index 81% rename from modules/beast_core/threads/beast_WaitableEvent.h rename to beast/threads/WaitableEvent.h index 8cbb68c840..1e8b2a2cba 100644 --- a/modules/beast_core/threads/beast_WaitableEvent.h +++ b/beast/threads/WaitableEvent.h @@ -21,18 +21,26 @@ */ //============================================================================== -#ifndef BEAST_WAITABLEEVENT_H_INCLUDED -#define BEAST_WAITABLEEVENT_H_INCLUDED +#ifndef BEAST_THREADS_WAITABLEEVENT_H_INCLUDED +#define BEAST_THREADS_WAITABLEEVENT_H_INCLUDED -//============================================================================== -/** - Allows threads to wait for events triggered by other threads. +#include "../Config.h" +#include "../Uncopyable.h" - A thread can call wait() on a WaitableObject, and this will suspend the +#if ! BEAST_WINDOWS +#include +#endif + +namespace beast { + +/** Allows threads to wait for events triggered by other threads. + A thread can call wait() on a WaitableEvent, and this will suspend the calling thread until another thread wakes it up by calling the signal() method. */ -class BEAST_API WaitableEvent : LeakChecked , public Uncopyable +class WaitableEvent + : public Uncopyable + //, LeakChecked // VFALCO TODO Move LeakChecked to beast/ { public: //============================================================================== @@ -45,14 +53,14 @@ public: @param initiallySignaled If this is true then the event will be signaled when the constructor returns. */ - explicit WaitableEvent (bool manualReset = false, bool initiallySignaled = false) noexcept; + explicit WaitableEvent (bool manualReset = false, bool initiallySignaled = false); /** Destructor. If other threads are waiting on this object when it gets deleted, this can cause nasty errors, so be careful! */ - ~WaitableEvent() noexcept; + ~WaitableEvent(); //============================================================================== /** Suspends the calling thread until the event has been signalled. @@ -69,7 +77,11 @@ public: @returns true if the object has been signalled, false if the timeout expires first. @see signal, reset */ - bool wait (int timeOutMilliseconds = -1) const noexcept; + /** @{ */ + bool wait () const; // wait forever + // VFALCO TODO Change wait() to seconds instead of millis + bool wait (int timeOutMilliseconds) const; // DEPRECATED + /** @} */ //============================================================================== /** Wakes up any threads that are currently waiting on this object. @@ -87,26 +99,26 @@ public: @see wait, reset */ - void signal() const noexcept; + void signal() const; //============================================================================== /** Resets the event to an unsignalled state. If it's not already signalled, this does nothing. */ - void reset() const noexcept; - + void reset() const; private: - //============================================================================== - #if BEAST_WINDOWS +#if BEAST_WINDOWS void* handle; - #else +#else mutable pthread_cond_t condition; mutable pthread_mutex_t mutex; - mutable bool triggered, manualReset; - #endif + mutable bool triggered; + mutable bool manualReset; +#endif }; +} -#endif // BEAST_WAITABLEEVENT_H_INCLUDED +#endif diff --git a/beast/threads/detail/BindHandler.h b/beast/threads/detail/BindHandler.h new file mode 100644 index 0000000000..32199b73fd --- /dev/null +++ b/beast/threads/detail/BindHandler.h @@ -0,0 +1,276 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_BINDHANDLER_H_INCLUDED +#define BEAST_THREADS_BINDHANDLER_H_INCLUDED + +namespace beast { +namespace detail { + +/** Overloaded function that re-binds arguments to a handler. */ +/** @{ */ +template +class BindHandler1 +{ +private: + Handler handler; + P1 p1; + +public: + BindHandler1 (Handler const& handler_, P1 const& p1_) + : handler (handler_) + , p1 (p1_) + { } + + BindHandler1 (Handler& handler_, P1 const& p1_) + : handler (BEAST_MOVE_CAST(Handler)(handler_)) + , p1 (p1_) + { } + + void operator()() + { + handler ( + static_cast (p1) + ); + } + + void operator()() const + { + handler (p1); + } +}; + +template +BindHandler1 bindHandler (Handler handler, P1 const& p1) +{ + return BindHandler1 (handler, p1); +} + +//------------------------------------------------------------------------------ + +template +class BindHandler2 +{ +private: + Handler handler; + P1 p1; P2 p2; + +public: + BindHandler2 (Handler const& handler_, + P1 const& p1_, P2 const& p2_) + : handler (handler_) + , p1 (p1_), p2 (p2_) + { } + + BindHandler2 (Handler& handler_, + P1 const& p1_, P2 const& p2_) + : handler (BEAST_MOVE_CAST(Handler)(handler_)) + , p1 (p1_), p2 (p2_) + { } + + void operator()() + { + handler ( + static_cast (p1), static_cast (p2)); + } + + void operator()() const + { handler (p1, p2); } +}; + +template +BindHandler2 bindHandler (Handler handler, + P1 const& p1, P2 const& p2) +{ + return BindHandler2 ( + handler, p1, p2); +} + +//------------------------------------------------------------------------------ + +template +class BindHandler3 +{ +private: + Handler handler; + P1 p1; P2 p2; P3 p3; + +public: + BindHandler3 (Handler const& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_) + : handler (handler_) + , p1 (p1_), p2 (p2_), p3 (p3_) + { } + + BindHandler3 (Handler& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_) + : handler (BEAST_MOVE_CAST(Handler)(handler_)) + , p1 (p1_), p2 (p2_), p3 (p3_) + { } + + void operator()() + { + handler ( + static_cast (p1), static_cast (p2), static_cast (p3)); + } + + void operator()() const + { handler (p1, p2, p3); } +}; + +template +BindHandler3 bindHandler (Handler handler, + P1 const& p1, P2 const& p2, P3 const& p3) +{ + return BindHandler3 ( + handler, p1, p2, p3); +} + +//------------------------------------------------------------------------------ + +template +class BindHandler4 +{ +private: + Handler handler; + P1 p1; P2 p2; P3 p3; P4 p4; + +public: + BindHandler4 (Handler const& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_, P4 const& p4_) + : handler (handler_) + , p1 (p1_), p2 (p2_), p3 (p3_), p4 (p4_) + { } + + BindHandler4 (Handler& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_, P4 const& p4_) + : handler (BEAST_MOVE_CAST(Handler)(handler_)) + , p1 (p1_), p2 (p2_), p3 (p3_), p4 (p4_) + { } + + void operator()() + { + handler ( + static_cast (p1), static_cast (p2), static_cast (p3), + static_cast (p4) + ); + } + + void operator()() const + { handler (p1, p2, p3, p4); } +}; + +template +BindHandler4 bindHandler (Handler handler, + P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) +{ + return BindHandler4 ( + handler, p1, p2, p3, p4); +} + +//------------------------------------------------------------------------------ + +template +class BindHandler5 +{ +private: + Handler handler; + P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; + +public: + BindHandler5 (Handler const& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_, P4 const& p4_, P5 const& p5_) + : handler (handler_) + , p1 (p1_), p2 (p2_), p3 (p3_), p4 (p4_), p5 (p5_) + { } + + BindHandler5 (Handler& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_, P4 const& p4_, P5 const& p5_) + : handler (BEAST_MOVE_CAST(Handler)(handler_)) + , p1 (p1_), p2 (p2_), p3 (p3_), p4 (p4_), p5 (p5_) + { } + + void operator()() + { + handler ( + static_cast (p1), static_cast (p2), static_cast (p3), + static_cast (p4), static_cast (p5) + ); + } + + void operator()() const + { handler (p1, p2, p3, p4, p5); } +}; + +template +BindHandler5 bindHandler (Handler handler, + P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5) +{ + return BindHandler5 ( + handler, p1, p2, p3, p4, p5); +} + +//------------------------------------------------------------------------------ + +template +class BindHandler6 +{ +private: + Handler handler; + P1 p1; P2 p2; P3 p3; P4 p4; P5 p5; P6 p6; + +public: + BindHandler6 (Handler const& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_, P4 const& p4_, P5 const& p5_, P6 const& p6_) + : handler (handler_) + , p1 (p1_), p2 (p2_), p3 (p3_), p4 (p4_), p5 (p5_), p6 (p6_) + { } + + BindHandler6 (Handler& handler_, + P1 const& p1_, P2 const& p2_, P3 const& p3_, P4 const& p4_, P5 const& p5_, P6 const& p6_) + : handler (BEAST_MOVE_CAST(Handler)(handler_)) + , p1 (p1_), p2 (p2_), p3 (p3_), p4 (p4_), p5 (p5_), p6 (p6_) + { } + + void operator()() + { + handler ( + static_cast (p1), static_cast (p2), static_cast (p3), + static_cast (p4), static_cast (p5), static_cast (p6) + ); + } + + void operator()() const + { handler (p1, p2, p3, p4, p5, p6); } +}; + +template +BindHandler6 bindHandler (Handler handler, + P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5, P6 const& p6) +{ + return BindHandler6 ( + handler, p1, p2, p3, p4, p5, p6); +} + +/** @} */ + +} +} + +#endif diff --git a/beast/threads/detail/DispatchedHandler.h b/beast/threads/detail/DispatchedHandler.h new file mode 100644 index 0000000000..8cd1897e49 --- /dev/null +++ b/beast/threads/detail/DispatchedHandler.h @@ -0,0 +1,173 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_THREADS_DISPATCHEDHANDLER_H_INCLUDED +#define BEAST_THREADS_DISPATCHEDHANDLER_H_INCLUDED + +#include "BindHandler.h" + +namespace beast { +namespace detail { + +/** A wrapper that packages function call arguments into a dispatch. */ +template +class DispatchedHandler +{ +private: + Dispatcher m_dispatcher; + Handler m_handler; + +public: + typedef void result_type; + + DispatchedHandler (Dispatcher dispatcher, Handler& handler) + : m_dispatcher (dispatcher) + , m_handler (BEAST_MOVE_CAST(Handler)(handler)) + { + } + +#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS + DispatchedHandler (DispatchedHandler const& other) + : m_dispatcher (other.m_dispatcher) + , m_handler (other.m_handler) + { + } + + DispatchedHandler (DispatchedHandler&& other) + : m_dispatcher (other.m_dispatcher) + , m_handler (BEAST_MOVE_CAST(Handler)(other.m_handler)) + { + } +#endif + + void operator()() + { + m_dispatcher.dispatch (m_handler); + } + + void operator()() const + { + m_dispatcher.dispatch (m_handler); + } + + template + void operator() (P1 const& p1) + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1)); + } + + template + void operator() (P1 const& p1) const + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1)); + } + + template + void operator() (P1 const& p1, P2 const& p2) + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2)); + } + + template + void operator() (P1 const& p1, P2 const& p2) const + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3) + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3) const + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3, p4)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3, p4)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5) + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3, p4, p5)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5) const + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3, p4, p5)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5, P6 const& p6) + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3, p4, p5, p6)); + } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5, P6 const& p6) const + { + m_dispatcher.dispatch ( + detail::bindHandler (m_handler, + p1, p2, p3, p4, p5, p6)); + } +}; + +} +} + +#endif diff --git a/beast/threads/impl/Atomic.cpp b/beast/threads/impl/Atomic.cpp new file mode 100644 index 0000000000..5f1790fd48 --- /dev/null +++ b/beast/threads/impl/Atomic.cpp @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../../../modules/beast_core/beast_core.h" // for UnitTest + +namespace beast { + +class AtomicTests : public UnitTest +{ +public: + AtomicTests() : UnitTest ("Atomic", "beast") {} + + template + void testFloat () + { + Atomic a, b; + a = (Type) 21; + memoryBarrier(); + + /* These are some simple test cases to check the atomics - let me know + if any of these assertions fail on your system! + */ + expect (a.get() == (Type) 21); + expect (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21); + expect (a.get() == (Type) 21); + expect (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21); + expect (a.get() == (Type) 101); + expect (! a.compareAndSetBool ((Type) 300, (Type) 200)); + expect (a.get() == (Type) 101); + expect (a.compareAndSetBool ((Type) 200, a.get())); + expect (a.get() == (Type) 200); + + expect (a.exchange ((Type) 300) == (Type) 200); + expect (a.get() == (Type) 300); + + b = a; + expect (b.get() == a.get()); + } + + template + void testInteger () + { + Atomic a, b; + a.set ((Type) 10); + expect (a.value == (Type) 10); + expect (a.get() == (Type) 10); + a += (Type) 15; + expect (a.get() == (Type) 25); + memoryBarrier(); + a -= (Type) 5; + expect (a.get() == (Type) 20); + expect (++a == (Type) 21); + ++a; + expect (--a == (Type) 21); + expect (a.get() == (Type) 21); + memoryBarrier(); + + testFloat (); + } + + void runTest() + { + beginTestCase ("Misc"); + + char a1[7]; + expect (numElementsInArray(a1) == 7); + int a2[3]; + expect (numElementsInArray(a2) == 3); + + expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211); + expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); + expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211)); + + beginTestCase ("int"); + testInteger (); + + beginTestCase ("unsigned int"); + testInteger (); + + beginTestCase ("int32"); + testInteger (); + + beginTestCase ("uint32"); + testInteger (); + + beginTestCase ("long"); + testInteger (); + + beginTestCase ("void*"); + testInteger (); + + beginTestCase ("int*"); + testInteger (); + + beginTestCase ("float"); + testFloat (); + + #if ! BEAST_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms + beginTestCase ("int64"); + testInteger (); + + beginTestCase ("uint64"); + testInteger (); + + beginTestCase ("double"); + testFloat (); + #endif + } +}; + +static AtomicTests atomicTests; + +} diff --git a/beast/threads/impl/RecursiveMutex.cpp b/beast/threads/impl/RecursiveMutex.cpp new file mode 100644 index 0000000000..414f883c91 --- /dev/null +++ b/beast/threads/impl/RecursiveMutex.cpp @@ -0,0 +1,111 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../RecursiveMutex.h" + +#if BEAST_WINDOWS + +#include "../StaticAssert.h" + +#include +#undef check +#undef direct +#undef max +#undef min +#undef TYPE_BOOL + +namespace beast { + +RecursiveMutex::RecursiveMutex() +{ + // (just to check the MS haven't changed this structure and broken things...) +#if BEAST_VC7_OR_EARLIER + static_bassert (sizeof (CRITICAL_SECTION) <= 24); +#else + static_bassert (sizeof (CRITICAL_SECTION) <= sizeof (section)); +#endif + + InitializeCriticalSection ((CRITICAL_SECTION*) section); +} + +RecursiveMutex::~RecursiveMutex() +{ + DeleteCriticalSection ((CRITICAL_SECTION*) section); +} + +void RecursiveMutex::lock() const +{ + EnterCriticalSection ((CRITICAL_SECTION*) section); +} + +void RecursiveMutex::unlock() const +{ + LeaveCriticalSection ((CRITICAL_SECTION*) section); +} + +bool RecursiveMutex::try_lock() const +{ + return TryEnterCriticalSection ((CRITICAL_SECTION*) section) != FALSE; +} + +} + +#else + +namespace beast { + +RecursiveMutex::RecursiveMutex() +{ + pthread_mutexattr_t atts; + pthread_mutexattr_init (&atts); + pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); +#if ! BEAST_ANDROID + pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT); +#endif + pthread_mutex_init (&mutex, &atts); + pthread_mutexattr_destroy (&atts); +} + +RecursiveMutex::~RecursiveMutex() +{ + pthread_mutex_destroy (&mutex); +} + +void RecursiveMutex::lock() const +{ + pthread_mutex_lock (&mutex); +} + +void RecursiveMutex::unlock() const +{ + pthread_mutex_unlock (&mutex); +} + +bool RecursiveMutex::try_lock() const +{ + return pthread_mutex_trylock (&mutex) == 0; +} + +} + +#endif diff --git a/beast/threads/impl/ServiceQueue.cpp b/beast/threads/impl/ServiceQueue.cpp new file mode 100644 index 0000000000..f82368c49a --- /dev/null +++ b/beast/threads/impl/ServiceQueue.cpp @@ -0,0 +1,465 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../ServiceQueue.h" + +#include "../../../modules/beast_core/beast_core.h" // for UnitTest + +namespace beast { + +namespace detail { + +//------------------------------------------------------------------------------ + +class ServiceQueueBase::ScopedServiceThread : public List ::Node +{ +public: + explicit ScopedServiceThread (ServiceQueueBase* queue) + : m_saved (ServiceQueueBase::s_service.get()) + { + ServiceQueueBase::s_service.get() = queue; + } + + ~ScopedServiceThread() + { + ServiceQueueBase::s_service.get() = m_saved; + } + +private: + ServiceQueueBase* m_saved; +}; + +//------------------------------------------------------------------------------ + +ServiceQueueBase::ServiceQueueBase() +{ +} + +ServiceQueueBase::~ServiceQueueBase() +{ +} + +std::size_t ServiceQueueBase::poll () +{ + CPUMeter::ScopedActiveTime interval (m_cpuMeter); + + std::size_t total (0); + ScopedServiceThread thread (this); + for (;;) + { + std::size_t const n (dequeue()); + if (! n) + break; + total += n; + } + return total; +} + +std::size_t ServiceQueueBase::poll_one () +{ + CPUMeter::ScopedActiveTime interval (m_cpuMeter); + + ScopedServiceThread thread (this); + return dequeue(); +} + +std::size_t ServiceQueueBase::run () +{ + std::size_t total (0); + ScopedServiceThread thread (this); + while (! stopped()) + { + { + CPUMeter::ScopedActiveTime interval (m_cpuMeter); + total += poll (); + } + + { + CPUMeter::ScopedIdleTime interval (m_cpuMeter); + wait (); + } + } + return total; +} + +std::size_t ServiceQueueBase::run_one () +{ + std::size_t n; + ScopedServiceThread (this); + for (;;) + { + { + CPUMeter::ScopedActiveTime interval (m_cpuMeter); + n = poll_one(); + if (n != 0) + break; + } + + { + CPUMeter::ScopedIdleTime interval (m_cpuMeter); + wait(); + } + } + return n; +} + +void ServiceQueueBase::stop () +{ + SharedState::Access state (m_state); + m_stopped.set (1); + for(;;) + { + Waiter* waiting (state->waiting.pop_front()); + if (waiting == nullptr) + break; + waiting->signal(); + } +} + +void ServiceQueueBase::reset() +{ + // Must be stopped + bassert (m_stopped.get () != 0); + m_stopped.set (0); +} + +// Block on the event if there are no items +// in the queue and we are not stopped. +// +void ServiceQueueBase::wait () +{ + Waiter* waiter (nullptr); + + { + SharedState::Access state (m_state); + if (stopped ()) + return; + if (! state->handlers.empty()) + return; + waiter = state->unused.pop_front(); + if (! waiter) + waiter = new_waiter(); + state->waiting.push_front (waiter); + } + + waiter->wait(); + + // Waiter got taken off the waiting list + + { + SharedState::Access state (m_state); + state->unused.push_front (waiter); + } +} + +void ServiceQueueBase::enqueue (Item* item) +{ + Waiter* waiter; + + { + SharedState::Access state (m_state); + state->handlers.push_back (*item); + // Signal a Waiter if one exists + waiter = state->waiting.pop_front(); + } + + if (waiter != nullptr) + waiter->signal(); +} + +// A thread can only be blocked on one ServiceQueue so we store the pointer +// to which ServiceQueue it is blocked on to determine if the thread belongs +// to that queue. +// +ThreadLocalValue ServiceQueueBase::s_service; + +} + +//------------------------------------------------------------------------------ + +namespace detail +{ + +//------------------------------------------------------------------------------ + +class ServiceQueueTimingTests + : public UnitTest +{ +public: + class Stopwatch + { + public: + Stopwatch () { start(); } + void start () { m_startTime = Time::getHighResolutionTicks (); } + double getElapsed () + { + int64 const now = Time::getHighResolutionTicks(); + return Time::highResolutionTicksToSeconds (now - m_startTime); + } + private: + int64 m_startTime; + }; + + static int const callsPerThread = 50000; + + //-------------------------------------------------------------------------- + + template + struct Consumer : Thread + { + ServiceType& m_service; + Random m_random; + String m_string; + + Consumer (int id, int64 seedValue, ServiceType& service) + : Thread ("C#" + String::fromNumber (id)) + , m_service (service) + , m_random (seedValue) + { startThread(); } + + ~Consumer () + { stopThread(); } + + static Consumer*& thread() + { + static ThreadLocalValue local; + return local.get(); + } + + static void stop_one () + { thread()->signalThreadShouldExit(); } + + static void handler () + { thread()->do_handler(); } + + void do_handler() + { + String const s (String::fromNumber (m_random.nextInt())); + m_string += s; + if (m_string.length() > 100) + m_string = String::empty; + } + + void run () + { + thread() = this; + while (! threadShouldExit()) + m_service.run_one(); + } + }; + + //-------------------------------------------------------------------------- + + template + struct Producer : Thread + { + ServiceType& m_service; + Random m_random; + String m_string; + + Producer (int id, int64 seedValue, ServiceType& service) + : Thread ("P#" + String::fromNumber (id)) + , m_service (service) + , m_random (seedValue) + { } + + ~Producer () + { stopThread(); } + + void run () + { + for (std::size_t i = 0; i < callsPerThread; ++i) + { + String const s (String::fromNumber (m_random.nextInt())); + m_string += s; + if (m_string.length() > 100) + m_string = String::empty; + m_service.dispatch (bind (&Consumer::handler)); + } + } + }; + + //-------------------------------------------------------------------------- + + template + void testThreads (std::size_t nConsumers, std::size_t nProducers) + { + beginTestCase (String::fromNumber (nConsumers) + " consumers, " + + String::fromNumber (nProducers) + " producers, " + + "Allocator = " + std::string(typeid(Allocator).name())); + + typedef ServiceQueueType ServiceType; + + ServiceType service (nConsumers); + std::vector > > consumers; + std::vector > > producers; + consumers.reserve (nConsumers); + producers.reserve (nProducers); + + for (std::size_t i = 0; i < nConsumers; ++i) + consumers.push_back (new Consumer (i + 1, + random().nextInt64(), service)); + + for (std::size_t i = 0; i < nProducers; ++i) + producers.push_back (new Producer (i + 1, + random().nextInt64(), service)); + + Stopwatch t; + + for (std::size_t i = 0; i < producers.size(); ++i) + producers[i]->startThread(); + + for (std::size_t i = 0; i < producers.size(); ++i) + producers[i]->waitForThreadToExit(); + + for (std::size_t i = 0; i < consumers.size(); ++i) + service.dispatch (bind (&Consumer ::stop_one)); + + for (std::size_t i = 0; i < consumers.size(); ++i) + consumers[i]->waitForThreadToExit(); + + double const seconds (t.getElapsed()); + logMessage (String (seconds, 2) + " seconds"); + + pass(); + } + + void runTest() + { +#if 1 + testThreads > (1, 1); + testThreads > (1, 4); + testThreads > (1, 16); + testThreads > (4, 1); + testThreads > (8, 16); +#endif + +#if 0 + testThreads > (1, 1); + testThreads > (1, 4); + testThreads > (1, 16); + testThreads > (4, 1); + testThreads > (8, 16); +#endif + } + + ServiceQueueTimingTests () : UnitTest ("ServiceQueueTiming", "beast", runManual) + { + } +}; + +static ServiceQueueTimingTests serviceQueueTimingTests; + +//------------------------------------------------------------------------------ + +class ServiceQueueTests + : public UnitTest +{ +public: + struct ServiceThread : Thread + { + Random m_random; + ServiceQueue& m_service; + String m_string; + + ServiceThread (int id, int64 seedValue, + ServiceQueue& service) + : Thread ("#" + String::fromNumber (id)) + , m_random (seedValue) + , m_service (service) + { + startThread(); + } + + ~ServiceThread () + { + stopThread(); + } + + static ServiceThread*& thread() + { + static ThreadLocalValue local; + return local.get(); + } + + static void stop_one () + { + thread()->signalThreadShouldExit(); + } + + static void handler () + { + thread()->do_handler(); + } + + void do_handler() + { +#if 1 + String const s (String::fromNumber (m_random.nextInt())); + m_string += s; + if (m_string.length() > 100) + m_string = String::empty; +#endif + } + + void run () + { + thread() = this; + while (! threadShouldExit()) + m_service.run_one(); + } + }; + + static int const callsPerThread = 10000; + + void testThreads (std::size_t n) + { + beginTestCase (String::fromNumber (n) + " threads"); + ServiceQueue service (n); + std::vector > threads; + threads.reserve (n); + for (std::size_t i = 0; i < n; ++i) + threads.push_back (new ServiceThread (i + 1, + random().nextInt64(), service)); + for (std::size_t i = n * callsPerThread; i; --i) + service.dispatch (bind (&ServiceThread::handler)); + for (std::size_t i = 0; i < threads.size(); ++i) + service.dispatch (bind (&ServiceThread::stop_one)); + for (std::size_t i = 0; i < threads.size(); ++i) + threads[i]->waitForThreadToExit(); + pass(); + } + + void runTest() + { + testThreads (1); + testThreads (4); + testThreads (16); + } + + ServiceQueueTests () : UnitTest ("ServiceQueue", "beast") + { + } +}; + +static ServiceQueueTests serviceQueueTests; + +} + +} diff --git a/beast/threads/impl/Stoppable.cpp b/beast/threads/impl/Stoppable.cpp new file mode 100644 index 0000000000..75e01986aa --- /dev/null +++ b/beast/threads/impl/Stoppable.cpp @@ -0,0 +1,198 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../Stoppable.h" + +namespace beast { + +Stoppable::Stoppable (char const* name, RootStoppable& root) + : m_name (name) + , m_root (root) + , m_child (this) + , m_stopped (false) + , m_childrenStopped (false) +{ +} + +Stoppable::Stoppable (char const* name, Stoppable& parent) + : m_name (name) + , m_root (parent.m_root) + , m_child (this) + , m_stopped (false) + , m_childrenStopped (false) +{ + // Must not have stopping parent. + bassert (! parent.isStopping()); + + parent.m_children.push_front (&m_child); +} + +Stoppable::~Stoppable () +{ + // Children must be stopped. + bassert (m_childrenStopped); +} + +bool Stoppable::isStopping() const +{ + return m_root.isStopping(); +} + +bool Stoppable::isStopped () const +{ + return m_stopped; +} + +bool Stoppable::areChildrenStopped () const +{ + return m_childrenStopped; +} + +void Stoppable::stopped () +{ + m_stoppedEvent.signal(); +} + +void Stoppable::onPrepare () +{ +} + +void Stoppable::onStart () +{ +} + +void Stoppable::onStop () +{ + stopped(); +} + +void Stoppable::onChildrenStopped () +{ +} + +//------------------------------------------------------------------------------ + +void Stoppable::prepareRecursive () +{ + for (Children::const_iterator iter (m_children.cbegin ()); + iter != m_children.cend(); ++iter) + iter->stoppable->prepareRecursive (); + onPrepare (); +} + +void Stoppable::startRecursive () +{ + onStart (); + for (Children::const_iterator iter (m_children.cbegin ()); + iter != m_children.cend(); ++iter) + iter->stoppable->startRecursive (); +} + +void Stoppable::stopAsyncRecursive () +{ + onStop (); + for (Children::const_iterator iter (m_children.cbegin ()); + iter != m_children.cend(); ++iter) + iter->stoppable->stopAsyncRecursive (); +} + +void Stoppable::stopRecursive (Journal journal) +{ + // Block on each child from the bottom of the tree up. + // + for (Children::const_iterator iter (m_children.cbegin ()); + iter != m_children.cend(); ++iter) + iter->stoppable->stopRecursive (journal); + + // if we get here then all children have stopped + // + memoryBarrier (); + m_childrenStopped = true; + onChildrenStopped (); + + // Now block on this Stoppable. + // + bool const timedOut (! m_stoppedEvent.wait (1 * 1000)); // milliseconds + if (timedOut) + { + journal.warning << "Waiting for '" << m_name << "' to stop"; + m_stoppedEvent.wait (); + } + + // once we get here, we know the stoppable has stopped. + m_stopped = true; +} + +//------------------------------------------------------------------------------ + +RootStoppable::RootStoppable (char const* name) + : Stoppable (name, *this) +{ +} + +RootStoppable::~RootStoppable () +{ +} + +bool RootStoppable::isStopping() const +{ + return m_calledStopAsync.get() != 0; +} + +void RootStoppable::prepare () +{ + if (! m_prepared.compareAndSetBool (1, 0)) + return; + + prepareRecursive (); +} + +void RootStoppable::start () +{ + // Courtesy call to prepare. + if (m_prepared.compareAndSetBool (1, 0)) + prepareRecursive (); + + if (! m_started.compareAndSetBool (1, 0)) + return; + + startRecursive (); +} + +void RootStoppable::stop (Journal journal) +{ + if (! m_calledStop.compareAndSetBool (1, 0)) + { + journal.warning << "Stoppable::stop called again"; + return; + } + + stopAsync (); + stopRecursive (journal); +} + +void RootStoppable::stopAsync () +{ + if (! m_calledStopAsync.compareAndSetBool (1, 0)) + return; + + stopAsyncRecursive (); +} + +} diff --git a/beast/threads/impl/Thread.cpp b/beast/threads/impl/Thread.cpp new file mode 100644 index 0000000000..d6969552b5 --- /dev/null +++ b/beast/threads/impl/Thread.cpp @@ -0,0 +1,599 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../Thread.h" + +namespace beast { + +Thread::Thread (const String& threadName_) + : threadName (threadName_), + threadHandle (nullptr), + threadId (0), + threadPriority (5), + affinityMask (0), + shouldExit (false) +{ +} + +Thread::~Thread() +{ + /* If your thread class's destructor has been called without first stopping the thread, that + means that this partially destructed object is still performing some work - and that's + probably a Bad Thing! + + To avoid this type of nastiness, always make sure you call stopThread() before or during + your subclass's destructor. + */ + check_precondition (! isThreadRunning()); + + stopThread (); +} + +//============================================================================== +// Use a ref-counted object to hold this shared data, so that it can outlive its static +// shared pointer when threads are still running during static shutdown. +struct CurrentThreadHolder : public SharedObject +{ + CurrentThreadHolder() noexcept {} + + typedef SharedPtr Ptr; + ThreadLocalValue value; +}; + +static char currentThreadHolderLock [sizeof (SpinLock)]; // (statically initialised to zeros). + +static SpinLock* castToSpinLockWithoutAliasingWarning (void* s) +{ + return static_cast (s); +} + +static CurrentThreadHolder::Ptr getCurrentThreadHolder() +{ + static CurrentThreadHolder::Ptr currentThreadHolder; + SpinLock::ScopedLockType lock (*castToSpinLockWithoutAliasingWarning (currentThreadHolderLock)); + + if (currentThreadHolder == nullptr) + currentThreadHolder = new CurrentThreadHolder(); + + return currentThreadHolder; +} + +void Thread::threadEntryPoint() +{ + const CurrentThreadHolder::Ptr currentThreadHolder (getCurrentThreadHolder()); + currentThreadHolder->value = this; + + if (threadName.isNotEmpty()) + setCurrentThreadName (threadName); + + if (startSuspensionEvent.wait (10000)) + { + bassert (getCurrentThreadId() == threadId); + + if (affinityMask != 0) + setCurrentThreadAffinityMask (affinityMask); + + run(); + } + + currentThreadHolder->value.releaseCurrentThreadStorage(); + closeThreadHandle(); +} + +// used to wrap the incoming call from the platform-specific code +void BEAST_API beast_threadEntryPoint (void* userData) +{ + static_cast (userData)->threadEntryPoint(); +} + +//============================================================================== +void Thread::startThread() +{ + const RecursiveMutex::ScopedLockType sl (startStopLock); + + shouldExit = false; + + if (threadHandle == nullptr) + { + launchThread(); + setThreadPriority (threadHandle, threadPriority); + startSuspensionEvent.signal(); + } +} + +void Thread::startThread (const int priority) +{ + const RecursiveMutex::ScopedLockType sl (startStopLock); + + if (threadHandle == nullptr) + { + threadPriority = priority; + startThread(); + } + else + { + setPriority (priority); + } +} + +bool Thread::isThreadRunning() const +{ + return threadHandle != nullptr; +} + +Thread* Thread::getCurrentThread() +{ + return getCurrentThreadHolder()->value.get(); +} + +//============================================================================== +void Thread::signalThreadShouldExit() +{ + shouldExit = true; +} + +bool Thread::waitForThreadToExit (const int timeOutMilliseconds) const +{ + // Doh! So how exactly do you expect this thread to wait for itself to stop?? + bassert (getThreadId() != getCurrentThreadId() || getCurrentThreadId() == 0); + + const uint32 timeoutEnd = Time::getMillisecondCounter() + (uint32) timeOutMilliseconds; + + while (isThreadRunning()) + { + if (timeOutMilliseconds >= 0 && Time::getMillisecondCounter() > timeoutEnd) + return false; + + sleep (2); + } + + return true; +} + +bool Thread::stopThread (const int timeOutMilliseconds) +{ + bool cleanExit = true; + + // agh! You can't stop the thread that's calling this method! How on earth + // would that work?? + bassert (getCurrentThreadId() != getThreadId()); + + const RecursiveMutex::ScopedLockType sl (startStopLock); + + if (isThreadRunning()) + { + signalThreadShouldExit(); + notify(); + + if (timeOutMilliseconds != 0) + { + cleanExit = waitForThreadToExit (timeOutMilliseconds); + } + + if (isThreadRunning()) + { + bassert (! cleanExit); + + // very bad karma if this point is reached, as there are bound to be + // locks and events left in silly states when a thread is killed by force.. + killThread(); + + threadHandle = nullptr; + threadId = 0; + + cleanExit = false; + } + else + { + cleanExit = true; + } + } + + return cleanExit; +} + +void Thread::stopThreadAsync () +{ + const RecursiveMutex::ScopedLockType sl (startStopLock); + + if (isThreadRunning()) + { + signalThreadShouldExit(); + notify(); + } +} + +//============================================================================== +bool Thread::setPriority (const int newPriority) +{ + // NB: deadlock possible if you try to set the thread prio from the thread itself, + // so using setCurrentThreadPriority instead in that case. + if (getCurrentThreadId() == getThreadId()) + return setCurrentThreadPriority (newPriority); + + const RecursiveMutex::ScopedLockType sl (startStopLock); + + if (setThreadPriority (threadHandle, newPriority)) + { + threadPriority = newPriority; + return true; + } + + return false; +} + +bool Thread::setCurrentThreadPriority (const int newPriority) +{ + return setThreadPriority (0, newPriority); +} + +void Thread::setAffinityMask (const uint32 newAffinityMask) +{ + affinityMask = newAffinityMask; +} + +//============================================================================== +bool Thread::wait (const int timeOutMilliseconds) const +{ + return defaultEvent.wait (timeOutMilliseconds); +} + +void Thread::notify() const +{ + defaultEvent.signal(); +} + +//============================================================================== + +// This is here so we dont have circular includes +// +void SpinLock::enter() const noexcept +{ + if (! tryEnter()) + { + for (int i = 20; --i >= 0;) + if (tryEnter()) + return; + + while (! tryEnter()) + Thread::yield(); + } +} + +} + +//------------------------------------------------------------------------------ + +#if BEAST_WINDOWS + +#include +#include +#include + +namespace beast { + +HWND beast_messageWindowHandle = 0; // (this is used by other parts of the codebase) + +void BEAST_API beast_threadEntryPoint (void*); + +static unsigned int __stdcall threadEntryProc (void* userData) +{ + if (beast_messageWindowHandle != 0) + AttachThreadInput (GetWindowThreadProcessId (beast_messageWindowHandle, 0), + GetCurrentThreadId(), TRUE); + + beast_threadEntryPoint (userData); + + _endthreadex (0); + return 0; +} + +void Thread::launchThread() +{ + unsigned int newThreadId; + threadHandle = (void*) _beginthreadex (0, 0, &threadEntryProc, this, 0, &newThreadId); + threadId = (ThreadID) newThreadId; +} + +void Thread::closeThreadHandle() +{ + CloseHandle ((HANDLE) threadHandle); + threadId = 0; + threadHandle = 0; +} + +void Thread::killThread() +{ + if (threadHandle != 0) + { + #if BEAST_DEBUG + OutputDebugStringA ("** Warning - Forced thread termination **\n"); + #endif + TerminateThread (threadHandle, 0); + } +} + +void Thread::setCurrentThreadName (const String& name) +{ + #if BEAST_DEBUG && BEAST_MSVC + struct + { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + } info; + + info.dwType = 0x1000; + info.szName = name.toUTF8(); + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; + + __try + { + RaiseException (0x406d1388 /*MS_VC_EXCEPTION*/, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info); + } + __except (EXCEPTION_CONTINUE_EXECUTION) + {} + #else + (void) name; + #endif +} + +Thread::ThreadID Thread::getCurrentThreadId() +{ + return (ThreadID) (pointer_sized_int) GetCurrentThreadId(); +} + +bool Thread::setThreadPriority (void* handle, int priority) +{ + int pri = THREAD_PRIORITY_TIME_CRITICAL; + + if (priority < 1) pri = THREAD_PRIORITY_IDLE; + else if (priority < 2) pri = THREAD_PRIORITY_LOWEST; + else if (priority < 5) pri = THREAD_PRIORITY_BELOW_NORMAL; + else if (priority < 7) pri = THREAD_PRIORITY_NORMAL; + else if (priority < 9) pri = THREAD_PRIORITY_ABOVE_NORMAL; + else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST; + + if (handle == 0) + handle = GetCurrentThread(); + + return SetThreadPriority (handle, pri) != FALSE; +} + +void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) +{ + SetThreadAffinityMask (GetCurrentThread(), affinityMask); +} + +struct SleepEvent +{ + SleepEvent() noexcept + : handle (CreateEvent (nullptr, FALSE, FALSE, + #if BEAST_DEBUG + _T("BEAST Sleep Event"))) + #else + nullptr)) + #endif + {} + + ~SleepEvent() noexcept + { + CloseHandle (handle); + handle = 0; + } + + HANDLE handle; +}; + +static SleepEvent sleepEvent; + +void BEAST_CALLTYPE Thread::sleep (const int millisecs) +{ + if (millisecs >= 10 || sleepEvent.handle == 0) + { + Sleep ((DWORD) millisecs); + } + else + { + // unlike Sleep() this is guaranteed to return to the current thread after + // the time expires, so we'll use this for short waits, which are more likely + // to need to be accurate + WaitForSingleObject (sleepEvent.handle, (DWORD) millisecs); + } +} + +void Thread::yield() +{ + Sleep (0); +} + +} + +//------------------------------------------------------------------------------ + +#else + +#include +#if BEAST_BSD + // ??? +#else +# include +#endif + +namespace beast { + +void BEAST_CALLTYPE Thread::sleep (int millisecs) +{ + struct timespec time; + time.tv_sec = millisecs / 1000; + time.tv_nsec = (millisecs % 1000) * 1000000; + nanosleep (&time, nullptr); +} + +void BEAST_API beast_threadEntryPoint (void*); + +extern "C" void* threadEntryProc (void*); +extern "C" void* threadEntryProc (void* userData) +{ + BEAST_AUTORELEASEPOOL + { + #if BEAST_ANDROID + struct AndroidThreadScope + { + AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } + ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } + }; + + const AndroidThreadScope androidEnv; + #endif + + beast_threadEntryPoint (userData); + } + + return nullptr; +} + +void Thread::launchThread() +{ + threadHandle = 0; + pthread_t handle = 0; + + if (pthread_create (&handle, 0, threadEntryProc, this) == 0) + { + pthread_detach (handle); + threadHandle = (void*) handle; + threadId = (ThreadID) threadHandle; + } +} + +void Thread::closeThreadHandle() +{ + threadId = 0; + threadHandle = 0; +} + +void Thread::killThread() +{ + if (threadHandle != 0) + { + #if BEAST_ANDROID + bassertfalse; // pthread_cancel not available! + #else + pthread_cancel ((pthread_t) threadHandle); + #endif + } +} + +void Thread::setCurrentThreadName (const String& name) +{ + #if BEAST_IOS || (BEAST_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) + BEAST_AUTORELEASEPOOL + { + [[NSThread currentThread] setName: beastStringToNS (name)]; + } + #elif BEAST_LINUX + #if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012 + pthread_setname_np (pthread_self(), name.toRawUTF8()); + #else + prctl (PR_SET_NAME, name.toRawUTF8(), 0, 0, 0); + #endif + #endif +} + +bool Thread::setThreadPriority (void* handle, int priority) +{ + struct sched_param param; + int policy; + priority = blimit (0, 10, priority); + + if (handle == nullptr) + handle = (void*) pthread_self(); + + if (pthread_getschedparam ((pthread_t) handle, &policy, ¶m) != 0) + return false; + + policy = priority == 0 ? SCHED_OTHER : SCHED_RR; + + const int minPriority = sched_get_priority_min (policy); + const int maxPriority = sched_get_priority_max (policy); + + param.sched_priority = ((maxPriority - minPriority) * priority) / 10 + minPriority; + return pthread_setschedparam ((pthread_t) handle, policy, ¶m) == 0; +} + +Thread::ThreadID Thread::getCurrentThreadId() +{ + return (ThreadID) pthread_self(); +} + +void Thread::yield() +{ + sched_yield(); +} + +//============================================================================== +/* Remove this macro if you're having problems compiling the cpu affinity + calls (the API for these has changed about quite a bit in various Linux + versions, and a lot of distros seem to ship with obsolete versions) +*/ +#if defined (CPU_ISSET) && ! defined (SUPPORT_AFFINITIES) + #define SUPPORT_AFFINITIES 1 +#endif + +void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) +{ + #if SUPPORT_AFFINITIES + cpu_set_t affinity; + CPU_ZERO (&affinity); + + for (int i = 0; i < 32; ++i) + if ((affinityMask & (1 << i)) != 0) + CPU_SET (i, &affinity); + + /* + N.B. If this line causes a compile error, then you've probably not got the latest + version of glibc installed. + + If you don't want to update your copy of glibc and don't care about cpu affinities, + then you can just disable all this stuff by setting the SUPPORT_AFFINITIES macro to 0. + */ + sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity); + sched_yield(); + + #else + /* affinities aren't supported because either the appropriate header files weren't found, + or the SUPPORT_AFFINITIES macro was turned off + */ + bassertfalse; + (void) affinityMask; + #endif +} + +} + +//------------------------------------------------------------------------------ + +#endif + diff --git a/beast/threads/impl/WaitableEvent.cpp b/beast/threads/impl/WaitableEvent.cpp new file mode 100644 index 0000000000..9e882c499b --- /dev/null +++ b/beast/threads/impl/WaitableEvent.cpp @@ -0,0 +1,168 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Portions of this file are from JUCE. + Copyright (c) 2013 - Raw Material Software Ltd. + Please visit http://www.juce.com + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../WaitableEvent.h" + +#if BEAST_WINDOWS + +#include +#undef check +#undef direct +#undef max +#undef min +#undef TYPE_BOOL + +namespace beast { + +WaitableEvent::WaitableEvent (const bool manualReset, bool initiallySignaled) + : handle (CreateEvent (0, manualReset ? TRUE : FALSE, initiallySignaled ? TRUE : FALSE, 0)) +{ +} + +WaitableEvent::~WaitableEvent() +{ + CloseHandle (handle); +} + +void WaitableEvent::signal() const +{ + SetEvent (handle); +} + +void WaitableEvent::reset() const +{ + ResetEvent (handle); +} + +bool WaitableEvent::wait () const +{ + return WaitForSingleObject (handle, INFINITE) == WAIT_OBJECT_0; +} + +bool WaitableEvent::wait (const int timeOutMs) const +{ + if (timeOutMs >= 0) + return WaitForSingleObject (handle, + (DWORD) timeOutMs) == WAIT_OBJECT_0; + return wait (); +} + +} + +#else + +namespace beast { + +WaitableEvent::WaitableEvent (const bool useManualReset, bool initiallySignaled) + : triggered (false), manualReset (useManualReset) +{ + pthread_cond_init (&condition, 0); + + pthread_mutexattr_t atts; + pthread_mutexattr_init (&atts); + #if ! BEAST_ANDROID + pthread_mutexattr_setprotocol (&atts, PTHREAD_PRIO_INHERIT); + #endif + pthread_mutex_init (&mutex, &atts); + + if (initiallySignaled) + signal (); +} + +WaitableEvent::~WaitableEvent() +{ + pthread_cond_destroy (&condition); + pthread_mutex_destroy (&mutex); +} + +bool WaitableEvent::wait () const +{ + return wait (-1); +} + +bool WaitableEvent::wait (const int timeOutMillisecs) const +{ + pthread_mutex_lock (&mutex); + + if (! triggered) + { + if (timeOutMillisecs < 0) + { + do + { + pthread_cond_wait (&condition, &mutex); + } + while (! triggered); + } + else + { + struct timeval now; + gettimeofday (&now, 0); + + struct timespec time; + time.tv_sec = now.tv_sec + (timeOutMillisecs / 1000); + time.tv_nsec = (now.tv_usec + ((timeOutMillisecs % 1000) * 1000)) * 1000; + + if (time.tv_nsec >= 1000000000) + { + time.tv_nsec -= 1000000000; + time.tv_sec++; + } + + do + { + if (pthread_cond_timedwait (&condition, &mutex, &time) == ETIMEDOUT) + { + pthread_mutex_unlock (&mutex); + return false; + } + } + while (! triggered); + } + } + + if (! manualReset) + triggered = false; + + pthread_mutex_unlock (&mutex); + return true; +} + +void WaitableEvent::signal() const +{ + pthread_mutex_lock (&mutex); + triggered = true; + pthread_cond_broadcast (&condition); + pthread_mutex_unlock (&mutex); +} + +void WaitableEvent::reset() const +{ + pthread_mutex_lock (&mutex); + triggered = false; + pthread_mutex_unlock (&mutex); +} + +} + +#endif diff --git a/beast/type_traits/IntegralConstant.h b/beast/type_traits/IntegralConstant.h new file mode 100644 index 0000000000..2ccc55a1e4 --- /dev/null +++ b/beast/type_traits/IntegralConstant.h @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_TYPE_TRAITS_INTEGRALCONSTANT_H_INCLUDED +#define BEAST_TYPE_TRAITS_INTEGRALCONSTANT_H_INCLUDED + +namespace beast { + +// ideas from boost + +template +struct IntegralConstant +{ + typedef IntegralConstant type; + typedef T value_type; + static const T value = val; +}; + +typedef IntegralConstant TrueType; +typedef IntegralConstant FalseType; + +} + +#endif diff --git a/beast/type_traits/IsIntegral.h b/beast/type_traits/IsIntegral.h new file mode 100644 index 0000000000..96b8840328 --- /dev/null +++ b/beast/type_traits/IsIntegral.h @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_TYPE_TRAITS_ISINTEGRAL_H_INCLUDED +#define BEAST_TYPE_TRAITS_ISINTEGRAL_H_INCLUDED + +#include "../CStdInt.h" +#include "IntegralConstant.h" + +namespace beast { + +template struct IsIntegral : FalseType { }; + +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; +template <> struct IsIntegral : TrueType { }; + +} + +#endif diff --git a/beast/type_traits/IsSigned.h b/beast/type_traits/IsSigned.h new file mode 100644 index 0000000000..908dd62e09 --- /dev/null +++ b/beast/type_traits/IsSigned.h @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_TYPE_TRAITS_ISSIGNED_H_INCLUDED +#define BEAST_TYPE_TRAITS_ISSIGNED_H_INCLUDED + +#include "IntegralConstant.h" +#include "../CStdInt.h" + +namespace beast { + +template struct IsSigned : FalseType { }; + +template <> struct IsSigned : TrueType { }; +template <> struct IsSigned : TrueType { }; +template <> struct IsSigned : TrueType { }; +template <> struct IsSigned : TrueType { }; +template <> struct IsSigned : TrueType { }; +template <> struct IsSigned : TrueType { }; +template <> struct IsSigned : TrueType { }; + +} + +#endif diff --git a/beast/type_traits/RemoveSigned.h b/beast/type_traits/RemoveSigned.h new file mode 100644 index 0000000000..e159d4d4bb --- /dev/null +++ b/beast/type_traits/RemoveSigned.h @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_TYPE_TRAITS_REMOVESIGNED_H_INCLUDED +#define BEAST_TYPE_TRAITS_REMOVESIGNED_H_INCLUDED + +#include "IntegralConstant.h" +#include "../CStdInt.h" + +namespace beast { + +/** Returns an equally sized, unsigned type. + Requires: + IsIntegral::value == true +*/ +template +struct RemoveSigned +{ + typedef T type; +}; + +template <> struct RemoveSigned { typedef uint8 type; }; +template <> struct RemoveSigned { typedef uint16 type; }; +template <> struct RemoveSigned { typedef uint32 type; }; +template <> struct RemoveSigned { typedef uint64 type; }; + +} + +#endif diff --git a/beast/utility/BaseFromMember.h b/beast/utility/BaseFromMember.h new file mode 100644 index 0000000000..e2103b6493 --- /dev/null +++ b/beast/utility/BaseFromMember.h @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_BASEFROMMEMBER_H_INCLUDED +#define BEAST_UTILITY_BASEFROMMEMBER_H_INCLUDED + +namespace beast { + +template +class BaseFromMember +{ +private: + T m_t; + +public: + BaseFromMember () + : m_t (T()) + { + } + + template + explicit BaseFromMember (P1 const& p1) + : m_t (p1) + { } + + template + BaseFromMember (P1 const& p1, P2 const& p2) + : m_t (p1, p2) + { } + + template + BaseFromMember (P1 const& p1, P2 const& p2, P3 const& p3) + : m_t (p1, p2, p3) + { } + + template + BaseFromMember (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) + : m_t (p1, p2, p3, p4) + { } + + template + BaseFromMember (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4, P5 const& p5) + : m_t (p1, p2, p3, p4, p5) + { } + + T& member() + { return m_t; } + + T const& member() const + { return m_t; } +}; + +} + +#endif diff --git a/modules/beast_core/diagnostic/beast_Debug.h b/beast/utility/Debug.h similarity index 95% rename from modules/beast_core/diagnostic/beast_Debug.h rename to beast/utility/Debug.h index e80418e042..0a1d5e3e0f 100644 --- a/modules/beast_core/diagnostic/beast_Debug.h +++ b/beast/utility/Debug.h @@ -17,8 +17,12 @@ */ //============================================================================== -#ifndef BEAST_DEBUG_H_INCLUDED -#define BEAST_DEBUG_H_INCLUDED +#ifndef BEAST_UTILITY_DEBUG_H_INCLUDED +#define BEAST_UTILITY_DEBUG_H_INCLUDED + +#include "../strings/String.h" + +namespace beast { // Auxiliary outines for debugging @@ -83,4 +87,6 @@ extern void checkHeap (); } +} + #endif diff --git a/beast/utility/EnableIf.h b/beast/utility/EnableIf.h new file mode 100644 index 0000000000..51087fa41f --- /dev/null +++ b/beast/utility/EnableIf.h @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_ENABLEIF_H_INCLUDED +#define BEAST_UTILITY_ENABLEIF_H_INCLUDED + +#include "../type_traits/IntegralConstant.h" + +namespace beast +{ + +template +struct EnableIfBool : TrueType { typedef T type; }; + +template +struct EnableIfBool : FalseType { }; + +template +struct EnableIf : public EnableIfBool { }; + +template +struct DisableIfBool : FalseType { typedef T type; }; + +template +struct DisableIfBool { }; + +template +struct DisableIf : public DisableIfBool { }; + +} + +#endif diff --git a/modules/beast_core/diagnostic/beast_Error.h b/beast/utility/Error.h similarity index 95% rename from modules/beast_core/diagnostic/beast_Error.h rename to beast/utility/Error.h index 946270b758..f9b188925e 100644 --- a/modules/beast_core/diagnostic/beast_Error.h +++ b/beast/utility/Error.h @@ -17,8 +17,17 @@ */ //============================================================================== -#ifndef BEAST_ERROR_H_INCLUDED -#define BEAST_ERROR_H_INCLUDED +#ifndef BEAST_UTILITY_ERROR_H_INCLUDED +#define BEAST_UTILITY_ERROR_H_INCLUDED + +#include "../Config.h" + +#include "../SafeBool.h" +#include "../strings/String.h" + +#include + +namespace beast { /** A concise error report. @@ -32,7 +41,7 @@ @ingroup beast_core */ -class BEAST_API Error +class Error : public std::exception , public SafeBool { @@ -119,4 +128,6 @@ private: mutable char const* m_szWhat; }; +} + #endif diff --git a/beast/utility/Journal.h b/beast/utility/Journal.h new file mode 100644 index 0000000000..e262d98a45 --- /dev/null +++ b/beast/utility/Journal.h @@ -0,0 +1,193 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_JOURNAL_H_INCLUDED +#define BEAST_UTILITY_JOURNAL_H_INCLUDED + +#include + +namespace beast +{ + +/** A generic endpoint for log messages. */ +class Journal +{ +public: + class Sink; + +private: + Sink* m_sink; + +public: + /** Severity level of the message. */ + enum Severity + { + kLowestSeverity = 0, + kTrace = kLowestSeverity, + kDebug, + kInfo, + kWarning, + kError, + kFatal, + + kDisabled + }; + + //-------------------------------------------------------------------------- + + /** Abstraction for the underlying message destination. */ + class Sink + { + public: + virtual ~Sink () { } + + /** Write text to the sink at the specified severity. */ + virtual void write (Severity severity, std::string const& text) = 0; + + /** Returns `true` if text at the passed severity produces output. */ + virtual bool active (Severity severity) = 0; + + /** Returns `true` if a message is also written to the Output Window (MSVC). */ + virtual bool console () = 0; + + /** Set the minimum severity this sink will report. */ + virtual void set_severity (Severity severity) = 0; + + /** Set whether messages are also written to the Output Window (MSVC). */ + virtual void set_console (bool to_console) = 0; + }; + + /** Returns a Sink which does nothing. */ + static Sink& getNullSink (); + + //-------------------------------------------------------------------------- + + class Stream; + + /** Scoped ostream-based container for writing messages to a Journal. */ + class ScopedStream + { + public: + explicit ScopedStream (Stream const& stream); + ScopedStream (ScopedStream const& other); + + template + ScopedStream (Stream const& stream, T const& t) + : m_sink (stream.sink()) + , m_severity (stream.severity()) + { + m_ostream << t; + } + + ScopedStream (Stream const& stream, std::ostream& manip (std::ostream&)); + + ~ScopedStream (); + + std::ostringstream& ostream () const; + + std::ostream& operator<< (std::ostream& manip (std::ostream&)) const; + + template + std::ostream& operator<< (T const& t) const + { + return m_ostream << t; + } + + private: + ScopedStream& operator= (ScopedStream const&); // disallowed + + Sink& m_sink; + Severity const m_severity; + std::ostringstream mutable m_ostream; + bool m_toOutputWindow; + }; + + //-------------------------------------------------------------------------- + + class Stream + { + public: + /** Construct a stream which produces no logging output. */ + Stream (); + + /** Construct a stream that writes to the Sink at the given Severity. */ + Stream (Sink& sink, Severity severity); + + /** Construct or copy another Stream. */ + /** @{ */ + Stream (Stream const& other); + Stream& operator= (Stream const& other); + /** @} */ + + /** Returns the Sink that this Stream writes to. */ + Sink& sink() const; + + /** Returns the Severity of messages this Stream reports. */ + Severity severity() const; + + /** Returns `true` if sink logs anything at this stream's severity. */ + bool active() const; + + /** Output stream support. */ + /** @{ */ + ScopedStream operator<< (std::ostream& manip (std::ostream&)) const; + + template + ScopedStream operator<< (T const& t) const + { + return ScopedStream (*this, t); + } + /** @} */ + + private: + Sink* m_sink; + Severity m_severity; + }; + + //-------------------------------------------------------------------------- + + Journal (); + explicit Journal (Sink& sink); + Journal (Journal const& other); + ~Journal (); + + /** Returns the Sink associated with this Journal. */ + Sink& sink() const; + + /** Returns a stream for this sink, with the specified severity. */ + Stream stream (Severity severity) const; + + /** Returns `true` if any message would be logged at this severity level. */ + bool active (Severity severity) const; + + /** Convenience sink streams for each severity level. */ + Stream const trace; + Stream const debug; + Stream const info; + Stream const warning; + Stream const error; + Stream const fatal; + +private: + Journal& operator= (Journal const& other); // disallowed +}; + +} + +#endif diff --git a/modules/beast_core/diagnostic/beast_LeakChecked.h b/beast/utility/LeakChecked.h similarity index 74% rename from modules/beast_core/diagnostic/beast_LeakChecked.h rename to beast/utility/LeakChecked.h index 4d84722422..296d315efb 100644 --- a/modules/beast_core/diagnostic/beast_LeakChecked.h +++ b/beast/utility/LeakChecked.h @@ -17,21 +17,32 @@ */ //============================================================================== -#ifndef BEAST_LEAKCHECKED_H_INCLUDED -#define BEAST_LEAKCHECKED_H_INCLUDED +#ifndef BEAST_UTILITY_LEAKCHECKED_H_INCLUDED +#define BEAST_UTILITY_LEAKCHECKED_H_INCLUDED -namespace Implemented -{ +#include "../Config.h" +#include "../Atomic.h" +#include "../intrusive/LockFreeStack.h" +#include "StaticObject.h" -class BEAST_API LeakCheckedBase +namespace beast { + +namespace detail { + +class LeakCheckedBase { +public: + static void checkForLeaks (); + protected: - class CounterBase : public LockFreeStack ::Node + class LeakCounterBase : public LockFreeStack ::Node { public: - CounterBase (); + LeakCounterBase (); - virtual ~CounterBase () { } + virtual ~LeakCounterBase () + { + } inline int increment () { @@ -47,24 +58,15 @@ protected: private: void checkForLeaks (); - virtual void checkPureVirtual () const = 0; - private: - friend class LeakCheckedBase; - class Singleton; + friend class LeakCheckedBase; Atomic m_count; }; -protected: static void reportDanglingPointer (char const* objectName); - -private: - friend class PerformedAtExit::ExitHook; - - static void checkForLeaks (); }; //------------------------------------------------------------------------------ @@ -99,10 +101,10 @@ protected: private: // Singleton that maintains the count of this object // - class Counter : public CounterBase + class LeakCounter : public LeakCounterBase { public: - Counter () noexcept + LeakCounter () noexcept { } @@ -127,20 +129,9 @@ private: // Retrieve the singleton for this object // - static Counter& getCounter () noexcept + static LeakCounter& getCounter () noexcept { - static Counter* volatile s_instance; - static Static::Initializer s_initializer; - - if (s_initializer.beginConstruction ()) - { - static char s_storage [sizeof (Counter)]; - s_instance = new (s_storage) Counter; - - s_initializer.endConstruction (); - } - - return *s_instance; + return StaticObject ::get(); } }; @@ -148,35 +139,42 @@ private: //------------------------------------------------------------------------------ -namespace Dummy +namespace detail { -class BEAST_API LeakCheckedBase +namespace disabled { -private: - friend class PerformedAtExit; +class LeakCheckedBase +{ public: - static void checkForLeaks () { } + static void checkForLeaks () + { + } }; template -struct LeakChecked : LeakCheckedBase +class LeakChecked : public LeakCheckedBase { +public: }; } +} + //------------------------------------------------------------------------------ -// Lift the corresponding implementation +// Lift the appropriate implementation into our namespace // #if BEAST_CHECK_MEMORY_LEAKS -using Implemented::LeakChecked; -using Implemented::LeakCheckedBase; +using detail::LeakChecked; +using detail::LeakCheckedBase; #else -using Dummy::LeakChecked; -using Dummy::LeakCheckedBase; +using detail::disabled::LeakChecked; +using detail::disabled::LeakCheckedBase; #endif +} + #endif diff --git a/beast/utility/PropertyStream.h b/beast/utility/PropertyStream.h new file mode 100644 index 0000000000..2871499718 --- /dev/null +++ b/beast/utility/PropertyStream.h @@ -0,0 +1,297 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_PROPERTYSTREAM_H_INCLUDED +#define BEAST_UTILITY_PROPERTYSTREAM_H_INCLUDED + +#include "../CStdInt.h" +#include "../Uncopyable.h" +#include "../intrusive/List.h" +#include "../threads/SharedData.h" + +#include +#include +#include + +namespace beast { + +//------------------------------------------------------------------------------ + +/** Abstract stream with RAII containers that produce a property tree. */ +class PropertyStream +{ +public: + class Map; + class Set; + class Source; + + PropertyStream (); + virtual ~PropertyStream (); + +protected: + virtual void map_begin () = 0; + virtual void map_begin (std::string const& key) = 0; + virtual void map_end () = 0; + + virtual void add (std::string const& key, std::string const& value) = 0; + + template + void lexical_add (std::string const &key, Value value) + { + std::stringstream ss; + ss << value; + add (key, ss.str()); + } + virtual void add (std::string const& key, int32 value); + virtual void add (std::string const& key, uint32 value); + virtual void add (std::string const& key, int64 value); + virtual void add (std::string const& key, uint64 value); + + virtual void array_begin () = 0; + virtual void array_begin (std::string const& key) = 0; + virtual void array_end () = 0; + + virtual void add (std::string const& value) = 0; + + template + void lexical_add (Value value) + { + std::stringstream ss; + ss << value; + add (ss.str()); + } + virtual void add ( int32 value); + virtual void add (uint32 value); + virtual void add ( int64 value); + virtual void add (uint64 value); + +private: + class Item; + class Proxy; +}; + +//------------------------------------------------------------------------------ +// +// Item +// + +class PropertyStream::Item : public List ::Node +{ +public: + explicit Item (Source* source); + Source& source() const; + Source* operator-> () const; + Source& operator* () const; +private: + Source* m_source; +}; + +//------------------------------------------------------------------------------ +// +// Proxy +// + +class PropertyStream::Proxy +{ +private: + Map const* m_map; + std::string m_key; + +public: + Proxy (Map const& map, std::string const& key); + + template + Proxy& operator= (Value value); +}; + +//------------------------------------------------------------------------------ +// +// Map +// + +class PropertyStream::Map : public Uncopyable +{ +private: + PropertyStream& m_stream; + +public: + explicit Map (PropertyStream& stream); + explicit Map (Set& parent); + Map (std::string const& key, Map& parent); + Map (std::string const& key, PropertyStream& stream); + ~Map (); + + PropertyStream& stream(); + PropertyStream const& stream() const; + + template + void add (std::string const& key, Value value) const + { + m_stream.add (key, value); + } + + template + void add (Key key, Value value) const + { + std::stringstream ss; + ss << key; + add (ss.str(), value); + } + + Proxy operator[] (std::string const& key); + + Proxy operator[] (char const* key) + { return Proxy (*this, key); } + + template + Proxy operator[] (Key key) const + { + std::stringstream ss; + ss << key; + return Proxy (*this, ss.str()); + } +}; + +//-------------------------------------------------------------------------- + +template +PropertyStream::Proxy& PropertyStream::Proxy::operator= (Value value) +{ + m_map->add (m_key, value); + return *this; +} + +//-------------------------------------------------------------------------- +// +// Set +// + +class PropertyStream::Set : public Uncopyable +{ +private: + PropertyStream& m_stream; + +public: + explicit Set (Set& set); + Set (std::string const& key, Map& map); + Set (std::string const& key, PropertyStream& stream); + ~Set (); + + PropertyStream& stream(); + PropertyStream const& stream() const; + + template + void add (Value value) const + { m_stream.add (value); } +}; + +//------------------------------------------------------------------------------ +// +// Source +// + +/** Subclasses can be called to write to a stream and have children. */ +class PropertyStream::Source : public Uncopyable +{ +private: + struct State + { + explicit State (Source* source) + : item (source) + , parent (nullptr) + { } + + Item item; + Source* parent; + List children; + }; + + typedef SharedData SharedState; + + std::string const m_name; + SharedState m_state; + + //-------------------------------------------------------------------------- + + void remove (SharedState::Access& state, + SharedState::Access& childState); + + void removeAll (SharedState::Access& state); + + void write (SharedState::Access& state, PropertyStream& stream); + +public: + explicit Source (std::string const& name); + ~Source (); + + /** Returns the name of this source. */ + std::string const& name() const; + + /** Add a child source. */ + void add (Source& source); + + /** Add a child source by pointer. + The source pointer is returned so it can be used in ctor-initializers. + */ + template + Derived* add (Derived* child) + { + add (*static_cast (child)); + return child; + } + + /** Remove a child source from this Source. */ + void remove (Source& child); + + /** Remove all child sources of this Source. */ + void removeAll (); + + /** Write only this Source to the stream. */ + void write_one (PropertyStream& stream); + + /** write this source and all its children recursively to the stream. */ + void write (PropertyStream& stream); + + /** Parse the path and write the corresponding Source and optional children. + If the source is found, it is written. If the wildcard character '*' + exists as the last character in the path, then all the children are + written recursively. + */ + void write (PropertyStream& stream, std::string const& path); + + /** Parse the dot-delimited Source path and return the result. + The first value will be a pointer to the Source object corresponding + to the given path. If no Source object exists, then the first value + will be nullptr and the second value will be undefined. + The second value is a boolean indicating whether or not the path string + specifies the wildcard character '*' as the last character. + */ + std::pair find (std::string const& path); + + //-------------------------------------------------------------------------- + + /** Subclass override. + The default version does nothing. + */ + virtual void onWrite (Map&); +}; + +} + +#endif diff --git a/beast/utility/StaticObject.h b/beast/utility/StaticObject.h new file mode 100644 index 0000000000..30ab11cb9d --- /dev/null +++ b/beast/utility/StaticObject.h @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_UTILITY_STATICOBJECT_H_INCLUDED +#define BEAST_UTILITY_STATICOBJECT_H_INCLUDED + +namespace beast { + +// Spec: N2914=09-0104 +// +// [3.6.2] Initialization of non-local objects +// +// Objects with static storage duration (3.7.1) or thread storage +// duration (3.7.2) shall be zero-initialized (8.5) before any +// other initialization takes place. +// + +namespace detail { + +extern void staticObjectWait (std::size_t n); + +} + +/** Wrapper to produce an object with static storage duration. + + The object is constructed in a thread-safe fashion when the get function + is first called. Note that the destructor for Object is never called. To + invoke the destructor, use the AtExitHook facility (with caution). + + The Tag parameter allows multiple instances of the same Object type, by + using different tags. + + Object must meet these requirements: + DefaultConstructible + + @see AtExitHook +*/ +template +class StaticObject +{ +public: + static Object& get () + { + StaticData& staticData (StaticData::get()); + + if (staticData.state.get() != initialized) + { + if (staticData.state.compareAndSetBool (initializing, uninitialized)) + { + // Initialize the object. + new (&staticData.object) Object; + staticData.state = initialized; + } + else + { + for (std::size_t n = 0; staticData.state.get() != initialized; ++n) + { + detail::staticObjectWait (n); + } + } + } + + return staticData.object; + } + +private: + enum + { + uninitialized = 0, // must be zero to function properly + initializing, + initialized + }; + + // This structure gets zero-filled at static initialization time. + // No constructors are called. + // + class StaticData : public Uncopyable + { + public: + Atomic state; + Object object; + + static StaticData& get () + { + static uint8 storage [sizeof (StaticData)]; + return *(reinterpret_cast (&storage [0])); + } + + private: + StaticData(); + ~StaticData(); + }; +}; + +} + +#endif diff --git a/beast/utility/Utility.cpp b/beast/utility/Utility.cpp new file mode 100644 index 0000000000..e2b254bfdb --- /dev/null +++ b/beast/utility/Utility.cpp @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "BeastConfig.h" + +#include "impl/Error.cpp" + +// For Journal and Debug +#include "../../modules/beast_core/beast_core.h" + +#include "impl/Debug.cpp" +#include "impl/Journal.cpp" +#include "impl/LeakChecked.cpp" +#include "impl/StaticObject.cpp" +#include "impl/PropertyStream.cpp" diff --git a/modules/beast_core/diagnostic/beast_Debug.cpp b/beast/utility/impl/Debug.cpp similarity index 86% rename from modules/beast_core/diagnostic/beast_Debug.cpp rename to beast/utility/impl/Debug.cpp index 3580b04540..d3a26e0aad 100644 --- a/modules/beast_core/diagnostic/beast_Debug.cpp +++ b/beast/utility/impl/Debug.cpp @@ -17,8 +17,9 @@ */ //============================================================================== -namespace Debug -{ +namespace beast { + +namespace Debug { void breakPoint () { @@ -296,19 +297,57 @@ String commandLineToString (const String& commandLine) //------------------------------------------------------------------------------ +// A simple unit test to determine the diagnostic settings in a build. +// class DebugTests : public UnitTest { public: - DebugTests () : UnitTest ("Debug", "beast", runManual) + static int envDebug () { + #ifdef _DEBUG + return 1; + #else + return 0; + #endif + } + + static int beastDebug () + { + #ifdef BEAST_DEBUG + return BEAST_DEBUG; + #else + return 0; + #endif + } + + static int beastForceDebug () + { + #ifdef BEAST_FORCE_DEBUG + return BEAST_FORCE_DEBUG; + #else + return 0; + #endif } void runTest () { - beginTestCase ("bassert"); + beginTestCase ("diagnostics"); + + logMessage ("operatingSystemName = '" + SystemStats::getOperatingSystemName () + "'"); + logMessage ("_DEBUG = " + String::fromNumber (envDebug ())); + logMessage ("BEAST_DEBUG = " + String::fromNumber (beastDebug ())); + logMessage ("BEAST_FORCE_DEBUG = " + String::fromNumber (beastForceDebug ())); + logMessage ("sizeof(std::size_t) = " + String::fromNumber (sizeof(std::size_t))); bassertfalse; + fail (); } + + DebugTests () : UnitTest ("Debug", "beast", runManual) + { + } }; static DebugTests debugTests; + +} diff --git a/modules/beast_core/diagnostic/beast_Error.cpp b/beast/utility/impl/Error.cpp similarity index 96% rename from modules/beast_core/diagnostic/beast_Error.cpp rename to beast/utility/impl/Error.cpp index 055d89a09a..9083413fed 100644 --- a/modules/beast_core/diagnostic/beast_Error.cpp +++ b/beast/utility/impl/Error.cpp @@ -17,6 +17,19 @@ */ //============================================================================== +#include "../Error.h" +#include "../Debug.h" + +#include + +// VFALCO TODO Localizable strings +#ifndef TRANS +#define TRANS(s) (s) +#define UNDEF_TRANS +#endif + +namespace beast { + Error::Error () : m_code (success) , m_lineNumber (0) @@ -241,3 +254,11 @@ String const Error::getReasonTextForCode (Code code) return s; } + +#ifdef UNDEF_TRANS +#undef TRANs +#undef UNDEF_TRANS +#endif + +} + diff --git a/beast/utility/impl/Journal.cpp b/beast/utility/impl/Journal.cpp new file mode 100644 index 0000000000..868e5ad64d --- /dev/null +++ b/beast/utility/impl/Journal.cpp @@ -0,0 +1,205 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../Journal.h" + +namespace beast +{ + +//------------------------------------------------------------------------------ + +// A Sink that does nothing. +class NullJournalSink : public Journal::Sink +{ +public: + void write (Journal::Severity, std::string const&) + { + } + + bool active (Journal::Severity) + { + return false; + } + + bool console () + { + return false; + } + + void set_severity (Journal::Severity) + { + } + + void set_console (bool) + { + } +}; + +//------------------------------------------------------------------------------ + +Journal::Sink& Journal::getNullSink () +{ + return *SharedSingleton ::get ( + SingletonLifetime::neverDestroyed); +} + +//------------------------------------------------------------------------------ + +Journal::ScopedStream::ScopedStream (Stream const& stream) + : m_sink (stream.sink()) + , m_severity (stream.severity()) +{ +} + +Journal::ScopedStream::ScopedStream (ScopedStream const& other) + : m_sink (other.m_sink) + , m_severity (other.m_severity) +{ +} + +Journal::ScopedStream::ScopedStream (Stream const& stream, std::ostream& manip (std::ostream&)) + : m_sink (stream.sink()) + , m_severity (stream.severity()) +{ + m_ostream << manip; +} + +Journal::ScopedStream::~ScopedStream () +{ + if (! m_ostream.str().empty()) + { + if (m_sink.active (m_severity)) + m_sink.write (m_severity, m_ostream.str()); + } +} + +std::ostream& Journal::ScopedStream::operator<< (std::ostream& manip (std::ostream&)) const +{ + return m_ostream << manip; +} + +std::ostringstream& Journal::ScopedStream::ostream () const +{ + return m_ostream; +} + +//------------------------------------------------------------------------------ + +Journal::Stream::Stream () + : m_sink (&getNullSink ()) + , m_severity (kDisabled) +{ +} + +Journal::Stream::Stream (Sink& sink, Severity severity) + : m_sink (&sink) + , m_severity (severity) +{ + bassert (severity != kDisabled); +} + +Journal::Stream::Stream (Stream const& other) + : m_sink (other.m_sink) + , m_severity (other.m_severity) +{ +} + +Journal::Sink& Journal::Stream::sink () const +{ + return *m_sink; +} + +Journal::Severity Journal::Stream::severity () const +{ + return m_severity; +} + +bool Journal::Stream::active () const +{ + return m_sink->active (m_severity); +} + +Journal::Stream& Journal::Stream::operator= (Stream const& other) +{ + m_sink = other.m_sink; + m_severity = other.m_severity; + return *this; +} + +Journal::ScopedStream Journal::Stream::operator<< (std::ostream& manip (std::ostream&)) const +{ + return ScopedStream (*this, manip); +} + +//------------------------------------------------------------------------------ + +Journal::Journal () + : m_sink (&getNullSink()) + , trace (stream (kTrace)) + , debug (stream (kDebug)) + , info (stream (kInfo)) + , warning (stream (kWarning)) + , error (stream (kError)) + , fatal (stream (kFatal)) +{ +} + +Journal::Journal (Sink& sink) + : m_sink (&sink) + , trace (stream (kTrace)) + , debug (stream (kDebug)) + , info (stream (kInfo)) + , warning (stream (kWarning)) + , error (stream (kError)) + , fatal (stream (kFatal)) +{ +} + +Journal::Journal (Journal const& other) + : m_sink (other.m_sink) + , trace (stream (kTrace)) + , debug (stream (kDebug)) + , info (stream (kInfo)) + , warning (stream (kWarning)) + , error (stream (kError)) + , fatal (stream (kFatal)) +{ +} + +Journal::~Journal () +{ +} + +Journal::Sink& Journal::sink() const +{ + return *m_sink; +} + +Journal::Stream Journal::stream (Severity severity) const +{ + return Stream (*m_sink, severity); +} + +bool Journal::active (Severity severity) const +{ + bassert (severity != kDisabled); + return m_sink->active (severity); +} + +} diff --git a/modules/beast_core/diagnostic/beast_LeakChecked.cpp b/beast/utility/impl/LeakChecked.cpp similarity index 88% rename from modules/beast_core/diagnostic/beast_LeakChecked.cpp rename to beast/utility/impl/LeakChecked.cpp index b70e41697a..2209995e68 100644 --- a/modules/beast_core/diagnostic/beast_LeakChecked.cpp +++ b/beast/utility/impl/LeakChecked.cpp @@ -17,13 +17,17 @@ */ //============================================================================== -namespace Implemented +#include "../LeakChecked.h" + +namespace beast { + +namespace detail { -class LeakCheckedBase::CounterBase::Singleton +class LeakCheckedBase::LeakCounterBase::Singleton { public: - void push_back (CounterBase* counter) + void push_back (LeakCounterBase* counter) { m_list.push_front (counter); } @@ -32,7 +36,7 @@ public: { for (;;) { - CounterBase* const counter = m_list.pop_front (); + LeakCounterBase* const counter = m_list.pop_front (); if (!counter) break; @@ -51,17 +55,17 @@ public: private: friend class LeakCheckedBase; - LockFreeStack m_list; + LockFreeStack m_list; }; //------------------------------------------------------------------------------ -LeakCheckedBase::CounterBase::CounterBase () +LeakCheckedBase::LeakCounterBase::LeakCounterBase () { Singleton::getInstance ().push_back (this); } -void LeakCheckedBase::CounterBase::checkForLeaks () +void LeakCheckedBase::LeakCounterBase::checkForLeaks () { // If there's a runtime error from this line, it means there's // an order of destruction problem between different translation units! @@ -120,7 +124,9 @@ void LeakCheckedBase::reportDanglingPointer (char const*) void LeakCheckedBase::checkForLeaks () { - CounterBase::Singleton::getInstance ().checkForLeaks (); + LeakCounterBase::Singleton::getInstance ().checkForLeaks (); +} + } } diff --git a/beast/utility/impl/PropertyStream.cpp b/beast/utility/impl/PropertyStream.cpp new file mode 100644 index 0000000000..7afab58f36 --- /dev/null +++ b/beast/utility/impl/PropertyStream.cpp @@ -0,0 +1,422 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../PropertyStream.h" + +#include + +namespace beast { + +//------------------------------------------------------------------------------ +// +// Item +// +//------------------------------------------------------------------------------ + +PropertyStream::Item::Item (Source* source) + : m_source (source) +{ +} + +PropertyStream::Source& PropertyStream::Item::source() const +{ + return *m_source; +} + +PropertyStream::Source* PropertyStream::Item::operator-> () const +{ + return &source(); +} + +PropertyStream::Source& PropertyStream::Item::operator* () const +{ + return source(); +} + +//------------------------------------------------------------------------------ +// +// Proxy +// +//------------------------------------------------------------------------------ + +PropertyStream::Proxy::Proxy ( + Map const& map, std::string const& key) + : m_map (&map) + , m_key (key) +{ +} + +//------------------------------------------------------------------------------ +// +// Map +// +//------------------------------------------------------------------------------ + +PropertyStream::Map::Map (PropertyStream& stream) + : m_stream (stream) +{ +} + +PropertyStream::Map::Map (Set& parent) + : m_stream (parent.stream()) +{ + m_stream.map_begin (); +} + +PropertyStream::Map::Map (std::string const& key, Map& map) + : m_stream (map.stream()) +{ + m_stream.map_begin (key); +} + +PropertyStream::Map::Map (std::string const& key, PropertyStream& stream) + : m_stream (stream) +{ + m_stream.map_begin (key); +} + +PropertyStream::Map::~Map () +{ + m_stream.map_end (); +} + +PropertyStream& PropertyStream::Map::stream() +{ + return m_stream; +} + +PropertyStream const& PropertyStream::Map::stream() const +{ + return m_stream; +} + +PropertyStream::Proxy PropertyStream::Map::operator[] (std::string const& key) +{ + return Proxy (*this, key); +} + +//------------------------------------------------------------------------------ +// +// Set +// +//------------------------------------------------------------------------------ + +PropertyStream::Set::Set (Set& set) + : m_stream (set.m_stream) +{ + m_stream.array_begin (); +} + +PropertyStream::Set::Set (std::string const& key, Map& map) + : m_stream (map.stream()) +{ + m_stream.array_begin (key); +} + +PropertyStream::Set::Set (std::string const& key, PropertyStream& stream) + : m_stream (stream) +{ + m_stream.array_begin (key); +} + +PropertyStream::Set::~Set () +{ + m_stream.array_end (); +} + +PropertyStream& PropertyStream::Set::stream() +{ + return m_stream; +} + +PropertyStream const& PropertyStream::Set::stream() const +{ + return m_stream; +} + +//------------------------------------------------------------------------------ +// +// Source +// +//------------------------------------------------------------------------------ + +PropertyStream::Source::Source (std::string const& name) + : m_name (name) + , m_state (this) +{ +} + +PropertyStream::Source::~Source () +{ + SharedState::Access state (m_state); + if (state->parent != nullptr) + state->parent->remove (*this); + removeAll (state); +} + +std::string const& PropertyStream::Source::name () const +{ + return m_name; +} + +void PropertyStream::Source::add (Source& source) +{ + SharedState::Access state (m_state); + SharedState::Access childState (source.m_state); + bassert (childState->parent == nullptr); + state->children.push_back (childState->item); + childState->parent = this; +} + +void PropertyStream::Source::remove (Source& child) +{ + SharedState::Access state (m_state); + SharedState::Access childState (child.m_state); + remove (state, childState); +} + +void PropertyStream::Source::removeAll () +{ + SharedState::Access state (m_state); + removeAll (state); +} + +//------------------------------------------------------------------------------ + +void PropertyStream::Source::write ( + SharedState::Access& state, PropertyStream &stream) +{ + for (List ::iterator iter (state->children.begin()); + iter != state->children.end(); ++iter) + { + Source& source (iter->source()); + Map map (source.name(), stream); + source.write (stream); + } +} + +//------------------------------------------------------------------------------ + +void PropertyStream::Source::write_one (PropertyStream& stream) +{ + Map map (m_name, stream); + //onWrite (map); +} + +void PropertyStream::Source::write (PropertyStream& stream) +{ + Map map (m_name, stream); + onWrite (map); + + SharedState::Access state (m_state); + + for (List ::iterator iter (state->children.begin()); + iter != state->children.end(); ++iter) + { + Source& source (iter->source()); + source.write (stream); + } +} + +void PropertyStream::Source::write (PropertyStream& stream, std::string const& path) +{ + std::pair result (find (path)); + + if (result.first == nullptr) + return; + + if (result.second) + result.first->write (stream); + else + result.first->write_one (stream); +} + +std::pair PropertyStream::Source::find (std::string const& path) +{ + struct Parser + { + Parser (std::string const& path) + : m_first (path.begin()) + , m_last (path.end()) + { + } + + std::string next () + { + std::string::const_iterator pos ( + std::find (m_first, m_last, '.')); + std::string const s (m_first, pos); + if (pos != m_last) + m_first = pos + 1; + else + m_first = pos; + return s; + } + + std::string::const_iterator m_first; + std::string::const_iterator m_last; + }; + + if (path.empty ()) + return std::make_pair (this, false); + + Parser p (path); + Source* source (this); + if (p.next() != this->m_name) + return std::make_pair (nullptr, false); + + for (;;) + { + std::string const s (p.next()); + + if (s.empty()) + return std::make_pair (source, false); + + if (s == "*") + return std::make_pair (source, true); + + SharedState::Access state (source->m_state); + for (List ::iterator iter (state->children.begin());;) + { + if (iter->source().m_name == s) + { + source = &iter->source(); + break; + } + + if (++iter == state->children.end()) + return std::make_pair (nullptr, false); + } + } +} + +void PropertyStream::Source::onWrite (Map&) +{ +} + +//------------------------------------------------------------------------------ + +void PropertyStream::Source::remove ( + SharedState::Access& state, SharedState::Access& childState) +{ + bassert (childState->parent == this); + state->children.erase ( + state->children.iterator_to ( + childState->item)); + childState->parent = nullptr; +} + +void PropertyStream::Source::removeAll (SharedState::Access& state) +{ + for (List ::iterator iter (state->children.begin()); + iter != state->children.end();) + { + SharedState::Access childState ((*iter)->m_state); + remove (state, childState); + } +} + +//------------------------------------------------------------------------------ +// +// PropertyStream +// +//------------------------------------------------------------------------------ + +PropertyStream::PropertyStream () +{ +} + +PropertyStream::~PropertyStream () +{ +} + +void PropertyStream::add (std::string const& key, int32 value) +{ + lexical_add (key, value); +} + +void PropertyStream::add (std::string const& key, uint32 value) +{ + lexical_add (key, value); +} + +void PropertyStream::add (std::string const& key, int64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (key, int32(value)); + } + else + { + lexical_add(key, value); + } +} + +void PropertyStream::add (std::string const& key, uint64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (key, uint32(value)); + } + else + { + lexical_add (key, value); + } +} + +void PropertyStream::add (int32 value) +{ + lexical_add (value); +} + +void PropertyStream::add (uint32 value) +{ + lexical_add (value); +} + +void PropertyStream::add (int64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (int32(value)); + } + else + { + lexical_add (value); + } +} + +void PropertyStream::add (uint64 value) +{ + if (value <= std::numeric_limits ::max() && + value >= std::numeric_limits ::min()) + { + add (uint32(value)); + } + else + { + lexical_add (value); + } +} + + +} diff --git a/beast/utility/impl/StaticObject.cpp b/beast/utility/impl/StaticObject.cpp new file mode 100644 index 0000000000..5b44bb0dd7 --- /dev/null +++ b/beast/utility/impl/StaticObject.cpp @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include "../StaticObject.h" +#include "../../threads/Thread.h" + +namespace beast { + +namespace detail +{ + +// This is here so we don't need the Thread class declaration +void staticObjectWait (std::size_t n) +{ + // Wait for initialization + Thread::yield (); + if (n > 10) + Thread::sleep (1); + else if (n > 100) + Thread::sleep (10); +} + +} + +} diff --git a/config/BeastConfig.h b/config/BeastConfig.h new file mode 100644 index 0000000000..ee6a48375a --- /dev/null +++ b/config/BeastConfig.h @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_BEASTCONFIG_H_INCLUDED +#define BEAST_BEASTCONFIG_H_INCLUDED + +/** Configuration file for Beast. + This sets various configurable options for Beast. In order to compile you + must place a copy of this file in a location where your build environment + can find it, and then customize its contents to suit your needs. + @file BeastConfig.h +*/ + +//------------------------------------------------------------------------------ +// +// Diagnostics +// +//------------------------------------------------------------------------------ + +/** Config: BEAST_FORCE_DEBUG + Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project + settings, but if you define this value, you can override this to force it + to be true or false. +*/ +#ifndef BEAST_FORCE_DEBUG +//#define BEAST_FORCE_DEBUG 1 +#endif + +/** Config: BEAST_LOG_ASSERTIONS + If this flag is enabled, the the bassert and bassertfalse macros will always + use Logger::writeToLog() to write a message when an assertion happens. + Enabling it will also leave this turned on in release builds. When it's + disabled, however, the bassert and bassertfalse macros will not be compiled + in a release build. + @see bassert, bassertfalse, Logger +*/ +#ifndef BEAST_LOG_ASSERTIONS +//#define BEAST_LOG_ASSERTIONS 1 +#endif + +/** Config: BEAST_CHECK_MEMORY_LEAKS + Enables a memory-leak check for certain objects when the app terminates. + See the LeakChecked class for more details about enabling leak checking for + specific classes. +*/ +#ifndef BEAST_CHECK_MEMORY_LEAKS +//#define BEAST_CHECK_MEMORY_LEAKS 0 +#endif + +/** Config: BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES + Setting this option makes Socket-derived classes generate compile errors + if they forget any of the virtual overrides As some Socket-derived classes + intentionally omit member functions that are not applicable, this macro + should only be enabled temporarily when writing your own Socket-derived + class, to make sure that the function signatures match as expected. +*/ +#ifndef BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES +//#define BEAST_COMPILER_CHECKS_SOCKET_OVERRIDES 1 +#endif + +//------------------------------------------------------------------------------ +// +// Libraries +// +//------------------------------------------------------------------------------ + +/** Config: BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES + In a Visual C++ build, this can be used to stop the required system libs + being automatically added to the link stage. +*/ +#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES +//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1 +#endif + +/** Config: BEAST_INCLUDE_ZLIB_CODE + This can be used to disable Beast's embedded 3rd-party zlib code. + You might need to tweak this if you're linking to an external zlib library + in your app, but for normal apps, this option should be left alone. + + If you disable this, you might also want to set a value for + BEAST_ZLIB_INCLUDE_PATH, to specify the path where your zlib headers live. +*/ +#ifndef BEAST_INCLUDE_ZLIB_CODE +//#define BEAST_INCLUDE_ZLIB_CODE 1 +#endif + +/** Config: BEAST_ZLIB_INCLUDE_PATH + This is included when BEAST_INCLUDE_ZLIB_CODE is set to zero. +*/ +#ifndef BEAST_ZLIB_INCLUDE_PATH +#define BEAST_ZLIB_INCLUDE_PATH +#endif + +/** Config: BEAST_FUNCTIONAL_USES_### + source configuration. + Set one of these to manually force a particular implementation of bind(). + If nothing is chosen then beast will use whatever is appropriate for your + environment based on what is available. + If you override these, set ONE to 1 and the rest to 0 +*/ +#ifndef BEAST_FUNCTIONAL_USES_STD +//#define BEAST_FUNCTIONAL_USES_STD 0 +#endif +#ifndef BEAST_FUNCTIONAL_USES_TR1 +//#define BEAST_FUNCTIONAL_USES_TR1 0 +#endif +#ifndef BEAST_FUNCTIONAL_USES_BOOST +//#define BEAST_FUNCTIONAL_USES_BOOST 0 +#endif + +//------------------------------------------------------------------------------ +// +// Boost +// +//------------------------------------------------------------------------------ + +/** Config: BEAST_USE_BOOST_FEATURES + This activates boost specific features and improvements. If this is + turned on, the include paths for your build environment must be set + correctly to find the boost headers. +*/ +#ifndef BEAST_USE_BOOST_FEATURES +//#define BEAST_USE_BOOST_FEATURES 1 +#endif + +//------------------------------------------------------------------------------ + +#endif diff --git a/modules/beast_asio/async/AbstractHandler.h b/modules/beast_asio/async/AbstractHandler.h new file mode 100644 index 0000000000..f999b9e5d4 --- /dev/null +++ b/modules/beast_asio/async/AbstractHandler.h @@ -0,0 +1,712 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_ASIO_ABSTRACTHANDLER_H_INCLUDED +#define BEAST_ASIO_ABSTRACTHANDLER_H_INCLUDED + +namespace beast { + +namespace detail { + +struct AbstractHandlerCallBase : SharedObject +{ + //typedef SharedFunction > invoked_type; + + typedef SharedFunction invoked_type; + + virtual void* allocate (std::size_t size) = 0; + virtual void deallocate (void* p, std::size_t size) = 0; + virtual bool is_continuation () = 0; + virtual void invoke (invoked_type& invoked) = 0; + + template + void invoke (BEAST_MOVE_ARG(Function) f) + { + invoked_type invoked (BEAST_MOVE_CAST(Function)(f) + //, AbstractHandlerAllocator(this) + ); + invoke (invoked); + } +}; + +/* +template +struct AbstractHandlerAllocator +{ + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef T const* const_pointer; + typedef T const& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + AbstractHandlerAllocator (AbstractHandler* handler) noexcept + : m_ptr (handler) + { + } + + AbstractHandlerAllocator (SharedPtr const& ptr) noexcept + : m_ptr (ptr) + { + } + + template + AbstractHandlerAllocator (AbstractHandlerAllocator const& other) + : m_ptr (other.m_ptr) + { + } + + template + struct rebind + { + typedef AbstractHandlerAllocator other; + }; + + pointer address (reference x) const + { + return &x; + } + + const_pointer address (const_reference x) const + { + return &x; + } + + pointer allocate (size_type n) const + { + size_type const bytes = n * sizeof (value_type); + return static_cast (m_ptr->allocate (bytes)); + } + + void deallocate (pointer p, size_type n) const + { + size_type const bytes = n * sizeof (value_type); + m_ptr->deallocate (p, bytes); + } + + size_type max_size () const noexcept + { + return std::numeric_limits ::max () / sizeof (value_type); + } + + void construct (pointer p, const_reference val) const + { + new ((void *)p) value_type (val); + } + + void destroy (pointer p) const + { + p->~value_type (); + } + +private: + template + friend struct AbstractHandlerAllocator; + friend class AbstractHandler; + + SharedPtr m_ptr; +}; +*/ + +} + +/** A reference counted, abstract completion handler. */ +template > +class AbstractHandler; + +//------------------------------------------------------------------------------ + +// arity 0 +template +struct AbstractHandler +{ + typedef R result_type; + struct Call : detail::AbstractHandlerCallBase + { virtual R operator() () = 0; }; + + template + struct CallType : public Call + { + typedef typename A:: template rebind >::other Allocator; + CallType (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a) + { } + R operator()() + { return (m_h)(); } + R operator()() const + { return (m_h)(); } + void* allocate (std::size_t size) + { return boost_asio_handler_alloc_helpers::allocate(size, m_h); } + void deallocate (void* pointer, std::size_t size) + { boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); } + bool is_continuation () +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + { return boost_asio_handler_cont_helpers::is_continuation(m_h); } +#else + { return false; } +#endif + void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked) + { boost_asio_handler_invoke_helpers::invoke < + typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); } + private: + H m_h; + Allocator m_alloc; + }; + + template + AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_call (new ( + typename A:: template rebind >::other (a) + .allocate (1)) CallType (BEAST_MOVE_CAST(H)(h), a)) + { } + R operator() () + { return (*m_call)(); } + R operator() () const + { return (*m_call)(); } + void* allocate (std::size_t size) const { return m_call->allocate(size); } + void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); } + bool is_continuation () const { return m_call->is_continuation(); } + template + void invoke (Function& function) const + { + m_call->invoke(function); + } + template + void invoke (Function const& function) const + { + m_call->invoke(function); + } + +private: + SharedPtr m_call; +}; + +template +void* asio_handler_allocate (std::size_t size, + AbstractHandler * handler) +{ + return handler->allocate (size); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + AbstractHandler * handler) +{ + handler->deallocate (pointer, size); +} + +template +bool asio_handler_is_continuation( + AbstractHandler * handler) +{ + return handler->is_continuation(); +} + +template +void asio_handler_invoke (BEAST_MOVE_ARG(Function) function, + AbstractHandler * handler) +{ + handler->invoke (BEAST_MOVE_CAST(Function)(function)); +} + +//------------------------------------------------------------------------------ + +// arity 1 +template +struct AbstractHandler +{ + typedef R result_type; + struct Call : detail::AbstractHandlerCallBase + { virtual R operator() (P1) = 0; }; + + template + struct CallType : public Call + { + typedef typename A:: template rebind >::other Allocator; + CallType (H h, A a = A ()) + : m_h (h) + , m_alloc (a) + { + } + + R operator()(P1 p1) + { return (m_h)(p1); } + R operator()(P1 p1) const + { return (m_h)(p1); } + void* allocate (std::size_t size) + { return boost_asio_handler_alloc_helpers::allocate(size, m_h); } + void deallocate (void* pointer, std::size_t size) + { boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); } + bool is_continuation () +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + { return boost_asio_handler_cont_helpers::is_continuation(m_h); } +#else + { return false; } +#endif + void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked) + { boost_asio_handler_invoke_helpers::invoke < + typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); } + private: + H m_h; + Allocator m_alloc; + }; + + template + AbstractHandler (H h, A a = A ()) + : m_call (new ( + typename A:: template rebind >::other (a) + .allocate (1)) CallType (h, a)) + { + } + + R operator() (P1 p1) + { return (*m_call)(p1); } + R operator() (P1 p1) const + { return (*m_call)(p1); } + void* allocate (std::size_t size) const { return m_call->allocate(size); } + void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); } + bool is_continuation () const { return m_call->is_continuation(); } + template + void invoke (Function& function) const + { + m_call->invoke(function); + } + template + void invoke (Function const& function) const + { + m_call->invoke(function); + } + +private: + SharedPtr m_call; +}; + +template +void* asio_handler_allocate (std::size_t size, + AbstractHandler * handler) +{ + return handler->allocate (size); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + AbstractHandler * handler) +{ + handler->deallocate (pointer, size); +} + +template +bool asio_handler_is_continuation( + AbstractHandler * handler) +{ + return handler->is_continuation(); +} + +template +void asio_handler_invoke (BEAST_MOVE_ARG(Function) function, + AbstractHandler * handler) +{ + handler->invoke (BEAST_MOVE_CAST(Function)(function)); +} + +//------------------------------------------------------------------------------ + +// arity 2 +template +struct AbstractHandler +{ + typedef R result_type; + struct Call : detail::AbstractHandlerCallBase + { virtual R operator() (P1, P2) = 0; }; + + template + struct CallType : public Call + { + typedef typename A:: template rebind >::other Allocator; + CallType (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a) + { } + R operator()(P1 p1, P2 p2) + { return (m_h)(p1, p2); } + R operator()(P1 p1, P2 p2) const + { return (m_h)(p1, p2); } + void* allocate (std::size_t size) + { return boost_asio_handler_alloc_helpers::allocate(size, m_h); } + void deallocate (void* pointer, std::size_t size) + { boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); } + bool is_continuation () +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + { return boost_asio_handler_cont_helpers::is_continuation(m_h); } +#else + { return false; } +#endif + void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked) + { boost_asio_handler_invoke_helpers::invoke < + typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); } + private: + H m_h; + Allocator m_alloc; + }; + + template + AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_call (new ( + typename A:: template rebind >::other (a) + .allocate (1)) CallType (BEAST_MOVE_CAST(H)(h), a)) + { } + R operator() (P1 p1, P2 p2) + { return (*m_call)(p1, p2); } + R operator() (P1 p1, P2 p2) const + { return (*m_call)(p1, p2); } + void* allocate (std::size_t size) const { return m_call->allocate(size); } + void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); } + bool is_continuation () const { return m_call->is_continuation(); } + template + void invoke (Function& function) const + { + m_call->invoke(function); + } + template + void invoke (Function const& function) const + { + m_call->invoke(function); + } + +private: + SharedPtr m_call; +}; + +template +void* asio_handler_allocate (std::size_t size, + AbstractHandler * handler) +{ + return handler->allocate (size); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + AbstractHandler * handler) +{ + handler->deallocate (pointer, size); +} + +template +bool asio_handler_is_continuation( + AbstractHandler * handler) +{ + return handler->is_continuation(); +} + +template +void asio_handler_invoke (BEAST_MOVE_ARG(Function) function, + AbstractHandler * handler) +{ + handler->invoke (BEAST_MOVE_CAST(Function)(function)); +} + +//------------------------------------------------------------------------------ + +// arity 3 +template +struct AbstractHandler +{ + typedef R result_type; + struct Call : detail::AbstractHandlerCallBase + { virtual R operator() (P1, P2, P3) = 0; }; + + template + struct CallType : public Call + { + typedef typename A:: template rebind >::other Allocator; + CallType (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a) + { } + R operator()(P1 p1, P2 p2, P3 p3) + { return (m_h)(p1, p2, p3); } + R operator()(P1 p1, P2 p2, P3 p3) const + { return (m_h)(p1, p2, p3); } + void* allocate (std::size_t size) + { return boost_asio_handler_alloc_helpers::allocate(size, m_h); } + void deallocate (void* pointer, std::size_t size) + { boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); } + bool is_continuation () +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + { return boost_asio_handler_cont_helpers::is_continuation(m_h); } +#else + { return false; } +#endif + void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked) + { boost_asio_handler_invoke_helpers::invoke < + typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); } + private: + H m_h; + Allocator m_alloc; + }; + + template + AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_call (new ( + typename A:: template rebind >::other (a) + .allocate (1)) CallType (BEAST_MOVE_CAST(H)(h), a)) + { } + R operator() (P1 p1, P2 p2, P3 p3) + { return (*m_call)(p1, p2, p3); } + R operator() (P1 p1, P2 p2, P3 p3) const + { return (*m_call)(p1, p2, p3); } + void* allocate (std::size_t size) const { return m_call->allocate(size); } + void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); } + bool is_continuation () const { return m_call->is_continuation(); } + template + void invoke (Function& function) const + { + m_call->invoke(function); + } + template + void invoke (Function const& function) const + { + m_call->invoke(function); + } + +private: + SharedPtr m_call; +}; + +template +void* asio_handler_allocate (std::size_t size, + AbstractHandler * handler) +{ + return handler->allocate (size); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + AbstractHandler * handler) +{ + handler->deallocate (pointer, size); +} + +template +bool asio_handler_is_continuation( + AbstractHandler * handler) +{ + return handler->is_continuation(); +} + +template +void asio_handler_invoke (BEAST_MOVE_ARG(Function) function, + AbstractHandler * handler) +{ + handler->invoke (BEAST_MOVE_CAST(Function)(function)); +} + +//------------------------------------------------------------------------------ + +// arity 4 +template +struct AbstractHandler +{ + typedef R result_type; + struct Call : detail::AbstractHandlerCallBase + { virtual R operator() (P1, P2, P3, P4) = 0; }; + + template + struct CallType : public Call + { + typedef typename A:: template rebind >::other Allocator; + CallType (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a) + { } + R operator()(P1 p1, P2 p2, P3 p3, P4 p4) + { return (m_h)(p1, p2, p3, p4); } + R operator()(P1 p1, P2 p2, P3 p3, P4 p4) const + { return (m_h)(p1, p2, p3, p4); } + void* allocate (std::size_t size) + { return boost_asio_handler_alloc_helpers::allocate(size, m_h); } + void deallocate (void* pointer, std::size_t size) + { boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); } + bool is_continuation () +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + { return boost_asio_handler_cont_helpers::is_continuation(m_h); } +#else + { return false; } +#endif + void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked) + { boost_asio_handler_invoke_helpers::invoke < + typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); } + private: + H m_h; + Allocator m_alloc; + }; + + template + AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_call (new ( + typename A:: template rebind >::other (a) + .allocate (1)) CallType (BEAST_MOVE_CAST(H)(h), a)) + { } + R operator() (P1 p1, P2 p2, P3 p3, P4 p4) + { return (*m_call)(p1, p2, p3, p4); } + R operator() (P1 p1, P2 p2, P3 p3, P4 p4) const + { return (*m_call)(p1, p2, p3, p4); } + void* allocate (std::size_t size) const { return m_call->allocate(size); } + void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); } + bool is_continuation () const { return m_call->is_continuation(); } + template + void invoke (Function& function) const + { + m_call->invoke(function); + } + template + void invoke (Function const& function) const + { + m_call->invoke(function); + } + +private: + SharedPtr m_call; +}; + +template +void* asio_handler_allocate (std::size_t size, + AbstractHandler * handler) +{ + return handler->allocate (size); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + AbstractHandler * handler) +{ + handler->deallocate (pointer, size); +} + +template +bool asio_handler_is_continuation( + AbstractHandler * handler) +{ + return handler->is_continuation(); +} + +template +void asio_handler_invoke (BEAST_MOVE_ARG(Function) function, + AbstractHandler * handler) +{ + handler->invoke (BEAST_MOVE_CAST(Function)(function)); +} + +//------------------------------------------------------------------------------ + +// arity 5 +template +struct AbstractHandler +{ + typedef R result_type; + struct Call : detail::AbstractHandlerCallBase + { virtual R operator() (P1, P2, P3, P4, P5) = 0; }; + + template + struct CallType : public Call + { + typedef typename A:: template rebind >::other Allocator; + CallType (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_h (BEAST_MOVE_CAST(H)(h)), m_alloc (a) + { } + R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + { return (m_h)(p1, p2, p3, p4, p5); } + R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const + { return (m_h)(p1, p2, p3, p4, p5); } + void* allocate (std::size_t size) + { return boost_asio_handler_alloc_helpers::allocate(size, m_h); } + void deallocate (void* pointer, std::size_t size) + { boost_asio_handler_alloc_helpers::deallocate( pointer, size, m_h); } + bool is_continuation () +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + { return boost_asio_handler_cont_helpers::is_continuation(m_h); } +#else + { return false; } +#endif + void invoke (typename detail::AbstractHandlerCallBase::invoked_type& invoked) + { boost_asio_handler_invoke_helpers::invoke < + typename detail::AbstractHandlerCallBase::invoked_type, H> (invoked, m_h); } + private: + H m_h; + Allocator m_alloc; + }; + + template + AbstractHandler (BEAST_MOVE_ARG(H) h, A a = A ()) + : m_call (new ( + typename A:: template rebind >::other (a) + .allocate (1)) CallType (BEAST_MOVE_CAST(H)(h), a)) + { } + R operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + { return (*m_call)(p1, p2, p3, p4, p5); } + R operator() (P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const + { return (*m_call)(p1, p2, p3, p4, p5); } + void* allocate (std::size_t size) const { return m_call->allocate(size); } + void deallocate (void* pointer, std::size_t size) const { m_call->deallocate(pointer,size); } + bool is_continuation () const { return m_call->is_continuation(); } + template + void invoke (Function& function) const + { + m_call->invoke(function); + } + template + void invoke (Function const& function) const + { + m_call->invoke(function); + } + +private: + SharedPtr m_call; +}; + +template +void* asio_handler_allocate (std::size_t size, + AbstractHandler * handler) +{ + return handler->allocate (size); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + AbstractHandler * handler) +{ + handler->deallocate (pointer, size); +} + +template +bool asio_handler_is_continuation( + AbstractHandler * handler) +{ + return handler->is_continuation(); +} + +template +void asio_handler_invoke (BEAST_MOVE_ARG(Function) function, + AbstractHandler * handler) +{ + handler->invoke (BEAST_MOVE_CAST(Function)(function)); +} + +} + +#endif diff --git a/modules/beast_asio/async/AsyncObject.h b/modules/beast_asio/async/AsyncObject.h new file mode 100644 index 0000000000..12606ffaf5 --- /dev/null +++ b/modules/beast_asio/async/AsyncObject.h @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_ASIO_ASYNCOBJECT_H_INCLUDED +#define BEAST_ASIO_ASYNCOBJECT_H_INCLUDED + +/** Mix-in to track when all pending I/O is complete. + Derived classes must be callable with this signature: + void asyncHandlersComplete() +*/ +template +class AsyncObject +{ +public: + ~AsyncObject () + { + // Destroying the object with I/O pending? Not a clean exit! + bassert (m_pending.get() == 0); + } + + /** RAII container that maintains the count of pending I/O. + Bind this into the argument list of every handler passed + to an initiating function. + */ + class CompletionCounter + { + public: + explicit CompletionCounter (Derived* owner) + : m_owner (owner) + { + ++m_owner->m_pending; + } + + CompletionCounter (CompletionCounter const& other) + : m_owner (other.m_owner) + { + ++m_owner->m_pending; + } + + ~CompletionCounter () + { + if (--m_owner->m_pending == 0) + m_owner->asyncHandlersComplete (); + } + + private: + CompletionCounter& operator= (CompletionCounter const&); + Derived* m_owner; + }; + +private: + // The number of handlers pending. + Atomic m_pending; +}; + +#endif diff --git a/modules/beast_asio/async/ComposedAsyncOperation.h b/modules/beast_asio/async/ComposedAsyncOperation.h index 54fffe055f..a5884ccb16 100644 --- a/modules/beast_asio/async/ComposedAsyncOperation.h +++ b/modules/beast_asio/async/ComposedAsyncOperation.h @@ -87,7 +87,7 @@ protected: #endif } - void destroy () + void destroy () const { delete this; } diff --git a/modules/beast_asio/async/SharedHandler.h b/modules/beast_asio/async/SharedHandler.h index cd6543c9f0..9a1c58ed18 100644 --- a/modules/beast_asio/async/SharedHandler.h +++ b/modules/beast_asio/async/SharedHandler.h @@ -45,11 +45,9 @@ class SharedHandler : public SharedObject { protected: typedef boost::system::error_code error_code; -#if 0 - typedef boost::function invoked_type; -#else - typedef SharedFunction > invoked_type; -#endif + + typedef SharedFunction > invoked_type; SharedHandler () noexcept { } @@ -65,9 +63,6 @@ public: template void invoke (BOOST_ASIO_MOVE_ARG(Function) f) -#if 0 - ; -#else { // The allocator will hold a reference to the SharedHandler // so that we can safely destroy the function object. @@ -75,7 +70,6 @@ public: SharedHandlerAllocator (this)); invoke (invoked); } -#endif virtual void invoke (invoked_type& invoked) = 0; virtual void* allocate (std::size_t size) = 0; diff --git a/modules/beast_asio/async/SharedHandlerAllocator.h b/modules/beast_asio/async/SharedHandlerAllocator.h index 86d894e951..41606f4562 100644 --- a/modules/beast_asio/async/SharedHandlerAllocator.h +++ b/modules/beast_asio/async/SharedHandlerAllocator.h @@ -94,7 +94,7 @@ struct SharedHandlerAllocator void construct (pointer p, const_reference val) const { - ::new ((void *)p) value_type (val); + new ((void *)p) value_type (val); } void destroy (pointer p) const diff --git a/modules/beast_asio/async/SharedHandlerPtr.h b/modules/beast_asio/async/SharedHandlerPtr.h index d864ca8cc9..b2ef86e441 100644 --- a/modules/beast_asio/async/SharedHandlerPtr.h +++ b/modules/beast_asio/async/SharedHandlerPtr.h @@ -43,7 +43,7 @@ public: @see isNull, isNotNull */ - inline SharedHandlerPtr () noexcept + inline SharedHandlerPtr () { } @@ -55,15 +55,14 @@ public: { } - /** Construct a reference from an existing container. - */ - inline SharedHandlerPtr (SharedHandlerPtr const& other) noexcept + /** Construct a reference from an existing container. */ + inline SharedHandlerPtr (SharedHandlerPtr const& other) : m_ptr (other.m_ptr) { } /** Assign a reference from an existing container. */ - inline SharedHandlerPtr& operator= (SharedHandlerPtr const& other) noexcept + inline SharedHandlerPtr& operator= (SharedHandlerPtr const& other) { m_ptr = other.m_ptr; return *this; @@ -73,7 +72,7 @@ public: /** Move-construct a reference from an existing container. The other container is set to a null handler. */ - inline SharedHandlerPtr (SharedHandlerPtr&& other) noexcept + inline SharedHandlerPtr (SharedHandlerPtr&& other) : m_ptr (other.m_ptr) { other.m_ptr = nullptr; @@ -82,7 +81,7 @@ public: /** Move-assign a reference from an existing container. The other container is set to a null handler. */ - inline SharedHandlerPtr& operator= (SharedHandlerPtr&& other) noexcept + inline SharedHandlerPtr& operator= (SharedHandlerPtr&& other) { m_ptr = other.m_ptr; other.m_ptr = nullptr; @@ -91,13 +90,13 @@ public: #endif /** Returns true if the handler is a null handler. */ - inline bool isNull () const noexcept + inline bool isNull () const { return m_ptr == nullptr; } /** Returns true if the handler is not a null handler. */ - inline bool isNotNull () const noexcept + inline bool isNotNull () const { return m_ptr != nullptr; } @@ -105,7 +104,7 @@ public: /** Dereference the container. This returns a reference to the underlying SharedHandler object. */ - inline SharedHandler& operator* () const noexcept + inline SharedHandler& operator* () const { return *m_ptr; } @@ -113,7 +112,7 @@ public: /** SharedHandler member access. This lets you call functions directly on the SharedHandler. */ - inline SharedHandler* operator-> () const noexcept + inline SharedHandler* operator-> () const { return m_ptr.get (); } @@ -132,7 +131,7 @@ public: @endcode */ - inline SharedHandler* get () const noexcept + inline SharedHandler* get () const { return m_ptr.get (); } @@ -144,7 +143,7 @@ public: { (*m_ptr)(); } - + /** Invoke the SharedHandler with signature void(error_code) Normally this is called by a dispatcher, you shouldn't call it directly. */ @@ -180,7 +179,7 @@ private: // template -inline void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr* ptr) +void asio_handler_invoke (BOOST_ASIO_MOVE_ARG(Function) f, SharedHandlerPtr* ptr) { boost_asio_handler_invoke_helpers:: invoke diff --git a/modules/beast_asio/async/SharedHandlerType.h b/modules/beast_asio/async/SharedHandlerType.h index 40de9f3262..7ff937962c 100644 --- a/modules/beast_asio/async/SharedHandlerType.h +++ b/modules/beast_asio/async/SharedHandlerType.h @@ -21,7 +21,6 @@ #define BEAST_ASIO_ASYNC_SHAREDHANDLERTYPE_H_INCLUDED /** An instance of SharedHandler that wraps an existing Handler. - The wrapped handler will meet all the execution guarantees of the original Handler object. */ @@ -85,31 +84,21 @@ protected: // the size from the original allocation, which we saved at // the time of construction. // - void destroy () + void destroy () const { Handler local (BOOST_ASIO_MOVE_CAST(Handler)(m_handler)); std::size_t const size (m_size); - SharedHandler* const shared (static_cast (this)); + SharedHandler* const shared ( + const_cast ( + static_cast (this))); shared->~SharedHandler (); boost_asio_handler_alloc_helpers:: deallocate (shared, size, local); } - // If these somehow get called, bad things will happen - // - void* operator new (std::size_t) - { - return pure_virtual_called (__FILE__, __LINE__); - } - - void operator delete (void*) - { - return pure_virtual_called (__FILE__, __LINE__); - } - protected: std::size_t const m_size; - Handler m_handler; + Handler mutable m_handler; }; //-------------------------------------------------------------------------- @@ -216,7 +205,7 @@ Container * newSharedHandlerContainer (BOOST_ASIO_MOVE_ARG(Handler) han Handler local (BOOST_ASIO_MOVE_CAST(Handler)(handler)); void* const p (boost_asio_handler_alloc_helpers:: allocate (size, local)); - return ::new (p) ContainerType (size, BOOST_ASIO_MOVE_CAST(Handler)(local)); + return new (p) ContainerType (size, BOOST_ASIO_MOVE_CAST(Handler)(local)); } #endif diff --git a/modules/beast_asio/async/WrapHandler.h b/modules/beast_asio/async/WrapHandler.h new file mode 100644 index 0000000000..7134d2bc79 --- /dev/null +++ b/modules/beast_asio/async/WrapHandler.h @@ -0,0 +1,209 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_ASIO_WRAPHANDLER_H_INCLUDED +#define BEAST_ASIO_WRAPHANDLER_H_INCLUDED + +namespace beast { +namespace detail { + +// Wrapper returned by wrapHandler, calls the Handler in the given Context +// +template +class WrappedHandler +{ +public: + typedef void result_type; // for result_of + + WrappedHandler (Handler& handler, Context const& context) + : m_handler (handler) + , m_context (context) + { + } + + WrappedHandler (Handler const& handler, Context const& context) + : m_handler (handler) + , m_context (context) + { + } + +#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS + WrappedHandler (WrappedHandler const& other) + : m_handler (other.m_handler) + , m_context (other.m_context) + { + } + + WrappedHandler (BEAST_MOVE_ARG(WrappedHandler) other) + : m_handler (BEAST_MOVE_CAST(Handler)(other.m_handler)) + , m_context (BEAST_MOVE_CAST(Context)(other.m_context)) + { + } +#endif + + Handler& handler() + { return m_handler; } + + Handler const& handler() const + { return m_handler; } + + Context& context() + { return m_context; } + + Context const& context() const + { return m_context; } + + void operator() () + { m_handler(); } + + void operator() () const + { m_handler(); } + + template + void operator() (P1 const& p1) + { m_handler(p1); } + + template + void operator() (P1 const& p1) const + { m_handler(p1); } + + template + void operator() (P1 const& p1, P2 const& p2) + { m_handler(p1, p2); } + + template + void operator() (P1 const& p1, P2 const& p2) const + { m_handler(p1, p2); } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3) + { m_handler(p1, p2, p3); } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3) const + { m_handler(p1, p2, p3); } + + template + void operator() + (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) + { m_handler(p1, p2, p3, p4); } + + template + void operator() + (P1 const& p1, P2 const& p2, P3 const& p3, P4 const& p4) const + { m_handler(p1, p2, p3, p4); } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5) + { m_handler(p1, p2, p3, p4, p5); } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5) const + { m_handler(p1, p2, p3, p4, p5); } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5, P6 const& p6) + { m_handler(p1, p2, p3, p4, p5, p6); } + + template + void operator() (P1 const& p1, P2 const& p2, P3 const& p3, + P4 const& p4, P5 const& p5, P6 const& p6) const + { m_handler(p1, p2, p3, p4, p5, p6); } + +private: + Handler m_handler; + Context m_context; +}; + +//------------------------------------------------------------------------------ + +template +void* asio_handler_allocate (std::size_t size, + WrappedHandler * this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->context()); +} + +template +void asio_handler_deallocate (void* pointer, std::size_t size, + WrappedHandler * this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->context()); +} + +template +bool asio_handler_is_continuation( + WrappedHandler * this_handler) +{ +#if BEAST_ASIO_HAS_CONTINUATION_HOOKS + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler()); +#else + return false; +#endif +} + +template +void asio_handler_invoke (Function& function, + WrappedHandler * handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, handler->context()); +} + +template +void asio_handler_invoke (Function const& function, + WrappedHandler * handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, handler->context()); +} + +} + +//------------------------------------------------------------------------------ + +/** Returns a handler that calls Handler using Context hooks. + This is useful when implementing composed asynchronous operations that + need to call their own intermediate handlers before issuing the final + completion to the original handler. +*/ +template +detail::WrappedHandler + wrapHandler ( + BEAST_MOVE_ARG(Handler) handler, + BEAST_MOVE_ARG(Context) context) +{ + return detail::WrappedHandler ( + BEAST_MOVE_CAST(Handler)(handler), + BEAST_MOVE_CAST(Context)(context)); +} + +} + +#endif diff --git a/modules/beast_asio/basics/BuffersType.h b/modules/beast_asio/basics/BuffersType.h index 770c1b47ab..a14890e1b6 100644 --- a/modules/beast_asio/basics/BuffersType.h +++ b/modules/beast_asio/basics/BuffersType.h @@ -121,11 +121,9 @@ private: //------------------------------------------------------------------------------ /** A single linear read-only buffer. */ -//typedef BufferType ConstBuffer; typedef boost::asio::const_buffer ConstBuffer; /** A single linear writable buffer. */ -//typedef BufferType MutableBuffer; typedef boost::asio::mutable_buffer MutableBuffer; /** Meets the requirements of ConstBufferSequence */ diff --git a/modules/beast_asio/basics/SharedArg.h b/modules/beast_asio/basics/SharedArg.h new file mode 100644 index 0000000000..95f05c891a --- /dev/null +++ b/modules/beast_asio/basics/SharedArg.h @@ -0,0 +1,161 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_ASIO_SHAREDARG_H_INCLUDED +#define BEAST_ASIO_SHAREDARG_H_INCLUDED + +/** A container that turns T into a SharedObject. + We use this to manage the lifetime of objects passed to handlers. +*/ +template +struct SharedArg +{ +private: + struct Arg : SharedObject + { + Arg () + { + } + + explicit Arg (BEAST_MOVE_ARG(T) t) + : value (BEAST_MOVE_CAST(T)(t)) + { + } + + template + explicit Arg (P1 p1) + : value (p1) + { + } + + template + Arg (P1 p1, P2 p2) + : value (p1, p2) + { + } + + template + Arg (P1 p1, P2 p2, P3 p3) + : value (p1, p2, p3) + { + } + + template + Arg (P1 p1, P2 p2, P3 p3, P4 p4) + : value (p1, p2, p3, p4) + { + } + + ~Arg () + { + } + + T value; + }; + +public: + SharedArg () + { + } + + explicit SharedArg (BEAST_MOVE_ARG(T) t) + : m_arg (new Arg (BEAST_MOVE_CAST(T)(t))) + { + } + + template + explicit SharedArg (P1 p1) + : m_arg (new Arg (p1)) + { + } + + template + SharedArg (P1 p1, P2 p2) + : m_arg (new Arg (p1, p2)) + { + } + + template + SharedArg (P1 p1, P2 p2, P3 p3) + : m_arg (new Arg (p1, p2, p3)) + { + } + + template + SharedArg (P1 p1, P2 p2, P3 p3, P4 p4) + : m_arg (new Arg (p1, p2, p3, p4)) + { + } + + SharedArg (SharedArg const& other) + : m_arg (other.m_arg) + { + } + + SharedArg& operator= (SharedArg const& other) + { + m_arg = other.m_arg; + return *this; + } + + T& get () + { + return m_arg->value; + } + + T const& get () const + { + return m_arg->value; + } + + T& operator* () + { + return get(); + } + + T const& operator* () const + { + return get(); + } + + T* operator-> () + { + return &get(); + } + + T const* operator-> () const + { + return &get(); + } + + operator T& () + { + return m_arg->value; + } + + operator T const& () const + { + return m_arg->value; + } + +private: + SharedPtr m_arg; +}; + +#endif diff --git a/modules/beast_asio/beast_asio.cpp b/modules/beast_asio/beast_asio.cpp index 6301c1c2e6..e088b895bf 100644 --- a/modules/beast_asio/beast_asio.cpp +++ b/modules/beast_asio/beast_asio.cpp @@ -23,12 +23,12 @@ #include "beast_asio.h" -namespace beast -{ +namespace beast { + +# include "../../beast/http/impl/http-parser/http_parser.h" #include "async/SharedHandler.cpp" -#include "basics/ContentBodyBuffer.cpp" #include "basics/PeerRole.cpp" #include "basics/SSLContext.cpp" @@ -37,14 +37,12 @@ namespace beast #include "protocol/HandshakeDetectLogicPROXY.cpp" -# include "parsehttp/http_parser.h" # include "http/HTTPParserImpl.h" -#include "http/HTTPParser.cpp" -#include "http/UniformResourceLocator.cpp" #include "http/HTTPClientType.cpp" #include "http/HTTPField.cpp" #include "http/HTTPHeaders.cpp" #include "http/HTTPMessage.cpp" +#include "http/HTTPRequest.cpp" #include "http/HTTPResponse.cpp" #include "http/HTTPVersion.cpp" @@ -60,16 +58,8 @@ namespace beast #include "system/BoostUnitTests.cpp" -#ifdef _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4127) // conditional expression is constant -#pragma warning (disable: 4244) // integer conversion, possible loss of data -#endif -#include "parsehttp/http_parser.c" -#ifdef _MSC_VER -#pragma warning (pop) -#endif - } -//------------------------------------------------------------------------------ +#include "http/HTTPParser.cpp" +#include "http/HTTPRequestParser.cpp" +#include "http/HTTPResponseParser.cpp" diff --git a/modules/beast_asio/beast_asio.h b/modules/beast_asio/beast_asio.h index 3d514f0fdc..f66d966e22 100644 --- a/modules/beast_asio/beast_asio.h +++ b/modules/beast_asio/beast_asio.h @@ -53,8 +53,14 @@ # define BEAST_SOCKET_VIRTUAL #endif -namespace beast -{ +#include "../../beast/MPL.h" +#include "../../beast/Utility.h" +#include "../../beast/HTTP.h" + +#include "async/AbstractHandler.h" +#include "async/WrapHandler.h" + +namespace beast { // Order matters # include "async/SharedHandler.h" @@ -62,13 +68,13 @@ namespace beast # include "async/SharedHandlerPtr.h" # include "async/ComposedAsyncOperation.h" #include "async/SharedHandlerAllocator.h" +#include "async/AsyncObject.h" -# include "basics/BufferType.h" # include "basics/BuffersType.h" -#include "basics/ContentBodyBuffer.h" #include "basics/FixedInputBuffer.h" #include "basics/PeerRole.h" #include "basics/SSLContext.h" +#include "basics/SharedArg.h" # include "sockets/SocketBase.h" # include "sockets/Socket.h" @@ -79,11 +85,19 @@ namespace beast # include "http/HTTPField.h" # include "http/HTTPHeaders.h" # include "http/HTTPMessage.h" +# include "http/HTTPRequest.h" # include "http/HTTPResponse.h" + +} + # include "http/HTTPParser.h" -# include "http/UniformResourceLocator.h" +#include "http/HTTPRequestParser.h" +#include "http/HTTPResponseParser.h" + #include "http/HTTPClientType.h" +namespace beast { + # include "protocol/InputParser.h" # include "protocol/HandshakeDetectLogic.h" #include "protocol/HandshakeDetectLogicPROXY.h" diff --git a/modules/beast_asio/http/HTTPClientType.cpp b/modules/beast_asio/http/HTTPClientType.cpp index 143b19fdbe..6a85eb77f0 100644 --- a/modules/beast_asio/http/HTTPClientType.cpp +++ b/modules/beast_asio/http/HTTPClientType.cpp @@ -19,121 +19,108 @@ class HTTPClientType : public HTTPClientBase, public Uncopyable { -private: - using HTTPClientBase::Listener; +public: + class Session; - typedef boost::system::error_code error_code; - - class ListenerHandler + struct State { - public: - ListenerHandler () - : m_owner (nullptr) - , m_listener (nullptr) - { - } - - ListenerHandler (HTTPClientType* owner, Listener* listener = nullptr) - : m_owner (owner) - , m_listener (listener) - { - } - - ListenerHandler (ListenerHandler const& other) - : m_owner (other.m_owner) - , m_listener (other.m_listener) - { - } - - ListenerHandler& operator= (ListenerHandler const& other) - { - m_owner = other.m_owner; - m_listener = other.m_listener; - return *this; - } - - void operator() (error_code) - { - if (m_listener != nullptr) - m_listener->onHTTPRequestComplete ( - *m_owner, m_owner->result ()); - } - - private: - HTTPClientType* m_owner; - Listener* m_listener; + List list; }; -public: + typedef SharedData SharedState; + + SharedState m_state; + Journal m_journal; + double m_timeoutSeconds; + std::size_t m_messageLimitBytes; + std::size_t m_bufferSize; + boost::asio::io_service m_io_service; + WaitableEvent m_stopped; + //-------------------------------------------------------------------------- HTTPClientType ( + Journal journal, double timeoutSeconds, std::size_t messageLimitBytes, std::size_t bufferSize) - : m_timeoutSeconds (timeoutSeconds) + : m_journal (journal) + , m_timeoutSeconds (timeoutSeconds) , m_messageLimitBytes (messageLimitBytes) , m_bufferSize (bufferSize) + , m_stopped (true, true) // manual reset, initially signaled { } ~HTTPClientType () { - m_async_op = nullptr; + cancel(); + wait(); } - Result const& result () const - { - return m_result; - } - - Result const& get (UniformResourceLocator const& url) + result_type get (URL const& url) { + result_type result; boost::asio::io_service io_service; - async_get (io_service, nullptr, url); + async_get (io_service, url, beast::bind ( + &HTTPClientType::handle_get, beast::placeholders::_1, &result)); io_service.run (); - cancel (); - return result (); + return result; } - //-------------------------------------------------------------------------- - - void async_get (boost::asio::io_service& io_service, Listener* listener, - UniformResourceLocator const& url) + void async_get (boost::asio::io_service& io_service, URL const& url, + AbstractHandler handler) { - async_get (io_service, url, ListenerHandler (this, listener)); - } - - // Handler signature is void(error_code) - // - template - void async_get (boost::asio::io_service& io_service, - UniformResourceLocator const& url, - BOOST_ASIO_MOVE_ARG(Handler) handler) - { - async_get (io_service, url, newErrorHandler ( - BOOST_ASIO_MOVE_CAST(Handler)(handler))); - } - - void async_get (boost::asio::io_service& io_service, - UniformResourceLocator const& url, SharedHandlerPtr handler) - { - // This automatically dispatches - m_async_op = new AsyncGetOp ( - *this, io_service, url, handler, - m_timeoutSeconds, m_messageLimitBytes, m_bufferSize); + new Session (*this, io_service, url, + handler, m_timeoutSeconds, m_messageLimitBytes, m_bufferSize); } void cancel () { - if (m_async_op != nullptr) - { - m_async_op->cancel (); - m_async_op = nullptr; - } + SharedState::Access state (m_state); + for (List ::iterator iter (state->list.begin()); + iter != state->list.end(); ++iter) + iter->cancel(); + } + + void wait() + { + m_stopped.wait(); + } + + //-------------------------------------------------------------------------- + + void add (Session& session) + { + SharedState::Access state (m_state); + if (state->list.empty()) + m_stopped.reset(); + state->list.push_back (session); + } + + void remove (Session& session) + { + SharedState::Access state (m_state); + state->list.erase (state->list.iterator_to (session)); + if (state->list.empty()) + m_stopped.signal(); + } + + static void handle_get (result_type const& result, result_type* dest) + { + *dest = result; + } + + Journal journal() const + { + return m_journal; + } + + boost::asio::io_service& get_io_service() + { + return m_io_service; } -private: //-------------------------------------------------------------------------- /** Helper function to get a const_buffer from a String. */ @@ -144,7 +131,7 @@ private: /** Helper function to fill out a Query from a URL. */ template - static Query queryFromURL (UniformResourceLocator const& url) + static Query queryFromURL (URL const& url) { if (url.port () != 0) { @@ -161,74 +148,82 @@ private: //-------------------------------------------------------------------------- - class AsyncGetOp : public ComposedAsyncOperation + class Session + : public SharedObject + , public AsyncObject + , public List ::Node { - private: - typedef boost::asio::ip::tcp Protocol; - typedef boost::system::error_code error_code; - - typedef Protocol::resolver resolver; - typedef resolver::query query; - typedef resolver::iterator iterator; - typedef iterator::value_type resolver_entry; - typedef Protocol::socket socket; - - //---------------------------------------------------------------------- - - enum State - { - stateStart, - stateResolveComplete, - stateConnectComplete, - stateHandshakeComplete, - stateWriteComplete, - stateShutdownComplete - }; - - //---------------------------------------------------------------------- - - struct TimerHandler : SharedHandlerPtr - { - explicit TimerHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - void operator() (error_code const& ec) - { - m_owner->timerCompletion (ec); - } - - AsyncGetOp* m_owner; - }; - - //---------------------------------------------------------------------- - public: - AsyncGetOp (HTTPClientType& owner, - boost::asio::io_service& io_service, - UniformResourceLocator const& url, - SharedHandlerPtr const& handler, - double timeoutSeconds, - std::size_t messageLimitBytes, - std::size_t bufferSize) - : ComposedAsyncOperation (sizeof (*this), handler) - , m_owner (owner) + typedef SharedPtr Ptr; + typedef boost::asio::ip::tcp Protocol; + typedef boost::system::error_code error_code; + typedef HTTPClientBase::error_type error_type; + typedef HTTPClientBase::value_type value_type; + typedef HTTPClientBase::result_type result_type; + + typedef Protocol::resolver resolver; + typedef Protocol::socket socket; + typedef resolver::query query; + typedef resolver::iterator iterator; + typedef iterator::value_type resolver_entry; + + HTTPClientType& m_owner; + boost::asio::io_service& m_io_service; + boost::asio::io_service::strand m_strand; + boost::asio::deadline_timer m_timer; + resolver m_resolver; + socket m_socket; + AbstractHandler m_handler; + + URL m_url; + boost::asio::ssl::context m_context; + MemoryBlock m_buffer; + HTTPResponseParser m_parser; + std::size_t m_messageLimitBytes; + std::size_t m_bytesReceived; + + String m_get_string; + WaitableEvent m_done; + ScopedPointer m_stream; + + struct State + { + State () : complete (false) + { + } + + bool complete; + error_code error; + SharedPtr response; + }; + typedef SharedData SharedState; + SharedState m_state; + + //---------------------------------------------------------------------- + + Session (HTTPClientType& owner, + boost::asio::io_service& io_service, + URL const& url, + AbstractHandler const& handler, + double timeoutSeconds, + std::size_t messageLimitBytes, + std::size_t bufferSize) + : m_owner (owner) , m_io_service (io_service) - , m_strand (m_io_service) - , m_url (url) - , m_handler (handler) + , m_strand (io_service) , m_timer (io_service) , m_resolver (io_service) , m_socket (io_service) + , m_handler (handler) + , m_url (url) , m_context (boost::asio::ssl::context::sslv23) , m_buffer (bufferSize) - , m_parser (HTTPParser::typeResponse) - , m_timer_canceled (false) - , m_timer_expired (false) , m_messageLimitBytes (messageLimitBytes) , m_bytesReceived (0) { + m_owner.add (*this); + + // Configure the SSL context for certificate verification m_context.set_default_verify_paths (); m_context.set_options ( boost::asio::ssl::context::no_sslv2 | @@ -236,314 +231,163 @@ private: boost::asio::ssl::context::default_workarounds); //m_context.set_verify_mode (boost::asio::ssl::verify_peer); + // Set the timer if a timeout is requested if (timeoutSeconds > 0) { m_timer.expires_from_now ( boost::posix_time::milliseconds ( long (timeoutSeconds * 1000))); - ++m_io_pending; - m_timer.async_wait (TimerHandler (this)); + m_timer.async_wait (m_strand.wrap (wrapHandler ( + boost::bind (&Session::handle_timer, Ptr(this), + boost::asio::placeholders::error, + CompletionCounter(this)), m_handler))); } - // Count as pending i/o - ++m_io_pending; - m_io_service.dispatch ( - m_strand.wrap (StartHandler (this))); + // Start the operation on an io_service thread + io_service.dispatch (m_strand.wrap (wrapHandler ( + boost::bind (&Session::handle_start, Ptr(this), + CompletionCounter(this)), m_handler))); } - ~AsyncGetOp () + ~Session () { + State result; + { + SharedState::ConstAccess state (m_state); + result = *state; + } + + m_io_service.wrap (m_handler) (std::make_pair ( + result.error, result.response)); + + m_owner.remove (*this); } - // Cancel all pending I/O, if any, and block until - // there are no more completion handler calls pending. - // + //---------------------------------------------------------------------- + + // Called by the owner to cancel pending i/o. void cancel () { - cancel_all (); - m_done.wait (); - } - - private: - //---------------------------------------------------------------------- - - // Counts a pending i/o as canceled - // - void cancel_io () - { - bassert (m_io_pending.get () > 0); - if (--m_io_pending == 0) - m_done.signal (); - } - - // Cancels the deadline timer. - // - void cancel_timer () - { - m_timer_canceled = true; - error_code ec; - m_timer.cancel (ec); - } - - // Called to notify the original handler the operation is complete. - // - void complete (error_code const& ec) - { - m_owner.m_result.error = ec; - - cancel_timer (); - - bassert (m_io_pending.get () > 0); - - cancel_io (); - - // We call the handler directly since we know - // we are already in the right context, and - // because we need to do some things afterwards. - // - m_handler->operator() (ec); - } - - // Called every time an async operation completes. - // The return value indicates if the handler should - // stop additional activity and return immediately. - // - bool io_complete (error_code const& ec) - { - if (m_timer_expired || - ec == boost::asio::error::operation_aborted) { - cancel_io (); - return true; - } - else if (ec != 0 && ec != boost::asio::error::eof) - { - complete (ec); - return true; + SharedState::Access state (m_state); + if (! state->complete) + { + state->complete = true; + state->error = boost::asio::error::operation_aborted; + } } - return false; + cancel_all(); } - // Cancels/closes all i/o objects. - // + // Cancel all pending I/O void cancel_all () { - cancel_timer (); - m_resolver.cancel (); error_code ec; - m_socket.close (ec); + m_timer.cancel (ec); + m_resolver.cancel (); + m_socket.cancel (ec); + m_socket.shutdown (socket::shutdown_both); } - // Called when the deadline timer expires or is canceled. - // - void timerCompletion (error_code ec) + // Called by a completion handler when error is not eof or aborted. + void failed (error_code ec) { - if (ec == boost::asio::error::operation_aborted) { - bassert (m_timer_canceled); - return cancel_io (); + SharedState::Access state (m_state); + if (! state->complete) + { + state->complete = true; + state->error = ec; + state->response = nullptr; + } } - check_invariant (ec == 0); - - // Handle the case where the timer completion has already - // been queued for dispatch but we have finished the operation - // and queued the completion handler for dispatch. - // - if (! m_timer_canceled) - { - m_timer_expired = true; - - ec = error_code (boost::asio::error::timed_out, - boost::asio::error::get_system_category ()); - - complete (ec); - - io_complete (ec); - - m_resolver.cancel (); - m_socket.close (ec); - } - else - { - cancel_io (); - } + cancel_all(); } - //---------------------------------------------------------------------- - - struct StartHandler : SharedHandlerPtr - { - explicit StartHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() () - { - m_owner->start_complete (); - } - - AsyncGetOp* m_owner; - }; - - struct ResolveHandler : SharedHandlerPtr - { - explicit ResolveHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() (error_code const& ec, iterator iter) - { - m_owner->resolve_complete (ec, iter); - } - - AsyncGetOp* m_owner; - }; - - struct ConnectHandler : SharedHandlerPtr - { - explicit ConnectHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() (error_code const& ec) - { - m_owner->connect_complete (ec); - } - - AsyncGetOp* m_owner; - }; - - struct HandshakeHandler : SharedHandlerPtr - { - explicit HandshakeHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() (error_code const& ec) - { - m_owner->handshake_complete (ec); - } - - AsyncGetOp* m_owner; - }; - - struct WriteHandler : SharedHandlerPtr - { - explicit WriteHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() (error_code const& ec, std::size_t bytes_transferred) - { - m_owner->write_complete (ec, bytes_transferred); - } - - AsyncGetOp* m_owner; - }; - - struct ReadHandler : SharedHandlerPtr - { - explicit ReadHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() (error_code const& ec, std::size_t bytes_transferred) - { - m_owner->read_complete (ec, bytes_transferred); - } - - AsyncGetOp* m_owner; - }; - - struct ShutdownHandler : SharedHandlerPtr - { - explicit ShutdownHandler (AsyncGetOp* owner) - : SharedHandlerPtr (owner) - , m_owner (owner) - { - } - - void operator() (error_code const& ec) - { - m_owner->shutdown_complete (ec); - } - - AsyncGetOp* m_owner; - }; - - //---------------------------------------------------------------------- - void async_read_some () { boost::asio::mutable_buffers_1 buf ( m_buffer.getData (), m_buffer.getSize ()); - m_stream->async_read_some (buf, - m_strand.wrap (ReadHandler (this))); - } - - // Called when the HTTP parser returns an error - void parse_error () - { - //unsigned char const http_errno (m_parser.error ()); - String const http_errmsg (m_parser.message ()); - - // VFALCO TODO put the parser error in ec - error_code ec ( - boost::system::errc::invalid_argument, - boost::system::system_category ()); - - complete (ec); - } - - // Called to create an error when the message is over the limit - error_code message_limit_error () - { - // VFALCO TODO Make a suitable error code - return error_code ( - boost::system::errc::invalid_argument, - boost::system::system_category ()); + m_stream->async_read_some (buf, m_strand.wrap ( + wrapHandler (boost::bind (&Session::handle_read, + Ptr(this), boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred, + CompletionCounter(this)), m_handler))); } //---------------------------------------------------------------------- + // + // Completion handlers + // - void start_complete () + // Called when there are no more pending i/o completions + void asyncHandlersComplete() + { + } + + // Called when the operation starts + void handle_start (CompletionCounter) { query q (queryFromURL (m_url)); - m_resolver.async_resolve (q, - m_strand.wrap (ResolveHandler (this))); + + m_resolver.async_resolve (q, m_strand.wrap ( + wrapHandler (boost::bind (&Session::handle_resolve, + Ptr(this), boost::asio::placeholders::error, + boost::asio::placeholders::iterator, + CompletionCounter(this)), m_handler))); } - void resolve_complete (error_code ec, iterator iter) + // Called when the timer completes + void handle_timer (error_code ec, CompletionCounter) { - if (io_complete (ec)) + if (ec == boost::asio::error::operation_aborted) return; + if (ec != 0) + { + failed (ec); + return; + } + + failed (boost::system::errc::make_error_code ( + boost::system::errc::timed_out)); + } + + // Called when the resolver completes + void handle_resolve (error_code ec, iterator iter, CompletionCounter) + { + if (ec == boost::asio::error::operation_aborted) + return; + + if (ec != 0) + { + failed (ec); + return; + } + resolver_entry const entry (*iter); - m_socket.async_connect (entry.endpoint (), - m_strand.wrap (ConnectHandler (this))); + m_socket.async_connect (entry.endpoint (), m_strand.wrap ( + wrapHandler (boost::bind (&Session::handle_connect, + Ptr(this), boost::asio::placeholders::error, + CompletionCounter(this)), m_handler))); } - void connect_complete (error_code ec) + // Called when the connection attempt completes + void handle_connect (error_code ec, CompletionCounter) { - if (io_complete (ec)) + if (ec == boost::asio::error::operation_aborted) return; + if (ec != 0) + { + failed (ec); + return; + } + if (m_url.scheme () == "https") { typedef boost::asio::ssl::stream ssl_stream; @@ -553,153 +397,163 @@ private: boost::asio::ssl::verify_peer | boost::asio::ssl::verify_fail_if_no_peer_cert); */ - m_stream->async_handshake ( - Socket::client, HandshakeHandler (this)); + m_stream->async_handshake (Socket::client, m_strand.wrap ( + wrapHandler (boost::bind (&Session::handle_handshake, + Ptr(this), boost::asio::placeholders::error, + CompletionCounter(this)), m_handler))); return; } m_stream = new SocketWrapper (m_socket); - handshake_complete (ec); + handle_handshake (ec, CompletionCounter(this)); } - void handshake_complete (error_code ec) + // Called when the SSL handshake completes + void handle_handshake (error_code ec, CompletionCounter) { - if (io_complete (ec)) + if (ec == boost::asio::error::operation_aborted) return; + if (ec != 0) + { + failed (ec); + return; + } + m_get_string = "GET " + m_url.path() + " HTTP/1.1\r\n" + "Host: " + m_url.host() + "\r\n" + "Accept: */*\r\n" + "Connection: close\r\n\r\n"; - boost::asio::async_write ( - *m_stream, stringBuffer (m_get_string), - m_strand.wrap (WriteHandler (this))); - ++m_io_pending; + boost::asio::async_write (*m_stream, stringBuffer ( + m_get_string), m_strand.wrap (wrapHandler ( + boost::bind (&Session::handle_write, Ptr(this), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred, + CompletionCounter(this)), m_handler))); async_read_some (); } - void write_complete (error_code ec, std::size_t) + // Called when the write operation completes + void handle_write (error_code ec, std::size_t, CompletionCounter) { - if (io_complete (ec)) + if (ec == boost::asio::error::operation_aborted) return; - if (! m_stream->needs_handshake ()) + if (ec != 0) { - m_socket.shutdown (socket::shutdown_send, ec); - if (ec != 0) - return complete (ec); + failed (ec); + return; } - // deduct one i/o since we aren't issuing any new one - cancel_io (); + if (! m_stream->needs_handshake ()) + m_socket.shutdown (socket::shutdown_send, ec); } - void read_complete (error_code ec, std::size_t bytes_transferred) + void handle_read (error_code ec, + std::size_t bytes_transferred, CompletionCounter) { + if (ec == boost::asio::error::operation_aborted) + return; + + if (ec != 0) + { + failed (ec); + return; + } + m_bytesReceived += bytes_transferred; if (m_bytesReceived > m_messageLimitBytes) - ec = message_limit_error (); - - if (io_complete (ec)) + { + failed (error_code ( + boost::system::errc::invalid_argument, + boost::system::system_category ())); return; + } std::size_t const bytes_parsed (m_parser.process ( m_buffer.getData (), bytes_transferred)); if (m_parser.error ()) { - parse_error (); + failed (error_code ( + boost::system::errc::invalid_argument, + boost::system::system_category ())); return; } if (bytes_parsed != bytes_transferred) { - // VFALCO TODO put an appropriate error in ec - ec = error_code ( + failed (error_code ( boost::system::errc::invalid_argument, - boost::system::system_category ()); - return complete (ec); + boost::system::system_category ())); + return; } if (ec == boost::asio::error::eof) - { m_parser.process_eof (); - } if (m_parser.finished ()) { - m_state = stateShutdownComplete; if (m_stream->needs_handshake ()) - m_stream->async_shutdown (ShutdownHandler (this)); + { + m_stream->async_shutdown (m_strand.wrap (wrapHandler ( + boost::bind (&Session::handle_shutdown, Ptr(this), + boost::asio::placeholders::error, + CompletionCounter(this)), m_handler))); + } else - shutdown_complete (error_code ()); + { + handle_shutdown (error_code (), CompletionCounter(this)); + } return; } async_read_some (); } - void shutdown_complete (error_code ec) + void handle_shutdown (error_code ec, CompletionCounter) { - if (io_complete (ec)) + if (ec == boost::asio::error::operation_aborted) return; - m_owner.m_result.response = m_parser.response (); if (ec == boost::asio::error::eof) - ec = error_code (); + ec = error_code(); - return complete (ec); + if (ec != 0) + { + failed (ec); + return; + } + + { + SharedState::Access state (m_state); + if (! state->complete) + { + state->complete = true; + state->response = m_parser.response(); + } + } + + cancel_all(); } - - private: - WaitableEvent m_done; - Atomic m_io_pending; - HTTPClientType& m_owner; - boost::asio::io_service& m_io_service; - boost::asio::io_service& m_strand; - UniformResourceLocator m_url; - SharedHandlerPtr m_handler; - boost::asio::deadline_timer m_timer; - resolver m_resolver; - socket m_socket; - ScopedPointer m_stream; - boost::asio::ssl::context m_context; - MemoryBlock m_buffer; - State m_state; - HTTPParser m_parser; - String m_get_string; - bool m_timer_canceled; - bool m_timer_expired; - std::size_t m_messageLimitBytes; - std::size_t m_bytesReceived; }; - - double m_timeoutSeconds; - std::size_t m_messageLimitBytes; - std::size_t m_bufferSize; - boost::asio::io_service m_io_service; - SharedPtr m_async_op; - Result m_result; }; //------------------------------------------------------------------------------ -HTTPClientBase* HTTPClientBase::New ( +HTTPClientBase* HTTPClientBase::New (Journal journal, double timeoutSeconds, std::size_t messageLimitBytes, std::size_t bufferSize) { - ScopedPointer object (new HTTPClientType - (timeoutSeconds, messageLimitBytes, bufferSize)); - return object.release (); + return new HTTPClientType ( + journal, timeoutSeconds, messageLimitBytes, bufferSize); } //------------------------------------------------------------------------------ -class HTTPClientTests - : public UnitTest - , public HTTPClientBase::Listener +class HTTPClientTests : public UnitTest { public: typedef boost::system::error_code error_code; @@ -758,19 +612,19 @@ public: } } - void log (HTTPClientBase::Result const& result) + void log (HTTPClientBase::error_type error, HTTPClientBase::value_type const& response) { - if (result.error != 0) + if (error != 0) { logMessage (String ( - "HTTPClient error: '" + result.error.message() + "'")); + "HTTPClient error: '" + error.message() + "'")); } - else if (! result.response.empty ()) + else if (! response.empty ()) { logMessage (String ("Status: ") + - String::fromNumber (result.response->status())); - - log (*result.response); + String::fromNumber (response->status())); + + log (*response); } else { @@ -780,28 +634,31 @@ public: //-------------------------------------------------------------------------- - void onHTTPRequestComplete ( - HTTPClientBase const&, HTTPClientBase::Result const& result) + void handle_get (HTTPClientBase::result_type result) { - log (result); + log (result.first, result.second); } void testSync (String const& s, double timeoutSeconds) { ScopedPointer client ( - HTTPClientBase::New (timeoutSeconds)); + HTTPClientBase::New (Journal(), timeoutSeconds)); - log (client->get (ParsedURL (s).url ())); + HTTPClientBase::result_type const& result ( + client->get (ParsedURL (s).url ())); + + log (result.first, result.second); } void testAsync (String const& s, double timeoutSeconds) { IoServiceThread t; ScopedPointer client ( - HTTPClientBase::New (timeoutSeconds)); + HTTPClientBase::New (Journal(), timeoutSeconds)); - client->async_get (t.get_io_service (), this, - ParsedURL (s).url ()); + client->async_get (t.get_io_service (), ParsedURL (s).url (), + beast::bind (&HTTPClientTests::handle_get, this, + beast::_1)); t.start (); t.join (); diff --git a/modules/beast_asio/http/HTTPClientType.h b/modules/beast_asio/http/HTTPClientType.h index 5922813f38..364b409000 100644 --- a/modules/beast_asio/http/HTTPClientType.h +++ b/modules/beast_asio/http/HTTPClientType.h @@ -20,46 +20,54 @@ #ifndef BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED #define BEAST_ASIO_HTTPCLIENTTYPE_H_INCLUDED +#include + +namespace beast { + class HTTPClientBase { public: - struct Result - { - boost::system::error_code error; - SharedPtr response; - }; - - class Listener - { - public: - virtual void onHTTPRequestComplete ( - HTTPClientBase const& client, - Result const& result) = 0; - }; + typedef boost::system::error_code error_type; + typedef SharedPtr value_type; + typedef std::pair result_type; static HTTPClientBase* New ( + Journal journal = Journal(), double timeoutSeconds = 30, std::size_t messageLimitBytes = 256 * 1024, std::size_t bufferSize = 16 * 1024); + /** Destroy the client. + This will cancel any pending i/o and block until all completion + handlers have been called. + */ virtual ~HTTPClientBase () { } - virtual Result const& result () const = 0; + virtual result_type get (URL const& url) = 0; - virtual Result const& get ( - UniformResourceLocator const& url) = 0; + /** Perform an asynchronous get on the specified URL. + Handler will be called with this signature: + void (result_type) + */ + template + void async_get (boost::asio::io_service& io_service, + URL const& url, BEAST_MOVE_ARG(Handler) handler) + { + async_get (io_service, url, + AbstractHandler ( + BEAST_MOVE_CAST(Handler)(handler))); + } virtual void async_get (boost::asio::io_service& io_service, - Listener* listener, - UniformResourceLocator const& url) = 0; + URL const& url, AbstractHandler handler) = 0; - /** Cancel any pending asynchronous operations. - This must be called before destroying the container if there are - any pending asynchronous operations. This routine does nothing if - there are no pending operations. The call will block until all - pending i/o is canceled. - */ - virtual void cancel () = 0; + /** Cancel all pending asynchronous operations. */ + virtual void cancel() = 0; + + /** Block until all asynchronous i/o completes. */ + virtual void wait() = 0; }; +} + #endif diff --git a/modules/beast_asio/http/HTTPHeaders.cpp b/modules/beast_asio/http/HTTPHeaders.cpp index f28f5113f2..48c460026d 100644 --- a/modules/beast_asio/http/HTTPHeaders.cpp +++ b/modules/beast_asio/http/HTTPHeaders.cpp @@ -72,3 +72,15 @@ String HTTPHeaders::operator[] (String const& field) const { return get (field); } + +String HTTPHeaders::toString () const +{ + String s; + for (int i = 0; i < m_fields.size (); ++i) + { + HTTPField const field (at(i)); + s << field.name() << ": " << field.value() << newLine; + } + return s; +} + diff --git a/modules/beast_asio/http/HTTPHeaders.h b/modules/beast_asio/http/HTTPHeaders.h index d2a1a4cad1..6cf7e7e2aa 100644 --- a/modules/beast_asio/http/HTTPHeaders.h +++ b/modules/beast_asio/http/HTTPHeaders.h @@ -61,6 +61,9 @@ public: String operator[] (String const& field) const; /** @} */ + /** Outputs all the headers into one string. */ + String toString () const; + private: StringPairArray m_fields; }; diff --git a/modules/beast_asio/http/HTTPMessage.cpp b/modules/beast_asio/http/HTTPMessage.cpp index aeb743843e..698ec0dcc9 100644 --- a/modules/beast_asio/http/HTTPMessage.cpp +++ b/modules/beast_asio/http/HTTPMessage.cpp @@ -19,7 +19,7 @@ HTTPMessage::HTTPMessage (HTTPVersion const& version_, StringPairArray& fields, - ContentBodyBuffer& body) + DynamicBuffer& body) : m_version (version_) , m_headers (fields) { @@ -36,7 +36,15 @@ HTTPHeaders const& HTTPMessage::headers () const return m_headers; } -ContentBodyBuffer const& HTTPMessage::body () const +DynamicBuffer const& HTTPMessage::body () const { return m_body; } + +String HTTPMessage::toString () const +{ + String s; + s << "HTTP " << version().toString() << newLine; + s << m_headers.toString (); + return s; +} diff --git a/modules/beast_asio/http/HTTPMessage.h b/modules/beast_asio/http/HTTPMessage.h index 549d7d43c1..f2ca3e5756 100644 --- a/modules/beast_asio/http/HTTPMessage.h +++ b/modules/beast_asio/http/HTTPMessage.h @@ -40,7 +40,7 @@ public: */ HTTPMessage (HTTPVersion const& version_, StringPairArray& fields, - ContentBodyBuffer& body); + DynamicBuffer& body); /** Returns the HTTP version of this message. */ HTTPVersion const& version () const; @@ -49,12 +49,15 @@ public: HTTPHeaders const& headers () const; /** Returns the content-body. */ - ContentBodyBuffer const& body () const; + DynamicBuffer const& body () const; + /** Outputs all the HTTPMessage data excluding the body into a string. */ + String toString () const; + private: HTTPVersion m_version; HTTPHeaders m_headers; - ContentBodyBuffer m_body; + DynamicBuffer m_body; }; #endif diff --git a/modules/beast_asio/http/HTTPParser.cpp b/modules/beast_asio/http/HTTPParser.cpp index 5ca1c9ed83..db11fda651 100644 --- a/modules/beast_asio/http/HTTPParser.cpp +++ b/modules/beast_asio/http/HTTPParser.cpp @@ -17,6 +17,8 @@ */ //============================================================================== +namespace beast { + HTTPParser::HTTPParser (Type type) : m_type (type) , m_impl (new HTTPParserImpl ( @@ -44,7 +46,15 @@ std::size_t HTTPParser::process (void const* buf, std::size_t bytes) if (m_impl->finished ()) { - if (m_type == typeResponse) + if (m_type == typeRequest) + { + m_request = new HTTPRequest ( + m_impl->version (), + m_impl->fields (), + m_impl->body (), + m_impl->method ()); + } + else if (m_type == typeResponse) { m_response = new HTTPResponse ( m_impl->version (), @@ -54,7 +64,7 @@ std::size_t HTTPParser::process (void const* buf, std::size_t bytes) } else { - // m_request = new HTTPRequest ( + bassertfalse; } } @@ -71,9 +81,28 @@ bool HTTPParser::finished () const return m_impl->finished(); } +StringPairArray const& HTTPParser::fields () const +{ + return m_impl->fields(); +} + +bool HTTPParser::headersComplete () const +{ + return m_impl->headers_complete(); +} + +SharedPtr const& HTTPParser::request () +{ + bassert (m_type == typeRequest); + + return m_request; +} + SharedPtr const& HTTPParser::response () { bassert (m_type == typeResponse); return m_response; } + +} diff --git a/modules/beast_asio/http/HTTPParser.h b/modules/beast_asio/http/HTTPParser.h index d6e3a287e2..4295310616 100644 --- a/modules/beast_asio/http/HTTPParser.h +++ b/modules/beast_asio/http/HTTPParser.h @@ -20,6 +20,8 @@ #ifndef BEAST_ASIO_HTTPPARSER_H_INCLUDED #define BEAST_ASIO_HTTPPARSER_H_INCLUDED +namespace beast { + class HTTPParserImpl; /** A parser for HTTPRequest and HTTPResponse objects. */ @@ -57,18 +59,31 @@ public: /** Returns `true` when parsing is successful and complete. */ bool finished () const; - /** Return the HTTPResponse object produce from the parsing. + /** Peek at the header fields as they are being built. + Only complete pairs will show up, never partial strings. + */ + StringPairArray const& fields () const; + + /** Returns `true` if all the HTTP headers have been received. */ + bool headersComplete () const; + + /** Return the HTTPRequest object produced from the parsiing. + Only valid after finished returns `true`. + */ + SharedPtr const& request (); + + /** Return the HTTPResponse object produced from the parsing. Only valid after finished returns `true`. */ SharedPtr const& response (); - //SharedPtr const& request (); - -private: +protected: Type m_type; ScopedPointer m_impl; + SharedPtr m_request; SharedPtr m_response; - //SharedPtr m_request; }; +} + #endif diff --git a/modules/beast_asio/http/HTTPParserImpl.h b/modules/beast_asio/http/HTTPParserImpl.h index c01fd58114..dfd8b1d8ee 100644 --- a/modules/beast_asio/http/HTTPParserImpl.h +++ b/modules/beast_asio/http/HTTPParserImpl.h @@ -31,6 +31,7 @@ public: explicit HTTPParserImpl (enum http_parser_type type) : m_finished (false) , m_was_value (false) + , m_headersComplete (false) { m_settings.on_message_begin = &HTTPParserImpl::on_message_begin; m_settings.on_url = &HTTPParserImpl::on_url; @@ -119,7 +120,12 @@ public: return m_fields; } - ContentBodyBuffer& body () + bool headers_complete () const + { + return m_headersComplete; + } + + DynamicBuffer& body () { return m_body; } @@ -174,6 +180,7 @@ private: int onHeadersComplete () { + m_headersComplete = true; int ec (0); addFieldValue (); return ec; @@ -181,8 +188,9 @@ private: int onBody (char const* at, std::size_t length) { - m_body.commit (boost::asio::buffer_copy (m_body.prepare (length), - boost::asio::buffer (at, length))); + m_body.commit (boost::asio::buffer_copy ( + m_body.prepare (length), + boost::asio::buffer (at, length))); return 0; } @@ -250,7 +258,8 @@ private: bool m_was_value; std::string m_field; std::string m_value; - ContentBodyBuffer m_body; + bool m_headersComplete; + DynamicBuffer m_body; }; #endif diff --git a/modules/beast_asio/http/HTTPRequest.cpp b/modules/beast_asio/http/HTTPRequest.cpp new file mode 100644 index 0000000000..f5a61c947e --- /dev/null +++ b/modules/beast_asio/http/HTTPRequest.cpp @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +HTTPRequest::HTTPRequest ( + HTTPVersion const& version_, + StringPairArray& fields, + DynamicBuffer& body, + unsigned short method_) + : HTTPMessage (version_, fields, body) + , m_method (method_) +{ +} + +unsigned short HTTPRequest::method () const +{ + return m_method; +} + +String HTTPRequest::toString () const +{ + String s; + s << "Method: " << String::fromNumber (method ()) << newLine; + s << this->HTTPMessage::toString (); + return s; +} + diff --git a/modules/beast_asio/http/HTTPRequest.h b/modules/beast_asio/http/HTTPRequest.h new file mode 100644 index 0000000000..f21c30879a --- /dev/null +++ b/modules/beast_asio/http/HTTPRequest.h @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_ASIO_HTTPREQUEST_H_INCLUDED +#define BEAST_ASIO_HTTPREQUEST_H_INCLUDED + +class HTTPRequest : public HTTPMessage +{ +public: + /** Construct a complete response from values. + Ownership of the fields and body parameters are + transferred from the caller. + */ + HTTPRequest ( + HTTPVersion const& version_, + StringPairArray& fields, + DynamicBuffer& body, + unsigned short method_); + + unsigned short method () const; + + /** Convert the request into a string, excluding the body. */ + String toString () const; + +private: + unsigned short m_method; +}; + +#endif diff --git a/modules/beast_core/memory/beast_GlobalPagedFreeStore.cpp b/modules/beast_asio/http/HTTPRequestParser.cpp similarity index 73% rename from modules/beast_core/memory/beast_GlobalPagedFreeStore.cpp rename to modules/beast_asio/http/HTTPRequestParser.cpp index 1074728c51..0647bf5016 100644 --- a/modules/beast_core/memory/beast_GlobalPagedFreeStore.cpp +++ b/modules/beast_asio/http/HTTPRequestParser.cpp @@ -17,26 +17,22 @@ */ //============================================================================== -namespace -{ +//#include "HTTPRequestParser.h" -// Size of a page -// -static const size_t globalPageBytes = 8 * 1024; +namespace beast { -} - -GlobalPagedFreeStore::GlobalPagedFreeStore () - : SharedSingleton (SingletonLifetime::persistAfterCreation) - , m_allocator (globalPageBytes) +HTTPRequestParser::HTTPRequestParser () + : HTTPParser (typeRequest) { } -GlobalPagedFreeStore::~GlobalPagedFreeStore () +HTTPRequestParser::~HTTPRequestParser () { } -GlobalPagedFreeStore* GlobalPagedFreeStore::createInstance () +SharedPtr const& HTTPRequestParser::request () { - return new GlobalPagedFreeStore; + return m_request; +} + } diff --git a/modules/beast_asio/http/HTTPRequestParser.h b/modules/beast_asio/http/HTTPRequestParser.h new file mode 100644 index 0000000000..00cda4135f --- /dev/null +++ b/modules/beast_asio/http/HTTPRequestParser.h @@ -0,0 +1,46 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HTTP_REQUESTPARSER_H_INCLUDED +#define BEAST_HTTP_REQUESTPARSER_H_INCLUDED + +#include "HTTPParser.h" + +namespace beast { + +/** A parser for HTTPRequest objects. */ +class HTTPRequestParser : public HTTPParser +{ +public: + /** Construct a new parser for the specified HTTPMessage type. */ + HTTPRequestParser (); + + /** Destroy the parser. */ + ~HTTPRequestParser (); + + /** Return the HTTPRequest object produced from the parsing. */ + SharedPtr const& request (); + +private: + //SharedPtr m_request; +}; + +} + +#endif diff --git a/modules/beast_asio/http/HTTPResponse.cpp b/modules/beast_asio/http/HTTPResponse.cpp index 7396127b5c..503a2eb208 100644 --- a/modules/beast_asio/http/HTTPResponse.cpp +++ b/modules/beast_asio/http/HTTPResponse.cpp @@ -20,7 +20,7 @@ HTTPResponse::HTTPResponse ( HTTPVersion const& version_, StringPairArray& fields, - ContentBodyBuffer& body, + DynamicBuffer& body, unsigned short status_) : HTTPMessage (version_, fields, body) , m_status (status_) @@ -31,3 +31,12 @@ unsigned short HTTPResponse::status () const { return m_status; } + +String HTTPResponse::toString () const +{ + String s; + s << "Status: " << String::fromNumber (status ()) << newLine; + s << this->HTTPMessage::toString (); + return s; +} + diff --git a/modules/beast_asio/http/HTTPResponse.h b/modules/beast_asio/http/HTTPResponse.h index bb3f89cb11..2edfc99f17 100644 --- a/modules/beast_asio/http/HTTPResponse.h +++ b/modules/beast_asio/http/HTTPResponse.h @@ -30,11 +30,14 @@ public: HTTPResponse ( HTTPVersion const& version_, StringPairArray& fields, - ContentBodyBuffer& body, + DynamicBuffer& body, unsigned short status_); unsigned short status () const; + /** Convert the response into a string, excluding the body. */ + String toString () const; + private: unsigned short m_status; }; diff --git a/modules/beast_asio/http/HTTPResponseParser.cpp b/modules/beast_asio/http/HTTPResponseParser.cpp new file mode 100644 index 0000000000..b5e5857428 --- /dev/null +++ b/modules/beast_asio/http/HTTPResponseParser.cpp @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +//#include "HTTPResponseParser.h" + +namespace beast { + +HTTPResponseParser::HTTPResponseParser () + : HTTPParser (typeResponse) +{ +} + +HTTPResponseParser::~HTTPResponseParser () +{ +} + +SharedPtr const& HTTPResponseParser::response () +{ + return m_response; +} + +} diff --git a/modules/beast_asio/http/HTTPResponseParser.h b/modules/beast_asio/http/HTTPResponseParser.h new file mode 100644 index 0000000000..422c9f0b26 --- /dev/null +++ b/modules/beast_asio/http/HTTPResponseParser.h @@ -0,0 +1,46 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HTTP_RESPONSEPARSER_H_INCLUDED +#define BEAST_HTTP_RESPONSEPARSER_H_INCLUDED + +#include "HTTPParser.h" + +namespace beast { + +/** A parser for HTTPResponse objects. */ +class HTTPResponseParser : public HTTPParser +{ +public: + /** Construct a new parser for the specified HTTPMessage type. */ + HTTPResponseParser (); + + /** Destroy the parser. */ + ~HTTPResponseParser (); + + /** Return the HTTPResponse object produced from the parsing. */ + SharedPtr const& response (); + +private: + //SharedPtr m_response; +}; + +} + +#endif diff --git a/modules/beast_asio/http/HTTPVersion.cpp b/modules/beast_asio/http/HTTPVersion.cpp index 7fcf4dc5ad..b6e9dfd8b0 100644 --- a/modules/beast_asio/http/HTTPVersion.cpp +++ b/modules/beast_asio/http/HTTPVersion.cpp @@ -44,16 +44,16 @@ HTTPVersion& HTTPVersion::operator= (HTTPVersion const& other) String HTTPVersion::toString () const { - return String::fromNumber (major ()) + "." + - String::fromNumber (minor ()); + return String::fromNumber (vmajor ()) + "." + + String::fromNumber (vminor ()); } -unsigned short HTTPVersion::major () const +unsigned short HTTPVersion::vmajor () const { return m_major; } -unsigned short HTTPVersion::minor () const +unsigned short HTTPVersion::vminor () const { return m_minor; } diff --git a/modules/beast_asio/http/HTTPVersion.h b/modules/beast_asio/http/HTTPVersion.h index c3e2a196c3..408e637944 100644 --- a/modules/beast_asio/http/HTTPVersion.h +++ b/modules/beast_asio/http/HTTPVersion.h @@ -29,8 +29,8 @@ public: HTTPVersion (HTTPVersion const& other); HTTPVersion& operator= (HTTPVersion const& other); String toString () const; - unsigned short major () const; - unsigned short minor () const; + unsigned short vmajor () const; + unsigned short vminor () const; bool operator== (HTTPVersion const& rhs) const; bool operator!= (HTTPVersion const& rhs) const; bool operator> (HTTPVersion const& rhs) const; @@ -40,7 +40,7 @@ public: private: unsigned short m_major; - unsigned short m_minor;; + unsigned short m_minor; }; #endif diff --git a/modules/beast_asio/sockets/SocketWrapper.h b/modules/beast_asio/sockets/SocketWrapper.h index b93ee8ea9f..7c80eff28a 100644 --- a/modules/beast_asio/sockets/SocketWrapper.h +++ b/modules/beast_asio/sockets/SocketWrapper.h @@ -51,12 +51,6 @@ namespace detail namespace SocketWrapperMemberChecks { - template - struct EnableIf : boost::false_type { }; - - template <> - struct EnableIf : boost::true_type { }; - BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service); BEAST_DEFINE_IS_CALL_POSSIBLE(has_lowest_layer, lowest_layer); @@ -133,6 +127,12 @@ class SocketWrapper , public Uncopyable { public: + // Converts a static bool constexpr member named 'value' into + // an IntegralConstant for SFINAE overload resolution. + // + template + struct Enabled : public IntegralConstant { }; + template explicit SocketWrapper (Arg& arg) : m_object (arg) @@ -232,11 +232,11 @@ public: { using namespace detail::SocketWrapperMemberChecks; return native_handle (type_name, dest, - EnableIf ::value> ()); + Enabled > ()); } bool native_handle (char const* type_name, void* dest, - boost::true_type) + TrueType) { char const* const name (typeid (typename this_layer_type::native_handle_type).name ()); if (strcmp (name, type_name) == 0) @@ -249,7 +249,7 @@ public: } bool native_handle (char const*, void*, - boost::false_type) + FalseType) { pure_virtual_called (__FILE__, __LINE__); return false; @@ -266,21 +266,21 @@ public: // Apparently has_get_io_service always results in false using namespace detail::SocketWrapperMemberChecks; return get_io_service ( - EnableIf ::value> ()); + Enabled > ()); #else - return get_io_service (boost::true_type ()); + return get_io_service (TrueType ()); #endif } boost::asio::io_service& get_io_service ( - boost::true_type) + TrueType) { return m_object.get_io_service (); } boost::asio::io_service& get_io_service ( - boost::false_type) + FalseType) { pure_virtual_called (__FILE__, __LINE__); return *static_cast (nullptr); @@ -334,11 +334,11 @@ public: { using namespace detail::SocketWrapperMemberChecks; return lowest_layer_ptr (type_name, - EnableIf ::value> ()); + Enabled > ()); } void* lowest_layer_ptr (char const* type_name, - boost::true_type) const + TrueType) const { char const* const name (typeid (typename this_layer_type::lowest_layer_type).name ()); if (strcmp (name, type_name) == 0) @@ -347,7 +347,7 @@ public: } void* lowest_layer_ptr (char const*, - boost::false_type) const + FalseType) const { pure_virtual_called (__FILE__, __LINE__); return nullptr; @@ -359,18 +359,18 @@ public: { using namespace detail::SocketWrapperMemberChecks; return cancel (ec, - EnableIf ::value> ()); + Enabled > ()); } error_code cancel (error_code& ec, - boost::true_type) + TrueType) { return m_object.cancel (ec); } error_code cancel (error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -381,19 +381,19 @@ public: { using namespace detail::SocketWrapperMemberChecks; return shutdown (what, ec, - EnableIf ::value> ()); + Enabled > ()); } error_code shutdown (shutdown_type what, error_code& ec, - boost::true_type) + TrueType) { return m_object.shutdown (what, ec); } error_code shutdown (shutdown_type, error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -404,18 +404,18 @@ public: { using namespace detail::SocketWrapperMemberChecks; return close (ec, - EnableIf ::value> ()); + Enabled > ()); } error_code close (error_code& ec, - boost::true_type) + TrueType) { return m_object.close (ec); } error_code close (error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -430,12 +430,12 @@ public: using namespace detail::SocketWrapperMemberChecks; typedef typename native_socket ::socket_type socket_type; return accept (peer, ec, - EnableIf ::value> ()); + Enabled > ()); } error_code accept (Socket& peer, error_code& ec, - boost::true_type) + TrueType) { using namespace detail::SocketWrapperMemberChecks; return m_object.accept ( @@ -443,7 +443,7 @@ public: } error_code accept (Socket&, error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -455,12 +455,12 @@ public: using namespace detail::SocketWrapperMemberChecks; typedef typename native_socket ::socket_type socket_type; async_accept (peer, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler), - EnableIf ::value> ()); + Enabled > ()); } void async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::true_type) + TrueType) { using namespace detail::SocketWrapperMemberChecks; m_object.async_accept ( @@ -469,7 +469,7 @@ public: } void async_accept (Socket&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::false_type) + FalseType) { get_io_service ().wrap ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)) @@ -485,20 +485,20 @@ public: { using namespace detail::SocketWrapperMemberChecks; return read_some (buffers, ec, - EnableIf ::value> ()); + Enabled > ()); } template std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec, - boost::true_type) + TrueType) { return m_object.read_some (buffers, ec); } template std::size_t read_some (MutableBufferSequence const&, error_code& ec, - boost::false_type) + FalseType) { pure_virtual_called (__FILE__, __LINE__); ec = pure_virtual_error (); @@ -511,20 +511,20 @@ public: { using namespace detail::SocketWrapperMemberChecks; return write_some (buffers, ec, - EnableIf ::value> ()); + Enabled > ()); } template std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec, - boost::true_type) + TrueType) { return m_object.write_some (buffers, ec); } template std::size_t write_some (ConstBufferSequence const&, error_code& ec, - boost::false_type) + FalseType) { pure_virtual_called (__FILE__, __LINE__); ec = pure_virtual_error (); @@ -537,13 +537,13 @@ public: { using namespace detail::SocketWrapperMemberChecks; async_read_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler), - EnableIf ::value> ()); + Enabled > ()); } void async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::true_type) + TrueType) { m_object.async_read_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)); @@ -551,7 +551,7 @@ public: void async_read_some (MutableBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::false_type) + FalseType) { get_io_service ().wrap ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)) @@ -564,13 +564,13 @@ public: { using namespace detail::SocketWrapperMemberChecks; async_write_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler), - EnableIf ::value> ()); + Enabled > ()); } void async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::true_type) + TrueType) { m_object.async_write_some (buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)); @@ -578,7 +578,7 @@ public: void async_write_some (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::false_type) + FalseType) { get_io_service ().wrap ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)) @@ -624,11 +624,11 @@ public: { using namespace detail::SocketWrapperMemberChecks; return next_layer_ptr (type_name, - EnableIf ::value> ()); + Enabled > ()); } void* next_layer_ptr (char const* type_name, - boost::true_type) const + TrueType) const { char const* const name (typeid (typename this_layer_type::next_layer_type).name ()); if (strcmp (name, type_name) == 0) @@ -637,7 +637,7 @@ public: } void* next_layer_ptr (char const*, - boost::false_type) const + FalseType) const { pure_virtual_called (__FILE__, __LINE__); return nullptr; @@ -661,19 +661,19 @@ public: { using namespace detail::SocketWrapperMemberChecks; set_verify_mode (verify_mode, - EnableIf ::value> ()); + Enabled > ()); } void set_verify_mode (int verify_mode, - boost::true_type) + TrueType) { m_object.set_verify_mode (verify_mode); } void set_verify_mode (int, - boost::false_type) + FalseType) { pure_virtual_called (__FILE__, __LINE__); } @@ -684,18 +684,18 @@ public: { using namespace detail::SocketWrapperMemberChecks; return handshake (type, ec, - EnableIf ::value> ()); + Enabled > ()); } error_code handshake (handshake_type type, error_code& ec, - boost::true_type) + TrueType) { return m_object.handshake (type, ec); } error_code handshake (handshake_type, error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -706,20 +706,20 @@ public: { using namespace detail::SocketWrapperMemberChecks; async_handshake (type, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler), - EnableIf ::value> ()); + Enabled > ()); } void async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::true_type) + TrueType) { m_object.async_handshake (type, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)); } void async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::false_type) + FalseType) { get_io_service ().wrap ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)) @@ -735,19 +735,19 @@ public: { using namespace detail::SocketWrapperMemberChecks; return handshake (type, buffers, ec, - EnableIf ::value> ()); + Enabled > ()); } error_code handshake (handshake_type type, ConstBuffers const& buffers, error_code& ec, - boost::true_type) + TrueType) { return m_object.handshake (type, buffers, ec); } error_code handshake (handshake_type, ConstBuffers const&, error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -760,14 +760,14 @@ public: using namespace detail::SocketWrapperMemberChecks; async_handshake (type, buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler), - EnableIf ::value> ()); + BOOST_ASIO_MOVE_ARG(SharedHandlerPtr))> > ()); } void async_handshake (handshake_type type, ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::true_type) + TrueType) { m_object.async_handshake (type, buffers, BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)); @@ -775,7 +775,7 @@ public: void async_handshake (handshake_type, ConstBuffers const&, BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::false_type) + FalseType) { get_io_service ().wrap ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)) @@ -790,18 +790,18 @@ public: { using namespace detail::SocketWrapperMemberChecks; return shutdown (ec, - EnableIf ::value> ()); + Enabled > ()); } error_code shutdown (error_code& ec, - boost::true_type) + TrueType) { return m_object.shutdown (ec); } error_code shutdown (error_code& ec, - boost::false_type) + FalseType) { return pure_virtual_error (ec, __FILE__, __LINE__); } @@ -812,19 +812,19 @@ public: { using namespace detail::SocketWrapperMemberChecks; async_shutdown (BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler), - EnableIf ::value> ()); + Enabled > ()); } void async_shutdown (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::true_type) + TrueType) { m_object.async_shutdown ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)); } void async_shutdown (BOOST_ASIO_MOVE_ARG(SharedHandlerPtr) handler, - boost::false_type) + FalseType) { get_io_service ().wrap ( BOOST_ASIO_MOVE_CAST(SharedHandlerPtr)(handler)) diff --git a/modules/beast_core/beast_core.cpp b/modules/beast_core/beast_core.cpp index e837f976d7..8608e180d1 100644 --- a/modules/beast_core/beast_core.cpp +++ b/modules/beast_core/beast_core.cpp @@ -21,21 +21,12 @@ */ //============================================================================== -#if defined BEAST_CORE_H_INCLUDED - /* When you add this cpp file to your project, you mustn't include it in a file where you've - already included any other headers - just put it inside a file on its own, possibly with your config - flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix - header files that the compiler may be using. - */ - #error "Incorrect use of BEAST cpp file" -#endif - // Your project must contain a BeastConfig.h file with your project-specific settings in it, // and your header search path must make it accessible to the module's files. #include "BeastConfig.h" //============================================================================== -#include "native/beast_BasicNativeHeaders.h" +#include "native/BasicNativeHeaders.h" #include "beast_core.h" #include @@ -138,170 +129,155 @@ namespace beast { -#include "containers/beast_AbstractFifo.cpp" -#include "containers/beast_DynamicObject.cpp" -#include "containers/beast_NamedValueSet.cpp" -#include "containers/beast_PropertySet.cpp" -#include "containers/beast_Variant.cpp" -#include "containers/DynamicArray.cpp" -#include "containers/DynamicList.cpp" -#include "containers/HashMap.cpp" +#include "containers/AbstractFifo.cpp" +#include "containers/DynamicObject.cpp" +#include "containers/NamedValueSet.cpp" +#include "containers/PropertySet.cpp" +#include "containers/Variant.cpp" -#include "diagnostic/beast_Debug.cpp" -#include "diagnostic/beast_Error.cpp" -#include "diagnostic/beast_FatalError.cpp" -#include "diagnostic/beast_FPUFlags.cpp" -#include "diagnostic/beast_LeakChecked.cpp" -#include "diagnostic/beast_ProtectedCall.cpp" -#include "diagnostic/beast_SemanticVersion.cpp" -#include "diagnostic/beast_UnitTest.cpp" -#include "diagnostic/beast_UnitTestUtilities.cpp" +#include "diagnostic/FatalError.cpp" +#include "diagnostic/FPUFlags.cpp" +#include "diagnostic/SemanticVersion.cpp" +#include "diagnostic/UnitTest.cpp" +#include "diagnostic/UnitTestUtilities.cpp" -#include "files/beast_DirectoryIterator.cpp" -#include "files/beast_File.cpp" -#include "files/beast_FileInputStream.cpp" -#include "files/beast_FileOutputStream.cpp" -#include "files/beast_FileSearchPath.cpp" -#include "files/beast_RandomAccessFile.cpp" -#include "files/beast_TemporaryFile.cpp" +#include "files/DirectoryIterator.cpp" +#include "files/File.cpp" +#include "files/FileInputStream.cpp" +#include "files/FileOutputStream.cpp" +#include "files/FileSearchPath.cpp" +#include "files/RandomAccessFile.cpp" +#include "files/TemporaryFile.cpp" -#include "json/beast_JSON.cpp" +#include "json/JSON.cpp" -#include "logging/beast_FileLogger.cpp" -#include "logging/beast_Logger.cpp" +#include "logging/FileLogger.cpp" +#include "logging/Logger.cpp" -#include "maths/beast_BigInteger.cpp" -#include "maths/beast_Expression.cpp" -#include "maths/beast_MurmurHash.cpp" -#include "maths/beast_Random.cpp" +#include "maths/BigInteger.cpp" +#include "maths/Expression.cpp" +#include "maths/MurmurHash.cpp" +#include "maths/Random.cpp" -#include "memory/beast_MemoryBlock.cpp" -#include "memory/beast_FifoFreeStoreWithTLS.cpp" -#include "memory/beast_FifoFreeStoreWithoutTLS.cpp" -#include "memory/beast_GlobalPagedFreeStore.cpp" -#include "memory/beast_PagedFreeStore.cpp" +#include "memory/MemoryBlock.cpp" -#include "misc/beast_Main.cpp" -#include "misc/beast_Result.cpp" -#include "misc/beast_Uuid.cpp" +#include "misc/Main.cpp" +#include "misc/Result.cpp" +#include "misc/Uuid.cpp" -#include "network/beast_MACAddress.cpp" -#include "network/beast_NamedPipe.cpp" -#include "network/beast_Socket.cpp" -#include "network/beast_URL.cpp" -#include "network/beast_IPAddress.cpp" +#include "network/MACAddress.cpp" +#include "network/NamedPipe.cpp" +#include "network/Socket.cpp" +#include "network/IPAddress.cpp" -#include "streams/beast_BufferedInputStream.cpp" -#include "streams/beast_FileInputSource.cpp" -#include "streams/beast_InputStream.cpp" -#include "streams/beast_MemoryInputStream.cpp" -#include "streams/beast_MemoryOutputStream.cpp" -#include "streams/beast_OutputStream.cpp" -#include "streams/beast_SubregionStream.cpp" +#include "streams/BufferedInputStream.cpp" +#include "streams/FileInputSource.cpp" +#include "streams/InputStream.cpp" +#include "streams/MemoryInputStream.cpp" +#include "streams/MemoryOutputStream.cpp" +#include "streams/OutputStream.cpp" +#include "streams/SubregionStream.cpp" #include "system/SystemStats.cpp" -#include "text/beast_CharacterFunctions.cpp" -#include "text/beast_LexicalCast.cpp" -#include "text/beast_Identifier.cpp" -#include "text/beast_LocalisedStrings.cpp" -#include "text/beast_String.cpp" -#include "text/beast_StringArray.cpp" -#include "text/beast_StringPairArray.cpp" -#include "text/beast_StringPool.cpp" -#include "text/beast_TextDiff.cpp" +#include "text/LexicalCast.cpp" +#include "text/Identifier.cpp" +#include "text/LocalisedStrings.cpp" +#include "text/StringArray.cpp" +#include "text/StringPairArray.cpp" +#include "text/StringPool.cpp" +#include "text/TextDiff.cpp" #include "thread/impl/TrackedMutex.cpp" -#include "thread/beast_DeadlineTimer.cpp" -#include "thread/beast_InterruptibleThread.cpp" -#include "thread/beast_Semaphore.cpp" -#include "thread/beast_CallQueue.cpp" -#include "thread/beast_Listeners.cpp" -#include "thread/beast_ManualCallQueue.cpp" -#include "thread/beast_ParallelFor.cpp" -#include "thread/beast_ThreadGroup.cpp" -#include "thread/beast_ThreadWithCallQueue.cpp" -#include "thread/beast_Workers.cpp" +#include "thread/DeadlineTimer.cpp" +#include "thread/Semaphore.cpp" +#include "thread/Workers.cpp" -#include "threads/beast_ChildProcess.cpp" -#include "threads/beast_ReadWriteLock.cpp" -#include "threads/beast_ReadWriteMutex.cpp" -#include "threads/beast_SpinDelay.cpp" -#include "threads/beast_Thread.cpp" -#include "threads/beast_ThreadPool.cpp" -#include "threads/beast_TimeSliceThread.cpp" +#include "threads/ChildProcess.cpp" +#include "threads/ReadWriteLock.cpp" +#include "threads/SpinDelay.cpp" -#include "time/beast_PerformanceCounter.cpp" -#include "time/beast_PerformedAtExit.cpp" -#include "time/beast_RelativeTime.cpp" -#include "time/beast_Time.cpp" +#include "time/PerformanceCounter.cpp" +#include "time/AtExitHook.cpp" +#include "time/Time.cpp" -#include "xml/beast_XmlDocument.cpp" -#include "xml/beast_XmlElement.cpp" +#include "xml/XmlDocument.cpp" +#include "xml/XmlElement.cpp" -#include "zip/beast_GZIPDecompressorInputStream.cpp" -#include "zip/beast_GZIPCompressorOutputStream.cpp" -#include "zip/beast_ZipFile.cpp" +#include "zip/GZIPDecompressorInputStream.cpp" +#include "zip/GZIPCompressorOutputStream.cpp" +#include "zip/ZipFile.cpp" #if BEAST_MAC || BEAST_IOS -#include "native/beast_osx_ObjCHelpers.h" +#include "native/osx_ObjCHelpers.h" #endif #if BEAST_WINDOWS -#include "native/beast_win32_FPUFlags.cpp" +#include "native/win32_FPUFlags.cpp" #else -#include "native/beast_posix_FPUFlags.cpp" +#include "native/posix_FPUFlags.cpp" #endif #if BEAST_ANDROID -#include "native/beast_android_JNIHelpers.h" +#include "native/android_JNIHelpers.h" #endif #if ! BEAST_WINDOWS -#include "native/beast_posix_SharedCode.h" -#include "native/beast_posix_NamedPipe.cpp" +#include "native/posix_SharedCode.h" +#include "native/posix_NamedPipe.cpp" #endif #if BEAST_MAC || BEAST_IOS -#include "native/beast_mac_Files.mm" -#include "native/beast_mac_Network.mm" -#include "native/beast_mac_Strings.mm" -#include "native/beast_mac_SystemStats.mm" -#include "native/beast_mac_Threads.mm" +#include "native/mac_Files.mm" +#include "native/mac_Network.mm" +#include "native/mac_Strings.mm" +#include "native/mac_SystemStats.mm" +#include "native/mac_Threads.mm" #elif BEAST_WINDOWS -#include "native/beast_win32_ComSmartPtr.h" -#include "native/beast_win32_Files.cpp" -#include "native/beast_win32_Network.cpp" -#include "native/beast_win32_Registry.cpp" -#include "native/beast_win32_SystemStats.cpp" -#include "native/beast_win32_Threads.cpp" +#include "native/win32_ComSmartPtr.h" +#include "native/win32_Files.cpp" +#include "native/win32_Network.cpp" +#include "native/win32_Registry.cpp" +#include "native/win32_SystemStats.cpp" +#include "native/win32_Threads.cpp" #elif BEAST_LINUX -#include "native/beast_linux_Files.cpp" -#include "native/beast_linux_Network.cpp" -#include "native/beast_linux_SystemStats.cpp" -#include "native/beast_linux_Threads.cpp" +#include "native/linux_Files.cpp" +#include "native/linux_Network.cpp" +#include "native/linux_SystemStats.cpp" +#include "native/linux_Threads.cpp" #elif BEAST_BSD -#include "native/beast_bsd_Files.cpp" -#include "native/beast_bsd_Network.cpp" -#include "native/beast_bsd_SystemStats.cpp" -#include "native/beast_bsd_Threads.cpp" +#include "native/bsd_Files.cpp" +#include "native/bsd_Network.cpp" +#include "native/bsd_SystemStats.cpp" +#include "native/bsd_Threads.cpp" #elif BEAST_ANDROID -#include "native/beast_android_Files.cpp" -#include "native/beast_android_Misc.cpp" -#include "native/beast_android_Network.cpp" -#include "native/beast_android_SystemStats.cpp" -#include "native/beast_android_Threads.cpp" +#include "native/android_Files.cpp" +#include "native/android_Misc.cpp" +#include "native/android_Network.cpp" +#include "native/android_SystemStats.cpp" +#include "native/android_Threads.cpp" #endif -#include "threads/beast_HighResolutionTimer.cpp" +#include "threads/HighResolutionTimer.cpp" } +// Has to be outside the beast namespace +extern "C" { +void beast_reportFatalError (char const* message, char const* fileName, int lineNumber) +{ + if (beast::beast_isRunningUnderDebugger()) + beast_breakDebugger; + beast::FatalError (message, fileName, lineNumber); + BEAST_ANALYZER_NORETURN +} +} + #ifdef _CRTDBG_MAP_ALLOC #pragma pop_macro("calloc") #pragma pop_macro("free") @@ -320,5 +296,21 @@ namespace beast //------------------------------------------------------------------------------ +// When we compile the static library, which is really just for browsing the +// sources in the Visual Studio IDE, we want to compile each individual unity +// .cpp in order to make sure that it builds by itself. An application that +// uses beast will typically include all of these .cpp files in one of its +// own unity .cpp +#if ! BEAST_COMPILING_STATIC_LIBARARY +/* +#include "../../beast/chrono/Chrono.cpp" +#include "../../beast/crypto/Crypto.cpp" +#include "../../beast/http/HTTP.cpp" +#include "../../beast/net/Net.cpp" +#include "../../beast/strings/Strings.cpp" +#include "../../beast/utility/Utility.cpp" +*/ +#endif + // Must be outside the namespace #include "system/BoostPlaceholdersFix.cpp" diff --git a/modules/beast_core/beast_core.h b/modules/beast_core/beast_core.h index 1e0e7a0527..fff039ba9f 100644 --- a/modules/beast_core/beast_core.h +++ b/modules/beast_core/beast_core.h @@ -24,160 +24,14 @@ #ifndef BEAST_CORE_H_INCLUDED #define BEAST_CORE_H_INCLUDED -//------------------------------------------------------------------------------ -/** - -@mainpage Beast: A C++ library for peer to peer and client server development. - -### Version 1.0 - -Copyright 2008, 2013 by Vinnie Falco \ ([e-mail][0]) - -Beast is a source code collection of individual modules containing -functionality for a variety of applications, with an emphasis on building -concurrent systems. Beast incorporates parts of [JUCE][3] (Jules' Utility -Class Extensions), available from [Raw Material Software][4]. Beast has no -external dependencies - -Beast is hosted on Github at [https://github.com/vinniefalco/Beast][1] - -The online documentation is at [http://vinniefalco.github.com/Beast][2] - -## Platforms - -All platforms supported by JUCE are also supported by Beast. Currently these -platforms include: - -- **Windows**: Applications and VST/RTAS/NPAPI/ActiveX plugins can be built -using MS Visual Studio. The results are all fully compatible with Windows -XP, Vista or Windows 7. - -- **Mac OS X**: Applications and VST/AudioUnit/RTAS/NPAPI plugins with Xcode. - -- **GNU/Linux**: Applications and plugins can be built for any kernel 2.6 or -later. - -- **FreeBSD**: Kernel version 8.4 or higher required. - -- **iOS**: Native iPhone and iPad apps. - -- **Android**: Supported. - -## Prerequisites - -This documentation assumes that the reader has a working knowledge of JUCE. -Some modules built on external libraries assume that the reader understands -the operation of those external libraries. Certain modules assume that the -reader understands additional domain-specific information. Modules with -additional prerequisites are marked in the documentation. - -## External Modules - -Some modules bring in functionality provided by external libraries. For -example, the @ref beast_bzip2 module provides the compression and decompression -algorithms in [bZip2][7]. Usage of these external library modules is optional. -They come with complete source code, as well as options for using either -system or user provided variants of the external libraries: it is not -necessary to download additional source code packages to use these modules. - -External code incorporated into Beast is covered by separate licenses. See -the licensing information and notes in the corresponding source files for -copyright information and terms of use. - -## Integration - -Beast requires recent versions of JUCE. It won't work with versions 1.53 or -earlier. To use the library it is necessary to first download JUCE to a -location where your development environment can find it. Or, you can use your -existing installation of JUCE. - -This library uses the same modularized organizational structure as JUCE. To -use a module, first add a path to the list of includes searched by your -development environment or project, which points to the Beast directory. Then, -add the single corresponding .c or .cpp file to your existing project which -already uses JUCE. For example, to use the @ref beast_core module, add the file -beast_core.cpp to your project. Some modules depend on other modules. - -To use a module, include the appropriate header from within your source code. -For example, to access classes in the @ref beast_concurrent module, use this: - -@code - -#include "modules/beast_concurrent/beast_concurrent.h" - -@endcode - -Then add the corresponding file beast_concurrent.cpp to your build. - -## AppConfig - -Some Beast features can be controlled at compilation time through -preprocessor directives. The available choices of compilation options are -described in AppConfig.h, located in the AppConfigTemplate directory. Copy -the provided settings into your existing AppConfig.h (a file used by JUCE -convention). - -## License - -This library contains portions of other open source products covered by -separate licenses. Please see the corresponding source files for specific -terms. - -Beast is provided under the terms of The ISC License: - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Some files contain portions of these external projects, licensed separately: - -- [bZip2][7] is Copyright (C) 1996-2010 Julian R Seward. All rights - reserved. See the corresponding file LICENSE for licensing terms. - -- [Soci][13] is Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton, and - various others noted in the corresponding source files. Soci is distributed - under the [Boost Software License, Version 1.0][14]. - -- [SQLite][15], placed in the public domain. - -[0]: mailto:vinnie.falco@gmail.com "Vinnie Falco (Email)" -[1]: https://github.com/vinniefalco/Beast "Beast Project" -[2]: http://vinniefalco.github.com/Beast/ "Beast Documentation" -[3]: http://rawmaterialsoftware.com/juce.php "JUCE" -[4]: http://rawmaterialsoftware.com/ "Raw Material Software" -[5]: http://www.gnu.org/licenses/gpl-2.0.html "GNU General Public License, version 2" -[6]: http://rawmaterialsoftware.com/jucelicense.php "JUCE Licenses" -[7]: http://www.bzip.org/ "bZip2: Home" -[8]: http://freetype.org/ "The FreeType Project" -[9]: http://www.freetype.org/FTL.TXT "The FreeType Project License" -[10]: http://www.lua.org/ "The Programming Language Lua" -[11]: http://opensource.org/licenses/ISC "The ISC License" -[12]: https://github.com/vinniefalco/LuaBridge -[13]: http://soci.sourceforge.net/ "SOCI" -[14]: http://www.boost.org/LICENSE_1_0.txt "Boost Software License, Version 1.0" -[15]: http://sqlite.org/ "SQLite Home Page" -[16]: http://developer.kde.org/~wheeler/taglib.html "TagLib" -[17]: http://www.gnu.org/licenses/lgpl-2.1.html "Gnu Lesser General Public License, version 2.1" -[18]: http://www.mozilla.org/MPL/1.1/ "Mozilla Public License" - -@copyright Copyright 2008-2013 by Vinnie Falco \ ([e-mail][0]) -@copyright Provided under the [ISC LIcense][11] -*/ +// TargetPlatform.h should not use anything from BeastConfig.h +#include "../../beast/Config.h" +#include "../../beast/config/ContractChecks.h" # include "system/BeforeBoost.h" # include "system/BoostIncludes.h" #include "system/FunctionalIncludes.h" -#include "system/StandardHeader.h" - #if BEAST_MSVC # pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state) # pragma warning (push) @@ -187,6 +41,53 @@ Some files contain portions of these external projects, licensed separately: # endif #endif +//------------------------------------------------------------------------------ + +// New header-only library modeled more closely according to boost +#include "../../beast/CStdInt.h" +#include "../../beast/SmartPtr.h" +#include "../../beast/StaticAssert.h" +#include "../../beast/Uncopyable.h" +#include "../../beast/Atomic.h" +#include "../../beast/Arithmetic.h" +#include "../../beast/ByteOrder.h" +#include "../../beast/HeapBlock.h" +#include "../../beast/Memory.h" +#include "../../beast/Intrusive.h" +#include "../../beast/Net.h" +#include "../../beast/SafeBool.h" +#include "../../beast/Strings.h" +#include "../../beast/TypeTraits.h" +#include "../../beast/Threads.h" +#include "../../beast/Utility.h" +#include "../../beast/Chrono.h" + +#include "system/StandardIncludes.h" + +namespace beast { + +class InputStream; +class OutputStream; +class FileInputStream; +class FileOutputStream; + +// Order matters, since headers don't have their own #include lines. +// Add new includes to the bottom. + +#include "diagnostic/Throw.h" +#include "system/Functional.h" +#include "memory/AtomicCounter.h" +#include "memory/AtomicFlag.h" +#include "memory/AtomicPointer.h" +#include "memory/AtomicState.h" +#include "threads/SpinDelay.h" + +#include "time/AtExitHook.h" +#include "time/Time.h" +#include "threads/ScopedLock.h" +#include "threads/CriticalSection.h" +#include "containers/ElementComparator.h" + // If the MSVC debug heap headers were included, disable // the macros during the juce include since they conflict. #ifdef _CRTDBG_MAP_ALLOC @@ -217,219 +118,7 @@ Some files contain portions of these external projects, licensed separately: #undef _aligned_offset_recalloc #undef _aligned_msize #endif - -//------------------------------------------------------------------------------ - -// New header-only library modeled more closely according to boost -#include "../../beast/intrusive/ForwardList.h" - -//------------------------------------------------------------------------------ - -namespace beast -{ - -class InputStream; -class OutputStream; -class FileInputStream; -class FileOutputStream; - -extern BEAST_API bool BEAST_CALLTYPE beast_isRunningUnderDebugger(); -extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) noexcept; - -// Order matters, since headers don't have their own #include lines. -// Add new includes to the bottom. - -#include "diagnostic/ContractChecks.h" -#include "memory/beast_Uncopyable.h" -#include "memory/beast_Memory.h" -#include "maths/beast_MathsFunctions.h" -#include "memory/beast_ByteOrder.h" -#include "memory/beast_Atomic.h" -#include "text/beast_CharacterFunctions.h" - -#if BEAST_MSVC -# pragma warning (push) -# pragma warning (disable: 4514 4996) -#endif -#include "text/beast_CharPointer_UTF8.h" -#include "text/beast_CharPointer_UTF16.h" -#include "text/beast_CharPointer_UTF32.h" -#include "text/beast_CharPointer_ASCII.h" -#if BEAST_MSVC -# pragma warning (pop) -#endif - -# include "containers/detail/removecv.h" -#include "containers/detail/copyconst.h" -#include "system/PlatformDefs.h" -#include "system/TargetPlatform.h" -#include "diagnostic/beast_Throw.h" -#include "system/Functional.h" -#include "memory/beast_AtomicCounter.h" -#include "memory/beast_AtomicFlag.h" -#include "memory/beast_AtomicPointer.h" -#include "memory/beast_AtomicState.h" -#include "containers/List.h" -#include "containers/beast_LockFreeStack.h" -#include "threads/beast_SpinDelay.h" -#include "memory/beast_StaticObject.h" - -#include "text/StringCharPointerType.h" -#include "text/StringFromNumber.h" -#include "text/beast_String.h" -#include "time/beast_PerformedAtExit.h" -#include "diagnostic/beast_LeakChecked.h" -#include "time/beast_RelativeTime.h" -#include "time/beast_Time.h" -#include "memory/beast_HeapBlock.h" -#include "threads/beast_ScopedLock.h" -#include "threads/beast_CriticalSection.h" -#include "containers/beast_ElementComparator.h" -#include "containers/beast_ArrayAllocationBase.h" -#include "containers/beast_Array.h" -#include "misc/beast_Result.h" -#include "text/beast_StringArray.h" -#include "memory/beast_MemoryBlock.h" -#include "files/beast_File.h" -#include "time/beast_PerformanceCounter.h" - -#include "memory/beast_MemoryAlignment.h" -#include "memory/beast_CacheLine.h" -#include "threads/beast_ReadWriteMutex.h" -#include "threads/beast_SharedData.h" -#include "diagnostic/beast_SafeBool.h" -#include "threads/beast_WaitableEvent.h" -#include "threads/beast_Thread.h" -#include "threads/beast_SpinLock.h" -#include "threads/beast_ThreadLocalValue.h" -#include "thread/MutexTraits.h" -#include "thread/TrackedMutex.h" -#include "diagnostic/beast_FatalError.h" -#include "diagnostic/beast_Error.h" -#include "diagnostic/beast_Debug.h" -#include "text/beast_LexicalCast.h" -#include "memory/beast_ContainerDeletePolicy.h" -#include "memory/beast_ByteSwap.h" -#include "maths/beast_Math.h" -#include "maths/beast_uint24.h" -#include "logging/beast_Logger.h" -#include "diagnostic/beast_FPUFlags.h" -#include "memory/SharedObject.h" -#include "memory/SharedPtr.h" -#include "functional/SharedFunction.h" -#include "diagnostic/beast_ProtectedCall.h" -#include "containers/beast_AbstractFifo.h" -#include "text/beast_Identifier.h" -#include "containers/beast_Variant.h" -#include "containers/beast_LinkedListPointer.h" -#include "containers/beast_NamedValueSet.h" -#include "containers/beast_DynamicObject.h" -#include "maths/beast_BigInteger.h" -#include "maths/beast_Random.h" -#include "containers/beast_LockFreeQueue.h" -#include "containers/beast_OwnedArray.h" -#include "text/beast_StringPairArray.h" -#include "containers/beast_PropertySet.h" -#include "containers/beast_SharedObjectArray.h" -#include "containers/beast_ScopedValueSetter.h" -#include "containers/beast_SharedTable.h" -#include "containers/beast_SortedLookupTable.h" -#include "containers/beast_SortedSet.h" -#include "maths/beast_Range.h" -#include "containers/beast_SparseSet.h" -# include "containers/DynamicList.h" -# include "containers/DynamicArray.h" -#include "containers/HashMap.h" -#include "memory/beast_ScopedPointer.h" -#include "files/beast_DirectoryIterator.h" -#include "streams/beast_InputStream.h" -#include "files/beast_FileInputStream.h" -#include "streams/beast_InputSource.h" -#include "streams/beast_FileInputSource.h" -#include "text/beast_NewLine.h" -#include "streams/beast_OutputStream.h" -#include "files/beast_FileOutputStream.h" -#include "files/beast_FileSearchPath.h" -#include "files/beast_MemoryMappedFile.h" -#include "files/beast_RandomAccessFile.h" -#include "files/beast_TemporaryFile.h" -#include "json/beast_JSON.h" -#include "logging/beast_FileLogger.h" -#include "logging/beast_Logger.h" -#include "maths/beast_Expression.h" -#include "maths/beast_Interval.h" -#include "maths/beast_MathsFunctions.h" -#include "maths/beast_MurmurHash.h" -#include "memory/beast_ByteOrder.h" -#include "memory/beast_Memory.h" -#include "memory/beast_OptionalScopedPointer.h" -#include "memory/beast_SharedSingleton.h" -#include "memory/beast_WeakReference.h" -#include "memory/beast_RecycledObjectPool.h" -#include "misc/beast_Main.h" -#include "misc/beast_Uuid.h" -#include "misc/beast_WindowsRegistry.h" -#include "network/beast_IPAddress.h" -#include "network/beast_MACAddress.h" -#include "threads/beast_ReadWriteLock.h" -#include "network/beast_NamedPipe.h" -#include "network/beast_Socket.h" -#include "network/beast_URL.h" -#include "streams/beast_BufferedInputStream.h" -#include "streams/beast_MemoryInputStream.h" -#include "streams/beast_MemoryOutputStream.h" -#include "streams/beast_SubregionStream.h" - -#include "system/SystemStats.h" -#include "text/beast_LocalisedStrings.h" -#include "diagnostic/beast_SemanticVersion.h" -#include "text/beast_StringPool.h" -#include "text/beast_TextDiff.h" -#include "threads/beast_ChildProcess.h" -#include "threads/beast_DynamicLibrary.h" -#include "threads/beast_HighResolutionTimer.h" -#include "threads/beast_InterProcessLock.h" -#include "threads/beast_Process.h" -#include "threads/beast_ScopedReadLock.h" -#include "threads/beast_ScopedWriteLock.h" -#include "threads/beast_ThreadPool.h" -#include "threads/beast_TimeSliceThread.h" -#include "diagnostic/beast_UnitTest.h" -#include "xml/beast_XmlDocument.h" -#include "xml/beast_XmlElement.h" -#include "diagnostic/beast_UnitTestUtilities.h" -#include "zip/beast_GZIPCompressorOutputStream.h" -#include "zip/beast_GZIPDecompressorInputStream.h" -#include "zip/beast_ZipFile.h" - -#include "diagnostic/MeasureFunctionCallTime.h" - -#include "functional/beast_Function.h" - -#include "thread/beast_DeadlineTimer.h" - -#include "memory/beast_AllocatedBy.h" -#include "memory/beast_PagedFreeStore.h" -#include "memory/beast_GlobalPagedFreeStore.h" -#include "memory/beast_FifoFreeStoreWithTLS.h" -#include "memory/beast_FifoFreeStoreWithoutTLS.h" -#include "memory/beast_FifoFreeStore.h" -#include "memory/beast_GlobalFifoFreeStore.h" - -#include "thread/beast_Semaphore.h" -#include "thread/beast_SerialFor.h" -#include "thread/beast_InterruptibleThread.h" -#include "thread/beast_ThreadGroup.h" -#include "thread/beast_CallQueue.h" -#include "thread/beast_GlobalThreadGroup.h" -#include "thread/beast_Listeners.h" -#include "thread/beast_ManualCallQueue.h" -#include "thread/beast_ParallelFor.h" -#include "thread/beast_ThreadWithCallQueue.h" -#include "thread/beast_Workers.h" - -} - +#include "containers/ArrayAllocationBase.h" #ifdef _CRTDBG_MAP_ALLOC #pragma pop_macro("_aligned_msize") #pragma pop_macro("_aligned_offset_recalloc") @@ -446,6 +135,105 @@ extern BEAST_API void BEAST_CALLTYPE logAssertion (char const* file, int line) n #pragma pop_macro("calloc") #endif +#include "containers/Array.h" + +#include "misc/Result.h" +#include "text/StringArray.h" +#include "memory/MemoryBlock.h" +#include "files/File.h" +#include "time/PerformanceCounter.h" + +#include "memory/MemoryAlignment.h" +#include "memory/CacheLine.h" +#include "thread/MutexTraits.h" +#include "thread/TrackedMutex.h" +#include "diagnostic/FatalError.h" +#include "text/LexicalCast.h" +#include "maths/Math.h" +#include "maths/uint24.h" +#include "logging/Logger.h" +#include "diagnostic/FPUFlags.h" +#include "memory/SharedFunction.h" +#include "containers/AbstractFifo.h" +#include "text/Identifier.h" +#include "containers/Variant.h" +#include "containers/LinkedListPointer.h" +#include "containers/NamedValueSet.h" +#include "containers/DynamicObject.h" +#include "maths/BigInteger.h" +#include "maths/Random.h" +#include "containers/LockFreeQueue.h" +#include "containers/OwnedArray.h" +#include "text/StringPairArray.h" +#include "containers/PropertySet.h" +#include "containers/SharedObjectArray.h" +#include "containers/ScopedValueSetter.h" +#include "containers/SortedSet.h" +#include "maths/Range.h" +#include "containers/SparseSet.h" +#include "files/DirectoryIterator.h" +#include "streams/InputStream.h" +#include "files/FileInputStream.h" +#include "streams/InputSource.h" +#include "streams/FileInputSource.h" +#include "streams/OutputStream.h" +#include "files/FileOutputStream.h" +#include "files/FileSearchPath.h" +#include "files/MemoryMappedFile.h" +#include "files/RandomAccessFile.h" +#include "files/TemporaryFile.h" +#include "json/JSON.h" +#include "logging/FileLogger.h" +#include "logging/Logger.h" +#include "maths/Expression.h" +#include "maths/Interval.h" +#include "maths/MurmurHash.h" +#include "memory/OptionalScopedPointer.h" +#include "memory/SharedSingleton.h" +#include "memory/WeakReference.h" +#include "memory/RecycledObjectPool.h" +#include "misc/Main.h" +#include "misc/Uuid.h" +#include "misc/WindowsRegistry.h" +#include "network/IPAddress.h" +#include "network/MACAddress.h" +#include "threads/ReadWriteLock.h" +#include "network/NamedPipe.h" +#include "network/Socket.h" +#include "streams/BufferedInputStream.h" +#include "streams/MemoryInputStream.h" +#include "streams/MemoryOutputStream.h" +#include "streams/SubregionStream.h" + +#include "system/SystemStats.h" +#include "text/LocalisedStrings.h" +#include "diagnostic/SemanticVersion.h" +#include "text/StringPool.h" +#include "text/TextDiff.h" +#include "threads/ChildProcess.h" +#include "threads/DynamicLibrary.h" +#include "threads/HighResolutionTimer.h" +#include "threads/InterProcessLock.h" +#include "threads/Process.h" +#include "threads/ScopedReadLock.h" +#include "threads/ScopedWriteLock.h" +#include "diagnostic/UnitTest.h" +#include "xml/XmlDocument.h" +#include "xml/XmlElement.h" +#include "diagnostic/UnitTestUtilities.h" +#include "zip/GZIPCompressorOutputStream.h" +#include "zip/GZIPDecompressorInputStream.h" +#include "zip/ZipFile.h" + +#include "diagnostic/MeasureFunctionCallTime.h" + +#include "thread/DeadlineTimer.h" + +#include "thread/Semaphore.h" +#include "thread/Workers.h" + +} + #if BEAST_MSVC #pragma warning (pop) #endif diff --git a/modules/beast_core/containers/beast_AbstractFifo.cpp b/modules/beast_core/containers/AbstractFifo.cpp similarity index 100% rename from modules/beast_core/containers/beast_AbstractFifo.cpp rename to modules/beast_core/containers/AbstractFifo.cpp diff --git a/modules/beast_core/containers/beast_AbstractFifo.h b/modules/beast_core/containers/AbstractFifo.h similarity index 100% rename from modules/beast_core/containers/beast_AbstractFifo.h rename to modules/beast_core/containers/AbstractFifo.h diff --git a/modules/beast_core/containers/beast_Array.h b/modules/beast_core/containers/Array.h similarity index 100% rename from modules/beast_core/containers/beast_Array.h rename to modules/beast_core/containers/Array.h diff --git a/modules/beast_core/containers/beast_ArrayAllocationBase.h b/modules/beast_core/containers/ArrayAllocationBase.h similarity index 100% rename from modules/beast_core/containers/beast_ArrayAllocationBase.h rename to modules/beast_core/containers/ArrayAllocationBase.h diff --git a/modules/beast_core/containers/DynamicArray.cpp b/modules/beast_core/containers/DynamicArray.cpp deleted file mode 100644 index bd67b2c009..0000000000 --- a/modules/beast_core/containers/DynamicArray.cpp +++ /dev/null @@ -1,175 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -class DynamicArrayTests : public UnitTest -{ -public: - struct T - { - T () - { - } - - explicit T (String what) - : msg (what) - { - } - - T& operator= (T const& other) - { - msg = other.msg; - return *this; - } - - String msg; - }; - - enum - { - numberToAssign = 1000 * 1000, - numberToReserve = 1000 * 1000, - numberToMutate = 12139 - - }; - - void testAssign () - { - String s; - s << "assign (" << String::fromNumber (numberToAssign) << ")"; - beginTestCase (s); - - DynamicArray v; - v.assign (numberToAssign); - - pass (); - } - - void testReserve () - { - String s; - s << "reserve (" << String::fromNumber (numberToReserve) << ")"; - beginTestCase (s); - - DynamicArray v; - v.reserve (numberToReserve); - - v.assign (numberToReserve); - - pass (); - } - - void testMutate () - { - String s; - DynamicArray v; - - s = "push_back (" + String::fromNumber (numberToMutate) + ")"; - beginTestCase (s); - for (std::size_t i = 0; i < numberToMutate; ++i) - v.push_back (T (String::fromNumber (i))); - pass (); - - s = "read [] (" + String::fromNumber (numberToMutate) + ")"; - beginTestCase (s); - for (std::size_t i = 0; i < numberToMutate; ++i) - expect (v [i].msg == String::fromNumber (i)); - - s = "write [] (" + String::fromNumber (numberToMutate) + ")"; - beginTestCase (s); - for (std::size_t i = 0; i < numberToMutate; ++i) - v [i].msg = "+" + String::fromNumber (i); - pass (); - - s = "verify [] (" + String::fromNumber (numberToMutate) + ")"; - beginTestCase (s); - for (std::size_t i = 0; i < numberToMutate; ++i) - expect (v [i].msg == String ("+") + String::fromNumber (i)); - } - - void testIterate () - { - typedef DynamicArray V; - - V v; - for (std::size_t i = 0; i < numberToMutate; ++i) - v.push_back (T (String::fromNumber (i))); - - { - int step = 1; - beginTestCase ("iterator"); - V::iterator iter; - for (iter = v.begin (); iter + step < v.end (); iter += step) - { - step ++; - V::difference_type d = iter - v.begin (); - expect (iter->msg == String::fromNumber (d)); - } - } - - { - int step = 1; - beginTestCase ("const_iterator"); - V::const_iterator iter; - for (iter = v.begin (); iter + step < v.end (); iter += step) - { - step ++; - V::difference_type d = iter - v.begin (); - expect (iter->msg == String::fromNumber (d)); - } - } - - { - int step = 1; - beginTestCase ("reverse_iterator"); - V::reverse_iterator iter; - for (iter = v.rbegin (); iter + step < v.rend (); iter += step) - { - step ++; - iter - v.rend (); - } - pass (); - } - - { - int step = 1; - beginTestCase ("const_reverse_iterator"); - V::const_reverse_iterator iter; - for (iter = v.crbegin (); iter + step < v.crend (); iter += step) - { - step ++; - iter - v.crend (); - } - pass (); - } - } - - void runTest () - { - testAssign (); - testReserve (); - testMutate (); - testIterate (); - } - - DynamicArrayTests () : UnitTest ("DynamicArray", "beast") - { - } -}; - -static DynamicArrayTests dynamicArrayTests; diff --git a/modules/beast_core/containers/DynamicArray.h b/modules/beast_core/containers/DynamicArray.h deleted file mode 100644 index 70a079cae1..0000000000 --- a/modules/beast_core/containers/DynamicArray.h +++ /dev/null @@ -1,728 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -#ifndef BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED -#define BEAST_CORE_CONTAINERS_DYNAMICARRAY_H_INCLUDED - -template -class DynamicArray; - -namespace detail -{ - -template -class DynamicArrayIterator - : public std::iterator -{ -public: - typedef typename copyconst ::type - - value_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef std::ptrdiff_t difference_type; - typedef typename V::size_type size_type; - - DynamicArrayIterator (V* v = nullptr, size_type pos = 0) noexcept - : m_v (v) - , m_pos (pos) - { - } - - template - DynamicArrayIterator (DynamicArrayIterator const& u) noexcept - : m_v (u.m_v) - , m_pos (u.m_pos) - { - } - - template - DynamicArrayIterator& operator= (DynamicArrayIterator const& u) noexcept - { - m_v = u.m_v; - m_pos = u.m_pos; - return *this; - } - - template - bool operator== (DynamicArrayIterator const& u) const noexcept - { - return (m_v == u.m_v) && (m_pos == u.m_pos); - } - - template - bool operator!= (DynamicArrayIterator const& u) const noexcept - { - return ! ((*this) == u); - } - - reference operator* () const noexcept - { - return dereference (); - } - - pointer operator-> () const noexcept - { - return &dereference (); - } - - DynamicArrayIterator& operator++ () noexcept - { - increment (1); - return *this; - } - - DynamicArrayIterator operator++ (int) noexcept - { - DynamicArrayIterator const result (*this); - increment (1); - return result; - } - - DynamicArrayIterator& operator-- () noexcept - { - decrement (1); - return *this; - } - - DynamicArrayIterator operator-- (int) noexcept - { - DynamicArrayIterator const result (*this); - decrement (1); - return result; - } - - DynamicArrayIterator& operator+= (difference_type n) noexcept - { - increment (n); - return *this; - } - - DynamicArrayIterator& operator-= (difference_type n) noexcept - { - decrement (n); - return *this; - } - - DynamicArrayIterator operator+ (difference_type n) noexcept - { - return DynamicArrayIterator (m_v, m_pos + n); - } - - DynamicArrayIterator operator- (difference_type n) noexcept - { - return DynamicArrayIterator (m_v, m_pos - n); - } - - template - difference_type operator- (DynamicArrayIterator const& rhs) const noexcept - { - return m_pos - rhs.m_pos; - } - - template - bool operator< (DynamicArrayIterator const& rhs) const noexcept - { - return m_pos < rhs.m_pos; - } - - template - bool operator> (DynamicArrayIterator const& rhs) const noexcept - { - return m_pos > rhs.m_pos; - } - - template - bool operator<= (DynamicArrayIterator const& rhs) const noexcept - { - return m_pos <= rhs.m_pos; - } - - template - bool operator>= (DynamicArrayIterator const& rhs) const noexcept - { - return m_pos >= rhs.m_pos; - } - - reference operator[] (difference_type n) noexcept - { - return (*m_v)[m_pos + n]; - } - -private: - reference dereference () const noexcept - { - return (*m_v) [m_pos]; - } - - void increment (difference_type n) noexcept - { - m_pos += n; - } - - void decrement (difference_type n) noexcept - { - m_pos -= n; - } - -private: - template - friend class DynamicArrayIterator; - - V* m_v; - size_type m_pos; -}; - -//------------------------------------------------------------------------------ - -template -DynamicArrayIterator operator+ ( - typename DynamicArrayIterator ::difference_type n, - DynamicArrayIterator iter) noexcept -{ - return iter + n; -} - -template -DynamicArrayIterator operator- ( - typename DynamicArrayIterator ::difference_type n, - DynamicArrayIterator iter) noexcept -{ - return iter - n; -} - -//------------------------------------------------------------------------------ - -template -class DynamicArrayReverseIterator - : public std::iterator -{ -public: - typedef typename copyconst ::type - - value_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef std::ptrdiff_t difference_type; - typedef typename V::size_type size_type; - - DynamicArrayReverseIterator (V* v = nullptr, difference_type pos = 0) noexcept - : m_v (v) - , m_pos (pos) - { - } - - template - DynamicArrayReverseIterator (DynamicArrayReverseIterator const& u) noexcept - : m_v (u.m_v) - , m_pos (u.m_pos) - { - } - - template - DynamicArrayReverseIterator& operator= (DynamicArrayReverseIterator const& u) noexcept - { - m_v = u.m_v; - m_pos = u.m_pos; - return *this; - } - - template - bool operator== (DynamicArrayReverseIterator const& u) const noexcept - { - return (m_v == u.m_v) && (m_pos == u.m_pos); - } - - template - bool operator!= (DynamicArrayReverseIterator const& u) const noexcept - { - return ! ((*this) == u); - } - - reference operator* () const noexcept - { - return dereference (); - } - - pointer operator-> () const noexcept - { - return &dereference (); - } - - DynamicArrayReverseIterator& operator++ () noexcept - { - increment (1); - return *this; - } - - DynamicArrayReverseIterator operator++ (int) noexcept - { - DynamicArrayReverseIterator const result (*this); - increment (1); - return result; - } - - DynamicArrayReverseIterator& operator-- () noexcept - { - decrement (1); - return *this; - } - - DynamicArrayReverseIterator operator-- (int) noexcept - { - DynamicArrayReverseIterator const result (*this); - decrement (1); - return result; - } - - DynamicArrayReverseIterator& operator+= (difference_type n) noexcept - { - increment (n); - return *this; - } - - DynamicArrayReverseIterator& operator-= (difference_type n) noexcept - { - decrement (n); - return *this; - } - - DynamicArrayReverseIterator operator+ (difference_type n) noexcept - { - return DynamicArrayReverseIterator (m_v, m_pos - n); - } - - DynamicArrayReverseIterator operator- (difference_type n) noexcept - { - return DynamicArrayReverseIterator (m_v, m_pos + n); - } - - template - difference_type operator- (DynamicArrayReverseIterator const& rhs) const noexcept - { - return rhs.m_pos - m_pos; - } - - template - bool operator< (DynamicArrayReverseIterator const& rhs) const noexcept - { - return m_pos > rhs.m_pos; - } - - template - bool operator> (DynamicArrayReverseIterator const& rhs) const noexcept - { - return m_pos < rhs.m_pos; - } - - template - bool operator<= (DynamicArrayReverseIterator const& rhs) const noexcept - { - return m_pos >= rhs.m_pos; - } - - template - bool operator>= (DynamicArrayReverseIterator const& rhs) const noexcept - { - return m_pos <= rhs.m_pos; - } - - reference operator[] (difference_type n) noexcept - { - return (*m_v)[(m_pos - 1) - n]; - } - -private: - template - friend class DynamicArrayReverseIterator; - - reference dereference () const noexcept - { - return (*m_v) [m_pos - 1]; - } - - void increment (difference_type n) noexcept - { - m_pos -= n; - } - - void decrement (difference_type n) noexcept - { - m_pos += n; - } - - V* m_v; - difference_type m_pos; -}; - -//------------------------------------------------------------------------------ - -template -DynamicArrayReverseIterator operator+ ( - typename DynamicArrayReverseIterator ::difference_type n, - DynamicArrayReverseIterator iter) noexcept -{ - return iter + n; -} - -template -DynamicArrayReverseIterator operator- ( - typename DynamicArrayReverseIterator ::difference_type n, - DynamicArrayReverseIterator iter) noexcept -{ - return iter - n; -} - -} - -//------------------------------------------------------------------------------ - -template > -class DynamicArray -{ -private: - typedef PARAMETER_TYPE (T) TParam; - - typedef std::vector handles_t; - -public: - enum - { - defaultBlocksize = 1000, - growthPercentage = 10 - }; - - typedef T value_type; - typedef Allocator allocator_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef value_type* pointer; - typedef value_type& reference; - typedef value_type const* const_pointer; - typedef value_type const& const_reference; - - typedef detail::DynamicArrayIterator > iterator; - - typedef detail::DynamicArrayIterator const> const_iterator; - - typedef detail::DynamicArrayReverseIterator > reverse_iterator; - - typedef detail::DynamicArrayReverseIterator const> const_reverse_iterator; - - //-------------------------------------------------------------------------- - - explicit DynamicArray (size_type blocksize = defaultBlocksize) noexcept - : m_blocksize (blocksize) - , m_capacity (0) - , m_size (0) - { - } - - ~DynamicArray() - { - clear (); - shrink_to_fit (); - } - - /** Replace the array with 'count' copies of a default-constructed T. - */ - void assign (size_type count) - { - clear (); - resize (count); - } - - //-------------------------------------------------------------------------- - - reference at (size_type pos) - { - if (pos >= size ()) - Throw (std::out_of_range ("bad pos"), __FILE__, __LINE__); - return get (pos); - } - - const_reference at (size_type pos) const - { - if (pos >= size ()) - Throw (std::out_of_range ("bad pos"), __FILE__, __LINE__); - return get (pos); - } - - reference operator[] (size_type pos) noexcept - { - return get (pos); - } - - const_reference operator[] (size_type pos) const noexcept - { - return get (pos); - } - - reference front () noexcept - { - return get (0); - } - - const_reference front () const noexcept - { - return get (0); - } - - reference back () noexcept - { - return get (size () - 1); - } - - const_reference back () const noexcept - { - return get (size () - 1); - } - - //-------------------------------------------------------------------------- - - iterator begin () noexcept - { - return iterator (this, 0); - } - - const_iterator begin () const noexcept - { - return const_iterator (this, 0); - } - - const_iterator cbegin () const noexcept - { - return const_iterator (this, 0); - } - - iterator end () noexcept - { - return iterator (this, size ()); - } - - const_iterator end () const noexcept - { - return const_iterator (this, size ()); - } - - const_iterator cend () const noexcept - { - return const_iterator (this, size ()); - } - - reverse_iterator rbegin () noexcept - { - return reverse_iterator (this, size ()); - } - - const_reverse_iterator rbegin () const noexcept - { - return const_reverse_iterator (this, size ()); - } - - const_reverse_iterator crbegin () const noexcept - { - return const_reverse_iterator (this, size ()); - } - - reverse_iterator rend () noexcept - { - return reverse_iterator (this, 0); - } - - const_reverse_iterator rend () const noexcept - { - return const_reverse_iterator (this, 0); - } - - const_reverse_iterator crend () const noexcept - { - return const_reverse_iterator (this, 0); - } - - //-------------------------------------------------------------------------- - - bool empty () const noexcept - { - return m_size == 0; - } - - size_type size () const noexcept - { - return m_size; - } - - size_type max_size () const noexcept - { - return std::numeric_limits ::max (); - } - - void reserve (size_type new_cap) - { - new_cap = m_blocksize * ( - (new_cap + m_blocksize - 1) / m_blocksize); - if (new_cap > max_size ()) - Throw (std::length_error ("new_cap > max_size"), __FILE__, __LINE__); - if (new_cap <= m_capacity) - return; - size_type const n (new_cap / m_blocksize); - m_handles.reserve (n); - for (size_type i = m_handles.size (); i < n; ++i) - m_handles.push_back (static_cast (std::malloc ( - m_blocksize * sizeof (T)))); - m_capacity = new_cap; - } - - size_type capacity () const noexcept - { - return m_capacity; - } - - void shrink_to_fit () - { - size_type const handles ( - (size () + m_blocksize - 1) / m_blocksize); - m_capacity = handles * m_blocksize; - for (size_type i = m_handles.size (); i-- > handles;) - { - std::free (m_handles [i]); - m_handles.erase (m_handles.begin () + i); - } - } - - //-------------------------------------------------------------------------- - - void clear () - { - resize (0); - } - - iterator push_back (TParam value) - { - ::new (alloc ()) T (value); - return iterator (this, size () - 1); - } - - iterator emplace_back () - { - ::new (alloc ()) T (); - return iterator (this, size () - 1); - } - - template - iterator emplace_back (A1 a1) - { - ::new (alloc ()) T (a1); - return iterator (this, size () - 1); - } - - template - iterator emplace_back (A1 a1, A2 a2) - { - ::new (alloc ()) T (a1, a2); - return iterator (this, size () - 1); - } - - template - iterator emplace_back (A1 a1, A2 a2, A3 a3) - { - ::new (alloc ()) T (a1, a2, a3); - return iterator (this, size () - 1); - } - - template - iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4) - { - ::new (alloc ()) T (a1, a2, a3, a4); - return iterator (this, size () - 1); - } - - template - iterator emplace_back (A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) - { - ::new (alloc ()) T (a1, a2, a3, a4, a5); - return iterator (this, size () - 1); - } - - void pop_back () - { - resize (size () - 1); - } - - void resize (size_type count) - { - while (count > size ()) - ::new (alloc ()) T; - - while (count < size ()) - get (--m_size).~T (); - } - - void resize (size_type count, TParam value) - { - while (count > size ()) - ::new (alloc ()) T (value); - - while (count < size ()) - get (--m_size).~T (); - } - - void swap (DynamicArray& other) - { - std::swap (m_blocksize, other.m_blocksize); - std::swap (m_size, other.m_size); - std::swap (m_capacity, other.m_capacity); - std::swap (m_handles, other.m_handles); - } - -private: - reference get (size_type pos) noexcept - { - size_type const index (pos / m_blocksize); - size_type const offset (pos % m_blocksize); - return m_handles [index] [offset]; - } - - const_reference get (size_type pos) const noexcept - { - size_type const index (pos / m_blocksize); - size_type const offset (pos % m_blocksize); - return m_handles [index] [offset]; - } - - T* alloc () noexcept - { - size_type const needed (size () + 1); - if (capacity () < needed) - reserve ((needed * (100 + growthPercentage) + 99) / 100); - return &get (m_size++); - } - -private: - Allocator m_allocator; - size_type m_blocksize; - size_type m_capacity; - size_type m_size; - handles_t m_handles; -}; - -#endif diff --git a/modules/beast_core/containers/DynamicList.cpp b/modules/beast_core/containers/DynamicList.cpp deleted file mode 100644 index 35d2ac15c5..0000000000 --- a/modules/beast_core/containers/DynamicList.cpp +++ /dev/null @@ -1,327 +0,0 @@ -//------------------------------------------------------------------------------ -/* - This file is part of Beast: https://github.com/vinniefalco/Beast - Copyright 2013, Vinnie Falco - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ -//============================================================================== - -namespace ContainerTests -{ - -//------------------------------------------------------------------------------ - -/** Counts the number of occurrences of each type of operation. */ -class Counts -{ -public: - typedef std::size_t count_type; - - Counts () - : default_ctor (0) - , copy_ctor (0) - , copy_assign (0) - #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - , move_ctor (0) - , move_assign (0) - #endif - { - } - - Counts (Counts const& other) - : default_ctor (other.default_ctor) - , copy_ctor (other.copy_ctor) - , copy_assign (other.copy_assign) - #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - , move_ctor (other.move_ctor) - , move_assign (other.move_assign) - #endif - { - } - - Counts& operator= (Counts const& other) - { - default_ctor = other.default_ctor; - copy_ctor = other.copy_ctor; - copy_assign = other.copy_assign; - #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - move_ctor = other.move_ctor; - move_assign = other.move_assign; - #endif - return *this; - } - - friend inline Counts operator- (Counts const& lhs, Counts const& rhs) - { - Counts result; - result.default_ctor = lhs.default_ctor - rhs.default_ctor; - result.copy_ctor = lhs.copy_ctor - rhs.copy_ctor; - result.copy_assign = lhs.copy_assign - rhs.copy_assign; - #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - result.move_ctor = lhs.move_ctor - rhs.move_ctor; - result.move_assign = lhs.move_assign - rhs.move_assign; - #endif - return result; - } - - String toString () const - { - return String() - + "default_ctor(" + String::fromNumber (default_ctor) + ") " - + ", copy_ctor(" + String::fromNumber (copy_ctor) + ")" - + ", copy_assign(" + String::fromNumber (copy_assign) + ")" - #if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - + ", move_ctor(" + String::fromNumber (move_ctor) + ")" - + ", move_assign(" + String::fromNumber (move_assign) + ")" - #endif - ; - } - - count_type default_ctor; - count_type copy_ctor; - count_type copy_assign; -#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - count_type move_ctor; - count_type move_assign; -#endif -}; - -//------------------------------------------------------------------------------ - -/** Counts the number of element operations performed in a scope. */ -class ScopedCounts : public Uncopyable -{ -public: - ScopedCounts (Counts const& counts) - : m_start (counts) - , m_counts (counts) - { - } - - Counts get () const - { - return m_counts - m_start; - } - -private: - Counts const m_start; - Counts const& m_counts; -}; - -//------------------------------------------------------------------------------ - -/* Base for element configurations. */ -class ElementConfigBase : public Uncopyable -{ -public: - typedef std::size_t IdType; -}; - -/** Provides the element-specific configuration members. */ -template -class ElementConfig : public ElementConfigBase -{ -public: - static Counts& getCounts () - { - static Counts counts; - return counts; - } -}; - -//------------------------------------------------------------------------------ - -/** Base for elements used in container unit tests. */ -class ElementBase -{ -public: -}; - -/** An object placed into a container for unit testing. */ -template -class Element : public ElementBase -{ -public: - typedef typename Config::IdType IdType; - - Element () - : m_id (0) - , m_msg (String::empty) - { - ++Config::getCounts ().default_ctor; - } - - explicit Element (IdType id) - : m_id (id) - , m_msg (String::fromNumber (id)) - { - } - - Element (Element const& other) - : m_id (other.m_id) - , m_msg (other.m_msg) - { - ++Config::getCounts ().copy_ctor; - } - - Element& operator= (Element const& other) - { - m_id = other.m_id; - m_msg = other.m_msg; - ++Config::getCounts ().copy_assign; - } - -#if BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS - Element (Element&& other) - : m_id (other.m_id) - , m_msg (other.m_msg) - { - other.m_msg = String::empty; - ++Config::getCounts ().move_ctor; - } - - Element& operator= (Element&& other) - { - m_id = other.m_id; - m_msg = other.m_msg; - other.m_msg = String::empty; - ++Config::getCounts ().move_assign; - } -#endif - - IdType id () const - { - return m_id; - } - - String msg () const - { - return m_msg; - } - -private: - IdType m_id; - String m_msg; -}; - -//------------------------------------------------------------------------------ - -/** Base for test state parameters. */ -class StateBase : public Uncopyable -{ -public: - typedef int64 SeedType; -}; - -/** Provides configuration-specific test state parameters. */ -template -class State : public StateBase -{ -public: - static Random& random () - { - static Random generator (Params::seedValue); - return generator; - } -}; - -//------------------------------------------------------------------------------ - -class ConfigBase -{ -}; - -template