From cf70f0d45c3cc39bc3cec703c1446303e9cc3d0c Mon Sep 17 00:00:00 2001 From: Reece Date: Thu, 17 Feb 2022 00:11:40 +0000 Subject: [PATCH] [*/+/-] MEGA COMMIT. ~2 weeks compressed. The intention is to quickly improve and add util apis, enhance functionality given current demands, go back to the build pipeline, finish that, publish runtime tests, and then use what we have to go back to to linux support with a more stable api. [+] AuMakeSharedArray [+] Technet ArgvQuote [+] Grug subsystem (UNIX signal thread async safe ipc + telemetry flusher + log flusher.) [+] auEndianness -> Endian swap utils [+] AuGet(...) [*] AUE_DEFINE conversion for ECompresionType, EAnsiColor, EHashType, EStreamError, EHexDump [+] ConsoleMessage ByteBuffer serialization [+] CmdLine subsystem for parsing command line arguments and simple switch/flag checks [*] Split logger from console subsystem [+] StartupParameters -> A part of a clean up effort under Process [*] Refactor SysErrors header + get caller hack [+] Atomic APIs [+] popcnt [+] Ring Buffer sink [+] Added more standard errors Catch, Submission, LockError, NoAccess, ResourceMissing, ResourceLocked, MalformedData, InSandboxContext, ParseError [+] Added ErrorCategorySet, ErrorCategoryClear, GetStackTrace [+] IExitSubscriber, ETriggerLevel [*] Write bias the high performance RWLockImpl read-lock operation operation [+] ExitHandlerAdd/ExitHandlerRemove (exit subsystem) [*] Updated API style Digests [+] CpuId::CpuBitCount [+] GetUserProgramsFolder [+] GetPackagePath [*] Split IStreamReader with an inl file [*] BlobWriter/BlobReader/BlobArbitraryReader can now take shared pointers to bytebuffers. default constructor allocates a new scalable bytebuffer [+] ICharacterProvider [+] ICharacterProviderEx [+] IBufferedCharacterConsumer [+] ProviderFromSharedString [+] ProviderFromString [+] BufferConsumerFromProvider [*] Parse Subsystem uses character io bufferer [*] Rewritten NT's high perf semaphore to use userland SRW/ConVars [like mutex, based on generic semaphore] [+] ByteBuffer::ResetReadPointer [*] Bug fix bytebuffer base not reset on free and some scaling issues [+] ProcessMap -> Added kSectionNameStack, kSectionNameFile, kSectionNameHeap for Section [*] ProcessMap -> Refactor Segment to Section. I was stupid for keeping a type conflict hack API facing [+] Added 64 *byte* fast RNG seeds [+] File Advisorys/File Lock Awareness [+] Added extended IAuroraThread from OS identifier caches for debug purposes [*] Tweaked how memory is reported on Windows. Better consistency of what values mean across functions. [*] Broke AuroraUtils/Typedefs out into a separate library [*] Update build script [+] Put some more effort into adding detail to the readme before rewriting it, plus, added some media [*] Improved public API documentation [*] Bug fix `SetConsoleCtrlHandler` [+] Locale TimeDateToFileNameISO8601 [+] Console config stdOutShortTime [*] Begin using internal UTF8/16 decoders when platform support isnt available (instead of stl) [*] Bug fixes in decoders [*] Major bug fix, AuMax [+] RateLimiter [+] Binary file sink [+] Log directory sink [*] Data header usability (more operators) [+] AuRemoveRange [+] AuRemove [+] AuTryRemove [+] AuTryRemoveRange [+] auCastUtils [+] Finish NewLSWin32Source [+] AuTryFindByTupleN, AuTryRemoveByTupleN [+] Separated AuRead/Write types, now in auTypeUtils [+] Added GetPosition/SetPosition to FileWriter [*] Fix stupid AuMin in place of AuMax in SpawnThread.Unix.Cpp [*] Refactored Arbitrary readers to SeekingReaders (as in, they could be atomic and/or parallelized, and accept an arbitrary position as a work parameter -> not Seekable, as in, you can simply set the position) [*] Hack back in the sched deinit [+] File AIO loop source interop [+] Begin to prototype a LoopQueue object I had in mind for NT, untested btw [+] Stub code for networking [+] Compression BaseStream/IngestableStreamBase [*] Major: read/write locks now support write-entrant read routines. [*] Compression subsystem now uses the MemoryView concept [*] Rewrite the base stream compressions, made them less broken [*] Update hashing api [*] WriterTryGoForward and ReaderTryGoForward now revert to the previous relative index instead of panicing [+] Added new AuByteBuffer apis Trim, Pad, WriteFrom, WriteString, [TODO: ReadString] [+] Added ByteBufferPushReadState [+] Added ByteBufferPushWriteState [*] Move from USC-16 to full UTF-16. Win32 can handle full UTF-16. [*] ELogLevel is now an Aurora enum [+] Raised arbitrary limit in header to 255, the max filter buffer [+] Explicit GZip support [+] Explicit Zip support [+] Added [some] compressors et al --- Aurora.json | 2 +- Include/Aurora/Async/AsyncTypes.hpp | 2 +- Include/Aurora/Async/IThreadPool.hpp | 3 +- Include/Aurora/Async/IWorkItem.hpp | 1 + Include/Aurora/Async/JobFrom.hpp | 16 +- Include/Aurora/Async/TaskFrom.hpp | 8 +- Include/Aurora/CmdLine/CmdLine.hpp | 59 + .../Aurora/Compression/BasicCompression.hpp | 14 +- Include/Aurora/Compression/Compression.hpp | 50 +- .../Aurora/Compression/CompressionInfo.hpp | 93 +- .../Aurora/Compression/ECompresionType.hpp | 8 +- .../Aurora/Compression/ICompressionStream.hpp | 63 +- .../Compression/StreamPipeProcessor.hpp | 2 +- .../Aurora/Compression/StreamProcessor.hpp | 7 + Include/Aurora/Console/Commands/Commands.hpp | 3 +- Include/Aurora/Console/Console.hpp | 21 +- Include/Aurora/Console/ConsoleMessage.hpp | 3 + Include/Aurora/Console/EAnsiColor.hpp | 9 +- Include/Aurora/Console/Logging/IBasicSink.hpp | 17 - .../Aurora/Console/Logging/IBasicSinkRB.hpp | 17 - Include/Aurora/Console/Logging/Sinks.hpp | 23 - Include/Aurora/Crypto/ECC/EECCCurve.hpp | 6 +- Include/Aurora/Data/TypedValue.hpp | 93 ++ Include/Aurora/Debug/Debug.hpp | 20 +- Include/Aurora/Debug/EFailureCategory.hpp | 12 +- Include/Aurora/Debug/SysAssertions.hpp | 16 +- Include/Aurora/Debug/SysErrors.hpp | 103 +- Include/Aurora/Debug/SysPanic.hpp | 4 +- Include/Aurora/Exit/ETriggerLevel.hpp | 26 + Include/Aurora/Exit/Exit.hpp | 36 + Include/Aurora/Exit/IExitSubscriber.hpp | 23 + Include/Aurora/HWInfo/CpuBitId.hpp | 3 +- Include/Aurora/HWInfo/CpuBitId.inl | 11 + Include/Aurora/Hashing/Digests.hpp | 54 +- Include/Aurora/Hashing/EHashType.hpp | 6 +- Include/Aurora/Hashing/HashStream.hpp | 2 +- .../IO/Buffered/BlobArbitraryReader.hpp | 50 - .../Aurora/IO/Buffered/BlobBuilder.hpp | 0 Include/Aurora/IO/Buffered/BlobReader.hpp | 32 +- .../Aurora/IO/Buffered/BlobSeekableReader.hpp | 46 + Include/Aurora/IO/Buffered/BlobWriter.hpp | 33 +- Include/Aurora/IO/Buffered/Buffered.hpp | 2 +- Include/Aurora/IO/Character/Character.hpp | 4 +- .../Character/IBufferedCharacterConsumer.hpp | 10 + .../IO/Character/IBufferedLineReader.hpp | 20 + .../IO/Character/ICharacterProvider.hpp | 2 +- .../IO/Character/ICharacterProviderEx.hpp | 17 + Include/Aurora/IO/Character/Providers.hpp | 16 + Include/Aurora/IO/EStreamError.hpp | 5 +- Include/Aurora/IO/FS/Async.hpp | 31 +- .../Aurora/IO/FS/EFileAdvisoryLockLevel.hpp | 29 + Include/Aurora/IO/FS/EFileOpenMode.hpp | 18 + Include/Aurora/IO/FS/FS.hpp | 7 +- Include/Aurora/IO/FS/FileReader.hpp | 15 +- ...traryReader.hpp => FileSeekableReader.hpp} | 13 +- Include/Aurora/IO/FS/FileStream.hpp | 6 +- Include/Aurora/IO/FS/FileWriter.hpp | 29 +- Include/Aurora/IO/FS/IAsyncFileStream.hpp | 18 + .../Aurora/IO/FS/IAsyncFinishedSubscriber.hpp | 15 + Include/Aurora/IO/FS/IAsyncTransaction.hpp | 30 + Include/Aurora/IO/FS/IFileStream.hpp | 59 +- Include/Aurora/IO/FS/Resources.hpp | 27 +- Include/Aurora/IO/IO.hpp | 5 +- ...bitraryStreamer.hpp => ISeekingReader.hpp} | 7 +- Include/Aurora/IO/IStreamReader.hpp | 46 +- Include/Aurora/IO/IStreamReader.inl | 47 + Include/Aurora/IO/IStreamWriter.hpp | 3 +- Include/Aurora/IO/Net/Net.hpp | 80 +- Include/Aurora/Locale/ECodePage.hpp | 26 +- Include/Aurora/Locale/Encoding/Encoding.hpp | 14 +- Include/Aurora/Locale/Locale.hpp | 2 +- Include/Aurora/Locale/LocaleStrings.hpp | 10 +- Include/Aurora/Logging/IBasicSink.hpp | 25 + Include/Aurora/Logging/IBasicSinkRB.hpp | 25 + .../Aurora/{Console => }/Logging/ILogger.hpp | 21 +- .../Aurora/{Console => }/Logging/Logging.hpp | 19 +- .../Aurora/{Console => Logging}/README.txt | 0 Include/Aurora/Logging/Sinks.hpp | 61 + Include/Aurora/Loop/ELoopSource.hpp | 41 + Include/Aurora/Loop/ILoopQueue.hpp | 186 +++ Include/Aurora/Loop/ILoopSource.hpp | 26 + Include/Aurora/Loop/ILoopSourceSubscriber.hpp | 36 + Include/Aurora/Loop/Loop.hpp | 75 +- Include/Aurora/Memory/ByteBuffer.hpp | 138 +- .../Aurora/Memory/ByteBufferPushReadState.hpp | 39 + .../Memory/ByteBufferPushWriteState.hpp | 39 + Include/Aurora/Memory/ByteBuffer_Memory.inl | 35 +- Include/Aurora/Memory/ByteBuffer_Position.inl | 33 +- .../Aurora/Memory/ByteBuffer_ReadWrite.inl | 45 +- Include/Aurora/Memory/ByteBuffer_Strings.inl | 137 ++ Include/Aurora/Memory/ByteBuffer_Utility.inl | 79 + Include/Aurora/Memory/ByteBuffer_Utils.inl | 2 +- .../Aurora/Memory/ByteBuffer_WriteFrom.inl | 16 + .../Aurora/Memory/ExtendStlLikeSharedPtr.hpp | 12 +- Include/Aurora/Memory/Memory.hpp | 8 +- Include/Aurora/Memory/MemoryView.hpp | 36 +- Include/Aurora/Memory/_ByteBuffer.hpp | 5 +- Include/Aurora/Parse/Base64.hpp | 14 +- Include/Aurora/Parse/Hex.hpp | 6 +- Include/Aurora/Parse/Parser.hpp | 39 +- Include/Aurora/Process/Paths.hpp | 2 +- Include/Aurora/Process/Process.hpp | 25 +- Include/Aurora/Process/ProcessMap.hpp | 34 +- Include/Aurora/Processes/ESpawnType.hpp | 10 +- Include/Aurora/Processes/EStandardHandle.hpp | 12 + Include/Aurora/Processes/ICommandFinished.hpp | 9 + Include/Aurora/Processes/IProcess.hpp | 60 +- Include/Aurora/Processes/Open.hpp | 13 +- Include/Aurora/Processes/StartupParmaters.hpp | 38 +- Include/Aurora/Processes/UtilRun.hpp | 19 +- Include/Aurora/RNG/ERngStringCharacters.hpp | 9 +- Include/Aurora/RNG/IRandomDevice.hpp | 25 - Include/Aurora/RNG/RNG.hpp | 1 + Include/Aurora/RNG/RandomDef.hpp | 53 + Include/Aurora/Registry/IRegistry.hpp | 31 +- Include/Aurora/Runtime.hpp | 81 +- Include/Aurora/SWInfo/SWInfo.hpp | 8 +- Include/Aurora/Telemetry/BlackBox.hpp | 2 +- .../Aurora/Threading/Primitives/RWLock.hpp | 33 +- .../Threading/Threads/IAuroraThread.hpp | 2 +- Include/Aurora/Time/DebugBenchmark.hpp | 2 +- Include/Aurora/Time/TM.hpp | 2 +- Include/Aurora/Utility/RateLimiter.hpp | 77 + Include/AuroraMacros.hpp | 225 +-- Include/AuroraTypedefs.hpp | 423 +----- Include/AuroraUtils.hpp | 1305 +---------------- Include/auROXTL.hpp | 31 + Include/auROXTL/AU_MACROS.hpp | 231 +++ Include/auROXTL/auArray.hpp | 15 + Include/auROXTL/auAtomic.hpp | 186 +++ Include/auROXTL/auBST.hpp | 18 + Include/auROXTL/auBitsUtils.hpp | 190 +++ Include/auROXTL/auCastUtils.hpp | 82 ++ Include/auROXTL/auContainerUtils.hpp | 487 ++++++ Include/auROXTL/auCopyMoveUtils.hpp | 26 + Include/auROXTL/auEndianness.hpp | 88 ++ Include/auROXTL/auFunctional.hpp | 29 + Include/auROXTL/auHashMap.hpp | 18 + Include/auROXTL/auList.hpp | 30 + Include/auROXTL/auMagicUtils.hpp | 71 + Include/auROXTL/auMemory.hpp | 44 + Include/auROXTL/auMemoryModel.hpp | 132 ++ Include/auROXTL/auNumberUtils.hpp | 20 + Include/auROXTL/auOptional.hpp | 15 + Include/auROXTL/auPosixUtils.hpp | 9 + Include/auROXTL/auString.hpp | 12 + Include/auROXTL/auStringUtils.hpp | 119 ++ Include/auROXTL/auTemplateMeta.hpp | 215 +++ Include/auROXTL/auTransform.hpp | 8 + Include/auROXTL/auTuple.hpp | 22 + Include/auROXTL/auTupleUtils.hpp | 70 + Include/auROXTL/auTypeUtils.hpp | 374 +++++ Include/auROXTL/auTypes.hpp | 27 + Include/auROXTL/auVector.hpp | 47 + Include/auROXTL/auWin32Utils.hpp | 20 + Include/auROXTLTypes.hpp | 52 + Include/auROXTLUtils.hpp | 80 + Media/Aurora Keys - test.reg | Bin 0 -> 822 bytes Media/Aurora Keys.reg | Bin 0 -> 836 bytes Media/ICanHasStackTraces.png | Bin 0 -> 130014 bytes Media/wxHello.png | Bin 0 -> 49535 bytes Source/Async/AsyncApp.cpp | 7 + Source/Async/AsyncApp.hpp | 1 + Source/Async/GroupState.cpp | 6 +- Source/Async/GroupState.hpp | 1 + Source/Async/Schedular.cpp | 6 +- Source/Async/ThreadPool.cpp | 13 + Source/Async/ThreadPool.hpp | 1 + Source/CmdLine/CmdLine.cpp | 88 ++ Source/CmdLine/CmdLine.hpp | 13 + Source/CmdLine/CmdLinePlatform.cpp | 144 ++ Source/CmdLine/CmdLinePlatform.hpp | 13 + Source/Compression/BaseStream.cpp | 105 ++ Source/Compression/BaseStream.hpp | 53 + Source/Compression/BlockCompressor.cpp | 153 +- Source/Compression/BlockCompressor.hpp | 27 - Source/Compression/BlockDecompressor.cpp | 491 +------ Source/Compression/BlockDecompressor.hpp | 23 - Source/Compression/Compression.cpp | 28 +- Source/Compression/Compression.hpp | 73 + .../Compressors/BZip2Compressor.hpp | 164 +++ .../Compressors/BZip2Decompressor.hpp | 118 ++ .../Compressors/DeflateCompressor.hpp | 152 ++ .../Compressors/DeflateDecompressor.hpp | 114 ++ .../Compression/Compressors/LZ4Compressor.hpp | 9 + .../Compressors/LZ4Decompressor.hpp | 123 ++ .../Compressors/ZSTDCompressor.hpp | 174 +++ .../Compressors/ZSTDDecompressor.hpp | 107 ++ Source/Compression/IngestableReadBase.hpp | 29 + Source/Compression/IngestableReadBase.inl | 64 + Source/Compression/StreamCompression.cpp | 55 +- Source/Console/Commands/Commands.cpp | 2 +- Source/Console/Console.cpp | 46 +- Source/Console/Console.hpp | 4 +- Source/Console/ConsoleFIO/ConsoleFIO.cpp | 87 +- Source/Console/ConsoleFIO/FileSink.cpp | 88 -- Source/Console/ConsoleMessage.cpp | 31 +- Source/Console/ConsoleStd/ConsoleStd.cpp | 103 +- Source/Console/ConsoleStd/ConsoleStd.hpp | 7 +- Source/Console/Flusher.cpp | 91 +- Source/Console/Flusher.hpp | 4 - Source/Console/Hooks/Hooks.cpp | 1 + Source/Console/Logging/Sinks.cpp | 54 - Source/Console/Logging/Sinks.hpp | 6 - Source/Crypto/ECC/ECC.cpp | 176 ++- Source/Crypto/ECC/ECCCurves.cpp | 6 +- Source/Crypto/ECC/ECCCurves.hpp | 2 +- Source/Crypto/ECC/ECCGeneric.cpp | 2 +- Source/Crypto/ECC/ECCGeneric.hpp | 33 +- Source/Crypto/ECC/ECCX25519.cpp | 15 - Source/Crypto/ECC/ECCX25519.hpp | 13 - Source/Crypto/ECC/ECCX25519Private.cpp | 230 +++ Source/Crypto/ECC/ECCX25519Private.hpp | 37 + Source/Crypto/ECC/ECCX25519Public.cpp | 150 ++ Source/Crypto/ECC/ECCX25519Public.hpp | 35 + Source/Crypto/ECC/PrivateECCImpl.cpp | 1 - Source/Crypto/ECC/PublicECCImpl.cpp | 7 +- Source/Crypto/ECC/PublicECCImpl.hpp | 3 - Source/Crypto/RSA/RSAPrivate.cpp | 2 +- Source/Crypto/RSA/RSAPublic.cpp | 2 +- Source/Debug/Debug.cpp | 46 +- Source/Debug/Debug.hpp | 6 +- Source/Debug/ExceptionWatcher.NT.cpp | 19 +- Source/Debug/ExceptionWatcher.Win32.cpp | 54 +- Source/Debug/GrugException.hpp | 29 + Source/Debug/Panic.cpp | 15 +- Source/Entrypoint.cpp | 27 +- Source/Exit/Exit.cpp | 122 ++ Source/Exit/Exit.hpp | 16 + Source/Exit/MTWatchDog.cpp | 43 + Source/Exit/MTWatchDog.hpp | 14 + Source/Extensions/LTC/LTCExtensions.h | 5 +- .../x509_decode_subject_public_key_info_2.c | 79 + Source/Grug/Arrow.cpp | 134 ++ Source/Grug/Arrow.hpp | 31 + Source/Grug/Grug.cpp | 182 +++ Source/Grug/Grug.hpp | 25 + Source/Grug/GrugThread.cpp | 54 + Source/Grug/GrugThread.hpp | 35 + Source/HWInfo/CpuInfo.NT.cpp | 2 +- Source/HWInfo/RamInfo.cpp | 30 +- Source/Hashing/Digests.cpp | 20 +- Source/Hashing/HashStream.cpp | 80 +- Source/Hashing/HashStream.hpp | 13 + Source/IO/Buffered/BlobBuilder.cpp | 7 + Source/IO/Buffered/BlobBuilder.hpp | 6 + .../Character/BufferedCharacterConsumer.cpp | 96 ++ .../Character/BufferedCharacterConsumer.hpp | 36 + Source/IO/Character/BufferedLineReader.cpp | 113 ++ Source/IO/Character/BufferedLineReader.hpp | 28 + Source/IO/Character/StringToProvider.cpp | 86 ++ .../IO/Character/StringToProvider.hpp | 4 +- Source/IO/FS/Async.NT.cpp | 138 +- Source/IO/FS/FS.NT.cpp | 2 +- Source/IO/FS/FS.cpp | 2 +- Source/IO/FS/FS.hpp | 2 +- Source/IO/FS/FileAdvisory.NT.cpp | 28 + Source/IO/FS/FileAdvisory.NT.hpp | 13 + Source/IO/FS/FileAdvisory.Unix.cpp | 7 + .../FileAdvisory.Unix.hpp} | 0 Source/IO/FS/FileStream.Generic.cpp | 4 +- Source/IO/FS/FileStream.NT.cpp | 41 +- Source/IO/FS/Resources.cpp | 27 +- Source/IO/Net/BaseChannel.cpp | 84 ++ Source/IO/Net/BaseChannel.hpp | 119 ++ Source/IO/Net/BaseLocalClient.cpp | 24 + Source/IO/Net/BaseLocalClient.hpp | 25 + Source/IO/Net/BaseNetworkInterface.cpp | 38 + Source/IO/Net/BaseNetworkInterface.hpp | 22 + Source/IO/Net/BaseServer.cpp | 45 + Source/IO/Net/BaseServer.hpp | 60 + Source/IO/Net/BaseSocket.cpp | 43 + Source/IO/Net/BaseSocket.hpp | 95 ++ Source/IO/Net/HelloNet.Win32.cpp | 22 + Source/IO/Net/HelloNet.Win32.hpp | 14 + Source/IO/Net/IPAddress.cpp | 32 + Source/IO/Net/IPAddress.hpp | 13 + Source/IO/Net/Net.cpp | 7 +- Source/IO/Net/Net.hpp | 7 +- Source/IO/Net/NetworkingPool.cpp | 68 + Source/IO/Net/NetworkingPool.hpp | 39 + Source/IO/Net/PlatformChannel.Win32.cpp | 15 + Source/IO/Net/PlatformChannel.Win32.hpp | 13 + Source/IO/Net/PlatformChannel.hpp | 28 + Source/IO/Net/PlatformSocket.Win32.cpp | 52 + Source/IO/Net/PlatformSocket.Win32.hpp | 25 + Source/IO/Net/PlatformSocket.hpp | 17 + Source/IO/Net/SocketFactory.cpp | 33 + Source/IO/Net/SocketFactory.hpp | 20 + Source/IO/Net/SocketStatAverageBps.hpp | 2 +- Source/IO/Net/WorkPoolGroup.cpp | 19 + Source/IO/Net/WorkPoolGroup.hpp | 13 + Source/IO/Net/WorkRange.cpp | 19 + Source/IO/Net/WorkRange.hpp | 13 + Source/Locale/Encoding/BOM.cpp | 43 + Source/Locale/Encoding/BOM.hpp | 8 + Source/Locale/Encoding/ConvertInternal.cpp | 238 +-- Source/Locale/Encoding/ConvertInternal.hpp | 5 - Source/Locale/Encoding/EncoderAdapter.cpp | 9 +- Source/Locale/Encoding/EncoderIConv.cpp | 10 +- Source/Locale/Encoding/EncoderNSL.cpp | 5 +- Source/Locale/Encoding/Encoding.cpp | 85 +- Source/Locale/Encoding/Encoding.hpp | 18 +- Source/Locale/Encoding/GBK/GBK.hpp | 30 +- Source/Locale/Encoding/SJIS/SJIS.hpp | 10 +- Source/Locale/Encoding/UTFn/AuUTF16.hpp | 215 ++- Source/Locale/Encoding/UTFn/AuUTF32.hpp | 175 +-- Source/Locale/Encoding/UTFn/AuUTF8.hpp | 160 ++ Source/Locale/Locale.cpp | 4 +- Source/Locale/Locale.hpp | 22 - Source/Locale/LocaleStrings.cpp | 31 +- Source/{Console => }/Logging/Logger.cpp | 115 +- Source/{Console => }/Logging/Logger.hpp | 14 +- Source/Logging/Logging.cpp | 40 + Source/Logging/Logging.hpp | 7 + Source/Logging/Sinks.cpp | 96 ++ Source/Logging/Sinks.hpp | 13 + Source/Logging/Sinks/DirLogArchive.cpp | 82 ++ Source/Logging/Sinks/DirLogArchive.hpp | 14 + Source/Logging/Sinks/EventLog.Win32.cpp | 129 ++ Source/Logging/Sinks/EventLog.Win32.hpp | 35 + Source/Logging/Sinks/FileSink.cpp | 104 ++ .../ConsoleFIO => Logging/Sinks}/FileSink.hpp | 13 +- Source/Logging/Sinks/RingBuffer.cpp | 149 ++ Source/Logging/Sinks/RingBuffer.hpp | 35 + Source/Logging/Sinks/StdConsole.cpp | 38 + Source/Logging/Sinks/StdConsole.hpp | 26 + Source/Logging/Sinks/SysLog.Unix.cpp | 7 + Source/Logging/Sinks/SysLog.Unix.hpp | 7 + Source/Logging/Sinks/SystemD.Unix.cpp | 7 + Source/Logging/Sinks/SystemD.Unix.hpp | 7 + Source/Loop/ILoopSourceEx.hpp | 5 +- Source/Loop/LSAsync.cpp | 17 +- Source/Loop/LSAsync.hpp | 2 +- Source/Loop/LSEvent.NT.cpp | 13 +- Source/Loop/LSEvent.NT.hpp | 7 +- Source/Loop/LSHandle.cpp | 9 +- Source/Loop/LSHandle.hpp | 15 +- Source/Loop/LSMutex.NT.cpp | 2 +- Source/Loop/LSSemaphore.NT.cpp | 2 +- Source/Loop/LSWin32.NT.cpp | 17 +- Source/Loop/LSWin32.NT.hpp | 11 +- Source/Loop/Loop.NT.cpp | 9 +- Source/Loop/Loop.cpp | 24 +- Source/Loop/LoopQueue.BSD.cpp | 1 + .../LoopQueue.BSD.hpp} | 0 Source/Loop/LoopQueue.Linux.cpp | 1 + Source/Loop/LoopQueue.Linux.hpp | 0 Source/Loop/LoopQueue.NT.cpp | 860 +++++++++++ Source/Loop/LoopQueue.NT.hpp | 106 ++ Source/Loop/WORK_IN_PROGRESS.txt | 0 Source/Loop/WaitSingle.NT.cpp | 1 - Source/Loop/WaitSingle.NT.hpp | 3 +- ...itSingle.Linux.cpp => WaitSingle.Unix.cpp} | 2 +- ...itSingle.Linux.hpp => WaitSingle.Unix.hpp} | 2 +- Source/Loop/WaitSingleBase.cpp | 5 +- Source/Loop/WaitSingleBase.hpp | 3 +- Source/Memory/ByteBuffer.cpp | 14 - Source/Memory/ByteBuffer.hpp | 8 - Source/Memory/Heap.cpp | 2 +- Source/Parse/Base64.cpp | 8 +- Source/Parse/Hex.cpp | 3 +- Source/Parse/Parser.cpp | 90 +- Source/Process/Paths.cpp | 19 +- Source/Process/Process.cpp | 10 +- Source/Process/ProcessMap.NT.cpp | 43 +- Source/Process/ProcessMap.NT.hpp | 2 +- Source/Process/ProcessMap.cpp | 38 +- Source/Processes/ArgvQuote.cpp | 87 ++ Source/Processes/ArgvQuote.hpp | 40 + Source/Processes/Open.Unix.cpp | 2 +- Source/Processes/Process.Linux.cpp | 2 +- Source/Processes/Process.NT.cpp | 131 +- Source/Processes/Process.NT.hpp | 45 + Source/Processes/Process.Win32.cpp | 12 +- Source/RNG/RNG.cpp | 4 +- Source/RNG/RandomDevice.cpp | 17 +- Source/RNG/WELL.cpp | 78 +- Source/RNG/WELL.hpp | 1 + Source/Registry/Registry.cpp | 65 +- Source/RuntimeInternal.hpp | 17 +- Source/SWInfo/SWInfo.Linux.cpp | 0 Source/SWInfo/SWInfo.Linux.hpp | 0 Source/SWInfo/SWInfo.NT.cpp | 132 ++ Source/SWInfo/SWInfo.NT.hpp | 13 + Source/SWInfo/SWInfo.cpp | 120 +- Source/SWInfo/VersionHelpers.cpp | 3 +- Source/SWInfo/VersionHelpers.hpp | 8 + Source/Threading/Primitives/ConditionEx.cpp | 2 +- .../Primitives/ConditionMutex.Generic.cpp | 2 +- .../Primitives/ConditionMutex.NT.cpp | 2 +- .../Primitives/ConditionVariable.Generic.cpp | 2 +- .../Primitives/ConditionVariable.NT.cpp | 3 +- .../Threading/Primitives/CriticalSection.cpp | 2 +- Source/Threading/Primitives/Event.cpp | 34 +- Source/Threading/Primitives/Mutex.Generic.cpp | 2 +- Source/Threading/Primitives/Mutex.NT.cpp | 2 +- Source/Threading/Primitives/RWLock.cpp | 111 +- Source/Threading/Primitives/RWLock.hpp | 10 +- .../Threading/Primitives/Semaphore.Apple.cpp | 0 .../Primitives/Semaphore.Generic.cpp | 3 +- Source/Threading/Primitives/Semaphore.NT.cpp | 54 +- Source/Threading/Primitives/Semaphore.NT.hpp | 9 +- .../Threading/Primitives/Semaphore.Unix.cpp | 2 +- Source/Threading/Threads/SpawnThread.Unix.cpp | 2 +- Source/Threading/Threads/ThreadHandles.cpp | 69 +- Source/Threading/Threads/ThreadHandles.hpp | 3 + Source/Threading/Threads/Threads.cpp | 2 +- Source/Time/Clock.cpp | 13 +- readme.md | 363 +++-- 410 files changed, 14066 insertions(+), 5180 deletions(-) create mode 100644 Include/Aurora/CmdLine/CmdLine.hpp delete mode 100644 Include/Aurora/Console/Logging/IBasicSink.hpp delete mode 100644 Include/Aurora/Console/Logging/IBasicSinkRB.hpp delete mode 100644 Include/Aurora/Console/Logging/Sinks.hpp create mode 100644 Include/Aurora/Exit/ETriggerLevel.hpp create mode 100644 Include/Aurora/Exit/Exit.hpp create mode 100644 Include/Aurora/Exit/IExitSubscriber.hpp delete mode 100644 Include/Aurora/IO/Buffered/BlobArbitraryReader.hpp rename Source/IO/Character/LineBuffer.cpp => Include/Aurora/IO/Buffered/BlobBuilder.hpp (100%) create mode 100644 Include/Aurora/IO/Buffered/BlobSeekableReader.hpp create mode 100644 Include/Aurora/IO/Character/IBufferedLineReader.hpp create mode 100644 Include/Aurora/IO/Character/ICharacterProviderEx.hpp create mode 100644 Include/Aurora/IO/Character/Providers.hpp create mode 100644 Include/Aurora/IO/FS/EFileAdvisoryLockLevel.hpp create mode 100644 Include/Aurora/IO/FS/EFileOpenMode.hpp rename Include/Aurora/IO/FS/{FileArbitraryReader.hpp => FileSeekableReader.hpp} (75%) create mode 100644 Include/Aurora/IO/FS/IAsyncFileStream.hpp create mode 100644 Include/Aurora/IO/FS/IAsyncFinishedSubscriber.hpp create mode 100644 Include/Aurora/IO/FS/IAsyncTransaction.hpp rename Include/Aurora/IO/{IArbitraryStreamer.hpp => ISeekingReader.hpp} (57%) create mode 100644 Include/Aurora/IO/IStreamReader.inl create mode 100644 Include/Aurora/Logging/IBasicSink.hpp create mode 100644 Include/Aurora/Logging/IBasicSinkRB.hpp rename Include/Aurora/{Console => }/Logging/ILogger.hpp (88%) rename Include/Aurora/{Console => }/Logging/Logging.hpp (89%) rename Include/Aurora/{Console => Logging}/README.txt (100%) create mode 100644 Include/Aurora/Logging/Sinks.hpp create mode 100644 Include/Aurora/Loop/ELoopSource.hpp create mode 100644 Include/Aurora/Loop/ILoopQueue.hpp create mode 100644 Include/Aurora/Loop/ILoopSource.hpp create mode 100644 Include/Aurora/Loop/ILoopSourceSubscriber.hpp create mode 100644 Include/Aurora/Memory/ByteBufferPushReadState.hpp create mode 100644 Include/Aurora/Memory/ByteBufferPushWriteState.hpp create mode 100644 Include/Aurora/Memory/ByteBuffer_Strings.inl create mode 100644 Include/Aurora/Memory/ByteBuffer_Utility.inl create mode 100644 Include/Aurora/Memory/ByteBuffer_WriteFrom.inl create mode 100644 Include/Aurora/Processes/ICommandFinished.hpp create mode 100644 Include/Aurora/RNG/RandomDef.hpp create mode 100644 Include/Aurora/Utility/RateLimiter.hpp create mode 100644 Include/auROXTL.hpp create mode 100644 Include/auROXTL/AU_MACROS.hpp create mode 100644 Include/auROXTL/auArray.hpp create mode 100644 Include/auROXTL/auAtomic.hpp create mode 100644 Include/auROXTL/auBST.hpp create mode 100644 Include/auROXTL/auBitsUtils.hpp create mode 100644 Include/auROXTL/auCastUtils.hpp create mode 100644 Include/auROXTL/auContainerUtils.hpp create mode 100644 Include/auROXTL/auCopyMoveUtils.hpp create mode 100644 Include/auROXTL/auEndianness.hpp create mode 100644 Include/auROXTL/auFunctional.hpp create mode 100644 Include/auROXTL/auHashMap.hpp create mode 100644 Include/auROXTL/auList.hpp create mode 100644 Include/auROXTL/auMagicUtils.hpp create mode 100644 Include/auROXTL/auMemory.hpp create mode 100644 Include/auROXTL/auMemoryModel.hpp create mode 100644 Include/auROXTL/auNumberUtils.hpp create mode 100644 Include/auROXTL/auOptional.hpp create mode 100644 Include/auROXTL/auPosixUtils.hpp create mode 100644 Include/auROXTL/auString.hpp create mode 100644 Include/auROXTL/auStringUtils.hpp create mode 100644 Include/auROXTL/auTemplateMeta.hpp create mode 100644 Include/auROXTL/auTransform.hpp create mode 100644 Include/auROXTL/auTuple.hpp create mode 100644 Include/auROXTL/auTupleUtils.hpp create mode 100644 Include/auROXTL/auTypeUtils.hpp create mode 100644 Include/auROXTL/auTypes.hpp create mode 100644 Include/auROXTL/auVector.hpp create mode 100644 Include/auROXTL/auWin32Utils.hpp create mode 100644 Include/auROXTLTypes.hpp create mode 100644 Include/auROXTLUtils.hpp create mode 100644 Media/Aurora Keys - test.reg create mode 100644 Media/Aurora Keys.reg create mode 100644 Media/ICanHasStackTraces.png create mode 100644 Media/wxHello.png create mode 100644 Source/CmdLine/CmdLine.cpp create mode 100644 Source/CmdLine/CmdLine.hpp create mode 100644 Source/CmdLine/CmdLinePlatform.cpp create mode 100644 Source/CmdLine/CmdLinePlatform.hpp create mode 100644 Source/Compression/BaseStream.cpp create mode 100644 Source/Compression/BaseStream.hpp create mode 100644 Source/Compression/Compressors/BZip2Compressor.hpp create mode 100644 Source/Compression/Compressors/BZip2Decompressor.hpp create mode 100644 Source/Compression/Compressors/DeflateCompressor.hpp create mode 100644 Source/Compression/Compressors/DeflateDecompressor.hpp create mode 100644 Source/Compression/Compressors/LZ4Compressor.hpp create mode 100644 Source/Compression/Compressors/LZ4Decompressor.hpp create mode 100644 Source/Compression/Compressors/ZSTDCompressor.hpp create mode 100644 Source/Compression/Compressors/ZSTDDecompressor.hpp create mode 100644 Source/Compression/IngestableReadBase.hpp create mode 100644 Source/Compression/IngestableReadBase.inl delete mode 100644 Source/Console/ConsoleFIO/FileSink.cpp delete mode 100644 Source/Console/Logging/Sinks.cpp delete mode 100644 Source/Console/Logging/Sinks.hpp delete mode 100644 Source/Crypto/ECC/ECCX25519.cpp delete mode 100644 Source/Crypto/ECC/ECCX25519.hpp create mode 100644 Source/Crypto/ECC/ECCX25519Private.cpp create mode 100644 Source/Crypto/ECC/ECCX25519Private.hpp create mode 100644 Source/Crypto/ECC/ECCX25519Public.cpp create mode 100644 Source/Crypto/ECC/ECCX25519Public.hpp create mode 100644 Source/Debug/GrugException.hpp create mode 100644 Source/Exit/Exit.cpp create mode 100644 Source/Exit/Exit.hpp create mode 100644 Source/Exit/MTWatchDog.cpp create mode 100644 Source/Exit/MTWatchDog.hpp create mode 100644 Source/Extensions/LTC/x509_decode_subject_public_key_info_2.c create mode 100644 Source/Grug/Arrow.cpp create mode 100644 Source/Grug/Arrow.hpp create mode 100644 Source/Grug/Grug.cpp create mode 100644 Source/Grug/Grug.hpp create mode 100644 Source/Grug/GrugThread.cpp create mode 100644 Source/Grug/GrugThread.hpp create mode 100644 Source/IO/Buffered/BlobBuilder.cpp create mode 100644 Source/IO/Buffered/BlobBuilder.hpp create mode 100644 Source/IO/Character/BufferedLineReader.cpp create mode 100644 Source/IO/Character/BufferedLineReader.hpp create mode 100644 Source/IO/Character/StringToProvider.cpp rename Include/Aurora/IO/Character/ILineBufferer.hpp => Source/IO/Character/StringToProvider.hpp (74%) create mode 100644 Source/IO/FS/FileAdvisory.NT.cpp create mode 100644 Source/IO/FS/FileAdvisory.NT.hpp create mode 100644 Source/IO/FS/FileAdvisory.Unix.cpp rename Source/IO/{Character/LineBuffer.hpp => FS/FileAdvisory.Unix.hpp} (100%) create mode 100644 Source/IO/Net/BaseChannel.cpp create mode 100644 Source/IO/Net/BaseChannel.hpp create mode 100644 Source/IO/Net/BaseLocalClient.cpp create mode 100644 Source/IO/Net/BaseLocalClient.hpp create mode 100644 Source/IO/Net/BaseNetworkInterface.cpp create mode 100644 Source/IO/Net/BaseNetworkInterface.hpp create mode 100644 Source/IO/Net/BaseServer.cpp create mode 100644 Source/IO/Net/BaseServer.hpp create mode 100644 Source/IO/Net/BaseSocket.cpp create mode 100644 Source/IO/Net/BaseSocket.hpp create mode 100644 Source/IO/Net/HelloNet.Win32.cpp create mode 100644 Source/IO/Net/HelloNet.Win32.hpp create mode 100644 Source/IO/Net/IPAddress.cpp create mode 100644 Source/IO/Net/IPAddress.hpp create mode 100644 Source/IO/Net/NetworkingPool.cpp create mode 100644 Source/IO/Net/NetworkingPool.hpp create mode 100644 Source/IO/Net/PlatformChannel.Win32.cpp create mode 100644 Source/IO/Net/PlatformChannel.Win32.hpp create mode 100644 Source/IO/Net/PlatformChannel.hpp create mode 100644 Source/IO/Net/PlatformSocket.Win32.cpp create mode 100644 Source/IO/Net/PlatformSocket.Win32.hpp create mode 100644 Source/IO/Net/PlatformSocket.hpp create mode 100644 Source/IO/Net/SocketFactory.cpp create mode 100644 Source/IO/Net/SocketFactory.hpp create mode 100644 Source/IO/Net/WorkPoolGroup.cpp create mode 100644 Source/IO/Net/WorkPoolGroup.hpp create mode 100644 Source/IO/Net/WorkRange.cpp create mode 100644 Source/IO/Net/WorkRange.hpp create mode 100644 Source/Locale/Encoding/BOM.cpp create mode 100644 Source/Locale/Encoding/BOM.hpp rename Source/{Console => }/Logging/Logger.cpp (67%) rename Source/{Console => }/Logging/Logger.hpp (74%) create mode 100644 Source/Logging/Logging.cpp create mode 100644 Source/Logging/Logging.hpp create mode 100644 Source/Logging/Sinks.cpp create mode 100644 Source/Logging/Sinks.hpp create mode 100644 Source/Logging/Sinks/DirLogArchive.cpp create mode 100644 Source/Logging/Sinks/DirLogArchive.hpp create mode 100644 Source/Logging/Sinks/EventLog.Win32.cpp create mode 100644 Source/Logging/Sinks/EventLog.Win32.hpp create mode 100644 Source/Logging/Sinks/FileSink.cpp rename Source/{Console/ConsoleFIO => Logging/Sinks}/FileSink.hpp (58%) create mode 100644 Source/Logging/Sinks/RingBuffer.cpp create mode 100644 Source/Logging/Sinks/RingBuffer.hpp create mode 100644 Source/Logging/Sinks/StdConsole.cpp create mode 100644 Source/Logging/Sinks/StdConsole.hpp create mode 100644 Source/Logging/Sinks/SysLog.Unix.cpp create mode 100644 Source/Logging/Sinks/SysLog.Unix.hpp create mode 100644 Source/Logging/Sinks/SystemD.Unix.cpp create mode 100644 Source/Logging/Sinks/SystemD.Unix.hpp create mode 100644 Source/Loop/LoopQueue.BSD.cpp rename Source/{Threading/Primitives/Sempahore.Apple.cpp => Loop/LoopQueue.BSD.hpp} (100%) create mode 100644 Source/Loop/LoopQueue.Linux.cpp create mode 100644 Source/Loop/LoopQueue.Linux.hpp create mode 100644 Source/Loop/LoopQueue.NT.cpp create mode 100644 Source/Loop/LoopQueue.NT.hpp create mode 100644 Source/Loop/WORK_IN_PROGRESS.txt rename Source/Loop/{WaitSingle.Linux.cpp => WaitSingle.Unix.cpp} (88%) rename Source/Loop/{WaitSingle.Linux.hpp => WaitSingle.Unix.hpp} (84%) delete mode 100644 Source/Memory/ByteBuffer.cpp delete mode 100644 Source/Memory/ByteBuffer.hpp create mode 100644 Source/Processes/ArgvQuote.cpp create mode 100644 Source/Processes/ArgvQuote.hpp create mode 100644 Source/SWInfo/SWInfo.Linux.cpp create mode 100644 Source/SWInfo/SWInfo.Linux.hpp create mode 100644 Source/SWInfo/SWInfo.NT.cpp create mode 100644 Source/SWInfo/SWInfo.NT.hpp create mode 100644 Source/SWInfo/VersionHelpers.hpp create mode 100644 Source/Threading/Primitives/Semaphore.Apple.cpp diff --git a/Aurora.json b/Aurora.json index 214db0cf..33c8a488 100644 --- a/Aurora.json +++ b/Aurora.json @@ -15,7 +15,7 @@ { "filter": {"platforms": "win32"}, "then": { - "links": ["Bcrypt.lib", "UxTheme.lib", "Aux_ulib.lib", "Dbghelp.lib", "ws2_32.lib", "Ntdll.lib"] + "links": ["Bcrypt.lib", "UxTheme.lib", "Aux_ulib.lib", "Dbghelp.lib", "ws2_32.lib", "Ntdll.lib", "Wer.lib", "wintrust.lib"] } } ] diff --git a/Include/Aurora/Async/AsyncTypes.hpp b/Include/Aurora/Async/AsyncTypes.hpp index 33c417c4..d4863e04 100644 --- a/Include/Aurora/Async/AsyncTypes.hpp +++ b/Include/Aurora/Async/AsyncTypes.hpp @@ -9,7 +9,7 @@ namespace Aurora::Loop { - class ILoopSource; + struct ILoopSource; } namespace Aurora::Async diff --git a/Include/Aurora/Async/IThreadPool.hpp b/Include/Aurora/Async/IThreadPool.hpp index 7bb06455..25f7f864 100644 --- a/Include/Aurora/Async/IThreadPool.hpp +++ b/Include/Aurora/Async/IThreadPool.hpp @@ -51,9 +51,10 @@ namespace Aurora::Async virtual WorkerId_t GetCurrentThread() = 0; // Synchronization - // Note: syncing to yourself will nullify requireSignal to prevent deadlock + // Note: syncing to yourself will nullify requireSignal to prevent deadlock conditions virtual bool Sync(WorkerId_t workerId, AuUInt32 timeoutMs = 0, bool requireSignal = false) = 0; virtual void Signal(WorkerId_t workerId) = 0; + virtual AuSPtr WorkerToLoopSource(WorkerId_t id) = 0; virtual void SyncAllSafe() = 0; // Features diff --git a/Include/Aurora/Async/IWorkItem.hpp b/Include/Aurora/Async/IWorkItem.hpp index 98decb95..327da125 100644 --- a/Include/Aurora/Async/IWorkItem.hpp +++ b/Include/Aurora/Async/IWorkItem.hpp @@ -32,6 +32,7 @@ namespace Aurora::Async // ns = time relative to the time at which the work item would otherwise dispatch virtual AuSPtr AddDelayTimeNs(AuUInt64 ns) = 0; + // inverted WaitFor virtual AuSPtr Then(const AuSPtr &next) = 0; virtual AuSPtr Dispatch() = 0; diff --git a/Include/Aurora/Async/JobFrom.hpp b/Include/Aurora/Async/JobFrom.hpp index d8b8f429..834ed424 100644 --- a/Include/Aurora/Async/JobFrom.hpp +++ b/Include/Aurora/Async/JobFrom.hpp @@ -37,7 +37,7 @@ namespace Aurora::Async FJob, Out_t> ret; ret.onSuccess = [=](const AuTuple &in, const Out_t &a) { - std::apply(onSuccess, std::tuple_cat(in, AuMakeTuple(a))); + AuTupleApply(onSuccess, AuTupleCat(in, AuMakeTuple(a))); }; return ret; } @@ -48,12 +48,12 @@ namespace Aurora::Async FJob, Out_t> ret; ret.onSuccess = [=](const AuTuple &in, const Out_t &a) { - std::apply(onSuccess, std::tuple_cat(in, AuMakeTuple(a))); + AuTupleApply(onSuccess, AuTupleCat(in, AuMakeTuple(a))); }; ret.onFailure = [=](const AuTuple &in) { - std::apply(onFailure, in); + AuTupleApply(onFailure, in); }; return ret; } @@ -115,7 +115,7 @@ namespace Aurora::Async FJob, ReturnValue_t> ret; ret.onSuccess = [=](const AuTuple &in, const ReturnValue_t &out) { - onSuccess(std::get<0>(in), out); + onSuccess(AuGet<0>(in), out); }; return ret; } @@ -126,12 +126,12 @@ namespace Aurora::Async FJob, ReturnValue_t> ret; ret.onSuccess = [=](const AuTuple &in, const ReturnValue_t &out) { - onSuccess(std::get<0>(in), out); + onSuccess(AuGet<0>(in), out); }; ret.onFailure = [=](const AuTuple &in) { - onFailure(std::get<0>(in)); + onFailure(AuGet<0>(in)); }; return ret; } @@ -154,7 +154,7 @@ namespace Aurora::Async FJob, Args...>, ReturnValue_t> ret; ret.onSuccess = [=](const AuTuple, Args...> &in, const ReturnValue_t &out) { - std::apply(onSuccess, std::tuple_cat(AuTuplePopFront(in), AuMakeTuple(out))); + AuTupleApply(onSuccess, AuTupleCat(AuTuplePopFront(in), AuMakeTuple(out))); }; return ret; } @@ -177,7 +177,7 @@ namespace Aurora::Async FJob, ReturnValue_t> ret; ret.onSuccess = [=](const AuTuple &in, const ReturnValue_t &out) { - std::apply(onSuccess, std::tuple_cat(in, AuMakeTuple(out))); + AuTupleApply(onSuccess, AuTupleCat(in, AuMakeTuple(out))); }; return ret; } diff --git a/Include/Aurora/Async/TaskFrom.hpp b/Include/Aurora/Async/TaskFrom.hpp index 0bcfceac..bd894384 100644 --- a/Include/Aurora/Async/TaskFrom.hpp +++ b/Include/Aurora/Async/TaskFrom.hpp @@ -34,7 +34,7 @@ namespace Aurora::Async FTask, Out_t> ret; ret.onFrame = [callable = func](const AuTuple &in) -> Out_t { - return std::apply(callable, in); + return AuTupleApply(callable, in); }; return ret; } @@ -45,7 +45,7 @@ namespace Aurora::Async FTask, Out_t> ret; ret.onFrame = [callable = func](const AuTuple &in) -> Out_t { - return std::apply(callable, AuTuple_cat(AuMakeTuple(ownerToPin), in)); + return AuTupleApply(callable, AuTupleCat(AuMakeTuple(ownerToPin), in)); }; return ret; } @@ -56,7 +56,7 @@ namespace Aurora::Async Task_t ret; ret.onFrame = [callable = func](const auto &in) -> ReturnValue_t { - return std::apply(callable, AuTuplePopFront(in)); + return AuTupleApply(callable, AuTuplePopFront(in)); }; return ret; } @@ -67,7 +67,7 @@ namespace Aurora::Async Task_t ret; ret.onFrame = [callable = func](const auto &in) -> ReturnValue_t { - return std::apply(callable, AuTuplePopFront(in)); + return AuTupleApply(callable, AuTuplePopFront(in)); }; return ret; } diff --git a/Include/Aurora/CmdLine/CmdLine.hpp b/Include/Aurora/CmdLine/CmdLine.hpp new file mode 100644 index 00000000..3b3b253b --- /dev/null +++ b/Include/Aurora/CmdLine/CmdLine.hpp @@ -0,0 +1,59 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: CmdLine.hpp + Date: 2022-1-31 + Author: Reece + Note: Even kernels have a commandline so why not? +***/ +#pragma once + +namespace Aurora::CmdLine +{ + /** + * @brief Returns a UTF-8 string array of argv[1, ...] + * @return + */ + AUKN_SYM const AuList &GetCommandLineArguments(); + + /** + * @brief Performs a check on whether the exact key matches an argument + * @param key + * @return + */ + AUKN_SYM bool HasFlag(const AuString &key); + + /** + * @brief Performs a check on whether such string came before an equals sign + * @param key + * @return + */ + AUKN_SYM bool HasValue(const AuString &key); + + /** + * @brief Returns part after key= or defaultDefault + * @param key + * @param defaultValue + * @return + */ + AUKN_SYM const AuString &GetValue(const AuString &key, const AuString &defaultValue); + + /** + * @brief Returns part after key= or an empty string + * @param key + * @return + */ + AUKN_SYM const AuString &GetValue(const AuString &key); + + /** + * @brief Returns a constant array of flag keys + * @return + */ + AUKN_SYM const AuList &GetFlags(); + + /** + * @brief Returns a constant array of value keys + * @return + */ + AUKN_SYM const AuList &GetValues(); +} \ No newline at end of file diff --git a/Include/Aurora/Compression/BasicCompression.hpp b/Include/Aurora/Compression/BasicCompression.hpp index f553014b..c992c698 100644 --- a/Include/Aurora/Compression/BasicCompression.hpp +++ b/Include/Aurora/Compression/BasicCompression.hpp @@ -12,20 +12,10 @@ namespace Aurora::Compression /** Compresses an in memory blob with zstandard */ - AUKN_SYM bool Compress(const void *buffer, AuUInt32 length, Memory::ByteBuffer &out, int compressionLevel = 3); - - /** - Compresses an in memory blob with zstandard - */ - AUKN_SYM bool Compress(const Memory::ByteBuffer &in, Memory::ByteBuffer &out, int compressionLevel = 3); + AUKN_SYM bool Compress(const Memory::MemoryViewRead &source, Memory::ByteBuffer &out, int compressionLevel = 3); /** Decompresses an in memory blob with zstandard */ - AUKN_SYM bool Decompress(const void *buffer, AuUInt32 length, Memory::ByteBuffer &out); - - /** - Decompresses an in memory blob with zstandard - */ - AUKN_SYM bool Decompress(const Memory::ByteBuffer &in, Memory::ByteBuffer &out); + AUKN_SYM bool Decompress(const Memory::MemoryViewRead &source, Memory::ByteBuffer &out); } \ No newline at end of file diff --git a/Include/Aurora/Compression/Compression.hpp b/Include/Aurora/Compression/Compression.hpp index 2bb6ab2d..14b5f44c 100644 --- a/Include/Aurora/Compression/Compression.hpp +++ b/Include/Aurora/Compression/Compression.hpp @@ -7,6 +7,44 @@ ***/ #pragma once + +// Types +#include "ECompresionType.hpp" +#include "CompressionInfo.hpp" + +// Legacy API +#include "StreamPipeProcessor.hpp" + +// Recommended API +#include "ICompressionStream.hpp" +#include "StreamProcessor.hpp" + +// Utility +#include "BasicCompression.hpp" + + + +// TODO: neat comment + real world data + + + + + + + + + + + + + + + + + + + + /* Ballpark figures of real world performance: https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=benchmarks+(2019+update) @@ -23,14 +61,4 @@ LZ4 -> Network compression and other large data streams (~4.5GB/s, 2.884 compression ratio) ZSTD -> Standard use (~1.5GB/s to 2.5GB/s, respective compression ratios 2.4 and 2.1. Can be pushed to ~10 at around 750MB/s. Great general use. ) ZIP -> Zlib has a disgusting decompression upper limit of around 450MB/s for 2.7 -*/ - -#include "BasicCompression.hpp" - -#include "ECompresionType.hpp" -#include "CompressionInfo.hpp" - -#include "StreamPipeProcessor.hpp" - -#include "ICompressionStream.hpp" -#include "StreamProcessor.hpp" \ No newline at end of file +*/ \ No newline at end of file diff --git a/Include/Aurora/Compression/CompressionInfo.hpp b/Include/Aurora/Compression/CompressionInfo.hpp index 541db09a..6a06d083 100644 --- a/Include/Aurora/Compression/CompressionInfo.hpp +++ b/Include/Aurora/Compression/CompressionInfo.hpp @@ -12,39 +12,94 @@ namespace Aurora::Compression struct CompressionInfo { ECompresionType type; + + /** + * @brief + * + * ZSTD: -5 <= level <= 22 + * recommended: ZSTD_CLEVEL_DEFAULT + * LZMA: 0 <= level <= 9 + * LZ4 : N/A + * Deflate: 0 <= x >= 9, + * recommended: 6 + * Zip: 0 <= x >= 9, + * recommended: 6 + * GZip: 0 <= x >= 9, + * recommended: 6 + * BZIP: 0 <= x >= 9 + * + */ + AuInt8 compressionLevel {6}; - /// ZSTD: -5 <= level <= 22 - /// recommended: ZSTD_CLEVEL_DEFAULT - /// LZMA: 0 <= level <= 9 - /// LZ4 : N/A - /// ZLIB: 0 <= x >= 9 - /// recommended: 6 - /// BZIP: 0 <= x >= 9 - AuInt8 compressionLevel{}; + /** + * @brief LZMA: 5 <= fb <= 273, default = 32 + */ + AuUInt32 fbWordSize {32}; - /// LZMA: 5 <= fb <= 273, default = 32 - AuUInt32 fbWordSize{}; - - /// LZMA only - /// (1 << 12) <= dictSize <= (1 << 27) for 32-bit version - /// (1 << 12) <= dictSize <= (3 << 29) for 64-bit version - /// default = (1 << 24) + /** + * LZMA only + * (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + * (1 << 12) <= dictSize <= (3 << 29) for 64-bit version + * default = (1 << 24) + */ AuUInt32 dictSize{}; - // 64KiB is a recommended "small" block size + /** + * @brief 64KiB is a recommended "small" block size + */ AuUInt16 lz4BlockSize {}; - }; + + /** + * @brief DEFLATE related variabl + * + * Deflate: 0 <= x >= 15, + * recommended: 15 + * Zip: 0 <= x >= 15, + * recommended: 15 + * GZip: 0 <= x >= 15, + * recommended: 15 + */ + AuUInt8 windowBits {15}; + + /** + * @brief Internal output buffer size. + * Internal swap page is undefined. + */ + AuUInt32 internalStreamSize {4096}; + + AuUInt8 threads {1}; +; }; struct DecompressInfo { + /** + * @brief algorithm + */ ECompresionType alg {ECompresionType::eDeflate}; + /** + * @brief Internal output buffer size. Internal swap page is undefined. + */ + AuUInt32 internalStreamSize {4096}; + + /** + * @brief Flag for headerless decompression streams + */ + bool hasWindowbits {true}; + + /** + * @brief Flag for headerless decompression streams + */ + AuInt8 windowBits {15}; + DecompressInfo(ECompresionType alg) : alg(alg) { } - AuUInt32 internalStreamSize {}; - bool permitResize {}; + DecompressInfo(ECompresionType alg, AuUInt32 bufferSize) : alg(alg), internalStreamSize(bufferSize) + { + + } }; } \ No newline at end of file diff --git a/Include/Aurora/Compression/ECompresionType.hpp b/Include/Aurora/Compression/ECompresionType.hpp index df3fc124..3bfe5097 100644 --- a/Include/Aurora/Compression/ECompresionType.hpp +++ b/Include/Aurora/Compression/ECompresionType.hpp @@ -9,12 +9,14 @@ namespace Aurora::Compression { - enum class ECompresionType - { + AUE_DEFINE(ECompresionType, + ( eLZMA, eZSTD, eDeflate, + eZip, + eGZip, eLZ4, eBZIP2 - }; + )); } \ No newline at end of file diff --git a/Include/Aurora/Compression/ICompressionStream.hpp b/Include/Aurora/Compression/ICompressionStream.hpp index 2139127d..87673253 100644 --- a/Include/Aurora/Compression/ICompressionStream.hpp +++ b/Include/Aurora/Compression/ICompressionStream.hpp @@ -9,25 +9,66 @@ namespace Aurora::Compression { - class ICompressionStream + struct ICompressionStream { - public: - /// Ingest n bytes from the input stream assigned to the compression object + /** + * @brief Ingest n bytes from the input stream assigned to the compression object. + * On error, returns {0, 0} or {bytesRead, 0} + * If the stream buffer runs out of memory, {bytesRead, 0} is expected, and although + * `GetAvailableProcessedBytes()` will still return some data, the decompressed data + * or uncompressed stream will be dropped in part, and you should destroy from the stream object + * @param bytesFromUnprocessedInputSource + * @return + */ virtual AuStreamReadWrittenPair_t Ingest(AuUInt32 bytesFromUnprocessedInputSource) = 0; - - /// Limited stream API - virtual bool ReadByProcessedN (void * /*opt*/, AuUInt32 minimumProcessed, AuStreamReadWrittenPair_t &pair, bool ingestUntilEOS = true) = 0; + + /** + * @brief Returns the available bytes for immediate release + * @return + */ + virtual AuUInt32 GetAvailableProcessedBytes() = 0; + + /** + * @brief Returns the internal overhead to store the seekable stream buffer + * @return + */ + virtual AuUInt32 GetInternalBufferSize() = 0; + + /** + * @brief Reads 'minimumProcessed', optionally into the first buffer, until EOS or destination length. + * If the destination is null and the length is a nonzero value, the stream seeks ahead + * If the destination is null and the length is a zero, {0, GetAvailableProcessedBytes} is returned + * @param destination + * @param ingestUntilEOS should continue to poll Ingest with an arbitrary page size to fulfill destination.length + * @return Bytes read / written + */ + virtual AuStreamReadWrittenPair_t ReadEx(const Memory::MemoryViewWrite & /*opt*/ destination, bool ingestUntilEOS = true) = 0; - /// Limited stream API - virtual bool ReadByProcessedN (void * /*opt*/, AuUInt32 minimumProcessed) = 0; + /** + * @brief Reads 'minimumProcessed', optionally into the first buffer, from the internal stream buffer + * @param destination + * @return Bytes written + */ + virtual AuUInt32 Read(const Memory::MemoryViewWrite & /*opt*/ destination) = 0; - /// Limited stream API + /** + * @brief Seek processed read functions backwards + * @param offset + * @return + */ virtual bool GoBackByProcessedN (AuUInt32 offset) = 0; - /// Limited stream API + /** + * @brief Seek read processed forward + * @param offset + * @return + */ virtual bool GoForwardByProcessedN(AuUInt32 offset) = 0; /// Compression only - virtual void Flush() = 0; + virtual bool Flush() = 0; + + /// Compression only + virtual bool Finish() = 0; }; } \ No newline at end of file diff --git a/Include/Aurora/Compression/StreamPipeProcessor.hpp b/Include/Aurora/Compression/StreamPipeProcessor.hpp index af0f25c0..8650311a 100644 --- a/Include/Aurora/Compression/StreamPipeProcessor.hpp +++ b/Include/Aurora/Compression/StreamPipeProcessor.hpp @@ -14,7 +14,7 @@ namespace Aurora::Compression /// algorithm /// LZMA decompression + compression, and ZSTD compression only - AuUInt32 threads; + AuUInt32 threads {1}; /// consume from stream callback AuFunction inPipe; diff --git a/Include/Aurora/Compression/StreamProcessor.hpp b/Include/Aurora/Compression/StreamProcessor.hpp index 88017c13..767846d4 100644 --- a/Include/Aurora/Compression/StreamProcessor.hpp +++ b/Include/Aurora/Compression/StreamProcessor.hpp @@ -11,6 +11,13 @@ namespace Aurora::Compression { + /** + * @brief + */ AUKN_SHARED_API(Decompressor, ICompressionStream, const AuSPtr &reader, const DecompressInfo &info); + + /** + * @brief + */ AUKN_SHARED_API(Compressor, ICompressionStream, const AuSPtr &reader, const CompressionInfo &info); } \ No newline at end of file diff --git a/Include/Aurora/Console/Commands/Commands.hpp b/Include/Aurora/Console/Commands/Commands.hpp index 99694e79..81c7b440 100644 --- a/Include/Aurora/Console/Commands/Commands.hpp +++ b/Include/Aurora/Console/Commands/Commands.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include "ICommandSubscriber.hpp" namespace Aurora::Async { @@ -15,8 +16,6 @@ namespace Aurora::Async struct WorkerPId_t; } -#include "ICommandSubscriber.hpp" - namespace Aurora::Console::Commands { AUKN_SYM void AddCommand(const AuString &tag, const Parse::ParseObject &commandStructure, const AuSPtr &subscriber); diff --git a/Include/Aurora/Console/Console.hpp b/Include/Aurora/Console/Console.hpp index c2b697aa..c70e42c9 100644 --- a/Include/Aurora/Console/Console.hpp +++ b/Include/Aurora/Console/Console.hpp @@ -10,23 +10,13 @@ #include "EAnsiColor.hpp" #include "ConsoleMessage.hpp" +namespace Aurora::Logging +{ + struct ILogger; +} + namespace Aurora::Console { - namespace Logging - { - struct ILogger; - } - - /// Writes a log message to the console subscribers and telemetry outputs - AUKN_SYM void WriteLine(AuUInt8 level, const ConsoleMessage &msg); - - /** - * @brief Overloads the ILogger backend of the AuLogXX functions - * @param defaultGlobalLogger - * @return - */ - AUKN_SYM void SetGlobalLogger(const AuSPtr &defaultGlobalLogger); - /** * @brief Returns the untouched ILogger interface of the AuLogXX functions as configured by the Aurora::RuntimeStartInfo structure * @return @@ -63,4 +53,3 @@ namespace Aurora::Console #include "Commands/Commands.hpp" #include "Hooks/Hooks.hpp" -#include "Logging/Logging.hpp" \ No newline at end of file diff --git a/Include/Aurora/Console/ConsoleMessage.hpp b/Include/Aurora/Console/ConsoleMessage.hpp index ee1980e8..9cb2d6e6 100644 --- a/Include/Aurora/Console/ConsoleMessage.hpp +++ b/Include/Aurora/Console/ConsoleMessage.hpp @@ -47,6 +47,9 @@ namespace Aurora::Console tid = Threading::Threads::GetThreadId(); } + AUKN_SYM void Read(Memory::ByteBuffer &deserialize); + AUKN_SYM void Write(Memory::ByteBuffer &serialize) const; + AUKN_SYM AuString StringifyTime(bool simple = false) const; AUKN_SYM AuString StringifyTimeUTC() const; AUKN_SYM AuString GetWrappedTag() const; diff --git a/Include/Aurora/Console/EAnsiColor.hpp b/Include/Aurora/Console/EAnsiColor.hpp index 43f8c0bd..faf3e8f9 100644 --- a/Include/Aurora/Console/EAnsiColor.hpp +++ b/Include/Aurora/Console/EAnsiColor.hpp @@ -9,8 +9,8 @@ namespace Aurora::Console { - enum class EAnsiColor - { + AUE_DEFINE(EAnsiColor, + ( eRed, eBoldRed, eGreen, @@ -23,7 +23,6 @@ namespace Aurora::Console eBoldMagenta, eCyan, eBoldCyan, - eReset, - eCount - }; + eReset + )); } \ No newline at end of file diff --git a/Include/Aurora/Console/Logging/IBasicSink.hpp b/Include/Aurora/Console/Logging/IBasicSink.hpp deleted file mode 100644 index 86e59f60..00000000 --- a/Include/Aurora/Console/Logging/IBasicSink.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/*** - Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. - - File: IBasicSink.hpp - Date: 2021-11-1 - Author: Reece -***/ -#pragma once - -namespace Aurora::Console::Logging -{ - AUKN_INTERFACE(IBasicSink, - AUI_METHOD(void, OnMessageBlocking, (AuUInt8, level, const ConsoleMessage &, msg)), - AUI_METHOD(void, OnMessageNonblocking, (AuUInt8, level, const ConsoleMessage &, msg)), - AUI_METHOD(void, OnFlush, ()) - ) -} \ No newline at end of file diff --git a/Include/Aurora/Console/Logging/IBasicSinkRB.hpp b/Include/Aurora/Console/Logging/IBasicSinkRB.hpp deleted file mode 100644 index 4dbe4e19..00000000 --- a/Include/Aurora/Console/Logging/IBasicSinkRB.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/*** - Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. - - File: IBasicSinkRB.hpp - Date: 2021-11-2 - Author: Reece -***/ -#pragma once - -namespace Aurora::Console::Logging -{ - struct IBasicSinkRB : IBasicSink - { - virtual void SaveToPath(const AuString &path, bool plainText = false) = 0; - virtual AuList Export() = 0; - }; -} \ No newline at end of file diff --git a/Include/Aurora/Console/Logging/Sinks.hpp b/Include/Aurora/Console/Logging/Sinks.hpp deleted file mode 100644 index 845c0510..00000000 --- a/Include/Aurora/Console/Logging/Sinks.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/*** - Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. - - File: Sinks.hpp - Date: 2021-11-2 - Author: Reece -***/ -#pragma once - -namespace Aurora -{ - struct SocketConsole; -} - -namespace Aurora::Console::Logging -{ - AUKN_SHARED_API(NewStdSink, IBasicSink); - AUKN_SHARED_API(NewOSEventDirectorySink, IBasicSink); - AUKN_SHARED_API(NewFileSink, IBasicSink, const AuString &path, bool binary = false); - AUKN_SHARED_API(NewIPCSink, IBasicSink, const SocketConsole &console); - AUKN_SHARED_API(NewRingLogger, IBasicSinkRB, AuUInt32 approxMaxBytes); - AUKN_SHARED_API(NewLogger, ILogger, const AuList> &sinks); -} \ No newline at end of file diff --git a/Include/Aurora/Crypto/ECC/EECCCurve.hpp b/Include/Aurora/Crypto/ECC/EECCCurve.hpp index 3bab0804..1b930b56 100644 --- a/Include/Aurora/Crypto/ECC/EECCCurve.hpp +++ b/Include/Aurora/Crypto/ECC/EECCCurve.hpp @@ -9,12 +9,12 @@ namespace Aurora::Crypto::ECC { - enum EECCCurve - { + AUE_DEFINE(EECCCurve, + ( eCurve256, eCurve384, eCurve521, eCurveX25519, eCurveEd25519 - }; + )); } \ No newline at end of file diff --git a/Include/Aurora/Data/TypedValue.hpp b/Include/Aurora/Data/TypedValue.hpp index 560e8eb4..0efd45cf 100644 --- a/Include/Aurora/Data/TypedValue.hpp +++ b/Include/Aurora/Data/TypedValue.hpp @@ -13,5 +13,98 @@ namespace Aurora::Data { EDataType type; Value value; + + TypedValue() + { + type = EDataType::kTypeEND; + } + + #define TYPEDVALUE_CONSTRUCTOR(typen, typeval, datatype) inline TypedValue(typen typeval) : value(typeval), type(datatype) {} + + TYPEDVALUE_CONSTRUCTOR(const AuVec3 &, vec3, EDataType::kTypeVec3); + TYPEDVALUE_CONSTRUCTOR(const AuVec4 &, vec4, EDataType::kTypeVec4); + TYPEDVALUE_CONSTRUCTOR(bool, boolean, EDataType::kTypeBoolean); + TYPEDVALUE_CONSTRUCTOR(double, number, EDataType::kTypeNumber); + TYPEDVALUE_CONSTRUCTOR(AuInt64, sint, EDataType::kTypeSInt); + TYPEDVALUE_CONSTRUCTOR(AuUInt64, uint, EDataType::kTypeUInt); + TYPEDVALUE_CONSTRUCTOR(uuids::uuid, uuid, EDataType::kTypeUUID); + TYPEDVALUE_CONSTRUCTOR(const AuString &, str, EDataType::kTypeString); + + #undef TYPEDVALUE_CONSTRUCTOR + + + inline AuString ToString() const + { + if (!IsValid()) return "INVALID DATATYPE"; + switch (type) + { + case EDataType::kTypeUInt: + return AuToString(value.primitive.uint); + case EDataType::kTypeSInt: + return AuToString(value.primitive.sint); + case EDataType::kTypeNumber: + return AuToString(value.primitive.number); + case EDataType::kTypeString: + return value.string; + case EDataType::kTypeBoolean: + return value.primitive.boolean ? "true" : "false"; + case EDataType::kTypeUUID: + return uuids::to_string(value.UUID); + case EDataType::kTypeVec3: + return AuToString(value.primitive.vec3[0]) + "." + + AuToString(value.primitive.vec3[1]) + "." + + AuToString(value.primitive.vec3[2]); + case EDataType::kTypeVec4: + return AuToString(value.primitive.vec4[0]) + "." + + AuToString(value.primitive.vec4[1]) + "." + + AuToString(value.primitive.vec4[2]) + "." + + AuToString(value.primitive.vec4[3]); + default: + return {}; + } + return {}; + } + + inline bool operator==(const TypedValue &cmp) const + { + if (cmp.type != type) + { + return false; + } + + switch (type) + { + case EDataType::kTypeUInt: + return cmp.value.primitive.uint == value.primitive.uint; + case EDataType::kTypeSInt: + return cmp.value.primitive.sint == value.primitive.sint; + case EDataType::kTypeNumber: + return cmp.value.primitive.number == value.primitive.number; + case EDataType::kTypeString: + return cmp.value.string == value.string; + case EDataType::kTypeBoolean: + return cmp.value.primitive.boolean == value.primitive.boolean; + case EDataType::kTypeUUID: + return cmp.value.UUID == value.UUID; + case EDataType::kTypeVec3: + return cmp.value.primitive.vec3 == value.primitive.vec3; + case EDataType::kTypeVec4: + return cmp.value.primitive.vec4 == value.primitive.vec4; + default: + return false; + } + + return false; + } + + inline bool IsValid() const + { + return static_cast(type) < static_cast(EDataType::kTypeGenericMax); + } + + inline operator bool() const + { + return IsValid(); + } }; } \ No newline at end of file diff --git a/Include/Aurora/Debug/Debug.hpp b/Include/Aurora/Debug/Debug.hpp index f3a38c08..a5b851fb 100644 --- a/Include/Aurora/Debug/Debug.hpp +++ b/Include/Aurora/Debug/Debug.hpp @@ -48,7 +48,25 @@ namespace Aurora::Debug AUKN_SYM void CheckErrors(); - + /** + * @brief Specifies an EFailureCategory value for the current thread + * @param category + * @return + */ + AUKN_SYM void ErrorCategorySet(EFailureCategory category); + + /** + * @brief Guarantees a refresh of ErrorCategoryGet's current value + * @return + */ + AUKN_SYM void ErrorCategoryClear(); + + /** + * @brief Returns the last EFailureCategory as specified by ErrorCategorySet or SysPushErrors + * @return + */ + AUKN_SYM EFailureCategory ErrorCategoryGet(); + AUKN_SYM StackTrace GetStackTrace(); /** diff --git a/Include/Aurora/Debug/EFailureCategory.hpp b/Include/Aurora/Debug/EFailureCategory.hpp index 720cffd2..1dc5f1f1 100644 --- a/Include/Aurora/Debug/EFailureCategory.hpp +++ b/Include/Aurora/Debug/EFailureCategory.hpp @@ -34,7 +34,17 @@ namespace Aurora::Debug kFailureDisconnected, kFailureUninitialized, kFailureUnimplemented, - + kFailureCatch, + kFailureSubmission, + kFailureLockError, + kFailureNoAccess, + kFailureResourceMissing, + kFailureResourceLocked, + kFailureMalformedData, + kFailureInSandboxContext, + kFailureParseError, + + kFailureNone = 255, kFailureUserBegin = 256 }; } \ No newline at end of file diff --git a/Include/Aurora/Debug/SysAssertions.hpp b/Include/Aurora/Debug/SysAssertions.hpp index f5c4ea5d..fe92efb0 100644 --- a/Include/Aurora/Debug/SysAssertions.hpp +++ b/Include/Aurora/Debug/SysAssertions.hpp @@ -21,8 +21,8 @@ return; } - Aurora::Console::Logging::WriteLinef( - static_cast(Aurora::Console::Logging::ELogLevel::eError), + Aurora::Logging::WriteLinef( + static_cast(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", "Expression address: {} {}:{}", func, file, fileno); @@ -107,14 +107,14 @@ return; } - Aurora::Console::Logging::WriteLinef( - static_cast(Aurora::Console::Logging::ELogLevel::eError), + Aurora::Logging::WriteLinef( + static_cast(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", "Expression address: {} {}:{}", func, file, fileno); - Aurora::Console::Logging::WriteLinef( - static_cast(Aurora::Console::Logging::ELogLevel::eError), + Aurora::Logging::WriteLinef( + static_cast(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", "Expression failed: {}", exp); @@ -158,8 +158,8 @@ return; } - Aurora::Console::Logging::WriteLinef( - static_cast(Aurora::Console::Logging::ELogLevel::eError), + Aurora::Logging::WriteLinef( + static_cast(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", "Expression failed: {}", exp); diff --git a/Include/Aurora/Debug/SysErrors.hpp b/Include/Aurora/Debug/SysErrors.hpp index c1475702..d9f5996a 100644 --- a/Include/Aurora/Debug/SysErrors.hpp +++ b/Include/Aurora/Debug/SysErrors.hpp @@ -28,23 +28,55 @@ namespace Aurora::Debug #define _FREECOMPILER_OPTIMIZE_OFF __attribute__((optimize("0"))) #endif - static AU_NOINLINE void ErrorMakeNested() _FREECOMPILER_OPTIMIZE_OFF + // TODO: bring the xenus thing into here + + static AU_NOINLINE AuUInt GetIPNoBackend() _FREECOMPILER_OPTIMIZE_OFF + { + return _DBG_RET_ADDR; + } + + #if defined(AURORA_COMPILER_MSVC) + #pragma optimize("", on) + #endif + #undef _FREECOMPILER_OPTIMIZE_OFF + + static auline void ErrorMakeNested() { _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, nullptr); } template - static AU_NOINLINE void ErrorMakeNested(const AuString &msg, T&& ... args) _FREECOMPILER_OPTIMIZE_OFF + auline void ErrorMakeNested(const AuString &msg, T&& ... args) { - #if defined(_AUHAS_FMT) - _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, fmt::format(msg, AuForward(args)...).c_str()); - #else - _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, nullptr); - #endif + if constexpr (sizeof...(T) == 0) + { + _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, msg.c_str()); + } + else + { + #if defined(_AUHAS_FMT) + try + { + auto tempString = fmt::format(msg, AuForward(args)...); + _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, tempString.c_str()); + } + catch (...) + { + _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, msg.c_str()); + } + #else + _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, msg.c_str()); + #endif + } + } + + static auline void ErrorMakeNested(const char *msg) + { + _PushError(_DBG_RET_ADDR, EFailureCategory::kFailureNested, msg); } template - static AU_NOINLINE void SysPushError(EFailureCategory category, const AuString &msg, T&& ... args) _FREECOMPILER_OPTIMIZE_OFF + auline void SysPushError(EFailureCategory category, const AuString &msg, T&& ... args) { if constexpr (sizeof...(T) == 0) { @@ -53,22 +85,30 @@ namespace Aurora::Debug else { #if defined(_AUHAS_FMT) - _PushError(_DBG_RET_ADDR, category, fmt::format(msg, AuForward(args)...).c_str()); + try + { + auto tempString = fmt::format(msg, AuForward(args)...); + _PushError(_DBG_RET_ADDR, category, tempString.c_str()); + } + catch (...) + { + _PushError(_DBG_RET_ADDR, category, msg.c_str()); + } #else - _PushError(_DBG_RET_ADDR, category, "Missing dependency"); + _PushError(_DBG_RET_ADDR, category, msg.c_str()); #endif } } - static AU_NOINLINE void SysPushError(EFailureCategory category) _FREECOMPILER_OPTIMIZE_OFF + static auline void SysPushError(EFailureCategory category, const char *msg) + { + _PushError(_DBG_RET_ADDR, category, msg); + } + + static auline void SysPushError(EFailureCategory category) { _PushError(_DBG_RET_ADDR, category, nullptr); } - - #if defined(AURORA_COMPILER_MSVC) - #pragma optimize("", on) - #endif - #undef _FREECOMPILER_OPTIMIZE_OFF } #define SysCheckReturn(x, ...) if (!(static_cast(x))) { Aurora::Debug::ErrorMakeNested(); return __VA_ARGS__; } @@ -88,6 +128,7 @@ namespace Aurora::Debug // enums #define SysPushErrorGeneric(...) SysPushErrorError(kFailureGeneric, ## __VA_ARGS__) +#define SysPushErrorCatch(...) SysPushErrorError(kFailureCatch, ## __VA_ARGS__) #define SysPushErrorMemory(...) SysPushErrorError(kFailureMemory, ## __VA_ARGS__) #define SysPushErrorIO(...) SysPushErrorError(kFailureIO, ## __VA_ARGS__) #define SysPushErrorFIO(...) SysPushErrorError(kFailureFIO, ## __VA_ARGS__) @@ -109,6 +150,15 @@ namespace Aurora::Debug #define SysPushErrorDisconnected(...) SysPushErrorError(kFailureDisconnected, ## __VA_ARGS__) #define SysPushErrorUninitialized(...) SysPushErrorError(kFailureUninitialized, ## __VA_ARGS__) #define SysPushErrorUnimplemented(...) SysPushErrorError(kFailureUnimplemented, ## __VA_ARGS__) +#define SysPushErrorSubmission(...) SysPushErrorError(kFailureSubmission, ## __VA_ARGS__) +#define SysPushErrorLockError(...) SysPushErrorError(kFailureLockError, ## __VA_ARGS__) +#define SysPushErrorSyntax(...) SysPushErrorError(kFailureSyntax, ## __VA_ARGS__) +#define SysPushErrorNoAccess(...) SysPushErrorError(kFailureNoAccess, ## __VA_ARGS__) +#define SysPushErrorResourceMissing(...) SysPushErrorError(kFailureResourceMissing, ## __VA_ARGS__) +#define SysPushErrorResourceLocked(...) SysPushErrorError(kFailureResourceLocked, ## __VA_ARGS__) +#define SysPushErrorMalformedData(...) SysPushErrorError(kFailureMalformedData, ## __VA_ARGS__) +#define SysPushErrorInSandboxContext(...) SysPushErrorError(kFailureInSandboxContext, ## __VA_ARGS__) +#define SysPushErrorParseError(...) SysPushErrorError(kFailureParseError, ## __VA_ARGS__) #if defined(DEBUG) || defined(STAGING) @@ -144,6 +194,16 @@ namespace Aurora::Debug #define SysPushErrorDisconnectedDbg SysPushErrorDisconnected #define SysPushErrorUninitializedDbg SysPushErrorUninitialized #define SysPushErrorUnimplementedDbg SysPushErrorUnimplemented + #define SysPushErrorCatchDbg SysPushErrorCatch + #define SysPushErrorSubmissionDbg SysPushErrorSubmission + #define SysPushErrorLockErrorDbg SysPushErrorLockError + #define SysPushErrorSyntaxDbg SysPushErrorSyntax + #define SysPushErrorNoAccessDbg SysPushErrorNoAccess + #define SysPushErrorResourceMissingDbg SysPushErrorResourceMissing + #define SysPushErrorResourceLockedDbg SysPushErrorResourceLocked + #define SysPushErrorMalformedDataDbg SysPushErrorMalformedData + #define SysPushErrorInSandboxContextDbg SysPushErrorInSandboxContext + #define SysPushErrorParseErrorDbg SysPushErrorParseError #else @@ -177,5 +237,16 @@ namespace Aurora::Debug #define SysPushErrorDisconnectedDbg(...) #define SysPushErrorUninitializedDbg(...) #define SysPushErrorUnimplementedDbg(...) + #define SysPushErrorCatchDbg(...) + #define SysPushErrorSubmissionDbg(...) + #define SysPushErrorLockErrorDbg(...) + #define SysPushErrorSyntaxDbg(...) + #define SysPushErrorNoAccessDbg(...) + #define SysPushErrorResourceMissingDbg(...) + #define SysPushErrorResourceLockedDbg(...) + #define SysPushErrorMalformedDataDbg(...) + #define SysPushErrorInSandboxContextDbg(...) + #define SysPushErrorParseErrorDbg(...) + #endif diff --git a/Include/Aurora/Debug/SysPanic.hpp b/Include/Aurora/Debug/SysPanic.hpp index de377468..d9e35e67 100644 --- a/Include/Aurora/Debug/SysPanic.hpp +++ b/Include/Aurora/Debug/SysPanic.hpp @@ -9,9 +9,9 @@ #if defined(_AUHAS_FMT) template -static inline void __declspec(noreturn) SysPanic(T... args) +static inline void AU_NORETURN SysPanic(T... args) { - Aurora::Console::Logging::WriteLinef(static_cast(Aurora::Console::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", AuForward(args)...); + Aurora::Logging::WriteLinef(static_cast(Aurora::Logging::ELogLevel::eError), Aurora::Console::EAnsiColor::eBoldRed, "Fatal", AuForward(args)...); Aurora::Debug::Panic(); } #endif \ No newline at end of file diff --git a/Include/Aurora/Exit/ETriggerLevel.hpp b/Include/Aurora/Exit/ETriggerLevel.hpp new file mode 100644 index 00000000..da05c645 --- /dev/null +++ b/Include/Aurora/Exit/ETriggerLevel.hpp @@ -0,0 +1,26 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ETriggerLevel.hpp + Date: 2022-1-30 + Author: Reece +***/ +#pragma once + +namespace Aurora::Exit +{ + AUE_DEFINE(ETriggerLevel, ( + + // Runtime deinitialize + eSafeTermination, + + // A fatal exception was caught by the watchdog. The process is on its way out + eFatalException, + + // Control+C was sent, termination must follow + eSigTerminate, + + // Something went wrong in the process. These could be frequent depending on the process + eProblematicEvent + )); +} \ No newline at end of file diff --git a/Include/Aurora/Exit/Exit.hpp b/Include/Aurora/Exit/Exit.hpp new file mode 100644 index 00000000..d4fd9918 --- /dev/null +++ b/Include/Aurora/Exit/Exit.hpp @@ -0,0 +1,36 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: Exit.hpp + Date: 2022-1-30 + Author: Reece +***/ +#pragma once + +#include "ETriggerLevel.hpp" +#include "IExitSubscriber.hpp" + +namespace Aurora::Exit +{ + /** + * @brief Registers @param callback to the registry to subscribe to @param level events + * @param level + * @param callback + * @return + */ + AUKN_SYM bool ExitHandlerAdd(ETriggerLevel level, const AuSPtr &callback); + + /** + * @brief Removes all exit handlers by pointer + * @param callback + * @return + */ + AUKN_SYM void ExitHandlerRemove(const AuSPtr &callback); + + + /** + * @brief Used from within callbacks to determine if the application is shutting down. + * @return + */ + AUKN_SYM bool IsAppRunning(); +} \ No newline at end of file diff --git a/Include/Aurora/Exit/IExitSubscriber.hpp b/Include/Aurora/Exit/IExitSubscriber.hpp new file mode 100644 index 00000000..540c74f7 --- /dev/null +++ b/Include/Aurora/Exit/IExitSubscriber.hpp @@ -0,0 +1,23 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IExitSubscriber.hpp + Date: 2022-1-30 + Author: Reece +***/ +#pragma once + +namespace Aurora::Exit +{ + struct ExitInvoker + { + Threading::Threads::IAuroraThread *pCaller; + }; + + /** + * @brief User definedable callback + */ + AUKN_INTERFACE(IExitSubscriber, + AUI_METHOD(void, OnTrigger, (ETriggerLevel, level, const ExitInvoker *, pInvoker)) + ); +} \ No newline at end of file diff --git a/Include/Aurora/HWInfo/CpuBitId.hpp b/Include/Aurora/HWInfo/CpuBitId.hpp index 11bd74af..e846666c 100644 --- a/Include/Aurora/HWInfo/CpuBitId.hpp +++ b/Include/Aurora/HWInfo/CpuBitId.hpp @@ -32,7 +32,8 @@ namespace Aurora::HWInfo inline CpuBitId Or(const CpuBitId &id) const; inline bool CpuBitScanForward(AuUInt8 &index, AuUInt8 offset) const; - + inline AuUInt8 CpuBitCount() const; + inline bool TestCpuIdx(AuUInt8 idx) const; inline void Clear(); inline void SetBit(AuUInt8 idx); diff --git a/Include/Aurora/HWInfo/CpuBitId.inl b/Include/Aurora/HWInfo/CpuBitId.inl index 11a35320..9ea06d10 100644 --- a/Include/Aurora/HWInfo/CpuBitId.inl +++ b/Include/Aurora/HWInfo/CpuBitId.inl @@ -33,6 +33,17 @@ namespace Aurora::HWInfo #endif } + inline AuUInt8 CpuBitId::CpuBitCount() const + { + return AuPopCnt(lower) + + AuPopCnt(upper) + #if defined(_AU_MASSIVE_CPUID) + + AuPopCnt(upper2) + + AuPopCnt(upper3) + #endif + ; + } + bool CpuBitId::CpuBitScanForward(AuUInt8 &index, AuUInt8 offset) const { #if defined(_AU_MASSIVE_CPUID) diff --git a/Include/Aurora/Hashing/Digests.hpp b/Include/Aurora/Hashing/Digests.hpp index 7121b2ea..3d0476f6 100644 --- a/Include/Aurora/Hashing/Digests.hpp +++ b/Include/Aurora/Hashing/Digests.hpp @@ -9,53 +9,9 @@ namespace Aurora::Hashing { - AUKN_SYM void MD5(const void *buffer, AuMach length, AuArray &md5); - static void MD5(const Memory::ByteBuffer &bytebuffer, AuArray &md5) - { - return MD5(bytebuffer.data(), bytebuffer.size(), md5); - } - static void MD5(const AuString &bytebuffer, AuArray &md5) - { - return MD5(bytebuffer.data(), bytebuffer.size(), md5); - } - - AUKN_SYM void SHA1(const void *buffer, AuMach length, AuArray &sha1); - static void SHA1(const Memory::ByteBuffer &bytebuffer, AuArray &sha1) - { - return SHA1(bytebuffer.data(), bytebuffer.size(), sha1); - } - static void SHA1(const AuString &bytebuffer, AuArray &sha1) - { - return SHA1(bytebuffer.data(), bytebuffer.size(), sha1); - } - - AUKN_SYM void Tiger(const void *buffer, AuMach length, AuArray &tiger); - static void Tiger(const Memory::ByteBuffer &bytebuffer, AuArray &tiger) - { - return Tiger(bytebuffer.data(), bytebuffer.size(), tiger); - } - static void Tiger(const AuString &bytebuffer, AuArray &tiger) - { - return Tiger(bytebuffer.data(), bytebuffer.size(), tiger); - } - - AUKN_SYM void SHA2(const void *buffer, AuMach length, AuArray &sha2); - static void SHA2(const Memory::ByteBuffer &bytebuffer, AuArray &sha2) - { - return SHA2(bytebuffer.data(), bytebuffer.size(), sha2); - } - static void SHA2(const AuString &bytebuffer, AuArray &sha2) - { - return SHA2(bytebuffer.data(), bytebuffer.size(), sha2); - } - - AUKN_SYM void SHA2_64(const void *buffer, AuMach length, AuArray &sha2); - static void SHA2_64(const Memory::ByteBuffer &bytebuffer, AuArray &sha2) - { - return SHA2_64(bytebuffer.data(), bytebuffer.size(), sha2); - } - static void SHA2_64(const AuString &bytebuffer, AuArray &sha2) - { - return SHA2_64(bytebuffer.data(), bytebuffer.size(), sha2); - } + AUKN_SYM void MD5(const Memory::MemoryViewRead &span, AuArray &md5); + AUKN_SYM void SHA1(const Memory::MemoryViewRead &span, AuArray &sha1); + AUKN_SYM void Tiger(const Memory::MemoryViewRead &span, AuArray &tiger); + AUKN_SYM void SHA2(const Memory::MemoryViewRead &span, AuArray &sha2); + AUKN_SYM void SHA2_64(const Memory::MemoryViewRead &span, AuArray &sha2); } \ No newline at end of file diff --git a/Include/Aurora/Hashing/EHashType.hpp b/Include/Aurora/Hashing/EHashType.hpp index 01e761a1..0c6dd53f 100644 --- a/Include/Aurora/Hashing/EHashType.hpp +++ b/Include/Aurora/Hashing/EHashType.hpp @@ -9,12 +9,12 @@ namespace Aurora::Hashing { - enum class EHashType - { + AUE_DEFINE(EHashType, + ( eMD5, eSHA1, eSHA2_32, eSHA2_64, eTiger - }; + )); } \ No newline at end of file diff --git a/Include/Aurora/Hashing/HashStream.hpp b/Include/Aurora/Hashing/HashStream.hpp index 026283cb..dbfe799d 100644 --- a/Include/Aurora/Hashing/HashStream.hpp +++ b/Include/Aurora/Hashing/HashStream.hpp @@ -15,7 +15,7 @@ namespace Aurora::Hashing /** * Digest length of pBuf bytes */ - virtual void Ingest(const void *pBuf, AuUInt32 length) = 0; + virtual void Ingest(const Memory::MemoryViewRead &input) = 0; /** * Locks and returns the internal buffer diff --git a/Include/Aurora/IO/Buffered/BlobArbitraryReader.hpp b/Include/Aurora/IO/Buffered/BlobArbitraryReader.hpp deleted file mode 100644 index 32eb5ec6..00000000 --- a/Include/Aurora/IO/Buffered/BlobArbitraryReader.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/*** - Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. - - File: BlobArbitraryReader.hpp - Date: 2021-6-10 - Author: Reece -***/ -#pragma once - -namespace Aurora::IO::Buffered -{ - class BlobArbitraryReader : public IArbitraryStreamer - { - public: - AU_NO_COPY_NO_MOVE(BlobArbitraryReader) - - BlobArbitraryReader(const Memory::ByteBuffer &buffer) : buffer_(buffer) {} - BlobArbitraryReader() {} - ~BlobArbitraryReader(){} - - virtual EStreamError Open() override - { - return EStreamError::eErrorNone; - } - - virtual EStreamError ArbitraryRead(AuUInt32 offset, const Memory::MemoryViewStreamWrite ¶mters) override - { - if (buffer_.empty()) return EStreamError::eErrorEndOfStream; - - auto endOffset = offset + paramters.length; - auto realEndOffset = AuMin(buffer_.size(), endOffset); - auto actualLength = realEndOffset - offset; - - if (actualLength < 0) return EStreamError::eErrorEndOfStream; - - paramters.outVariable = actualLength; - AuMemcpy(paramters.ptr, buffer_.data() + offset, paramters.outVariable); - - return EStreamError::eErrorNone; - } - - virtual void Close() override - { - buffer_.clear(); - } - - private: - Memory::ByteBuffer buffer_; - }; -} \ No newline at end of file diff --git a/Source/IO/Character/LineBuffer.cpp b/Include/Aurora/IO/Buffered/BlobBuilder.hpp similarity index 100% rename from Source/IO/Character/LineBuffer.cpp rename to Include/Aurora/IO/Buffered/BlobBuilder.hpp diff --git a/Include/Aurora/IO/Buffered/BlobReader.hpp b/Include/Aurora/IO/Buffered/BlobReader.hpp index fdd97be4..c0fa7ad2 100644 --- a/Include/Aurora/IO/Buffered/BlobReader.hpp +++ b/Include/Aurora/IO/Buffered/BlobReader.hpp @@ -9,39 +9,33 @@ namespace Aurora::IO::Buffered { - class BlobReader : public IStreamReader + struct BlobReader : public IStreamReader { - public: AU_NO_COPY(BlobReader) - BlobReader(const AuSPtr &buffer) : buffer_(buffer) {} - BlobReader(Memory::ByteBuffer &&buffer) : buffer_(AuMakeShared(buffer)) {} - BlobReader(const Memory::ByteBuffer &buffer) : buffer_(AuMakeShared(buffer)) {} + inline BlobReader(const AuSPtr &buffer) : buffer_(buffer) {} + inline BlobReader(Memory::ByteBuffer &&buffer) : buffer_(AuMakeShared(buffer)) {} + inline BlobReader(const Memory::ByteBuffer &buffer) : buffer_(AuMakeShared(buffer)) {} - BlobReader() {} - ~BlobReader() {} + inline BlobReader() {} + inline ~BlobReader() {} - virtual EStreamError Open() override + inline virtual EStreamError Open() override { if (!buffer_) return EStreamError::eErrorStreamNotOpen; - if (!buffer_->operator bool()) return EStreamError::eErrorStreamNotOpen; return EStreamError::eErrorNone; } - virtual EStreamError Read(const Memory::MemoryViewStreamWrite ¶mters) override + inline virtual EStreamError Read(const Memory::MemoryViewStreamWrite ¶meters) override { - auto realEndOffset = AuMin(buffer_->size() - offset_, paramters.length); - if (realEndOffset == 0) return EStreamError::eErrorEndOfStream; - - paramters.outVariable = realEndOffset; - AuMemcpy(paramters.ptr, buffer_->data() + offset_, realEndOffset); - offset_ += realEndOffset; - - return EStreamError::eErrorNone; + if (!buffer_) return EStreamError::eErrorStreamNotOpen; + parameters.outVariable = buffer_->Read(parameters.ptr, parameters.length); + return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone; } - virtual void Close() override + inline virtual void Close() override { + if (!buffer_) return; buffer_->clear(); } diff --git a/Include/Aurora/IO/Buffered/BlobSeekableReader.hpp b/Include/Aurora/IO/Buffered/BlobSeekableReader.hpp new file mode 100644 index 00000000..4a1545fb --- /dev/null +++ b/Include/Aurora/IO/Buffered/BlobSeekableReader.hpp @@ -0,0 +1,46 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: BlobSeekableReader.hpp + Date: 2021-6-10 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::Buffered +{ + struct BlobSeekableReader : public ISeekingReader + { + AU_NO_COPY_NO_MOVE(BlobSeekableReader) + + inline BlobSeekableReader(const AuSPtr &buffer) : buffer_(buffer) {} + inline BlobSeekableReader(Memory::ByteBuffer &&buffer) : buffer_(AuMakeShared(buffer)) {} + inline BlobSeekableReader(const Memory::ByteBuffer &buffer) : buffer_(AuMakeShared(buffer)) {} + + inline BlobSeekableReader() {} + inline ~BlobSeekableReader(){} + + inline virtual EStreamError Open() override + { + if (!buffer_) return EStreamError::eErrorStreamNotOpen; + return EStreamError::eErrorNone; + } + + inline virtual EStreamError ArbitraryRead(AuUInt offset, const Memory::MemoryViewStreamWrite ¶meters) override + { + if (!buffer_) return EStreamError::eErrorStreamNotOpen; + if (buffer_->empty()) return EStreamError::eErrorEndOfStream; + buffer_->readPtr = buffer_->base + offset; + parameters.outVariable = buffer_->Read(parameters.ptr, parameters.length); + return parameters.outVariable == 0 ? EStreamError::eErrorEndOfStream : EStreamError::eErrorNone; + } + + inline virtual void Close() override + { + if (buffer_) buffer_->clear(); + } + + private: + AuSPtr buffer_; + }; +} \ No newline at end of file diff --git a/Include/Aurora/IO/Buffered/BlobWriter.hpp b/Include/Aurora/IO/Buffered/BlobWriter.hpp index da731244..83508234 100644 --- a/Include/Aurora/IO/Buffered/BlobWriter.hpp +++ b/Include/Aurora/IO/Buffered/BlobWriter.hpp @@ -9,41 +9,40 @@ namespace Aurora::IO::Buffered { - class BlobWriter : public IStreamWriter + struct BlobWriter : public IStreamWriter { - public: AU_NO_COPY_NO_MOVE(BlobWriter) - BlobWriter() {} - ~BlobWriter() {} + inline BlobWriter(const AuSPtr &buffer) : buffer_(buffer) {} + inline BlobWriter() : buffer_(AuMakeShared()) {} + inline ~BlobWriter() {} - virtual EStreamError Open() override + inline virtual EStreamError Open() override { + return buffer_ ? EStreamError::eErrorNone : EStreamError::eErrorStreamNotOpen; + } + + inline virtual EStreamError Write(const Memory::MemoryViewStreamRead ¶meters) override + { + if (!buffer_) return EStreamError::eErrorStreamNotOpen; + parameters.outVariable = buffer_->Write(parameters.ptr, parameters.length); return EStreamError::eErrorNone; } - virtual EStreamError Write(const Memory::MemoryViewStreamRead & parameters) override - { - auto idx = buffer_.size(); - buffer_.resize(idx + parameters.length); - AuMemcpy(buffer_.data() + idx, parameters.ptr, buffer_.size() - idx); - return EStreamError::eErrorNone; - } - - virtual void Flush() override + inline virtual void Flush() override { } - virtual void Close() override + inline virtual void Close() override { } - const Memory::ByteBuffer &GetBuffer() + inline AuSPtr GetBuffer() { return this->buffer_; } private: - Memory::ByteBuffer buffer_; + AuSPtr buffer_; }; } \ No newline at end of file diff --git a/Include/Aurora/IO/Buffered/Buffered.hpp b/Include/Aurora/IO/Buffered/Buffered.hpp index 9c9ad190..199d2685 100644 --- a/Include/Aurora/IO/Buffered/Buffered.hpp +++ b/Include/Aurora/IO/Buffered/Buffered.hpp @@ -9,6 +9,6 @@ // Most internal transactions will be buffered. // For sake of being able to mix network, file, serial, and other code, its nice to use the same reader interface for buffered and streams where read/write until EOS is required -#include "BlobArbitraryReader.hpp" +#include "BlobSeekableReader.hpp" #include "BlobReader.hpp" #include "BlobWriter.hpp" \ No newline at end of file diff --git a/Include/Aurora/IO/Character/Character.hpp b/Include/Aurora/IO/Character/Character.hpp index 01882818..dd8925c4 100644 --- a/Include/Aurora/IO/Character/Character.hpp +++ b/Include/Aurora/IO/Character/Character.hpp @@ -8,5 +8,7 @@ #pragma once #include "ICharacterProvider.hpp" +#include "ICharacterProviderEx.hpp" #include "IBufferedCharacterConsumer.hpp" -#include "ILineBufferer.hpp" \ No newline at end of file +#include "IBufferedLineReader.hpp" +#include "Providers.hpp" \ No newline at end of file diff --git a/Include/Aurora/IO/Character/IBufferedCharacterConsumer.hpp b/Include/Aurora/IO/Character/IBufferedCharacterConsumer.hpp index a753026f..6bb639ff 100644 --- a/Include/Aurora/IO/Character/IBufferedCharacterConsumer.hpp +++ b/Include/Aurora/IO/Character/IBufferedCharacterConsumer.hpp @@ -9,5 +9,15 @@ namespace Aurora::IO::Character { + struct IBufferedCharacterConsumer + { + virtual bool HasBufferedNext() const = 0; + virtual AuUInt8 NextBufferedByte() const = 0; + + virtual bool PeekNext(AuUInt8 &out) = 0; + virtual AuUInt8 GetCurrent() = 0; + virtual bool Next(AuUInt8 &out) = 0; + }; + AUKN_SHARED_API(BufferConsumerFromProvider, IBufferedCharacterConsumer, const AuSPtr &provider); } \ No newline at end of file diff --git a/Include/Aurora/IO/Character/IBufferedLineReader.hpp b/Include/Aurora/IO/Character/IBufferedLineReader.hpp new file mode 100644 index 00000000..bf70d8a0 --- /dev/null +++ b/Include/Aurora/IO/Character/IBufferedLineReader.hpp @@ -0,0 +1,20 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IBufferedLineReader.hpp + Date: 2022-1-29 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::Character +{ + struct IBufferedLineReader + { + virtual bool ReadBytes(AuUInt32 length) = 0; + virtual void Flush() = 0; + virtual AuList ReadLines() = 0; + }; + + AUKN_SHARED_API(NewLineReader, IBufferedLineReader, const AuSPtr &input); +} \ No newline at end of file diff --git a/Include/Aurora/IO/Character/ICharacterProvider.hpp b/Include/Aurora/IO/Character/ICharacterProvider.hpp index 70519c06..79da8f9e 100644 --- a/Include/Aurora/IO/Character/ICharacterProvider.hpp +++ b/Include/Aurora/IO/Character/ICharacterProvider.hpp @@ -10,6 +10,6 @@ namespace Aurora::IO::Character { AUKN_INTERFACE(ICharacterProvider, - AUI_METHOD(AuUInt8, GetByte, ()) + AUI_METHOD(bool, GetByte, (AuUInt8 &, val)) ); } \ No newline at end of file diff --git a/Include/Aurora/IO/Character/ICharacterProviderEx.hpp b/Include/Aurora/IO/Character/ICharacterProviderEx.hpp new file mode 100644 index 00000000..8615a150 --- /dev/null +++ b/Include/Aurora/IO/Character/ICharacterProviderEx.hpp @@ -0,0 +1,17 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ICharacterProviderEx.hpp + Date: 2022-1-29 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::Character +{ + struct ICharacterProviderEx : ICharacterProvider + { + virtual AuUInt GetPosition() = 0; + virtual bool SetPosition(AuUInt offset) = 0; + }; +} \ No newline at end of file diff --git a/Include/Aurora/IO/Character/Providers.hpp b/Include/Aurora/IO/Character/Providers.hpp new file mode 100644 index 00000000..ca010a37 --- /dev/null +++ b/Include/Aurora/IO/Character/Providers.hpp @@ -0,0 +1,16 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: Providers.hpp + Date: 2022-1-29 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::Character +{ + // you are responsible for maintaining a lock over shared string writes and provider use instances + // (string may change so long as a read/write lock is protecting ICharacterProviderEx reads) + AUKN_SHARED_API(ProviderFromSharedString, ICharacterProviderEx, const AuSPtr &str, AuUInt index = 0); + AUKN_SHARED_API(ProviderFromString, ICharacterProviderEx, const AuString &str, AuUInt index = 0); +} \ No newline at end of file diff --git a/Include/Aurora/IO/EStreamError.hpp b/Include/Aurora/IO/EStreamError.hpp index 47f471b6..e29659f5 100644 --- a/Include/Aurora/IO/EStreamError.hpp +++ b/Include/Aurora/IO/EStreamError.hpp @@ -9,12 +9,11 @@ namespace Aurora::IO { - enum class EStreamError - { + AUE_DEFINE_VA(EStreamError, eErrorNone, eErrorEndOfStream, eErrorStreamNotOpen, eErrorStreamInterrupted, eErrorHandleClosed - }; + ); } \ No newline at end of file diff --git a/Include/Aurora/IO/FS/Async.hpp b/Include/Aurora/IO/FS/Async.hpp index 2e5ed34c..d722253a 100644 --- a/Include/Aurora/IO/FS/Async.hpp +++ b/Include/Aurora/IO/FS/Async.hpp @@ -9,36 +9,7 @@ namespace Aurora::IO::FS { - class IAsyncTransaction; - - class IAsyncFileStream - { - public: - virtual AuSPtr NewTransaction() = 0; - }; - - class IAsyncFinishedSubscriber - { - public: - virtual void OnAsyncFileOpFinished(AuUInt64 offset, AuUInt32 length) = 0; - }; - - class IAsyncTransaction - { - public: - // Do not switch to Aurora::Memory::MemoryView, you must use a raw pointer to the parent object that effectively owns the IAsyncTransaction - virtual bool StartRead(AuUInt64 offset, void *, AuUInt32 length) = 0; - virtual bool StartWrite(AuUInt64 offset, const void *, AuUInt32 length) = 0; - - virtual bool Complete() = 0; - virtual AuUInt32 GetLastPacketLength() = 0; - - virtual void SetCallback(const AuSPtr &sub) = 0; - - virtual bool Wait(AuUInt32 timeout) = 0; - }; - - AUKN_SHARED_API(OpenAsync, IAsyncFileStream, const AuString &path, bool readOnly = true, bool directIO = false); + AUKN_SHARED_API(OpenAsync, IAsyncFileStream, const AuString &path, EFileOpenMode openMode, bool directIO = false, EFileAdvisoryLockLevel lock = EFileAdvisoryLockLevel::eNoSafety); /// \param transactions Array of FIO transactions /// \param timeout Aurora Timeout diff --git a/Include/Aurora/IO/FS/EFileAdvisoryLockLevel.hpp b/Include/Aurora/IO/FS/EFileAdvisoryLockLevel.hpp new file mode 100644 index 00000000..3d685d7a --- /dev/null +++ b/Include/Aurora/IO/FS/EFileAdvisoryLockLevel.hpp @@ -0,0 +1,29 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: EFileAdvisoryLockLevel.hpp + Date: 2022-1-29 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::FS +{ + // I know NT can do much better, network drives and unix can not. + // Do not open an issue over this + // There is no portable solution for file locks + + AUE_DEFINE(EFileAdvisoryLockLevel, + ( + // Nothing will invalidate the file stream, potentially causing corruption on lock race + // No lock will be placed on the file nor created to be polled + // File locks just aren't portable enough yet + eNoSafety, + + // Prevent software that is willing to play ball from writing to the file path + eBlockWrite, + + // Prevent software that is willing to play ball from reading the file, write blocking inherited + eBlockReadWrite + )); +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/EFileOpenMode.hpp b/Include/Aurora/IO/FS/EFileOpenMode.hpp new file mode 100644 index 00000000..10725cce --- /dev/null +++ b/Include/Aurora/IO/FS/EFileOpenMode.hpp @@ -0,0 +1,18 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: EOpenMode.hpp + Date: 2022-1-29 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::FS +{ + AUE_DEFINE(EFileOpenMode, + ( + eRead, + eWrite, + eReadWrite + )); +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/FS.hpp b/Include/Aurora/IO/FS/FS.hpp index 92394c83..9c6a1091 100644 --- a/Include/Aurora/IO/FS/FS.hpp +++ b/Include/Aurora/IO/FS/FS.hpp @@ -44,11 +44,16 @@ namespace Aurora::IO::FS AUKN_SYM bool GoUpToSeparator(AuString &out, const AuString &path); } +#include "EFileAdvisoryLockLevel.hpp" +#include "EFileOpenMode.hpp" #include "IFileStream.hpp" #include "FileStream.hpp" -#include "FileArbitraryReader.hpp" +#include "FileSeekableReader.hpp" #include "FileReader.hpp" #include "FileWriter.hpp" #include "Resources.hpp" #include "Stat.hpp" +#include "IAsyncFileStream.hpp" +#include "IAsyncFinishedSubscriber.hpp" +#include "IAsyncTransaction.hpp" #include "Async.hpp" \ No newline at end of file diff --git a/Include/Aurora/IO/FS/FileReader.hpp b/Include/Aurora/IO/FS/FileReader.hpp index 6ea189ce..5bc1faf2 100644 --- a/Include/Aurora/IO/FS/FileReader.hpp +++ b/Include/Aurora/IO/FS/FileReader.hpp @@ -9,27 +9,26 @@ namespace Aurora::IO::FS { - class FileReader : public IStreamReader + struct FileReader : public IStreamReader { - public: AU_NO_COPY_NO_MOVE(FileReader) - FileReader() {} - ~FileReader() {} + inline FileReader() {} + inline ~FileReader() {} template - bool OpenFile(T... args) + inline bool OpenFile(T... args) { stream_ = OpenReadUnique(args...); return stream_ != nullptr; } - virtual EStreamError Open() override + inline virtual EStreamError Open() override { return stream_ ? EStreamError::eErrorNone : EStreamError::eErrorStreamNotOpen; } - virtual EStreamError Read(const Memory::MemoryViewStreamWrite ¶mters) override + inline virtual EStreamError Read(const Memory::MemoryViewStreamWrite ¶mters) override { if (!stream_) return EStreamError::eErrorStreamNotOpen; if (!stream_->Read(paramters)) return EStreamError::eErrorStreamInterrupted; @@ -37,7 +36,7 @@ namespace Aurora::IO::FS return EStreamError::eErrorNone; } - virtual void Close() override + inline virtual void Close() override { stream_.reset(); } diff --git a/Include/Aurora/IO/FS/FileArbitraryReader.hpp b/Include/Aurora/IO/FS/FileSeekableReader.hpp similarity index 75% rename from Include/Aurora/IO/FS/FileArbitraryReader.hpp rename to Include/Aurora/IO/FS/FileSeekableReader.hpp index 1e1a2527..6b57a68e 100644 --- a/Include/Aurora/IO/FS/FileArbitraryReader.hpp +++ b/Include/Aurora/IO/FS/FileSeekableReader.hpp @@ -1,7 +1,7 @@ /*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. - File: FileArbitraryReader.hpp + File: FileSeekableReader.hpp Date: 2021-6-10 Author: Reece ***/ @@ -9,13 +9,12 @@ namespace Aurora::IO::FS { - class FileArbitraryReader : public IArbitraryStreamer + struct FileSeekableReader : public ISeekingReader { - public: - AU_NO_COPY_NO_MOVE(FileArbitraryReader) + AU_NO_COPY_NO_MOVE(FileSeekableReader) - FileArbitraryReader() {} - ~FileArbitraryReader() {} + FileSeekableReader() {} + ~FileSeekableReader() {} template bool OpenFile(T... args) @@ -29,7 +28,7 @@ namespace Aurora::IO::FS return stream_ ? EStreamError::eErrorNone : EStreamError::eErrorStreamInterrupted; } - virtual EStreamError ArbitraryRead(AuUInt32 offset, const Memory::MemoryViewStreamWrite ¶mters) override + virtual EStreamError ArbitraryRead(AuUInt offset, const Memory::MemoryViewStreamWrite ¶mters) override { if (!stream_) return EStreamError::eErrorStreamNotOpen; if (!stream_->SetOffset(offset)) return EStreamError::eErrorEndOfStream; diff --git a/Include/Aurora/IO/FS/FileStream.hpp b/Include/Aurora/IO/FS/FileStream.hpp index 489e38d3..f003caf1 100644 --- a/Include/Aurora/IO/FS/FileStream.hpp +++ b/Include/Aurora/IO/FS/FileStream.hpp @@ -9,6 +9,8 @@ namespace Aurora::IO::FS { - AUKN_SHARED_API(OpenRead, IFileStream, const AuString &path); - AUKN_SHARED_API(OpenWrite, IFileStream, const AuString &path); + AUKN_SHARED_API(OpenRead, IFileStream, const AuString &path, EFileAdvisoryLockLevel successPostAdvisoryLevel = EFileAdvisoryLockLevel::eBlockWrite); + AUKN_SHARED_API(OpenWrite, IFileStream, const AuString &path, EFileAdvisoryLockLevel successPostAdvisoryLevel = EFileAdvisoryLockLevel::eBlockReadWrite); + + AUKN_SHARED_API(Open, IFileStream, const AuString &path, EFileOpenMode mode = EFileOpenMode::eRead, EFileAdvisoryLockLevel successPostAdvisoryLevel = EFileAdvisoryLockLevel::eBlockReadWrite); } \ No newline at end of file diff --git a/Include/Aurora/IO/FS/FileWriter.hpp b/Include/Aurora/IO/FS/FileWriter.hpp index b7d00975..ebb84fba 100644 --- a/Include/Aurora/IO/FS/FileWriter.hpp +++ b/Include/Aurora/IO/FS/FileWriter.hpp @@ -9,45 +9,54 @@ namespace Aurora::IO::FS { - class FileWriter : public IStreamWriter + struct FileWriter : public IStreamWriter { - public: AU_NO_COPY_NO_MOVE(FileWriter) - FileWriter() {} - ~FileWriter() {} + inline FileWriter() {} + inline ~FileWriter() {} template - bool OpenFile(T... args) + inline bool OpenFile(T... args) { stream_ = OpenWriteUnique(args...); return stream_ != nullptr; } - virtual EStreamError Open() override + inline virtual EStreamError Open() override { return stream_ ? EStreamError::eErrorNone : EStreamError::eErrorStreamNotOpen; } - virtual EStreamError Write(const Memory::MemoryViewStreamRead & parameters) override + inline virtual EStreamError Write(const Memory::MemoryViewStreamRead ¶meters) override { if (!stream_) return EStreamError::eErrorStreamNotOpen; - if (!stream_->Write(parameters)) return EStreamError::eErrorStreamInterrupted; + if (!stream_->Write(parameters)) return EStreamError::eErrorStreamInterrupted; if (parameters.outVariable == 0) return EStreamError::eErrorEndOfStream; if (parameters.outVariable != parameters.length) return EStreamError::eErrorStreamInterrupted; return EStreamError::eErrorNone; } - virtual void Flush() override + inline virtual void Flush() override { if (stream_) stream_->Flush(); } - virtual void Close() override + inline virtual void Close() override { stream_.reset(); } + inline virtual AuUInt64 GetPosition() + { + return stream_ ? stream_->GetOffset() : 0; + } + + inline virtual bool SetPosition(AuUInt64 pos) + { + return stream_ ? stream_->SetOffset(pos) : false; + } + private: OpenWriteUnique_t stream_{}; }; diff --git a/Include/Aurora/IO/FS/IAsyncFileStream.hpp b/Include/Aurora/IO/FS/IAsyncFileStream.hpp new file mode 100644 index 00000000..230e5b49 --- /dev/null +++ b/Include/Aurora/IO/FS/IAsyncFileStream.hpp @@ -0,0 +1,18 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IAsyncFileStream.hpp + Date: 2022-2-14 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::FS +{ + struct IAsyncTransaction; + + struct IAsyncFileStream + { + virtual AuSPtr NewTransaction() = 0; + }; +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/IAsyncFinishedSubscriber.hpp b/Include/Aurora/IO/FS/IAsyncFinishedSubscriber.hpp new file mode 100644 index 00000000..3bf940d3 --- /dev/null +++ b/Include/Aurora/IO/FS/IAsyncFinishedSubscriber.hpp @@ -0,0 +1,15 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IAsyncFinishedSubscriber.hpp + Date: 2022-2-14 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO::FS +{ + AUKN_INTERFACE(IAsyncFinishedSubscriber, + AUI_METHOD(void, OnAsyncFileOpFinished, (AuUInt64, offset, AuUInt32, length)) + ); +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/IAsyncTransaction.hpp b/Include/Aurora/IO/FS/IAsyncTransaction.hpp new file mode 100644 index 00000000..2170112c --- /dev/null +++ b/Include/Aurora/IO/FS/IAsyncTransaction.hpp @@ -0,0 +1,30 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IAsyncTransaction.hpp + Date: 2022-2-14 + Author: Reece +***/ +#pragma once + +namespace Aurora::Loop +{ + struct ILoopSource; +} + +namespace Aurora::IO::FS +{ + struct IAsyncTransaction + { + virtual bool StartRead(AuUInt64 offset, const AuSPtr &memoryView) = 0; + virtual bool StartWrite(AuUInt64 offset, const AuSPtr &memoryView) = 0; + + virtual bool Complete() = 0; + virtual AuUInt32 GetLastPacketLength() = 0; + + virtual void SetCallback(const AuSPtr &sub) = 0; + + virtual bool Wait(AuUInt32 timeout) = 0; + virtual AuSPtr NewLoopSource() = 0; + }; +} \ No newline at end of file diff --git a/Include/Aurora/IO/FS/IFileStream.hpp b/Include/Aurora/IO/FS/IFileStream.hpp index 38882aca..a69d69da 100644 --- a/Include/Aurora/IO/FS/IFileStream.hpp +++ b/Include/Aurora/IO/FS/IFileStream.hpp @@ -1,17 +1,64 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IFileStream.hpp + Date: 2022-01-17 (wrong) + Author: Reece +***/ #pragma once namespace Aurora::IO::FS { - class IFileStream + struct IFileStream { - public: - virtual AuUInt64 GetOffset() = 0; - virtual bool SetOffset(AuUInt64 offset) = 0; - virtual AuUInt64 GetLength() = 0; + /** + * @brief Read memoryview from the filestream at an auto-incrementing offset + * @param parameters + * @return + */ virtual bool Read(const Memory::MemoryViewStreamWrite ¶meters) = 0; + + /** + * @brief Writes memoryview to the filestream at an auto-incrementing offset + * @param parameters + * @return + */ virtual bool Write(const Memory::MemoryViewStreamRead ¶meters) = 0; - virtual void Close() = 0; + + /** + * @brief Returns the length of the file + * @return + */ + virtual AuUInt64 GetLength() = 0; + + /** + * @brief Returns the offset of the internal streams + * @return + */ + virtual AuUInt64 GetOffset() = 0; + + /** + * @brief Updates the stream pointer + * @param offset + * @return + */ + virtual bool SetOffset(AuUInt64 offset) = 0; + + /** + * @brief Flush read/write streams + */ virtual void Flush() = 0; + + /** + * @brief Termiantes/truncates the file at the current offset + */ virtual void WriteEoS() = 0; + + + /** + * @brief Close IFileStream resource + */ + virtual void Close() = 0; + }; } \ No newline at end of file diff --git a/Include/Aurora/IO/FS/Resources.hpp b/Include/Aurora/IO/FS/Resources.hpp index 65dc1979..beeadfa3 100644 --- a/Include/Aurora/IO/FS/Resources.hpp +++ b/Include/Aurora/IO/FS/Resources.hpp @@ -15,15 +15,29 @@ namespace Aurora::IO::FS AUKN_SYM bool GetSystemDomain(AuString &path); /** - * @brief Provides an application specific storage path for local application data, isolated for your Aurora application brand info (defer to the init structure) + * @brief Provides an application specific storage path for user-local application data, isolated with respect to your Aurora application brand info (defer to the init structure) */ AUKN_SYM bool GetProfileDomain(AuString &path); AUKN_SYM bool GetSystemResourcePath(const AuString &fileName, AuString &path); + + /** + * @brief Get package path + * This could be a read-only path if relevant to the platform + * This may be `/storage/emulated/0/Android/data/` (`Context#getExternalFilesDir(java.lang.String)`) + * `/Applications/` + * `\\some uwp path` + * ...on platforms with read-only application specific data directories + * @param path + * @return + */ + AUKN_SYM bool GetPackagePath(AuString &path); /** * @brief Pulls the application directory as defined by the operating system standard file system hierarchy + * Otherwise, XDG_CONFIG_CONFIG or %appdata%. + * This directory might be sandboxed to the user or application by the operating system. */ AUKN_SYM bool GetAppData(AuString &path); @@ -33,12 +47,19 @@ namespace Aurora::IO::FS AUKN_SYM bool GetUserHome(AuString &path); /** - * @brief Global application data that requires no special permissions to access + * @brief Global application data that requires no special permissions to access. + * This could be an SD-Card or user profile. + * This could be the root of the user managable aplication directory. */ AUKN_SYM bool GetWritableAppdata(AuString &path); - + /** * @brief Global application data that requires special permissions to access, usually configured by a system account during installation */ AUKN_SYM bool GetRootAppdata(AuString &path); + + /** + * @brief Get user installable application directory + */ + AUKN_SYM bool GetUserProgramsFolder(AuString &path); } \ No newline at end of file diff --git a/Include/Aurora/IO/IO.hpp b/Include/Aurora/IO/IO.hpp index a4acbbec..d9cefd95 100644 --- a/Include/Aurora/IO/IO.hpp +++ b/Include/Aurora/IO/IO.hpp @@ -11,9 +11,10 @@ #include "IStreamReader.hpp" #include "IStreamWriter.hpp" -#include "IArbitraryStreamer.hpp" // arbitrary read stream, dunno what you would want to call thousands_sep +#include "ISeekingReader.hpp" // arbitrary read stream, dunno what you would want to call thousands_sep #include "Buffered/Buffered.hpp" #include "FS/FS.hpp" -#include "Net/Net.hpp" \ No newline at end of file +#include "Net/Net.hpp" +#include "Character/Character.hpp" \ No newline at end of file diff --git a/Include/Aurora/IO/IArbitraryStreamer.hpp b/Include/Aurora/IO/ISeekingReader.hpp similarity index 57% rename from Include/Aurora/IO/IArbitraryStreamer.hpp rename to Include/Aurora/IO/ISeekingReader.hpp index b9ced8be..6c357379 100644 --- a/Include/Aurora/IO/IArbitraryStreamer.hpp +++ b/Include/Aurora/IO/ISeekingReader.hpp @@ -1,7 +1,7 @@ /*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. - File: IArbitraryStreamer.hpp + File: ISeekingReader.hpp Date: 2021-6-10 Author: Reece ***/ @@ -9,11 +9,10 @@ namespace Aurora::IO { - class IArbitraryStreamer + struct ISeekingReader { - public: virtual EStreamError Open() = 0; - virtual EStreamError ArbitraryRead(AuUInt32 offset, const Memory::MemoryViewStreamWrite ¶mters) = 0; + virtual EStreamError ArbitraryRead(AuUInt offset, const Memory::MemoryViewStreamWrite ¶mters) = 0; virtual void Close() = 0; }; } \ No newline at end of file diff --git a/Include/Aurora/IO/IStreamReader.hpp b/Include/Aurora/IO/IStreamReader.hpp index fe07fd83..7b7897f5 100644 --- a/Include/Aurora/IO/IStreamReader.hpp +++ b/Include/Aurora/IO/IStreamReader.hpp @@ -9,47 +9,17 @@ namespace Aurora::IO { - class IStreamReader + // TODO (Reece): Consider publishing the multiple inverted ext hack for Aurora Interfaces for binding this. + // It would be nice to have cs-style extensions on this interface. Maybe I shouldn't double down + // over a double blocking API. Maybe I should focus on the stream pumpers. + struct IStreamReader { - public: virtual EStreamError Open() = 0; virtual EStreamError Read(const Memory::MemoryViewStreamWrite ¶mters) = 0; virtual void Close() = 0; - EStreamError ReadAll(Memory::ByteBuffer &buffer) - { - static const int kBufferSize = 2048; - - AuUInt len; - EStreamError ret; - AuUInt8 temp[kBufferSize]; - - len = kBufferSize; - ret = EStreamError::eErrorEndOfStream; - - buffer = Memory::NewResizableBuffer(); - - while ((ret = Read(Memory::MemoryViewStreamWrite(temp, len))) == EStreamError::eErrorNone) - { - if (len == 0) - { - break; - } - - buffer.Write(temp, len); - - if (len != kBufferSize) - { - break; - } - } - - if (ret == EStreamError::eErrorEndOfStream) - { - return EStreamError::eErrorNone; - } - - return ret; - } + inline EStreamError ReadAll(Memory::ByteBuffer &buffer); }; -} \ No newline at end of file +} + +#include "IStreamReader.inl" // ReadAll utility \ No newline at end of file diff --git a/Include/Aurora/IO/IStreamReader.inl b/Include/Aurora/IO/IStreamReader.inl new file mode 100644 index 00000000..329a59aa --- /dev/null +++ b/Include/Aurora/IO/IStreamReader.inl @@ -0,0 +1,47 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IStreamReader.inl + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +namespace Aurora::IO +{ + EStreamError IStreamReader::ReadAll(Memory::ByteBuffer &buffer) + { + static const int kBufferSize = 2048; + + AuUInt len; + EStreamError ret; + AuUInt8 temp[kBufferSize]; + + len = kBufferSize; + ret = EStreamError::eErrorEndOfStream; + + buffer = Memory::NewResizableBuffer(); + + while ((ret = Read(Memory::MemoryViewStreamWrite(temp, len))) == EStreamError::eErrorNone) + { + if (len == 0) + { + break; + } + + buffer.Write(temp, len); + + if (len != kBufferSize) + { + break; + } + } + + if (ret == EStreamError::eErrorEndOfStream) + { + return EStreamError::eErrorNone; + } + + return ret; + } +} \ No newline at end of file diff --git a/Include/Aurora/IO/IStreamWriter.hpp b/Include/Aurora/IO/IStreamWriter.hpp index 3db7efe3..d0caaeb1 100644 --- a/Include/Aurora/IO/IStreamWriter.hpp +++ b/Include/Aurora/IO/IStreamWriter.hpp @@ -9,9 +9,8 @@ namespace Aurora::IO { - class IStreamWriter + struct IStreamWriter { - public: virtual EStreamError Open() = 0; virtual EStreamError Write(const Memory::MemoryViewStreamRead ¶meters) = 0; virtual void Flush() = 0; diff --git a/Include/Aurora/IO/Net/Net.hpp b/Include/Aurora/IO/Net/Net.hpp index 8c9bebd6..71a6a87b 100644 --- a/Include/Aurora/IO/Net/Net.hpp +++ b/Include/Aurora/IO/Net/Net.hpp @@ -14,11 +14,11 @@ namespace Aurora::Async namespace Aurora::IO::Net { - static const AuUInt16 kMagicPortAny = 65535; + static const AuUInt16 kMagicPortAny = 0; struct INetworkStream; struct IBasicSocket; - struct IClientSocket; + struct ISocket; struct IServer; AUE_DEFINE(ETransportProtocol, ( @@ -60,11 +60,11 @@ namespace Aurora::IO::Net if (cmp.ip == EIPProtocol::eIPProtocolV4) { - return memcmp(cmp.v4, this->v4, sizeof(this->v4)) == 0; + return AuMemcmp(cmp.v4, this->v4, sizeof(this->v4)) == 0; } else { - return memcmp(cmp.v6, this->v6, sizeof(this->v6)) == 0; + return AuMemcmp(cmp.v6, this->v6, sizeof(this->v6)) == 0; } } }; @@ -104,11 +104,13 @@ namespace Aurora::IO::Net { IPAddress ip; AuUInt16 port; + AuUInt8 hint[32] {0}; }; struct ConnectionEndpoint { ETransportProtocol protocol; + IPEndpoint ip; bool tls {}; bool compressed {}; // 0 - destination is a stateless datagram server @@ -138,18 +140,18 @@ namespace Aurora::IO::Net AUKN_INTERFACE(IClientSubscriber, // - AUI_METHOD(void, OnServerConnectSuccess, (const AuSPtr &, socket)), - AUI_METHOD(void, OnServerConnectFailed, (const AuSPtr &, socket)), + AUI_METHOD(void, OnServerConnectSuccess, (const AuSPtr &, socket)), + AUI_METHOD(void, OnServerConnectFailed, (const AuSPtr &, socket)), // DTLS/UDP/TCP/TLS -> TRUE = expects another datagram or read pump // FALSE = end of socket life - AUI_METHOD(bool, OnSockeData, (const AuSPtr &, socket)), + AUI_METHOD(bool, OnSocketData, (const AuSPtr &, socket)), // - AUI_METHOD(void, OnSocketError, (const AuSPtr &, socket)), + AUI_METHOD(void, OnSocketError, (const AuSPtr &, socket)), // - AUI_METHOD(void, OnSocketShutdown, (const AuSPtr &, socket)) + AUI_METHOD(void, OnSocketShutdown, (const AuSPtr &, socket)) ); AUKN_INTERFACE(IClientSubscriberTls, @@ -158,16 +160,16 @@ namespace Aurora::IO::Net ); AUKN_INTERFACE(IServerSubscriber, - AUI_METHOD(bool, OnClientAccept, (const AuSPtr &, server, const AuSPtr &, socket)), - AUI_METHOD(bool, OnClientDoS, (const AuSPtr &, server, const AuSPtr &, socket)), - AUI_METHOD(void, OnClientError, (const AuSPtr &, server, const AuSPtr &, socket)), - AUI_METHOD(void, OnClientShutdown, (const AuSPtr &, server, const AuSPtr &, socket)), - AUI_METHOD(bool, OnReadFrame, (const AuSPtr &, server, const AuList> &, sockets)), + AUI_METHOD(bool, OnClientAccept, (const AuSPtr &, server, const AuSPtr &, socket)), + AUI_METHOD(bool, OnClientDoS, (const AuSPtr &, server, const AuSPtr &, socket)), + AUI_METHOD(void, OnClientError, (const AuSPtr &, server, const AuSPtr &, socket)), + AUI_METHOD(void, OnClientShutdown, (const AuSPtr &, server, const AuSPtr &, socket)), + AUI_METHOD(bool, OnReadFrame, (const AuSPtr &, server, const AuList> &, sockets)), AUI_METHOD(void, OnShutdown, (const AuSPtr &, server)) ); AUKN_INTERFACE(IServerSubscriberTls, - AUI_METHOD(bool, OnClientTLSReport, (const AuSPtr &, server, const AuSPtr &, socket, const TLSHandshakeError &, error)) + AUI_METHOD(bool, OnClientTLSReport, (const AuSPtr &, server, const AuSPtr &, socket, const TLSHandshakeError &, error)) ); // TODO: We should introduce another std:: customer overloadable type reproducing hardcoded ascii and an int, basically std::error_code @@ -235,19 +237,8 @@ namespace Aurora::IO::Net AuUInt32 bufferedWriteSize {4096 * 10}; // see: enableBufferedOutput }; - - struct IClientSocket : public IBasicSocket + struct ISocketChannel { - virtual bool GetRemoteEndpoint(ConnectionEndpoint &out) = 0; - virtual bool GetLocalEndpoint(ConnectionEndpoint &out) = 0; - - virtual bool PumpRead() = 0; - virtual bool PumpWrite() = 0; - virtual bool Pump() = 0; - - virtual void Run(int idx, AuUInt32 timeout) = 0; - - // If memory.ptr is a nullptr, this method immediately returns with the expected write length in memory.out // // If all is true and the internal buffer is not saturated enough yet, no data is read and @@ -333,7 +324,21 @@ namespace Aurora::IO::Net virtual void ReconfigureStreams(const StreamConfig &config) = 0; }; - struct ILocalClientSocket : public IClientSocket + struct IBasicSocketThreaded : public IBasicSocket + { + virtual bool PumpRead() = 0; + virtual bool PumpWrite() = 0; + virtual bool Pump() = 0; + + virtual void Run(int idx, AuUInt32 timeout) = 0; + }; + + struct ISocket : public IBasicSocketThreaded, public ISocketChannel + { + virtual bool GetRemoteEndpoint(ConnectionEndpoint &out) = 0; + }; + + struct ILocalClientSocket : public ISocket { // Connects to the endpoint defined in the ClientConfig // Completion will be notified by the following callbacks; @@ -389,9 +394,10 @@ namespace Aurora::IO::Net AuSPtr clientSubscriber; }; - struct IServer : public IBasicSocket + struct IServer : public IBasicSocketThreaded { - virtual void GetClients(AuList> &clients) = 0; + virtual bool GetLocalEndpoint(ConnectionEndpoint &out) = 0; + virtual void GetClients(AuList> &clients) = 0; virtual bool Listen() = 0; virtual void ReconfigureDefaultStream(const StreamConfig &config) = 0; }; @@ -414,10 +420,11 @@ namespace Aurora::IO::Net struct INetworkInterface { - virtual IPEndpoint ResolveSocketSync(const SocketHostName &hostname, AuUInt16 port); - virtual IPEndpoint ResolveServiceSync(const ServiceEndpoint &service); + virtual AuList ResolveSocketSync(const SocketHostName &hostname, AuUInt16 port) = 0; + virtual AuList ResolveServiceSync(const ServiceEndpoint &service) = 0; - virtual bool SendDatagramAsync(const ConnectionEndpoint &endpoint, const Memory::MemoryViewRead &memory); + virtual bool SendDatagramAsync(const ConnectionEndpoint &endpoint, const Memory::MemoryViewRead &memory) = 0; + virtual bool SendDatagramAsync(const AuSPtr &datagramServer, const ConnectionEndpoint &endpoint, const Memory::MemoryViewRead &memory) = 0; virtual AuSPtr GetSocketFactory() = 0; }; @@ -453,12 +460,14 @@ namespace Aurora::IO::Net virtual AuUInt32 PollWorker(AuUInt8 workerId) = 0; virtual AuUInt32 RunWorker(AuUInt8 workerId, AuUInt32 timeout) = 0; - - // D: class APIs + // D: virtual bool BeginReadPollingOnWorkQueues(const WorkPoolGroup &workGroup) = 0; virtual bool BeginSubmissionsOnOnWorkQueues(const WorkPoolGroup &workGroup) = 0; virtual void StopPollingOnWorkQueues() = 0; + // E: + // .. + virtual AuUInt8 GetWorkers() = 0; virtual AuSPtr GetNetworkInterface() = 0; @@ -466,7 +475,6 @@ namespace Aurora::IO::Net virtual void Shutdown() = 0; }; - struct NetworkPool { AuUInt8 workers {1}; diff --git a/Include/Aurora/Locale/ECodePage.hpp b/Include/Aurora/Locale/ECodePage.hpp index 276a92ec..294cce33 100644 --- a/Include/Aurora/Locale/ECodePage.hpp +++ b/Include/Aurora/Locale/ECodePage.hpp @@ -9,21 +9,35 @@ namespace Aurora::Locale { - enum class ECodePage - { - eUnsupported, + AUE_DEFINE(ECodePage, ( eUTF32, eUTF32BE, + + eUTF16, eUTF16BE, + + // Extended 6 byte UTF8, capable of encoding disallowed characters in recent specs eUTF8, + + // Barely supported eUTF7, + + // GB2312 -> (Microsofts non-standard) GBK <-> GB 18030 + // GBK is the relevant subset of GB 18030, implemented by MS and iconv + // GB2312 is not so relevant + // GB 18030 is a backwards compatible modern spec e18030, e2312, eGBK, + + // SHIFT_JIS eSJIS, + + // Latin-x eLatin1, - eSysUnk, - eMax = eUnsupported - }; + + // System Codepage + eSysUnk + )); } \ No newline at end of file diff --git a/Include/Aurora/Locale/Encoding/Encoding.hpp b/Include/Aurora/Locale/Encoding/Encoding.hpp index 210cd3f0..4b9d7b40 100644 --- a/Include/Aurora/Locale/Encoding/Encoding.hpp +++ b/Include/Aurora/Locale/Encoding/Encoding.hpp @@ -19,11 +19,12 @@ namespace Aurora::Locale::Encoding AUKN_SYM BOM DecodeBOM(const Memory::MemoryViewRead &binary); // General purpose arbitrary page to UTF8 (AuStrings are UTF-8 - not 16 or 32; bite me) - AUKN_SYM AuStreamReadWrittenPair_t EncodeUTF8(const Memory::MemoryViewRead &utf8, const Memory::MemoryViewWrite &binary, ECodePage page = ECodePage::eUnsupported); - AUKN_SYM AuStreamReadWrittenPair_t DecodeUTF8(const Memory::MemoryViewRead &binary, const Memory::MemoryViewWrite &utf8, ECodePage page = ECodePage::eUnsupported); - AUKN_SYM AuStreamReadWrittenPair_t DecodeUTF8(const Memory::MemoryViewRead &binary, AuString &out, ECodePage page = ECodePage::eUnsupported); + AUKN_SYM AuStreamReadWrittenPair_t EncodeUTF8(const Memory::MemoryViewRead &utf8, const Memory::MemoryViewWrite &binary, ECodePage page = ECodePage::eEnumInvalid); + AUKN_SYM AuStreamReadWrittenPair_t DecodeUTF8(const Memory::MemoryViewRead &binary, const Memory::MemoryViewWrite &utf8, ECodePage page = ECodePage::eEnumInvalid); + AUKN_SYM AuStreamReadWrittenPair_t DecodeUTF8(const Memory::MemoryViewRead &binary, AuString &out, ECodePage page = ECodePage::eEnumInvalid); // Optimized UTF translation functions + // Note: these functions support full 6-byte UTF8 encoding. 5&6 are reserved. AUKN_SYM AuStreamReadWrittenPair_t ReadUTF32IntoUTF8ByteString(const Memory::MemoryViewRead &utf32, const Memory::MemoryViewWrite &utf8); AUKN_SYM AuStreamReadWrittenPair_t ReadUTF8IntoUTF32ByteString(const Memory::MemoryViewRead &utf8, const Memory::MemoryViewWrite &utf32); @@ -34,7 +35,10 @@ namespace Aurora::Locale::Encoding // Counst the amount of codepoints in a buffer, breaking when the stream is incomplete, giving you the accurate amount of bytes or relevant codepoints in a stream view AUKN_SYM AuUInt32 CountUTF32Length(const Memory::MemoryViewRead &utf32, bool bytes = false); // codepoint = U32 encoded; always 4 bytes per codepoint AUKN_SYM AuUInt32 CountUTF16Length(const Memory::MemoryViewRead &utf16, bool bytes = false); // codepoint = U32 encoded; at most: 4 bytes per codepoint, usual: 2 bytes - AUKN_SYM AuUInt32 CountUTF8Length(const Memory::MemoryViewRead &utf8, bool bytes = false); // codepoint = U32 encoded; at most: 6 bytes per codepoint - AUKN_SYM AuUInt32 CountSJISLength(const Memory::MemoryViewRead &sjis, bool bytes = false); // codepoint = one character + AUKN_SYM AuUInt32 CountUTF8Length (const Memory::MemoryViewRead &utf8, bool bytes = false); // codepoint = U32 encoded; at most: 6 bytes per codepoint + AUKN_SYM AuUInt32 CountSJISLength (const Memory::MemoryViewRead &sjis, bool bytes = false); // codepoint = one character AUKN_SYM AuUInt32 CountGBK16Length(const Memory::MemoryViewRead &gbk, bool bytes = false); // codepoint = at most; one GBK byte pair + + + AUKN_SYM AuUInt32 CountEncodedStringLength(ECodePage page, const Memory::MemoryViewRead &view, bool bytes = false); } \ No newline at end of file diff --git a/Include/Aurora/Locale/Locale.hpp b/Include/Aurora/Locale/Locale.hpp index a014f547..cbb24d2c 100644 --- a/Include/Aurora/Locale/Locale.hpp +++ b/Include/Aurora/Locale/Locale.hpp @@ -20,7 +20,7 @@ namespace Aurora::Locale const AuString &language; /// ISO 639 const AuString &country; /// ISO 3166 const AuString &codeset; /// - const ECodePage codepage; /// Potentially eSysUnk; noting that eSysUnk is valid and handlable by the internal backend + const ECodePage codepage; /// Potentially eSysUnk. Note that eSysUnk is valid and handlable by iconv and nsl. On windows and unix, this is your codepage. }; /* diff --git a/Include/Aurora/Locale/LocaleStrings.hpp b/Include/Aurora/Locale/LocaleStrings.hpp index 11cfff2d..b2f2d10f 100644 --- a/Include/Aurora/Locale/LocaleStrings.hpp +++ b/Include/Aurora/Locale/LocaleStrings.hpp @@ -1,3 +1,10 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: LocaleStrings.hpp + Date: 2022-1-24 + Author: Reece +***/ #pragma once #include @@ -10,10 +17,11 @@ namespace Aurora::Locale AUKN_SYM const AuString &NewLine(); AUKN_SYM const AuString &TimeLocaleGetMSChar(); - AUKN_SYM const AuString &TimeLocaleS(); + AUKN_SYM const AuString &TimeLocaleGetSChar(); AUKN_SYM const AuString &TimeLocaleGetDayChar(); AUKN_SYM AuString TimeDateToString(const Time::tm &time); + AUKN_SYM AuString TimeDateToFileNameISO8601(const Time::tm &time, Time::ETimezoneShift shift = Time::ETimezoneShift::eUTC); AUKN_SYM AuString TimeDateToISO8601(const Time::tm &time, Time::ETimezoneShift shift = Time::ETimezoneShift::eUTC); AUKN_SYM AuString ConvertMSToTimescale(AuUInt32 ms); diff --git a/Include/Aurora/Logging/IBasicSink.hpp b/Include/Aurora/Logging/IBasicSink.hpp new file mode 100644 index 00000000..278b94e8 --- /dev/null +++ b/Include/Aurora/Logging/IBasicSink.hpp @@ -0,0 +1,25 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IBasicSink.hpp + Date: 2021-11-1 + Author: Reece +***/ +#pragma once + +namespace Aurora::Logging +{ + AUKN_INTERFACE(IBasicSink, + + // async callback + AUI_METHOD(void, OnMessageBlocking, (AuUInt8, level, const ConsoleMessage &, msg)), + + // sync callback + // returns true if async aware, that is, OnMessageBlocking will be scheduled + AUI_METHOD(bool, OnMessageNonblocking, (AuUInt8, level, const ConsoleMessage &, msg)), + + // called every configurable MS or during a problematic event warrenting flush + // expect onflush to be called once after a series of OnMessageNonblocking and every N milliseconds (^1) + AUI_METHOD(void, OnFlush, ()) + ) +} \ No newline at end of file diff --git a/Include/Aurora/Logging/IBasicSinkRB.hpp b/Include/Aurora/Logging/IBasicSinkRB.hpp new file mode 100644 index 00000000..6b01858a --- /dev/null +++ b/Include/Aurora/Logging/IBasicSinkRB.hpp @@ -0,0 +1,25 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: IBasicSinkRB.hpp + Date: 2021-11-2 + Author: Reece +***/ +#pragma once + +namespace Aurora::Logging +{ + struct IBasicSinkRB : IBasicSink + { + /** + * @brief Writes the log buffer to a file as though it were an FIO sink + */ + virtual void SaveToPath(const AuString &path, bool binary = false) = 0; + + /** + * @brief Dumps the ring buffer to an ordered list + * This method does not clear the ring buffer + */ + virtual AuList Export() = 0; + }; +} \ No newline at end of file diff --git a/Include/Aurora/Console/Logging/ILogger.hpp b/Include/Aurora/Logging/ILogger.hpp similarity index 88% rename from Include/Aurora/Console/Logging/ILogger.hpp rename to Include/Aurora/Logging/ILogger.hpp index 2e01e001..730b6302 100644 --- a/Include/Aurora/Console/Logging/ILogger.hpp +++ b/Include/Aurora/Logging/ILogger.hpp @@ -7,21 +7,24 @@ ***/ #pragma once -namespace Aurora::Console::Logging +namespace Aurora::Logging { - enum class ELogLevel - { - eZero = 0, - eInfo = 0, + using ConsoleMessage = Console::ConsoleMessage; + using EAnsiColor = Console::EAnsiColor; + + AUE_DEFINE(ELogLevel, + ( + eInfo, eVerbose, eError, eDebug, eWarn - }; + )); - static auto const kLogLevelDefault = static_cast(ELogLevel::eZero); - static auto const kLogLevelUsr = static_cast(ELogLevel::eWarn); - static auto const kLogLevelMax = 16; + static auto const kLogLevelDefault = static_cast(kELogLevelMinLegal); + static auto const kLogLevelUsr = static_cast(kELogLevelMaxLegal); + static auto const kLogLevelMax = AuUInt8(255); + struct ILogger { virtual void WriteMessage(AuUInt8 level, const ConsoleMessage &msg) = 0; diff --git a/Include/Aurora/Console/Logging/Logging.hpp b/Include/Aurora/Logging/Logging.hpp similarity index 89% rename from Include/Aurora/Console/Logging/Logging.hpp rename to Include/Aurora/Logging/Logging.hpp index 7a569629..8995eddc 100644 --- a/Include/Aurora/Console/Logging/Logging.hpp +++ b/Include/Aurora/Logging/Logging.hpp @@ -12,8 +12,19 @@ #include "IBasicSinkRB.hpp" #include "Sinks.hpp" -namespace Aurora::Console::Logging +namespace Aurora::Logging { + /// Writes a log message to the console subscribers and telemetry sinks + AUKN_SYM void WriteLine(AuUInt8 level, const Console::ConsoleMessage &msg); + + /** + * @brief Overloads the ILogger backend of the AuLogXX functions + * @param defaultGlobalLogger + * @return + */ + AUKN_SYM void SetGlobalLogger(const AuSPtr &defaultGlobalLogger); + + #if defined(_AUHAS_FMT) template @@ -134,7 +145,7 @@ namespace Aurora::Console::Logging template \ static void AuLog ## level(T&& ... args) \ { \ - Aurora::Console::Logging::Log ## level(AuForward(args)...); \ + Aurora::Logging::Log ## level(AuForward(args)...); \ } ADD_AU_GLOBAL_ALIAS(Info) @@ -148,4 +159,6 @@ ADD_AU_GLOBAL_ALIAS(Verbose) ADD_AU_GLOBAL_ALIAS(VerboseNoShip) #else #define AuLogVerboseNoShip(...) -#endif \ No newline at end of file +#endif + +#undef ADD_AU_GLOBAL_ALIAS \ No newline at end of file diff --git a/Include/Aurora/Console/README.txt b/Include/Aurora/Logging/README.txt similarity index 100% rename from Include/Aurora/Console/README.txt rename to Include/Aurora/Logging/README.txt diff --git a/Include/Aurora/Logging/Sinks.hpp b/Include/Aurora/Logging/Sinks.hpp new file mode 100644 index 00000000..b790e1db --- /dev/null +++ b/Include/Aurora/Logging/Sinks.hpp @@ -0,0 +1,61 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: Sinks.hpp + Date: 2021-11-2 + Author: Reece +***/ +#pragma once + +namespace Aurora +{ + struct SocketConsole; +} + +namespace Aurora::Logging +{ + struct DirectoryLogger + { + AuUInt32 maxLogsOrZero {}; + AuUInt32 maxFileSizeOrZero {}; // MB + }; + + /** + * @brief Constructs a UTF8 output sink. + * Backed by stdconsole; supports posix fd stdin/out localized, visual studio debugger, and conhost + */ + AUKN_SHARED_API(NewStdSink, IBasicSink); + + /** + * @brief Unimplemented systemd or service (?) backend + */ + AUKN_SHARED_API(NewOSEventDirectorySink, IBasicSink); + + /** + * @brief Constructs a new sink backed by, syslog or eventlog, by name or event source respectively + */ + AUKN_SHARED_API(NewOSNamedEventDirectorySink, IBasicSink, const AuString &name); + + /** + * @brief Constructs a text of binary log file sink + */ + AUKN_SHARED_API(NewFileSink, IBasicSink, const AuString &path, bool binary = false); + + /** + * @brief Constructs a dedicated log directory subject to erasure as defined by defined DirectoryLogger + */ + AUKN_SHARED_API(NewDirectorySink, IBasicSink, const AuString &path, DirectoryLogger dirInfo, bool binary = false); + + // TODO: + AUKN_SHARED_API(NewIPCSink, IBasicSink, const SocketConsole &console); + + /** + * @brief Constructs an in-memory ring buffer sink + */ + AUKN_SHARED_API(NewRingLogger, IBasicSinkRB, AuUInt32 maxLogEntries); + + /** + * @brief Constructs a logger object from an array of sinks + */ + AUKN_SHARED_API(NewLogger, ILogger, const AuList> &sinks); +} \ No newline at end of file diff --git a/Include/Aurora/Loop/ELoopSource.hpp b/Include/Aurora/Loop/ELoopSource.hpp new file mode 100644 index 00000000..1088c7f8 --- /dev/null +++ b/Include/Aurora/Loop/ELoopSource.hpp @@ -0,0 +1,41 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ELoopSource.hpp + Date: 2022-2-9 + Author: Reece +***/ +#pragma once + +namespace Aurora::Loop +{ + enum class ELoopSource + { + eSourceInternalReserved1, + eSourceInternalReserved2, + eSourceInternalReserved3, + eSourceInternalReserved4, + + // generic + eSourceSemaphore, + eSourceCV, + eSourceEvent, + eSourceMutex, + eSourceSRW, + eSourceSocketGroup, + eSourceTimer, + eSourceAIO, + eSourceHandle, + + // Specific to the runtime subsystem + eSourceAsync, + + // glib oses only + eSourceGlib, + + // window messge loops + eSourceApple, + eSourceX11, + eSourceWin32 + }; +} \ No newline at end of file diff --git a/Include/Aurora/Loop/ILoopQueue.hpp b/Include/Aurora/Loop/ILoopQueue.hpp new file mode 100644 index 00000000..f4ec5e7f --- /dev/null +++ b/Include/Aurora/Loop/ILoopQueue.hpp @@ -0,0 +1,186 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ILoopQueue.hpp + Date: 2022-2-12 + Author: Reece +***/ +#pragma once + +namespace Aurora::Loop +{ + // This is like a CF RunLoop with the input parameters of NT's WaitMultipleObjects + // This shouldn't be too much heavier than CF's libevent/NT abstraction in the style of a kevent interface with objects + + struct ILoopQueue + { + /** + * @brief + * [*] Source add/remove operations should be followed by a Commit() to commit the changes + * + * [*] Calling Source[Add/Remove] during a Wait[Any/All[Ex]] will cause the wait function to + * return false, allowing for the caller to rewait on the updated queue, or to allow + * the thread to account for the object-was-invalidated condition + * + * @param source + * @return + */ + virtual bool SourceAdd(const AuSPtr &source) = 0; + + /** + * @brief Same behaviour as SourceAdd + * @param source + * @param timeoutMS + * @return + */ + virtual bool SourceAddWithTimeout(const AuSPtr &source, AuUInt32 timeoutMS) = 0; + + /** + * @brief Remove operations include commit. You do not need to follow a remove with a commit. + * Sources are defacto poped unless subscriber returns false indicating repeated lock attempts are wanted. + * Should no subscriber be registered, the loop source will not be automatically removed + * @param source + */ + virtual bool SourceRemove(const AuSPtr &source) = 0; + + /** + * @brief Updates the OS watchdog list cache concept after Source[Remove/Add[WithTimeout]] + * @return + */ + virtual bool Commit() = 0; + + /** + * @brief + * @return the amount of loop sources added to the queue + */ + virtual AuUInt32 GetSourceCount() = 0; + + /** + * @brief Appends a callback handler to be paired with a loop source + * + * Once a loop source become signaled, and a Wait[Any/All] function call is made, loop source subscribers are called + * to filter the final should-remove operation. The final popped objects are returned from Wait[Any[Ex]] and forgotten. + * + * If no ILoopSourceSubscribers are registered, the edge case behaviour is that loop sources will not be automatically + * dequeued. No user code explicitly told us to do anything other than wait, so the default behaviour of Wait[Any[Ex]] + * shall be to not evict loop sources, until at least one callback is registered, or until SourceRemove is called. + * + * Returning true from a ILoopSourceSubscriber will allow the ILoopQueue to evict the loop source + * Returning false from a ILoopSourceSubscriber will prevent eviction, resulting in continued ILoopSourceSubscriber callbacks to all subscribers + * + * @param source + * @param subscriber + * @return + */ + virtual bool AddCallback(const AuSPtr &source, const AuSPtr &subscriber) = 0; + + /** + * @brief Identical behaviour to that of the basic method. In addition, ILoopSourceSubscriberEx::OnTimeout is called + * on violation of the timeout provided to SourceAddWithTimeout + * @param source + * @param subscriber + * @return + */ + virtual bool AddCallbackEx(const AuSPtr &source, const AuSPtr &subscriber) = 0; + + /** + * @brief Near identical behaviour of the extended AddCallback method. + * Registers a callback to handle all loop source signaled events. + * @param subscriber + * @return + */ + virtual bool AddCallback(const AuSPtr &subscriber) = 0; + + /** + * @brief Indicates whether or not all the loop sources are in a signaled state and all + * relevant interfaces, such as internal IPC handlers and ILoopSourceSubscribers, + * have received the update. Merely waiting for all loop sources to finish is not + * sufficient. One must process the signaled states by calling a Wait function + * when the HasAnyPending() condition is valid. + * @return + */ + virtual bool HasFinished() = 0; + + /** + * @brief Nonblocking wait-any for all objects in the loop queue + * @return + */ + virtual bool IsSignaled() = 0; + + /** + * @brief Waits on all the submitted loop sources until they are all complete or until the timeout has finished. + * Note: the completion of another Wait[All/Any[Ex]] call may result in a + * @param timeout + * @return + */ + virtual bool WaitAll (AuUInt32 timeout = 0) = 0; + + /** + * @brief Waits on all the loop sources until at least one is signaled + * @param timeout + * @return + */ + virtual AuUInt32 WaitAny (AuUInt32 timeout = 0) = 0; + + /** + * @brief + * @param timeout + * @return + */ + virtual AuList> WaitAnyEx(AuUInt32 timeout = 0) = 0; + + /** + * @brief + * Mostly relevant on Windows where the limit is 64 versus horrible BSD-y socket + * optimized interfaces that can handle thousands of fds + * + * In large loop queues, a maximum of + * `sectionTickTime * (sectionDequeCount + clamp(platformSanity, sectionDequeCount))` + * kernel objects can be checked within a given time frame. + * + * What this effectively does is iterate over a subdivided work queue, aligned + * to platformSanity, [i, i+platform sanity] objects can be safely waitany on. + * + * On timeout of sectionTickTime, + * [i, i+sectionDequeCount] of the tick could be checked, however, we know + * [i, i+platform sanity] timeouted so, in the event of a timeout, we can + * asynchronously check [i+platform sanity, ...] to be nicer faster. Since + * we've already spent the maximum allocated time to poll on a mere subset, + * we may as well desperately check sectionDequeCount worth of objects, and + * write-off the time spent blocking. That way, we get upto platform sanity + * of is signaled checks for free in the worst case scenario. The perspective + * that the overshoot is expensive doesn't make sense, when the is signaled + * check is basically free and the timeout on a subset of the req was the + * bottleneck. + * + * Otherwise on success, we know to check in the range of [i, platform sanity + * for at least one alerted object. + * + * Looking anywhere else given any help from a waitany interface would be stupid. + * + * Internal logic will dequeue platform coefficient aligned handles, and the timeout + * optimization shall check [i+platform sanity, i+platform sanity+sectionDequeCount]. + * 1 handle =/= 1 loop source, tho usually 1 loop source ~= 1 handle + * + * tl'dr: + * [*] dont use if you cant stall for sectionTickTime if sectionDequeCount of your + * loop sources are unsignaled + * [*] chug paths are intended for observer threads and not for maintaining high + * performance. no sane traditional application would ever have 64+ signalable + * objects stuck in a loop. though if you do, and you dont configure anything, + * the worst case scenario is, WaitAny can take upto a millisecond to discover + * a signaled loop source. + * + * @param sectionTickTime + * @param sectionDequeCount + */ + virtual void ChugPathConfigure(AuUInt32 sectionTickTime, AuSInt sectionDequeCount) = 0; + + /** + * @brief Hints that the calling program understands the kernel shouldnt schedule tne entire source list, and instead, we should long poll + */ + virtual void ChugHint(bool value) = 0; + }; + + AUKN_SYM AuSPtr NewLoopQueue(); +} \ No newline at end of file diff --git a/Include/Aurora/Loop/ILoopSource.hpp b/Include/Aurora/Loop/ILoopSource.hpp new file mode 100644 index 00000000..ffa56b3c --- /dev/null +++ b/Include/Aurora/Loop/ILoopSource.hpp @@ -0,0 +1,26 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ILoopSource.hpp + Date: 2022-2-12 + Author: Reece +***/ +#pragma once + +namespace Aurora::Loop +{ + struct ILoopSource + { + /** + * @brief Atomic is-signaled-and-latch + * @return + */ + virtual bool IsSignaled() = 0; + + /** + * @brief Returns a generic description about the loop source handle + * @return + */ + virtual ELoopSource GetType() = 0; + }; +} \ No newline at end of file diff --git a/Include/Aurora/Loop/ILoopSourceSubscriber.hpp b/Include/Aurora/Loop/ILoopSourceSubscriber.hpp new file mode 100644 index 00000000..d42f3262 --- /dev/null +++ b/Include/Aurora/Loop/ILoopSourceSubscriber.hpp @@ -0,0 +1,36 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ILoopSourceSubscriber.hpp + Date: 2022-2-12 + Author: Reece +***/ +#pragma once + +namespace Aurora::Loop +{ + AUKN_INTERFACE(ILoopSourceSubscriber, + /** + * @brief called under Wait[All/Any[Ex]] once an object is signaled + * @return should pop from ILoopQueue + */ + AUI_METHOD(bool, OnFinished, (const AuSPtr &, source)) + ); + + + AUKN_INTERFACE(ILoopSourceSubscriberEx, + /** + * @brief called under Wait[All/Any[Ex]] once an object is signaled + * @return should pop from ILoopQueue + */ + AUI_METHOD(bool, OnFinished, (const AuSPtr &, source)), + + /** + * @brief called under Wait[All/Any[Ex]] once an object timesout before being evicted + * @param + * @param AUI_METHOD + * @param AUI_METHOD + */ + AUI_METHOD(void, OnTimeout, (const AuSPtr &, source)) + ); +} \ No newline at end of file diff --git a/Include/Aurora/Loop/Loop.hpp b/Include/Aurora/Loop/Loop.hpp index 684c86c1..95700f22 100644 --- a/Include/Aurora/Loop/Loop.hpp +++ b/Include/Aurora/Loop/Loop.hpp @@ -4,91 +4,63 @@ File: Loop.hpp Date: 2021-8-21 Author: Reece + Notes: This API class is specifically for kernel objects or similar userland schedular handles, this is not comparable to the async subsystem. + While you may drive low perf user facing apps and small services from this, other services should divide and conquer + * Allow the network subsystem to load balance sockets across a predefined amount of workers, + * Use semaphores instead of massive lengthy arrays of mutexes + * Use grouped long-polling LoopSources to convert kernel or waitable objects to a single time-polled loop source ***/ #pragma once -namespace Aurora::Loop -{ - enum class ELoopSource - { - eSourceInternalReserved1, - eSourceInternalReserved2, - eSourceInternalReserved3, - eSourceInternalReserved4, - - // generic - eSourceSemaphore, - eSourceCV, - eSourceEvent, - eSourceMutex, - eSourceSRW, - eSourceTimer, - eSourceAIO, - eSourceHandle, - - // Specific to the runtime subsystem - eSourceAsync, - - // glib oses only - eSourceGlib, - - // window messge loops - eSourceApple, - eSourceX11, - eSourceWin32 - }; +#include "ELoopSource.hpp" +#include "ILoopSource.hpp" +#include "ILoopSourceSubscriber.hpp" +#include "ILoopQueue.hpp" - class ILoopSource - { - public: - virtual bool IsSignaled() = 0; - virtual ELoopSource GetType() = 0; - }; - +namespace Aurora::Loop +{ + /// @deprecated AUKN_SYM AuList> WaitMultipleOrObjects(const AuList> &objects, AuUInt32 timeout); - class ILSSemaphore : public ILoopSource + struct ILSSemaphore : public ILoopSource { - public: virtual bool AddOne() = 0; }; - class ILSEvent : public ILoopSource + struct ILSEvent : public ILoopSource { - public: virtual bool Set() = 0; virtual bool Reset() = 0; }; - class ILSMutex : public ILoopSource + struct ILSMutex : public ILoopSource { - public: virtual bool Unlock() = 0; }; - class IConditionVar : public ILoopSource + struct IConditionVar : public ILoopSource { - public: virtual bool Signal() = 0; virtual bool Broadcast() = 0; }; - class ITimer : public ILoopSource + struct ITimer : public ILoopSource { - public: virtual void UpdateTime(AuUInt64 absTimeMs) = 0; + virtual void Stop() = 0; }; AUKN_SYM AuSPtr NewLSCondVar(const AuSPtr &primitive); AUKN_SYM AuSPtr NewLSCondVar(const AuSPtr &source); - AUKN_SYM AuSPtr NewLSTimer(AuUInt64 absTimeMs); + AUKN_SYM AuSPtr NewLSTimer(AuUInt64 absTimeMs, AuUInt32 reschedMs = 0); AUKN_SYM AuSPtr NewLSMutex(); AUKN_SYM AuSPtr NewLSEvent(bool triggerd = false, bool atomicRelease = true, bool permitMultipleTriggers = false); AUKN_SYM AuSPtr NewLSSemaphore(AuUInt32 initialCount = 0); AUKN_SYM AuSPtr NewLSOSHandle(AuUInt); - AUKN_SYM AuSPtr NewLSAsync(); - AUKN_SYM AuSPtr NewLSWin32Source(); + AUKN_SYM AuSPtr NewLSAsync(Async::WorkerPId_t workerPid); + AUKN_SYM AuSPtr NewLSFile(const AuSPtr &fileTransaction); + AUKN_SYM AuSPtr NewLSWin32Source(bool dispatchMessages); AUKN_SYM AuSPtr NewLSAppleSource(); #if defined(X_PROTOCOL) @@ -113,4 +85,5 @@ namespace Aurora::Loop return NewLSOSHandle(reinterpret_cast(handle)); } #endif -} \ No newline at end of file +} + diff --git a/Include/Aurora/Memory/ByteBuffer.hpp b/Include/Aurora/Memory/ByteBuffer.hpp index a2345fda..4fa52948 100644 --- a/Include/Aurora/Memory/ByteBuffer.hpp +++ b/Include/Aurora/Memory/ByteBuffer.hpp @@ -7,33 +7,45 @@ ***/ #pragma once +#include + namespace Aurora::Memory { + enum class EStringType + { + eStringTerminated, + eStringByte, + eStringWord, + eStringDword, + eStringQword + }; + static const auto kBufferPageSize = 512; //static const auto kBufferBasePower = 8; static const auto kBufferInitialPower = 9;// -kBufferBasePower; // 4-bit integer /*** - * A bytebuffer object represents a linear, partially-linear resizable, buffer **or** a ring buffer. + * A bytebuffer object represents a exponentially page-scale resizable buffer **or** a ring buffer. + + * Trivial, linear, use-once serialization use cases will likely follow the linear fast paths, not that of a + * ring buffer. * * Use cases for a ring buffer include wrapping streams for a use case in which the consumer may * expect arbitrary stream seeks of an otherwise limited consume-once stream * - * IE; + * EG: * -> Peeking a header in a datagram, or tcp stream; where instead of freeing the datagram or double * buffering the network stack when required, a ring buffer is used to prevent reallocation on each frame - * -> Peeking, or seeking back after, compression read. A compression api could be fed on-Sdemand or ad hoc, - * writing to its write head pointer, while never running out of space so long as the decompressed ring - * read head continues moving + * -> Peeking, or seeking back after, compression read. A compression api could be fed on-known-input-available + * or on-demand, writing to its write head pointer, while never running out of space so long as the + * decompressed ring read head continues moving * - * Small, linear, write/read-once [de]serialization use cases may elect to allocate a buffer and - * follow the linear fast paths; perhaps even enabling flagExpandable for hopefully-smarter-than-stdvec-scaling - * - * Ring buffers scale from the write head, to the read head, potentially going-around in the process - * - * Linear flagExpandable buffers scale from [0, length]; reallocating at end of buffer if flagExpandable is enabled - * if expanding is enabled, - * realloc(max(size + offset, (offset / kBufferPageSize + 1) * kBufferPageSize)) + * Writing: + * Ring buffers scale from the write head, to the read head, potentially going-around in the process + * + * Linear flagExpandable buffers scale from [0, length] + * if expanding is enabled, + * ~~realloc(max(size + offset, (offset / kBufferPageSize + [1 or 2]) * kBufferPageSize))~~ wrong, this was too slow for large streams, high write count cases * * Deprecates INetworkStream, fixes allocation issues around compression backends * Superseeds abuse of AuList for binary blobs, alongside Memory::Array @@ -72,6 +84,10 @@ namespace Aurora::Memory AuUInt8 scaleSize;// : 4; screw it.... we should just take 6 * (4/8) up to 32/64, we wont go up a slab allocation bucket, whatever you want to call it /////////////////////////////////////////////////////////////////////// + /** + * @brief Move constructor + * @param buffer + */ ByteBuffer(ByteBuffer &&buffer) { this->base = buffer.base; @@ -92,6 +108,11 @@ namespace Aurora::Memory buffer.scaleSize = {}; } + /** + * @brief Copy with possible preserve pointers + * @param buffer + * @param preservePointers + */ ByteBuffer(const ByteBuffer &buffer, bool preservePointers = true) { this->base = FAlloc(buffer.length); @@ -118,6 +139,13 @@ namespace Aurora::Memory this->scaleSize = buffer.scaleSize; } + /** + * @brief Copy pointer range into a new ring or byte buffer + * @param in + * @param length + * @param circular + * @param expandable + */ ByteBuffer(const void *in, AuUInt length, bool circular = false, bool expandable = false) : flagCircular(circular), flagExpandable(expandable), flagReadError(0), flagWriteError(0) { this->base = FAlloc(length); @@ -180,14 +208,17 @@ namespace Aurora::Memory Reset(); return; } - this->length = length; + this->length = length; this->allocSize = length; - this->readPtr = this->base; - this->writePtr = this->base; + this->readPtr = this->base; + this->writePtr = this->base + length; this->scaleSize = kBufferInitialPower; AuMemcpy(this->base, base, length); } + /** + * @brief Default constructor, allocates an auto-expanding linear bytebuffer + */ ByteBuffer() : flagCircular(0), flagExpandable(true), flagReadError(0), flagWriteError(0) { this->base = {}; @@ -214,39 +245,40 @@ namespace Aurora::Memory this->writePtr = base; } - // Iterator - inline auline AuUInt8 * data() const; - inline auline AuUInt size() const; + // utils: Iterator + inline auline AuUInt8 * data() const; + inline auline AuUInt size() const; inline auline AuUInt8 * begin() const; - inline auline AuUInt8 * end() const; + inline auline AuUInt8 * end() const; inline auline bool empty() const; inline void clear(); inline void resize(AuUInt size); inline void reserve(AuUInt size); - // Utils To alternative types + // utils: Utils to alternative types inline auline AuList ToVector() const; inline AuUInt32 GetAllocationPower() const; inline operator AuList() const; inline operator MemoryViewRead() const; - // Internal buffer comparison + // utils: Internal buffer comparison inline bool operator ==(const AuList &) const; inline bool operator ==(const MemoryViewRead &) const; inline bool operator ==(const ByteBuffer &) const; - // Move assignment + // utils: Move assignment inline ByteBuffer &operator =(ByteBuffer &&); - // &byteArray[n] + // utils: &byteArray[n] inline AuUInt8 &operator [](AuUInt idx) const; - // if (byteArray) -> if (byteArray->IsValid()) + // utils: if (byteArray) -> if (byteArray->IsValid()) inline operator bool() const; inline AuList RemainingBytesToVector(bool endAtWrite = true) const; - + // ... utils are mostly const functions that provide language intrinsics, access, and container-like compatibility + // ByteBuffer specific utils can be found under Utilities // Seek / Position inline auline bool ReaderTryGoForward(AuUInt32 offset); @@ -261,6 +293,7 @@ namespace Aurora::Memory inline auline AuUInt GetReadOffset() const; inline auline AuUInt GetWriteOffset() const; + inline auline void ResetReadPointer(); inline AuOptional WriterTryGetWriteHeadFor(AuUInt32 nBytes); @@ -270,13 +303,53 @@ namespace Aurora::Memory inline auline bool SetBuffer(const void *in, AuUInt length); inline auline bool SetBuffer(const AuList &buffer); + /** + * @brief Releases excess memory (like, shrink to fit in c++) + * @return + */ inline auline void GC(); + + /** + * @brief Releases all resources and resets the bytebuffer without an allocation + */ inline void Reset(); + + /** + * @brief Expands the underlying buffer allocation to at least length. + * Does nothing on failure. Programs can try to allocate in real time + * and handle the write error flag condition from there. To pull the + * real buffer size, see member field allocSize. + * @param length + */ inline void Reserve(AuUInt length); + + /** + * @brief Is allocated or dummy object? + * @return + */ inline auline bool IsEmpty() const; + + /** + * @brief Is an error flag set? + * @return + */ inline auline bool HasStreamError() const; + + /** + * @brief Returns true so long as + * 1) an error has not occured or, + * 1) the relevant error flag was reset; and + * 2) there is a valid underlying buffer + * + * @return + */ inline auline bool IsValid() const; + /** + * @brief Allocate at least length bytes, without adjusting the relative read/write head offsets + * @param length + * @return + */ inline auline bool Resize(AuUInt length); // Basic Read Write @@ -284,6 +357,19 @@ namespace Aurora::Memory inline auline AuUInt Write(const void *buffer, AuUInt requestLength); inline auline AuUInt Read(void *out, AuUInt requestedLength, bool peek = false); + // String API + + inline bool WriteString(const AuString &string, EStringType type, Locale::ECodePage codepage = Locale::ECodePage::eUTF8); + inline bool ReadString(AuString &string, EStringType type, Locale::ECodePage codepage = Locale::ECodePage::eUTF8); + + // Copy, concat, etc + inline bool WriteFrom(ByteBuffer &buffer, AuUInt length); + + // Utilities + inline bool Trim(AuUInt tail); + inline bool Pad(AuUInt16 aPowOf2, AuUInt8 magicCharacter = '\x00'); + inline bool Fill(AuUInt length, AuUInt8 magicCharacter = '\x00'); + // Typed read/write template T Read(); diff --git a/Include/Aurora/Memory/ByteBufferPushReadState.hpp b/Include/Aurora/Memory/ByteBufferPushReadState.hpp new file mode 100644 index 00000000..bd22cc1e --- /dev/null +++ b/Include/Aurora/Memory/ByteBufferPushReadState.hpp @@ -0,0 +1,39 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ByteBufferPushReadState.hpp + Date: 2022-2-15 + Author: Reece +***/ +#pragma once + +namespace Aurora::Memory +{ + struct ByteBufferPushReadState + { + ByteBuffer &bytebuffer; + + ByteBufferPushReadState(ByteBuffer &bytebuffer, bool pushError = false) : bytebuffer(bytebuffer), shouldPopError_(pushError) + { + this->readPos_ = this->bytebuffer.readPtr - this->bytebuffer.base; + this->readErrorFlag_ = bytebuffer.flagReadError; + } + + ~ByteBufferPushReadState() + { + if (this->readErrorFlag_ != bytebuffer.flagReadError) + { + if (this->shouldPopError_) + { + this->bytebuffer.flagReadError = this->readErrorFlag_; + } + this->bytebuffer.readPtr = this->bytebuffer.base + this->readPos_; + } + } + + private: + bool readErrorFlag_; + AuUInt readPos_; + const bool shouldPopError_; + }; +} \ No newline at end of file diff --git a/Include/Aurora/Memory/ByteBufferPushWriteState.hpp b/Include/Aurora/Memory/ByteBufferPushWriteState.hpp new file mode 100644 index 00000000..25f2b47e --- /dev/null +++ b/Include/Aurora/Memory/ByteBufferPushWriteState.hpp @@ -0,0 +1,39 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ByteBufferPushWriteState.hpp + Date: 2022-2-15 + Author: Reece +***/ +#pragma once + +namespace Aurora::Memory +{ + struct ByteBufferPushWriteState + { + ByteBuffer &bytebuffer; + + ByteBufferPushWriteState(ByteBuffer &bytebuffer, bool pushError = false) : bytebuffer(bytebuffer), shouldPopError_(pushError) + { + this->writePos_ = this->bytebuffer.writePtr - this->bytebuffer.base; + this->writeErrorFlag_ = bytebuffer.flagWriteError; + } + + ~ByteBufferPushWriteState() + { + if (this->writeErrorFlag_ != bytebuffer.flagWriteError) + { + if (this->shouldPopError_) + { + this->bytebuffer.flagWriteError = this->writeErrorFlag_; + } + this->bytebuffer.writePtr = this->bytebuffer.base + this->writePos_; + } + } + + private: + bool writeErrorFlag_; + AuUInt writePos_; + const bool shouldPopError_; + }; +} \ No newline at end of file diff --git a/Include/Aurora/Memory/ByteBuffer_Memory.inl b/Include/Aurora/Memory/ByteBuffer_Memory.inl index b53bc861..e1be3559 100644 --- a/Include/Aurora/Memory/ByteBuffer_Memory.inl +++ b/Include/Aurora/Memory/ByteBuffer_Memory.inl @@ -49,6 +49,7 @@ namespace Aurora::Memory if (this->base) { Free(this->base); + this->base = {}; } this->base = {}; @@ -62,16 +63,32 @@ namespace Aurora::Memory void ByteBuffer::Reserve(AuUInt length) { auto oldLength = this->length; - this->Resize(length); - this->length = AuMin(oldLength, length); + if (length > this->allocSize) + { + this->Resize(length); + } + this->length = AuMin(oldLength, this->length); } void ByteBuffer::GC() { - if (this->length) - if (this->allocSize == this->length) return; - auto temp = Memory::FRealloc(this->base, this->length); - if (!temp) return; + if (!this->base) + { + return; + } + + if (this->allocSize == this->length) + { + return; + } + + auto temp = Memory::ZRealloc(this->base, this->length); + + if (!temp) + { + return; + } + this->base = temp; this->length = this->length; this->allocSize = this->length; @@ -84,7 +101,9 @@ namespace Aurora::Memory if (length == 0) { - Reset(); + this->length = 0; + this->writePtr = this->base; + this->readPtr = this->base; return true; } @@ -109,7 +128,7 @@ namespace Aurora::Memory { auto scale = GetAllocationPower(); oldLength = this->length; - newLength = AuMax(AuUInt(length), AuUInt(((this->allocSize / scale) + 1) * scale)); + newLength = AuMax(AuUInt(length), (((this->allocSize * 2) / scale) + 1) * scale);// AuUInt(((this->allocSize / scale) + 2) * scale)); < this spends too much time spinning nextPtr = ZRealloc(this->base, newLength); if (!nextPtr) diff --git a/Include/Aurora/Memory/ByteBuffer_Position.inl b/Include/Aurora/Memory/ByteBuffer_Position.inl index 0ddf89b1..e9a770e0 100644 --- a/Include/Aurora/Memory/ByteBuffer_Position.inl +++ b/Include/Aurora/Memory/ByteBuffer_Position.inl @@ -11,19 +11,37 @@ namespace Aurora::Memory { bool ByteBuffer::WriterTryGoForward(AuUInt32 offset) { + if (!offset) + { + return true; + } + + auto old = writePtr - base; auto n = Write(nullptr, offset); - SysAssert(n == offset); // TODO: writer go back + if (n != offset) + { + this->writePtr = this->base + old; + return false; + } + return true; } bool ByteBuffer::ReaderTryGoForward(AuUInt32 offset) { + if (!offset) + { + return true; + } + + auto old = readPtr - base; auto n = Read(nullptr, offset, false); if (n != offset) { - SysAssert(ReaderTryGoBack(n)); + this->readPtr = this->base + old; return false; } + return true; } @@ -70,12 +88,12 @@ namespace Aurora::Memory if (readOffset < offset) { - auto absPosition = offset - readOffset; + auto absPosition = (AuUInt)offset - readOffset; auto goAround = absPosition; auto backIdx = length - goAround; auto writeOffset = writePtr - base; - if (writeOffset > backIdx) + if ((AuUInt)writeOffset > (AuUInt)backIdx) { return false; } @@ -118,7 +136,7 @@ namespace Aurora::Memory { if ((readPtr < writePtr) && (endAtWrite)) { - return length - (writePtr - readPtr); + return writePtr - readPtr; } else { @@ -180,6 +198,11 @@ namespace Aurora::Memory return true; } + void ByteBuffer::ResetReadPointer() + { + readPtr = base; + } + AuUInt ByteBuffer::GetReadOffset() const { if (flagCircular) diff --git a/Include/Aurora/Memory/ByteBuffer_ReadWrite.inl b/Include/Aurora/Memory/ByteBuffer_ReadWrite.inl index 5a822b76..6c08df51 100644 --- a/Include/Aurora/Memory/ByteBuffer_ReadWrite.inl +++ b/Include/Aurora/Memory/ByteBuffer_ReadWrite.inl @@ -66,19 +66,35 @@ namespace Aurora::Memory else { auto offset = writePtr - base; + + if ((AuUInt)offset > (AuUInt)length) + { + SysPushErrorIO(); + this->flagWriteError = true; + return 0; + } + auto overhead = length - offset; AuUInt len = AuMin(overhead, requestLength); - if ((len != requestLength) && (flagExpandable)) + if ((len != requestLength)) { - if (!Resize(offset + requestLength)) - { - return 0; - } - overhead = length - offset; - len = AuMin(overhead, requestLength); + if ((flagExpandable)) + { + if (!Resize(offset + requestLength)) + { + return 0; + } + + overhead = length - offset; + len = AuMin(overhead, requestLength); + } + else + { + if (len == 0) return 0; + } } if (buffer) @@ -87,11 +103,11 @@ namespace Aurora::Memory } writePtr += len; + SysAssert(writePtr <= base + length); return len; } } - AuUInt ByteBuffer::Read(void *out, AuUInt requestedLength, bool peek) { AuUInt linearOverhead = 0, toWriteOverhead = 0, linearReadable = 0, toWriteReadable = 0; @@ -125,7 +141,10 @@ namespace Aurora::Memory if (toWriteOverhead) { - AuMemcpy(reinterpret_cast(out) + linearOverhead, base, toWriteReadable); + if (out) + { + AuMemcpy(reinterpret_cast(out) + linearOverhead, base, toWriteReadable); + } if (!peek) { @@ -144,6 +163,13 @@ namespace Aurora::Memory } else { + if (readPtr > writePtr) + { + SysPushErrorIO(); + this->flagReadError = true; + return 0; + } + AuUInt len = AuMin(AuUInt(writePtr - readPtr), requestedLength); if (out) @@ -159,5 +185,4 @@ namespace Aurora::Memory return len; } } - } diff --git a/Include/Aurora/Memory/ByteBuffer_Strings.inl b/Include/Aurora/Memory/ByteBuffer_Strings.inl new file mode 100644 index 00000000..219d278f --- /dev/null +++ b/Include/Aurora/Memory/ByteBuffer_Strings.inl @@ -0,0 +1,137 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ByteBuffer_Strings.inl + Date: 2022-2-15 + Author: Reece +***/ +#pragma once + +namespace Aurora::Memory +{ + bool ByteBuffer::WriteString(const AuString &string, EStringType type, Locale::ECodePage codepage) + { + ByteBufferPushWriteState a(*this); + AuStreamReadWrittenPair_t len {}; + Memory::ByteBuffer temp; + + if (codepage != Locale::ECodePage::eUTF8) + { + len = Aurora::Locale::Encoding::EncodeUTF8(string, {}, codepage); + if (len == AuStreamReadWrittenPair_t {0, 0}) + { + return false; + } + + temp = Memory::ByteBuffer(len.second); + len = Aurora::Locale::Encoding::EncodeUTF8(string, Memory::MemoryViewStreamWrite(temp.begin(), temp.end()), codepage); + if (len == AuStreamReadWrittenPair_t {0, 0}) + { + return false; + } + } + else + { + len = AuStreamReadWrittenPair_t {AuUInt32(string.size()), AuUInt32(string.size())}; + } + + switch (type) + { + case EStringType::eStringByte: + { + if (len.second > 255) + { + return {}; + } + + if (!Write(static_cast(len.second))) + { + return {}; + } + break; + } + case EStringType::eStringWord: + { + if (len.second > std::numeric_limits::max()) + { + return {}; + } + + if (!Write(static_cast(len.second))) + { + return {}; + } + break; + } + case EStringType::eStringDword: + { + if (len.second > std::numeric_limits::max()) + { + return {}; + } + + if (!Write(static_cast(len.second))) + { + return {}; + } + break; + } + case EStringType::eStringQword: + { + if (!Write(static_cast(len.second))) + { + return {}; + } + break; + } + } + + if (codepage != Locale::ECodePage::eUTF8) + { + if (!Write(temp.base, temp.length)) + { + return {}; + } + } + else + { + if (!Write(string.data(), string.size())) + { + return {}; + } + } + + if (type == EStringType::eStringTerminated) + { + if (codepage == Locale::ECodePage::eUTF16 || codepage == Locale::ECodePage::eUTF16BE) + { + if (!Write(0)) + { + return {}; + } + } + else if (codepage == Locale::ECodePage::eUTF32 || codepage == Locale::ECodePage::eUTF32BE) + { + if (!Write(0)) + { + return {}; + } + } + else + { + if (!Write(0)) + { + return {}; + } + } + } + + return true; + } + + bool ByteBuffer::ReadString(AuString &string, EStringType type, Locale::ECodePage codepage) + { + // TODO: ... + return {}; + } +} \ No newline at end of file diff --git a/Include/Aurora/Memory/ByteBuffer_Utility.inl b/Include/Aurora/Memory/ByteBuffer_Utility.inl new file mode 100644 index 00000000..7670c26e --- /dev/null +++ b/Include/Aurora/Memory/ByteBuffer_Utility.inl @@ -0,0 +1,79 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ByteBuffer_Utility.inl + Date: 2022-2-15 + Author: Reece +***/ +#pragma once + +namespace Aurora::Memory +{ + bool ByteBuffer::Trim(AuUInt tail) + { + if (this->length > tail) + { + return false; + } + + return Resize(this->length - tail); + } + + bool ByteBuffer::Fill(AuUInt length, AuUInt8 magicCharacter) + { + ByteBufferPushWriteState a(*this); + + auto maxLinear = this->writePtr - AuMin(this->readPtr, this->base + this->length); + maxLinear = AuMin(AuUInt(maxLinear), length); + + if (maxLinear) + { + AuMemset(this->writePtr, magicCharacter, maxLinear); + this->writePtr += maxLinear; + } + + if (maxLinear != length) + { + auto delta = length - maxLinear; + + // HACK: + Memory::ByteBuffer inner(delta); + if (!inner) + { + return {}; + } + + AuMemset(inner.base, magicCharacter, inner.length); + + if (!Write(inner.base, inner.length)) + { + return {}; + } + } + + return true; + } + + bool ByteBuffer::Pad(AuUInt16 aPowOf2, AuUInt8 magicCharacter) + { + ByteBufferPushWriteState a(*this); + + auto oldLen = this->length; + auto newLen = ((this->length + aPowOf2) & ~(aPowOf2 - 1)); + + if (!Resize(newLen)) + { + return {}; + } + + auto old = this->writePtr - this->base; + this->writePtr = this->base + oldLen; + if (!this->Fill(newLen - oldLen)) + { + return {}; + } + + this->writePtr = this->base + old; + return true; + } +} \ No newline at end of file diff --git a/Include/Aurora/Memory/ByteBuffer_Utils.inl b/Include/Aurora/Memory/ByteBuffer_Utils.inl index f6e11b9e..e6a5b33e 100644 --- a/Include/Aurora/Memory/ByteBuffer_Utils.inl +++ b/Include/Aurora/Memory/ByteBuffer_Utils.inl @@ -41,6 +41,7 @@ namespace Aurora::Memory AuUInt8 &ByteBuffer::operator [](AuUInt idx) const { + SysAssert(idx < length); return *(data() + idx); } @@ -119,7 +120,6 @@ namespace Aurora::Memory return !IsEmpty() && !HasStreamError(); } - bool ByteBuffer::IsEmpty() const { return !length || !base; diff --git a/Include/Aurora/Memory/ByteBuffer_WriteFrom.inl b/Include/Aurora/Memory/ByteBuffer_WriteFrom.inl new file mode 100644 index 00000000..b25cce73 --- /dev/null +++ b/Include/Aurora/Memory/ByteBuffer_WriteFrom.inl @@ -0,0 +1,16 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ByteBuffer_WriteFrom.inl + Date: 2022-2-15 + Author: Reece +***/ +#pragma once + +namespace Aurora::Memory +{ + bool ByteBuffer::WriteFrom(ByteBuffer &buffer, AuUInt length) + { + return {}; + } +} \ No newline at end of file diff --git a/Include/Aurora/Memory/ExtendStlLikeSharedPtr.hpp b/Include/Aurora/Memory/ExtendStlLikeSharedPtr.hpp index c374a6b5..05a54bb2 100644 --- a/Include/Aurora/Memory/ExtendStlLikeSharedPtr.hpp +++ b/Include/Aurora/Memory/ExtendStlLikeSharedPtr.hpp @@ -35,25 +35,29 @@ namespace Aurora::Memory return *this; } - TType_t &operator*() const + template + TType2_t &operator*() const { throwif(); return Base_t::operator*(); } - TType_t *operator->() const + template + TType2_t *operator->() const { throwif(); return Base_t::operator->(); } - TType_t &operator*() + template + TType2_t &operator*() { throwif(); return Base_t::operator*(); } - TType_t *operator->() + template + TType2_t *operator->() { throwif(); return Base_t::operator->(); diff --git a/Include/Aurora/Memory/Memory.hpp b/Include/Aurora/Memory/Memory.hpp index 9b09eb14..22fa9668 100644 --- a/Include/Aurora/Memory/Memory.hpp +++ b/Include/Aurora/Memory/Memory.hpp @@ -83,7 +83,7 @@ namespace Aurora::Memory { } - [[nodiscard]] T *allocate(std::size_t n) + [[nodiscard]] T *allocate(Types::size_t n) { if (auto p = (NewArray(n))) { @@ -93,7 +93,7 @@ namespace Aurora::Memory throw std::bad_alloc(); } - void deallocate(T *p, std::size_t n) noexcept + void deallocate(T *p, Types::size_t n) noexcept { _Free(p); } @@ -145,4 +145,6 @@ namespace Aurora::Memory #endif } -#include "ByteBuffer.hpp" \ No newline at end of file +#include "ByteBuffer.hpp" +#include "ByteBufferPushReadState.hpp" +#include "ByteBufferPushWriteState.hpp" \ No newline at end of file diff --git a/Include/Aurora/Memory/MemoryView.hpp b/Include/Aurora/Memory/MemoryView.hpp index 69608c6d..f6da8e50 100644 --- a/Include/Aurora/Memory/MemoryView.hpp +++ b/Include/Aurora/Memory/MemoryView.hpp @@ -18,11 +18,10 @@ namespace Aurora::Memory using StdArray_t = AuConditional_t, AuArray>; /* - YadaYada(MemoryView(tempstring/array/etc)) should be legal, right? + MethodName(MemoryView(tempstring/array/etc)) should be legal, right? - --------------------- Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created. - --------------------- + A full-expression is: [...] * an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression. @@ -103,9 +102,9 @@ namespace Aurora::Memory } template - T *Begin() const + AuConditional_t Begin() const { - return reinterpret_cast(ptr); + return reinterpret_cast>(ptr); } template @@ -119,6 +118,11 @@ namespace Aurora::Memory return ptr && length; } + operator bool() const + { + return HasMemory(); + } + Void_t /*const*/ ptr; AuUInt /*const*/ length; }; @@ -162,12 +166,22 @@ namespace Aurora::Memory { outVariable = 0; } - + template constexpr MemoryViewStream(T *start, T *end) : MemoryView(start, end), outVariable(unused) { outVariable = 0; } + + constexpr MemoryViewStream(MemoryView in) : MemoryView(in.ptr, in.length), outVariable(unused) + { + outVariable = 0; + } + + constexpr MemoryViewStream(MemoryView in, AuUInt &len) : MemoryView(in.ptr, in.length), outVariable(len) + { + outVariable = 0; + } template constexpr MemoryViewStream(T(&a)[Z]) : MemoryView(a), outVariable(unused) @@ -175,6 +189,16 @@ namespace Aurora::Memory outVariable = 0; } + bool HasMemory() const + { + return this->ptr && this->length; + } + + operator bool() const + { + return HasMemory(); + } + AuUInt &outVariable; private: AuUInt unused; diff --git a/Include/Aurora/Memory/_ByteBuffer.hpp b/Include/Aurora/Memory/_ByteBuffer.hpp index 356eb3de..80ca5e47 100644 --- a/Include/Aurora/Memory/_ByteBuffer.hpp +++ b/Include/Aurora/Memory/_ByteBuffer.hpp @@ -4,4 +4,7 @@ #include "ByteBuffer_ReadWrite.inl" #include "ByteBuffer_Memory.inl" #include "ByteBuffer_Utils.inl" -#include "ByteBuffer_Position.inl" \ No newline at end of file +#include "ByteBuffer_Position.inl" +#include "ByteBuffer_Utility.inl" +#include "ByteBuffer_Strings.inl" +#include "ByteBuffer_WriteFrom.inl" \ No newline at end of file diff --git a/Include/Aurora/Parse/Base64.hpp b/Include/Aurora/Parse/Base64.hpp index e7962ae6..2df73a81 100644 --- a/Include/Aurora/Parse/Base64.hpp +++ b/Include/Aurora/Parse/Base64.hpp @@ -11,13 +11,21 @@ namespace Aurora::Parse { AUKN_SYM bool Base64Decode(const AuString &in, Memory::ByteBuffer &decoded, bool url = false); - AUKN_SYM bool Base64Encode(const void *buffer, AuMach length, AuString &encoded, bool url = false); + AUKN_SYM bool Base64Encode(const Memory::MemoryViewRead &input, AuString &encoded, bool url = false); + static bool Base64Encode(const AuString &in, AuString &encoded, bool url = false) { - return Base64Encode(in.data(), in.size(), encoded, url); + return Base64Encode(Memory::MemoryViewRead {in}, encoded, url); } + static bool Base64Encode(const Memory::ByteBuffer &in, AuString &encoded, bool url = false) { - return Base64Encode(in.data(), in.size(), encoded, url); + return Base64Encode(Memory::MemoryViewRead {in}, encoded, url); + } + + template + static bool Base64Encode(T begin, Z end, AuString &encoded, bool url = false) + { + return Base64Encode(Memory::MemoryViewRead {begin, end}, encoded, url); } } \ No newline at end of file diff --git a/Include/Aurora/Parse/Hex.hpp b/Include/Aurora/Parse/Hex.hpp index 489648c5..e5df3244 100644 --- a/Include/Aurora/Parse/Hex.hpp +++ b/Include/Aurora/Parse/Hex.hpp @@ -9,14 +9,14 @@ namespace Aurora::Parse { - enum class EHexDump - { + AUE_DEFINE(EHexDump, + ( eString, eZeroXSpace, eHexEditor, eCLiteral, eJSLiteral - }; + )); AUKN_SYM void ByteToHex(AuUInt8 val, char(&hex)[2]); AUKN_SYM bool HexToInt (const char *hex, AuUInt32 length, AuUInt64 &val); diff --git a/Include/Aurora/Parse/Parser.hpp b/Include/Aurora/Parse/Parser.hpp index 9cadced0..e9c76319 100644 --- a/Include/Aurora/Parse/Parser.hpp +++ b/Include/Aurora/Parse/Parser.hpp @@ -8,6 +8,10 @@ #pragma once #include +#include +#include +#include +#include namespace Aurora::Parse { @@ -112,6 +116,7 @@ namespace Aurora::Parse ParsedObject result; }; +#if 0 using ConsumeStream_cb = AuFunction; static ConsumeStream_cb StringToConsumable(const AuString &str, AuMach &index) @@ -128,17 +133,15 @@ namespace Aurora::Parse }; return getc; } +#endif struct ParseState { - ParseState(ConsumeStream_cb &str) : stringstream(str) + ParseState(const AuSPtr &stream) : stream(stream) {} - ParseState(ConsumeStream_cb &&str) : stringstream(AuMove(str)) - {} - - ConsumeStream_cb stringstream; + AuSPtr stream; AuUInt8 *additionalTokens {}; AuUInt16 countOfTokens {}; @@ -149,31 +152,41 @@ namespace Aurora::Parse }; AUKN_SYM void VaildateStructure(const ParseObject &object); - AUKN_SYM bool ConsumeToken(ParsableTag type, ConsumeStream_cb getc, ParseValue &out); + AUKN_SYM bool ConsumeToken(ParsableTag type, const AuSPtr &getc, ParseValue &out); static bool ConsumeToken(ParsableTag type, const AuString &str, AuMach &index, ParseValueEx &out) { - return ConsumeToken(type, StringToConsumable(str, index), out); + auto strStream = IO::Character::ProviderFromStringUnique(str, index); + if (!strStream) return false; + if (!ConsumeToken(type, AuUnsafeRaiiToShared(strStream), out)) return false; + index = strStream->GetPosition(); + return true; } static bool ConsumeToken(ParsableTag type, const AuString &str, ParseValueEx &out) { - AuMach index{}; - return ConsumeToken(type, StringToConsumable(str, index), out); + auto strStream = IO::Character::ProviderFromStringUnique(str); + if (!strStream) return false; + return ConsumeToken(type, AuUnsafeRaiiToShared(strStream), out); } AUKN_SYM bool Parse(ParseState &state, const ParseObject &structure, ParseResult &result); static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str, AuMach &index) { - ParseState state(StringToConsumable(str, index)); - return Parse(state, structure, result); + auto strStream = IO::Character::ProviderFromStringUnique(str, index); + if (!strStream) return false; + ParseState state(AuUnsafeRaiiToShared(strStream)); + if (!Parse(state, structure, result)) return false; + index = strStream->GetPosition(); + return true; } static bool Parse(ParseResult &result, const ParseObject &structure, const AuString &str) { - AuMach index{}; - ParseState state(StringToConsumable(str, index)); + auto strStream = IO::Character::ProviderFromStringUnique(str, 0); + if (!strStream) return false; + ParseState state(AuUnsafeRaiiToShared(strStream)); return Parse(state, structure, result); } diff --git a/Include/Aurora/Process/Paths.hpp b/Include/Aurora/Process/Paths.hpp index f3d54cab..2709ff2d 100644 --- a/Include/Aurora/Process/Paths.hpp +++ b/Include/Aurora/Process/Paths.hpp @@ -15,6 +15,6 @@ namespace Aurora::Process AUKN_SYM bool GetWorkingDirectory(AuString &path); AUKN_SYM bool GetProcName(AuString &executable); - AUKN_SYM bool GetProcPath(AuString &path); + AUKN_SYM bool GetProcDirectory(AuString &path); AUKN_SYM bool GetProcFullPath(AuString &path); } \ No newline at end of file diff --git a/Include/Aurora/Process/Process.hpp b/Include/Aurora/Process/Process.hpp index 4145ebba..3881f5b4 100644 --- a/Include/Aurora/Process/Process.hpp +++ b/Include/Aurora/Process/Process.hpp @@ -12,17 +12,29 @@ namespace Aurora::Process { + /** + * @brief Aborts the current process with the provided exitcode + * @param exitcode + * @return + */ AUKN_SYM AU_NORETURN void Exit(AuUInt32 exitcode); AUE_DEFINE(EModulePath, ( eModulePathCWD, - eModulePathSystemDir, /// /lib/, windir/system32 - eModulePathUserDir, /// /usr/lib/ + eModulePathSystemDir, /// /usr/lib/, windir/system32 + eModulePathUserDir, /// /usr/local/lib eProcessDirectory, /// //eOSSpecified, /// LD_LIBRARY_PATH + /etc/ld.so.conf, AddDllDirectory eSpecified )); + + + // eModulePathSystemDir -> why /usr/lib and not /lib? + // https://www.freedesktop.org/wiki/Software/systemd/TheCaseForTheUsrMerge/ + // Arch 2012: https://archlinux.org/news/the-lib-directory-becomes-a-symlink/ + // Ubuntu 2018 (mandatory 2021+): https://lists.ubuntu.com/archives/ubuntu-devel-announce/2018-November/001253.html https://wiki.debian.org/UsrMerge + // Fedora (2011?): https://fedoraproject.org/wiki/Features/UsrMove static AuList kUserOverloadableSearchPath = {EModulePath::eSpecified, EModulePath::eModulePathCWD, EModulePath::eProcessDirectory, EModulePath::eModulePathUserDir, EModulePath::eModulePathSystemDir}; static AuList kAdminOverloadableSearchPath = {EModulePath::eSpecified, EModulePath::eModulePathSystemDir, EModulePath::eProcessDirectory, EModulePath::eModulePathCWD, EModulePath::eModulePathUserDir}; @@ -53,6 +65,15 @@ namespace Aurora::Process bool enableMitigations {true}; }; + /** + * @brief Loads a dynamic link module into cache, by the name of 'mod', somewhere in the directories specified by 'searchPath'. + * You should not provide a suffix, platform extension, or the full aurora dll string. Path resolution will take care of + * resolving the Aurora ABI, falling back to mod.platformext. + * @param request + * @return + */ AUKN_SYM bool LoadModule(const ModuleLoadRequest &request); + + AUKN_SYM AuMach GetProcAddress(AuString mod, AuString symbol); } \ No newline at end of file diff --git a/Include/Aurora/Process/ProcessMap.hpp b/Include/Aurora/Process/ProcessMap.hpp index a8d591eb..2507b614 100644 --- a/Include/Aurora/Process/ProcessMap.hpp +++ b/Include/Aurora/Process/ProcessMap.hpp @@ -26,8 +26,12 @@ namespace Aurora::Process bool readable; bool acSanity; }; + + static const auto kSectionNameStack = "STACK"; + static const auto kSectionNameFile = "FILE"; + static const auto kSectionNameHeap = "HEAP"; - struct Segment + struct Section { AuUInt baseVa; AuUInt origVa; @@ -38,16 +42,36 @@ namespace Aurora::Process AuWPtr moduleMeta; }; - using Segments = AuList; + using Sections = AuList
; struct PublicModule { - AuList segments; + Sections sections; AuSPtr moduleMeta; }; + + /** + * @brief Given a pointer to anything whatsoever looks up a section struct worth of page map data + * @param pointer + * @return + */ + AUKN_SYM AuOptional
GetSection(AuUInt pointer); - AUKN_SYM AuOptional GetSegment(AuUInt pointer); + /** + * @brief Returns the executable module (like GetModuleHandle(NULL) on Windows) + * @return + */ AUKN_SYM PublicModule DumpExecutableRoot(); - AUKN_SYM Segments DumpExecutableAll(); + + /** + * @brief Dumps all known sections belonging to points of interest and modules + * @return + */ + AUKN_SYM Sections DumpExecutableAll(); + + /** + * @brief Rescans for loaded dynamic libraries, recalculates lookup tables + * @return + */ AUKN_SYM void TryRescanSlow(); } \ No newline at end of file diff --git a/Include/Aurora/Processes/ESpawnType.hpp b/Include/Aurora/Processes/ESpawnType.hpp index fe768300..549df582 100644 --- a/Include/Aurora/Processes/ESpawnType.hpp +++ b/Include/Aurora/Processes/ESpawnType.hpp @@ -11,11 +11,13 @@ namespace Aurora::Processes { AUE_DEFINE(ESpawnType, ( - // posix: exec, win32: i dunno - eSpawnAtomicOvermap, - // posix: thread, win32: job process + // Launching this process will effectively replace ourselves + eSpawnOvermap, + + // Child process workers are attached to our process. When we die, they die. eSpawnChildProcessWorker, - // posix: thread leader / new sid / pid != 0 daemon, win32: process + + // Thread group leaders are daemons -> they are free from us. eSpawnThreadLeader )); } \ No newline at end of file diff --git a/Include/Aurora/Processes/EStandardHandle.hpp b/Include/Aurora/Processes/EStandardHandle.hpp index deee0d4d..1104a0dd 100644 --- a/Include/Aurora/Processes/EStandardHandle.hpp +++ b/Include/Aurora/Processes/EStandardHandle.hpp @@ -1,11 +1,23 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: EStandardHandle.hpp + Date: 2022-1-29 + Author: Reece +***/ #pragma once namespace Aurora::Processes { AUE_DEFINE(EStandardHandle, ( + // Process Input Stream eStdIn, + + // Process Output Stream eStdOut, + + // Process Error Stream eStdError )); } \ No newline at end of file diff --git a/Include/Aurora/Processes/ICommandFinished.hpp b/Include/Aurora/Processes/ICommandFinished.hpp new file mode 100644 index 00000000..bfcecb66 --- /dev/null +++ b/Include/Aurora/Processes/ICommandFinished.hpp @@ -0,0 +1,9 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ICommandFinished.hpp + Date: 2022-1-27 + Author: Reece +***/ +#pragma once + diff --git a/Include/Aurora/Processes/IProcess.hpp b/Include/Aurora/Processes/IProcess.hpp index f89e87be..b9ec8868 100644 --- a/Include/Aurora/Processes/IProcess.hpp +++ b/Include/Aurora/Processes/IProcess.hpp @@ -14,27 +14,67 @@ namespace Aurora::Threading namespace Aurora::Processes { - class IProcess + struct IProcess { - public: - /// - /// @return the waitable of a waitable child process or thread leader + /** + * @brief High performance thread primitive to synchronize against the process + * @deprecated - but not really. You should rethink your code design if you're + * using this over the loop source. Won't remove. Has legitmate + * use cases. You could use this lock state as 'has terminated' + * @return + */ virtual AuSPtr AsWaitable() = 0; - /// Assuming AsWaitable()->TryLock() && Spawn != SpawnType::kSpawnAtomicOvermap, - /// returns the true return value of the process - /// otherwise returns zero + /** + * @brief returns the exit code of the process should we outlive them + * @return + */ virtual AuSInt GetExitCode() = 0; + /** + * @brief returns *something* about the process. you should not use this + * @return + */ virtual AuUInt GetProcessId() = 0; + /** + * @brief Creates the process, for the first and only time, given the input + * StartupParmaters provided to the relevant Spawn function + * @return + */ virtual bool Start() = 0; + /** + * @brief Forcefully terminates the process + * @return + */ virtual bool Terminate() = 0; + + /** + * WARNING: this function **MAY** block for quite some time. + * @brief Sends SIGTERM, Close all Windows under watchdog, and/or conhost + terminate key sequence to the process + * @return whether or not the thread is still alive at the end of the kill + * attempt. + */ virtual bool TryKill() = 0; - virtual bool Read(bool error, void *buffer, AuUInt32 &len) = 0; - virtual bool Read(void *buffer, AuUInt32 &len, bool errorStream = false, bool nonblock = true) = 0; - virtual bool Write(const void *buffer, AuUInt32 len) = 0; + /** + * @brief Reads asynchronously (^ if nonblock is true) or synchronously reads destination length of bytes from the stream + * If the destination pointer is null, the AuMemoryStreamWrite output variable with be assigned to the available bytes for possible sync or async read + * @param stream Specifies the standard C stream for stdin/out UNIX style IPC + * @param destination Memory span of output bytes, should the intention be to _read_ from the stream specified by the stream EStandardHandle. + * If input byte range is null, out is the available bytes in the IPC buffer + * @param nonblock + * @return + */ + virtual bool Read(EStandardHandle stream, const Memory::MemoryViewStreamWrite &destination, bool nonblock = true) = 0; + + /** + * @brief Synchronously writes `source` bytes to the processes stdin stream + * @param source + * @return + */ + virtual bool Write(const Memory::MemoryViewStreamRead &source) = 0; }; } \ No newline at end of file diff --git a/Include/Aurora/Processes/Open.hpp b/Include/Aurora/Processes/Open.hpp index 69d38dbb..df01934f 100644 --- a/Include/Aurora/Processes/Open.hpp +++ b/Include/Aurora/Processes/Open.hpp @@ -9,9 +9,18 @@ namespace Aurora::Processes { - /// opens a standard uri formatted string (eg, protocol://endpoint/path) + /** + * @brief Opens a standard uri formatted string (eg, protocol://endpoint/path) + * @param uri + * @return + */ AUKN_SYM void OpenUri(const AuString &uri); - /// opens a file given a relative path or abs path + + /** + * @brief Opens a file or directory + * @param file unexpanded relative or absolute filepath + * @return + */ AUKN_SYM void OpenFile(const AuString &file); } \ No newline at end of file diff --git a/Include/Aurora/Processes/StartupParmaters.hpp b/Include/Aurora/Processes/StartupParmaters.hpp index 416b2a58..e97e6fae 100644 --- a/Include/Aurora/Processes/StartupParmaters.hpp +++ b/Include/Aurora/Processes/StartupParmaters.hpp @@ -1,15 +1,51 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: StartupParmaters.hpp + Date: 2022-1-29 + Author: Reece +***/ #pragma once namespace Aurora::Processes { struct StartupParmaters { + /** + * @brief Relative or absolute path to the executable binary + */ AuString process; + + /** + * @brief Raw arguments (argv[1]...) + */ AuList args; + + /** + * @brief Child possession type + */ enum ESpawnType type; + + /** + * @brief Enables stdout ipc to parent + */ bool fwdOut {}; + + /** + * @brief Enables stderr ipc to parent + */ bool fwdErr {}; + + /** + * @brief Enables stdin ipc from parent (us) to child + */ bool fwdIn {}; - bool noShowConsole {}; // Hides conhost or otherwise blanks stdin/out handles + + /** + * @brief Effectively is user facing. + * Under Windows GUI, this means hides conhost. + * Under ConsoleApps, this means blank the childs output handles. + */ + bool noShowConsole {}; }; } \ No newline at end of file diff --git a/Include/Aurora/Processes/UtilRun.hpp b/Include/Aurora/Processes/UtilRun.hpp index 4bad5013..741eb4a4 100644 --- a/Include/Aurora/Processes/UtilRun.hpp +++ b/Include/Aurora/Processes/UtilRun.hpp @@ -2,7 +2,7 @@ Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: UtilRun.hpp - Date: + Date: 2022-1-27 Author: Reece ***/ #pragma once @@ -10,16 +10,24 @@ namespace Aurora::Processes { AUKN_INTERFACE(ICommandFinished, - AUI_METHOD(void, OnLines, (const AuList &, buffer)), - AUI_METHOD(void, OnBuffered, (const Memory::ByteBuffer &, buffer)), AUI_METHOD(void, OnExit, (AuUInt32, exitCode)) ); + AUKN_INTERFACE(IStdOutConsumer, + AUI_METHOD(void, OnLines, (const AuList &, buffer)), + AUI_METHOD(void, OnBuffered, (const Memory::ByteBuffer &, buffer)) + ); + + AUKN_INTERFACE(IStdInProvider, + AUI_METHOD(bool, OnLines, (AuList &, buffer)), + AUI_METHOD(bool, OnBuffered, (Memory::ByteBuffer &, buffer)) + ); + struct CommandRun_s { AuString cmd; AuList args; - Memory::ByteBuffer stdIn; + Memory::ByteBuffer startStdIn; bool stdOutLongerThan64k {false}; // common constraint on linux and windows, at the very least. linux -> max pipe = 16k, windows -> 16k minimum guaranteed bool stdOutIsText {true}; bool runCallbackOnRandomThread {true}; @@ -27,6 +35,9 @@ namespace Aurora::Processes Async::WorkerPId_t worker; bool syncToResult {}; // default -> async AuSPtr callback; + AuSPtr stdInPoller; + AuSPtr stdOutPoller; + AuSPtr bufferAllStdout; }; AUKN_SYM void RunCommand(const CommandRun_s &in); diff --git a/Include/Aurora/RNG/ERngStringCharacters.hpp b/Include/Aurora/RNG/ERngStringCharacters.hpp index 16c84abd..2674a980 100644 --- a/Include/Aurora/RNG/ERngStringCharacters.hpp +++ b/Include/Aurora/RNG/ERngStringCharacters.hpp @@ -9,14 +9,13 @@ namespace Aurora::RNG { - enum class ERngStringCharacters - { + AUE_DEFINE(ERngStringCharacters, + ( eAlphaCharacters, eLowerCharacters, eUpperCharacters, eNumericCharacters, eAlphaNumericCharacters, - eExtendedEntropy, - eCount - }; + eExtendedEntropy + )); } \ No newline at end of file diff --git a/Include/Aurora/RNG/IRandomDevice.hpp b/Include/Aurora/RNG/IRandomDevice.hpp index 3d9a6e65..f09a91c0 100644 --- a/Include/Aurora/RNG/IRandomDevice.hpp +++ b/Include/Aurora/RNG/IRandomDevice.hpp @@ -59,31 +59,6 @@ namespace Aurora::RNG return NextArray(items.data(), items.size()); } }; - - struct RandomDef - { - bool secure; - AuOptional seed; - AuOptional seed64; - - inline void SetSeed(AuUInt32 seed) - { - this->seed = seed; - this->secure = false; - } - - inline void SetSeed64(AuUInt64 seed) - { - this->seed64 = seed; - this->secure = false; - } - - inline void SetCSRNG() - { - this->secure = true; - this->seed.reset(); - } - }; AUKN_SHARED_API(Random, IRandomDevice, const RandomDef &def); } \ No newline at end of file diff --git a/Include/Aurora/RNG/RNG.hpp b/Include/Aurora/RNG/RNG.hpp index 4dc9a275..ac8e8e50 100644 --- a/Include/Aurora/RNG/RNG.hpp +++ b/Include/Aurora/RNG/RNG.hpp @@ -8,6 +8,7 @@ #pragma once #include "ERngStringCharacters.hpp" +#include "RandomDef.hpp" #include "IRandomDevice.hpp" namespace Aurora::RNG diff --git a/Include/Aurora/RNG/RandomDef.hpp b/Include/Aurora/RNG/RandomDef.hpp new file mode 100644 index 00000000..0008b592 --- /dev/null +++ b/Include/Aurora/RNG/RandomDef.hpp @@ -0,0 +1,53 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: RandomDef.hpp + Date: 2022-2-6 + Author: Reece +***/ +#pragma once + +namespace Aurora::RNG +{ + struct RandomDef + { + bool secure; + AuOptional seed; + AuOptional seed64; + AuOptional> seedMassive; + + inline auline void SetSeed(AuUInt32 seed) + { + Reset(); + this->seed = seed; + this->secure = false; + } + + inline auline void SetSeed64(AuUInt64 seed) + { + Reset(); + this->seed64 = seed; + this->secure = false; + } + + inline auline void SetMassiveSeed(const AuArray &seed) + { + Reset(); + this->seedMassive = seed; + this->secure = false; + } + + inline auline void SetCSRNG() + { + this->secure = true; + Reset(); + } + + inline auline void Reset() + { + this->seed.reset(); + this->seed64.reset(); + this->seedMassive.reset(); + } + }; +} \ No newline at end of file diff --git a/Include/Aurora/Registry/IRegistry.hpp b/Include/Aurora/Registry/IRegistry.hpp index ab9d13aa..dd70c890 100644 --- a/Include/Aurora/Registry/IRegistry.hpp +++ b/Include/Aurora/Registry/IRegistry.hpp @@ -12,6 +12,23 @@ namespace Aurora::Registry using RegistryType = Data::EDataType; using RegistryValue = Data::TypedValue; + struct AUKN_SYM IOPath + { + IOPath(); + IOPath(const AuString &path); + + bool isSpecified {}; + + // ERegistrySource::eFS + AuString filePath; + + // [...] + + bool operator ==(const IOPath &other) const; + operator bool() const; + }; + + /** * This registry implementation is a fairly reliable, small scale, preference, and app variable database * Do not consider this as a replacement for a "real" high performance kvp database, it is not, it's a small cache backed document serializer for user profiles @@ -81,7 +98,7 @@ namespace Aurora::Registry eStoreAll }; - virtual bool Read(const AuString &path, EReadType read) = 0; + virtual bool Read(const IOPath &path, EReadType read) = 0; /** * Puts the registry in read only mode @@ -99,34 +116,34 @@ namespace Aurora::Registry /** * Puts the registry in a live write mode */ - virtual void SetWriteModeStream(const AuOptional &path) = 0; + virtual void SetWriteModeStream(const AuOptional &path) = 0; /** * Puts the registry in a write-back-like mode */ - virtual void SetWriteModeBuffered(const AuOptional &path) = 0; + virtual void SetWriteModeBuffered(const AuOptional &path) = 0; virtual void WriteAllCacheBack() = 0; /// eqiv of ForEach((key) => { WriteKey(key, GetKey(key)); }; writes all updated cache entries back to io buffer or stream virtual void SaveBuffered() = 0; /** * Saves the current state of the registry */ - virtual void SaveAll(const AuOptional &path) = 0; + virtual void SaveAll(const AuOptional &path) = 0; /** * Further calls to SetKeys will; update a database on write, if buffered; or write to a buffer and serialize on flush (`SaveBuffered`) */ - virtual void OpenSave(const AuString &path, bool buffered = false) = 0; + virtual void OpenSave(const IOPath &path, bool buffered = false) = 0; /** * equiv Read(path, EReadType::eClearCacheAndStore) */ - virtual void OpenRead(const AuString &path) = 0; + virtual void OpenRead(const IOPath &path) = 0; /** * equiv Read(path, EReadType::eClearCacheAndStore), OpenSave(path, false) */ - virtual void OpenReadWriteback(const AuString &path) = 0; + virtual void OpenReadWriteback(const IOPath &path) = 0; virtual void CloseSave() = 0; diff --git a/Include/Aurora/Runtime.hpp b/Include/Aurora/Runtime.hpp index 74662a21..1b5b7ee6 100644 --- a/Include/Aurora/Runtime.hpp +++ b/Include/Aurora/Runtime.hpp @@ -17,26 +17,7 @@ #endif #endif -#include -#include - -#include -#include -#include - -#include "../AuroraMacros.hpp" - -#include -#include -#include -#include - -#include "../AuroraTypedefs.hpp" - -#define _ALLOW_AURORA_ENUM_AUENVHPP -#include - -#include "../AuroraUtils.hpp" +#include #if defined(_AUHAS_FMT) #include @@ -54,13 +35,16 @@ #if defined(_AURORA_RUNTIME_BUILD_API_INTERFACES) #define AUKN_INTERFACE AUI_INTERFACE_IMPL + #define AUKN_INTERFACE_EXT AUI_INTERFACE_EXT_IMPL #else #define AUKN_INTERFACE AUI_INTERFACE_FWD + #define AUKN_INTERFACE_EXT AUI_INTERFACE_EXT_FWD #endif #include "Memory/Memory.hpp" #include "Console/Console.hpp" +#include "Logging/Logging.hpp" #include "Crypto/Crypto.hpp" #include "Compression/Compression.hpp" #include "Data/Data.hpp" @@ -80,7 +64,9 @@ #include "Processes/Processes.hpp" #include "Loop/Loop.hpp" #include "SWInfo/SWInfo.hpp" - +#include "Exit/Exit.hpp" +#include "CmdLine/CmdLine.hpp" +#include "Utility/RateLimiter.hpp" #include "Memory/_ByteBuffer.hpp" namespace AuAsync = Aurora::Async; @@ -105,7 +91,7 @@ namespace AuProcesses = Aurora::Processes; namespace AuTelemetry = Aurora::Telemetry; namespace AuTime = Aurora::Time; namespace AuTypes = Aurora::Types; -namespace AuLog = Aurora::Console::Logging; +namespace AuLog = Aurora::Logging; namespace AuMemory = Aurora::Memory; using AuWorkerId_t = AuAsync::WorkerId_t; @@ -154,14 +140,7 @@ namespace Aurora bool wantsActiveMonitoring {false}; - bool privacyNoData {false}; - bool privacyNoMod {false}; - bool privacyNoLog {false}; - bool privacyNoWarn {false}; - - bool alwaysCrashdump {true}; - bool alwaysDisableCrashdump {false}; - + bool privacyConsoleLog[255] {}; }; struct TelemetryConfig @@ -193,19 +172,22 @@ namespace Aurora bool forceToolKitWindow {}; /// In conjunction with enableStdPassthrough, Aurora::Console::ReadStd reads a binary stream - /// In conjunction with !enableStdPassthrough, enables stdout logging + /// In conjunction with !enableStdPassthrough, enables stdin cmd processing, otherwise disables stdin input bool enableStdIn {true}; /// In conjunction with enableStdPassthrough, enables Aurora::Console::WriteStd to write binary, otherwise enables the console logger - /// In conjunction with !enableStdPassthrough, enables stdin cmd processing, otherwise disables stdin input + /// In conjunction with !enableStdPassthrough, enables stdout logging bool enableStdOut {true}; /// Use WxWidgets when possible bool enableWxWidgets {true}; /// Delegate stdout writes to loops -> recommended for servers - bool asyncWrite {false}; + bool asyncWrite {true}; + /// Should stdout print the full date or a mere HH MM SS prefix? + bool stdOutShortTime {false}; + #if 1 /// FIO config LocalLogInfo fio; @@ -219,12 +201,6 @@ namespace Aurora struct LoggerConfig { - /// - bool enableStdIn {true}; - - /// - bool enableStdOut {true}; - /// FIO config LocalLogInfo fileConfiguration; @@ -253,7 +229,7 @@ namespace Aurora struct AsyncConfig { - bool enableSchedularThread {true}; // turn this off to make your application lighter weight + bool enableSchedularThread {false}; // turn this off to make your application lighter weight, turn this on for higher performance (+expensive) scheduling AuUInt32 threadPoolDefaultStackSize {}; AuUInt32 schedularFrequency {2}; // * 0.5 or 1 MS depending on the platform AuUInt32 sysPumpFrequency {25}; // x amount of schedularFrequencys @@ -274,9 +250,34 @@ namespace Aurora FIOConfig fio; }; + /** + * @brief Initializes Aurora Runtime for the first and only time + * @return + */ AUKN_SYM void RuntimeStart(const RuntimeStartInfo &info); + + /** + * @brief Querys the state of the DLL or Static Library + * @return true after at least one RuntimeStart + */ AUKN_SYM bool RuntimeHasStarted(); + + /** + * @brief You have **one** opportunity to swap the system locality before it locked + * This can be used by platform gems to align the runtime language and decimal dot notation to a given locality + * @return + */ AUKN_SYM void RuntimeOverloadLocality(const AuPair &locality); + + /** + * @brief Cleans up Aurora Runtime regardless of the count of calls to RuntimeShutdown or RuntimeStart + * @return + */ AUKN_SYM void RuntimeShutdown(); + + /** + * @brief Single threaded main pump for GUI applications polling for non-async subsystem callbacks + * @return + */ AUKN_SYM void RuntimeSysPump(); } \ No newline at end of file diff --git a/Include/Aurora/SWInfo/SWInfo.hpp b/Include/Aurora/SWInfo/SWInfo.hpp index 5ba37f84..2f642b49 100644 --- a/Include/Aurora/SWInfo/SWInfo.hpp +++ b/Include/Aurora/SWInfo/SWInfo.hpp @@ -11,14 +11,14 @@ namespace Aurora::SWInfo { struct OSInformation { - // I tried to make these references, but benji the retard decided that objects and functions should hold constantness, not the data - // Returning a const reference to a struct containing const references, keeping the ability to move, and disabling copy -> impossible - // Nice tardlang + // I tried to make these references, but the special c++ andineers decided that objects and functions should hold constantness, not the data + // Returning a const reference to a struct containing const references, maintaining the ability to move, and disabling copy, is impossible + // Nice highiq lang const AuString *kKernelString; // const AuString *kUserlandBrand; // Windows 10 Pro, Xbox, glibc, Ubuntu, distro name const AuString *kUserlandDesktopEnv; // DWM, CF, [kwin/etc] - const AuString *kBuildString; // Example: (`Linux version wtf-doxing-lts (no-lts@fingerprinterinos) (some things here) #1 SMP Mon, 69 Apr 2000 13:33:37 +0000`, `??7??.?.amd64???.rs?_release.??-??`) + const AuString *kBuildString; // Example: (`??7??.?.amd64???.rs?_release.??-??`, `Linux version wtf-doxing-lts (no-lts@fingerprinterinos) (some things here) #1 SMP Mon, 69 Apr 2000 13:33:37 +0000`) AuUInt32 uKernelMajor {}; AuUInt32 uKernelMinor {}; diff --git a/Include/Aurora/Telemetry/BlackBox.hpp b/Include/Aurora/Telemetry/BlackBox.hpp index 86273321..b77d7f68 100644 --- a/Include/Aurora/Telemetry/BlackBox.hpp +++ b/Include/Aurora/Telemetry/BlackBox.hpp @@ -51,7 +51,7 @@ namespace Aurora::Telemetry struct NewBlackboxEntryUpdateMap { - Aurora::Process::Segments map; + Aurora::Process::Sections map; }; enum class ENewBlackBoxAccessViolation diff --git a/Include/Aurora/Threading/Primitives/RWLock.hpp b/Include/Aurora/Threading/Primitives/RWLock.hpp index 09927f0c..e5416e3c 100644 --- a/Include/Aurora/Threading/Primitives/RWLock.hpp +++ b/Include/Aurora/Threading/Primitives/RWLock.hpp @@ -12,28 +12,25 @@ namespace Aurora::Threading::Primitives class RWLock { public: + /** + * @brief Returns a complete IWaitable interface for reantrant access to the protected resources. + * Once a thread takes exclusive access of the resource, only it shall pass read + * @return + */ virtual IWaitable *AsReadable() = 0; + + /** + * @brief Returns a complete IWaitable interface for exclusive thread access to the protected resources + * + * @return + */ virtual IWaitable *AsWritable() = 0; /** - * Solves the problem of atomic write racing - * Consider: Thread 1 | Thread 2 - * ReadLock() | - * cmp internal_x, 0| - * jmp not eq +1 | - * ret | - * ReadUnlock() | - * | WriteLock() - * | internal_x = 1 - * | WriteUnlock() - * WriteLock() | - * internal_x = 0 | - * WriteUnlock() - * - * where 1 and 0 should have been decided on mutually exclusively, losing the 1 state while assuming a decision in the locked state would remain true - * workaround: [1] check for the race conditions, implmeneting slow and inefficient branching and spurious checks - * workaround: [2] upgrade from read to write - */ + * @brief Allows for read-to-write upgrades when the decision to esclate is made based upon a shared resource + * @param timeout + * @return + */ virtual bool UpgradeReadToWrite(AuUInt64 timeout) = 0; }; diff --git a/Include/Aurora/Threading/Threads/IAuroraThread.hpp b/Include/Aurora/Threading/Threads/IAuroraThread.hpp index bc0d7c1a..bd96a5b8 100644 --- a/Include/Aurora/Threading/Threads/IAuroraThread.hpp +++ b/Include/Aurora/Threading/Threads/IAuroraThread.hpp @@ -9,7 +9,7 @@ namespace Aurora::Loop { - class ILoopSource; + struct ILoopSource; } namespace Aurora::Threading::Threads diff --git a/Include/Aurora/Time/DebugBenchmark.hpp b/Include/Aurora/Time/DebugBenchmark.hpp index 4b6506cd..2c6680be 100644 --- a/Include/Aurora/Time/DebugBenchmark.hpp +++ b/Include/Aurora/Time/DebugBenchmark.hpp @@ -27,7 +27,7 @@ namespace Aurora::Time { if (AuExchange(finished_, true)) return; auto time = timer_.End(); - Aurora::Console::Logging::LogDbg("[Benchmark] {} took {}", message_, ConvertNSToTimescale(time)); + Aurora::Logging::LogDbg("[Benchmark] {} took {}", message_, ConvertNSToTimescale(time)); } private: diff --git a/Include/Aurora/Time/TM.hpp b/Include/Aurora/Time/TM.hpp index f7305745..1292b78a 100644 --- a/Include/Aurora/Time/TM.hpp +++ b/Include/Aurora/Time/TM.hpp @@ -1,7 +1,7 @@ /*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. - File: ETimezoneShift.hpp + File: TM.hpp Date: 2022-1-24 Author: Reece ***/ diff --git a/Include/Aurora/Utility/RateLimiter.hpp b/Include/Aurora/Utility/RateLimiter.hpp new file mode 100644 index 00000000..3203040b --- /dev/null +++ b/Include/Aurora/Utility/RateLimiter.hpp @@ -0,0 +1,77 @@ +/*** + Copyright (C) 20212J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: RateLimiter.hpp + Date: 2022-2-8 + Author: Reece +***/ +#pragma once + +namespace Aurora::Utility +{ + struct RateLimiter + { + AuUInt64 nextTriggerTime; + AuUInt64 nsTimeStep; + + inline auline void SetNextStep(AuUInt64 nsTimeStep) + { + this->nsTimeStep = nsTimeStep; + this->nextTriggerTime = nsTimeStep + Aurora::Time::CurrentInternalClockNS(); + } + + inline auline bool CheckExchangePass() + { + auto cur = this->nextTriggerTime; + + if (!cur) + { + return false; + } + + if (cur <= Aurora::Time::CurrentInternalClockNS()) + { + if (this->nsTimeStep) + { + return AuAtomicCompareExchange(&this->nextTriggerTime, GetLatch(), cur) == cur; + } + else + { + return true; + } + } + + return false; + } + + inline auline bool HasPassed() + { + if (!this->nextTriggerTime) + { + return false; + } + + if (this->nextTriggerTime <= Aurora::Time::CurrentInternalClockNS()) + { + return true; + } + + return false; + } + + inline auline void Relatch() + { + if (this->nsTimeStep) + { + AuAtomicAdd(&this->nextTriggerTime, GetLatch()); + } + } + + private: + + inline auline AuUInt64 GetLatch() + { + return this->nextTriggerTime + this->nsTimeStep; + } + }; +}; \ No newline at end of file diff --git a/Include/AuroraMacros.hpp b/Include/AuroraMacros.hpp index b1d77e64..bc70b5d1 100644 --- a/Include/AuroraMacros.hpp +++ b/Include/AuroraMacros.hpp @@ -6,227 +6,6 @@ Author: Reece ***/ #pragma once +// deprecated header -- -#define AU_COPY(type) type(const type&) = default; type &operator=(const type &) = default; -#define AU_MOVE(type) type(type&&) = default; type &operator=(type &&) = default; - -#define AU_COPY_MOVE(type) AU_COPY(type) AU_MOVE(type) - -#define AU_NO_COPY(type) type(const type&) = delete; -#define AU_NO_MOVE(type) type(type&&) = delete; -#define AU_NO_COPY_NO_MOVE(type) AU_NO_COPY(type) AU_NO_MOVE(type) - - -#if !defined(AU_SHARED_FROM_THIS) - #define AU_SHARED_FROM_THIS (AuStaticPointerCast>(this->SharedFromThis())) -#endif - -#if !defined(AU_WEAK_FROM_THIS) - #define AU_WEAK_FROM_THIS (AuWPtr>(AuStaticPointerCast>(this->SharedFromThis()))) -#endif - -#define AU_BRACKET_SCOPE(...) __VA_ARGS__ - -#if !defined(AU_TEMPLATE_ENABLE_WHEN) - #define AU_TEMPLATE_ENABLE_WHEN(...) typename AuEnableIf<__VA_ARGS__>::type* = nullptr -#endif - -#define AU_WHAT(n) n - -/// @hideinitializer -#define AU_STRINGIFY_(in) #in -#define AU_STRINGIFY(in) AU_STRINGIFY_(in) - -/// @hideinitializer -#define AU_CONCAT_(a, b) a ## b -#define AU_CONCAT(a, b) AU_CONCAT_(a, b) - -/// @hideinitializer -#define _AUKCON_STRINGIFY_X(in) AU_STRINGIFY(in) - -#if !defined(AU_SHARED_API_EX) - #define AU_SHARED_API_EX(vis, name, type, ...) \ - \ - vis type *name ## New(__VA_ARGS__); \ - vis void name ## Release(type *); \ - static inline void name ## Destroy(type *val) \ - { \ - name ## Release(val); \ - } \ - \ - struct CppDeleter ## name \ - { \ - void operator()(type *t) \ - { \ - name ## Release(t); \ - } \ - }; \ - \ - using name ## Unique_t = AURORA_RUNTIME_AU_UNIQUE_PTR; \ - template \ - name ## Unique_t name ## Unique(T... args) \ - { \ - return name ## Unique_t(name ## New(args...)); \ - } \ - \ - using name ## Shared_t = std::shared_ptr; \ - template \ - name ## Shared_t name ## Shared(T... args) \ - { \ - return name ## Shared_t(name ## New(args...), name ## Release); \ - } -#endif - -#if !defined(AU_SHARED_API) - #define AU_SHARED_API(name, type, ...) AU_SHARED_API_EX(, name, type, #__VA_ARGS__) -#endif - -#if !defined(AU_NOINLINE) - #if defined(AURORA_COMPILER_MSVC) - #define AU_NOINLINE __declspec(noinline) - #else - #define AU_NOINLINE __attribute__((noinline)) - #endif -#endif - -#if !defined(AU_INLINE) - #if defined(AURORA_COMPILER_MSVC) - #define AU_INLINE __forceinline - #else - #define AU_INLINE __attribute__((always_inline)) - #endif -#endif - -#if !defined(AU_NORETURN) - #if defined(AURORA_COMPILER_MSVC) - #define AU_NORETURN __declspec(noreturn) - #elif (defined(AURORA_COMPILER_CLANG) || defined(AURORA_COMPILER_GCC)) - #define AU_NORETURN __attribute__((noreturn)) - #elif defined(AU_LANG_CPP) - #define AU_NORETURN [[noreturn]] - #else - #define AU_NORETURN - #endif -#endif - -#if !defined(AU_ALLOC) - #if defined(AURORA_PLATFORM_WIN32) - #define AU_ALLOC __declspec(allocator) - #elif defined(AURORA_COMPILER_CLANG) - #define AU_ALLOC __declspec(allocator) - #elif defined(AURORA_COMPILER_GCC) - #define AU_ALLOC __attribute__((malloc)) - #else - #define AU_ALLOC - #endif -#endif - -#if !defined(NO__NEW) - #if !defined(_new) - #define _new new (std::nothrow) - #endif -#endif - -#if !defined(NO__INLINE) - #if !defined(auline) - #define auline AU_INLINE - #endif -#endif - -#if !defined(AU_FWD) - #define AU_FWD(var) std::forward(var) -#endif - -#if !defined(AU_THROW_STRING) - #define AU_THROW_STRING(var) throw std::string(var) -#endif - -#define AU_ITERATE_ARRAY(index, arry) AuUInt index = 0; index < AuArraySize(arry); index++ -#define AU_ITERATE_N(index, n) AuUInt index = 0; index < n; index++ -#define AU_ITERATE_N_TO_X(index, n, x) AuUInt index = n; index < x; index++ -#define AU_ITERATE_BACKWARDS(index, lastIdx) AuUInt index = lastIdx; index <= 0; index-- - -#define AU_ITR_ARRAY AU_ITERATE_ARRAY -#define AU_ITR_N AU_ITERATE_N -#define AU_ITR_N_TO_X AU_ITERATE_N_TO_X -#define AU_ITR_BACKWARDS AU_ITERATE_BACKWARDS - -#define AU_STRIP_BRACKETS_IMPL(...) __VA_ARGS__ - -#if !defined(AU_STRIP_BRACKETS) - #define AU_STRIP_BRACKETS(X) AU_WHAT(AU_STRIP_BRACKETS_IMPL X) -#endif - -#if !defined(AU_STRIP) - #define AU_STRIP AU_STRIP_BRACKETS -#endif - -#if !defined(AU_EMIT_FIRST) - #define AU_EMIT_FIRST(a, b)a -#endif - -#if !defined(AU_EMIT_SECOND) - #define AU_EMIT_SECOND(a, b)b -#endif - -#if !defined(AU_EMIT_BOTH) - #define AU_EMIT_BOTH(a, b)a, a -#endif - -#if !defined(AuBindThis) - #define AuBindThis(method, ...) std::bind(method, this, ## __VA_ARGS__) -#endif - -#if !defined(AuSharedFromThis) - #define AuSharedFromThis() AU_SHARED_FROM_THIS -#endif - -#if !defined(AuWeakFromThis) - #define AuWeakFromThis() AU_SHARED_FROM_THIS -#endif - -#define AU_EMIT_FIRST_COMMA_FIRST(n)n -#define AU_EMIT_FIRST_COMMA_OTHERS(n),n - -/// @hideinitializer -#define AU_EMIT_FIRST_TYPEREDUCED_PAIR_REDUCED(variable) AuRemoveConst_t> - - -/// @hideinitializer -#define AU_EMIT_CTOR_CPY(pair) const AU_EMIT_FIRST_TYPEREDUCED_PAIR_REDUCED(pair) &pair -/// @hideinitializer -#define AU_EMIT_CTOR_CPY_SECOND(pair) ,AU_EMIT_CTOR_CPY(pair) - - -/// @hideinitializer -#define AU_EMIT_CTOR_MOV(pair) AU_EMIT_FIRST_TYPEREDUCED_PAIR_REDUCED(pair) &&pair -/// @hideinitializer -#define AU_EMIT_CTOR_MOV_SECOND(pair) ,AU_EMIT_CTOR_MOV(pair) - - -/// @hideinitializer -#define AU_EMIT_CTOR_ASSIGN(pair) pair(pair) -/// @hideinitializer -#define AU_EMIT_CTOR_ASSIGN_SECOND(pair) ,AU_EMIT_CTOR_ASSIGN(pair) - - -/// @hideinitializer -#define AU_DEFINE_CTOR_CPY_VA(thisType, args) \ -inline thisType(AU_FOR_EACH_FIRST(AU_EMIT_CTOR_CPY, AU_EMIT_CTOR_CPY_SECOND, AU_STRIP_BRACKETS(args))) : AU_FOR_EACH_FIRST(AU_EMIT_CTOR_ASSIGN, AU_EMIT_CTOR_ASSIGN_SECOND, AU_STRIP_BRACKETS(args)) \ -{} - -/// @hideinitializer -#define AU_DEFINE_CTOR_MOV_VA(thisType, args) \ -inline thisType(AU_FOR_EACH_FIRST(AU_EMIT_CTOR_MOV, AU_EMIT_CTOR_MOV_SECOND, AU_STRIP_BRACKETS(args))) : AU_FOR_EACH_FIRST(AU_EMIT_CTOR_ASSIGN, AU_EMIT_CTOR_ASSIGN_SECOND, AU_STRIP_BRACKETS(args)) \ -{} - -/// @hideinitializer -#define AU_DEFINE_CTOR_VA_(thisType, args) AU_DEFINE_CTOR_CPY_VA(thisType, args) AU_DEFINE_CTOR_MOV_VA(thisType, args) - - -/// @deprecated -#define AU_DEFINE_CTOR_ONE(thisType, pairTypeName) AU_DEFINE_CTOR_VA_(thisType, (AU_EMIT_SECOND pairTypeName)) - - -/// -#define AU_DEFINE_CTOR_VA(thisType, args) AU_DEFINE_CTOR_CPY_VA(thisType, args) AU_DEFINE_CTOR_MOV_VA(thisType, args) \ No newline at end of file +#include \ No newline at end of file diff --git a/Include/AuroraTypedefs.hpp b/Include/AuroraTypedefs.hpp index 845cf138..d3d0425c 100644 --- a/Include/AuroraTypedefs.hpp +++ b/Include/AuroraTypedefs.hpp @@ -6,425 +6,6 @@ Author: Reece ***/ #pragma once +// deprecated header -- -#if !defined(AURORA_RUNTINE_TYPEDEFS_INCLUDE) - #include - #include - #include - #include - #include - #include - #include - #include -#else - #if defined(AURORA_RUNTINE_TYPEDEFS_INCLUDE_HEADER) - #include - #endif -#endif - -template -struct AuBoolType -{ - static constexpr bool value = v; - using value_type = bool; - using type = AuBoolType; - - constexpr operator value_type() const noexcept - { - return value; -} - - constexpr value_type operator()() const noexcept - { - return value; - } -}; - -using AuFalseType = AuBoolType; -using AuTrueType = AuBoolType; - -template -struct AuIsSame : AuFalseType -{}; - -template -struct AuIsSame : AuTrueType -{}; - -template -inline constexpr bool AuIsSame_v = AuIsSame::value; - -namespace _audetail { - template - AuBoolType::value> test(int T:: *); - - template - AuFalseType test(...); - - template - AuTrueType test_pre_ptr_convertible(const volatile B *); - template - AuFalseType test_pre_ptr_convertible(const volatile void *); - - template - auto test_pre_is_base_of(...) -> AuTrueType; - - template - auto test_pre_is_base_of(int) -> decltype(test_pre_ptr_convertible(static_cast(nullptr))); -} - -template -struct AuIsClass : decltype(_audetail::test(nullptr)) -{}; - -template -inline constexpr bool AuIsClass_v = AuIsClass::value; - -template -struct AuIsBaseOf : - AuBoolType< - AuIsClass_v && - AuIsClass_v && - decltype(_audetail::test_pre_is_base_of(0))::value - > -{}; - -template -inline constexpr bool AuIsBaseOf_v = AuIsBaseOf::value; - -template -inline constexpr bool AuIsPointer_v = false; - -template -inline constexpr bool AuIsPointer_v = true; - -template -inline constexpr bool AuIsPointer_v = true; - -template -inline constexpr bool AuIsPointer_v = true; - -template -inline constexpr bool AuIsPointer_v = true; - -template -struct AuRemovePointer {typedef T type;}; - -template -struct AuRemovePointer {typedef T type;}; - -template -struct AuRemovePointer {typedef T type;}; - -template -struct AuRemovePointer {typedef T type;}; - -template -struct AuRemovePointer {typedef T type;}; - -template -using AuRemovePointer_t = typename AuRemovePointer::type; - -template -using AuIsVoid = AuIsSame; - -template -inline constexpr bool AuIsVoid_v = AuIsVoid::value; - -template -struct AuRemoveReference -{ - using type = T; -}; - -template -struct AuRemoveReference -{ - using type = T; -}; - -template -struct AuRemoveReference -{ - using type = T; -}; - -template -using AuRemoveReference_t = typename AuRemoveReference::type; - -template -constexpr AuRemoveReference_t &&AuMove(T &&arg) noexcept -{ - return static_cast &&>(arg); -} - -template struct AuRemoveConst -{ - typedef T type; -}; - -template struct AuRemoveConst -{ - typedef T type; -}; - -template -using AuRemoveConst_t = typename AuRemoveConst::type; - -template -struct AuEnableIf -{ -}; - -template -struct AuEnableIf -{ - using type = T; -}; - -template -using AuEnableIf_t = typename AuEnableIf::type; - - -template -struct AuConditional -{ - using type = T; -}; - -template -struct AuConditional -{ - using type = T2; -}; - -template -using AuConditional_t = typename AuConditional::type; - -template -constexpr T &&AuForward(AuRemoveReference_t &arg) noexcept -{ - return static_cast(arg); -} - -template -constexpr T &&AuForward(AuRemoveReference_t &&arg) noexcept -{ - //static_assert(!is_lvalue_reference_v, "bad forward call"); - return static_cast(arg); -} - -#if !defined(AURORA_RUNTIME_AU_LIST) - #define AURORA_RUNTIME_AU_LIST std::vector -#endif - -#if defined(_CPPSHARP) - -template -using AuList = AURORA_RUNTIME_AU_LIST; - -#else - -namespace Aurora::Memory -{ - template - struct SpeedyArrayAllocator; -} - -template -using AuList = AuConditional_t, AURORA_RUNTIME_AU_LIST, AURORA_RUNTIME_AU_LIST>>; - -#endif - -#if !defined(AURORA_RUNTIME_AU_ARRAY) - #define AURORA_RUNTIME_AU_ARRAY std::array -#endif - -template -using AuArray = AURORA_RUNTIME_AU_ARRAY; - - -#if !defined(AURORA_RUNTIME_AU_FUNC) - #define AURORA_RUNTIME_AU_FUNC std::function -#endif - -template -using AuFunction = AURORA_RUNTIME_AU_FUNC; - - -#if !defined(AURORA_RUNTIME_AU_HASH_MAP) -#define AURORA_RUNTIME_AU_HASH_MAP std::unordered_map -#endif - -template -using AuHashMap = AURORA_RUNTIME_AU_HASH_MAP; - -template -using AuHashMapEx = AURORA_RUNTIME_AU_HASH_MAP; - -#if !defined(AURORA_RUNTIME_AU_BST) -#define AURORA_RUNTIME_AU_BST std::map -#endif - -template -using AuBST = AURORA_RUNTIME_AU_BST; - -template -using AuBSTEx = AURORA_RUNTIME_AU_BST; - -#if !defined(AURORA_RUNTIME_AU_SHARED_PTR) -#define AURORA_RUNTIME_AU_SHARED_PTR std::shared_ptr -#endif - -#if !defined(AURORA_RUNTIME_AU_WEAK_PTR) -#define AURORA_RUNTIME_AU_WEAK_PTR std::weak_ptr -#endif - -template -using AuWPtr = AURORA_RUNTIME_AU_WEAK_PTR; - -#if !defined(AURORA_RUNTIME_AU_UNIQUE_PTR) -#define AURORA_RUNTIME_AU_UNIQUE_PTR std::unique_ptr -#endif - - -#if !defined(AURORA_RUNTIME_AU_DEFAULT_DELETER) -#define AURORA_RUNTIME_AU_DEFAULT_DELETER std::default_delete -#endif - - -template -using AuDefaultDeleter = AURORA_RUNTIME_AU_DEFAULT_DELETER; - - -#include - -template -using AuSPtr = typename Aurora::Memory::ExSharedPtr>; - -template -using AuUPtr = AURORA_RUNTIME_AU_UNIQUE_PTR; - -#if !defined(AU_AuEnableSharedFromThis) -#define AU_AuEnableSharedFromThis - -template -struct AuEnableSharedFromThis : Aurora::Memory::ExSharedFromThis> -{}; - -#endif - - -template -AuSPtr AuStaticPointerCast(const AuSPtr &other) noexcept -{ - return AuSPtr(other, static_cast::element_type *>(other.get())); -} - -template -AuSPtr AuStaticPointerCast(AuSPtr &&other) noexcept -{ - return AuSPtr(AuMove(other), static_cast::element_type *>(other.get())); -} - -#if !defined(AURORA_RUNTIME_AU_PAIR) -#define AURORA_RUNTIME_AU_PAIR std::pair -#endif - -template -using AuPair = AURORA_RUNTIME_AU_PAIR; - - -#if !defined(AURORA_RUNTIME_AU_TUPLE) -#define AURORA_RUNTIME_AU_TUPLE std::tuple -#endif - -template -using AuTuple = AURORA_RUNTIME_AU_TUPLE; - -#if defined(AURORA_COMPILER_MSVC) -using AuAtomicInt = long; -#else -using AuAtomicInt = int; -#endif - -#if !defined(AURORA_RUNTIME_AU_OPTIONAL) -#define AURORA_RUNTIME_AU_OPTIONAL std::optional -#endif - -template -using AuOptional = AURORA_RUNTIME_AU_OPTIONAL; - -template -using AuPredicate = AuFunction; - -using AuVoidFunc = AuFunction; - -template -using AuConsumer = AuFunction; - -template -using AuSupplier = AuFunction; - -template -using AuSupplierConsumer = AuFunction; - -//#include "tinyutf8.h" - -using AuString = std::string;// tiny_utf8::utf8_string; - - -using AuUInt64 = Aurora::Types::uint64_t; -using AuUInt32 = Aurora::Types::uint32_t; -using AuUInt16 = Aurora::Types::uint16_t; -using AuUInt8 = Aurora::Types::uint8_t; -using AuInt64 = Aurora::Types::int64_t; -using AuInt32 = Aurora::Types::int32_t; -using AuInt16 = Aurora::Types::int16_t; - -#if defined(_CPPSHARP) -using AuInt8 = Aurora::Types::uint8_t; -#else -using AuInt8 = Aurora::Types::int8_t; -#endif -using AuMach = Aurora::Types::size_t; -using AuSMach = Aurora::Types::ssize_t; -using AuSInt = AuSMach; -using AuUInt = AuMach; - -using AuStreamReadWrittenPair_t = AuPair; - -using AuThreadId_t = AuUInt64; -static const AuThreadId_t kThreadIdSpecialMask = AuThreadId_t(1) << AuThreadId_t(63); - -#if defined(__has_include) && !defined(_AUHAS_GLM) && defined(_AU_DETECT_GLM) - #if __has_include() - #define _AUHAS_GLM - #endif -#endif - -#if !defined(_AUHAS_GLM) - template - struct AuFVec - { - float elements[N]; - - float operator [](int idx) const - { - return elements[N]; - } - - float &operator [](int idx) - { - return elements[N]; - } - }; - - using AuVec3 = AuFVec<3>; - using AuVec4 = AuFVec<4>; -#else - #include - - using AuVec3 = glm::vec3; - using AuVec4 = glm::vec4; -#endif +#include "auROXTLTypes.hpp" \ No newline at end of file diff --git a/Include/AuroraUtils.hpp b/Include/AuroraUtils.hpp index 2a0aff58..b469705c 100644 --- a/Include/AuroraUtils.hpp +++ b/Include/AuroraUtils.hpp @@ -6,1307 +6,6 @@ Author: Reece ***/ #pragma once +// deprecated header -- -#if !defined(AURORA_RUNTIME_MAKE_SHARED) -#define AURORA_RUNTIME_MAKE_SHARED std::make_shared -#endif - -template -static auline AuSPtr AuMakeShared(Args&&... args) -{ - try - { - return AURORA_RUNTIME_MAKE_SHARED(AuForward(args)...); - } - catch (...) - { - return {}; - } -} - -#if !defined(AURORA_RUNTIME_MAKE_PAIR) -#define AURORA_RUNTIME_MAKE_PAIR std::make_pair -#endif - -template -static auline auto AuMakePair(Args&&... args) -{ - return AURORA_RUNTIME_MAKE_PAIR(AuForward(args)...); -} - - -#if !defined(AURORA_RUNTIME_MAKE_TUPLE) -#define AURORA_RUNTIME_MAKE_TUPLE std::make_tuple -#endif - -template -static auline auto AuMakeTuple(Args&&... args) -{ - return AURORA_RUNTIME_MAKE_TUPLE(AuForward(args)...); -} - - -#if !defined(AURORA_RUNTIME_TO_STRING) -#define AURORA_RUNTIME_TO_STRING std::to_string -#endif - -template -AuString AuToString(const T &obj) -{ - return AURORA_RUNTIME_TO_STRING(obj); -} - - -#if !defined(AURORA_RUNTIME_EXCHANGE) -#define AURORA_RUNTIME_EXCHANGE std::exchange -#endif - -template -T AuExchange(T &obj, U &&new_value) -{ - return AURORA_RUNTIME_EXCHANGE(obj, new_value); -} - -#if !defined(AURORA_RUNTIME_MEMCMP) -#define AURORA_RUNTIME_MEMCMP std::memcmp -#endif - -static auline int AuMemcmp(const void *dest, const void *src, size_t n) -{ - return AURORA_RUNTIME_MEMCMP(dest, src, n); -} - -#if !defined(AURORA_RUNTIME_MEMSET) -#define AURORA_RUNTIME_MEMSET std::memset -#endif - -static auline void *AuMemset(void *dest, AuUInt8 c, size_t n) -{ - return AURORA_RUNTIME_MEMSET(dest, c, n); -} - -#if !defined(AURORA_RUNTIME_MEMCPY) -#define AURORA_RUNTIME_MEMCPY std::memcpy -#endif - -static auline void *AuMemcpy(void *dest, const void *src, size_t n) -{ - return AURORA_RUNTIME_MEMCPY(dest, src, n); -} - -#if !defined(AURORA_RUNTIME_MEMMOVE) -#define AURORA_RUNTIME_MEMMOVE std::memmove -#endif - -static auline void *AuMemmove(void *dest, const void *src, size_t n) -{ - return AURORA_RUNTIME_MEMMOVE(dest, src, n); -} - -#if defined(AURORA_IS_MODERNNT_DERIVED) && (defined(_WINDOWS_) || defined(_OTHER_MS_MAIN_HEADER_GUARDS_HERE)) -static auline void AuWin32CloseHandle(HANDLE &handle) -{ - HANDLE local; - - if ((local = AuExchange(handle, INVALID_HANDLE_VALUE)) != INVALID_HANDLE_VALUE) - { - CloseHandle(local); - } -} -#endif - -template -static AuSPtr AuUnsafeRaiiToShared(T *in) -{ - return AuSPtr(in, [](T *){}); -} - -template -static AuSPtr AuUnsafeRaiiToShared(const AuUPtr &in) -{ - return AuSPtr(in.get(), [](T *){}); -} - -template -static constexpr int AuArraySize(const T(&array)[Z]) -{ - return Z; -} - -#if defined(DEBUG) || defined(STAGING) - -template -static auline void __declspec(noreturn) SysPanic(T... args); - -template -static void auline SafeDelete(T *in) -{ - static_assert(std::is_base_of::type>::value, "Couldn't not safe delete from type T because it is not derived from Z"); - auto cast = dynamic_cast(in); - if (cast == nullptr) - { - Z re; - SysPanic("Tried to free: 0x{:x}, type \"{}\" was not inherited from \"{}\"", AuUInt(in), typeid(in).name(), typeid(re).name()); - } - delete cast; -} - -#else - -template -static void auline SafeDelete(T *in) -{ - static_assert(std::is_base_of::type>::value, "Couldn't not safe delete from type T because it is not derived from Z"); - delete static_cast(in); -} - -#endif - -struct IAuNullDelegate -{ - virtual void OnCall() = 0; -}; - -struct AuNullCallback -{ - const AuVoidFunc voidFunc; - const AuSPtr callbackFunc; - - AU_DEFINE_CTOR_ONE(AuNullCallback, (AuVoidFunc, voidFunc)); - AU_DEFINE_CTOR_ONE(AuNullCallback, (AuSPtr, callbackFunc)); - - auline void operator()() - { - if (voidFunc) - { - voidFunc(); - } - else if (callbackFunc) - { - callbackFunc->OnCall(); - } - } -}; - -static constexpr auline AuUInt32 AuConvertMagicTag32(const char buffer[4]) -{ - AuUInt32 magic {}; - if (Aurora::Build::kCurrentEndian == Aurora::Build::ECPUEndian::eCPULittle) - { - magic |= AuUInt32(buffer[0]); - magic |= AuUInt32(buffer[1]) << 8; - magic |= AuUInt32(buffer[2]) << 16; - magic |= AuUInt32(buffer[3]) << 24; - // LE will look alright in memory dumps - // MSFT uses tags that read back the initial string value when read back hex ints - // I prefer binary streams and file headers contain a 4x or 8x ascii char headers (eg. LuaX) - } - else - { - // Lazy reinterpret cast reads will always be flipped - // Assume byte buffers read/write machine endian - // Assume *reinterpret_cast returns machine endian - // BE needs to be flipped in memory - // BE will look fine in memory dumps - // BE will also look fine in stack/variable dumps when printed in hex - magic |= AuUInt32(buffer[4]); - magic |= AuUInt32(buffer[2]) << 8; - magic |= AuUInt32(buffer[1]) << 16; - magic |= AuUInt32(buffer[0]) << 24; - } - // Determinstic across platforms, perhaps unexpected by endian normalized streams - // When asserting read(noEndian) against a tag, an endian swap would cause the - // assertion to fail, thus providing you with the endian match check - // This step is delegated to a de-facto machine endian buffer builder - // ByteBuffers that normalize for endianness continue to work with tags - // irrespective of reader/writer endianness - return magic; -} - -static constexpr auline AuUInt64 AuConvertMagicTag64(const char buffer[8]) -{ - AuUInt64 magic {}; - if (Aurora::Build::kCurrentEndian == Aurora::Build::ECPUEndian::eCPULittle) - { - magic |= AuUInt64(buffer[0]); - magic |= AuUInt64(buffer[1]) << 8; - magic |= AuUInt64(buffer[2]) << 16; - magic |= AuUInt64(buffer[3]) << 24; - magic |= AuUInt64(buffer[4]) << 32; - magic |= AuUInt64(buffer[5]) << 40; - magic |= AuUInt64(buffer[6]) << 48; - magic |= AuUInt64(buffer[7]) << 56; - } - else - { - magic |= AuUInt64(buffer[7]); - magic |= AuUInt64(buffer[6]) << 8; - magic |= AuUInt64(buffer[5]) << 16; - magic |= AuUInt64(buffer[4]) << 24; - magic |= AuUInt64(buffer[3]) << 32; - magic |= AuUInt64(buffer[2]) << 40; - magic |= AuUInt64(buffer[1]) << 48; - magic |= AuUInt64(buffer[0]) << 56; - } - return magic; -} - -template -static auline AuOptional> AuOptionalSharedDynamicCast(AuOptional> &in) -{ - if (!in.has_value()) return {}; - return std::dynamic_pointer_cast(in.value()); -} - -template -static auline AuOptional> AuOptionalSharedStaticCast(AuOptional> &in) -{ - if (!in.has_value()) return {}; - return AuStaticPointerCast(in.value()); -} - -static auline bool AuEndsWith(AuString const &value, AuString const &ending) -{ - if (ending.size() > value.size()) return false; - return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); -} - -static auline bool AuStartsWith(AuString const &value, AuString const &starting) -{ - return value.rfind(starting, 0) == 0; -} - -template -static auline AuString AuToStringASCIIOp(T op, const AuString &in) -{ - AuString ret; - ret.resize(in.size()); - std::transform(in.begin(), in.end(), ret.begin(), [=](const char &c) - { - return op(c); - }); - return ret; -} - -static auline AuString AuToLower(const AuString &in) -{ - return AuToStringASCIIOp(std::tolower, in); -} - -static auline AuString AuToUpper(const AuString &in) -{ - return AuToStringASCIIOp(std::toupper, in); -} - -template -static auline bool AuTryFind(Map &map, const Key &key, Value *&ptr) -{ - auto itr = map.find(key); - if (itr != map.end()) - { - ptr = &itr->second; - return true; - } - else - { - ptr = nullptr; - return false; - } -} - -template -static auline bool AuTryFind(Map *map, const Key &key, Value *&ptr) -{ - auto itr = map->find(key); - if (itr != map->end()) - { - ptr = &itr->second; - return true; - } - else - { - ptr = nullptr; - return false; - } -} - -template -static auline bool AuTryFind(Map &map, const Key &key) -{ - auto itr = map.find(key); - if (itr != map.end()) - { - return true; - } - else - { - return false; - } -} - -template -static auline bool AuExists(Range &a, const Key &item) -{ - return std::find(a.begin(), a.end(), item) != a.end(); -} - -template -static auline bool AuTryFind(Map *map, const Key &key) -{ - auto itr = map->find(key); - if (itr != map->end()) - { - return true; - } - else - { - return false; - } -} - -template -static auline bool AuTryFindGeneric(Map &map, const Key &key, Value *&ptr) -{ - auto itr = map.find(key); - if (itr != map.end()) - { - ptr = &*itr; - return true; - } - else - { - ptr = nullptr; - return false; - } -} - -template -static auline bool AuTryFindGeneric(Map &map, const Key &key) -{ - if (map.find(key) != map.end()) - { - return true; - } - else - { - return false; - } -} - -template -static auline bool AuTryDelete(Map &map, const Key &key) -{ - auto itr = map.find(key); - if (itr != map.end()) - { - map.erase(itr); - return true; - } - else - { - return false; - } -} - -template -static auline bool AuTryDeleteList(List &list, const Key &key) -{ - auto itr = std::find(list.begin(), list.end(), key); - if (itr != list.end()) - { - list.erase(itr); - return true; - } - else - { - return false; - } -} - -template -static auline bool AuTryInsert(Container &container, const Type &value) -{ - try - { - container.insert(container.end(), value); - - return true; - } - catch (...) - { - return false; - } -} -template -static auline bool AuTryInsert(Container &container, Type &&value) -{ - try - { - container.insert(container.end(), value); - - return true; - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryInsert(Container *container, const Type &value) -{ - try - { - container->insert(container->end(), value); - - return true; - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryInsert(Container *container, Type &&value) -{ - try - { - container->insert(container->end(), value); - - return true; - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryInsertNoEnd(Container &container, Type &&value) // move -{ - try - { - container.insert(value); - - return true; - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryInsertNoEnd(Container &container, const Type &value) // copy -{ - try - { - container.insert(value); - - return true; - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryInsertNoEnd(Container *container, Type &&value) // move -{ - try - { - container->insert(value); - - return true; - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryInsertNoEnd(Container *container, const Type &value) // copy -{ - try - { - container->insert(value); - - return true; - } - catch (...) - { - return false; - } -} - -namespace Aurora::Memory -{ - struct ByteBuffer; -} - -template -static auline bool AuTryResize(T &list, AuUInt length) -{ - try - { - if constexpr (AuIsSame_v) - { - return list.Resize(length); - } - else - { - list.resize(length); - return true; - } - } - catch (...) - { - return false; - } -} - -template -static auline bool AuTryDownsize(T &list, AuUInt length) -{ - try - { - if constexpr (AuIsSame_v) - { - return list.Resize(length); - } - else - { - list.resize(length); - list.shrink_to_fit(); - return true; - } - } - catch (...) - { - return false; - } -} - -static auline AuString AuReplaceAll(AuString &str, const AuString &from, const AuString &to) -{ - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) - { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); // Handles case where 'to' is a substring of 'from' - } - return str; // :( -} - -// i told myself not to copy this, required a split function twice, now here we are :D -static auline AuList AuSplitString(const AuString& str, const AuString& delim, bool ignoreEmpty = true) -{ - AuList tokens; - AuUInt prev = 0, pos = 0; - do - { - pos = str.find(delim, prev); - if (pos == AuString::npos) pos = str.length(); - auto token = str.substr(prev, pos-prev); - if ((!token.empty()) && ignoreEmpty) tokens.push_back(token); - prev = pos + delim.length(); - } - while (pos < str.length() && prev < str.length()); - return tokens; -} - -// more copy/pasta. work smart, not hard. -// i dont want to waste time working out template kinks between clang and msvc -template class base,typename derived> -struct is_base_of_template_impl_au -{ - template - static constexpr AuTrueType test(const base *); - static constexpr AuFalseType test(...); - using type = decltype(test(std::declval())); -}; - -template < template class base,typename derived> -using AuIsBaseOfTemplate = typename is_base_of_template_impl_au::type; - -template -auto AuTuplePopFrontImpl(const Tuple& tuple, std::index_sequence) -{ - return std::make_tuple(std::get<1 + Is>(tuple)...); -} - -template -auto AuTuplePopFront(const Tuple& tuple) -{ - return AuTuplePopFrontImpl(tuple, std::make_index_sequence::value - 1>()); -} - -template -constexpr const T AuMin(const T &a, const T &b) -{ - return a < b ? a : b; -} - -template -constexpr const T AuMax(const T &a, const T &b) -{ - return a > b ? b : a; -} - -template -static auline bool AuTestBit(T value, AuUInt8 idx) -{ - return value & (T(1) << T(idx)); -} - -template -static auline void AuSetBit(T &value, AuUInt8 idx) -{ - value |= T(1) << T(idx); -} - -template -static auline void AuClearBit(T &value, AuUInt8 idx) -{ - value &= ~(T(1) << T(idx)); -} - -template -static auline bool AuBitScanForward(AuUInt8 &index, T value) -{ - unsigned long ret; - bool success; - - success = false; - index = 0; - -#if defined(AURORA_COMPILER_MSVC) - if constexpr (sizeof(T) == sizeof(AuUInt64)) - #if defined(AURORA_IS_32BIT) - if (!_BitScanForward(&ret, static_cast(value & 0xffffffff))) - { - if (!_BitScanForward(&ret, static_cast((value >> 32) & 0xffffffff))) - { - return false; - } - ret += 32; - } - #else - success = _BitScanForward64(&ret, static_cast(value)); - #endif - else success = _BitScanForward(&ret, static_cast(value)); -#elif defined(AURORA_COMPILER_GCC) || defined(AURORA_COMPILER_CLANG) - if (value == 0) - { - return false; - } - - if constexpr (sizeof(T) == sizeof(AuUInt64)) - #if defined(AURORA_IS_32BIT) - auto lower = static_cast(value & 0xffffffff)); - if (lower == 0) - { - ret = __builtin_ctzl(static_cast((value >> 32) & 0xffffffff)); - ret += 32; - } - else - { - ret = __builtin_ctzl(static_cast(lower)); - } - #else - ret = __builtin_ctzll(static_cast(value)); - #endif - else if constexpr (sizeof(T) == sizeof(unsigned long)) - ret = __builtin_ctzl(static_cast(value)); - else if constexpr (sizeof(T) == sizeof(unsigned int)) - ret = __builtin_ctz(static_cast(value)); - success = true; -#endif - index = ret; - return success; -} - -template -struct AuHalfWord -{ - using ReturnType_t = AuConditional_t, AuUInt32, AuConditional_t, AuUInt32, AuConditional_t, AuUInt8, AuFalseType>>>; - - static ReturnType_t ToLower(T in) - { - if constexpr (AuIsSame_v) - { - return in & AuUInt64(0xFFFFFFFF); - } - else if constexpr (AuIsSame_v) - { - return in & 0xFFFF; - } - else if constexpr (AuIsSame_v) - { - return in & 0xFF; - } - else - { - return {}; - } - } - - static ReturnType_t ToHigher(T in) - { - if constexpr (AuIsSame_v) - { - return (in >> AuUInt64(32)) & AuUInt64(0xFFFFFFFF); - } - else if constexpr (AuIsSame_v) - { - return (in >> 16) & 0xFFFF; - } - else if constexpr (AuIsSame_v) - { - return (in >> 8) & 0xFF; - } - else - { - return {}; - } - } -}; - -template -static auto AuBitsToLower(T in) -{ - return AuHalfWord::ToLower(in); -} - -template -static auto AuBitsToHigher(T in) -{ - return AuHalfWord::ToHigher(in); -} - -template -static AuUInt8 AuPopCnt(T in) -{ -#if defined(AURORA_COMPILER_MSVC) - #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) - #if defined(AURORA_ARCH_X64) - if constexpr (sizeof(T) == sizeof(AuUInt64)) - return _mm_popcnt_u64(in); - else - #endif - if constexpr (sizeof(T) < sizeof(AuUInt32)) - return __popcnt(in); - else if constexpr (sizeof(T) <= sizeof(AuUInt16)) - return __popcnt16(in); - #endif -#else - if constexpr (sizeof(T) == sizeof(unsigned long long)) - return __builtin_popcountll(static_cast(value)); - else if constexpr (sizeof(T) == sizeof(unsigned long)) - return __builtin_popcountl(static_cast(value)); - else if constexpr (sizeof(T) == sizeof(unsigned int)) - return __builtin_popcount(static_cast(value)); -#endif - -#if defined(AU_CPU_ENDIAN_LITTLE) - if constexpr (sizeof(T) == sizeof(AuUInt64)) - { - AuUInt64 m1 = 0x5555555555555555ll; - AuUInt64 m2 = 0x3333333333333333ll; - AuUInt64 m4 = 0x0F0F0F0F0F0F0F0Fll; - AuUInt64 h01 = 0x0101010101010101ll; - - in -= (in >> 1) & m1; - in = (in & m2) + ((in >> 2) & m2); - in = (in + (in >> 4)) & m4; - - return (in * h01) >> 56; - } - else if constexpr (sizeof(T) == sizeof(AuUInt32)) - { - in = in - ((in >> 1) & 0x55555555); - in = (in & 0x33333333) + ((in >> 2) & 0x33333333); - return (((in + (in >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; - } -#endif - - return {}; -} - -// TODO: AuBitScanReverse - -#if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) || defined(AURORA_ARCH_ARM) -#define AURORA_PERMIT_ARBITRARY_REF -#endif - - -// I'm sorry to anyone reading this. I wanted it to be verbose. I should've just used my old friends, macros :( - -template -static auline T AuReadGenericLE(const void *ptr, int offset) -{ -#if defined(AURORA_PERMIT_ARBITRARY_REF) && defined(AU_CPU_ENDIAN_LITTLE) - return *reinterpret_cast(reinterpret_cast(ptr) + offset); -#else - T temp; - AuMemcpy(&temp, reinterpret_cast(ptr) + offset, sizeof(temp)); -#if !defined(AU_CPU_ENDIAN_LITTLE) -#if defined(AURORA_COMPILER_MSVC) - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ulong(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_uint64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ushort(temp); - } -#else - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap32(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = (temp << 8) | ((temp >> 8) & 0xFF); - } -#endif -#endif - return temp; -#endif -} - -template -static auline T AuReadGenericBE(const void *ptr, int offset) -{ -#if defined(AURORA_PERMIT_ARBITRARY_REF) && defined(AU_CPU_ENDIAN_BIG) - return *reinterpret_cast(reinterpret_cast(ptr) + offset); -#else - T temp; - AuMemcpy(&temp, reinterpret_cast(ptr) + offset, sizeof(temp)); -#if defined(AU_CPU_ENDIAN_LITTLE) -#if defined(AURORA_COMPILER_MSVC) - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ulong(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_uint64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ushort(temp); - } -#else - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap32(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = (temp << 8) | ((temp >> 8) & 0xFF); - } -#endif -#endif - return temp; -#endif -} - -static auline AuUInt64 AuReadU64LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuUInt32 AuReadU32LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuUInt16 AuReadU16LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuUInt8 AuReadU8LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuInt64 AuReadS64LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuInt32 AuReadS32LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuInt16 AuReadS16LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuInt8 AuReadS8LE(const void *ptr, int offset) -{ - return AuReadGenericLE(ptr, offset); -} - -static auline AuUInt64 AuReadU64BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuUInt32 AuReadU32BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuUInt16 AuReadU16BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuUInt8 AuReadU8BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuInt64 AuReadS64BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuInt32 AuReadS32BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuInt16 AuReadS16BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuInt8 AuReadS8BE(const void *ptr, int offset) -{ - return AuReadGenericBE(ptr, offset); -} - -static auline AuUInt64 AuReadU64(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadU64LE(ptr, offset); -#else - return AuReadU64BE(ptr, offset); -#endif -} - -static auline AuUInt32 AuReadU32(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadU32LE(ptr, offset); -#else - return AuReadU32BE(ptr, offset); -#endif -} - -static auline AuUInt16 AuReadU16(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadU16LE(ptr, offset); -#else - return AuReadU16BE(ptr, offset); -#endif -} - -static auline AuUInt8 AuReadU8(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadU8LE(ptr, offset); -#else - return AuReadU8BE(ptr, offset); -#endif -} - -static auline AuInt64 AuReadS64(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadS64LE(ptr, offset); -#else - return AuReadS64BE(ptr, offset); -#endif -} - -static auline AuInt32 AuReadS32(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadS32LE(ptr, offset); -#else - return AuReadS32BE(ptr, offset); -#endif -} - -static auline AuInt16 AuReadS16(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadS16LE(ptr, offset); -#else - return AuReadS16BE(ptr, offset); -#endif -} - -static auline AuInt8 AuReadS8(const void *ptr, int offset) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - return AuReadS8LE(ptr, offset); -#else - return AuReadS8BE(ptr, offset); -#endif -} - -template -static auline void AuWriteGenericLE(void *ptr, int offset, T value) -{ -#if defined(AURORA_PERMIT_ARBITRARY_REF) && defined(AU_CPU_ENDIAN_LITTLE) - *reinterpret_cast(reinterpret_cast(ptr) + offset) = value; -#else - T temp = value; -#if !defined(AU_CPU_ENDIAN_LITTLE) -#if defined(AURORA_COMPILER_MSVC) - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ulong(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_uint64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ushort(temp); - } -#else - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap32(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = (temp << 8) | ((temp >> 8) & 0xFF); - } -#endif -#endif - AuMemcpy(reinterpret_cast(ptr) + offset, &temp, sizeof(temp)); -#endif -} - -template -static auline void AuWriteGenericBE(void *ptr, T value, int offset) -{ -#if defined(AURORA_PERMIT_ARBITRARY_REF) && defined(AU_CPU_ENDIAN_BIG) - *reinterpret_cast(reinterpret_cast(ptr) + offset) = value; -#else - T temp = value; -#if defined(AU_CPU_ENDIAN_LITTLE) -#if defined(AURORA_COMPILER_MSVC) - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ulong(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_uint64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = _byteswap_ushort(temp); - } -#else - if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap32(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = __builtin_bswap64(temp); - } - else if constexpr (AuIsSame_v || AuIsSame_v) - { - temp = (temp << 8) | ((temp >> 8) & 0xFF); - } -#endif -#endif - AuMemcpy(reinterpret_cast(ptr) + offset, &temp, sizeof(temp)); -#endif -} - -static auline void AuWriteU64LE(void *ptr, int offset, AuUInt64 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteU32LE(void *ptr, int offset, AuUInt32 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteU16LE(void *ptr, int offset, AuUInt16 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteU8LE(void *ptr, int offset, AuUInt8 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteS64LE(void *ptr, int offset, AuInt64 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteS32LE(void *ptr, int offset, AuInt32 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteS16LE(void *ptr, int offset, AuInt16 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteS8LE(void *ptr, int offset, AuInt8 value) -{ - AuWriteGenericLE(ptr, offset, value); -} - -static auline void AuWriteU64BE(void *ptr, int offset, AuUInt64 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteU32BE(void *ptr, int offset, AuUInt32 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteU16BE(void *ptr, int offset, AuUInt16 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteU8BE(void *ptr, int offset, AuUInt8 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteS64BE(void *ptr, int offset, AuInt64 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteS32BE(void *ptr, int offset, AuInt32 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteS16BE(void *ptr, int offset, AuInt16 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteS8BE(void *ptr, int offset, AuInt8 value) -{ - AuWriteGenericBE(ptr, offset, value); -} - -static auline void AuWriteU64(void *ptr, int offset, AuUInt64 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteU64LE(ptr, offset, value); -#else - AuWriteU64BE(ptr, offset, value); -#endif -} - -static auline void AuWriteU32(void *ptr, int offset, AuUInt32 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteU32LE(ptr, offset, value); -#else - AuWriteU32BE(ptr, offset, value); -#endif -} - -static auline void AuWriteU16(void *ptr, int offset, AuUInt16 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteU16LE(ptr, offset, value); -#else - AuWriteU16BE(ptr, offset, value); -#endif -} - -static auline void AuWriteU8(void *ptr, int offset, AuUInt8 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteU8LE(ptr, offset, value); -#else - AuWriteU8BE(ptr, offset, value); -#endif -} - -static auline void AuWriteS64(void *ptr, int offset, AuInt64 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteS64LE(ptr, offset, value); -#else - AuWriteS64BE(ptr, offset, value); -#endif -} - -static auline void AuWriteS32(void *ptr, int offset, AuInt32 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteS32LE(ptr, offset, value); -#else - AuWriteS32BE(ptr, offset, value); -#endif -} - -static auline void AuWriteS16(void *ptr, int offset, AuInt16 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteS16LE(ptr, offset, value); -#else - AuWriteS16BE(ptr, offset, value); -#endif -} - -static auline void AuWriteS8(void *ptr, int offset, AuInt8 value) -{ -#if defined(AU_CPU_ENDIAN_LITTLE) - AuWriteS8LE(ptr, offset, value); -#else - AuWriteS8BE(ptr, offset, value); -#endif -} +#include "auROXTLUtils.hpp" \ No newline at end of file diff --git a/Include/auROXTL.hpp b/Include/auROXTL.hpp new file mode 100644 index 00000000..b6f0a26d --- /dev/null +++ b/Include/auROXTL.hpp @@ -0,0 +1,31 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auROXTL.hpp + Date: 2022-2-2 + Author: Reece +***/ +#pragma once + +#include +#include + +#if defined(_AUHAS_AURORAENUM) + #include + #include + #include +#endif + +#if defined(_AUHAS_FMT) + #include +#endif + +#include "auROXTL/AU_MACROS.hpp" +#include "auROXTLTypes.hpp" + +#if defined(_AUHAS_AURORAENUM) + #define _ALLOW_AURORA_ENUM_AUENVHPP + #include +#endif + +#include "auROXTLUtils.hpp" \ No newline at end of file diff --git a/Include/auROXTL/AU_MACROS.hpp b/Include/auROXTL/AU_MACROS.hpp new file mode 100644 index 00000000..46249f65 --- /dev/null +++ b/Include/auROXTL/AU_MACROS.hpp @@ -0,0 +1,231 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: AuroraMacros.hpp + File: AU_MACROS.hpp + Date: 2021-6-10 + Author: Reece +***/ +#pragma once + +#define AU_COPY(type) type(const type&) = default; type &operator=(const type &) = default; +#define AU_MOVE(type) type(type&&) = default; type &operator=(type &&) = default; +#define AU_COPY_MOVE(type) AU_COPY(type) AU_MOVE(type) + +#define AU_NO_COPY(type) type(const type&) = delete; +#define AU_NO_MOVE(type) type(type&&) = delete; +#define AU_NO_COPY_NO_MOVE(type) AU_NO_COPY(type) AU_NO_MOVE(type) + +#if !defined(AU_SHARED_FROM_THIS) + #define AU_SHARED_FROM_THIS (AuStaticPointerCast>(this->SharedFromThis())) +#endif + +#if !defined(AU_WEAK_FROM_THIS) + #define AU_WEAK_FROM_THIS (AuWPtr>(AuStaticPointerCast>(this->SharedFromThis()))) +#endif + +#define AU_BRACKET_SCOPE(...) __VA_ARGS__ + +#if !defined(AU_TEMPLATE_ENABLE_WHEN) + #define AU_TEMPLATE_ENABLE_WHEN(...) typename AuEnableIf<__VA_ARGS__>::type* = nullptr +#endif + +#define AU_WHAT(n) n + +/// @hideinitializer +#define _AU_STRINGIFY(in) #in +#define AU_STRINGIFY(in) _AU_STRINGIFY(in) + +/// @hideinitializer +#define _AU_CONCAT(a, b) a ## b +#define AU_CONCAT(a, b) _AU_CONCAT(a, b) + +/// @hideinitializer +#define _AUKCON_STRINGIFY_X(in) AU_STRINGIFY(in) + +#if !defined(AU_SHARED_API_EX) + #define AU_SHARED_API_EX(vis, name, type, ...) \ + \ + vis type *name ## New(__VA_ARGS__); \ + vis void name ## Release(type *); \ + static inline void name ## Destroy(type *val) \ + { \ + name ## Release(val); \ + } \ + \ + struct CppDeleter ## name \ + { \ + void operator()(type *t) \ + { \ + name ## Release(t); \ + } \ + }; \ + \ + using name ## Unique_t = AURORA_RUNTIME_AU_UNIQUE_PTR; \ + template \ + name ## Unique_t name ## Unique(T... args) \ + { \ + return name ## Unique_t(name ## New(args...)); \ + } \ + \ + using name ## Shared_t = std::shared_ptr; \ + template \ + name ## Shared_t name ## Shared(T... args) \ + { \ + return name ## Shared_t(name ## New(args...), name ## Release); \ + } +#endif + +#if !defined(AU_SHARED_API) + #define AU_SHARED_API(name, type, ...) AU_SHARED_API_EX(, name, type, #__VA_ARGS__) +#endif + +#if !defined(AU_NOINLINE) + #if defined(AURORA_COMPILER_MSVC) + #define AU_NOINLINE __declspec(noinline) + #else + #define AU_NOINLINE __attribute__((noinline)) + #endif +#endif + +#if !defined(AU_INLINE) + #if defined(AURORA_COMPILER_MSVC) + #define AU_INLINE __forceinline + #else + #define AU_INLINE __attribute__((always_inline)) + #endif +#endif + +#if !defined(AU_NORETURN) + #if defined(AURORA_COMPILER_MSVC) + #define AU_NORETURN __declspec(noreturn) + #elif (defined(AURORA_COMPILER_CLANG) || defined(AURORA_COMPILER_GCC)) + #define AU_NORETURN __attribute__((noreturn)) + #elif defined(AU_LANG_CPP) + #define AU_NORETURN [[noreturn]] + #else + #define AU_NORETURN + #endif +#endif + +#if !defined(AU_ALLOC) + #if defined(AURORA_PLATFORM_WIN32) + #define AU_ALLOC __declspec(allocator) + #elif defined(AURORA_COMPILER_CLANG) + #define AU_ALLOC __declspec(allocator) + #elif defined(AURORA_COMPILER_GCC) + #define AU_ALLOC __attribute__((malloc)) + #else + #define AU_ALLOC + #endif +#endif + +#if !defined(NO__NEW) + #if !defined(_new) + #define _new new (std::nothrow) + #endif +#endif + +#if !defined(NO__INLINE) + #if !defined(auline) + #define auline AU_INLINE + #endif +#endif + +#if !defined(AU_FWD) + #define AU_FWD(var) AuForward(var) +#endif + +#if !defined(AU_THROW_STRING) + #define AU_THROW_STRING(var) throw AuString(var) +#endif + +#define AU_ITERATE_ARRAY(index, arry) AuUInt index = 0; index < AuArraySize(arry); index++ +#define AU_ITERATE_N(index, n) AuUInt index = 0; index < n; index++ +#define AU_ITERATE_N_TO_X(index, n, x) AuUInt index = n; index < x; index++ +#define AU_ITERATE_BACKWARDS(index, lastIdx) AuUInt index = lastIdx; index <= 0; index-- + +#define AU_ITR_ARRAY AU_ITERATE_ARRAY +#define AU_ITR_N AU_ITERATE_N +#define AU_ITR_N_TO_X AU_ITERATE_N_TO_X +#define AU_ITR_BACKWARDS AU_ITERATE_BACKWARDS + +#define AU_STRIP_BRACKETS_IMPL(...) __VA_ARGS__ + +#if !defined(AU_STRIP_BRACKETS) + #define AU_STRIP_BRACKETS(X) AU_WHAT(AU_STRIP_BRACKETS_IMPL X) +#endif + +#if !defined(AU_STRIP) + #define AU_STRIP AU_STRIP_BRACKETS +#endif + +#if !defined(AU_EMIT_FIRST) + #define AU_EMIT_FIRST(a, b)a +#endif + +#if !defined(AU_EMIT_SECOND) + #define AU_EMIT_SECOND(a, b)b +#endif + +#if !defined(AU_EMIT_BOTH) + #define AU_EMIT_BOTH(a, b)a, a +#endif + +#if !defined(AuBindThis) + #define AuBindThis(method, ...) std::bind(method, this, ## __VA_ARGS__) +#endif + +#if !defined(AuSharedFromThis) + #define AuSharedFromThis() AU_SHARED_FROM_THIS +#endif + +#if !defined(AuWeakFromThis) + #define AuWeakFromThis() AU_SHARED_FROM_THIS +#endif + +#define AU_EMIT_FIRST_COMMA_FIRST(n)n +#define AU_EMIT_FIRST_COMMA_OTHERS(n),n + +/// @hideinitializer +#define AU_EMIT_FIRST_TYPEREDUCED_PAIR_REDUCED(variable) AuRemoveConst_t> + + +/// @hideinitializer +#define AU_EMIT_CTOR_CPY(pair) const AU_EMIT_FIRST_TYPEREDUCED_PAIR_REDUCED(pair) &pair +/// @hideinitializer +#define AU_EMIT_CTOR_CPY_SECOND(pair) ,AU_EMIT_CTOR_CPY(pair) + + +/// @hideinitializer +#define AU_EMIT_CTOR_MOV(pair) AU_EMIT_FIRST_TYPEREDUCED_PAIR_REDUCED(pair) &&pair +/// @hideinitializer +#define AU_EMIT_CTOR_MOV_SECOND(pair) ,AU_EMIT_CTOR_MOV(pair) + + +/// @hideinitializer +#define AU_EMIT_CTOR_ASSIGN(pair) pair(pair) +/// @hideinitializer +#define AU_EMIT_CTOR_ASSIGN_SECOND(pair) ,AU_EMIT_CTOR_ASSIGN(pair) + + +/// @hideinitializer +#define AU_DEFINE_CTOR_CPY_VA(thisType, args) \ +inline thisType(AU_FOR_EACH_FIRST(AU_EMIT_CTOR_CPY, AU_EMIT_CTOR_CPY_SECOND, AU_STRIP_BRACKETS(args))) : AU_FOR_EACH_FIRST(AU_EMIT_CTOR_ASSIGN, AU_EMIT_CTOR_ASSIGN_SECOND, AU_STRIP_BRACKETS(args)) \ +{} + +/// @hideinitializer +#define AU_DEFINE_CTOR_MOV_VA(thisType, args) \ +inline thisType(AU_FOR_EACH_FIRST(AU_EMIT_CTOR_MOV, AU_EMIT_CTOR_MOV_SECOND, AU_STRIP_BRACKETS(args))) : AU_FOR_EACH_FIRST(AU_EMIT_CTOR_ASSIGN, AU_EMIT_CTOR_ASSIGN_SECOND, AU_STRIP_BRACKETS(args)) \ +{} + +/// @hideinitializer +#define AU_DEFINE_CTOR_VA_(thisType, args) AU_DEFINE_CTOR_CPY_VA(thisType, args) AU_DEFINE_CTOR_MOV_VA(thisType, args) + + +/// @deprecated +#define AU_DEFINE_CTOR_ONE(thisType, pairTypeName) AU_DEFINE_CTOR_VA_(thisType, (AU_EMIT_SECOND pairTypeName)) + + +/// +#define AU_DEFINE_CTOR_VA(thisType, args) AU_DEFINE_CTOR_CPY_VA(thisType, args) AU_DEFINE_CTOR_MOV_VA(thisType, args) \ No newline at end of file diff --git a/Include/auROXTL/auArray.hpp b/Include/auROXTL/auArray.hpp new file mode 100644 index 00000000..ec48ad05 --- /dev/null +++ b/Include/auROXTL/auArray.hpp @@ -0,0 +1,15 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auArray.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_AU_ARRAY) + #define AURORA_RUNTIME_AU_ARRAY std::array +#endif + +template +using AuArray = AURORA_RUNTIME_AU_ARRAY; \ No newline at end of file diff --git a/Include/auROXTL/auAtomic.hpp b/Include/auROXTL/auAtomic.hpp new file mode 100644 index 00000000..8f845520 --- /dev/null +++ b/Include/auROXTL/auAtomic.hpp @@ -0,0 +1,186 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auAtomic.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +template +struct AuAtomicUtils +{ + static T Set(T *in, AuUInt8 offset); + static T Add(T *in, T addend); + static T Sub(T *in, T minuend); + static T CompareExchange(T *in, T replace, T compare); +}; + +#if defined(AURORA_COMPILER_MSVC) + +template<> +inline auline AuUInt64 AuAtomicUtils::CompareExchange(AuUInt64 *in, AuUInt64 replace, AuUInt64 compare) +{ + return static_cast(_InterlockedCompareExchange64(reinterpret_cast(in), static_cast(replace), static_cast(compare))); +} + +template<> +inline auline AuUInt32 AuAtomicUtils::CompareExchange(AuUInt32 *in, AuUInt32 replace, AuUInt32 compare) +{ + return static_cast(_InterlockedCompareExchange(reinterpret_cast(in), static_cast(replace), static_cast(compare))); +} + +template<> +inline auline AuUInt16 AuAtomicUtils::CompareExchange(AuUInt16 *in, AuUInt16 replace, AuUInt16 compare) +{ + return static_cast(_InterlockedCompareExchange16(reinterpret_cast(in), static_cast(replace), static_cast(compare))); +} + +template<> +inline auline AuInt64 AuAtomicUtils::CompareExchange(AuInt64 *in, AuInt64 replace, AuInt64 compare) +{ + return _InterlockedCompareExchange64(reinterpret_cast(in), static_cast(replace), static_cast(compare)); +} + +template<> +inline auline AuInt32 AuAtomicUtils::CompareExchange(AuInt32 *in, AuInt32 replace, AuInt32 compare) +{ + return _InterlockedCompareExchange(reinterpret_cast(in), static_cast(replace), static_cast(compare)); +} + +template<> +inline auline AuInt16 AuAtomicUtils::CompareExchange(AuInt16 *in, AuInt16 replace, AuInt16 compare) +{ + return _InterlockedCompareExchange16(reinterpret_cast(in), static_cast(replace), static_cast(compare)); +} + +template<> +inline auline AuUInt64 AuAtomicUtils::Add(AuUInt64 *in, AuUInt64 addend) +{ + return static_cast(_InterlockedExchangeAdd64(reinterpret_cast(in), static_cast(addend)) + static_cast(addend)); +} + +template<> +inline auline AuUInt32 AuAtomicUtils::Add(AuUInt32 *in, AuUInt32 addend) +{ + return static_cast(_InterlockedExchangeAdd(reinterpret_cast(in), static_cast(addend)) + static_cast(addend)); +} + +template<> +inline auline AuInt64 AuAtomicUtils::Add(AuInt64 *in, AuInt64 addend) +{ + return _InterlockedExchangeAdd64(reinterpret_cast(in), static_cast(addend)) + static_cast(addend); +} + +template<> +inline auline AuInt32 AuAtomicUtils::Add(AuInt32 *in, AuInt32 addend) +{ + return _InterlockedExchangeAdd(reinterpret_cast(in), static_cast(addend)) + static_cast(addend); +} + +// TODO: +#if 0 +template<> +inline auline AuUInt16 AuAtomicUtils::Add(AuUInt16 *in, AuUInt16 addend) +{ + return {}; +} +#endif + + +template<> +inline auline AuUInt64 AuAtomicUtils::Sub(AuUInt64 *in, AuUInt64 minuend) +{ + return Add(in, AuUInt64(0) - minuend); +} + +template<> +inline auline AuUInt32 AuAtomicUtils::Sub(AuUInt32 *in, AuUInt32 minuend) +{ + return Add(in, AuUInt32(0) - minuend); +} + +// TODO: +#if 0 +template<> +inline auline AuUInt16 AuAtomicUtils::Sub(AuUInt16 *in, AuUInt16 minuend) +{ + return {}; +} + +#endif + +template<> +inline auline AuUInt64 AuAtomicUtils::Set(AuUInt64 *in, AuUInt8 offset) +{ + return _InterlockedOr64(reinterpret_cast(in), AuUInt64(1) << offset); +} + +template<> +inline auline AuUInt32 AuAtomicUtils::Set(AuUInt32 *in, AuUInt8 offset) +{ + return _InterlockedOr(reinterpret_cast(in), 1 << offset); +} + +template<> +inline auline AuUInt16 AuAtomicUtils::Set(AuUInt16 *in, AuUInt8 offset) +{ + return _InterlockedOr16(reinterpret_cast(in), 1 << offset); +} + + +#elif defined(AURORA_COMPILER_CLANG) || defined(AURORA_COMPILER_GCC) + +template +inline auline T AuAtomicUtils::CompareExchange(T *in, T replace, T compare) +{ + return __sync_val_compare_and_swap(in, compare, replace); +} + +template +inline auline T AuAtomicUtils::Add(T *in, T addend) +{ + return __sync_add_and_fetch(in, addend); +} + +template +inline auline T AuAtomicUtils::Sub(T *in, T minuend) +{ + return __sync_sub_and_fetch(in, minuend); +} + +template +inline auline T AuAtomicUtils::Set(T *in, AuUInt8 offset) +{ + return __sync_or_and_fetch(in, T(1) << offset); +} + +#endif + +template +auline +T AuAtomicSet(T *in, AuUInt8 offset) +{ + return AuAtomicUtils::Set(in, offset); +} + +template +auline +T AuAtomicAdd(T *in, T addend) +{ + return AuAtomicUtils::Add(in, addend); +} + +template +auline +T AuAtomicSub(T *in, T minuend) +{ + return AuAtomicUtils::Sub(in, minuend); +} + +template +auline +T AuAtomicCompareExchange(T *in, T replace, T compare) +{ + return AuAtomicUtils::CompareExchange(in, replace, compare); +} \ No newline at end of file diff --git a/Include/auROXTL/auBST.hpp b/Include/auROXTL/auBST.hpp new file mode 100644 index 00000000..2b27c9ea --- /dev/null +++ b/Include/auROXTL/auBST.hpp @@ -0,0 +1,18 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auBST.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_AU_BST) + #define AURORA_RUNTIME_AU_BST std::map +#endif + +template +using AuBST = AURORA_RUNTIME_AU_BST; + +template +using AuBSTEx = AURORA_RUNTIME_AU_BST; \ No newline at end of file diff --git a/Include/auROXTL/auBitsUtils.hpp b/Include/auROXTL/auBitsUtils.hpp new file mode 100644 index 00000000..87734519 --- /dev/null +++ b/Include/auROXTL/auBitsUtils.hpp @@ -0,0 +1,190 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auBitsUtils.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +template +static auline bool AuTestBit(T value, AuUInt8 idx) +{ + return value & (T(1) << T(idx)); +} + +template +static auline void AuSetBit(T &value, AuUInt8 idx) +{ + value |= T(1) << T(idx); +} + +template +static auline void AuClearBit(T &value, AuUInt8 idx) +{ + value &= ~(T(1) << T(idx)); +} + +template +static auline bool AuBitScanForward(AuUInt8 &index, T value) +{ + unsigned long ret; + bool success; + + success = false; + index = 0; + +#if defined(AURORA_COMPILER_MSVC) + if constexpr (sizeof(T) == sizeof(AuUInt64)) + #if defined(AURORA_IS_32BIT) + if (!_BitScanForward(&ret, static_cast(value & 0xffffffff))) + { + if (!_BitScanForward(&ret, static_cast((value >> 32) & 0xffffffff))) + { + return false; + } + ret += 32; + } + #else + success = _BitScanForward64(&ret, static_cast(value)); + #endif + else success = _BitScanForward(&ret, static_cast(value)); +#elif defined(AURORA_COMPILER_GCC) || defined(AURORA_COMPILER_CLANG) + if (value == 0) + { + return false; + } + + if constexpr (sizeof(T) == sizeof(AuUInt64)) + #if defined(AURORA_IS_32BIT) + auto lower = static_cast(value & 0xffffffff)); + if (lower == 0) + { + ret = __builtin_ctzl(static_cast((value >> 32) & 0xffffffff)); + ret += 32; + } + else + { + ret = __builtin_ctzl(static_cast(lower)); + } + #else + ret = __builtin_ctzll(static_cast(value)); + #endif + else if constexpr (sizeof(T) == sizeof(unsigned long)) + ret = __builtin_ctzl(static_cast(value)); + else if constexpr (sizeof(T) == sizeof(unsigned int)) + ret = __builtin_ctz(static_cast(value)); + success = true; +#endif + index = ret; + return success; +} + +template +struct AuHalfWord +{ + using ReturnType_t = AuConditional_t, AuUInt32, AuConditional_t, AuUInt32, AuConditional_t, AuUInt8, AuFalseType>>>; + + static ReturnType_t ToLower(T in) + { + if constexpr (AuIsSame_v) + { + return in & AuUInt64(0xFFFFFFFF); + } + else if constexpr (AuIsSame_v) + { + return in & 0xFFFF; + } + else if constexpr (AuIsSame_v) + { + return in & 0xFF; + } + else + { + return {}; + } + } + + static ReturnType_t ToHigher(T in) + { + if constexpr (AuIsSame_v) + { + return (in >> AuUInt64(32)) & AuUInt64(0xFFFFFFFF); + } + else if constexpr (AuIsSame_v) + { + return (in >> 16) & 0xFFFF; + } + else if constexpr (AuIsSame_v) + { + return (in >> 8) & 0xFF; + } + else + { + return {}; + } + } +}; + +template +static auto AuBitsToLower(T in) +{ + return AuHalfWord::ToLower(in); +} + +template +static auto AuBitsToHigher(T in) +{ + return AuHalfWord::ToHigher(in); +} + +template +static AuUInt8 AuPopCnt(T in) +{ +#if defined(AURORA_COMPILER_MSVC) + #if defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86) + #if defined(AURORA_ARCH_X64) + if constexpr (sizeof(T) == sizeof(AuUInt64)) + return _mm_popcnt_u64(in); + else + #endif + if constexpr (sizeof(T) == sizeof(unsigned int)) + return __popcnt(in); + else if constexpr (sizeof(T) <= sizeof(AuUInt16)) + return __popcnt16(in); + #endif +#else + if constexpr (sizeof(T) == sizeof(unsigned long long)) + return __builtin_popcountll(static_cast(value)); + else if constexpr (sizeof(T) == sizeof(unsigned long)) + return __builtin_popcountl(static_cast(value)); + else if constexpr (sizeof(T) == sizeof(unsigned int)) + return __builtin_popcount(static_cast(value)); +#endif + +#if defined(AU_CPU_ENDIAN_LITTLE) + if constexpr (sizeof(T) == sizeof(AuUInt64)) + { + AuUInt64 m1 = 0x5555555555555555ll; + AuUInt64 m2 = 0x3333333333333333ll; + AuUInt64 m4 = 0x0F0F0F0F0F0F0F0Fll; + AuUInt64 h01 = 0x0101010101010101ll; + + in -= (in >> 1) & m1; + in = (in & m2) + ((in >> 2) & m2); + in = (in + (in >> 4)) & m4; + + return (in * h01) >> 56; + } + else if constexpr (sizeof(T) == sizeof(AuUInt32)) + { + in = in - ((in >> 1) & 0x55555555); + in = (in & 0x33333333) + ((in >> 2) & 0x33333333); + return (((in + (in >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; + } +#endif + + return {}; +} + +// TODO: AuBitScanReverse diff --git a/Include/auROXTL/auCastUtils.hpp b/Include/auROXTL/auCastUtils.hpp new file mode 100644 index 00000000..a6bd14e5 --- /dev/null +++ b/Include/auROXTL/auCastUtils.hpp @@ -0,0 +1,82 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auCastUtils.hpp + Date: 2022-2-10 + Author: Reece +***/ +#pragma once + +template +AuSPtr AuStaticCast(const AuSPtr &other) +{ + return AuSPtr(other, static_cast(other.get())); +} + +template +AuSPtr AuStaticCast(AuSPtr &&other) +{ + return AuSPtr(AuMove(other), static_cast(other.get())); +} + +template +AuSPtr AuConstCast(const AuSPtr &other) +{ + return AuSPtr(other, const_cast(other.get())); +} + +template +AuSPtr AuConstCast(AuSPtr &&other) +{ + return AuSPtr(AuMove(other), const_cast(other.get())); +} + +template +AuSPtr AuReinterpretCast(const AuSPtr &other) +{ + return AuSPtr(other, reinterpret_cast(other.get())); +} + +template +AuSPtr AuReinterpretCast(AuSPtr &&other) +{ + return AuSPtr(AuMove(other), reinterpret_cast(other.get())); +} + +template +AuSPtr AuDynamicCast(const AuSPtr &other) +{ + return AuSPtr(other, dynamic_cast(other.get())); +} + +template +AuSPtr AuDynamicCast(AuSPtr &&other) +{ + return AuSPtr(AuMove(other), dynamic_cast(other.get())); +} + +template +AuOptional> AuOptionalSharedDynamicCast(AuOptional> &in) +{ + if (!in.has_value()) return {}; + return AuDynamicCast(in.value()); +} + +template +AuOptional> AuOptionalSharedStaticCast(AuOptional> &in) +{ + if (!in.has_value()) return {}; + return AuStaticPointerCast(in.value()); +} + +template +AuSPtr AuStaticPointerCast(const AuSPtr &other) noexcept +{ + return AuSPtr(other, static_cast::element_type *>(other.get())); +} + +template +AuSPtr AuStaticPointerCast(AuSPtr &&other) noexcept +{ + return AuSPtr(AuMove(other), static_cast::element_type *>(other.get())); +} \ No newline at end of file diff --git a/Include/auROXTL/auContainerUtils.hpp b/Include/auROXTL/auContainerUtils.hpp new file mode 100644 index 00000000..fefda3f0 --- /dev/null +++ b/Include/auROXTL/auContainerUtils.hpp @@ -0,0 +1,487 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auContainerUtils.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +template +static bool _AuRemoveIfBase(T &in, const AuPredicate &> &predicate); + +template +static bool AuRemoveAllIf(T &in, const AuPredicate &> &predicate) +{ + return _AuRemoveIfBase(in, predicate); +} + +template +static bool AuRemoveIf(T &in, const AuPredicate &> &predicate) +{ + return _AuRemoveIfBase(in, predicate); +} + +template +static bool AuTryRemove(T &in, const Z &type) +{ + try + { + auto itr = in.find(type); + if (itr == in.end()) + { + return false; + } + in.erase(itr); + return true; + } + catch (...) + { + return false; + } +} + +template +static void AuRemove(T &in, const Z &type) +{ + auto itr = in.find(type); + if (itr == in.end()) + { + return; + } + in.erase(itr); +} + +template +static void AuRemoveRange(T &in, AuUInt index, AuUInt length) +{ + if (index + length > in.size()) + { + return; + } + + auto begin = in.begin(); + std::advance(begin, index); + + auto end = begin; + + std::advance(end, length); + + while (begin != end) + { + in.erase(begin++); + } +} + +template +static bool AuTryRemoveRange(T &in, AuUInt index, AuUInt length) +{ + try + { + if (index + length > in.size()) + { + return false; + } + + auto begin = in.begin(); + auto end = begin; + + std::advance(end, index + length); + + while (begin != end) + { + in.erase(begin++); + } + } + catch (...) + { + return false; + } + + return true; +} + +template +static auline bool AuTryFind(Map &map, const Key &key, Value *&ptr) +{ + auto itr = map.find(key); + if (itr != map.end()) + { + ptr = &itr->second; + return true; + } + else + { + ptr = nullptr; + return false; + } +} + +template +static auline bool AuTryFind(Map *map, const Key &key, Value *&ptr) +{ + auto itr = map->find(key); + if (itr != map->end()) + { + ptr = &itr->second; + return true; + } + else + { + ptr = nullptr; + return false; + } +} + +template +static auline bool AuTryFind(Map &map, const Key &key) +{ + auto itr = map.find(key); + if (itr != map.end()) + { + return true; + } + else + { + return false; + } +} + +template +static auline auto AuTryFindByTupleN(List &list, const Key &key) +{ + for (auto itr = list.begin(); itr != list.end(); ) + { + if (AuGet(*itr) == key) + { + return itr; + } + else + { + itr++; + } + } + return list.end(); +} + +template +static auline bool AuExists(Range &a, const Key &item) +{ + return std::find(a.begin(), a.end(), item) != a.end(); +} + +template +static auline bool AuTryFind(Map *map, const Key &key) +{ + auto itr = map->find(key); + if (itr != map->end()) + { + return true; + } + else + { + return false; + } +} + +template +static auline bool AuTryFindGeneric(Map &map, const Key &key, Value *&ptr) +{ + auto itr = map.find(key); + if (itr != map.end()) + { + ptr = &*itr; + return true; + } + else + { + ptr = nullptr; + return false; + } +} + +template +static auline bool AuTryFindGeneric(Map &map, const Key &key) +{ + if (map.find(key) != map.end()) + { + return true; + } + else + { + return false; + } +} + +template +static auline bool AuTryClear(Container &container) +{ + container.clear(); // clears are generally noexcept. + return true; +} + +template +static auline bool AuTryDelete(Map &map, const Key &key) +{ + auto itr = map.find(key); + if (itr != map.end()) + { + map.erase(itr); + return true; + } + else + { + return false; + } +} + +/// @deprecated -> Should've been named AuTryRemoveList +template +static auline bool AuTryDeleteList(List &list, const Key &key) +{ + auto itr = std::find(list.begin(), list.end(), key); + if (itr != list.end()) + { + list.erase(itr); + return true; + } + else + { + return false; + } +} + +template +static auline bool AuTryRemoveList(List &list, const Key &key) +{ + auto itr = std::find(list.begin(), list.end(), key); + if (itr != list.end()) + { + list.erase(itr); + return true; + } + else + { + return false; + } +} + +template +static auline bool AuTryRemoveByTupleN(List &list, const Key &key) +{ + for (auto itr = list.begin(); itr != list.end(); ) + { + if (AuGet(*itr) == key) + { + itr = list.erase(itr); + return true; + } + else + { + itr++; + } + } + + return false; +} + +template +static auline bool AuTryInsert(Container &container, const Type &value) +{ + try + { + container.insert(container.end(), value); + + return true; + } + catch (...) + { + return false; + } +} +template +static auline bool AuTryInsert(Container &container, Type &&value) +{ + try + { + container.insert(container.end(), value); + + return true; + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryInsert(Container *container, const Type &value) +{ + try + { + container->insert(container->end(), value); + + return true; + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryInsert(Container *container, Type &&value) +{ + try + { + container->insert(container->end(), value); + + return true; + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryInsertNoEnd(Container &container, Type &&value) // move +{ + try + { + container.insert(value); + + return true; + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryInsertNoEnd(Container &container, const Type &value) // copy +{ + try + { + container.insert(value); + + return true; + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryInsertNoEnd(Container *container, Type &&value) // move +{ + try + { + container->insert(value); + + return true; + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryInsertNoEnd(Container *container, const Type &value) // copy +{ + try + { + container->insert(value); + + return true; + } + catch (...) + { + return false; + } +} + +namespace Aurora::Memory +{ + struct ByteBuffer; +} + +template +static auline bool AuTryResize(T &list, AuUInt length) +{ + try + { + if constexpr (AuIsSame_v) + { + return list.Resize(length); + } + else + { + list.resize(length); + return true; + } + } + catch (...) + { + return false; + } +} + +template +static auline bool AuTryDownsize(T &list, AuUInt length) +{ + try + { + if constexpr (AuIsSame_v) + { + if (!list.Resize(length)) + { + return false; + } + + list.GC(); + return true; + } + else + { + list.resize(length); + list.shrink_to_fit(); + return true; + } + } + catch (...) + { + return false; + } +} + +template +static bool _AuRemoveIfBase(T &in, const AuPredicate &> &predicate) +{ + bool retOne {}; + + for (auto itr = in.begin(); itr != in.end(); ) + { + if (predicate(*itr)) + { + itr = in.erase(itr); + if constexpr (!all) + { + return true; + } + + retOne = true; + } + else + { + itr++; + } + } + + // optimization hint + if constexpr (all) return retOne; + return {}; +} \ No newline at end of file diff --git a/Include/auROXTL/auCopyMoveUtils.hpp b/Include/auROXTL/auCopyMoveUtils.hpp new file mode 100644 index 00000000..5246518f --- /dev/null +++ b/Include/auROXTL/auCopyMoveUtils.hpp @@ -0,0 +1,26 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auCopyMoveUtils.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +template +constexpr AuRemoveReference_t &&AuMove(T &&arg) +{ + return static_cast &&>(arg); +} + +template +constexpr T &&AuForward(AuRemoveReference_t &arg) +{ + return static_cast(arg); +} + +template +constexpr T &&AuForward(AuRemoveReference_t &&arg) +{ + return static_cast(arg); +} \ No newline at end of file diff --git a/Include/auROXTL/auEndianness.hpp b/Include/auROXTL/auEndianness.hpp new file mode 100644 index 00000000..9d094989 --- /dev/null +++ b/Include/auROXTL/auEndianness.hpp @@ -0,0 +1,88 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auEndianness.hpp + Date: 2022-2-6 + Author: Reece +***/ +#pragma once + +template +struct AuEndianUtils +{ + static T Swap(T in); +}; + +template +inline T AuEndianUtils::Swap(T in) +{ + if constexpr (sizeof(T) == 8) + return (T(in) & 0xFF) << T(56) | + (T(in >> T(8)) & T(0xFF)) << T(48) | + (T(in >> T(16)) & T(0xFF)) << T(40) | + (T(in >> T(24)) & T(0xFF)) << T(32) | + (T(in >> T(32)) & T(0xFF)) << T(24) | + (T(in >> T(40)) & T(0xFF)) << T(16) | + (T(in >> T(48)) & T(0xFF)) << T(8) | + (T(in >> T(56)) & T(0xFF)); + + if constexpr (sizeof(T) == 4) + return T(in & 0xFF) << 24 | + (T(in >> 8) & 0xFF) << 16 | + (T(in >> 16) & 0xFF) << 8 | + (T(in >> 24) & 0xFF); + + if constexpr (sizeof(T) == 2) + return (in & 0xFF) << 8 | + ((in >> 8) & 0xFF); + + return in; +} + +#if defined(AURORA_COMPILER_MSVC) + +template<> +inline AuUInt64 AuEndianUtils::Swap(AuUInt64 in) +{ + return _byteswap_uint64(in); +} + +template<> +inline AuUInt32 AuEndianUtils::Swap(AuUInt32 in) +{ + return _byteswap_ulong(in); +} + +template<> +inline AuUInt16 AuEndianUtils::Swap(AuUInt16 in) +{ + return _byteswap_ushort(in); +} + +#elif defined(AURORA_COMPILER_CLANG) + +template<> +inline AuUInt64 AuEndianUtils::Swap(AuUInt64 in) +{ + return __builtin_bswap64(in); +} + +template<> +inline AuUInt32 AuEndianUtils::Swap(AuUInt32 in) +{ + return __builtin_bswap32(in); +} + +template<> +inline AuUInt16 AuEndianUtils::Swap(AuUInt16 in) +{ + return __builtin_bswap16(in); +} + +#endif + +template +inline auline Type_t AuFlipEndian(Type_t in) +{ + return AuEndianUtils::Swap(in); +} \ No newline at end of file diff --git a/Include/auROXTL/auFunctional.hpp b/Include/auROXTL/auFunctional.hpp new file mode 100644 index 00000000..abc9890e --- /dev/null +++ b/Include/auROXTL/auFunctional.hpp @@ -0,0 +1,29 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auFunctional.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_AU_FUNC) + #define AURORA_RUNTIME_AU_FUNC std::function +#endif + +template +using AuFunction = AURORA_RUNTIME_AU_FUNC; + +template +using AuPredicate = AuFunction; + +using AuVoidFunc = AuFunction; + +template +using AuConsumer = AuFunction; + +template +using AuSupplier = AuFunction; + +template +using AuSupplierConsumer = AuFunction; \ No newline at end of file diff --git a/Include/auROXTL/auHashMap.hpp b/Include/auROXTL/auHashMap.hpp new file mode 100644 index 00000000..926dc484 --- /dev/null +++ b/Include/auROXTL/auHashMap.hpp @@ -0,0 +1,18 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auHashMap.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_AU_HASH_MAP) + #define AURORA_RUNTIME_AU_HASH_MAP std::unordered_map +#endif + +template +using AuHashMap = AURORA_RUNTIME_AU_HASH_MAP; + +template +using AuHashMapEx = AURORA_RUNTIME_AU_HASH_MAP; \ No newline at end of file diff --git a/Include/auROXTL/auList.hpp b/Include/auROXTL/auList.hpp new file mode 100644 index 00000000..005e2ecc --- /dev/null +++ b/Include/auROXTL/auList.hpp @@ -0,0 +1,30 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auList.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_AU_LIST) + #define AURORA_RUNTIME_AU_LIST std::vector +#endif + +#if defined(_CPPSHARP) || defined(_AURORA_NO_SPECIAL_ARRAY_OPTIMIAZATION) || (!defined(_AUHAS_AURORARUNTIME) && !defined(AURORA_ENGINE_KERNEL)) + +template +using AuList = AURORA_RUNTIME_AU_LIST; + +#else + +namespace Aurora::Memory +{ + template + struct SpeedyArrayAllocator; +} + +template +using AuList = AuConditional_t, AURORA_RUNTIME_AU_LIST, AURORA_RUNTIME_AU_LIST>>; + +#endif \ No newline at end of file diff --git a/Include/auROXTL/auMagicUtils.hpp b/Include/auROXTL/auMagicUtils.hpp new file mode 100644 index 00000000..d781c33a --- /dev/null +++ b/Include/auROXTL/auMagicUtils.hpp @@ -0,0 +1,71 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auMagicUtils.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +static constexpr auline AuUInt32 AuConvertMagicTag32(const char buffer[4]) +{ + AuUInt32 magic {}; + if (Aurora::Build::kCurrentEndian == Aurora::Build::ECPUEndian::eCPULittle) + { + magic |= AuUInt32(buffer[0]); + magic |= AuUInt32(buffer[1]) << 8; + magic |= AuUInt32(buffer[2]) << 16; + magic |= AuUInt32(buffer[3]) << 24; + // LE will look alright in memory dumps + // MSFT uses tags that read back the initial string value when read back hex ints + // I prefer binary streams and file headers contain a 4x or 8x ascii char headers (eg. LuaX) + } + else + { + // Lazy reinterpret cast reads will always be flipped + // Assume byte buffers read/write machine endian + // Assume *reinterpret_cast returns machine endian + // BE needs to be flipped in memory + // BE will look fine in memory dumps + // BE will also look fine in stack/variable dumps when printed in hex + magic |= AuUInt32(buffer[4]); + magic |= AuUInt32(buffer[2]) << 8; + magic |= AuUInt32(buffer[1]) << 16; + magic |= AuUInt32(buffer[0]) << 24; + } + // Determinstic across platforms, perhaps unexpected by endian normalized streams + // When asserting read(noEndian) against a tag, an endian swap would cause the + // assertion to fail, thus providing you with the endian match check + // This step is delegated to a de-facto machine endian buffer builder + // ByteBuffers that normalize for endianness continue to work with tags + // irrespective of reader/writer endianness + return magic; +} + +static constexpr auline AuUInt64 AuConvertMagicTag64(const char buffer[8]) +{ + AuUInt64 magic {}; + if (Aurora::Build::kCurrentEndian == Aurora::Build::ECPUEndian::eCPULittle) + { + magic |= AuUInt64(buffer[0]); + magic |= AuUInt64(buffer[1]) << 8; + magic |= AuUInt64(buffer[2]) << 16; + magic |= AuUInt64(buffer[3]) << 24; + magic |= AuUInt64(buffer[4]) << 32; + magic |= AuUInt64(buffer[5]) << 40; + magic |= AuUInt64(buffer[6]) << 48; + magic |= AuUInt64(buffer[7]) << 56; + } + else + { + magic |= AuUInt64(buffer[7]); + magic |= AuUInt64(buffer[6]) << 8; + magic |= AuUInt64(buffer[5]) << 16; + magic |= AuUInt64(buffer[4]) << 24; + magic |= AuUInt64(buffer[3]) << 32; + magic |= AuUInt64(buffer[2]) << 40; + magic |= AuUInt64(buffer[1]) << 48; + magic |= AuUInt64(buffer[0]) << 56; + } + return magic; +} \ No newline at end of file diff --git a/Include/auROXTL/auMemory.hpp b/Include/auROXTL/auMemory.hpp new file mode 100644 index 00000000..5d16b20b --- /dev/null +++ b/Include/auROXTL/auMemory.hpp @@ -0,0 +1,44 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auMemory.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_MEMCMP) + #define AURORA_RUNTIME_MEMCMP std::memcmp +#endif + +static auline int AuMemcmp(const void *dest, const void *src, size_t n) +{ + return AURORA_RUNTIME_MEMCMP(dest, src, n); +} + +#if !defined(AURORA_RUNTIME_MEMSET) + #define AURORA_RUNTIME_MEMSET std::memset +#endif + +static auline void *AuMemset(void *dest, AuUInt8 c, size_t n) +{ + return AURORA_RUNTIME_MEMSET(dest, c, n); +} + +#if !defined(AURORA_RUNTIME_MEMCPY) + #define AURORA_RUNTIME_MEMCPY std::memcpy +#endif + +static auline void *AuMemcpy(void *dest, const void *src, size_t n) +{ + return AURORA_RUNTIME_MEMCPY(dest, src, n); +} + +#if !defined(AURORA_RUNTIME_MEMMOVE) + #define AURORA_RUNTIME_MEMMOVE std::memmove +#endif + +static auline void *AuMemmove(void *dest, const void *src, size_t n) +{ + return AURORA_RUNTIME_MEMMOVE(dest, src, n); +} \ No newline at end of file diff --git a/Include/auROXTL/auMemoryModel.hpp b/Include/auROXTL/auMemoryModel.hpp new file mode 100644 index 00000000..2d05655b --- /dev/null +++ b/Include/auROXTL/auMemoryModel.hpp @@ -0,0 +1,132 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auMemoryModel.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#include "auTypes.hpp" + +#if !defined(AURORA_RUNTIME_AU_SHARED_PTR) + #define AURORA_RUNTIME_AU_SHARED_PTR std::shared_ptr +#endif + +#if !defined(AURORA_RUNTIME_AU_WEAK_PTR) + #define AURORA_RUNTIME_AU_WEAK_PTR std::weak_ptr +#endif + +template +using AuWPtr = AURORA_RUNTIME_AU_WEAK_PTR; + +#if !defined(AURORA_RUNTIME_AU_UNIQUE_PTR) + #define AURORA_RUNTIME_AU_UNIQUE_PTR std::unique_ptr +#endif + +#if !defined(AURORA_RUNTIME_AU_DEFAULT_DELETER) + #define AURORA_RUNTIME_AU_DEFAULT_DELETER std::default_delete +#endif + +template +using AuDefaultDeleter = AURORA_RUNTIME_AU_DEFAULT_DELETER; + +#include + +template +using AuSPtr = typename Aurora::Memory::ExSharedPtr>; + +template +using AuUPtr = AURORA_RUNTIME_AU_UNIQUE_PTR; + +#if !defined(AU_AuEnableSharedFromThis) +#define AU_AuEnableSharedFromThis + +template +struct AuEnableSharedFromThis : Aurora::Memory::ExSharedFromThis> +{}; + +#endif + +#if !defined(AURORA_RUNTIME_MAKE_SHARED) + #define AURORA_RUNTIME_MAKE_SHARED std::make_shared +#endif + +template +static auline AuSPtr AuMakeShared(Args&&... args) +{ + try + { + return AURORA_RUNTIME_MAKE_SHARED(AuForward(args)...); + } + catch (...) + { + return {}; + } +} + +template +static auline AuSPtr AuMakeSharedArray(AuUInt count) +{ + try + { + #if defined(AU_LANG_CPP_20) && !defined(AURORA_COMPILER_MSVC) + return AURORA_RUNTIME_AU_SHARED_PTR(count); + #else + return AURORA_RUNTIME_AU_SHARED_PTR(new T[count], AuDefaultDeleter()); + #endif + } + catch (...) + { + return {}; + } +} + +template +static AuSPtr AuUnsafeRaiiToShared(T *in) +{ + return AuSPtr(in, [](T *) + {}); +} + +template +static AuSPtr AuUnsafeRaiiToShared(const AuUPtr &in) +{ + return AuSPtr(in.get(), [](T *) + {}); +} + +template +static constexpr int AuArraySize(const T(&array)[Z]) +{ + return Z; +} + +#if defined(DEBUG) || defined(STAGING) + +template +static auline void AU_NORETURN SysPanic(T... args); + +template +static void auline AuSafeDelete(T *in) +{ + static_assert(AuIsBaseOf_v>, "Couldn't not safe delete from type T because it is not derived from Z"); + auto cast = dynamic_cast(in); + if (cast == nullptr) + { + Z re; + SysPanic("Tried to free: 0x{:x}, type \"{}\" was not inherited from \"{}\"", AuUInt(in), typeid(in).name(), typeid(re).name()); + } + delete cast; +} + +#else + +template +static void auline AuSafeDelete(T *in) +{ + static_assert(AuIsBaseOf_v>, "Couldn't not safe delete from type T because it is not derived from Z"); + delete static_cast(in); +} + +#endif \ No newline at end of file diff --git a/Include/auROXTL/auNumberUtils.hpp b/Include/auROXTL/auNumberUtils.hpp new file mode 100644 index 00000000..4354c9b0 --- /dev/null +++ b/Include/auROXTL/auNumberUtils.hpp @@ -0,0 +1,20 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auNumberUtils.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +template +constexpr const T AuMin(const T &a, const T &b) +{ + return a < b ? a : b; +} + +template +constexpr const T AuMax(const T &a, const T &b) +{ + return a < b ? b : a; +} \ No newline at end of file diff --git a/Include/auROXTL/auOptional.hpp b/Include/auROXTL/auOptional.hpp new file mode 100644 index 00000000..5addae5f --- /dev/null +++ b/Include/auROXTL/auOptional.hpp @@ -0,0 +1,15 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auOptional.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +#if !defined(AURORA_RUNTIME_AU_OPTIONAL) + #define AURORA_RUNTIME_AU_OPTIONAL std::optional +#endif + +template +using AuOptional = AURORA_RUNTIME_AU_OPTIONAL; \ No newline at end of file diff --git a/Include/auROXTL/auPosixUtils.hpp b/Include/auROXTL/auPosixUtils.hpp new file mode 100644 index 00000000..f06cfa79 --- /dev/null +++ b/Include/auROXTL/auPosixUtils.hpp @@ -0,0 +1,9 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auPosixUtils.hpp + Date: 2022-2-6 + Author: Reece +***/ +#pragma once + diff --git a/Include/auROXTL/auString.hpp b/Include/auROXTL/auString.hpp new file mode 100644 index 00000000..6586be8d --- /dev/null +++ b/Include/auROXTL/auString.hpp @@ -0,0 +1,12 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auString.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +//#include "tinyutf8.h" +//#define AU_STRING_IS_TINYUTF_EXPERIMENT +using AuString = std::string; \ No newline at end of file diff --git a/Include/auROXTL/auStringUtils.hpp b/Include/auROXTL/auStringUtils.hpp new file mode 100644 index 00000000..70495307 --- /dev/null +++ b/Include/auROXTL/auStringUtils.hpp @@ -0,0 +1,119 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auStringUtils.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +static auline bool AuStringContains(const AuString &value, const AuString &subpattern) +{ + return value.find(subpattern) != AuString::npos; +} + +static auline bool AuEndsWith(AuString const &value, AuString const &ending) +{ + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + +static auline bool AuStartsWith(AuString const &value, AuString const &starting) +{ +#if defined(AU_STRING_IS_TINYUTF_EXPERIMENT) + return value.starts_with(starting); +#else + return value.rfind(starting, 0) == 0; +#endif +} + +#if defined(AU_STRING_IS_TINYUTF_EXPERIMENT) + +static AuString AuStringTransform(const AuString &in, const AuSupplierConsumer &out) +{ + AuString cpy = in; + for (int i = 0; i < cpy.length(); i++) + { + cpy[i] = out(cpy[i]); + } + return cpy; +} + +static auline AuString AuToUpper(const AuString &in) +{ + return AuStringTransform(in, std::toupper); +} + + +static auline AuString AuToLower(const AuString &in) +{ + return AuStringTransform(in, std::toupper); +} + +#else + +template +static auline AuString AuToStringASCIIOp(T op, const AuString &in) +{ + AuString ret; + ret.resize(in.size()); + std::transform(in.begin(), in.end(), ret.begin(), [=](const char &c) + { + return op(c); + }); + return ret; +} + +static auline AuString AuToLower(const AuString &in) +{ + return AuToStringASCIIOp(std::tolower, in); +} + +static auline AuString AuToUpper(const AuString &in) +{ + return AuToStringASCIIOp(std::toupper, in); +} +#endif + +static auline AuString AuReplaceAll(AuString &str, const AuString &from, const AuString &to) +{ + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + return str; // :( +} + +// i told myself not to copy this, required a split function twice, now here we are :D +static auline AuList AuSplitString(const AuString &str, const AuString &delim, bool ignoreEmpty = true) +{ + AuList tokens; + AuUInt prev = 0, pos = 0; + do + { + pos = str.find(delim, prev); + if (pos == AuString::npos) pos = str.length(); + auto token = str.substr(prev, pos - prev); + if ((!token.empty()) && ignoreEmpty) tokens.push_back(token); + prev = pos + delim.length(); + } + while (pos < str.length() && prev < str.length()); + return tokens; +} + +#if !defined(AURORA_RUNTIME_TO_STRING) + #define AURORA_RUNTIME_TO_STRING std::to_string +#endif + +template +static auline AuString AuToString(const T &obj) +{ +#if defined(_AUHAS_FMT) + // locale independent and better optimized! + return fmt::format("{}", obj); +#else + return AURORA_RUNTIME_TO_STRING(obj); +#endif +} \ No newline at end of file diff --git a/Include/auROXTL/auTemplateMeta.hpp b/Include/auROXTL/auTemplateMeta.hpp new file mode 100644 index 00000000..cae86d57 --- /dev/null +++ b/Include/auROXTL/auTemplateMeta.hpp @@ -0,0 +1,215 @@ +/*** + Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: auTemplateMeta.hpp + Date: 2022-2-1 + Author: Reece +***/ +#pragma once + +template +struct AuBoolType +{ + static constexpr bool value = v; + using value_type = bool; + using type = AuBoolType; + + constexpr operator value_type() const noexcept + { + return value; + } + + constexpr value_type operator()() const noexcept + { + return value; + } +}; + +using AuFalseType = AuBoolType; +using AuTrueType = AuBoolType; + +template +using AuToValueType_t = typename T::value_type; + +template +using AuToElementType_t = typename T::yelement_type; + +template +struct AuIsSame : AuFalseType +{}; + +template +struct AuIsSame : AuTrueType +{}; + +template +inline constexpr bool AuIsSame_v = AuIsSame::value; + +namespace _audetail +{ + template + AuBoolType::value> IsClass(int T:: *); + + template + AuFalseType IsClass(...); + + template + AuTrueType TestIsPtrConvertible(const volatile B *); + template + AuFalseType TestIsPtrConvertible(const volatile void *); + + template + auto TestIsBaseOf(...)->AuTrueType; + + template + auto TestIsBaseOf(int) -> decltype(TestIsPtrConvertible(static_cast(nullptr))); +} + +template +struct AuIsClass : decltype(_audetail::IsClass(nullptr)) +{}; + +template +inline constexpr bool AuIsClass_v = AuIsClass::value; + +template +struct AuIsBaseOf : + AuBoolType< + AuIsClass_v && + AuIsClass_v && + decltype(_audetail::TestIsBaseOf(0))::value + > +{}; + +template +inline constexpr bool AuIsBaseOf_v = AuIsBaseOf::value; + +template +inline constexpr bool AuIsPointer_v = false; + +template +inline constexpr bool AuIsPointer_v = true; + +template +inline constexpr bool AuIsPointer_v = true; + +template +inline constexpr bool AuIsPointer_v = true; + +template +inline constexpr bool AuIsPointer_v = true; + +template +struct AuRemovePointer +{ + typedef T type; +}; + +template +struct AuRemovePointer +{ + typedef T type; +}; + +template +struct AuRemovePointer +{ + typedef T type; +}; + +template +struct AuRemovePointer +{ + typedef T type; +}; + +template +struct AuRemovePointer +{ + typedef T type; +}; + +template +using AuRemovePointer_t = typename AuRemovePointer::type; + +template +using AuIsVoid = AuIsSame; + +template +inline constexpr bool AuIsVoid_v = AuIsVoid::value; + +template +struct AuRemoveReference +{ + using type = T; +}; + +template +struct AuRemoveReference +{ + using type = T; +}; + +template +struct AuRemoveReference +{ + using type = T; +}; + +template +using AuRemoveReference_t = typename AuRemoveReference::type; + +template +struct AuRemoveConst +{ + typedef T type; +}; + +template +struct AuRemoveConst +{ + typedef T type; +}; + +template +using AuRemoveConst_t = typename AuRemoveConst::type; + +template +struct AuEnableIf +{}; + +template +struct AuEnableIf +{ + using type = T; +}; + +template +using AuEnableIf_t = typename AuEnableIf::type; + +template +struct AuConditional +{ + using type = T; +}; + +template +struct AuConditional +{ + using type = T2; +}; + +template +using AuConditional_t = typename AuConditional::type; + +template class base, typename derived> +struct is_base_of_template_impl_au +{ + template + static constexpr AuTrueType test(const base *); + static constexpr AuFalseType test(...); + using type = decltype(test(std::declval())); +}; + +template