├── .appveyor ├── build.bat └── setup_environment.bat ├── .clang-format ├── .gitignore ├── .gitmodules ├── .travis.yml ├── AMBuildScript ├── README.md ├── amtl ├── AMBuilder ├── am-allocator-policies.h ├── am-arithmetic.h ├── am-assert.h ├── am-bits.h ├── am-cxx.h ├── am-deque.h ├── am-enum.h ├── am-fixedarray.h ├── am-flags.h ├── am-float.h ├── am-function.h ├── am-hashmap.h ├── am-hashset.h ├── am-hashtable.h ├── am-inlinelist.h ├── am-linking.h ├── am-maybe.h ├── am-mutex.h ├── am-platform.h ├── am-priority-queue.h ├── am-raii.h ├── am-refcounting-threadsafe.h ├── am-refcounting.h ├── am-storagebuffer.h ├── am-string.h ├── am-thread.h ├── am-threadlocal.h ├── am-time.h ├── am-unused.h ├── am-utility.h ├── am-vector.h ├── experimental │ ├── am-argparser.cpp │ └── am-argparser.h └── os │ ├── am-fsutil-posix.h │ ├── am-fsutil-windows.h │ ├── am-fsutil.h │ ├── am-path.h │ ├── am-shared-library.h │ └── am-system-errors.h ├── appveyor.yml ├── checkout-deps.sh ├── compat └── stdcxx.cpp ├── configure.py ├── tests ├── AMBuild.tests ├── main.cpp ├── runner.h ├── test-argparser.cpp ├── test-bits.cpp ├── test-callable.cpp ├── test-deque.cpp ├── test-flags.cpp ├── test-hashmap.cpp ├── test-inlinelist.cpp ├── test-priority-queue.cpp ├── test-raii.cpp ├── test-refcounting.cpp ├── test-string.cpp ├── test-system.cpp ├── test-threadlocal-threaded.cpp ├── test-threadlocal-unthreaded.cpp ├── test-time.cpp └── test-vector.cpp └── tools └── restyler ├── .clang-format ├── .gitignore ├── Makefile ├── README.md ├── amstyler.cpp └── test ├── amstyler_in.cpp └── amstyler_out.cpp /.appveyor/build.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 3 | mkdir opt32 && cd opt32 4 | python ..\configure.py --enable-optimize 5 | ambuild 6 | cd .. 7 | opt32\dist\testrunner.exe 8 | -------------------------------------------------------------------------------- /.appveyor/setup_environment.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | SET PYTHON=c:\python33 3 | SET PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% 4 | git submodule update --init 5 | git clone https://github.com/alliedmodders/ambuild ambuild 6 | pip install ./ambuild 7 | chdir /D "%APPVEYOR_BUILD_FOLDER%" 8 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | Language: Cpp 3 | AllowAllParametersOfDeclarationOnNextLine: false 4 | AllowShortCaseLabelsOnASingleLine: false 5 | AllowShortFunctionsOnASingleLine: None 6 | AllowShortIfStatementsOnASingleLine: false 7 | AllowShortLoopsOnASingleLine: false 8 | AlwaysBreakAfterReturnType: TopLevelDefinitions 9 | AlwaysBreakBeforeMultilineStrings: true 10 | AccessModifierOffset: -2 11 | BinPackArguments: true 12 | BinPackParameters: true 13 | BraceWrapping: 14 | AfterClass: true 15 | AfterControlStatement: false 16 | AfterEnum: false 17 | AfterFunction: false 18 | AfterNamespace: false 19 | AfterObjCDeclaration: false 20 | AfterStruct: false 21 | AfterUnion: false 22 | AfterExternBlock: false 23 | BeforeCatch: false 24 | BeforeElse: false 25 | IndentBraces: false 26 | SplitEmptyFunction: false 27 | SplitEmptyRecord: true 28 | SplitEmptyNamespace: true 29 | BreakBeforeBraces: Custom 30 | BreakBeforeInheritanceComma: false 31 | BreakStringLiterals: true 32 | ColumnLimit: 100 33 | BreakConstructorInitializers: BeforeComma 34 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 35 | ConstructorInitializerIndentWidth: 1 36 | ContinuationIndentWidth: 4 37 | Cpp11BracedListStyle: true 38 | IncludeBlocks: Preserve 39 | IncludeCategories: 40 | - Regex: '^' 41 | Priority: 2 42 | - Regex: '^<.*\.h>' 43 | Priority: 1 44 | - Regex: '^<.*' 45 | Priority: 2 46 | - Regex: '.*' 47 | Priority: 3 48 | IncludeIsMainRegex: '([-_](test|unittest))?$' 49 | IndentCaseLabels: true 50 | IndentPPDirectives: AfterHash 51 | IndentWidth: 4 52 | MaxEmptyLinesToKeep: 1 53 | ReflowComments: false 54 | SortIncludes: true 55 | SortUsingDeclarations: true 56 | SpacesBeforeTrailingComments: 1 57 | SpacesInContainerLiterals: false 58 | Standard: Cpp11 59 | TabWidth: 8 60 | UseTab: Never 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gdb_history 2 | obj-linux-x86_64 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/googletest"] 2 | path = third_party/googletest 3 | url = https://github.com/google/googletest 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | git: 2 | depth: 3 3 | 4 | sudo: false 5 | language: cpp 6 | 7 | matrix: 8 | fast_finish: true 9 | include: 10 | - os: linux 11 | dist: trusty 12 | sudo: false 13 | language: cpp 14 | addons: 15 | apt: 16 | sources: 17 | - ubuntu-toolchain-r-test 18 | packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-4.9-multilib'] 19 | env: 20 | - PATH="~/.local/bin:$PATH" 21 | - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8" 22 | 23 | - os: linux 24 | dist: trusty 25 | sudo: false 26 | language: cpp 27 | addons: 28 | apt: 29 | sources: 30 | - ubuntu-toolchain-r-test 31 | packages: ['clang-3.4', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-4.9-multilib'] 32 | env: 33 | - PATH="~/.local/bin:$PATH" 34 | - MATRIX_EVAL="CC=clang && CXX=clang++" 35 | 36 | - os: osx 37 | osx_image: xcode6.4 38 | sudo: true 39 | language: cpp 40 | env: 41 | - PATH="~/Library/Python/2.7/bin:$PATH" 42 | - MATRIX_EVAL="CC=clang && CXX=clang++" 43 | 44 | - os: linux 45 | dist: bionic 46 | sudo: false 47 | language: cpp 48 | addons: 49 | apt: 50 | packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-multilib', 'clang'] 51 | env: 52 | - PATH="~/.local/bin:$PATH" 53 | - MATRIX_EVAL="CC=clang && CXX=clang++" 54 | 55 | - os: linux 56 | dist: bionic 57 | sudo: false 58 | language: cpp 59 | addons: 60 | apt: 61 | packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-multilib', 'g++'] 62 | env: 63 | - PATH="~/.local/bin:$PATH" 64 | - MATRIX_EVAL="CC=gcc && CXX=g++" 65 | 66 | before_script: 67 | - CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/checkout-deps.sh && cd $CHECKOUT_DIR 68 | script: 69 | - eval "${MATRIX_EVAL}" 70 | - eval "${CC} --version" 71 | - eval "${CXX} --version" 72 | 73 | - mkdir build-opt && cd build-opt 74 | - python ../configure.py --enable-optimize 75 | - ambuild 76 | - ./dist/testrunner 77 | - cd .. 78 | 79 | - mkdir build-debug && cd build-debug 80 | - python ../configure.py --enable-debug 81 | - ambuild 82 | - ./dist/testrunner 83 | -------------------------------------------------------------------------------- /AMBuildScript: -------------------------------------------------------------------------------- 1 | # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: 2 | import os 3 | import sys 4 | 5 | class KEConfig(object): 6 | def __init__(self): 7 | pass 8 | 9 | def configure(self): 10 | cxx = builder.DetectCxx() 11 | 12 | builder.cxx = cxx 13 | builder.dist_folder = builder.AddFolder('dist') 14 | 15 | if cxx.like('gcc'): 16 | if cxx.target.platform != 'windows': 17 | if cxx.version >= 'gcc-8.0' or cxx.version >= 'clang-5.0': 18 | cxx.cxxflags += ['-std=c++17'] 19 | else: 20 | cxx.cxxflags += ['-std=c++14'] 21 | 22 | cxx.defines += [ 23 | 'stricmp=strcasecmp', 24 | '_stricmp=strcasecmp', 25 | '_snprintf=snprintf', 26 | '_vsnprintf=vsnprintf', 27 | ] 28 | cxx.linkflags += ['-lpthread'] 29 | if cxx.target.platform != 'mac': 30 | cxx.linkflags += ['-lrt'] 31 | else: 32 | cxx.cxxflags += [ 33 | '-std=c++14', 34 | '-fms-compatibility-version=19', 35 | ] 36 | 37 | cxx.cflags += [ 38 | '-pipe', 39 | '-Wall', 40 | '-Werror', 41 | ] 42 | 43 | cxx.cflags += ['-fvisibility=hidden'] 44 | cxx.cxxflags += ['-fvisibility-inlines-hidden'] 45 | # -Wunused-function breaks test_flags.cpp 46 | cxx.cxxflags += ['-Wno-unused-function'] 47 | if cxx.like('clang'): 48 | cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] 49 | elif cxx.like('gcc'): 50 | cxx.cxxflags += ['-Wformat-truncation=0'] 51 | 52 | cxx.cxxflags += [ 53 | '-fno-exceptions', 54 | '-fno-threadsafe-statics', 55 | ] 56 | 57 | cxx.cflags += ['-mfpmath=sse'] 58 | elif cxx.like('msvc'): 59 | if builder.options.debug == '1': 60 | cxx.cflags += ['/MTd'] 61 | cxx.linkflags += ['/NODEFAULTLIB:libcmt'] 62 | else: 63 | cxx.cflags += ['/MT'] 64 | cxx.defines += [ 65 | '_CRT_SECURE_NO_DEPRECATE', 66 | '_CRT_SECURE_NO_WARNINGS', 67 | '_CRT_NONSTDC_NO_DEPRECATE', 68 | '_ITERATOR_DEBUG_LEVEL=0', 69 | ] 70 | cxx.cflags += [ 71 | '/W3', 72 | ] 73 | cxx.cxxflags += [ 74 | '/EHsc', 75 | '/GR-', 76 | '/TP', 77 | ] 78 | cxx.linkflags += [ 79 | '/MACHINE:X86', 80 | 'kernel32.lib', 81 | 'user32.lib', 82 | 'gdi32.lib', 83 | 'winspool.lib', 84 | 'comdlg32.lib', 85 | 'advapi32.lib', 86 | 'shell32.lib', 87 | 'ole32.lib', 88 | 'oleaut32.lib', 89 | 'uuid.lib', 90 | 'odbc32.lib', 91 | 'odbccp32.lib', 92 | ] 93 | 94 | # Optimization 95 | if builder.options.opt == '1': 96 | cxx.defines += ['NDEBUG'] 97 | if cxx.like('gcc'): 98 | cxx.cflags += ['-O3'] 99 | elif cxx.like('msvc'): 100 | cxx.cflags += ['/Ox'] 101 | cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] 102 | 103 | # Debugging 104 | if builder.options.debug == '1': 105 | cxx.defines += ['DEBUG', '_DEBUG'] 106 | if cxx.like('msvc'): 107 | cxx.cflags += ['/Od', '/RTC1'] 108 | if cxx.version >= 1600: 109 | cxx.cflags += ['/d2Zi+'] 110 | 111 | # This needs to be after our optimization flags which could otherwise disable it. 112 | if cxx.like('msvc'): 113 | # Don't omit the frame pointer. 114 | cxx.cflags += ['/Oy-'] 115 | 116 | # Platform-specifics 117 | if cxx.target.platform == 'linux': 118 | cxx.defines += ['_LINUX', 'POSIX'] 119 | if cxx.like('gcc'): 120 | cxx.linkflags += ['-static-libgcc'] 121 | elif cxx.like('clang'): 122 | cxx.linkflags += ['-lgcc_eh'] 123 | elif cxx.target.platform == 'mac': 124 | cxx.defines += ['OSX', '_OSX', 'POSIX'] 125 | cxx.cflags += ['-mmacosx-version-min=10.7'] 126 | cxx.linkflags += [ 127 | '-mmacosx-version-min=10.7', 128 | '-lstdc++', 129 | '-stdlib=libc++', 130 | ] 131 | cxx.cxxflags += ['-stdlib=libc++'] 132 | elif cxx.target.platform == 'windows': 133 | cxx.defines += ['WIN32', '_WINDOWS'] 134 | 135 | def Program(self, context, name): 136 | compiler = context.cxx.clone() 137 | binary = compiler.Program(name) 138 | return binary 139 | 140 | def StaticLibrary(self, context, name): 141 | compiler = context.cxx.clone() 142 | binary = compiler.StaticLibrary(name) 143 | return binary 144 | 145 | KE = KEConfig() 146 | KE.configure() 147 | 148 | KE.libamtl = builder.Build('amtl/AMBuilder', { 149 | 'Configure': lambda builder, name: KE.StaticLibrary(builder, name), 150 | }) 151 | KE.libamtl = KE.libamtl.binary 152 | 153 | builder.Build( 154 | [ 155 | 'tests/AMBuild.tests', 156 | ], 157 | { 158 | 'KE': KE, 159 | } 160 | ) 161 | -------------------------------------------------------------------------------- /amtl/AMBuilder: -------------------------------------------------------------------------------- 1 | # vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: 2 | # 3 | # Copyright (C) 2004-2012 David Anderson 4 | # 5 | # This file is part of SourcePawn. 6 | # 7 | # SourcePawn is free software: you can redistribute it and/or modify it under 8 | # the terms of the GNU General Public License as published by the Free 9 | # Software Foundation, either version 3 of the License, or (at your option) 10 | # any later version. 11 | # 12 | # SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # SourcePawn. If not, see http://www.gnu.org/licenses/. 18 | # 19 | import os 20 | 21 | binary = Configure(builder, 'libamtl') 22 | 23 | amtl_path = os.path.join(builder.sourcePath, builder.sourceFolder, '..') 24 | 25 | binary.compiler.includes += [ 26 | amtl_path, 27 | ] 28 | binary.sources += [ 29 | 'experimental/am-argparser.cpp', 30 | ] 31 | 32 | rvalue = builder.Add(binary) 33 | -------------------------------------------------------------------------------- /amtl/am-allocator-policies.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_allocatorpolicies_h_ 31 | #define _include_amtl_allocatorpolicies_h_ 32 | 33 | #include 34 | #include 35 | 36 | namespace ke { 37 | 38 | // The default system allocator policy will crash on out-of-memory. 39 | class SystemAllocatorPolicy 40 | { 41 | public: 42 | void reportOutOfMemory() { 43 | fprintf(stderr, "OUT OF MEMORY\n"); 44 | abort(); 45 | } 46 | void reportAllocationOverflow() { 47 | fprintf(stderr, "OUT OF MEMORY\n"); 48 | abort(); 49 | } 50 | 51 | public: 52 | void am_free(void* memory) { 53 | #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) 54 | free(memory); 55 | #else 56 | ::free(memory); 57 | #endif 58 | } 59 | void* am_malloc(size_t bytes) { 60 | #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) 61 | void* ptr = malloc(bytes); 62 | #else 63 | void* ptr = ::malloc(bytes); 64 | #endif 65 | if (!ptr) 66 | reportOutOfMemory(); 67 | return ptr; 68 | } 69 | }; 70 | 71 | } // namespace ke 72 | 73 | #endif // _include_amtl_allocatorpolicies_h_ 74 | -------------------------------------------------------------------------------- /amtl/am-arithmetic.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_bits_h_ 30 | #define _include_amtl_bits_h_ 31 | 32 | #include 33 | 34 | namespace ke { 35 | 36 | static inline bool 37 | TryUint64Multiply(uint64_t left, uint64_t right, uint64_t* out) 38 | { 39 | uint64_t r = left * right; 40 | if (r != 0 && ((r / left) != right)) 41 | return false; 42 | 43 | *out = r; 44 | return true; 45 | } 46 | 47 | static inline bool 48 | TryUint32Add(uint32_t left, uint32_t right, uint32_t* out) 49 | { 50 | if (left + right < std::max(left, right)) 51 | return false; 52 | *out = left + right; 53 | return true; 54 | } 55 | 56 | static inline bool 57 | TryUint64Add(uint64_t left, uint64_t right, uint64_t* out) 58 | { 59 | if (left + right < std::max(left, right)) 60 | return false; 61 | *out = left + right; 62 | return true; 63 | } 64 | 65 | } // namespace ke 66 | 67 | #endif // _include_amtl_bits_h_ 68 | -------------------------------------------------------------------------------- /amtl/am-assert.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_assert_h_ 31 | #define _include_amtl_assert_h_ 32 | 33 | #include 34 | #include 35 | 36 | #if !defined(NDEBUG) 37 | # define KE_RELEASE_ASSERT assert 38 | #else 39 | # define KE_RELEASE_ASSERT(cond) \ 40 | do { \ 41 | if (!(cond)) \ 42 | abort(); \ 43 | } while (0) 44 | #endif 45 | 46 | #endif // _include_amtl_assert_h_ 47 | -------------------------------------------------------------------------------- /amtl/am-cxx.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_cxx_support_h_ 30 | #define _include_amtl_cxx_support_h_ 31 | 32 | #if defined(__clang__) 33 | # if !(defined(__clang_major__) && defined(__clang_minor__)) 34 | # define KE_CLANG_MAJOR 1 35 | # define KE_CLANG_MINOR __GNUC_MINOR__ 36 | # else 37 | # if defined(__apple_build_version__) && clang_major__ > 3 38 | // 4.0 => 3.1, 4.1 => 3.2 39 | # if __clang_major__ == 4 40 | # define KE_CLANG_MAJOR 3 41 | # if __clang_minor__ == 0 42 | # define KE_CLANG_MINOR 1 43 | # else 44 | # define KE_CLANG_MINOR 2 45 | # endif 46 | // 5.0 => 3.3, 5.1 => 3.4 47 | # elif __clang_major__ == 5 48 | # define KE_CLANG_MAJOR 3 49 | # if __clang_minor__ == 0 50 | # define KE_CLANG_MINOR 3 51 | # else 52 | # define KE_CLANG_MINOR 4 53 | # endif 54 | # elif __clang_major__ == 6 55 | # define KE_CLANG_MAJOR 3 56 | # define KE_CLANG_MINOR 5 57 | # endif 58 | # endif 59 | # if !defined(KE_CLANG_MAJOR) 60 | # define KE_CLANG_MAJOR __clang_major__ 61 | # endif 62 | # if !defined(KE_CLANG_MINOR) 63 | # define KE_CLANG_MINOR __clang_minor__ 64 | # endif 65 | # endif 66 | 67 | // Done with horrible clang version detection. 68 | # define KE_CLANG_AT_LEAST(x, y) \ 69 | ((__clang_major__ > (x)) || (__clang_major__ == x && __clang_minor__ >= y)) 70 | 71 | # if !KE_CLANG_AT_LEAST(3, 4) 72 | # error "AMTL requires clang 3.4 or higher" 73 | # endif 74 | 75 | #elif defined(__GNUC__) 76 | # define KE_GCC_AT_LEAST(x, y) ((__GNUC__ > (x)) || (__GNUC__ == x && __GNUC_MINOR__ >= y)) 77 | 78 | # if !KE_GCC_AT_LEAST(4, 9) 79 | # error "AMTL requires GCC 4.9 or higher" 80 | # endif 81 | 82 | #elif defined(_MSC_VER) 83 | # if _MSC_VER < 1900 84 | # error "AMTL requires Microsoft Visual Studio 2015 or higher" 85 | # endif 86 | #else 87 | # error "Unrecognized compiler." 88 | #endif 89 | 90 | // Done with compiler feature detection. 91 | 92 | #if defined(_MSC_VER) 93 | // This feature has been around for long enough that we shouldn't have to 94 | // warn for it. 95 | # pragma warning(disable : 4351) 96 | #endif 97 | 98 | #if defined(_MSC_VER) 99 | # define KE_LINKONCE(x) __declspec(selectany) x 100 | #else 101 | # define KE_LINKONCE(x) x __attribute__((weak)) 102 | #endif 103 | 104 | #endif // _include_amtl_cxx_support_h_ 105 | -------------------------------------------------------------------------------- /amtl/am-deque.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #pragma once 30 | 31 | #include 32 | 33 | namespace ke { 34 | 35 | template 36 | static inline T PopBack(std::deque* deque) { 37 | T t = std::move(deque->back()); 38 | deque->pop_back(); 39 | return t; 40 | } 41 | 42 | template 43 | static inline T PopFront(std::deque* deque) { 44 | T t = std::move(deque->front()); 45 | deque->pop_front(); 46 | return t; 47 | } 48 | 49 | } // namespace ke 50 | -------------------------------------------------------------------------------- /amtl/am-enum.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_enum_h_ 30 | #define _include_amtl_enum_h_ 31 | 32 | #ifdef KE_ALLOW_STD_CXX 33 | # include 34 | #endif 35 | 36 | namespace ke { 37 | template 38 | struct enum_integral_type { 39 | #ifdef KE_ALLOW_STD_CXX 40 | using type = std::underlying_type::type; 41 | #else 42 | using type = __underlying_type(T); 43 | #endif 44 | }; 45 | } // namespace ke 46 | 47 | #define KE_DEFINE_ENUM_OPERATORS(EnumName) \ 48 | static inline EnumName operator|(const EnumName& left, const EnumName& right) { \ 49 | typedef ke::enum_integral_type::type int_type; \ 50 | return EnumName(int_type(left) | int_type(right)); \ 51 | } \ 52 | static inline EnumName operator&(const EnumName& left, const EnumName& right) { \ 53 | typedef ke::enum_integral_type::type int_type; \ 54 | return EnumName(int_type(left) & int_type(right)); \ 55 | } \ 56 | static inline EnumName operator^(const EnumName& left, const EnumName& right) { \ 57 | typedef ke::enum_integral_type::type int_type; \ 58 | return EnumName(int_type(left) ^ int_type(right)); \ 59 | } \ 60 | static inline EnumName operator~(const EnumName& flags) { \ 61 | typedef ke::enum_integral_type::type int_type; \ 62 | return EnumName(~int_type(flags)); \ 63 | } \ 64 | static inline EnumName& operator|=(EnumName& left, const EnumName& right) { \ 65 | return left = left | right; \ 66 | } \ 67 | static inline EnumName& operator&=(EnumName& left, const EnumName& right) { \ 68 | return left = left & right; \ 69 | } \ 70 | static inline EnumName& operator^=(EnumName& left, const EnumName& right) { \ 71 | return left = left ^ right; \ 72 | } \ 73 | static inline bool operator!(const EnumName& obj) { \ 74 | typedef ke::enum_integral_type::type int_type; \ 75 | return int_type(obj) == 0; \ 76 | } 77 | 78 | #define KE_DEFINE_ENUM_COMPARATORS(EnumName, Type) \ 79 | static inline bool operator==(const EnumName& left, const Type& right) { \ 80 | return Type(left) == right; \ 81 | } \ 82 | static inline bool operator==(const Type& left, const EnumName& right) { \ 83 | return left == Type(right); \ 84 | } \ 85 | static inline bool operator!=(const EnumName& left, const Type& right) { \ 86 | return Type(left) != right; \ 87 | } \ 88 | static inline bool operator!=(const Type& left, const EnumName& right) { \ 89 | return left != Type(right); \ 90 | } 91 | 92 | #endif // _include_amtl_enum_h_ 93 | -------------------------------------------------------------------------------- /amtl/am-fixedarray.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_fixedarray_h_ 30 | #define _include_amtl_fixedarray_h_ 31 | 32 | #include 33 | 34 | #include 35 | 36 | #include 37 | 38 | namespace ke { 39 | 40 | template 41 | class FixedArray : private AllocPolicy 42 | { 43 | public: 44 | FixedArray() : size_(0), data_(nullptr) 45 | {} 46 | FixedArray(size_t size, AllocPolicy = AllocPolicy()) { 47 | if (!allocate(size)) 48 | return; 49 | for (size_t i = 0; i < size_; i++) 50 | new (&data_[i]) T(); 51 | } 52 | FixedArray(const FixedArray& other) { 53 | if (!allocate(other.size())) 54 | return; 55 | for (size_t i = 0; i < size_; i++) 56 | new (&data_[i]) T(other[i]); 57 | } 58 | 59 | FixedArray(FixedArray&& other) { 60 | size_ = other.size_; 61 | data_ = other.data_; 62 | other.size_ = 0; 63 | other.data_ = nullptr; 64 | } 65 | 66 | template > 67 | explicit FixedArray(const std::vector& other) { 68 | if (!allocate(other.size())) 69 | return; 70 | 71 | for (size_t i = 0; i < size_; i++) 72 | new (&data_[i]) T(other[i]); 73 | } 74 | 75 | template > 76 | explicit FixedArray(std::vector&& other) { 77 | if (!allocate(other.size())) 78 | return; 79 | 80 | for (size_t i = 0; i < size_; i++) 81 | new (&data_[i]) T(std::move(other[i])); 82 | } 83 | 84 | ~FixedArray() { 85 | destruct(); 86 | deallocate(); 87 | } 88 | 89 | // This call may be skipped if the allocator policy is infallible. 90 | bool initialize() { 91 | return size_ == 0 || !!data_; 92 | } 93 | 94 | size_t size() const { 95 | return size_; 96 | } 97 | T& operator [](size_t index) { 98 | return at(index); 99 | } 100 | const T& operator [](size_t index) const { 101 | return at(index); 102 | } 103 | T& at(size_t index) { 104 | assert(index < size()); 105 | return data_[index]; 106 | } 107 | const T& at(size_t index) const { 108 | assert(index < size()); 109 | return data_[index]; 110 | } 111 | T& back() { 112 | assert(size() > 0); 113 | return data_[size() - 1]; 114 | } 115 | const T& back() const { 116 | assert(size() > 0); 117 | return data_[size() - 1]; 118 | } 119 | T* begin() { return data_; } 120 | T* end() { return data_ + size_; } 121 | const T* begin() const { return data_; } 122 | const T* end() const { return data_ + size_; } 123 | bool empty() const { return size_ == 0; } 124 | T* buffer() const { return data_; } 125 | 126 | FixedArray& operator =(const FixedArray& other) { 127 | destruct(); 128 | if (size_ != other.size()) { 129 | deallocate(); 130 | if (!allocate(other.size())) 131 | return *this; 132 | } 133 | for (size_t i = 0; i < size_; i++) 134 | new (&data_[i]) T(other[i]); 135 | return *this; 136 | } 137 | FixedArray& operator =(FixedArray&& other) { 138 | size_ = other.size_; 139 | data_ = other.data_; 140 | other.size_ = 0; 141 | other.data_ = nullptr; 142 | return *this; 143 | } 144 | 145 | bool operator ==(const FixedArray& other) const { 146 | if (other.size() != size()) 147 | return false; 148 | for (size_t i = 0; i < other.size(); i++) { 149 | if (at(i) != other.at(i)) 150 | return false; 151 | } 152 | return true; 153 | } 154 | bool operator !=(const FixedArray& other) const { 155 | return !(*this == other); 156 | } 157 | 158 | private: 159 | bool allocate(size_t size) { 160 | size_ = size; 161 | data_ = (T*)this->am_malloc(sizeof(T) * size_); 162 | return !!data_; 163 | } 164 | void destruct() { 165 | for (size_t i = 0; i < size_; i++) 166 | data_[i].~T(); 167 | } 168 | void deallocate() { 169 | this->am_free(data_); 170 | } 171 | 172 | private: 173 | size_t size_; 174 | T* data_; 175 | }; 176 | 177 | } // namespace ke 178 | 179 | #endif // _include_amtl_fixedarray_h_ 180 | -------------------------------------------------------------------------------- /amtl/am-flags.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_flags_h_ 30 | #define _include_amtl_flags_h_ 31 | 32 | #include 33 | 34 | namespace ke { 35 | 36 | // This is a wrapper intended for use with typed/scoped enums in C++11. Since 37 | // enum classes cannot be implicitly converted to bool, it makes patterns like 38 | // |if (x & y)| possible without !!. 39 | // 40 | // Note that we explicitly don't expose an operator T here, since it creates 41 | // ambiguous operator overloads if using KE_DEFINE_ENUM_OPERATORS. 42 | template 43 | class Flags 44 | { 45 | public: 46 | Flags() 47 | : value_(static_cast(0)) 48 | {} 49 | 50 | // Note: these are not explicit since we want operators below to support 51 | // both Flags and the underlying T type. 52 | Flags(const T& t) 53 | : value_(t) 54 | {} 55 | Flags(const Flags& other) 56 | : value_(other.value_) 57 | {} 58 | 59 | using IntType = typename enum_integral_type::type; 60 | 61 | explicit operator bool() const { 62 | return value_ != static_cast(0); 63 | } 64 | bool operator !() const { 65 | return value_ == static_cast(0); 66 | } 67 | 68 | IntType bits() const { 69 | return static_cast(value_); 70 | } 71 | T get() const { 72 | return value_; 73 | } 74 | 75 | Flags operator +(const Flags& other) const { 76 | return Flags(static_cast(bits() | other.bits())); 77 | } 78 | Flags operator -(const Flags& other) const { 79 | return Flags(static_cast(bits() & (bits() ^ other.bits()))); 80 | } 81 | Flags operator |(const Flags& other) const { 82 | return Flags(static_cast(bits() | other.bits())); 83 | } 84 | Flags operator &(const Flags& other) const { 85 | return Flags(static_cast(bits() & other.bits())); 86 | } 87 | Flags operator ^(const Flags& other) const { 88 | return Flags(static_cast(bits() ^ other.bits())); 89 | } 90 | bool operator ==(const Flags& other) const { 91 | return value_ == other.value_; 92 | } 93 | bool operator !=(const Flags& other) const { 94 | return value_ != other.value_; 95 | } 96 | 97 | Flags& operator +=(const Flags& other) { 98 | *this = *this + other; 99 | return *this; 100 | } 101 | Flags& operator -=(const Flags& other) { 102 | *this = *this - other; 103 | return *this; 104 | } 105 | Flags& operator |=(const Flags& other) { 106 | *this = *this | other; 107 | return *this; 108 | } 109 | Flags& operator &=(const Flags& other) { 110 | *this = *this & other; 111 | return *this; 112 | } 113 | Flags& operator ^=(const Flags& other) { 114 | *this = *this ^ other; 115 | return *this; 116 | } 117 | 118 | Flags& operator =(const Flags& other) { 119 | value_ = other.value_; 120 | return *this; 121 | } 122 | 123 | private: 124 | T value_; 125 | }; 126 | 127 | } // namespace ke 128 | 129 | #endif // _include_amtl_flags_h_ 130 | -------------------------------------------------------------------------------- /amtl/am-float.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_float_h_ 31 | #define _include_amtl_float_h_ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | namespace ke { 39 | 40 | static const uint32_t kFloat32ExponentMask = 0x7F800000; 41 | static const uint64_t kFloat64ExponentMask = 0x7FFF000000000000ULL; 42 | 43 | struct float32_bits { 44 | static const uint32_t kExponentMask = kFloat32ExponentMask; 45 | 46 | typedef uint32_t Bits; 47 | 48 | union layout { 49 | uint32_t bits; 50 | float value; 51 | }; 52 | 53 | static layout to_layout(float value) { 54 | layout impl; 55 | impl.value = value; 56 | return impl; 57 | } 58 | }; 59 | 60 | struct float64_bits { 61 | static const uint64_t kExponentMask = kFloat64ExponentMask; 62 | 63 | typedef uint64_t Bits; 64 | 65 | union layout { 66 | uint64_t bits; 67 | float value; 68 | }; 69 | 70 | static layout to_layout(float value) { 71 | layout impl; 72 | impl.value = value; 73 | return impl; 74 | } 75 | }; 76 | 77 | template 78 | struct float_bits; 79 | template <> 80 | struct float_bits : public float32_bits {}; 81 | template <> 82 | struct float_bits : public float64_bits {}; 83 | 84 | template 85 | static inline bool 86 | IsNaN(T v) 87 | { 88 | #ifdef _MSC_VER 89 | return !!_isnan(v); 90 | #else 91 | return std::isnan(v); 92 | #endif 93 | } 94 | 95 | template 96 | static inline bool 97 | IsInfinite(T value) 98 | { 99 | typedef float_bits Properties; 100 | typedef typename Properties::Bits Bits; 101 | Bits bits = Properties::to_layout(value).bits; 102 | return (bits & Properties::kExponentMask) == Properties::kExponentMask; 103 | }; 104 | 105 | // Performs the operation (x % y) where x and y are floating-point values. 106 | // 107 | // To compute a floating point modulus, this function returns "r", where r 108 | // satisfies the following equation: 109 | // 110 | // x = (I * y) + r 111 | // 112 | // Where I is an integer <= x, and r is a value less than y. If no such 113 | // integer I exists, the result is NaN. 114 | // 115 | // If x or y are NaN, the result is NaN. 116 | // If x is +/-Infinity, the result is NaN. 117 | // If y is 0, the result is NaN (as a divide by zero is implied). 118 | // 119 | // If y is Infinity, then r = x (and I = 0). 120 | // If x is +/-0, then r = +/-0. 121 | template 122 | static inline T 123 | FloatModulo(T left, T right) 124 | { 125 | #if defined(KE_WINDOWS) 126 | // Windows fmod() does not follow the contract above, in that: 127 | // 42 % Infinity => NaN, instead of 42, and 128 | // -0 % -N => 0, instead of -0. 129 | if ((!IsInfinite(left) && IsInfinite(right)) || (left == 0 && !IsInfinite(right))) { 130 | return left; 131 | } 132 | #endif 133 | 134 | return fmod(left, right); 135 | } 136 | 137 | } // namespace ke 138 | 139 | #endif // _include_amtl_float_h_ 140 | -------------------------------------------------------------------------------- /amtl/am-function.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above cloneright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above cloneright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_function_h_ 30 | #define _include_amtl_function_h_ 31 | 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | namespace ke { 39 | 40 | namespace impl { 41 | template 42 | class FunctionHolderBase 43 | { 44 | public: 45 | virtual ~FunctionHolderBase() {} 46 | virtual ReturnType invoke(ArgTypes&&... argv) const = 0; 47 | virtual FunctionHolderBase* clone(void* mem) const = 0; 48 | virtual FunctionHolderBase* move(void* mem) = 0; 49 | }; 50 | 51 | template 52 | class FunctionHolder : public FunctionHolderBase 53 | { 54 | typedef FunctionHolderBase BaseType; 55 | 56 | public: 57 | FunctionHolder(const FunctionHolder& other) 58 | : obj_(other.obj_) 59 | {} 60 | FunctionHolder(FunctionHolder&& other) 61 | : obj_(std::move(other.obj_)) 62 | {} 63 | FunctionHolder(const T& obj) 64 | : obj_(obj) 65 | {} 66 | FunctionHolder(T&& obj) 67 | : obj_(std::move(obj)) 68 | {} 69 | 70 | virtual ~FunctionHolder() {} 71 | virtual ReturnType invoke(ArgTypes&&... argv) const override { 72 | return obj_(std::forward(argv)...); 73 | } 74 | virtual BaseType* clone(void* mem) const override { 75 | if (!mem) 76 | return new FunctionHolder(*this); 77 | new (mem) FunctionHolder(*this); 78 | return (BaseType*)mem; 79 | } 80 | virtual BaseType* move(void* mem) override { 81 | new (mem) FunctionHolder(std::move(*this)); 82 | return (BaseType*)mem; 83 | } 84 | 85 | private: 86 | T obj_; 87 | }; 88 | 89 | static const size_t kMinFunctionInlineBufferSize = sizeof(void*) * 3; 90 | } // namespace impl 91 | 92 | template 93 | class Function; 94 | 95 | template 96 | class Function 97 | { 98 | typedef impl::FunctionHolderBase HolderType; 99 | 100 | public: 101 | Function() 102 | : impl_(nullptr) 103 | {} 104 | Function(decltype(nullptr)) 105 | : impl_(nullptr) 106 | {} 107 | Function(const Function& other) { 108 | assign(other); 109 | } 110 | Function(Function&& other) { 111 | move(std::forward(other)); 112 | } 113 | 114 | template 115 | Function(T&& obj) { 116 | assign(std::forward(obj)); 117 | } 118 | 119 | ~Function() { 120 | destroy(); 121 | } 122 | 123 | Function& operator =(decltype(nullptr)) { 124 | destroy(); 125 | impl_ = nullptr; 126 | return *this; 127 | } 128 | Function& operator =(const Function& other) { 129 | destroy(); 130 | assign(other); 131 | return *this; 132 | } 133 | Function& operator =(Function&& other) { 134 | destroy(); 135 | move(std::move(other)); 136 | return *this; 137 | } 138 | 139 | template 140 | Function& operator =(T&& other) { 141 | destroy(); 142 | assign(other); 143 | return *this; 144 | } 145 | 146 | explicit operator bool() const { 147 | return !!impl_; 148 | } 149 | 150 | ReturnType operator ()(ArgTypes... argv) const { 151 | assert(impl_); 152 | return impl_->invoke(std::forward(argv)...); 153 | } 154 | 155 | bool usingInlineStorage() const { 156 | return (void*)impl_ == &buffer_; 157 | } 158 | 159 | private: 160 | void destroy() { 161 | if (!impl_) 162 | return; 163 | 164 | if (usingInlineStorage()) 165 | impl_->~HolderType(); 166 | else 167 | delete impl_; 168 | } 169 | void zap() { 170 | destroy(); 171 | impl_ = nullptr; 172 | } 173 | 174 | void* inline_buffer() { 175 | return &buffer_; 176 | } 177 | 178 | void assign(const Function& other) { 179 | if (!other) 180 | impl_ = nullptr; 181 | else if (other.usingInlineStorage()) 182 | impl_ = other.impl_->clone(inline_buffer()); 183 | else 184 | impl_ = other.impl_->clone(nullptr); 185 | } 186 | 187 | void move(Function&& other) { 188 | if (!other) { 189 | impl_ = nullptr; 190 | } else if (other.usingInlineStorage()) { 191 | impl_ = other.impl_->move(inline_buffer()); 192 | other.zap(); 193 | } else { 194 | impl_ = other.impl_; 195 | other.impl_ = nullptr; 196 | } 197 | } 198 | 199 | template 200 | void assign(T&& obj) { 201 | typedef typename std::decay::type CallableType; 202 | typedef impl::FunctionHolder ImplType; 203 | 204 | if (sizeof(ImplType) <= sizeof(buffer_)) { 205 | impl_ = reinterpret_cast(inline_buffer()); 206 | new (inline_buffer()) ImplType(std::forward(obj)); 207 | } else { 208 | impl_ = new ImplType(std::forward(obj)); 209 | } 210 | } 211 | 212 | private: 213 | HolderType* impl_; 214 | union { 215 | double alignment_; 216 | char alias_[impl::kMinFunctionInlineBufferSize]; 217 | } buffer_; 218 | }; 219 | 220 | } // namespace ke 221 | 222 | #endif // _include_amtl_function_h_ 223 | -------------------------------------------------------------------------------- /amtl/am-hashmap.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_hashmap_h_ 31 | #define _include_amtl_hashmap_h_ 32 | 33 | #include 34 | 35 | #include 36 | 37 | namespace ke { 38 | 39 | // Template parameters: 40 | // 41 | // K - Key type. 42 | // V - Value type. 43 | // HashPolicy - A struct with a hash and comparator function for each lookup type: 44 | // static uint32_t hash(const Type& value); 45 | // static bool matches(const Type& value, const K& key); 46 | // 47 | // All types that match a given key, must compute the same hash. 48 | // 49 | // Note that like HashTable, a HashMap is not usable until init() has been called. 50 | template 51 | class HashMap : private AllocPolicy 52 | { 53 | private: 54 | struct Entry { 55 | K key; 56 | V value; 57 | 58 | Entry() { 59 | } 60 | Entry(const Entry& other) 61 | : key(other.key), 62 | value(other.value) 63 | {} 64 | Entry(Entry&& other) 65 | : key(std::move(other.key)), 66 | value(std::move(other.value)) 67 | {} 68 | 69 | template 70 | Entry(UK&& aKey, UV&& aValue) 71 | : key(std::forward(aKey)), 72 | value(std::forward(aValue)) 73 | {} 74 | }; 75 | 76 | struct Policy { 77 | typedef Entry Payload; 78 | 79 | template 80 | static uint32_t hash(const Lookup& key) { 81 | return HashPolicy::hash(key); 82 | } 83 | 84 | template 85 | static bool matches(const Lookup& key, const Payload& payload) { 86 | return HashPolicy::matches(key, payload.key); 87 | } 88 | }; 89 | 90 | typedef HashTable Internal; 91 | 92 | public: 93 | explicit HashMap(AllocPolicy ap = AllocPolicy()) 94 | : table_(ap) 95 | {} 96 | 97 | HashMap(HashMap&& other) 98 | : table_(std::move(other.table_)) 99 | {} 100 | 101 | // capacity must be a power of two. 102 | bool init(size_t capacity = 16) { 103 | return table_.init(capacity); 104 | } 105 | 106 | typedef typename Internal::Result Result; 107 | typedef typename Internal::Insert Insert; 108 | typedef typename Internal::iterator iterator; 109 | 110 | template 111 | Result find(const Lookup& key) const { 112 | return table_.find(key); 113 | } 114 | 115 | template 116 | Insert findForAdd(const Lookup& key) { 117 | return table_.findForAdd(key); 118 | } 119 | 120 | template 121 | void removeIfExists(const Lookup& key) { 122 | return table_.removeIfExists(key); 123 | } 124 | 125 | void remove(Result& r) { 126 | table_.remove(r); 127 | } 128 | 129 | // The map must not have been mutated in between findForAdd() and add(). 130 | // The Insert object is still valid after add() returns, however. 131 | template 132 | bool add(Insert& i, UK&& key, UV&& value) { 133 | Entry entry(std::forward(key), std::forward(value)); 134 | return table_.add(i, std::move(entry)); 135 | } 136 | template 137 | bool add(Insert& i, UK&& key) { 138 | Entry entry(std::forward(key), V()); 139 | return table_.add(i, std::move(entry)); 140 | } 141 | 142 | // This can be used to avoid compiler constructed temporaries, since AMTL 143 | // does not yet support move semantics. If you use this, the key and value 144 | // must be set after. 145 | bool add(Insert& i) { 146 | return table_.add(i); 147 | } 148 | 149 | iterator iter() { 150 | return iterator(&table_); 151 | } 152 | 153 | void clear() { 154 | table_.clear(); 155 | } 156 | 157 | size_t elements() const { 158 | return table_.elements(); 159 | } 160 | 161 | size_t estimateMemoryUse() const { 162 | return table_.estimateMemoryUse(); 163 | } 164 | 165 | AllocPolicy& allocPolicy() { 166 | return *this; 167 | } 168 | const AllocPolicy& allocPolicy() const { 169 | return *this; 170 | } 171 | 172 | private: 173 | Internal table_; 174 | }; 175 | 176 | template 177 | struct PointerPolicy { 178 | static inline uint32_t hash(T* p) { 179 | return HashPointer(p); 180 | } 181 | static inline bool matches(T* p1, T* p2) { 182 | return p1 == p2; 183 | } 184 | }; 185 | 186 | } // namespace ke 187 | 188 | #endif // _include_amtl_hashmap_h_ 189 | -------------------------------------------------------------------------------- /amtl/am-hashset.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_hashset_h_ 31 | #define _include_amtl_hashset_h_ 32 | 33 | #include 34 | 35 | #include 36 | 37 | namespace ke { 38 | 39 | // Template parameters: 40 | // 41 | // K - Key type. 42 | // HashPolicy - A struct with a hash and comparator function for each lookup type: 43 | // static uint32_t hash(const Type& value); 44 | // static bool matches(const Type& value, const K& key); 45 | // 46 | // Like HashMap and HashTable, init() must be called to construct the set. 47 | template 48 | class HashSet : private AllocPolicy 49 | { 50 | struct Policy { 51 | typedef K Payload; 52 | 53 | template 54 | static uint32_t hash(const Lookup& key) { 55 | return HashPolicy::hash(key); 56 | } 57 | 58 | template 59 | static bool matches(const Lookup& key, const Payload& payload) { 60 | return HashPolicy::matches(key, payload); 61 | } 62 | }; 63 | 64 | typedef HashTable Internal; 65 | 66 | public: 67 | explicit HashSet(AllocPolicy ap = AllocPolicy()) 68 | : table_(ap) 69 | {} 70 | 71 | HashSet(HashSet&& other) 72 | : table_(std::move(other.table_)) 73 | {} 74 | 75 | // capacity must be a power of two. 76 | bool init(size_t capacity = 16) { 77 | return table_.init(capacity); 78 | } 79 | 80 | typedef typename Internal::Result Result; 81 | typedef typename Internal::Insert Insert; 82 | typedef typename Internal::iterator iterator; 83 | 84 | template 85 | Result find(const Lookup& key) { 86 | return table_.find(key); 87 | } 88 | 89 | template 90 | Insert findForAdd(const Lookup& key) { 91 | return table_.findForAdd(key); 92 | } 93 | 94 | template 95 | void removeIfExists(const Lookup& key) { 96 | return table_.removeIfExists(key); 97 | } 98 | 99 | void remove(Result& r) { 100 | table_.remove(r); 101 | } 102 | 103 | // The map must not have been mutated in between findForAdd() and add(). 104 | // The Insert object is still valid after add() returns, however. 105 | template 106 | bool add(Insert& i, UK&& key) { 107 | return table_.add(i, std::forward(key)); 108 | } 109 | 110 | // This can be used to avoid compiler constructed temporaries, since AMTL 111 | // does not yet support move semantics. If you use this, the key and value 112 | // must be set after. 113 | bool add(Insert& i) { 114 | return table_.add(i); 115 | } 116 | 117 | iterator iter() { 118 | return iterator(&table_); 119 | } 120 | void clear() { 121 | table_.clear(); 122 | } 123 | 124 | size_t elements() const { 125 | return table_.elements(); 126 | } 127 | 128 | size_t estimateMemoryUse() const { 129 | return table_.estimateMemoryUse(); 130 | } 131 | 132 | // Convenience wrapper for find().found(). 133 | template 134 | bool has(const Lookup& key) { 135 | Result r = table_.find(key); 136 | return r.found(); 137 | } 138 | 139 | // Convenience wrapper for findForAdd() + add(), if the item is not already 140 | // in the set. 141 | template 142 | void add(UK&& key) { 143 | Insert p = table_.findForAdd(key); 144 | if (!p.found()) 145 | table_.add(p, std::forward(key)); 146 | } 147 | 148 | AllocPolicy& allocPolicy() { 149 | return *this; 150 | } 151 | const AllocPolicy& allocPolicy() const { 152 | return *this; 153 | } 154 | 155 | private: 156 | Internal table_; 157 | }; 158 | 159 | } // namespace ke 160 | 161 | #endif // _include_amtl_hashset_h_ 162 | -------------------------------------------------------------------------------- /amtl/am-inlinelist.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_inline_list_h_ 31 | #define _include_amtl_inline_list_h_ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | namespace ke { 38 | 39 | template 40 | class InlineList; 41 | 42 | // Objects can recursively inherit from InlineListNode in order to have 43 | // membership in an InlineList. 44 | template 45 | class InlineListNode 46 | { 47 | friend class InlineList; 48 | 49 | public: 50 | InlineListNode() 51 | : next_(nullptr), 52 | prev_(nullptr) 53 | {} 54 | 55 | InlineListNode(InlineListNode* next, InlineListNode* prev) 56 | : next_(next), 57 | prev_(prev) 58 | {} 59 | 60 | bool isInList() const { 61 | assert(!!next_ == !!prev_); 62 | return !!next_; 63 | } 64 | 65 | void removeFromParentList() { 66 | prev_->next_ = next_; 67 | next_->prev_ = prev_; 68 | next_ = nullptr; 69 | prev_ = nullptr; 70 | } 71 | 72 | protected: 73 | InlineListNode* next_; 74 | InlineListNode* prev_; 75 | }; 76 | 77 | // An InlineList is a linked list that threads link pointers through objects, 78 | // rather than allocating node memory. A node can be in at most one list at 79 | // any time. 80 | // 81 | // Since InlineLists are designed to be very cheap, there is no requirement 82 | // that elements be removed from a list once the list is destructed. However, 83 | // for as long as the list is alive, all of its contained nodes must also 84 | // be alive. 85 | template 86 | class InlineList 87 | { 88 | typedef InlineListNode Node; 89 | 90 | Node head_; 91 | size_t length_; 92 | 93 | // Work around a clang bug where we can't initialize with &head_ in the ctor. 94 | inline Node* head() { 95 | return &head_; 96 | } 97 | 98 | public: 99 | InlineList() 100 | : head_(head(), head()), 101 | length_(0) 102 | {} 103 | 104 | ~InlineList() { 105 | #if !defined(NDEBUG) 106 | // Remove all items to clear their next/prev fields. 107 | while (begin() != end()) 108 | remove(*begin()); 109 | #endif 110 | } 111 | 112 | public: 113 | class iterator 114 | { 115 | friend class InlineList; 116 | Node* iter_; 117 | 118 | public: 119 | iterator(Node* iter) 120 | : iter_(iter) 121 | {} 122 | 123 | iterator& operator ++() { 124 | iter_ = iter_->next_; 125 | return *this; 126 | } 127 | iterator operator ++(int) { 128 | iterator old(*this); 129 | iter_ = iter_->next_; 130 | return old; 131 | } 132 | T* operator *() { 133 | return static_cast(iter_); 134 | } 135 | T* operator ->() { 136 | return static_cast(iter_); 137 | } 138 | bool operator !=(const iterator& where) const { 139 | return iter_ != where.iter_; 140 | } 141 | bool operator ==(const iterator& where) const { 142 | return iter_ == where.iter_; 143 | } 144 | }; 145 | 146 | class reverse_iterator 147 | { 148 | friend class InlineList; 149 | Node* iter_; 150 | 151 | public: 152 | reverse_iterator(Node* iter) 153 | : iter_(iter) 154 | {} 155 | 156 | reverse_iterator& operator ++() { 157 | iter_ = iter_->prev_; 158 | return *this; 159 | } 160 | reverse_iterator operator ++(int) { 161 | reverse_iterator old(*this); 162 | iter_ = iter_->prev_; 163 | return old; 164 | } 165 | T* operator *() { 166 | return static_cast(iter_); 167 | } 168 | T* operator ->() { 169 | return static_cast(iter_); 170 | } 171 | bool operator !=(const reverse_iterator& where) const { 172 | return iter_ != where.iter_; 173 | } 174 | bool operator ==(const reverse_iterator& where) const { 175 | return iter_ == where.iter_; 176 | } 177 | }; 178 | 179 | iterator begin() { 180 | return iterator(head_.next_); 181 | } 182 | reverse_iterator rbegin() { 183 | return reverse_iterator(head_.prev_); 184 | } 185 | 186 | iterator end() { 187 | return iterator(&head_); 188 | } 189 | reverse_iterator rend() { 190 | return reverse_iterator(&head_); 191 | } 192 | 193 | template 194 | IteratorType erase(IteratorType& at) { 195 | IteratorType next = at; 196 | next++; 197 | 198 | remove(at.iter_); 199 | 200 | // Iterator is no longer valid. 201 | at.iter_ = nullptr; 202 | 203 | return next; 204 | } 205 | 206 | bool empty() const { 207 | return head_.next_ == &head_; 208 | } 209 | 210 | void remove(Node* t) { 211 | t->prev_->next_ = t->next_; 212 | t->next_->prev_ = t->prev_; 213 | length_--; 214 | 215 | #if !defined(NDEBUG) 216 | t->next_ = nullptr; 217 | t->prev_ = nullptr; 218 | #endif 219 | } 220 | 221 | void append(Node* t) { 222 | assert(!t->next_); 223 | assert(!t->prev_); 224 | 225 | t->prev_ = head_.prev_; 226 | t->next_ = &head_; 227 | head_.prev_->next_ = t; 228 | head_.prev_ = t; 229 | length_++; 230 | } 231 | 232 | size_t length() const { 233 | return length_; 234 | } 235 | }; 236 | 237 | } // namespace ke 238 | 239 | #endif // _include_amtl_inline_list_h_ 240 | -------------------------------------------------------------------------------- /amtl/am-linking.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_linking_h_ 31 | #define _include_amtl_linking_h_ 32 | 33 | #include 34 | 35 | #if defined(_MSC_VER) 36 | # define KE_DLL_IMPORT __declspec(dllimport) 37 | # define KE_DLL_EXPORT __declspec(dllexport) 38 | # define KE_DLL_PRIVATE 39 | #else 40 | # define KE_DLL_IMPORT 41 | # define KE_DLL_EXPORT __attribute__((visibility("default"))) 42 | # define KE_DLL_PRIVATE __attribute__((visibility("hidden"))) 43 | #endif 44 | 45 | #endif // _include_amtl_linking_h_ 46 | -------------------------------------------------------------------------------- /amtl/am-maybe.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_maybe_h_ 30 | #define _include_amtl_maybe_h_ 31 | 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | namespace ke { 40 | 41 | struct Nothing {}; 42 | 43 | template 44 | class Maybe 45 | { 46 | public: 47 | Maybe() 48 | : initialized_(false) 49 | {} 50 | Maybe(const Maybe& other) 51 | : initialized_(false) 52 | { 53 | copyFrom(other); 54 | } 55 | Maybe(Maybe&& other) 56 | : initialized_(false) 57 | { 58 | moveFrom(std::move(other)); 59 | } 60 | Maybe(Nothing) 61 | : initialized_(false) 62 | {} 63 | 64 | ~Maybe() { 65 | if (isValid()) 66 | t_.address()->~T(); 67 | } 68 | 69 | template 70 | void init(ArgTypes&&... argv) { 71 | if (isValid()) 72 | t_.address()->~T(); 73 | 74 | new (t_.address()) T(std::forward(argv)...); 75 | initialized_ = true; 76 | } 77 | 78 | bool isValid() const { 79 | return initialized_; 80 | } 81 | 82 | T& operator ->() { 83 | assert(isValid()); 84 | return t_.address(); 85 | } 86 | T& operator *() { 87 | assert(isValid()); 88 | return *t_.address(); 89 | } 90 | const T& operator ->() const { 91 | assert(isValid()); 92 | return t_.address(); 93 | } 94 | const T& operator *() const { 95 | assert(isValid()); 96 | return *t_.address(); 97 | } 98 | T& get() { 99 | assert(isValid()); 100 | return *t_.address(); 101 | } 102 | const T& get() const { 103 | assert(isValid()); 104 | return *t_.address(); 105 | } 106 | 107 | explicit operator bool() const { 108 | return isValid(); 109 | } 110 | 111 | Maybe& operator =(const Maybe& other) { 112 | initialized_ = false; 113 | copyFrom(other); 114 | return *this; 115 | } 116 | Maybe& operator =(Maybe&& other) { 117 | initialized_ = false; 118 | moveFrom(std::move(other)); 119 | return *this; 120 | } 121 | 122 | private: 123 | void copyFrom(const Maybe& other) { 124 | if (other.initialized_) { 125 | init(*other.t_.address()); 126 | } 127 | } 128 | void moveFrom(Maybe&& other) { 129 | if (other.initialized_) { 130 | init(std::move(*other.t_.address())); 131 | other.initialized_ = false; 132 | } 133 | } 134 | 135 | private: 136 | bool initialized_; 137 | StorageBuffer t_; 138 | }; 139 | 140 | template ::type>::type> 141 | static inline Maybe 142 | Some(T&& value) 143 | { 144 | Maybe m; 145 | m.init(std::forward(value)); 146 | return m; 147 | } 148 | 149 | } // namespace ke 150 | 151 | #endif // _include_amtl_maybe_h_ 152 | -------------------------------------------------------------------------------- /amtl/am-mutex.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2020 David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #pragma once 31 | 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | namespace ke { 38 | 39 | // Wrapper for that allows asserting who owns it. 40 | class Mutex : public std::mutex 41 | { 42 | public: 43 | #ifdef NDEBUG 44 | void AssertCurrentThreadOwns() {} 45 | #else 46 | void lock() { 47 | std::mutex::lock(); 48 | owner_ = std::this_thread::get_id(); 49 | }; 50 | 51 | void unlock() { 52 | owner_ = {}; 53 | std::mutex::unlock(); 54 | } 55 | 56 | void AssertCurrentThreadOwns() { 57 | assert(owner_ == std::this_thread::get_id()); 58 | } 59 | 60 | private: 61 | std::thread::id owner_ = {}; 62 | #endif 63 | }; 64 | 65 | } // namespace ke 66 | -------------------------------------------------------------------------------- /amtl/am-platform.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_platform_h_ 30 | #define _include_amtl_platform_h_ 31 | 32 | namespace ke { 33 | 34 | #if defined(__EMSCRIPTEN__) 35 | # define KE_EMSCRIPTEN 36 | # define KE_POSIX 37 | #elif defined(__NetBSD__) 38 | # define KE_NETBSD 39 | # define KE_BSD 40 | #elif defined(__FreeBSD__) 41 | # define KE_FREEBSD 42 | # define KE_BSD 43 | #elif defined(__OpenBSD__) 44 | # define KE_OPENBSD 45 | # define KE_BSD 46 | #elif defined(__APPLE__) 47 | # define KE_MACOSX 48 | # define KE_MACH 49 | # define KE_BSD 50 | #elif defined(__MACH__) 51 | # define KE_MACH 52 | # define KE_BSD 53 | #elif defined(_WIN32) 54 | # define KE_WINDOWS 55 | #elif defined(__linux__) 56 | # define KE_LINUX 57 | # define KE_POSIX 58 | #elif defined(__sun__) 59 | # define KE_SOLARIS 60 | # define KE_POSIX 61 | #endif 62 | 63 | #if defined(KE_BSD) 64 | # define KE_POSIX 65 | #endif 66 | 67 | #if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__amd64) || \ 68 | (defined(_MSC_VER) && defined(_M_X64)) 69 | # define KE_ARCH_X64 70 | #elif defined(__i686) || defined(__i686__) || defined(__i386) || defined(__i386__) || \ 71 | defined(i386) || (defined(_MSC_VER) && defined(_M_IX86)) 72 | # define KE_ARCH_X86 73 | #elif defined(__aarch64__) || defined(_M_ARM64) 74 | # define KE_ARCH_ARM64 75 | #elif defined(__arm__) || defined(_M_ARM) 76 | # define KE_ARCH_ARM 77 | #else 78 | # define KE_ARCH_UNKNOWN 79 | #endif 80 | 81 | // Create macros that exactly match the compiler - peeking past any tricks 82 | // vendors play for interoperability. 83 | #if defined(__clang__) 84 | # define KE_CXX_CLANG 85 | #elif defined(__GNUC__) 86 | # define KE_CXX_GCC 87 | #elif defined(_MSC_VER) 88 | # define KE_CXX_MSVC 89 | #endif 90 | 91 | #if defined(KE_CXX_CLANG) || defined(KE_CXX_GCC) 92 | # define KE_CXX_LIKE_GCC 93 | #endif 94 | 95 | } // namespace ke 96 | 97 | #endif // _include_amtl_platform_h_ 98 | -------------------------------------------------------------------------------- /amtl/am-priority-queue.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2016, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_am_priority_queue_h_ 31 | #define _include_amtl_am_priority_queue_h_ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | 42 | namespace ke { 43 | 44 | // Basic priority queue implemented using a binary heap on top of vector. The 45 | // "IsHigherPriority" callable must take a left and right value of type T, and 46 | // return whether the left value should be dequeued before the right. 47 | // 48 | // This allows move-and-pop which the STL container does not. 49 | template > 50 | class PriorityQueue final 51 | { 52 | public: 53 | explicit PriorityQueue(IsHigherPriority hp = IsHigherPriority()) 54 | : is_higher_priority_(hp) 55 | {} 56 | 57 | PriorityQueue(PriorityQueue&& other) 58 | : impl_(std::move(other.impl_)), 59 | is_higher_priority_(std::move(other.is_higher_priority_)) 60 | {} 61 | 62 | template 63 | void add(U&& item) { 64 | impl_.push_back(std::forward(item)); 65 | if (impl_.size() > 1) 66 | propagateUp(impl_.size() - 1); 67 | } 68 | 69 | template 70 | void emplace(Args&&... args) { 71 | impl_.emplace_back(std::forward(args)...); 72 | if (impl_.size() > 1) 73 | propagateUp(impl_.size() - 1); 74 | } 75 | 76 | bool empty() const { 77 | return impl_.empty(); 78 | } 79 | 80 | const T& peek() const { 81 | assert(!empty()); 82 | return impl_[0]; 83 | } 84 | 85 | T pop() { 86 | assert(!empty()); 87 | 88 | T top = std::move(impl_[0]); 89 | if (impl_.size() == 1) { 90 | impl_.pop_back(); 91 | } else { 92 | impl_[0] = std::move(impl_.back()); 93 | impl_.pop_back(); 94 | propagateDown(0); 95 | } 96 | return top; 97 | } 98 | 99 | private: 100 | void propagateUp(size_t at) { 101 | size_t cursor = at; 102 | T key(std::move(impl_[cursor])); 103 | while (cursor != 0) { 104 | size_t parent = parentOf(cursor); 105 | if (!is_higher_priority_(key, impl_[parent])) 106 | break; 107 | 108 | impl_[cursor] = std::move(impl_[parent]); 109 | cursor = parent; 110 | } 111 | 112 | impl_[cursor] = std::move(key); 113 | } 114 | 115 | void propagateDown(size_t at) { 116 | size_t cursor = at; 117 | while (hasLeftChild(cursor)) { 118 | // Pick the child with the highest priority. 119 | size_t bestChild = leftChildOf(cursor); 120 | if (hasRightChild(cursor)) { 121 | size_t rightIndex = rightChildOf(cursor); 122 | if (is_higher_priority_(impl_[rightIndex], impl_[bestChild])) 123 | bestChild = rightIndex; 124 | } 125 | 126 | // If the highest priority child is not higher priority than the cursor, 127 | // then we are finished. 128 | if (!is_higher_priority_(impl_[bestChild], impl_[cursor])) 129 | break; 130 | 131 | // Otherwise, swap and move on. 132 | std::swap(impl_[bestChild], impl_[cursor]); 133 | cursor = bestChild; 134 | } 135 | } 136 | 137 | static constexpr size_t parentOf(size_t at) { 138 | #if __cplusplus >= 201402L 139 | assert(at > 0); 140 | #endif 141 | return (at - 1) / 2; 142 | } 143 | static constexpr size_t leftChildOf(size_t at) { 144 | return (at * 2) + 1; 145 | } 146 | static constexpr size_t rightChildOf(size_t at) { 147 | return (at * 2) + 2; 148 | } 149 | 150 | bool hasLeftChild(size_t at) const { 151 | return leftChildOf(at) < impl_.size(); 152 | } 153 | bool hasRightChild(size_t at) const { 154 | return rightChildOf(at) < impl_.size(); 155 | } 156 | 157 | private: 158 | PriorityQueue(const PriorityQueue& other) = delete; 159 | void operator =(const PriorityQueue& other) = delete; 160 | 161 | private: 162 | std::vector impl_; 163 | IsHigherPriority is_higher_priority_; 164 | }; 165 | 166 | } // namespace ke 167 | 168 | #endif // _include_amtl_am_priority_queue_h_ 169 | -------------------------------------------------------------------------------- /amtl/am-raii.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=4 ts=8 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_am_raii_h_ 31 | #define _include_amtl_am_raii_h_ 32 | 33 | #include 34 | 35 | namespace ke { 36 | 37 | template 38 | class SaveAndSet 39 | { 40 | public: 41 | SaveAndSet(T* location, const T& value) 42 | : location_(location), 43 | old_(*location) 44 | { 45 | *location_ = value; 46 | } 47 | ~SaveAndSet() { 48 | *location_ = old_; 49 | } 50 | 51 | private: 52 | T* location_; 53 | T old_; 54 | }; 55 | 56 | template 57 | class StackLinked 58 | { 59 | public: 60 | StackLinked(T** prevp) 61 | : prevp_(prevp), 62 | prev_(*prevp) 63 | { 64 | *prevp_ = static_cast(this); 65 | } 66 | virtual ~StackLinked() { 67 | assert(*prevp_ == this); 68 | *prevp_ = prev_; 69 | } 70 | 71 | protected: 72 | T** prevp_; 73 | T* prev_; 74 | }; 75 | 76 | template 77 | class ScopeGuard 78 | { 79 | public: 80 | ScopeGuard(T&& callback) noexcept 81 | : callback_(std::forward(callback)), 82 | cancelled_(false) 83 | {} 84 | ScopeGuard(ScopeGuard&& other) noexcept 85 | : callback_(std::move(other.callback_)), 86 | cancelled_(other.cancelled_) 87 | { 88 | other.cancel(); 89 | } 90 | 91 | ~ScopeGuard() { 92 | if (!cancelled_) 93 | callback_(); 94 | } 95 | 96 | void cancel() { 97 | cancelled_ = true; 98 | } 99 | 100 | private: 101 | ScopeGuard() = delete; 102 | ScopeGuard(const ScopeGuard&) = delete; 103 | 104 | void operator=(const ScopeGuard&) = delete; 105 | void operator=(ScopeGuard&&) = delete; 106 | 107 | private: 108 | T callback_; 109 | bool cancelled_; 110 | }; 111 | 112 | template 113 | ScopeGuard MakeScopeGuard(T&& callback) 114 | { 115 | return ScopeGuard(std::forward(callback)); 116 | } 117 | 118 | template 119 | T 120 | ReturnAndVoid(T& t) 121 | { 122 | T saved = t; 123 | t = T(); 124 | return saved; 125 | } 126 | 127 | } // namespace ke 128 | 129 | #endif // _include_amtl_am_raii_h_ 130 | -------------------------------------------------------------------------------- /amtl/am-refcounting-threadsafe.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_ts_refcounting_h_ 31 | #define _include_amtl_ts_refcounting_h_ 32 | 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | namespace ke { 40 | 41 | // See the comment above Refcounted for more information. This class is 42 | // identical, except changing the reference count is guaranteed to be atomic 43 | // with respect to other threads changing the reference count. 44 | template 45 | class RefcountedThreadsafe 46 | { 47 | public: 48 | RefcountedThreadsafe() 49 | : refcount_(0) 50 | {} 51 | 52 | void AddRef() { 53 | refcount_ += 1; 54 | } 55 | bool Release() { 56 | if (refcount_.fetch_sub(1) == 1) { 57 | assert(refcount_.load() == 0); 58 | delete static_cast(this); 59 | return false; 60 | } 61 | return true; 62 | } 63 | 64 | protected: 65 | ~RefcountedThreadsafe() {} 66 | 67 | private: 68 | std::atomic refcount_; 69 | }; 70 | 71 | // Use this to forward to ke::Refcounted, when implementing IRefcounted. 72 | #define KE_IMPL_REFCOUNTING_TS(classname) \ 73 | void AddRef() { \ 74 | ke::RefcountedThreadsafe::AddRef(); \ 75 | } \ 76 | void Release() { \ 77 | ke::RefcountedThreadsafe::Release(); \ 78 | } 79 | 80 | // Classes may be multiply-inherited may wish to derive from this Refcounted 81 | // instead. 82 | class VirtualRefcountedThreadsafe : public IRefcounted 83 | { 84 | public: 85 | VirtualRefcountedThreadsafe() 86 | : refcount_(0) 87 | { 88 | #if !defined(NDEBUG) 89 | destroying_ = false; 90 | #endif 91 | } 92 | virtual ~VirtualRefcountedThreadsafe() {} 93 | void AddRef() override { 94 | assert(!destroying_); 95 | refcount_ += 1; 96 | } 97 | void Release() override { 98 | if (refcount_.fetch_sub(1) == 0) { 99 | assert(refcount_.load() == 0); 100 | #if !defined(NDEBUG) 101 | destroying_ = true; 102 | #endif 103 | delete this; 104 | } 105 | } 106 | 107 | private: 108 | std::atomic refcount_; 109 | #if !defined(NDEBUG) 110 | bool destroying_; 111 | #endif 112 | }; 113 | 114 | // This is a specialized version of Ref<> that is safe to read and write from 115 | // multiple threads. It is not recommended for general use, since it imposes 116 | // a CAS spin-lock on every read/write. 117 | // 118 | // Normally, assigning Ref<> to Ref<> has a race condition where in between 119 | // the read and incref, another thread can assign, decref, and ultimately 120 | // destroy the left-hand side. This prevents such a scenario by making reads 121 | // atomic with respect to the incref operation. 122 | // 123 | // Pointers stored in an AtomicRef<> must be at least sizeof(void*) aligned. 124 | template 125 | class AtomicRef 126 | { 127 | public: 128 | AtomicRef() 129 | : thing_(nullptr) 130 | {} 131 | AtomicRef(T* thing) 132 | : thing_(thing) 133 | { 134 | assert(IsAligned(thing, sizeof(void*))); 135 | if (thing) 136 | thing->AddRef(); 137 | } 138 | ~AtomicRef() { 139 | // Should not be locked. 140 | assert(thing_ == untagged(thing_)); 141 | if (thing_) 142 | reinterpret_cast(thing_.load())->Release(); 143 | } 144 | 145 | // Atomically retrieve and add a reference to the contained value. 146 | AlreadyRefed get() { 147 | T* value = lock(); 148 | if (value) 149 | value->AddRef(); 150 | unlock(value); 151 | return AdoptRef(value); 152 | } 153 | 154 | // Atomically incref the new value and replace the old value. 155 | void operator =(T* other) { 156 | T* value = lock(); 157 | if (other) 158 | other->AddRef(); 159 | unlock(other); 160 | if (value) 161 | value->Release(); 162 | } 163 | 164 | private: 165 | AtomicRef(const AtomicRef& other) = delete; 166 | void operator =(const AtomicRef& other) = delete; 167 | 168 | private: 169 | // We represent a locked state with a tag bit. 170 | void* tagged(void* ptr) { 171 | return reinterpret_cast(uintptr_t(ptr) | 1); 172 | } 173 | void* untagged(void* ptr) { 174 | return reinterpret_cast(uintptr_t(ptr) & ~uintptr_t(1)); 175 | } 176 | 177 | T* lock() { 178 | // Spin until we can replace an untagged ptr with the tagged version. 179 | // Note that we cannot use compare_and_swap_weak. If |thing_| becomes 180 | // locked but spuriously fails (as can happen on ARM), we'll loop 181 | // indefinitely waiting for it to become unlocked. So we must have a 182 | // strong guarantee on failure. 183 | void* oldval = untagged(thing_); 184 | while (!thing_.compare_exchange_strong(oldval, tagged(oldval), std::memory_order_release, 185 | std::memory_order_relaxed)) 186 | { 187 | std::this_thread::yield(); 188 | oldval = untagged(thing_); 189 | } 190 | return reinterpret_cast(oldval); 191 | } 192 | void unlock(T* ptr) { 193 | // Nothing should have mutated the value, and the new value should be 194 | // untagged. 195 | assert(thing_ == tagged(thing_)); 196 | assert(ptr == untagged(ptr)); 197 | thing_ = ptr; 198 | } 199 | 200 | private: 201 | std::atomic thing_; 202 | }; 203 | 204 | } // namespace ke 205 | 206 | #endif // _include_amtl_ts_refcounting_h_ 207 | -------------------------------------------------------------------------------- /amtl/am-storagebuffer.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_storagebuffer_h_ 31 | #define _include_amtl_storagebuffer_h_ 32 | 33 | #include 34 | 35 | namespace ke { 36 | 37 | // StorageBuffer allows storage of objects where calling a destructor is 38 | // undesirable or impossible (for example, members in unions). 39 | template 40 | class StorageBuffer 41 | { 42 | public: 43 | T* address() { 44 | return reinterpret_cast(buffer_); 45 | } 46 | const T* address() const { 47 | return reinterpret_cast(buffer_); 48 | } 49 | 50 | private: 51 | union { 52 | char buffer_[sizeof(T)]; 53 | uint64_t aligned_; 54 | }; 55 | }; 56 | 57 | } // namespace ke 58 | 59 | #endif // _include_amtl_storagebuffer_h_ 60 | -------------------------------------------------------------------------------- /amtl/am-thread.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2020 David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #pragma once 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | 39 | #if defined(KE_POSIX) 40 | # include 41 | #elif defined(KE_WINDOWS) 42 | # include 43 | # include 44 | # include 45 | 46 | # include 47 | # include 48 | # include 49 | #endif 50 | 51 | namespace ke { 52 | 53 | namespace impl { 54 | 55 | #if defined(KE_WINDOWS) 56 | static void SetThreadName(HANDLE thread, const char* name) { 57 | auto module = LoadLibraryA("kernel32.dll"); 58 | if (!module) 59 | return; 60 | 61 | typedef HRESULT (WINAPI * SetThreadDescriptionFn)(HANDLE, PCWSTR); 62 | auto fn = (SetThreadDescriptionFn)GetProcAddress(module, "SetThreadDescription"); 63 | if (!fn) 64 | return; 65 | 66 | std::wstring_convert> converter; 67 | std::wstring utf16 = converter.from_bytes(name); 68 | fn(thread, utf16.c_str()); 69 | 70 | FreeLibrary(module); 71 | } 72 | #endif 73 | 74 | } // namespace detail 75 | 76 | static inline void SetThreadName(const char* name) { 77 | #if defined(KE_MACOSX) 78 | pthread_setname_np(name); 79 | #elif defined(KE_POSIX) 80 | pthread_setname_np(pthread_self(), name); 81 | #elif defined(KE_WINDOWS) 82 | impl::SetThreadName(::GetCurrentThread(), name); 83 | #else 84 | (void)name; 85 | #endif 86 | } 87 | 88 | static inline void SetThreadName(std::thread* thread, const char* name) { 89 | #if defined(KE_POSIX) && !defined(KE_MACOSX) 90 | pthread_setname_np(thread->native_handle(), name); 91 | #elif defined(KE_WINDOWS) 92 | impl::SetThreadName(thread->native_handle(), name); 93 | #else 94 | (void)thread; 95 | (void)name; 96 | #endif 97 | } 98 | 99 | // Helper to allocate named threads. We can't subclass std::thread for this 100 | // because the order of construction would be wrong. 101 | // 102 | // This version takes no additional args, as a workaround for a bug in recent 103 | // versions of libstdc++. Its implementation of std::bind uses std::result_of 104 | // which libstdc++ deprecates, and of course, provides no way to turn off the 105 | // deprecation warnings. 106 | // 107 | // Since perfect forwarding of argument packs to lambdas is a C++20 feature, 108 | // and we don't really use additional arguments, this is the simplest fix for 109 | // now. 110 | template 111 | static inline std::unique_ptr NewThread(const char* name, Function&& f) 112 | { 113 | auto fn = [f = std::forward(f)](const std::string& name) -> void { 114 | SetThreadName(name.c_str()); 115 | f(); 116 | }; 117 | return std::make_unique(std::move(fn), std::string(name)); 118 | } 119 | 120 | // Helper to allocate named threads. We can't subclass std::thread for this 121 | // because the order of construction would be wrong. 122 | template 123 | static inline std::unique_ptr NewThread(const char* name, Function&& f, Args&&... args) 124 | { 125 | auto callback = std::bind(f, std::forward(args)...); 126 | auto fn = [](const std::string& name, decltype(callback)&& callback) -> void { 127 | SetThreadName(name.c_str()); 128 | callback(); 129 | }; 130 | return std::make_unique(std::move(fn), std::string(name), std::move(callback)); 131 | } 132 | 133 | } // namespace ke 134 | 135 | -------------------------------------------------------------------------------- /amtl/am-threadlocal.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=2 ts=8 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_thread_local_h_ 31 | #define _include_amtl_thread_local_h_ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #ifdef _WIN32 40 | # include 41 | #else 42 | # include 43 | #endif 44 | 45 | namespace ke { 46 | 47 | // Stores a per-thread value. In single-threaded mode (KE_SINGLE_THREADED), 48 | // this is a no-op container wrapper. 49 | // 50 | // T must be castable to uintptr_t. 51 | // 52 | // When assigning to a ThreadLocal, the assigment will automatically attempt 53 | // to allocate thread-local storage from the operating system. If it fails, it 54 | // will abort the program. If this is undesirable, you may call allocate() 55 | // up-front and handle the error case manually. 56 | // 57 | // The number of thread local slots available to processes is limited (on 58 | // Linux, it is generally 1024). It is best to use ThreadLocal sparingly to 59 | // play nicely with other libraries. 60 | // 61 | // ThreadLocal will free the underlying thread-local storage slot in its 62 | // destructor, but it is not an AutoPtr. It does not delete pointers. Since 63 | // one thread's value is only observable from that thread, make sure to free 64 | // the contained resource (if necessary) before the thread exits. 65 | template 66 | class ThreadLocal 67 | { 68 | public: 69 | void operator =(const T& other) { 70 | set(other); 71 | } 72 | 73 | T operator *() const { 74 | return get(); 75 | } 76 | T operator ->() const { 77 | return get(); 78 | } 79 | bool operator !() const { 80 | return !get(); 81 | } 82 | bool operator ==(const T& other) const { 83 | return get() == other; 84 | } 85 | bool operator !=(const T& other) const { 86 | return get() != other; 87 | } 88 | 89 | private: 90 | ThreadLocal(const ThreadLocal& other) = delete; 91 | ThreadLocal& operator =(const ThreadLocal& other) = delete; 92 | 93 | #if !defined(KE_SINGLE_THREADED) 94 | private: 95 | volatile int allocated_; 96 | 97 | public: 98 | ThreadLocal() { 99 | allocated_ = 0; 100 | } 101 | 102 | T get() const { 103 | if (!allocated_) 104 | return T(); 105 | return internalGet(); 106 | } 107 | void set(const T& t) { 108 | if (!allocated_ && !allocate()) { 109 | fprintf(stderr, "could not allocate thread-local storage\n"); 110 | abort(); 111 | } 112 | internalSet(t); 113 | } 114 | 115 | # if defined(_MSC_VER) 116 | ~ThreadLocal() { 117 | if (allocated_) 118 | TlsFree(key_); 119 | } 120 | 121 | private: 122 | T internalGet() const { 123 | return (T)reinterpret_cast(TlsGetValue(key_)); 124 | } 125 | void internalSet(const T& t) { 126 | TlsSetValue(key_, cast_to_pointer::cast(t)); 127 | } 128 | bool allocate() { 129 | if (InterlockedCompareExchange((volatile LONG*)&allocated_, 1, 0) == 1) 130 | return true; 131 | key_ = TlsAlloc(); 132 | return key_ != TLS_OUT_OF_INDEXES; 133 | } 134 | 135 | DWORD key_; 136 | 137 | # else 138 | public: 139 | ~ThreadLocal() { 140 | if (allocated_) 141 | pthread_key_delete(key_); 142 | } 143 | 144 | bool allocate() { 145 | if (!__sync_bool_compare_and_swap(&allocated_, 0, 1)) 146 | return true; 147 | return pthread_key_create(&key_, nullptr) == 0; 148 | } 149 | 150 | private: 151 | T internalGet() const { 152 | return (T) reinterpret_cast(pthread_getspecific(key_)); 153 | } 154 | void internalSet(const T& t) { 155 | pthread_setspecific(key_, reinterpret_cast(t)); 156 | } 157 | 158 | pthread_key_t key_; 159 | # endif // !_MSC_VER 160 | 161 | #else // KE_SINGLE_THREADED 162 | public: 163 | ThreadLocal() { 164 | t_ = T(); 165 | } 166 | 167 | bool allocate() { 168 | return true; 169 | } 170 | 171 | T get() const { 172 | return t_; 173 | } 174 | void set(const T& t) { 175 | t_ = t; 176 | } 177 | 178 | private: 179 | T t_; 180 | #endif 181 | }; 182 | 183 | } // namespace ke 184 | 185 | #endif // _include_amtl_thread_local_h_ 186 | -------------------------------------------------------------------------------- /amtl/am-time.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=4 ts=8 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2020, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #pragma once 30 | 31 | // Support pre g++-4.8 is buggy. 32 | #if __cplusplus >= 201703L 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | namespace ke { 43 | 44 | static inline constexpr std::chrono::nanoseconds 45 | TimespecToDuration(timespec ts) 46 | { 47 | auto duration = std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}; 48 | return std::chrono::duration_cast(duration); 49 | } 50 | 51 | template 52 | static inline constexpr std::chrono::time_point 53 | TimespecToTimePoint(timespec ts) 54 | { 55 | auto duration = TimespecToDuration(ts); 56 | return typename Clock::time_point{std::chrono::duration_cast(duration)}; 57 | } 58 | 59 | // Uses the C++11 put_time() formatting, not strftime. 60 | // See: https://en.cppreference.com/w/cpp/io/manip/put_time 61 | static inline std::string FormatTime(const struct tm& tm, const char* fmt) 62 | { 63 | std::ostringstream ss; 64 | ss << std::put_time(&tm, fmt); 65 | return ss.str(); 66 | } 67 | 68 | static inline std::string FormatTime(const struct tm& tm, const std::string& str) 69 | { 70 | return FormatTime(tm, str.c_str()); 71 | } 72 | 73 | template 74 | static inline constexpr TimePointType EpochValueToTimePoint(T t) 75 | { 76 | auto duration = typename TimePointType::duration{t}; 77 | return TimePointType(duration); 78 | } 79 | 80 | } // namespace ke 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /amtl/am-unused.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_unused_ 31 | #define _include_amtl_unused_ 32 | 33 | namespace ke { 34 | 35 | class Unused 36 | { 37 | public: 38 | Unused() { 39 | } 40 | 41 | template 42 | void operator<<(const T&) { 43 | } 44 | }; 45 | 46 | } // namespace ke 47 | 48 | #endif // _include_amtl_unused_ 49 | -------------------------------------------------------------------------------- /amtl/am-utility.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2014, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_utility_h_ 31 | #define _include_amtl_utility_h_ 32 | 33 | #define __STDC_FORMAT_MACROS 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | 41 | #if defined(_MSC_VER) 42 | // Mac file format warning. 43 | # pragma warning(disable : 4355) 44 | #endif 45 | 46 | namespace ke { 47 | 48 | // Zero out a non-array pointer. 49 | template 50 | static inline void 51 | MemsetZero(T* t) { 52 | memset(t, 0, sizeof(*t)); 53 | } 54 | 55 | #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) 56 | #define IS_ALIGNED(addr, alignment) (!(uintptr_t(addr) & ((alignment)-1))) 57 | 58 | #if defined(__GNUC__) 59 | # define KE_CRITICAL_LIKELY(x) __builtin_expect(!!(x), 1) 60 | #else 61 | # define KE_CRITICAL_LIKELY(x) x 62 | #endif 63 | 64 | template 65 | struct cast_to_pointer { 66 | static void* cast(const T& t) { 67 | return reinterpret_cast((uintptr_t)t); 68 | } 69 | }; 70 | 71 | template 72 | struct cast_to_pointer { 73 | static const void* cast(const T* ptr) { 74 | return ptr; 75 | } 76 | static void* cast(T* ptr) { 77 | return ptr; 78 | } 79 | }; 80 | 81 | } // namespace ke 82 | 83 | #endif // _include_amtl_utility_h_ 84 | -------------------------------------------------------------------------------- /amtl/am-vector.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #pragma once 31 | 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | namespace ke { 38 | 39 | template 40 | static inline void MoveExtend(std::vector* dest, std::vector* src) { 41 | if (dest->empty()) { 42 | *dest = std::move(*src); 43 | } else { 44 | for (size_t i = 0; i < src->size(); i++) 45 | dest->emplace_back(std::move(src->at(i))); 46 | src->clear(); 47 | } 48 | } 49 | 50 | template 51 | static inline T PopBack(std::vector* src) { 52 | T t = std::move(src->back()); 53 | src->pop_back(); 54 | return t; 55 | } 56 | 57 | template 58 | static inline void RemoveAt(std::vector* vec, size_t at) { 59 | vec->erase(vec->begin() + at); 60 | } 61 | 62 | template 63 | static inline void InsertAt(std::vector* vec, size_t at, const T& item) { 64 | vec->insert(vec->begin() + at, item); 65 | } 66 | 67 | template 68 | static inline void InsertAt(std::vector* vec, size_t at, T&& item) { 69 | vec->insert(vec->begin() + at, std::forward(item)); 70 | } 71 | 72 | template 73 | static inline void EmplaceAt(std::vector* vec, size_t at, Args&&... item) { 74 | vec->emplace(vec->begin() + at, std::forward(item)...); 75 | } 76 | 77 | template 78 | static inline void EraseIf(std::vector* vec, Pred pred) { 79 | auto it = std::remove_if(vec->begin(), vec->end(), pred); 80 | vec->erase(it, vec->end()); 81 | } 82 | 83 | } // namespace ke 84 | -------------------------------------------------------------------------------- /amtl/experimental/am-argparser.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2018, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | namespace ke { 33 | namespace args { 34 | 35 | std::vector *Parser::sStaticOptions = nullptr; 36 | 37 | } // namespace args 38 | } // namespace ke 39 | -------------------------------------------------------------------------------- /amtl/os/am-fsutil-posix.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_os_fsutil_posix_h_ 30 | #define _include_amtl_os_fsutil_posix_h_ 31 | 32 | #include 33 | #include 34 | 35 | namespace ke { 36 | namespace file { 37 | 38 | static inline bool 39 | PathExists(const char* path) { 40 | struct stat s; 41 | return (stat(path, &s) == 0); 42 | } 43 | 44 | static inline bool 45 | IsFile(const char* path) { 46 | struct stat s; 47 | if (stat(path, &s) != 0) 48 | return false; 49 | return S_ISREG(s.st_mode) ? true : false; 50 | } 51 | 52 | static inline bool 53 | IsDirectory(const char* path) { 54 | struct stat s; 55 | if (stat(path, &s) != 0) 56 | return false; 57 | return S_ISDIR(s.st_mode) ? true : false; 58 | } 59 | 60 | static inline bool 61 | CreateDirectory(const char* path, unsigned mode = 0755) { 62 | return mkdir(path, mode) == 0; 63 | } 64 | 65 | } // namespace file 66 | } // namespace ke 67 | 68 | #endif // _include_amtl_os_fsutil_posix_h_ 69 | -------------------------------------------------------------------------------- /amtl/os/am-fsutil-windows.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_os_fsutil_windows_h_ 30 | #define _include_amtl_os_fsutil_windows_h_ 31 | 32 | #define WIN32_LEAN_AND_MEAN 33 | #include 34 | #include 35 | 36 | namespace ke { 37 | namespace file { 38 | 39 | static inline bool 40 | PathExists(const char* path) { 41 | return GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES; 42 | } 43 | 44 | static inline bool 45 | IsFile(const char* path) { 46 | DWORD attr = GetFileAttributesA(path); 47 | if (attr == INVALID_FILE_ATTRIBUTES) 48 | return false; 49 | if (attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) 50 | return false; 51 | return true; 52 | } 53 | 54 | static inline bool 55 | IsDirectory(const char* path) { 56 | DWORD attr = GetFileAttributesA(path); 57 | if (attr == INVALID_FILE_ATTRIBUTES) 58 | return false; 59 | return (attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) == FILE_ATTRIBUTE_DIRECTORY; 60 | } 61 | 62 | static inline bool 63 | CreateDirectory(const char* path, unsigned mode_IGNORED = 0) { 64 | return mkdir(path) == 0; 65 | } 66 | 67 | } // namespace file 68 | } // namespace ke 69 | 70 | #endif // _include_amtl_os_fsutil_windows_h_ 71 | -------------------------------------------------------------------------------- /amtl/os/am-fsutil.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_os_fsutil_h_ 30 | #define _include_amtl_os_fsutil_h_ 31 | 32 | #include 33 | #include 34 | #if defined(KE_WINDOWS) 35 | # include 36 | #else 37 | # include 38 | #endif 39 | 40 | namespace ke { 41 | namespace file {} // namespace file 42 | } // namespace ke 43 | 44 | #endif // _include_amtl_os_fsutil_h_ 45 | -------------------------------------------------------------------------------- /amtl/os/am-path.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_os_path_h_ 30 | #define _include_amtl_os_path_h_ 31 | 32 | #include 33 | #include 34 | 35 | namespace ke { 36 | namespace path { 37 | 38 | static inline size_t 39 | FormatVa(char* dest, size_t maxlength, const char* fmt, va_list ap) { 40 | size_t len = SafeVsprintf(dest, maxlength, fmt, ap); 41 | 42 | for (size_t i = 0; i < len; i++) { 43 | #if defined(KE_WINDOWS) 44 | if (dest[i] == '/') 45 | dest[i] = '\\'; 46 | #else 47 | if (dest[i] == '\\') 48 | dest[i] = '/'; 49 | #endif 50 | } 51 | 52 | return len; 53 | } 54 | 55 | static inline size_t 56 | Format(char* dest, size_t maxlength, const char* fmt, ...) { 57 | va_list ap; 58 | va_start(ap, fmt); 59 | size_t len = FormatVa(dest, maxlength, fmt, ap); 60 | va_end(ap); 61 | return len; 62 | } 63 | 64 | } // namespace path 65 | } // namespace ke 66 | 67 | #endif // _include_amtl_os_path_h_ 68 | -------------------------------------------------------------------------------- /amtl/os/am-shared-library.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_os_sharedlib_h_ 30 | #define _include_amtl_os_sharedlib_h_ 31 | 32 | #include 33 | #include 34 | #if defined(KE_WINDOWS) 35 | # define WIN32_LEAN_AND_MEAN 36 | # include 37 | # include 38 | #else 39 | # include 40 | # include 41 | #endif 42 | 43 | namespace ke { 44 | 45 | class SharedLib : public Refcounted 46 | { 47 | #if defined(KE_WINDOWS) 48 | typedef HMODULE SysType; 49 | #else 50 | typedef void* SysType; 51 | #endif 52 | 53 | public: 54 | SharedLib() 55 | : lib_(nullptr) { 56 | } 57 | explicit SharedLib(const SysType& lib) 58 | : lib_(lib) { 59 | } 60 | explicit SharedLib(const char* path) { 61 | #if defined(KE_WINDOWS) 62 | lib_ = LoadLibraryA(path); 63 | #else 64 | lib_ = dlopen(path, RTLD_NOW); 65 | #endif 66 | } 67 | ~SharedLib() { 68 | if (lib_ == nullptr) 69 | return; 70 | 71 | #if defined(KE_WINDOWS) 72 | FreeLibrary(lib_); 73 | #else 74 | dlclose(lib_); 75 | #endif 76 | } 77 | 78 | explicit operator bool() const { 79 | return !!lib_; 80 | } 81 | 82 | static inline AlreadyRefed Open(const char* path, char* error = nullptr, 83 | size_t maxlength = 0) { 84 | RefPtr lib = new SharedLib(path); 85 | if (!lib || !lib->valid()) { 86 | if (!error || !maxlength) 87 | return nullptr; 88 | #if defined(KE_WINDOWS) 89 | FormatSystemError(error, maxlength); 90 | #else 91 | SafeStrcpy(error, maxlength, dlerror()); 92 | #endif 93 | return nullptr; 94 | } 95 | return lib.forget(); 96 | } 97 | 98 | void* lookup(const char* symbol) { 99 | #if defined(KE_WINDOWS) 100 | return reinterpret_cast(GetProcAddress(lib_, symbol)); 101 | #else 102 | return dlsym(lib_, symbol); 103 | #endif 104 | } 105 | 106 | template 107 | T get(const char* symbol) { 108 | return reinterpret_cast(lookup(symbol)); 109 | } 110 | 111 | bool valid() const { 112 | return !!lib_; 113 | } 114 | 115 | private: 116 | SysType lib_; 117 | }; 118 | 119 | } // namespace ke 120 | 121 | #endif // _include_amtl_os_sharedlib_h_ 122 | -------------------------------------------------------------------------------- /amtl/os/am-system-errors.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013-2015, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #ifndef _include_amtl_os_system_errors_h_ 30 | #define _include_amtl_os_system_errors_h_ 31 | 32 | #if defined(KE_WINDOWS) 33 | # define WIN32_LEAN_AND_MEAN 34 | # include 35 | #else 36 | # include 37 | #endif 38 | #include 39 | #include 40 | 41 | namespace ke { 42 | 43 | static inline void 44 | FormatSystemErrorCode(int code, char* error, size_t maxlength) { 45 | #if defined(KE_WINDOWS) 46 | if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, code, 47 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error, maxlength, nullptr)) { 48 | SafeSprintf(error, maxlength, "error code %08x", code); 49 | return; 50 | } 51 | #elif defined(KE_LINUX) && defined(__GLIBC__) 52 | const char* ptr = strerror_r(code, error, maxlength); 53 | if (ptr != error) 54 | ke::SafeSprintf(error, maxlength, "%s", ptr); 55 | #else 56 | strerror_r(code, error, maxlength); 57 | #endif 58 | } 59 | 60 | static inline void 61 | FormatSystemError(char* error, size_t maxlength) { 62 | #if defined(KE_WINDOWS) 63 | FormatSystemErrorCode(GetLastError(), error, maxlength); 64 | #else 65 | FormatSystemErrorCode(errno, error, maxlength); 66 | #endif 67 | } 68 | 69 | } // namespace ke 70 | 71 | #endif // _include_amtl_os_system_errors_h_ 72 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 1.0.{build} 2 | clone_folder: c:\projects\amtl 3 | install: 4 | - cmd: .appveyor\setup_environment.bat 5 | build_script: 6 | - cmd: .appveyor\build.bat 7 | -------------------------------------------------------------------------------- /checkout-deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This should be run inside a folder that contains sourcemod, otherwise, it will checkout things into "sm-dependencies". 3 | 4 | trap "exit" INT 5 | 6 | ismac=0 7 | iswin=0 8 | 9 | if [ `uname` = "Darwin" ]; then 10 | ismac=1 11 | elif [ `uname` != "Linux" ] && [ -n "${COMSPEC:+1}" ]; then 12 | iswin=1 13 | fi 14 | 15 | checkout () 16 | { 17 | if [ ! -d "$name" ]; then 18 | git clone $repo -b $branch $name 19 | if [ -n "$origin" ]; then 20 | cd $name 21 | git remote rm origin 22 | git remote add origin $origin 23 | cd .. 24 | fi 25 | else 26 | cd $name 27 | git checkout $branch 28 | git pull origin $branch 29 | cd .. 30 | fi 31 | } 32 | 33 | python_cmd=`command -v python` 34 | if [ -z "$python_cmd" ]; then 35 | python_cmd=`command -v python3` 36 | 37 | if [ -z "$python_cmd" ]; then 38 | echo "No suitable installation of Python detected" 39 | exit 1 40 | fi 41 | fi 42 | 43 | `$python_cmd -c "import ambuild2"` 2>&1 1>/dev/null 44 | if [ $? -eq 1 ]; then 45 | echo "AMBuild is required to build AMTL" 46 | 47 | `$python_cmd -m pip --version` 2>&1 1>/dev/null 48 | if [ $? -eq 1 ]; then 49 | echo "The detected Python installation does not have PIP" 50 | echo "Installing the latest version of PIP available (VIA \"get-pip.py\")" 51 | 52 | get_pip="./get-pip.py" 53 | get_pip_url="https://bootstrap.pypa.io/get-pip.py" 54 | 55 | if [ `command -v wget` ]; then 56 | wget $get_pip_url -O $get_pip --no-check-certificate 57 | elif [ `command -v curl` ]; then 58 | curl -o $get_pip $get_pip_url --insecure 59 | else 60 | echo "Failed to locate wget or curl. Install one of these programs to download 'get-pip.py'." 61 | exit 1 62 | fi 63 | 64 | $python_cmd $get_pip 65 | if [ $? -eq 1 ]; then 66 | echo "Installation of PIP has failed" 67 | exit 1 68 | fi 69 | fi 70 | 71 | repo="https://github.com/alliedmodders/ambuild" 72 | origin= 73 | branch=master 74 | name=ambuild 75 | checkout 76 | 77 | if [ $iswin -eq 1 ] || [ $ismac -eq 1 ]; then 78 | $python_cmd -m pip install ./ambuild 79 | else 80 | echo "Installing AMBuild at the user level. Location can be: ~/.local/bin" 81 | $python_cmd -m pip install --user ./ambuild 82 | fi 83 | fi 84 | -------------------------------------------------------------------------------- /compat/stdcxx.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2023, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | extern "C" { 33 | double __attribute__((weak)) __pow_finite(double x, double y) { return pow(x, y); } 34 | double __attribute__((weak)) __atan2_finite(double x, double y) { return atan2(x, y); } 35 | double __attribute__((weak)) __log_finite(double x) { return log(x); } 36 | double __attribute__((weak)) __acos_finite(double x) { return acos(x); } 37 | double __attribute__((weak)) __asin_finite(double x) { return asin(x); } 38 | 39 | float __attribute__((weak)) __powf_finite(float x, float y) { return powf(x, y); } 40 | float __attribute__((weak)) __atan2f_finite(float x, float y) { return atan2f(x, y); } 41 | float __attribute__((weak)) __logf_finite(float x) { return logf(x); } 42 | float __attribute__((weak)) __acosf_finite(float x) { return acosf(x); } 43 | float __attribute__((weak)) __asinf_finite(float x) { return asinf(x); } 44 | } 45 | -------------------------------------------------------------------------------- /configure.py: -------------------------------------------------------------------------------- 1 | # vim: set ts=2 sw=2 tw=99 noet: 2 | import sys 3 | try: 4 | from ambuild2 import run 5 | except: 6 | try: 7 | import ambuild 8 | sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n') 9 | sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n') 10 | except: 11 | sys.stderr.write('AMBuild must be installed to build this project.\n') 12 | sys.stderr.write('http://www.alliedmods.net/ambuild\n') 13 | sys.exit(1) 14 | 15 | # Hack to show a decent upgrade message, which wasn't done until 2.2. 16 | ambuild_version = getattr(run, 'CURRENT_API', '2.1') 17 | if ambuild_version.startswith('2.1'): 18 | sys.stderr.write("AMBuild 2.2 or higher is required; please update\n") 19 | sys.exit(1) 20 | 21 | parser = run.BuildParser(sourcePath=sys.path[0], api='2.2') 22 | parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug', 23 | help='Enable debugging symbols') 24 | parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', 25 | help='Enable optimization') 26 | parser.options.add_argument('--std', type=str, default=None, help='Override C++ standard') 27 | parser.Configure() 28 | -------------------------------------------------------------------------------- /tests/AMBuild.tests: -------------------------------------------------------------------------------- 1 | # vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: 2 | # 3 | # Copyright (C) 2004-2012 David Anderson 4 | # 5 | # This file is part of SourcePawn. 6 | # 7 | # SourcePawn is free software: you can redistribute it and/or modify it under 8 | # the terms of the GNU General Public License as published by the Free 9 | # Software Foundation, either version 3 of the License, or (at your option) 10 | # any later version. 11 | # 12 | # SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 | # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # SourcePawn. If not, see http://www.gnu.org/licenses/. 18 | # 19 | import os 20 | 21 | binary = KE.StaticLibrary(builder, 'libgtest') 22 | binary.compiler.includes += [ 23 | os.path.join(builder.sourcePath, 'third_party', 'googletest', 'googletest', 'include'), 24 | os.path.join(builder.sourcePath, 'third_party', 'googletest', 'googletest'), 25 | ] 26 | binary.sources += [ 27 | os.path.join('..', 'third_party', 'googletest', 'googletest', 'src', 'gtest-all.cc'), 28 | ] 29 | libgtest = builder.Add(binary) 30 | 31 | binary = KE.Program(builder, 'testrunner') 32 | compiler = binary.compiler 33 | compiler.includes += [ 34 | os.path.join(builder.sourcePath), 35 | os.path.join(builder.sourcePath, 'third_party', 'googletest', 'googletest', 'include'), 36 | ] 37 | 38 | if compiler.like('msvc'): 39 | compiler.linkflags.append('/SUBSYSTEM:CONSOLE') 40 | if builder.cxx.target.platform == 'linux': 41 | compiler.linkflags.append('-ldl') 42 | compiler.linkflags.append(libgtest.binary) 43 | compiler.linkflags.append(KE.libamtl) 44 | 45 | binary.sources += [ 46 | 'main.cpp', 47 | 'test-argparser.cpp', 48 | 'test-bits.cpp', 49 | 'test-callable.cpp', 50 | 'test-deque.cpp', 51 | 'test-flags.cpp', 52 | 'test-hashmap.cpp', 53 | 'test-inlinelist.cpp', 54 | 'test-priority-queue.cpp', 55 | 'test-refcounting.cpp', 56 | 'test-raii.cpp', 57 | 'test-string.cpp', 58 | 'test-system.cpp', 59 | 'test-threadlocal-threaded.cpp', 60 | 'test-threadlocal-unthreaded.cpp', 61 | 'test-time.cpp', 62 | 'test-vector.cpp', 63 | ] 64 | 65 | node = builder.Add(binary) 66 | builder.AddCopy(node.binary, builder.dist_folder) 67 | -------------------------------------------------------------------------------- /tests/main.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "runner.h" 36 | 37 | using namespace ke; 38 | 39 | int 40 | main(int argc, char** argv) 41 | { 42 | ::testing::InitGoogleTest(&argc, argv); 43 | return RUN_ALL_TESTS(); 44 | } 45 | 46 | #if defined(__GNUC__) 47 | extern "C" void 48 | __cxa_pure_virtual() 49 | { 50 | abort(); 51 | } 52 | 53 | void* 54 | operator new(size_t amount) 55 | { 56 | return malloc(amount); 57 | } 58 | 59 | void* 60 | operator new[](size_t amount) 61 | { 62 | return malloc(amount); 63 | } 64 | 65 | void 66 | operator delete(void* p) 67 | { 68 | free(p); 69 | } 70 | 71 | void 72 | operator delete[](void* p) 73 | { 74 | free(p); 75 | } 76 | #endif 77 | -------------------------------------------------------------------------------- /tests/runner.h: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #ifndef _include_amtl_runner_h_ 31 | #define _include_amtl_runner_h_ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | namespace ke { 39 | 40 | class FallibleMalloc 41 | { 42 | public: 43 | FallibleMalloc() 44 | : shouldOutOfMemory_(false), 45 | ooms_(0), 46 | overflows_(0) 47 | {} 48 | 49 | void* am_malloc(size_t amount) { 50 | if (shouldOutOfMemory_) { 51 | reportOutOfMemory(); 52 | return nullptr; 53 | } 54 | #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) 55 | return malloc(amount); 56 | #else 57 | return ::malloc(amount); 58 | #endif 59 | } 60 | void am_free(void* p) { 61 | #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) 62 | return free(p); 63 | #else 64 | return ::free(p); 65 | #endif 66 | } 67 | void reportOutOfMemory() { 68 | ooms_++; 69 | } 70 | void reportAllocationOverflow() { 71 | overflows_++; 72 | } 73 | 74 | void setOutOfMemory(bool oom) { 75 | shouldOutOfMemory_ = oom; 76 | } 77 | size_t ooms() const { 78 | return ooms_; 79 | } 80 | size_t overflows() const { 81 | return overflows_; 82 | } 83 | 84 | private: 85 | bool shouldOutOfMemory_; 86 | size_t ooms_; 87 | size_t overflows_; 88 | }; 89 | 90 | } // namespace ke 91 | 92 | #endif // _include_amtl_runner_h_ 93 | -------------------------------------------------------------------------------- /tests/test-bits.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=4 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include "runner.h" 33 | 34 | using namespace ke; 35 | 36 | TEST(Bits, Multiply) { 37 | EXPECT_TRUE(IsUintMultiplySafe(0x80000000, 1)); 38 | EXPECT_FALSE(IsUintMultiplySafe(0x80000000, 2)); 39 | } 40 | 41 | TEST(Bits, MallocAlignment) { 42 | EXPECT_GE(kMallocAlignment, (size_t)16); 43 | } 44 | 45 | TEST(Bits, FindLeftmostBit) { 46 | EXPECT_EQ(FindLeftmostBit32(0x7f), 6); 47 | EXPECT_EQ(FindLeftmostBit64(0x7f), 6); 48 | 49 | EXPECT_EQ(FindLeftmostBit32(0xffffffff), 31); 50 | EXPECT_EQ(FindLeftmostBit64(0xffffffffffffffffULL), 63); 51 | } 52 | 53 | TEST(Bits, FindRightmostBit) { 54 | EXPECT_EQ(FindRightmostBit(0x7d), 0); 55 | EXPECT_EQ(FindRightmostBit(0x7d), 0); 56 | 57 | EXPECT_EQ(FindRightmostBit(0xffffffc0), 6); 58 | if (sizeof(size_t) == 8) 59 | EXPECT_EQ(FindRightmostBit(0xfffc000000000000ULL), 50); 60 | else 61 | EXPECT_EQ(FindRightmostBit(0xfffc000000000000ULL), 0); 62 | } 63 | 64 | TEST(Bits, PointerBits) { 65 | int local = 0; 66 | void* ptr = &local; 67 | 68 | EXPECT_EQ(GetPointerBits<2>(ptr), 0); 69 | 70 | void* changed = SetPointerBits(ptr, 0x3); 71 | void* expected = reinterpret_cast(reinterpret_cast(ptr) | uintptr_t(0x3)); 72 | EXPECT_EQ(changed, expected); 73 | 74 | EXPECT_EQ(ClearPointerBits<2>(changed), ptr); 75 | } 76 | -------------------------------------------------------------------------------- /tests/test-callable.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | static int 38 | test_old_fn(int x) 39 | { 40 | return 99 + x; 41 | } 42 | 43 | class MoveObj 44 | { 45 | public: 46 | static unsigned sNumMoves; 47 | 48 | MoveObj() { 49 | sNumMoves = 0; 50 | } 51 | MoveObj(MoveObj&& other) { 52 | sNumMoves++; 53 | } 54 | 55 | unsigned count() const { 56 | return sNumMoves; 57 | } 58 | 59 | private: 60 | MoveObj(const MoveObj& other); 61 | void operator =(const MoveObj& other); 62 | }; 63 | unsigned MoveObj::sNumMoves = 0; 64 | 65 | class CallableObj 66 | { 67 | public: 68 | int operator ()(int x) const { 69 | return x + 34; 70 | } 71 | }; 72 | 73 | TEST(Callable, BasicFunction) { 74 | int egg = 20; 75 | auto fn = [&egg](int x) -> int { return egg + x + 1; }; 76 | 77 | Function ptr(fn); 78 | EXPECT_EQ(ptr(10), 31); 79 | 80 | ptr = [](int x) -> int { return x + 15; }; 81 | EXPECT_EQ(ptr(7), 22); 82 | 83 | ptr = test_old_fn; 84 | EXPECT_EQ(ptr(10), 109); 85 | 86 | CallableObj obj; 87 | ptr = obj; 88 | EXPECT_EQ(ptr(66), 100); 89 | 90 | Function ptr2 = [](MoveObj&& obj) -> unsigned { 91 | MoveObj other(std::move(obj)); 92 | return other.count(); 93 | }; 94 | 95 | MoveObj moveObj; 96 | EXPECT_EQ(ptr2(std::move(moveObj)), (unsigned)1); 97 | } 98 | 99 | TEST(Callable, InlineStorage) { 100 | Function ptr = []() -> int { return 10; }; 101 | 102 | EXPECT_TRUE(ptr.usingInlineStorage()); 103 | EXPECT_EQ(ptr(), 10); 104 | 105 | static size_t dtors = 0; 106 | struct CallDtorObj { 107 | ~CallDtorObj() { 108 | dtors++; 109 | } 110 | }; 111 | 112 | struct { 113 | int a; 114 | void *b, *c, *d, *e, *f, *g; 115 | void *h, *j, *k, *m, *n, *o, *p; 116 | } huge_struct = {20}; 117 | CallDtorObj test_dtor; 118 | ptr = [huge_struct, test_dtor]() -> int { return huge_struct.a; }; 119 | EXPECT_FALSE(ptr.usingInlineStorage()); 120 | EXPECT_EQ(ptr(), 20); 121 | 122 | ptr = nullptr; 123 | EXPECT_EQ(dtors, (size_t)2); 124 | } 125 | 126 | TEST(Callable, Move) { 127 | static size_t ctors = 0; 128 | static size_t copyctors = 0; 129 | static size_t movectors = 0; 130 | static size_t dtors = 0; 131 | struct CallDtorObj { 132 | CallDtorObj() { 133 | ctors++; 134 | } 135 | CallDtorObj(const CallDtorObj& other) { 136 | copyctors++; 137 | } 138 | CallDtorObj(CallDtorObj&& other) { 139 | movectors++; 140 | } 141 | ~CallDtorObj() { 142 | dtors++; 143 | } 144 | }; 145 | 146 | CallDtorObj test_dtor; 147 | Function ptr = [test_dtor] {}; 148 | 149 | EXPECT_EQ(dtors, (size_t)1); 150 | 151 | ctors = 0; 152 | copyctors = 0; 153 | movectors = 0; 154 | dtors = 0; 155 | 156 | Function ptr2 = ptr; 157 | EXPECT_EQ(ctors, (size_t)0); 158 | EXPECT_EQ(copyctors, (size_t)1); 159 | EXPECT_EQ(movectors, (size_t)0); 160 | EXPECT_EQ(dtors, (size_t)0); 161 | 162 | copyctors = 0; 163 | 164 | Function ptr3 = std::move(ptr2); 165 | EXPECT_EQ(ctors, (size_t)0); 166 | EXPECT_EQ(copyctors, (size_t)0); 167 | EXPECT_EQ(movectors, (size_t)0); 168 | EXPECT_EQ(dtors, (size_t)0); 169 | 170 | copyctors = 0; 171 | 172 | auto fn = [test_dtor] {}; 173 | Function ptr4 = std::move(fn); 174 | EXPECT_EQ(ctors, (size_t)0); 175 | EXPECT_EQ(copyctors, (size_t)1); 176 | EXPECT_EQ(movectors, (size_t)1); 177 | EXPECT_EQ(dtors, (size_t)0); 178 | } 179 | -------------------------------------------------------------------------------- /tests/test-deque.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #include 30 | #include 31 | #include 32 | #include "runner.h" 33 | 34 | using namespace ke; 35 | 36 | TEST(Deque, Basic) { 37 | std::deque dq; 38 | 39 | for (int i = 0; i < 4; i++) { 40 | dq.push_back(i); 41 | ASSERT_EQ(dq.size(), size_t(i + 1)); 42 | } 43 | for (int i = 0; i < 4; i++) { 44 | dq.push_front(i + 4); 45 | ASSERT_EQ(dq.size(), size_t(i + 5)); 46 | } 47 | 48 | EXPECT_EQ(dq.back(), 3); 49 | EXPECT_EQ(dq.front(), 7); 50 | dq.pop_back(); 51 | dq.pop_front(); 52 | EXPECT_EQ(PopFront(&dq), 6); 53 | EXPECT_EQ(PopBack(&dq), 2); 54 | 55 | EXPECT_EQ(dq.size(), (size_t)4); 56 | 57 | while (!dq.empty()) 58 | dq.pop_back(); 59 | EXPECT_EQ(dq.size(), (size_t)0); 60 | } 61 | 62 | TEST(Deque, PrependEmpty) { 63 | std::deque dq; 64 | 65 | for (int i = 0; i < 8; i++) { 66 | if (i % 2 == 0) 67 | dq.push_front(i); 68 | else 69 | dq.push_back(i); 70 | EXPECT_EQ(dq.size(), size_t(i + 1)); 71 | } 72 | 73 | while (!dq.empty()) 74 | dq.pop_front(); 75 | EXPECT_EQ(dq.size(), (size_t)0); 76 | } 77 | 78 | TEST(Deque, Resize) { 79 | std::deque dq; 80 | for (int i = 0; i < 387; i++) 81 | dq.push_front(i); 82 | for (int i = 0; i < 293; i++) 83 | dq.push_back(i); 84 | 85 | ASSERT_EQ(dq.size(), size_t(293 + 387)); 86 | 87 | for (int i = 292; i >= 0; i--) { 88 | EXPECT_EQ(PopBack(&dq), i); 89 | } 90 | for (int i = 386; i >= 0; i--) { 91 | EXPECT_EQ(PopFront(&dq), i); 92 | } 93 | 94 | // Check that we can still add. 95 | dq.push_back(5); 96 | ASSERT_EQ(PopFront(&dq), 5); 97 | dq.push_back(6); 98 | ASSERT_EQ(PopBack(&dq), 6); 99 | 100 | dq.push_front(7); 101 | ASSERT_EQ(PopBack(&dq), 7); 102 | dq.push_front(8); 103 | ASSERT_EQ(PopFront(&dq), 8); 104 | } 105 | 106 | TEST(Deque, Move) { 107 | std::deque dq1; 108 | 109 | dq1.push_back(10); 110 | 111 | { 112 | std::deque dq2 = std::move(dq1); 113 | ASSERT_EQ(dq2.size(), (size_t)1); 114 | ASSERT_EQ(PopFront(&dq2), 10); 115 | } 116 | 117 | ASSERT_EQ(dq1.size(), (size_t)0); 118 | 119 | // Append so we can make sure that it's not holding a deleted pointer. 120 | dq1.push_back(11); 121 | } 122 | -------------------------------------------------------------------------------- /tests/test-flags.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | enum class Scoped : uint32_t { 38 | Flag0 = (1 << 0), 39 | Flag1 = (1 << 1), 40 | Flag2 = (1 << 2), 41 | Flag3 = (1 << 3) 42 | }; 43 | KE_DEFINE_ENUM_OPERATORS(Scoped) 44 | 45 | TEST(Flags, Basic) { 46 | Flags flags; 47 | ASSERT_TRUE(!flags); 48 | ASSERT_FALSE(flags); 49 | 50 | flags += Scoped::Flag0; 51 | ASSERT_TRUE((bool)flags); 52 | 53 | flags += Scoped::Flag1; 54 | 55 | Flags other(Scoped::Flag1 | Scoped::Flag2); 56 | ASSERT_NE(flags, other); 57 | ASSERT_EQ(other.bits(), (uint32_t)0x6); 58 | 59 | flags -= other; 60 | ASSERT_EQ(flags, Scoped::Flag0); 61 | 62 | uint32_t value = flags.bits(); 63 | ASSERT_EQ(value, (uint32_t)0x1); 64 | 65 | flags |= other; 66 | ASSERT_EQ(flags.bits(), (uint32_t)0x7); 67 | 68 | flags &= other; 69 | ASSERT_EQ(flags.bits(), (uint32_t)0x6); 70 | } 71 | -------------------------------------------------------------------------------- /tests/test-hashmap.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "runner.h" 35 | 36 | using namespace ke; 37 | 38 | struct StringPolicy { 39 | static inline uint32_t hash(const char* key) { 40 | return FastHashCharSequence(key, strlen(key)); 41 | } 42 | static inline bool matches(const char* find, const std::string& key) { 43 | return key.compare(find) == 0; 44 | } 45 | }; 46 | 47 | TEST(HashMap, Basic) { 48 | typedef HashMap Map; 49 | Map map; 50 | 51 | ASSERT_TRUE(map.init()); 52 | 53 | Map::Result r = map.find("cat"); 54 | ASSERT_FALSE(r.found()); 55 | 56 | Map::Insert i = map.findForAdd("cat"); 57 | ASSERT_FALSE(i.found()); 58 | ASSERT_TRUE(map.add(i, std::string("cat"), 5)); 59 | EXPECT_EQ(r->value, 5); 60 | 61 | Map::iterator iter = map.iter(); 62 | EXPECT_EQ(iter->key.compare("cat"), 0); 63 | EXPECT_EQ(iter->value, 5); 64 | iter.next(); 65 | EXPECT_TRUE(iter.empty()); 66 | 67 | i = map.findForAdd("cat"); 68 | EXPECT_TRUE(i.found()); 69 | 70 | r = map.find("dog"); 71 | EXPECT_FALSE(r.found()); 72 | 73 | r = map.find("cat"); 74 | ASSERT_TRUE(r.found()); 75 | EXPECT_EQ(r->value, 5); 76 | map.remove(r); 77 | 78 | r = map.find("cat"); 79 | EXPECT_FALSE(r.found()); 80 | } 81 | 82 | TEST(HashMap, Bug6527) { 83 | typedef HashMap Map; 84 | Map map; 85 | 86 | ASSERT_TRUE(map.init(16)); 87 | 88 | { 89 | char key[] = "bb"; 90 | Map::Insert p = map.findForAdd(key); 91 | ASSERT_FALSE(p.found()); 92 | ASSERT_TRUE(map.add(p, key)); 93 | p->value = 0xabab; 94 | } 95 | 96 | { 97 | char key[] = "dddd"; 98 | Map::Insert p = map.findForAdd(key); 99 | ASSERT_FALSE(p.found()); 100 | ASSERT_TRUE(map.add(p, key)); 101 | p->value = 0xacac; 102 | } 103 | 104 | { 105 | char key[] = "bb"; 106 | map.removeIfExists(key); 107 | } 108 | 109 | { 110 | char key[] = "dddd"; 111 | Map::Insert p = map.findForAdd(key); 112 | if (!p.found()) 113 | map.add(p, key); 114 | p->value = 0xadad; 115 | } 116 | 117 | bool found = false; 118 | for (Map::iterator iter = map.iter(); !iter.empty(); iter.next()) { 119 | if (iter->key.compare("dddd") == 0) { 120 | // Should only occur once. 121 | EXPECT_FALSE(found); 122 | found = true; 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /tests/test-inlinelist.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | class IntThing : public InlineListNode 38 | { 39 | public: 40 | IntThing(int value) 41 | : value_(value) 42 | {} 43 | ~IntThing() {} 44 | int value() const { 45 | return value_; 46 | } 47 | 48 | private: 49 | int value_; 50 | }; 51 | 52 | TEST(InlineList, Basic) { 53 | IntThing thing1(1); 54 | IntThing thing2(2); 55 | IntThing thing3(3); 56 | IntThing thing4(4); 57 | IntThing thing5(5); 58 | 59 | // Do these test twice. InlineList does not take ownership of pointers, 60 | // so we should be guaranteed we can keep moving them in between lists. 61 | for (size_t i = 0; i <= 1; i++) { 62 | InlineList list; 63 | 64 | InlineList::iterator iter = list.begin(); 65 | ASSERT_EQ(iter, list.end()); 66 | 67 | list.append(&thing1); 68 | list.append(&thing2); 69 | list.append(&thing3); 70 | list.append(&thing4); 71 | list.append(&thing5); 72 | 73 | iter = list.begin(); 74 | for (int n = 1; n <= 5; n++) { 75 | EXPECT_EQ(iter->value(), n); 76 | iter++; 77 | } 78 | EXPECT_EQ(iter, list.end()); 79 | 80 | list.remove(&thing1); 81 | iter = list.begin(); 82 | EXPECT_EQ(iter->value(), 2); 83 | 84 | list.remove(&thing5); 85 | iter = list.begin(); 86 | iter++; 87 | iter++; 88 | EXPECT_EQ(iter->value(), 4); 89 | iter++; 90 | EXPECT_EQ(iter, list.end()); 91 | 92 | list.remove(&thing3); 93 | iter = list.begin(); 94 | EXPECT_EQ(iter->value(), 2); 95 | iter++; 96 | EXPECT_EQ(iter->value(), 4); 97 | iter++; 98 | EXPECT_EQ(iter, list.end()); 99 | 100 | iter = list.begin(); 101 | while (iter != list.end()) 102 | iter = list.erase(iter); 103 | 104 | EXPECT_EQ(list.begin(), list.end()); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/test-priority-queue.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | TEST(PriorityQueue, Basic) { 38 | PriorityQueue pq; 39 | pq.add(16); 40 | pq.add(16); 41 | pq.add(16); 42 | pq.add(9); 43 | pq.add(77); 44 | pq.add(3); 45 | 46 | EXPECT_EQ(pq.pop(), 3); 47 | EXPECT_EQ(pq.pop(), 9); 48 | EXPECT_EQ(pq.pop(), 16); 49 | EXPECT_EQ(pq.pop(), 16); 50 | EXPECT_EQ(pq.pop(), 16); 51 | EXPECT_EQ(pq.pop(), 77); 52 | EXPECT_TRUE(pq.empty()); 53 | } 54 | -------------------------------------------------------------------------------- /tests/test-raii.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=4 ts=8 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2021 AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include "runner.h" 33 | 34 | using namespace ke; 35 | 36 | TEST(ScopeGuard, Invoke) 37 | { 38 | int invokes = 0; 39 | 40 | { 41 | auto guard1 = MakeScopeGuard([&]() -> void { 42 | invokes++; 43 | }); 44 | 45 | { 46 | auto guard2 = MakeScopeGuard([&]() -> void { 47 | invokes++; 48 | }); 49 | } 50 | ASSERT_EQ(invokes, 1); 51 | } 52 | ASSERT_EQ(invokes, 2); 53 | } 54 | 55 | TEST(ScopeGuard, Cancel) 56 | { 57 | int invokes = 0; 58 | 59 | { 60 | auto guard1 = MakeScopeGuard([&]() -> void { 61 | invokes++; 62 | }); 63 | 64 | guard1.cancel(); 65 | } 66 | ASSERT_EQ(invokes, 0); 67 | } 68 | -------------------------------------------------------------------------------- /tests/test-refcounting.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "runner.h" 36 | 37 | using namespace ke; 38 | 39 | static int sDtors = 0; 40 | 41 | class Counted : public Refcounted 42 | { 43 | public: 44 | ~Counted() { 45 | sDtors++; 46 | } 47 | }; 48 | 49 | class SubCounted : public Counted 50 | { 51 | }; 52 | 53 | void 54 | TypeChecks_DoNotCall() 55 | { 56 | RefPtr counted; 57 | if (counted) 58 | abort(); 59 | } 60 | 61 | static inline RefPtr 62 | PassThrough(const RefPtr& obj) 63 | { 64 | return obj; 65 | } 66 | 67 | TEST(RefPtr, Basic) { 68 | { RefPtr obj(new Counted()); } 69 | EXPECT_EQ(sDtors, 1); 70 | { RefPtr obj(new Counted()); } 71 | EXPECT_EQ(sDtors, 2); 72 | { 73 | Counted* counted = new Counted(); 74 | counted->AddRef(); 75 | RefPtr obj(AdoptRef(counted)); 76 | } 77 | EXPECT_EQ(sDtors, 3); 78 | 79 | // Check that subclass assignment works. 80 | { 81 | RefPtr obj(new SubCounted()); 82 | RefPtr obj2(PassThrough(new SubCounted())); 83 | } 84 | EXPECT_EQ(sDtors, 5); 85 | 86 | sDtors = 0; 87 | 88 | { 89 | RefPtr obj(new Counted()); 90 | RefPtr obj2 = PassThrough(obj); 91 | RefPtr obj3 = PassThrough(obj); 92 | EXPECT_EQ(sDtors, 0); 93 | RefPtr obj4 = PassThrough(PassThrough(PassThrough(obj))); 94 | EXPECT_EQ(sDtors, 0); 95 | } 96 | EXPECT_EQ(sDtors, 1); 97 | 98 | sDtors = 0; 99 | { AtomicRef obj(new Counted()); } 100 | EXPECT_EQ(sDtors, 1); 101 | 102 | sDtors = 0; 103 | { 104 | AtomicRef obj; 105 | obj = new Counted(); 106 | obj = new Counted(); 107 | obj = nullptr; 108 | } 109 | EXPECT_EQ(sDtors, 2); 110 | 111 | sDtors = 0; 112 | { 113 | RefPtr obj(new Counted()); 114 | AlreadyRefed xfer = obj.take(); 115 | EXPECT_FALSE(obj); 116 | EXPECT_TRUE(!!xfer); 117 | } 118 | EXPECT_EQ(sDtors, 1); 119 | } 120 | -------------------------------------------------------------------------------- /tests/test-string.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=4 ts=8 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | TEST(String, Sprintf) { 38 | int64_t x = 1234; 39 | char buffer[256]; 40 | SafeSprintf(buffer, sizeof(buffer), "%" KE_FMT_I64, x); 41 | ASSERT_EQ(strcmp(buffer, "1234"), 0); 42 | } 43 | 44 | TEST(String, Allocating) { 45 | int a = INT_MAX; 46 | const char* value = "Hello this is a test."; 47 | const char* expect = "A: 2147483647 B: Hello this is a test."; 48 | std::unique_ptr ptr = Sprintf("A: %d B: %s", a, value); 49 | EXPECT_EQ(strcmp(ptr.get(), expect), 0); 50 | 51 | auto str = StringPrintf("A: %d B: %s", a, value); 52 | EXPECT_EQ(str, expect); 53 | } 54 | 55 | TEST(String, Split) { 56 | auto out = Split(" ", " "); 57 | EXPECT_EQ(out.size(), (size_t)6); 58 | for (size_t i = 0; i < out.size(); i++) { 59 | EXPECT_EQ(out[i].size(), (size_t)0); 60 | } 61 | 62 | out = Split("egg", " "); 63 | EXPECT_EQ(out.size(), (size_t)1); 64 | EXPECT_EQ(out[0].compare("egg"), 0); 65 | 66 | out = Split("", "egg"); 67 | EXPECT_EQ(out.size(), (size_t)0); 68 | 69 | out = Split("xaba", "a"); 70 | EXPECT_EQ(out.size(), (size_t)3); 71 | EXPECT_EQ(out[0].compare("x"), 0); 72 | EXPECT_EQ(out[1].compare("b"), 0); 73 | EXPECT_EQ(out[2].compare(""), 0); 74 | 75 | out = Split("egg ham", " "); 76 | EXPECT_EQ(out.size(), (size_t)2); 77 | EXPECT_EQ(out[0].compare("egg"), 0); 78 | EXPECT_EQ(out[1].compare("ham"), 0); 79 | } 80 | 81 | TEST(String, Join) { 82 | std::vector in; 83 | 84 | auto result = Join(in, "x"); 85 | EXPECT_EQ(result, ""); 86 | 87 | in.emplace_back("abc"); 88 | result = Join(in, "x"); 89 | EXPECT_EQ(result, "abc"); 90 | 91 | in.emplace_back("xyz"); 92 | result = Join(in, "T"); 93 | EXPECT_EQ(result, "abcTxyz"); 94 | 95 | in.emplace_back("def"); 96 | result = Join(in, ""); 97 | EXPECT_EQ(result, "abcxyzdef"); 98 | 99 | in = {"a", "b", "", "d" }; 100 | result = Join(in, ","); 101 | EXPECT_EQ(result, "a,b,,d"); 102 | 103 | in = {"a", "b", "c", "" }; 104 | result = Join(in, ","); 105 | EXPECT_EQ(result, "a,b,c,"); 106 | } 107 | 108 | TEST(String, Case) { 109 | const char* str = "samPle1.com"; 110 | EXPECT_EQ(Uppercase(str), "SAMPLE1.COM"); 111 | EXPECT_EQ(Lowercase(str), "sample1.com"); 112 | 113 | EXPECT_EQ(Lowercase(""), ""); 114 | } 115 | 116 | TEST(String, StrCpy) { 117 | char buffer[6]; 118 | 119 | SafeStrcpy(buffer, sizeof(buffer), "hello"); 120 | EXPECT_EQ(strcmp(buffer, "hello"), 0); 121 | 122 | SafeStrcpy(buffer, sizeof(buffer), "hello, crab"); 123 | EXPECT_EQ(strcmp(buffer, "hello"), 0); 124 | 125 | SafeStrcpyN(buffer, sizeof(buffer), "asdfasdf", 8); 126 | EXPECT_EQ(strcmp(buffer, "asdfa"), 0); 127 | 128 | SafeStrcpyN(buffer, sizeof(buffer), "qwertyuiop", 3); 129 | EXPECT_EQ(strcmp(buffer, "qwe"), 0); 130 | } 131 | 132 | TEST(String, StartsWith) { 133 | std::string str("blah"); 134 | 135 | EXPECT_TRUE(StartsWith(str, "b")); 136 | EXPECT_TRUE(StartsWith(str, "blah")); 137 | EXPECT_FALSE(StartsWith(str, "a")); 138 | EXPECT_FALSE(StartsWith(str, "blah2")); 139 | } 140 | 141 | TEST(String, EndsWith) { 142 | std::string str("blah"); 143 | 144 | EXPECT_TRUE(EndsWith(str, "h")); 145 | EXPECT_TRUE(EndsWith(str, "blah")); 146 | EXPECT_FALSE(EndsWith(str, "a")); 147 | EXPECT_FALSE(EndsWith(str, "blah2")); 148 | } 149 | 150 | TEST(String, SafeStrcat) { 151 | char buffer[6] = "hello"; 152 | 153 | buffer[1] = '\0'; 154 | EXPECT_EQ(SafeStrcat(buffer, 0, "blah"), (size_t)1); 155 | EXPECT_EQ(SafeStrcat(buffer, 1, "blah"), (size_t)1); 156 | EXPECT_EQ(SafeStrcat(buffer, 2, "blah"), (size_t)1); 157 | EXPECT_EQ(buffer[1], '\0'); 158 | EXPECT_EQ(buffer[2], 'l'); 159 | 160 | EXPECT_EQ(SafeStrcat(buffer, sizeof(buffer), "b"), (size_t)2); 161 | EXPECT_EQ(strcmp(buffer, "hb"), 0); 162 | 163 | EXPECT_EQ(SafeStrcat(buffer, sizeof(buffer), "hamocrab"), (size_t)5); 164 | EXPECT_EQ(strcmp(buffer, "hbham"), 0); 165 | } 166 | -------------------------------------------------------------------------------- /tests/test-system.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | TEST(System, SharedLibs) { 38 | const char* libname = "unknown-library"; 39 | #if defined(KE_WINDOWS) 40 | const char* symbol = "GetProcAddress"; 41 | libname = "kernel32.dll"; 42 | #elif defined(KE_POSIX) 43 | const char* symbol = "malloc"; 44 | # if defined(KE_MACOSX) 45 | libname = "libc.dylib"; 46 | # elif defined(KE_LINUX) 47 | libname = "libc.so.6"; 48 | # endif 49 | #endif 50 | 51 | RefPtr lib = SharedLib::Open(libname, nullptr, 0); 52 | EXPECT_TRUE(lib); 53 | EXPECT_NE(lib->lookup(symbol), nullptr); 54 | EXPECT_NE(lib->get(symbol), nullptr); 55 | } 56 | 57 | TEST(System, Paths) { 58 | #if defined(KE_WINDOWS) 59 | const char* bad = "C:/egg.txt"; 60 | const char* good = "C:\\egg.txt"; 61 | #else 62 | const char* bad = "\\egg.txt"; 63 | const char* good = "/egg.txt"; 64 | #endif 65 | 66 | char buffer[255]; 67 | path::Format(buffer, sizeof(buffer), "%s", bad); 68 | EXPECT_EQ(strcmp(buffer, good), 0); 69 | } 70 | -------------------------------------------------------------------------------- /tests/test-threadlocal-threaded.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include "runner.h" 36 | 37 | using namespace ke; 38 | 39 | static ThreadLocal sThreadVar; 40 | static ThreadLocal sThreadVarPointer; 41 | 42 | class VarThread 43 | { 44 | public: 45 | VarThread() 46 | : succeeded_(false) 47 | {} 48 | 49 | void Run(int value) { 50 | ASSERT_EQ(sThreadVar.get(), 0); 51 | 52 | sThreadVar = value; 53 | ASSERT_EQ(sThreadVar.get(), 20); 54 | 55 | succeeded_ = true; 56 | } 57 | 58 | bool succeeded() const { 59 | return succeeded_; 60 | } 61 | 62 | private: 63 | bool succeeded_; 64 | }; 65 | 66 | TEST(ThreadLocal, Threaded) { 67 | sThreadVar = 10; 68 | 69 | VarThread run; 70 | auto thread = ke::NewThread("Test Thread", [&run](int value) -> void { 71 | run.Run(value); 72 | }, 20); 73 | thread->join(); 74 | thread = nullptr; 75 | 76 | ASSERT_TRUE(run.succeeded()); 77 | EXPECT_EQ(sThreadVar.get(), 10); 78 | 79 | // Check that pointers are allowed in T. 80 | sThreadVarPointer = &run; 81 | EXPECT_EQ(sThreadVarPointer.get(), &run); 82 | } 83 | -------------------------------------------------------------------------------- /tests/test-threadlocal-unthreaded.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=8 ts=2 sw=2 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #define KE_SINGLE_THREADED 31 | #include 32 | #include 33 | #include "runner.h" 34 | 35 | using namespace ke; 36 | 37 | static ThreadLocal sVar; 38 | 39 | TEST(ThreadLocal, Unthreaded) { 40 | EXPECT_EQ(sVar.get(), 0); 41 | sVar = 10; 42 | EXPECT_EQ(sVar.get(), 10); 43 | } 44 | -------------------------------------------------------------------------------- /tests/test-time.cpp: -------------------------------------------------------------------------------- 1 | // vim: set sts=4 ts=8 sw=4 tw=99 et: 2 | // 3 | // Copyright (C) 2013, David Anderson and AlliedModders LLC 4 | // All rights reserved. 5 | // 6 | // Redistribution and use in source and binary forms, with or without 7 | // modification, are permitted provided that the following conditions are met: 8 | // 9 | // * Redistributions of source code must retain the above copyright notice, this 10 | // list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above copyright notice, 12 | // this list of conditions and the following disclaimer in the documentation 13 | // and/or other materials provided with the distribution. 14 | // * Neither the name of AlliedModders LLC nor the names of its contributors 15 | // may be used to endorse or promote products derived from this software 16 | // without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | // POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | #include 32 | 33 | #if __cplusplus >= 201703L 34 | 35 | using namespace ke; 36 | 37 | TEST(Time, Timespec) 38 | { 39 | struct timespec ts = {}; 40 | ts.tv_sec = 100; 41 | ts.tv_nsec = 500000; 42 | 43 | auto tp = TimespecToTimePoint(ts); 44 | auto tt = std::chrono::system_clock::to_time_t(tp); 45 | EXPECT_EQ(tt, 100); 46 | EXPECT_EQ(tp.time_since_epoch(), TimespecToDuration(ts)); 47 | } 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /tools/restyler/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | -------------------------------------------------------------------------------- /tools/restyler/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /tools/restyler/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for amstyler 2 | 3 | ####################### 4 | # Configuration below # 5 | ####################### 6 | 7 | # By default, we build against system clang. 8 | 9 | # If building against clang source, uncomment these lines. 10 | #LLVM_SRC_PATH := /home/alliedmodders/llvm-project 11 | #LLVM_BUILD_PATH := /home/alliedmodders/llvm-project/build 12 | 13 | # If building against a release tarball, uncomment these lines. 14 | #LLVM_TARBALL_PATH := /home/alliedmodders/llvm-6.0 15 | 16 | # If building against an installed clang/llvm, llvm-config 17 | # will be used if found. To change it, specify below. 18 | #LLVM_CONFIG := llvm-config-6 19 | 20 | ##################### 21 | # Build rules below # 22 | ##################### 23 | 24 | ifneq (${LLVM_SRC_PATH},) 25 | LLVM_BIN_PATH := ${LLVM_BUILD_PATH}/bin 26 | else 27 | ifneq (${LLVM_TARBALL_PATH},) 28 | LLVM_SRC_PATH := ${LLVM_TARBALL_PATH} 29 | LLVM_BIN_PATH := ${LLVM_TARBALL_PATH}/bin 30 | else 31 | ifeq (${LLVM_CONFIG},) 32 | LLVM_CONFIG := llvm-config-6.0 33 | ifeq ($(shell which ${LLVM_CONFIG}),) 34 | LLVM_CONFIG := llvm-config 35 | endif 36 | endif 37 | LLVM_SRC_PATH := $(shell ${LLVM_CONFIG} --includedir) 38 | LLVM_BIN_PATH := $(shell ${LLVM_CONFIG} --bindir) 39 | endif 40 | endif 41 | 42 | LLVM_VERSION := $(shell ${LLVM_CONFIG} --version) 43 | ifeq ($(findstring 6.0,${LLVM_VERSION}),) 44 | $(error llvm version 6.0 is required) 45 | endif 46 | 47 | $(info -----------------------------------------------) 48 | $(info Using LLVM_SRC_PATH = $(LLVM_SRC_PATH)) 49 | $(info Using LLVM_BIN_PATH = $(LLVM_BIN_PATH)) 50 | $(info Using LLVM_VERSION = $(LLVM_VERSION)) 51 | $(info -----------------------------------------------) 52 | 53 | CXX := clang++ 54 | CXXFLAGS := -fno-rtti -O2 -Wall -Wno-c99-extensions -s 55 | 56 | ifeq (${LLVM_CONFIG},) 57 | LLVM_CONFIG := $(LLVM_BIN_PATH)/llvm-config 58 | endif 59 | 60 | LLVM_CXXFLAGS_STR := $(shell ${LLVM_CONFIG} --cxxflags) 61 | LLVM_CXXFLAGS := $(subst -std=c++11,-std=c++17,${LLVM_CXXFLAGS_STR}) 62 | LLVM_CXXFLAGS := $(subst -Wno-maybe-uninitialized,,${LLVM_CXXFLAGS}) 63 | LLVM_LDFLAGS := `${LLVM_CONFIG} --ldflags --libs --system-libs` 64 | 65 | CXXFLAGS += ${LLVM_CXXFLAGS} 66 | ifneq ($(ENABLE_DEBUG),) 67 | CXXFLAGS := $(subst -O2,,${CXXFLAGS}) 68 | CXXFLAGS := $(subst -O1,,${CXXFLAGS}) 69 | CXXFLAGS := $(subst -O3,,${CXXFLAGS}) 70 | CXXFLAGS := $(subst -s ,,${CXXFLAGS}) 71 | CXXFLAGS := $(subst -DNDEBUG,,${CXXFLAGS}) 72 | CXXFLAGS += -O0 -g -ggdb3 73 | endif 74 | 75 | # These are required when compiling vs. a source distribution of Clang. For 76 | # binary distributions llvm-config --cxxflags gives the right path. 77 | CLANG_INCLUDES := \ 78 | -I$(LLVM_SRC_PATH)/clang/include 79 | 80 | # List of Clang libraries to link. The proper -L will be provided by the 81 | # call to llvm-config 82 | # Note that I'm using -Wl,--{start|end}-group around the Clang libs; this is 83 | # because there are circular dependencies that make the correct order difficult 84 | # to specify and maintain. The linker group options make the linking somewhat 85 | # slower, but IMHO they're still perfectly fine for tools that link with Clang. 86 | CLANG_LIBS := \ 87 | -Wl,--start-group \ 88 | -lclangAST \ 89 | -lclangASTMatchers \ 90 | -lclangAnalysis \ 91 | -lclangBasic \ 92 | -lclangDriver \ 93 | -lclangEdit \ 94 | -lclangFrontend \ 95 | -lclangFrontendTool \ 96 | -lclangLex \ 97 | -lclangParse \ 98 | -lclangSema \ 99 | -lclangEdit \ 100 | -lclangRewrite \ 101 | -lclangRewriteFrontend \ 102 | -lclangStaticAnalyzerFrontend \ 103 | -lclangStaticAnalyzerCheckers \ 104 | -lclangStaticAnalyzerCore \ 105 | -lclangCrossTU \ 106 | -lclangIndex \ 107 | -lclangSerialization \ 108 | -lclangToolingCore \ 109 | -lclangTooling \ 110 | -lclangFormat \ 111 | -Wl,--end-group 112 | 113 | # Internal paths in this project: where to find sources, and where to put 114 | # build artifacts. 115 | BUILDDIR := build 116 | 117 | .PHONY: all 118 | all: make_builddir \ 119 | $(BUILDDIR)/amstyler 120 | 121 | .PHONY: emit_build_config 122 | emit_build_config: make_builddir 123 | @echo $(LLVM_BIN_PATH) > $(BUILDDIR)/_build_config 124 | 125 | .PHONY: make_builddir 126 | make_builddir: 127 | @test -d $(BUILDDIR) || mkdir $(BUILDDIR) 128 | 129 | $(BUILDDIR)/amstyler: amstyler.cpp 130 | $(CXX) $(CXXFLAGS) $(CLANG_INCLUDES) $^ \ 131 | $(CLANG_LIBS) $(LLVM_LDFLAGS) -o $@ 132 | 133 | .PHONY: clean 134 | 135 | clean: 136 | rm -rf $(BUILDDIR)/* 137 | -------------------------------------------------------------------------------- /tools/restyler/README.md: -------------------------------------------------------------------------------- 1 | The AMTL style is based on the Google style, with some differences: 2 | - Indents are 4 spaces instead of 2. 3 | - A brace is always placed onto a new line if the previous parenthetical 4 | was multi-line. 5 | - Functions in the first column always have their return type and name on 6 | separate lines. 7 | - A function can only be a one-liner if the entire function declaration fits 8 | on one line, and it is not in the first column. 9 | - Control structures cannot be one-liners, but braces are optional if the 10 | body fits on a single line. 11 | - A space is placed after the "operator" keyword. 12 | 13 | clang-format does not support these style changes, so for restyling existing 14 | code, a simple clang-based C++ restyler tool is provided. 15 | 16 | References: 17 | - https://github.com/eliben/llvm-clang-samples 18 | - https://github.com/nasa/trick/tree/master/trick\_source/codegen/Interface\_Code\_Gen 19 | -------------------------------------------------------------------------------- /tools/restyler/test/amstyler_in.cpp: -------------------------------------------------------------------------------- 1 | namespace egg { 2 | class A { 3 | public: 4 | A() 5 | : egg_(10) { 6 | if (int t = 5; egg_ || 7 | t) { 8 | A a; 9 | } else if (egg_ && 10 | egg_ == -1) { 11 | } else { 12 | } 13 | 14 | while (egg_ && 15 | egg_ == 16) { 16 | } 17 | 18 | switch (egg_ + 19 | 2) { 20 | default: 21 | egg_ = 2; 22 | break; 23 | } 24 | 25 | for (int i = 0; i < 10; 26 | i++) { 27 | } 28 | 29 | try { 30 | } catch (int 31 | egg) { 32 | } 33 | } 34 | 35 | bool operator==(const A& other 36 | ) const { 37 | return true; 38 | } 39 | 40 | private: 41 | int egg_; 42 | }; 43 | void f(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, 44 | int m, int n, int o, int p) { 45 | } 46 | void elah() noexcept { 47 | } 48 | void qlah() 49 | { 50 | } 51 | } 52 | 53 | void blah() noexcept { 54 | } 55 | 56 | void blah2() { 57 | // egg 58 | } 59 | 60 | void blah3() 61 | { 62 | } 63 | -------------------------------------------------------------------------------- /tools/restyler/test/amstyler_out.cpp: -------------------------------------------------------------------------------- 1 | namespace egg { 2 | class A { 3 | public: 4 | A() 5 | : egg_(10) 6 | { 7 | if (int t = 5; egg_ || 8 | t) 9 | { 10 | A a; 11 | } else if (egg_ && 12 | egg_ == -1) 13 | { 14 | } else { 15 | } 16 | 17 | while (egg_ && 18 | egg_ == 16) 19 | { 20 | } 21 | 22 | switch (egg_ + 23 | 2) 24 | { 25 | default: 26 | egg_ = 2; 27 | break; 28 | } 29 | 30 | for (int i = 0; i < 10; 31 | i++) 32 | { 33 | } 34 | 35 | try { 36 | } catch (int 37 | egg) 38 | { 39 | } 40 | } 41 | 42 | bool operator ==(const A& other 43 | ) const 44 | { 45 | return true; 46 | } 47 | 48 | private: 49 | int egg_; 50 | }; 51 | void f(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, 52 | int m, int n, int o, int p) {} 53 | void elah() noexcept {} 54 | void qlah() 55 | {} 56 | } 57 | 58 | void blah() noexcept 59 | { 60 | } 61 | 62 | void blah2() 63 | { 64 | // egg 65 | } 66 | 67 | void blah3() 68 | { 69 | } 70 | --------------------------------------------------------------------------------