├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── 3rdparty
├── .editorconfig
├── catch
│ ├── catch_amalgamated.cpp
│ └── catch_amalgamated.hpp
└── ini
│ ├── README.md
│ ├── ini.h
│ └── ini.md
├── LICENSE
├── README.md
├── include
├── bx
│ ├── allocator.h
│ ├── bounds.h
│ ├── bx.h
│ ├── commandline.h
│ ├── config.h
│ ├── constants.h
│ ├── cpu.h
│ ├── debug.h
│ ├── easing.h
│ ├── endian.h
│ ├── error.h
│ ├── file.h
│ ├── filepath.h
│ ├── float4x4_t.h
│ ├── handlealloc.h
│ ├── hash.h
│ ├── inline
│ │ ├── allocator.inl
│ │ ├── bounds.inl
│ │ ├── bx.inl
│ │ ├── cpu.inl
│ │ ├── easing.inl
│ │ ├── endian.inl
│ │ ├── error.inl
│ │ ├── float4x4_t.inl
│ │ ├── handlealloc.inl
│ │ ├── hash.inl
│ │ ├── math.inl
│ │ ├── mpscqueue.inl
│ │ ├── mutex.inl
│ │ ├── os.inl
│ │ ├── pixelformat.inl
│ │ ├── readerwriter.inl
│ │ ├── ringbuffer.inl
│ │ ├── rng.inl
│ │ ├── simd128_langext.inl
│ │ ├── simd128_neon.inl
│ │ ├── simd128_ref.inl
│ │ ├── simd128_sse.inl
│ │ ├── simd128_swizzle.inl
│ │ ├── simd256_avx.inl
│ │ ├── simd256_ref.inl
│ │ ├── simd_ni.inl
│ │ ├── sort.inl
│ │ ├── spscqueue.inl
│ │ ├── string.inl
│ │ ├── typetraits.inl
│ │ └── uint32_t.inl
│ ├── macros.h
│ ├── math.h
│ ├── mpscqueue.h
│ ├── mutex.h
│ ├── os.h
│ ├── pixelformat.h
│ ├── platform.h
│ ├── process.h
│ ├── readerwriter.h
│ ├── ringbuffer.h
│ ├── rng.h
│ ├── semaphore.h
│ ├── settings.h
│ ├── simd_t.h
│ ├── sort.h
│ ├── spscqueue.h
│ ├── string.h
│ ├── thread.h
│ ├── timer.h
│ ├── typetraits.h
│ ├── uint32_t.h
│ └── url.h
├── compat
│ ├── freebsd
│ │ ├── dirent.h
│ │ ├── malloc.h
│ │ └── signal.h
│ ├── ios
│ │ └── malloc.h
│ ├── linux
│ │ └── sal.h
│ ├── mingw
│ │ ├── dirent.h
│ │ ├── sal.h
│ │ ├── salieri.h
│ │ ├── specstrings_strict.h
│ │ └── specstrings_undef.h
│ ├── msvc
│ │ └── dirent.h
│ └── osx
│ │ └── malloc.h
└── tinystl
│ ├── LICENSE
│ ├── allocator.h
│ ├── buffer.h
│ ├── hash.h
│ ├── hash_base.h
│ ├── new.h
│ ├── stddef.h
│ ├── string.h
│ ├── string_view.h
│ ├── traits.h
│ ├── unordered_map.h
│ ├── unordered_set.h
│ └── vector.h
├── scripts
├── bin2c.lua
├── bx.lua
├── bx.natvis
├── genie.lua
├── tinystl.natvis
├── toolchain.lua
└── update_tinystl.sh
├── src
├── allocator.cpp
├── amalgamated.cpp
├── bounds.cpp
├── bx.cpp
├── commandline.cpp
├── crtnone.cpp
├── debug.cpp
├── dtoa.cpp
├── easing.cpp
├── file.cpp
├── filepath.cpp
├── hash.cpp
├── math.cpp
├── mutex.cpp
├── os.cpp
├── process.cpp
├── semaphore.cpp
├── settings.cpp
├── sort.cpp
├── string.cpp
├── thread.cpp
├── timer.cpp
└── url.cpp
├── tests
├── allocator_test.cpp
├── atomic_test.cpp
├── cast_test.cpp
├── crt_test.cpp
├── dbg.h
├── easing_test.cpp
├── filepath_test.cpp
├── handle_bench.cpp
├── handle_test.cpp
├── hash_test.cpp
├── macros_test.cpp
├── main_test.cpp
├── math_bench.cpp
├── math_test.cpp
├── os_test.cpp
├── pixelformat_test.cpp
├── queue_test.cpp
├── readerwriter_test.cpp
├── ringbuffer_test.cpp
├── rng_test.cpp
├── run_test.cpp
├── settings_test.cpp
├── simd_bench.cpp
├── simd_test.cpp
├── sort_test.cpp
├── string_test.cpp
├── test.h
├── thread_test.cpp
├── tokenizecmd_test.cpp
├── typetraits_test.cpp
├── uint32_test.cpp
├── unordered_map_nonpod_test.cpp
├── unordered_map_test.cpp
├── unordered_set_copyctor_test.cpp
├── unordered_set_pod_test.cpp
├── unordered_set_test.cpp
├── url_test.cpp
├── vector_complex_test.cpp
├── vector_header_test.cpp
├── vector_nocopy_test.cpp
├── vector_nodefault_test.cpp
├── vector_primitive_test.cpp
├── vector_shrinktofit_test.cpp
└── vsnprintf_test.cpp
└── tools
├── bin
├── darwin
│ ├── bin2c
│ ├── genie
│ └── ninja
├── linux
│ ├── bin2c
│ ├── genie
│ └── ninja
└── windows
│ ├── bin2c.exe
│ ├── genie.exe
│ └── ninja.exe
└── bin2c
└── bin2c.cpp
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = tab
6 | indent_size = 4
7 | end_of_line = lf
8 | max_line_length = 100
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 | max_line_length = 80
15 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.c eol=lf
2 | *.cpp eol=lf
3 | *.h eol=lf
4 | *.sc eol=lf
5 | *.sh eol=lf
6 | *.m eol=lf
7 | *.mm eol=lf
8 | *.md eol=lf
9 | *.lua eol=lf
10 | *.mk eol=lf
11 | makefile eol=lf
12 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | concurrency:
4 | group: ${{ github.ref }}
5 | cancel-in-progress: true
6 |
7 | on:
8 | push:
9 | pull_request:
10 |
11 | jobs:
12 | msvc:
13 | strategy:
14 | fail-fast: true
15 | matrix:
16 | include: [
17 | { config: Debug, platform: x64, bindir: 'win64_vs2022' },
18 | { config: Release, platform: x64, bindir: 'win64_vs2022' },
19 | ]
20 | name: msvc-${{ matrix.config }}-${{ matrix.platform }}
21 | runs-on: windows-2022
22 | steps:
23 | - name: Checkout bx
24 | uses: actions/checkout@v4
25 | with:
26 | repository: bkaradzic/bx
27 | path: bx
28 | - name: Prepare
29 | uses: microsoft/setup-msbuild@v2
30 | - name: Build
31 | shell: cmd
32 | run: |
33 | cd bx
34 | tools\bin\windows\genie.exe vs2022
35 | msbuild ".build/projects/vs2022/bx.sln" /m /v:minimal /p:Configuration=${{ matrix.config }} /p:Platform=${{ matrix.platform }}
36 | - name: Check
37 | shell: cmd
38 | run: |
39 | cd bx
40 | ".build\${{ matrix.bindir }}\bin\bx.test${{ matrix.config }}.exe" -d yes
41 | mingw:
42 | strategy:
43 | fail-fast: true
44 | matrix:
45 | include: [
46 | { msystem: MINGW64, project: 'mingw-gcc', bindir: 'win64_mingw-gcc' },
47 | # { msystem: CLANG64, project: 'mingw-clang', bindir: 'win64_mingw-clang' },
48 | ]
49 | name: mingw-${{ matrix.msystem }}
50 | runs-on: windows-2022
51 | steps:
52 | - name: Checkout bx
53 | uses: actions/checkout@v4
54 | with:
55 | repository: bkaradzic/bx
56 | path: bx
57 | - name: Prepare
58 | uses: msys2/setup-msys2@v2
59 | with:
60 | msystem: ${{ matrix.msystem }}
61 | update: true
62 | install: make
63 | pacboy: cc:p
64 | - name: Build
65 | shell: msys2 {0}
66 | run: |
67 | cd bx
68 | tools/bin/windows/genie.exe --gcc=${{ matrix.project }} gmake
69 | make -R -C .build/projects/gmake-${{ matrix.project }} config=release64 -j$(nproc) AR=ar CC=cc CXX=c++ MINGW=$MINGW_PREFIX
70 | - name: Check
71 | shell: cmd
72 | run: |
73 | cd bx
74 | ".build\${{ matrix.bindir }}\bin\bx.testRelease.exe" -d yes
75 | linux:
76 | strategy:
77 | fail-fast: true
78 | matrix:
79 | include: [
80 | { config: debug, binsuffix: Debug },
81 | { config: release, binsuffix: Release },
82 | ]
83 | name: linux-gcc-${{ matrix.config }}64
84 | runs-on: ubuntu-24.04
85 | steps:
86 | - name: Checkout bx
87 | uses: actions/checkout@v4
88 | with:
89 | repository: bkaradzic/bx
90 | path: bx
91 | - name: Build
92 | run: |
93 | cd bx
94 | tools/bin/linux/genie --gcc=linux-gcc gmake
95 | make -R -C .build/projects/gmake-linux-gcc config=${{ matrix.config }}64 -j$(nproc)
96 | - name: Check
97 | run: |
98 | cd bx
99 | ".build/linux64_gcc/bin/bx.test${{ matrix.binsuffix}}" -d yes
100 | osx:
101 | strategy:
102 | fail-fast: true
103 | matrix:
104 | include: [
105 | { config: debug, binsuffix: Debug },
106 | { config: release, binsuffix: Release },
107 | ]
108 | name: osx-x64-${{ matrix.config }}
109 | runs-on: macos-14
110 | steps:
111 | - name: Checkout bx
112 | uses: actions/checkout@v4
113 | with:
114 | repository: bkaradzic/bx
115 | path: bx
116 | - name: Build
117 | run: |
118 | cd bx
119 | tools/bin/darwin/genie --gcc=osx-x64 gmake
120 | make -C .build/projects/gmake-osx-x64 config=${{ matrix.config }} -j$(sysctl -n hw.physicalcpu)
121 | - name: Check
122 | run: |
123 | cd bx
124 | ".build/osx-x64/bin/bx.test${{ matrix.binsuffix}}" -d yes
125 | emscripten:
126 | strategy:
127 | fail-fast: true
128 | matrix:
129 | include: [
130 | { config: debug, binsuffix: Debug },
131 | { config: release, binsuffix: Release },
132 | ]
133 | name: wasm-${{ matrix.config }}
134 | runs-on: ubuntu-24.04
135 | steps:
136 | - name: Checkout bx
137 | uses: actions/checkout@v4
138 | with:
139 | repository: bkaradzic/bx
140 | path: bx
141 | - uses: mymindstorm/setup-emsdk@v14
142 | - uses: browser-actions/setup-chrome@v1
143 | - name: Build
144 | run: |
145 | cd bx
146 | tools/bin/linux/genie --gcc=wasm gmake
147 | make -C .build/projects/gmake-wasm config=${{ matrix.config }} -j$(nproc) EMSCRIPTEN=$EMSDK/upstream/emscripten
148 | - name: Check
149 | run: |
150 | cd bx
151 | # npx http-server -o .build/wasm/bin/ & chromium http://127.0.0.1:8080/.build/wasm/bin/bx.testRelease.html
152 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .git
2 | .build
3 | .debug
4 | .svn
5 | tags
6 | .DS_Store
7 | .gdb_history
8 |
--------------------------------------------------------------------------------
/3rdparty/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [ini/*]
4 | indent_style = space
5 | indent_size = 4
6 | trim_trailing_whitespace = true
7 |
--------------------------------------------------------------------------------
/3rdparty/ini/README.md:
--------------------------------------------------------------------------------
1 | https://github.com/mattiasgustavsson/libs/
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2010-2025 Branimir Karadzic
2 |
3 | Redistribution and use in source and binary forms, with or without modification,
4 | are permitted provided that the following conditions are met:
5 |
6 | 1. Redistributions of source code must retain the above copyright notice, this
7 | list of conditions and the following disclaimer.
8 |
9 | 2. Redistributions in binary form must reproduce the above copyright notice,
10 | this list of conditions and the following disclaimer in the documentation
11 | and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
17 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
21 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
22 | OF THE POSSIBILITY OF SUCH DAMAGE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | bx
2 | ==
3 |
4 | Base X-platform library.
5 |
6 | [](https://github.com/bkaradzic/bx/actions)
7 | [](https://bkaradzic.github.io/bgfx/license.html)
8 | [](https://discord.gg/9eMbv7J)
9 |
10 | Goals:
11 |
12 | - Provide OS/runtime/compiler independent core functionality to be able to
13 | write cross-platform applications.
14 | - Compile without C Runtime (CRT) and without C++ Standard Library (STL).
15 |
16 | Contact
17 | -------
18 |
19 | [@bkaradzic](https://twitter.com/bkaradzic)
20 |
21 | Project page
22 | https://github.com/bkaradzic/bx
23 |
24 | [License (BSD 2-clause)](https://github.com/bkaradzic/bx/blob/master/LICENSE)
25 | -----------------------------------------------------------------------------
26 |
27 |
28 |
29 |
30 |
31 | Copyright 2010-2025 Branimir Karadzic
32 |
33 | Redistribution and use in source and binary forms, with or without modification,
34 | are permitted provided that the following conditions are met:
35 |
36 | 1. Redistributions of source code must retain the above copyright notice, this
37 | list of conditions and the following disclaimer.
38 |
39 | 2. Redistributions in binary form must reproduce the above copyright notice,
40 | this list of conditions and the following disclaimer in the documentation
41 | and/or other materials provided with the distribution.
42 |
43 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
44 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
47 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
48 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
49 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
50 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
51 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52 | OF THE POSSIBILITY OF SUCH DAMAGE.
53 |
--------------------------------------------------------------------------------
/include/bx/allocator.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_ALLOCATOR_H_HEADER_GUARD
7 | #define BX_ALLOCATOR_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 | #include "uint32_t.h"
11 |
12 | #define BX_NEW(_allocator, _type) BX_PLACEMENT_NEW(bx::alloc(_allocator, sizeof(_type) ), _type)
13 | #define BX_ALIGNED_NEW(_allocator, _type, _align) BX_PLACEMENT_NEW(bx::alloc(_allocator, sizeof(_type), _align), _type)
14 | #define BX_PLACEMENT_NEW(_ptr, _type) ::new(bx::PlacementNew, _ptr) _type
15 |
16 | void* operator new(size_t, bx::PlacementNewTag, void* _ptr);
17 | void operator delete(void*, bx::PlacementNewTag, void*) throw();
18 |
19 | namespace bx
20 | {
21 | /// Abstract allocator interface.
22 | ///
23 | struct BX_NO_VTABLE AllocatorI
24 | {
25 | ///
26 | virtual ~AllocatorI() = 0;
27 |
28 | /// Allocates, resizes, or frees memory block.
29 | ///
30 | /// @remark
31 | /// - Allocate memory block: _ptr == NULL && size > 0
32 | /// - Resize memory block: _ptr != NULL && size > 0
33 | /// - Free memory block: _ptr != NULL && size == 0
34 | ///
35 | /// @param[in] _ptr If _ptr is NULL new block will be allocated. If _ptr is not-NULL, and
36 | /// _size is not 0, memory block will be resized.
37 | /// @param[in] _size If _ptr is set, and _size is 0, memory will be freed.
38 | /// @param[in] _align Alignment.
39 | /// @param[in] _filePath Debug file path info.
40 | /// @param[in] _line Debug file line info.
41 | ///
42 | virtual void* realloc(
43 | void* _ptr
44 | , size_t _size
45 | , size_t _align
46 | , const char* _filePath
47 | , uint32_t _line
48 | ) = 0;
49 | };
50 |
51 | ///
52 | class DefaultAllocator : public AllocatorI
53 | {
54 | public:
55 | ///
56 | DefaultAllocator();
57 |
58 | ///
59 | virtual ~DefaultAllocator();
60 |
61 | ///
62 | virtual void* realloc(
63 | void* _ptr
64 | , size_t _size
65 | , size_t _align
66 | , const char* _filePath
67 | , uint32_t _line
68 | ) override;
69 | };
70 |
71 | /// Aligns pointer to nearest next aligned address. _align must be power of two.
72 | void* alignPtr(
73 | void* _ptr
74 | , size_t _extra
75 | , size_t _align = 0
76 | );
77 |
78 | /// Allocate memory.
79 | void* alloc(
80 | AllocatorI* _allocator
81 | , size_t _size
82 | , size_t _align = 0
83 | , const Location& _location = Location::current()
84 | );
85 |
86 | /// Free memory.
87 | void free(
88 | AllocatorI* _allocator
89 | , void* _ptr
90 | , size_t _align = 0
91 | , const Location& _location = Location::current()
92 | );
93 |
94 | /// Resize memory block.
95 | void* realloc(
96 | AllocatorI* _allocator
97 | , void* _ptr
98 | , size_t _size
99 | , size_t _align = 0
100 | , const Location& _location = Location::current()
101 | );
102 |
103 | /// Allocate memory with specific alignment.
104 | void* alignedAlloc(
105 | AllocatorI* _allocator
106 | , size_t _size
107 | , size_t _align
108 | , const Location& _location = Location::current()
109 | );
110 |
111 | /// Free memory that was allocated with aligned allocator.
112 | void alignedFree(
113 | AllocatorI* _allocator
114 | , void* _ptr
115 | , size_t /*_align*/
116 | , const Location& _location = Location::current()
117 | );
118 |
119 | /// Resize memory block that was allocated with aligned allocator.
120 | void* alignedRealloc(
121 | AllocatorI* _allocator
122 | , void* _ptr
123 | , size_t _size
124 | , size_t _align
125 | , const Location& _location = Location::current()
126 | );
127 |
128 | /// Delete object with specific allocator.
129 | template
130 | void deleteObject(
131 | AllocatorI* _allocator
132 | , ObjectT* _object
133 | , size_t _align = 0
134 | , const Location& _location = Location::current()
135 | );
136 |
137 | } // namespace bx
138 |
139 | #include "inline/allocator.inl"
140 |
141 | #endif // BX_ALLOCATOR_H_HEADER_GUARD
142 |
--------------------------------------------------------------------------------
/include/bx/commandline.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_COMMANDLINE_H_HEADER_GUARD
7 | #define BX_COMMANDLINE_H_HEADER_GUARD
8 |
9 | #include "string.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | StringView tokenizeCommandLine(const StringView& _commandLine, char* _buffer, uint32_t& _bufferSize, int32_t& _argc, char* _argv[], int32_t _maxArgvs, char _term = '\0');
15 |
16 | ///
17 | class CommandLine
18 | {
19 | public:
20 | ///
21 | CommandLine(int32_t _argc, char const* const* _argv);
22 |
23 | ///
24 | const char* findOption(const char* _long, const char* _default) const;
25 |
26 | ///
27 | const char* findOption(const char _short, const char* _long, const char* _default) const;
28 |
29 | ///
30 | const char* findOption(const char* _long, int32_t _numParams = 1) const;
31 |
32 | ///
33 | const char* findOption(const char _short, const char* _long = NULL, int32_t _numParams = 1) const;
34 |
35 | ///
36 | const char* findOption(int32_t _skip, const char _short, const char* _long = NULL, int32_t _numParams = 1) const;
37 |
38 | ///
39 | bool hasArg(const char _short, const char* _long = NULL) const;
40 |
41 | ///
42 | bool hasArg(const char* _long) const;
43 |
44 | ///
45 | bool hasArg(const char*& _value, const char _short, const char* _long = NULL) const;
46 |
47 | ///
48 | bool hasArg(int32_t& _value, const char _short, const char* _long = NULL) const;
49 |
50 | ///
51 | bool hasArg(uint32_t& _value, const char _short, const char* _long = NULL) const;
52 |
53 | ///
54 | bool hasArg(float& _value, const char _short, const char* _long = NULL) const;
55 |
56 | ///
57 | bool hasArg(double& _value, const char _short, const char* _long = NULL) const;
58 |
59 | ///
60 | bool hasArg(bool& _value, const char _short, const char* _long = NULL) const;
61 |
62 | ///
63 | int32_t getNum() const;
64 |
65 | ///
66 | char const* get(int32_t _idx) const;
67 |
68 | private:
69 | ///
70 | const char* find(int32_t _skip, const char _short, const char* _long, int32_t _numParams) const;
71 |
72 | int32_t m_argc;
73 | char const* const* m_argv;
74 | };
75 |
76 | } // namespace bx
77 |
78 | #endif /// BX_COMMANDLINE_H_HEADER_GUARD
79 |
--------------------------------------------------------------------------------
/include/bx/config.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_CONFIG_H_HEADER_GUARD
7 | #define BX_CONFIG_H_HEADER_GUARD
8 |
9 | #ifndef BX_CONFIG_DEBUG
10 | # error "BX_CONFIG_DEBUG must be defined in build script!"
11 | #endif // BX_CONFIG_DEBUG
12 |
13 | #ifndef BX_CONFIG_ALLOCATOR_DEBUG
14 | # define BX_CONFIG_ALLOCATOR_DEBUG BX_CONFIG_DEBUG
15 | #endif // BX_CONFIG_ALLOCATOR_DEBUG
16 |
17 | #ifndef BX_CONFIG_SUPPORTS_THREADING
18 | # define BX_CONFIG_SUPPORTS_THREADING !(0 \
19 | || BX_PLATFORM_EMSCRIPTEN \
20 | )
21 | #endif // BX_CONFIG_SUPPORTS_THREADING
22 |
23 | #endif // BX_CONFIG_H_HEADER_GUARD
24 |
--------------------------------------------------------------------------------
/include/bx/constants.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_CONSTANTS_H_HEADER_GUARD
7 | #define BX_CONSTANTS_H_HEADER_GUARD
8 |
9 | namespace bx
10 | {
11 | /// Used to return successful execution of a program code.
12 | constexpr int32_t kExitSuccess = 0;
13 |
14 | /// Used to return unsuccessful execution of a program code.
15 | constexpr int32_t kExitFailure = 1;
16 |
17 | /// The ratio of a circle's circumference to its diameter,
18 | constexpr float kPi = 3.1415926535897932384626433832795f;
19 |
20 | /// The ratio of a circle's circumference to its radius. Pi multiplied by 2, or Tau. pi*2
21 | constexpr float kPi2 = 6.2831853071795864769252867665590f;
22 |
23 | /// The reciprocal of kPi. 1/kPi
24 | constexpr float kInvPi = 1.0f/kPi;
25 |
26 | /// The reciprocal of kPi2. 1/kPi2
27 | constexpr float kInvPi2 = 1.0f/kPi2;
28 |
29 | /// Pi divided by two. pi/2
30 | constexpr float kPiHalf = 1.5707963267948966192313216916398f;
31 |
32 | /// Pi divided by four. pi/4
33 | constexpr float kPiQuarter = 0.7853981633974483096156608458199f;
34 |
35 | /// The square root of two. sqrt(2)
36 | constexpr float kSqrt2 = 1.4142135623730950488016887242097f;
37 |
38 | /// ln(10)
39 | constexpr float kLogNat10 = 2.3025850929940456840179914546844f;
40 |
41 | /// The logarithm of the e to base 2. ln(kE) / ln(2)
42 | constexpr float kInvLogNat2 = 1.4426950408889634073599246810019f;
43 |
44 | /// The natural logarithm of the 2. ln(2)
45 | constexpr float kLogNat2 = 0.6931471805599453094172321214582f;
46 |
47 | /// The base of natural logarithms. e(1)
48 | constexpr float kE = 2.7182818284590452353602874713527f;
49 |
50 | ///
51 | constexpr float kNearZero = 1.0f/float(1 << 28);
52 |
53 | ///
54 | constexpr uint8_t kHalfSignNumBits = 1;
55 | constexpr uint8_t kHalfSignBitShift = 15;
56 | constexpr uint16_t kHalfSignMask = UINT16_C(0x8000);
57 | constexpr uint8_t kHalfExponentNumBits = 5;
58 | constexpr uint8_t kHalfExponentBitShift = 10;
59 | constexpr uint16_t kHalfExponentMask = UINT16_C(0x7c00);
60 | constexpr uint32_t kHalfExponentBias = 15;
61 | constexpr uint8_t kHalfMantissaNumBits = 10;
62 | constexpr uint8_t kHalfMantissaBitShift = 0;
63 | constexpr uint16_t kHalfMantissaMask = UINT16_C(0x03ff);
64 |
65 | ///
66 | constexpr uint8_t kFloatSignNumBits = 1;
67 | constexpr uint8_t kFloatSignBitShift = 31;
68 | constexpr uint32_t kFloatSignMask = UINT32_C(0x80000000);
69 | constexpr uint8_t kFloatExponentNumBits = 8;
70 | constexpr uint8_t kFloatExponentBitShift = 23;
71 | constexpr uint32_t kFloatExponentMask = UINT32_C(0x7f800000);
72 | constexpr uint32_t kFloatExponentBias = 127;
73 | constexpr uint8_t kFloatMantissaNumBits = 23;
74 | constexpr uint8_t kFloatMantissaBitShift = 0;
75 | constexpr uint32_t kFloatMantissaMask = UINT32_C(0x007fffff);
76 |
77 | /// Smallest normalized positive floating-point number.
78 | constexpr float kFloatSmallest = 1.175494351e-38f;
79 |
80 | /// Maximum representable floating-point number.
81 | constexpr float kFloatLargest = 3.402823466e+38f;
82 |
83 | /// Floating-point infinity.
84 | // constexpr float kFloatInfinity;
85 |
86 | ///
87 | constexpr uint8_t kDoubleSignNumBits = 1;
88 | constexpr uint8_t kDoubleSignBitShift = 63;
89 | constexpr uint64_t kDoubleSignMask = UINT64_C(0x8000000000000000);
90 | constexpr uint8_t kDoubleExponentNumBits = 11;
91 | constexpr uint8_t kDoubleExponentShift = 52;
92 | constexpr uint64_t kDoubleExponentMask = UINT64_C(0x7ff0000000000000);
93 | constexpr uint32_t kDoubleExponentBias = 1023;
94 | constexpr uint8_t kDoubleMantissaNumBits = 52;
95 | constexpr uint8_t kDoubleMantissaShift = 0;
96 | constexpr uint64_t kDoubleMantissaMask = UINT64_C(0x000fffffffffffff);
97 |
98 | /// Smallest normalized positive double-precision floating-point number.
99 | constexpr double kDoubleSmallest = 2.2250738585072014e-308;
100 |
101 | /// Largest representable double-precision floating-point number.
102 | constexpr double kDoubleLargest = 1.7976931348623158e+308;
103 |
104 | // Double-precision floating-point infinity.
105 | // constexpr double kDoubleInfinity;
106 |
107 | } // namespace bx
108 |
109 | #endif // BX_CONSTANTS_H_HEADER_GUARD
110 |
--------------------------------------------------------------------------------
/include/bx/cpu.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_CPU_H_HEADER_GUARD
7 | #define BX_CPU_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | void readBarrier();
15 |
16 | ///
17 | void writeBarrier();
18 |
19 | ///
20 | void readWriteBarrier();
21 |
22 | ///
23 | void memoryBarrier();
24 |
25 | ///
26 | template
27 | Ty atomicFetchAndAdd(volatile Ty* _ptr, Ty _value);
28 |
29 | ///
30 | template
31 | Ty atomicAddAndFetch(volatile Ty* _ptr, Ty _value);
32 |
33 | ///
34 | template
35 | Ty atomicFetchAndSub(volatile Ty* _ptr, Ty _value);
36 |
37 | ///
38 | template
39 | Ty atomicSubAndFetch(volatile Ty* _ptr, Ty _value);
40 |
41 | ///
42 | template
43 | Ty atomicCompareAndSwap(volatile Ty* _ptr, Ty _old, Ty _new);
44 |
45 | ///
46 | template
47 | Ty atomicFetchTestAndAdd(volatile Ty* _ptr, Ty _test, Ty _value);
48 |
49 | ///
50 | template
51 | Ty atomicFetchTestAndSub(volatile Ty* _ptr, Ty _test, Ty _value);
52 |
53 | ///
54 | template
55 | Ty atomicFetchAndAddsat(volatile Ty* _ptr, Ty _value, Ty _max);
56 |
57 | ///
58 | template
59 | Ty atomicFetchAndSubsat(volatile Ty* _ptr, Ty _value, Ty _min);
60 |
61 | ///
62 | void* atomicExchangePtr(void** _ptr, void* _new);
63 |
64 | } // namespace bx
65 |
66 | #include "inline/cpu.inl"
67 |
68 | #endif // BX_CPU_H_HEADER_GUARD
69 |
--------------------------------------------------------------------------------
/include/bx/debug.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_DEBUG_H_HEADER_GUARD
7 | #define BX_DEBUG_H_HEADER_GUARD
8 |
9 | #include // uint32_t
10 | #include // va_list
11 |
12 | namespace bx
13 | {
14 | class Error;
15 | class StringView;
16 | struct WriterI;
17 |
18 | /// Break in debugger.
19 | ///
20 | void debugBreak();
21 |
22 | /// Write string to debug output.
23 | ///
24 | /// @param[in] _str Zero terminated string to write.
25 | ///
26 | void debugOutput(const char* _str);
27 |
28 | /// Write string to debug output.
29 | ///
30 | /// @param[in] _str StringView to write.
31 | ///
32 | void debugOutput(const StringView& _str);
33 |
34 | /// Write formatted string to debug output.
35 | ///
36 | void debugPrintfVargs(const char* _format, va_list _argList);
37 |
38 | /// Write formatted string to debug output.
39 | ///
40 | void debugPrintf(const char* _format, ...);
41 |
42 | /// Write hex data into debug output.
43 | ///
44 | void debugPrintfData(const void* _data, uint32_t _size, const char* _format, ...);
45 |
46 | /// Return debug output writer.
47 | ///
48 | /// @returns Debug output writer.
49 | ///
50 | WriterI* getDebugOut();
51 |
52 | /// Capture current callstack.
53 | ///
54 | /// @param[in] _skip Skip top N stack frames.
55 | /// @param[in] _max Maximum frame to capture.
56 | /// @param[out] _outStack Stack frames array. Must be at least `_max` elements.
57 | ///
58 | /// @returns Number of stack frames captured.
59 | ///
60 | uint32_t getCallStack(uint32_t _skip, uint32_t _max, uintptr_t* _outStack);
61 |
62 | /// Write callstack.
63 | ///
64 | /// @param[in] _writer Writer.
65 | /// @param[in] _stack Callstack.
66 | /// @param[in] _num Number of stack addresses in `_stack` array.
67 | /// @param[out] _err Error.
68 | ///
69 | /// @returns Number of bytes writen to `_writer`.
70 | ///
71 | int32_t writeCallstack(WriterI* _writer, uintptr_t* _stack, uint32_t _num, Error* _err);
72 |
73 | /// Capture call stack, and write it to debug output.
74 | ///
75 | /// @param[in] _skip Skip top N stack frames.
76 | ///
77 | void debugOutputCallstack(uint32_t _skip);
78 |
79 | } // namespace bx
80 |
81 | #endif // BX_DEBUG_H_HEADER_GUARD
82 |
--------------------------------------------------------------------------------
/include/bx/endian.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_ENDIAN_H_HEADER_GUARD
7 | #define BX_ENDIAN_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | int16_t endianSwap(int16_t _in);
15 |
16 | ///
17 | uint16_t endianSwap(uint16_t _in);
18 |
19 | ///
20 | int32_t endianSwap(int32_t _in);
21 |
22 | ///
23 | uint32_t endianSwap(uint32_t _in);
24 |
25 | ///
26 | int64_t endianSwap(int64_t _in);
27 |
28 | ///
29 | uint64_t endianSwap(uint64_t _in);
30 |
31 | /// Input argument is encoded as little endian, convert it if necessary
32 | /// depending on host CPU endianness.
33 | template
34 | Ty toLittleEndian(const Ty _in);
35 |
36 | /// Input argument is encoded as big endian, convert it if necessary
37 | /// depending on host CPU endianness.
38 | template
39 | Ty toBigEndian(const Ty _in);
40 |
41 | /// If _littleEndian is true, converts input argument to from little endian
42 | /// to host CPU endiness.
43 | template
44 | Ty toHostEndian(const Ty _in, bool _fromLittleEndian);
45 |
46 | } // namespace bx
47 |
48 | #include "inline/endian.inl"
49 |
50 | #endif // BX_ENDIAN_H_HEADER_GUARD
51 |
--------------------------------------------------------------------------------
/include/bx/error.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_ERROR_H_HEADER_GUARD
7 | #define BX_ERROR_H_HEADER_GUARD
8 |
9 | #include "string.h"
10 |
11 | #define BX_ERROR_SET(_ptr, _result, _msg) \
12 | BX_MACRO_BLOCK_BEGIN \
13 | (_ptr)->setError(_result, "" _msg); \
14 | BX_MACRO_BLOCK_END
15 |
16 | #define BX_ERROR_USE_TEMP_WHEN_NULL(_ptr) \
17 | const bx::Error tmpError; /* It should not be used directly! */ \
18 | _ptr = NULL == _ptr ? const_cast(&tmpError) : _ptr
19 |
20 | #define BX_ERROR_SCOPE(_ptr, ...) \
21 | BX_ERROR_USE_TEMP_WHEN_NULL(_ptr); \
22 | bx::ErrorScope bxErrorScope(const_cast(&tmpError), "" __VA_ARGS__)
23 |
24 | #define BX_ERROR_RESULT(_err, _code) \
25 | static_assert(_code != 0, "ErrorCode 0 is reserved!"); \
26 | static constexpr bx::ErrorResult _err = { _code }
27 |
28 | namespace bx
29 | {
30 | ///
31 | struct ErrorResult
32 | {
33 | uint32_t code;
34 | };
35 |
36 | ///
37 | class Error
38 | {
39 | BX_CLASS(Error
40 | , NO_COPY
41 | );
42 |
43 | public:
44 | ///
45 | Error();
46 |
47 | ///
48 | void reset();
49 |
50 | ///
51 | void setError(ErrorResult _errorResult, const StringLiteral& _msg, const Location& _location = Location::current() );
52 |
53 | ///
54 | bool isOk() const;
55 |
56 | ///
57 | ErrorResult get() const;
58 |
59 | ///
60 | const StringLiteral& getMessage() const;
61 |
62 | ///
63 | const Location& getLocation() const;
64 |
65 | ///
66 | bool operator==(const ErrorResult& _rhs) const;
67 |
68 | ///
69 | bool operator!=(const ErrorResult& _rhs) const;
70 |
71 | private:
72 | Location m_location;
73 | StringLiteral m_msg;
74 | uint32_t m_code;
75 | };
76 |
77 | /// Do nothing even if error is set.
78 | class ErrorIgnore final : public Error
79 | {
80 | public:
81 | ///
82 | operator Error*();
83 | };
84 |
85 | /// In debug build assert if error is set.
86 | class ErrorAssert final : public Error
87 | {
88 | public:
89 | ///
90 | ~ErrorAssert();
91 |
92 | ///
93 | operator Error*();
94 | };
95 |
96 | /// Exit application if error is set.
97 | class ErrorFatal final : public Error
98 | {
99 | public:
100 | ///
101 | ~ErrorFatal();
102 |
103 | ///
104 | operator Error*();
105 | };
106 |
107 | ///
108 | class ErrorScope
109 | {
110 | BX_CLASS(ErrorScope
111 | , NO_DEFAULT_CTOR
112 | , NO_COPY
113 | );
114 |
115 | public:
116 | ///
117 | ErrorScope(Error* _err, const StringLiteral& _name);
118 |
119 | ///
120 | ~ErrorScope();
121 |
122 | ///
123 | const StringLiteral& getName() const;
124 |
125 | private:
126 | Error* m_err;
127 | const StringLiteral m_name;
128 | };
129 |
130 | } // namespace bx
131 |
132 | #include "inline/error.inl"
133 |
134 | #endif // BX_ERROR_H_HEADER_GUARD
135 |
--------------------------------------------------------------------------------
/include/bx/file.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_FILE_H_HEADER_GUARD
7 | #define BX_FILE_H_HEADER_GUARD
8 |
9 | #include "filepath.h"
10 | #include "readerwriter.h"
11 |
12 | namespace bx
13 | {
14 | /// Returns standard input reader.
15 | ReaderI* getStdIn();
16 |
17 | /// Returns standard output writer.
18 | WriterI* getStdOut();
19 |
20 | /// Returns standard error writer.
21 | WriterI* getStdErr();
22 |
23 | /// Returns null output writer.
24 | WriterI* getNullOut();
25 |
26 | /// File reader.
27 | class FileReader : public FileReaderI
28 | {
29 | public:
30 | ///
31 | FileReader();
32 |
33 | ///
34 | virtual ~FileReader();
35 |
36 | ///
37 | virtual bool open(const FilePath& _filePath, Error* _err) override;
38 |
39 | ///
40 | virtual void close() override;
41 |
42 | ///
43 | virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) override;
44 |
45 | ///
46 | virtual int32_t read(void* _data, int32_t _size, Error* _err) override;
47 |
48 | private:
49 | BX_ALIGN_DECL(16, uint8_t) m_internal[64];
50 | };
51 |
52 | /// File writer.
53 | class FileWriter : public FileWriterI
54 | {
55 | public:
56 | ///
57 | FileWriter();
58 |
59 | ///
60 | virtual ~FileWriter();
61 |
62 | ///
63 | virtual bool open(const FilePath& _filePath, bool _append, Error* _err) override;
64 |
65 | ///
66 | virtual void close() override;
67 |
68 | ///
69 | virtual int64_t seek(int64_t _offset = 0, Whence::Enum _whence = Whence::Current) override;
70 |
71 | ///
72 | virtual int32_t write(const void* _data, int32_t _size, Error* _err) override;
73 |
74 | private:
75 | BX_ALIGN_DECL(16, uint8_t) m_internal[64];
76 | };
77 |
78 | /// File type.
79 | struct FileType
80 | {
81 | /// File types:
82 | enum Enum
83 | {
84 | File, //!< File.
85 | Dir, //!< Directory.
86 |
87 | Count
88 | };
89 | };
90 |
91 | /// File info.
92 | struct FileInfo
93 | {
94 | FilePath filePath; //!< File path.
95 | uint64_t size; //!< File size.
96 | FileType::Enum type; //!< File type.
97 | };
98 |
99 | /// Directory reader.
100 | class DirectoryReader : public ReaderOpenI, public CloserI, public ReaderI
101 | {
102 | public:
103 | ///
104 | DirectoryReader();
105 |
106 | ///
107 | virtual ~DirectoryReader();
108 |
109 | ///
110 | virtual bool open(const FilePath& _filePath, Error* _err) override;
111 |
112 | ///
113 | virtual void close() override;
114 |
115 | ///
116 | virtual int32_t read(void* _data, int32_t _size, Error* _err) override;
117 |
118 | private:
119 | BX_ALIGN_DECL(16, uint8_t) m_internal[sizeof(FilePath)+sizeof(FileInfo)+16];
120 | };
121 |
122 | /// FIle stat.
123 | bool stat(FileInfo& _outFileInfo, const FilePath& _filePath);
124 |
125 | /// Creates a directory named `_filePath`.
126 | ///
127 | bool make(const FilePath& _filePath, Error* _err = ErrorIgnore{});
128 |
129 | /// Creates a directory named `_filePath` along with all necessary parents.
130 | ///
131 | bool makeAll(const FilePath& _filePath, Error* _err = ErrorIgnore{});
132 |
133 | /// Removes file or directory.
134 | ///
135 | bool remove(const FilePath& _filePath, Error* _err = ErrorIgnore{});
136 |
137 | /// Removes file or directory recursively.
138 | ///
139 | bool removeAll(const FilePath& _filePath, Error* _err = ErrorIgnore{});
140 |
141 | } // namespace bx
142 |
143 | #endif // BX_FILE_H_HEADER_GUARD
144 |
--------------------------------------------------------------------------------
/include/bx/filepath.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_FILEPATH_H_HEADER_GUARD
7 | #define BX_FILEPATH_H_HEADER_GUARD
8 |
9 | #include "error.h"
10 | #include "string.h"
11 |
12 | namespace bx
13 | {
14 | BX_ERROR_RESULT(kErrorAccess, BX_MAKEFOURCC('b', 'x', 1, 1) );
15 | BX_ERROR_RESULT(kErrorNotDirectory, BX_MAKEFOURCC('b', 'x', 1, 2) );
16 |
17 | constexpr int32_t kMaxFilePath = 1024;
18 |
19 | /// Special predefined OS directories.
20 | ///
21 | struct Dir
22 | {
23 | /// Special OS directories:
24 | enum Enum
25 | {
26 | Current, //!< Current directory.
27 | Executable, //!< Executable file path.
28 | Home, //!< User's home directory.
29 | Temp, //!< Temporary directory.
30 |
31 | Count
32 | };
33 | };
34 |
35 | /// FilePath parser and helper.
36 | ///
37 | /// /abv/gd/555/333/pod.mac
38 | /// ppppppppppppppppbbbeeee
39 | /// ^ ^ ^
40 | /// +-path base-+ +-ext
41 | /// ^^^^^^^
42 | /// +-filename
43 | ///
44 | class FilePath
45 | {
46 | public:
47 | /// Default constructor, creates empty file path.
48 | ///
49 | FilePath();
50 |
51 | /// Construct file path from special OS directory.
52 | ///
53 | FilePath(Dir::Enum _dir);
54 |
55 | /// Construct file path from C string.
56 | ///
57 | FilePath(const char* _str);
58 |
59 | /// Construct file path from string.
60 | ///
61 | FilePath(const StringView& _str);
62 |
63 | /// Assign file path from string.
64 | ///
65 | FilePath& operator=(const StringView& _rhs);
66 |
67 | /// Clear file path.
68 | ///
69 | void clear();
70 |
71 | /// Set file path from special OS directory.
72 | ///
73 | void set(Dir::Enum _dir);
74 |
75 | /// Set file path.
76 | ///
77 | void set(const StringView& _str);
78 |
79 | /// Join directory to file path.
80 | ///
81 | void join(const StringView& _str);
82 |
83 | /// Implicitly converts FilePath to StringView.
84 | ///
85 | operator StringView() const;
86 |
87 | /// Returns zero-terminated C string pointer to file path.
88 | ///
89 | const char* getCPtr() const;
90 |
91 | /// If path is `/abv/gd/555/333/pod.mac` returns `/abv/gd/555/333/`.
92 | ///
93 | StringView getPath() const;
94 |
95 | /// If path is `/abv/gd/555/333/pod.mac` returns `pod.mac`.
96 | ///
97 | StringView getFileName() const;
98 |
99 | /// If path is `/abv/gd/555/333/pod.mac` returns `pod`.
100 | ///
101 | StringView getBaseName() const;
102 |
103 | /// If path is `/abv/gd/555/333/pod.mac` returns `.mac`.
104 | ///
105 | StringView getExt() const;
106 |
107 | /// Returns true if file path is absolute.
108 | ///
109 | bool isAbsolute() const;
110 |
111 | /// Returns true if file path is empty.
112 | ///
113 | bool isEmpty() const;
114 |
115 | private:
116 | char m_filePath[kMaxFilePath];
117 | };
118 |
119 | } // namespace bx
120 |
121 | #endif // BX_FILEPATH_H_HEADER_GUARD
122 |
--------------------------------------------------------------------------------
/include/bx/float4x4_t.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_FLOAT4X4_H_HEADER_GUARD
7 | #define BX_FLOAT4X4_H_HEADER_GUARD
8 |
9 | #include "simd_t.h"
10 |
11 | namespace bx
12 | {
13 | /// 4x4 matrix.
14 | BX_ALIGN_DECL_16(struct) float4x4_t
15 | {
16 | simd128_t col[4];
17 | };
18 |
19 | /// Multiplies vector `_a` with matrix `_b` ignoring W component of vector `_a`.
20 | simd128_t simd_mul_xyz1(simd128_t _a, const float4x4_t* _b);
21 |
22 | /// Multiplies vector `_a` with matrix `_b`.
23 | simd128_t simd_mul(simd128_t _a, const float4x4_t* _b);
24 |
25 | /// Multiplies two matrices.
26 | void float4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b);
27 |
28 | /// Multiplies two 3x4 affine matrices (i.e. "model" or "world" matrices).
29 | /// This function is a micro-optimized version of float4x4_mul() in the case
30 | /// when the last row of the both input matrices are (0, 0, 0, 1).
31 | void model4x4_mul(float4x4_t* _result, const float4x4_t* _a, const float4x4_t* _b);
32 |
33 | /// Multiplies a 3x4 affine matrix with a general 4x4 matrix.
34 | /// This function is a micro-optimized version of float4x4_mul() in the case
35 | /// when the last row of the _model input matrix is (0, 0, 0, 1).
36 | void model4x4_mul_viewproj4x4(float4x4_t* _result, const float4x4_t* _model, const float4x4_t* _viewProj);
37 |
38 | /// Transpose of matrix.
39 | void float4x4_transpose(float4x4_t* _result, const float4x4_t* _mtx);
40 |
41 | /// Inverse of matrix.
42 | void float4x4_inverse(float4x4_t* _result, const float4x4_t* _a);
43 |
44 | } // namespace bx
45 |
46 | #include "inline/float4x4_t.inl"
47 |
48 | #endif // BX_FLOAT4X4_H_HEADER_GUARD
49 |
--------------------------------------------------------------------------------
/include/bx/hash.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_HASH_H_HEADER_GUARD
7 | #define BX_HASH_H_HEADER_GUARD
8 |
9 | #include "allocator.h" // isAligned
10 | #include "string.h" // StringView
11 |
12 | namespace bx
13 | {
14 | /// 32-bit Adler checksum hash.
15 | class HashAdler32
16 | {
17 | public:
18 | ///
19 | void begin();
20 |
21 | ///
22 | void add(const void* _data, int32_t _len);
23 |
24 | ///
25 | void add(const char* _data);
26 |
27 | ///
28 | void add(const StringView& _data);
29 |
30 | ///
31 | template
32 | void add(const Ty& _data);
33 |
34 | ///
35 | uint32_t end();
36 |
37 | private:
38 | uint32_t m_a;
39 | uint32_t m_b;
40 | };
41 |
42 | /// 32-bit cyclic redundancy checksum hash.
43 | class HashCrc32
44 | {
45 | public:
46 | enum Enum
47 | {
48 | Ieee, //!< 0xedb88320
49 | Castagnoli, //!< 0x82f63b78
50 | Koopman, //!< 0xeb31d82e
51 |
52 | Count
53 | };
54 |
55 | ///
56 | void begin(Enum _type = Ieee);
57 |
58 | ///
59 | void add(const void* _data, int32_t _len);
60 |
61 | ///
62 | void add(const char* _data);
63 |
64 | ///
65 | void add(const StringView& _data);
66 |
67 | ///
68 | template
69 | void add(const Ty& _data);
70 |
71 | ///
72 | uint32_t end();
73 |
74 | private:
75 | const uint32_t* m_table;
76 | uint32_t m_hash;
77 | };
78 |
79 | /// 32-bit non-cryptographic multiply and rotate hash.
80 | class HashMurmur2A
81 | {
82 | public:
83 | ///
84 | void begin(uint32_t _seed = 0);
85 |
86 | ///
87 | void add(const void* _data, int32_t _len);
88 |
89 | ///
90 | void add(const char* _data);
91 |
92 | ///
93 | void add(const StringView& _data);
94 |
95 | ///
96 | template
97 | void add(const Ty& _data);
98 |
99 | ///
100 | uint32_t end();
101 |
102 | private:
103 | uint32_t m_hash;
104 | uint32_t m_size;
105 | uint8_t m_tail[4];
106 | uint8_t m_count;
107 | };
108 |
109 | /// 32-bit non-cryptographic multiply and rotate hash.
110 | class HashMurmur3
111 | {
112 | public:
113 | ///
114 | void begin(uint32_t _seed = 0);
115 |
116 | ///
117 | void add(const void* _data, int32_t _len);
118 |
119 | ///
120 | void add(const char* _data);
121 |
122 | ///
123 | void add(const StringView& _data);
124 |
125 | ///
126 | template
127 | void add(const Ty& _data);
128 |
129 | ///
130 | uint32_t end();
131 |
132 | private:
133 | uint32_t m_hash;
134 | uint32_t m_size;
135 | uint8_t m_tail[4];
136 | uint8_t m_count;
137 | };
138 |
139 | ///
140 | template
141 | uint32_t hash(const void* _data, uint32_t _size);
142 |
143 | ///
144 | template
145 | uint32_t hash(const char* _data);
146 |
147 | ///
148 | template
149 | uint32_t hash(const StringView& _data);
150 |
151 | ///
152 | template
153 | uint32_t hash(const Ty& _data);
154 |
155 | } // namespace bx
156 |
157 | #include "inline/hash.inl"
158 |
159 | #endif // BX_HASH_H_HEADER_GUARD
160 |
--------------------------------------------------------------------------------
/include/bx/inline/allocator.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_ALLOCATOR_H_HEADER_GUARD
7 | # error "Must be included from bx/allocator.h"
8 | #endif // BX_ALLOCATOR_H_HEADER_GUARD
9 |
10 | inline void* operator new(size_t, bx::PlacementNewTag, void* _ptr)
11 | {
12 | return _ptr;
13 | }
14 |
15 | inline void operator delete(void*, bx::PlacementNewTag, void*) throw()
16 | {
17 | }
18 |
19 | namespace bx
20 | {
21 | inline AllocatorI::~AllocatorI()
22 | {
23 | }
24 |
25 | inline void* alignPtr(void* _ptr, size_t _extra, size_t _align)
26 | {
27 | const uintptr_t addr = bitCast(_ptr);
28 | const uintptr_t unaligned = addr + _extra; // space for header
29 | const uintptr_t aligned = alignUp(unaligned, _align);
30 |
31 | return bitCast(aligned);
32 | }
33 |
34 | inline void* alloc(AllocatorI* _allocator, size_t _size, size_t _align, const Location& _location)
35 | {
36 | return _allocator->realloc(NULL, _size, _align, _location.filePath, _location.line);
37 | }
38 |
39 | inline void free(AllocatorI* _allocator, void* _ptr, size_t _align, const Location& _location)
40 | {
41 | _allocator->realloc(_ptr, 0, _align, _location.filePath, _location.line);
42 | }
43 |
44 | inline void* realloc(AllocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const Location& _location)
45 | {
46 | return _allocator->realloc(_ptr, _size, _align, _location.filePath, _location.line);
47 | }
48 |
49 | inline void* alignedAlloc(AllocatorI* _allocator, size_t _size, size_t _align, const Location& _location)
50 | {
51 | const size_t align = max(_align, sizeof(uint32_t) );
52 | const size_t total = _size + align;
53 | uint8_t* ptr = (uint8_t*)alloc(_allocator, total, 0, _location);
54 | uint8_t* aligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), align);
55 | uint32_t* header = (uint32_t*)aligned - 1;
56 | *header = uint32_t(aligned - ptr);
57 | return aligned;
58 | }
59 |
60 | inline void alignedFree(AllocatorI* _allocator, void* _ptr, size_t _align, const Location& _location)
61 | {
62 | BX_UNUSED(_align);
63 | uint8_t* aligned = (uint8_t*)_ptr;
64 | uint32_t* header = (uint32_t*)aligned - 1;
65 | uint8_t* ptr = aligned - *header;
66 | free(_allocator, ptr, 0, _location);
67 | }
68 |
69 | inline void* alignedRealloc(AllocatorI* _allocator, void* _ptr, size_t _size, size_t _align, const Location& _location)
70 | {
71 | if (NULL == _ptr)
72 | {
73 | return alignedAlloc(_allocator, _size, _align, _location);
74 | }
75 |
76 | uint8_t* aligned = (uint8_t*)_ptr;
77 | uint32_t offset = *( (uint32_t*)aligned - 1);
78 | uint8_t* ptr = aligned - offset;
79 |
80 | const size_t align = max(_align, sizeof(uint32_t) );;
81 | const size_t total = _size + align;
82 | ptr = (uint8_t*)realloc(_allocator, ptr, total, 0, _location);
83 | uint8_t* newAligned = (uint8_t*)alignPtr(ptr, sizeof(uint32_t), align);
84 |
85 | if (newAligned == aligned)
86 | {
87 | return aligned;
88 | }
89 |
90 | aligned = ptr + offset;
91 | memMove(newAligned, aligned, _size);
92 | uint32_t* header = (uint32_t*)newAligned - 1;
93 | *header = uint32_t(newAligned - ptr);
94 | return newAligned;
95 | }
96 |
97 | template
98 | inline void deleteObject(AllocatorI* _allocator, ObjectT* _object, size_t _align, const Location& _location)
99 | {
100 | if (NULL != _object)
101 | {
102 | _object->~ObjectT();
103 | free(_allocator, _object, _align, _location);
104 | }
105 | }
106 |
107 | } // namespace bx
108 |
--------------------------------------------------------------------------------
/include/bx/inline/bx.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_H_HEADER_GUARD
7 | # error "Must be included from bx/bx.h!"
8 | #endif // BX_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | // Reference(S):
13 | // - https://web.archive.org/web/20181115035420/http://cnicholson.net/2011/01/stupid-c-tricks-a-better-sizeof_array/
14 | //
15 | template
16 | char (&CountOfRequireArrayArgumentT(const Ty (&)[NumT]) )[NumT];
17 |
18 | template
19 | struct isEnabled
20 | {
21 | // Template for avoiding MSVC: C4127: conditional expression is constant
22 | static constexpr bool value = B;
23 | };
24 |
25 | inline constexpr bool ignoreC4127(bool _x)
26 | {
27 | return _x;
28 | }
29 |
30 | template
31 | inline Ty* addressOf(Ty& _a)
32 | {
33 | return reinterpret_cast(
34 | &const_cast(
35 | reinterpret_cast(_a)
36 | )
37 | );
38 | }
39 |
40 | template
41 | inline const Ty* addressOf(const Ty& _a)
42 | {
43 | return reinterpret_cast(
44 | &const_cast(
45 | reinterpret_cast(_a)
46 | )
47 | );
48 | }
49 |
50 | template
51 | inline Ty* addressOf(void* _ptr, ptrdiff_t _offsetInBytes)
52 | {
53 | return (Ty*)( (uint8_t*)_ptr + _offsetInBytes);
54 | }
55 |
56 | template
57 | inline const Ty* addressOf(const void* _ptr, ptrdiff_t _offsetInBytes)
58 | {
59 | return (const Ty*)( (const uint8_t*)_ptr + _offsetInBytes);
60 | }
61 |
62 | template
63 | inline void swap(Ty& _a, Ty& _b)
64 | {
65 | Ty tmp = move(_a); _a = move(_b); _b = move(tmp);
66 | }
67 |
68 | template
69 | struct LimitsT
70 | {
71 | static constexpr Ty max = ( ( (Ty(1) << ( (sizeof(Ty) * 8) - 2) ) - Ty(1) ) << 1) | Ty(1);
72 | static constexpr Ty min = -max - Ty(1);
73 | };
74 |
75 | template
76 | struct LimitsT
77 | {
78 | static constexpr Ty min = 0;
79 | static constexpr Ty max = Ty(-1);
80 | };
81 |
82 | template<>
83 | struct LimitsT
84 | {
85 | static constexpr float min = -kFloatLargest;
86 | static constexpr float max = kFloatLargest;
87 | };
88 |
89 | template<>
90 | struct LimitsT
91 | {
92 | static constexpr double min = -kDoubleLargest;
93 | static constexpr double max = kDoubleLargest;
94 | };
95 |
96 | template
97 | inline constexpr Ty max()
98 | {
99 | return LimitsT::max;
100 | }
101 |
102 | template
103 | inline constexpr Ty min()
104 | {
105 | return LimitsT::min;
106 | }
107 |
108 | template
109 | inline constexpr Ty min(const Ty& _a, const TypeIdentityType& _b)
110 | {
111 | return _a < _b ? _a : _b;
112 | }
113 |
114 | template
115 | inline constexpr Ty max(const Ty& _a, const TypeIdentityType& _b)
116 | {
117 | return _a > _b ? _a : _b;
118 | }
119 |
120 | template
121 | inline constexpr Ty min(const Ty& _a, const TypeIdentityType& _b, const Args&... _args)
122 | {
123 | return min(min(_a, _b), _args...);
124 | }
125 |
126 | template
127 | inline constexpr Ty max(const Ty& _a, const TypeIdentityType& _b, const Args&... _args)
128 | {
129 | return max(max(_a, _b), _args...);
130 | }
131 |
132 | template
133 | inline constexpr Ty mid(const Ty& _a, const TypeIdentityType& _b, const Args&... _args)
134 | {
135 | return max(min(_a, _b), min(max(_a, _b), _args...) );
136 | }
137 |
138 | template
139 | inline constexpr Ty clamp(const Ty& _a, const TypeIdentityType& _min, const TypeIdentityType& _max)
140 | {
141 | return max(min(_a, _max), _min);
142 | }
143 |
144 | template
145 | inline constexpr bool isPowerOf2(Ty _a)
146 | {
147 | return _a && !(_a & (_a - 1) );
148 | }
149 |
150 | constexpr bool isConstantEvaluated()
151 | {
152 | return __builtin_is_constant_evaluated();
153 | }
154 |
155 | template
156 | inline constexpr Ty bitCast(const FromT& _from)
157 | {
158 | static_assert(sizeof(Ty) == sizeof(FromT)
159 | , "bx::bitCast failed! Ty and FromT must be the same size."
160 | );
161 | static_assert(isTriviallyCopyable()
162 | , "bx::bitCast failed! FromT must be trivially copyable."
163 | );
164 | static_assert(isTriviallyCopyable()
165 | , "bx::bitCast failed! Ty must be trivially copyable."
166 | );
167 | static_assert(isTriviallyConstructible()
168 | , "bx::bitCast failed! Ty must be trivially constructible."
169 | );
170 |
171 | return __builtin_bit_cast(Ty, _from);
172 | }
173 |
174 | template
175 | inline Ty narrowCast(const FromT& _from, Location _location)
176 | {
177 | Ty to = static_cast(_from);
178 | BX_ASSERT_LOC(_location, static_cast(to) == _from
179 | , "bx::narrowCast failed! Value is truncated!"
180 | );
181 | return to;
182 | }
183 |
184 | constexpr float kFloatInfinity = bitCast(kFloatExponentMask);
185 | constexpr double kDoubleInfinity = bitCast(kDoubleExponentMask);
186 |
187 | } // namespace bx
188 |
--------------------------------------------------------------------------------
/include/bx/inline/endian.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_ENDIAN_H_HEADER_GUARD
7 | # error "Must be included from bx/endian.h!"
8 | #endif // BX_ENDIAN_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | inline int16_t endianSwap(int16_t _in)
13 | {
14 | return (int16_t)endianSwap( (uint16_t)_in);
15 | }
16 |
17 | inline uint16_t endianSwap(uint16_t _in)
18 | {
19 | return (_in>>8) | (_in<<8);
20 | }
21 |
22 | inline int32_t endianSwap(int32_t _in)
23 | {
24 | return (int32_t)endianSwap( (uint32_t)_in);
25 | }
26 |
27 | inline uint32_t endianSwap(uint32_t _in)
28 | {
29 | return ( _in >>24) | ( _in <<24)
30 | | ( (_in&0x00ff0000)>> 8) | ( (_in&0x0000ff00)<< 8)
31 | ;
32 | }
33 |
34 | inline int64_t endianSwap(int64_t _in)
35 | {
36 | return (int64_t)endianSwap( (uint64_t)_in);
37 | }
38 |
39 | inline uint64_t endianSwap(uint64_t _in)
40 | {
41 | return (_in >>56) | ( _in <<56)
42 | | ( (_in&UINT64_C(0x00ff000000000000) )>>40) | ( (_in&UINT64_C(0x000000000000ff00) )<<40)
43 | | ( (_in&UINT64_C(0x0000ff0000000000) )>>24) | ( (_in&UINT64_C(0x0000000000ff0000) )<<24)
44 | | ( (_in&UINT64_C(0x000000ff00000000) )>> 8) | ( (_in&UINT64_C(0x00000000ff000000) )<< 8)
45 | ;
46 | }
47 |
48 | template
49 | inline Ty toLittleEndian(Ty _in)
50 | {
51 | #if BX_CPU_ENDIAN_BIG
52 | return endianSwap(_in);
53 | #else
54 | return _in;
55 | #endif // BX_CPU_ENDIAN_BIG
56 | }
57 |
58 | template
59 | inline Ty toBigEndian(Ty _in)
60 | {
61 | #if BX_CPU_ENDIAN_LITTLE
62 | return endianSwap(_in);
63 | #else
64 | return _in;
65 | #endif // BX_CPU_ENDIAN_LITTLE
66 | }
67 |
68 | template
69 | inline Ty toHostEndian(Ty _in, bool _fromLittleEndian)
70 | {
71 | #if BX_CPU_ENDIAN_LITTLE
72 | return _fromLittleEndian ? _in : endianSwap(_in);
73 | #else
74 | return _fromLittleEndian ? endianSwap(_in) : _in;
75 | #endif // BX_CPU_ENDIAN_LITTLE
76 | }
77 |
78 | } // namespace bx
79 |
--------------------------------------------------------------------------------
/include/bx/inline/error.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_ERROR_H_HEADER_GUARD
7 | # error "Must be included from bx/error!"
8 | #endif // BX_ERROR_H_HEADER_GUARD
9 |
10 | #include
11 |
12 | namespace bx
13 | {
14 | inline Error::Error()
15 | : m_code(0)
16 | {
17 | }
18 |
19 | inline void Error::reset()
20 | {
21 | m_code = 0;
22 | m_msg.clear();
23 | }
24 |
25 | inline void Error::setError(ErrorResult _errorResult, const StringLiteral& _msg, const Location& _location)
26 | {
27 | BX_ASSERT(0 != _errorResult.code, "Invalid ErrorResult passed to setError!");
28 |
29 | if (!isOk() )
30 | {
31 | return;
32 | }
33 |
34 | m_location = _location;
35 | m_code = _errorResult.code;
36 | m_msg = _msg;
37 | }
38 |
39 | inline bool Error::isOk() const
40 | {
41 | return 0 == m_code;
42 | }
43 |
44 | inline ErrorResult Error::get() const
45 | {
46 | ErrorResult result = { m_code };
47 | return result;
48 | }
49 |
50 | inline const StringLiteral& Error::getMessage() const
51 | {
52 | return m_msg;
53 | }
54 |
55 | inline const Location& Error::getLocation() const
56 | {
57 | return m_location;
58 | }
59 |
60 | inline bool Error::operator==(const ErrorResult& _rhs) const
61 | {
62 | return _rhs.code == m_code;
63 | }
64 |
65 | inline bool Error::operator!=(const ErrorResult& _rhs) const
66 | {
67 | return _rhs.code != m_code;
68 | }
69 |
70 | inline ErrorIgnore::operator Error*()
71 | {
72 | return this;
73 | }
74 |
75 | inline ErrorAssert::~ErrorAssert()
76 | {
77 | BX_ASSERT_LOC(getLocation(), isOk(), "ErrorAssert: 0x%08x `%S`"
78 | , get().code
79 | , &getMessage()
80 | );
81 | }
82 |
83 | inline ErrorFatal::operator Error*()
84 | {
85 | return this;
86 | }
87 |
88 | inline ErrorFatal::~ErrorFatal()
89 | {
90 | _BX_ASSERT_LOC(getLocation(), isOk(), "ErrorFatal: 0x%08x `%S`"
91 | , get().code
92 | , &getMessage()
93 | );
94 | }
95 |
96 | inline ErrorAssert::operator Error*()
97 | {
98 | return this;
99 | }
100 |
101 | inline ErrorScope::ErrorScope(Error* _err, const StringLiteral& _name)
102 | : m_err(_err)
103 | , m_name(_name)
104 | {
105 | BX_UNUSED(m_err);
106 | BX_ASSERT(NULL != _err, "_err can't be NULL");
107 | }
108 |
109 | inline ErrorScope::~ErrorScope()
110 | {
111 | if (m_name.isEmpty() )
112 | {
113 | BX_ASSERT_LOC(
114 | m_err->getLocation()
115 | , m_err->isOk()
116 | , "ErrorScope: 0x%08x `%S`"
117 | , m_err->get().code
118 | , &m_err->getMessage()
119 | );
120 | }
121 | else
122 | {
123 | BX_ASSERT_LOC(
124 | m_err->getLocation()
125 | , m_err->isOk()
126 | , "ErrorScope: %S - 0x%08x `%S`"
127 | , &m_name
128 | , m_err->get().code
129 | , &m_err->getMessage()
130 | );
131 | }
132 | }
133 |
134 | inline const StringLiteral& ErrorScope::getName() const
135 | {
136 | return m_name;
137 | }
138 |
139 | } // namespace bx
140 |
--------------------------------------------------------------------------------
/include/bx/inline/hash.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_HASH_H_HEADER_GUARD
7 | # error "Must be included from bx/hash.h!"
8 | #endif // BX_HASH_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | inline void HashAdler32::begin()
13 | {
14 | m_a = 1;
15 | m_b = 0;
16 | }
17 |
18 | inline void HashAdler32::add(const void* _data, int32_t _len)
19 | {
20 | constexpr uint32_t kModAdler = 65521;
21 |
22 | const uint8_t* data = (const uint8_t*)_data;
23 | for (; _len != 0; --_len)
24 | {
25 | m_a = (m_a + *data++) % kModAdler;
26 | m_b = (m_b + m_a ) % kModAdler;
27 | }
28 | }
29 |
30 | inline void HashAdler32::add(const char* _data)
31 | {
32 | return add(StringView(_data) );
33 | }
34 |
35 | inline void HashAdler32::add(const StringView& _data)
36 | {
37 | return add(_data.getPtr(), _data.getLength() );
38 | }
39 |
40 | template
41 | inline void HashAdler32::add(const Ty& _data)
42 | {
43 | add(&_data, sizeof(Ty) );
44 | }
45 |
46 | inline uint32_t HashAdler32::end()
47 | {
48 | return m_a | (m_b<<16);
49 | }
50 |
51 | inline void HashCrc32::add(const char* _data)
52 | {
53 | return add(StringView(_data) );
54 | }
55 |
56 | inline void HashCrc32::add(const StringView& _data)
57 | {
58 | return add(_data.getPtr(), _data.getLength() );
59 | }
60 |
61 | template
62 | inline void HashCrc32::add(const Ty& _data)
63 | {
64 | add(&_data, sizeof(Ty) );
65 | }
66 |
67 | inline uint32_t HashCrc32::end()
68 | {
69 | m_hash ^= UINT32_MAX;
70 | return m_hash;
71 | }
72 |
73 | inline void HashMurmur2A::begin(uint32_t _seed)
74 | {
75 | BX_UNUSED(m_tail);
76 | m_hash = _seed;
77 | m_size = 0;
78 | m_count = 0;
79 | }
80 |
81 | inline void HashMurmur2A::add(const char* _data)
82 | {
83 | return add(StringView(_data) );
84 | }
85 |
86 | inline void HashMurmur2A::add(const StringView& _data)
87 | {
88 | return add(_data.getPtr(), _data.getLength() );
89 | }
90 |
91 | template
92 | inline void HashMurmur2A::add(const Ty& _data)
93 | {
94 | add(&_data, sizeof(Ty) );
95 | }
96 |
97 | inline void HashMurmur3::begin(uint32_t _seed)
98 | {
99 | BX_UNUSED(m_tail);
100 | m_hash = _seed;
101 | m_size = 0;
102 | m_count = 0;
103 | }
104 |
105 | inline void HashMurmur3::add(const char* _data)
106 | {
107 | return add(StringView(_data) );
108 | }
109 |
110 | inline void HashMurmur3::add(const StringView& _data)
111 | {
112 | return add(_data.getPtr(), _data.getLength() );
113 | }
114 |
115 | template
116 | inline void HashMurmur3::add(const Ty& _data)
117 | {
118 | add(&_data, sizeof(Ty) );
119 | }
120 |
121 | template
122 | inline uint32_t hash(const void* _data, uint32_t _size)
123 | {
124 | HashT hh;
125 | hh.begin();
126 | hh.add(_data, (int32_t)_size);
127 | return hh.end();
128 | }
129 |
130 | template
131 | inline uint32_t hash(const char* _data)
132 | {
133 | return hash(StringView(_data) );
134 | }
135 |
136 | template
137 | inline uint32_t hash(const StringView& _data)
138 | {
139 | return hash(_data.getPtr(), _data.getLength() );
140 | }
141 |
142 | template
143 | inline uint32_t hash(const Ty& _data)
144 | {
145 | static_assert(isTriviallyCopyable() );
146 | return hash(&_data, sizeof(Ty) );
147 | }
148 |
149 | } // namespace bx
150 |
--------------------------------------------------------------------------------
/include/bx/inline/mpscqueue.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_MPSCQUEUE_H_HEADER_GUARD
7 | # error "Must be included from bx/mpscqueue.h!"
8 | #endif // BX_MPSCQUEUE_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | template
13 | inline MpScUnboundedQueueT::MpScUnboundedQueueT(AllocatorI* _allocator)
14 | : m_queue(_allocator)
15 | {
16 | }
17 |
18 | template
19 | inline MpScUnboundedQueueT::~MpScUnboundedQueueT()
20 | {
21 | }
22 |
23 | template
24 | inline void MpScUnboundedQueueT::push(Ty* _ptr)
25 | {
26 | MutexScope lock(m_write);
27 | m_queue.push(_ptr);
28 | }
29 |
30 | template
31 | inline Ty* MpScUnboundedQueueT::peek()
32 | {
33 | return m_queue.peek();
34 | }
35 |
36 | template
37 | inline Ty* MpScUnboundedQueueT::pop()
38 | {
39 | return m_queue.pop();
40 | }
41 |
42 | template
43 | inline MpScUnboundedBlockingQueue::MpScUnboundedBlockingQueue(AllocatorI* _allocator)
44 | : m_queue(_allocator)
45 | {
46 | }
47 |
48 | template
49 | inline MpScUnboundedBlockingQueue::~MpScUnboundedBlockingQueue()
50 | {
51 | }
52 |
53 | template
54 | inline void MpScUnboundedBlockingQueue::push(Ty* _ptr)
55 | {
56 | m_queue.push(_ptr);
57 | m_sem.post();
58 | }
59 |
60 | template
61 | inline Ty* MpScUnboundedBlockingQueue::pop()
62 | {
63 | m_sem.wait();
64 | return m_queue.pop();
65 | }
66 |
67 | } // namespace bx
68 |
--------------------------------------------------------------------------------
/include/bx/inline/mutex.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_MUTEX_H_HEADER_GUARD
7 | # error "Must be included from bx/mutex.h!"
8 | #endif // BX_MUTEX_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | inline MutexScope::MutexScope(Mutex& _mutex)
13 | : m_mutex(_mutex)
14 | {
15 | m_mutex.lock();
16 | }
17 |
18 | inline MutexScope::~MutexScope()
19 | {
20 | m_mutex.unlock();
21 | }
22 |
23 | } // namespace bx
24 |
--------------------------------------------------------------------------------
/include/bx/inline/os.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_H_HEADER_GUARD
7 | # error "Must be included from bx/os.h!"
8 | #endif // BX_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | template
13 | inline ProtoT dlsym(void* _handle, const StringView& _symbol)
14 | {
15 | return reinterpret_cast(dlsym(_handle, _symbol) );
16 | }
17 |
18 | } // namespace bx
19 |
--------------------------------------------------------------------------------
/include/bx/inline/rng.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_RNG_H_HEADER_GUARD
7 | # error "Must be included from bx/rng.h!"
8 | #endif // BX_RNG_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | inline RngMwc::RngMwc(uint32_t _z, uint32_t _w)
13 | : m_z(_z)
14 | , m_w(_w)
15 | {
16 | }
17 |
18 | inline void RngMwc::reset(uint32_t _z, uint32_t _w)
19 | {
20 | m_z = _z;
21 | m_w = _w;
22 | }
23 |
24 | inline uint32_t RngMwc::gen()
25 | {
26 | m_z = 36969*(m_z&65535)+(m_z>>16);
27 | m_w = 18000*(m_w&65535)+(m_w>>16);
28 | return (m_z<<16)+m_w;
29 | }
30 |
31 | inline RngShr3::RngShr3(uint32_t _jsr)
32 | : m_jsr(_jsr)
33 | {
34 | }
35 |
36 | inline void RngShr3::reset(uint32_t _jsr)
37 | {
38 | m_jsr = _jsr;
39 | }
40 |
41 | inline uint32_t RngShr3::gen()
42 | {
43 | m_jsr ^= m_jsr<<17;
44 | m_jsr ^= m_jsr>>13;
45 | m_jsr ^= m_jsr<<5;
46 | return m_jsr;
47 | }
48 |
49 | template
50 | inline float frnd(Rng* _rng)
51 | {
52 | uint32_t rnd = _rng->gen() & UINT16_MAX;
53 | return float(rnd) * 1.0f/float(UINT16_MAX);
54 | }
55 |
56 | template
57 | inline float frndh(Rng* _rng)
58 | {
59 | return 2.0f * frnd(_rng) - 1.0f;
60 | }
61 |
62 | template
63 | inline Vec3 randUnitCircle(Rng* _rng)
64 | {
65 | const float angle = frnd(_rng) * kPi2;
66 |
67 | return
68 | {
69 | cos(angle),
70 | 0.0f,
71 | sin(angle),
72 | };
73 | }
74 |
75 | template
76 | inline Vec3 randUnitSphere(Rng* _rng)
77 | {
78 | const float rand0 = frnd(_rng) * 2.0f - 1.0f;
79 | const float rand1 = frnd(_rng) * kPi2;
80 | const float sqrtf1 = sqrt(1.0f - rand0*rand0);
81 |
82 | return
83 | {
84 | sqrtf1 * cos(rand1),
85 | sqrtf1 * sin(rand1),
86 | rand0,
87 | };
88 | }
89 |
90 | template
91 | inline Vec3 randUnitHemisphere(Ty* _rng, const Vec3& _normal)
92 | {
93 | const Vec3 dir = randUnitSphere(_rng);
94 | const float ddotn = dot(dir, _normal);
95 |
96 | if (0.0f > ddotn)
97 | {
98 | return neg(dir);
99 | }
100 |
101 | return dir;
102 | }
103 |
104 | inline void generateSphereHammersley(void* _data, uint32_t _stride, uint32_t _num, float _scale)
105 | {
106 | // Reference(s):
107 | // - Sampling with Hammersley and Halton Points
108 | // https://web.archive.org/web/20190207230709/http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html
109 |
110 | uint8_t* data = (uint8_t*)_data;
111 |
112 | for (uint32_t ii = 0; ii < _num; ii++)
113 | {
114 | float tt = 0.0f;
115 | float pp = 0.5;
116 | for (uint32_t jj = ii; jj; jj >>= 1)
117 | {
118 | tt += (jj & 1) ? pp : 0.0f;
119 | pp *= 0.5f;
120 | }
121 |
122 | tt = 2.0f * tt - 1.0f;
123 |
124 | const float phi = (ii + 0.5f) / _num;
125 | const float phirad = phi * kPi2;
126 | const float st = sqrt(1.0f-tt*tt) * _scale;
127 |
128 | float* xyz = (float*)data;
129 | data += _stride;
130 |
131 | xyz[0] = st * cos(phirad);
132 | xyz[1] = st * sin(phirad);
133 | xyz[2] = tt * _scale;
134 | }
135 | }
136 |
137 | template
138 | inline void shuffle(Rng* _rng, Ty* _array, uint32_t _num)
139 | {
140 | BX_ASSERT(_num != 0, "Number of elements can't be 0!");
141 |
142 | for (uint32_t ii = 0, num = _num-1; ii < num; ++ii)
143 | {
144 | uint32_t jj = ii + 1 + _rng->gen() % (num - ii);
145 | swap(_array[ii], _array[jj]);
146 | }
147 | }
148 |
149 | } // namespace bx
150 |
--------------------------------------------------------------------------------
/include/bx/inline/simd256_avx.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_SIMD_T_H_HEADER_GUARD
7 | # error "Must be included from bx/simd_t.h!"
8 | #endif // BX_SIMD_T_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | template<>
13 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_ld(const void* _ptr)
14 | {
15 | return _mm256_load_ps(reinterpret_cast(_ptr) );
16 | }
17 |
18 | template<>
19 | BX_SIMD_FORCE_INLINE void simd_st(void* _ptr, simd256_avx_t _a)
20 | {
21 | _mm256_store_ps(reinterpret_cast(_ptr), _a);
22 | }
23 |
24 | template<>
25 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_ld(float _x, float _y, float _z, float _w, float _A, float _B, float _C, float _D)
26 | {
27 | return _mm256_set_ps(_D, _C, _B, _A, _w, _z, _y, _x);
28 | }
29 |
30 | template<>
31 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w, uint32_t _A, uint32_t _B, uint32_t _C, uint32_t _D)
32 | {
33 | const __m256i set = _mm256_set_epi32(_D, _C, _B, _A, _w, _z, _y, _x);
34 | const simd256_avx_t result = _mm256_castsi256_ps(set);
35 |
36 | return result;
37 | }
38 |
39 | template<>
40 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_splat(float _a)
41 | {
42 | return _mm256_set1_ps(_a);
43 | }
44 |
45 | template<>
46 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_isplat(uint32_t _a)
47 | {
48 | const __m256i splat = _mm256_set1_epi32(_a);
49 | const simd256_avx_t result = _mm256_castsi256_ps(splat);
50 |
51 | return result;
52 | }
53 |
54 | template<>
55 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_itof(simd256_avx_t _a)
56 | {
57 | const __m256i itof = _mm256_castps_si256(_a);
58 | const simd256_avx_t result = _mm256_cvtepi32_ps(itof);
59 |
60 | return result;
61 | }
62 |
63 | template<>
64 | BX_SIMD_FORCE_INLINE simd256_avx_t simd_ftoi(simd256_avx_t _a)
65 | {
66 | const __m256i ftoi = _mm256_cvtps_epi32(_a);
67 | const simd256_avx_t result = _mm256_castsi256_ps(ftoi);
68 |
69 | return result;
70 | }
71 |
72 | typedef simd256_avx_t simd256_t;
73 |
74 | } // namespace bx
75 |
--------------------------------------------------------------------------------
/include/bx/inline/simd256_ref.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_SIMD_T_H_HEADER_GUARD
7 | # error "Must be included from bx/simd_t.h!"
8 | #endif // BX_SIMD_T_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | template<>
13 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_ld(const void* _ptr)
14 | {
15 | const simd256_ref_t::type* ptr = reinterpret_cast(_ptr);
16 | simd256_ref_t result;
17 | result.simd128_0 = simd_ld(&ptr[0]);
18 | result.simd128_1 = simd_ld(&ptr[1]);
19 | return result;
20 | }
21 |
22 | template<>
23 | BX_SIMD_FORCE_INLINE void simd_st(void* _ptr, simd256_ref_t& _a)
24 | {
25 | simd256_ref_t* result = reinterpret_cast(_ptr);
26 | simd_st(&result[0], _a.simd128_0);
27 | simd_st(&result[1], _a.simd128_1);
28 | }
29 |
30 | template<>
31 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_ld(float _x, float _y, float _z, float _w, float _a, float _b, float _c, float _d)
32 | {
33 | simd256_ref_t result;
34 | result.simd128_0 = simd_ld(_x, _y, _z, _w);
35 | result.simd128_1 = simd_ld(_a, _b, _c, _d);
36 | return result;
37 | }
38 |
39 | template<>
40 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_ild(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w, uint32_t _a, uint32_t _b, uint32_t _c, uint32_t _d)
41 | {
42 | simd256_ref_t result;
43 | result.simd128_0 = simd_ild(_x, _y, _z, _w);
44 | result.simd128_1 = simd_ild(_a, _b, _c, _d);
45 | return result;
46 | }
47 |
48 | template<>
49 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_splat(float _a)
50 | {
51 | simd256_ref_t result;
52 | result.simd128_0 = simd_splat(_a);
53 | result.simd128_1 = simd_splat(_a);
54 | return result;
55 | }
56 |
57 | template<>
58 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_isplat(uint32_t _a)
59 | {
60 | simd256_ref_t result;
61 | result.simd128_0 = simd_isplat(_a);
62 | result.simd128_1 = simd_isplat(_a);
63 | return result;
64 | }
65 |
66 | template<>
67 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_itof(simd256_ref_t _a)
68 | {
69 | simd256_ref_t result;
70 | result.simd128_0 = simd_itof(_a.simd128_0);
71 | result.simd128_1 = simd_itof(_a.simd128_1);
72 | return result;
73 | }
74 |
75 | template<>
76 | BX_SIMD_FORCE_INLINE simd256_ref_t simd_ftoi(simd256_ref_t _a)
77 | {
78 | simd256_ref_t result;
79 | result.simd128_0 = simd_ftoi(_a.simd128_0);
80 | result.simd128_1 = simd_ftoi(_a.simd128_1);
81 | return result;
82 | }
83 |
84 | } // namespace bx
85 |
--------------------------------------------------------------------------------
/include/bx/inline/spscqueue.inl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_SPSCQUEUE_H_HEADER_GUARD
7 | # error "Must be included from bx/spscqueue.h!"
8 | #endif // BX_SPSCQUEUE_H_HEADER_GUARD
9 |
10 | namespace bx
11 | {
12 | // Reference(s):
13 | // - Writing Lock-Free Code: A Corrected Queue
14 | // https://web.archive.org/web/20190207230604/http://www.drdobbs.com/parallel/writing-lock-free-code-a-corrected-queue/210604448
15 | //
16 | inline SpScUnboundedQueue::SpScUnboundedQueue(AllocatorI* _allocator)
17 | : m_allocator(_allocator)
18 | , m_first(BX_NEW(m_allocator, Node)(NULL) )
19 | , m_divider(m_first)
20 | , m_last(m_first)
21 | {
22 | }
23 |
24 | inline SpScUnboundedQueue::~SpScUnboundedQueue()
25 | {
26 | while (NULL != m_first)
27 | {
28 | Node* node = m_first;
29 | m_first = node->m_next;
30 | deleteObject(m_allocator, node);
31 | }
32 | }
33 |
34 | inline void SpScUnboundedQueue::push(void* _ptr)
35 | {
36 | m_last->m_next = BX_NEW(m_allocator, Node)(_ptr);
37 | atomicExchangePtr( (void**)&m_last, m_last->m_next);
38 | while (m_first != m_divider)
39 | {
40 | Node* node = m_first;
41 | m_first = m_first->m_next;
42 | deleteObject(m_allocator, node);
43 | }
44 | }
45 |
46 | inline void* SpScUnboundedQueue::peek()
47 | {
48 | if (m_divider != m_last)
49 | {
50 | return m_divider->m_next->m_ptr;
51 | }
52 |
53 | return NULL;
54 | }
55 |
56 | inline void* SpScUnboundedQueue::pop()
57 | {
58 | if (m_divider != m_last)
59 | {
60 | void* ptr = m_divider->m_next->m_ptr;
61 | atomicExchangePtr( (void**)&m_divider, m_divider->m_next);
62 | return ptr;
63 | }
64 |
65 | return NULL;
66 | }
67 |
68 | inline SpScUnboundedQueue::Node::Node(void* _ptr)
69 | : m_ptr(_ptr)
70 | , m_next(NULL)
71 | {
72 | }
73 |
74 | template
75 | inline SpScUnboundedQueueT::SpScUnboundedQueueT(AllocatorI* _allocator)
76 | : m_queue(_allocator)
77 | {
78 | }
79 |
80 | template
81 | inline SpScUnboundedQueueT::~SpScUnboundedQueueT()
82 | {
83 | }
84 |
85 | template
86 | inline void SpScUnboundedQueueT::push(Ty* _ptr)
87 | {
88 | m_queue.push(_ptr);
89 | }
90 |
91 | template
92 | inline Ty* SpScUnboundedQueueT::peek()
93 | {
94 | return (Ty*)m_queue.peek();
95 | }
96 |
97 | template
98 | inline Ty* SpScUnboundedQueueT::pop()
99 | {
100 | return (Ty*)m_queue.pop();
101 | }
102 |
103 | #if BX_CONFIG_SUPPORTS_THREADING
104 | inline SpScBlockingUnboundedQueue::SpScBlockingUnboundedQueue(AllocatorI* _allocator)
105 | : m_queue(_allocator)
106 | {
107 | }
108 |
109 | inline SpScBlockingUnboundedQueue::~SpScBlockingUnboundedQueue()
110 | {
111 | }
112 |
113 | inline void SpScBlockingUnboundedQueue::push(void* _ptr)
114 | {
115 | m_queue.push(_ptr);
116 | m_count.post();
117 | }
118 |
119 | inline void* SpScBlockingUnboundedQueue::peek()
120 | {
121 | return m_queue.peek();
122 | }
123 |
124 | inline void* SpScBlockingUnboundedQueue::pop(int32_t _msecs)
125 | {
126 | if (m_count.wait(_msecs) )
127 | {
128 | return m_queue.pop();
129 | }
130 |
131 | return NULL;
132 | }
133 |
134 | template
135 | inline SpScBlockingUnboundedQueueT::SpScBlockingUnboundedQueueT(AllocatorI* _allocator)
136 | : m_queue(_allocator)
137 | {
138 | }
139 |
140 | template
141 | inline SpScBlockingUnboundedQueueT::~SpScBlockingUnboundedQueueT()
142 | {
143 | }
144 |
145 | template
146 | inline void SpScBlockingUnboundedQueueT::push(Ty* _ptr)
147 | {
148 | m_queue.push(_ptr);
149 | }
150 |
151 | template
152 | inline Ty* SpScBlockingUnboundedQueueT::peek()
153 | {
154 | return (Ty*)m_queue.peek();
155 | }
156 |
157 | template
158 | inline Ty* SpScBlockingUnboundedQueueT::pop(int32_t _msecs)
159 | {
160 | return (Ty*)m_queue.pop(_msecs);
161 | }
162 |
163 | #endif // BX_CONFIG_SUPPORTS_THREADING
164 |
165 | } // namespace bx
166 |
--------------------------------------------------------------------------------
/include/bx/mpscqueue.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_MPSCQUEUE_H_HEADER_GUARD
7 | #define BX_MPSCQUEUE_H_HEADER_GUARD
8 |
9 | #include "allocator.h"
10 | #include "mutex.h"
11 | #include "spscqueue.h"
12 |
13 | namespace bx
14 | {
15 | ///
16 | template
17 | class MpScUnboundedQueueT
18 | {
19 | BX_CLASS(MpScUnboundedQueueT
20 | , NO_DEFAULT_CTOR
21 | , NO_COPY
22 | );
23 |
24 | public:
25 | ///
26 | MpScUnboundedQueueT(AllocatorI* _allocator);
27 |
28 | ///
29 | ~MpScUnboundedQueueT();
30 |
31 | ///
32 | void push(Ty* _ptr); // producer only
33 |
34 | ///
35 | Ty* peek(); // consumer only
36 |
37 | ///
38 | Ty* pop(); // consumer only
39 |
40 | private:
41 | Mutex m_write;
42 | SpScUnboundedQueueT m_queue;
43 | };
44 |
45 | ///
46 | template
47 | class MpScUnboundedBlockingQueue
48 | {
49 | BX_CLASS(MpScUnboundedBlockingQueue
50 | , NO_DEFAULT_CTOR
51 | , NO_COPY
52 | );
53 |
54 | public:
55 | ///
56 | MpScUnboundedBlockingQueue(AllocatorI* _allocator);
57 |
58 | ///
59 | ~MpScUnboundedBlockingQueue();
60 |
61 | ///
62 | void push(Ty* _ptr); // producer only
63 |
64 | ///
65 | Ty* pop(); // consumer only
66 |
67 | private:
68 | MpScUnboundedQueueT m_queue;
69 | Semaphore m_sem;
70 | };
71 |
72 | } // namespace bx
73 |
74 | #include "inline/mpscqueue.inl"
75 |
76 | #endif // BX_MPSCQUEUE_H_HEADER_GUARD
77 |
--------------------------------------------------------------------------------
/include/bx/mutex.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_MUTEX_H_HEADER_GUARD
7 | #define BX_MUTEX_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | class Mutex
15 | {
16 | BX_CLASS(Mutex
17 | , NO_COPY
18 | );
19 |
20 | public:
21 | ///
22 | Mutex();
23 |
24 | ///
25 | ~Mutex();
26 |
27 | ///
28 | void lock();
29 |
30 | ///
31 | void unlock();
32 |
33 | private:
34 | BX_ALIGN_DECL(16, uint8_t) m_internal[64];
35 | };
36 |
37 | ///
38 | class MutexScope
39 | {
40 | BX_CLASS(MutexScope
41 | , NO_DEFAULT_CTOR
42 | , NO_COPY
43 | );
44 |
45 | public:
46 | ///
47 | MutexScope(Mutex& _mutex);
48 |
49 | ///
50 | ~MutexScope();
51 |
52 | private:
53 | Mutex& m_mutex;
54 | };
55 |
56 | } // namespace bx
57 |
58 | #include "inline/mutex.inl"
59 |
60 | #endif // BX_MUTEX_H_HEADER_GUARD
61 |
--------------------------------------------------------------------------------
/include/bx/os.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_OS_H_HEADER_GUARD
7 | #define BX_OS_H_HEADER_GUARD
8 |
9 | #include "filepath.h"
10 |
11 | #if BX_PLATFORM_OSX
12 | # define BX_DL_EXT "dylib"
13 | #elif BX_PLATFORM_WINDOWS
14 | # define BX_DL_EXT "dll"
15 | #else
16 | # define BX_DL_EXT "so"
17 | #endif //
18 |
19 | BX_ERROR_RESULT(kErrorMemoryMapFailed, BX_MAKEFOURCC('b', 'x', '8', '0') );
20 | BX_ERROR_RESULT(kErrorMemoryUnmapFailed, BX_MAKEFOURCC('b', 'x', '8', '1') );
21 |
22 | namespace bx
23 | {
24 | ///
25 | void sleep(uint32_t _ms);
26 |
27 | ///
28 | void yield();
29 |
30 | ///
31 | uint32_t getTid();
32 |
33 | ///
34 | size_t getProcessMemoryUsed();
35 |
36 | ///
37 | void* dlopen(const FilePath& _filePath);
38 |
39 | ///
40 | void dlclose(void* _handle);
41 |
42 | ///
43 | void* dlsym(void* _handle, const StringView& _symbol);
44 |
45 | ///
46 | template
47 | ProtoT dlsym(void* _handle, const StringView& _symbol);
48 |
49 | ///
50 | bool getEnv(char* _out, uint32_t* _inOutSize, const StringView& _name);
51 |
52 | ///
53 | void setEnv(const StringView& _name, const StringView& _value);
54 |
55 | ///
56 | int chdir(const char* _path);
57 |
58 | ///
59 | void* exec(const char* const* _argv);
60 |
61 | ///
62 | [[noreturn]] void exit(int32_t _exitCode);
63 |
64 | ///
65 | void* memoryMap(void* _address, size_t _size, Error* _err);
66 |
67 | ///
68 | void memoryUnmap(void* _address, size_t _size, Error* _err);
69 |
70 | ///
71 | size_t memoryPageSize();
72 |
73 | } // namespace bx
74 |
75 | #include "inline/os.inl"
76 |
77 | #endif // BX_OS_H_HEADER_GUARD
78 |
--------------------------------------------------------------------------------
/include/bx/process.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_PROCESS_H_HEADER_GUARD
7 | #define BX_PROCESS_H_HEADER_GUARD
8 |
9 | #include "readerwriter.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | class ProcessReader
15 | : public ProcessOpenI
16 | , public CloserI
17 | , public ReaderI
18 | {
19 | public:
20 | ///
21 | ProcessReader();
22 |
23 | ///
24 | ~ProcessReader();
25 |
26 | ///
27 | virtual bool open(const FilePath& _filePath, const StringView& _args, Error* _err) override;
28 |
29 | ///
30 | virtual void close() override;
31 |
32 | ///
33 | virtual int32_t read(void* _data, int32_t _size, Error* _err) override;
34 |
35 | ///
36 | int32_t getExitCode() const;
37 |
38 | private:
39 | void* m_file;
40 | int32_t m_exitCode;
41 | };
42 |
43 | ///
44 | class ProcessWriter
45 | : public ProcessOpenI
46 | , public CloserI
47 | , public WriterI
48 | {
49 | public:
50 | ///
51 | ProcessWriter();
52 |
53 | ///
54 | ~ProcessWriter();
55 |
56 | ///
57 | virtual bool open(const FilePath& _filePath, const StringView& _args, Error* _err) override;
58 |
59 | ///
60 | virtual void close() override;
61 |
62 | ///
63 | virtual int32_t write(const void* _data, int32_t _size, Error* _err) override;
64 |
65 | ///
66 | int32_t getExitCode() const;
67 |
68 | private:
69 | void* m_file;
70 | int32_t m_exitCode;
71 | };
72 |
73 | } // namespace bx
74 |
75 | #endif // BX_PROCESS_H_HEADER_GUARD
76 |
--------------------------------------------------------------------------------
/include/bx/ringbuffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_RINGBUFFER_H_HEADER_GUARD
7 | #define BX_RINGBUFFER_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 | #include "cpu.h"
11 | #include "uint32_t.h"
12 |
13 | namespace bx
14 | {
15 | ///
16 | class RingBufferControl
17 | {
18 | BX_CLASS(RingBufferControl
19 | , NO_DEFAULT_CTOR
20 | , NO_COPY
21 | );
22 |
23 | public:
24 | ///
25 | RingBufferControl(uint32_t _size);
26 |
27 | ///
28 | ~RingBufferControl();
29 |
30 | ///
31 | uint32_t available() const;
32 |
33 | ///
34 | uint32_t consume(uint32_t _size); // consumer only
35 |
36 | ///
37 | uint32_t reserve(uint32_t _size, bool _mustSucceed = false); // producer only
38 |
39 | ///
40 | uint32_t commit(uint32_t _size); // producer only
41 |
42 | ///
43 | uint32_t distance(uint32_t _from, uint32_t _to) const; // both
44 |
45 | ///
46 | void reset();
47 |
48 | const uint32_t m_size;
49 | uint32_t m_current;
50 | uint32_t m_write;
51 | uint32_t m_read;
52 | };
53 |
54 | ///
55 | class SpScRingBufferControl
56 | {
57 | BX_CLASS(SpScRingBufferControl
58 | , NO_DEFAULT_CTOR
59 | , NO_COPY
60 | );
61 |
62 | public:
63 | ///
64 | SpScRingBufferControl(uint32_t _size);
65 |
66 | ///
67 | ~SpScRingBufferControl();
68 |
69 | ///
70 | uint32_t available() const;
71 |
72 | ///
73 | uint32_t consume(uint32_t _size); // consumer only
74 |
75 | ///
76 | uint32_t reserve(uint32_t _size); // producer only
77 |
78 | ///
79 | uint32_t commit(uint32_t _size); // producer only
80 |
81 | ///
82 | uint32_t distance(uint32_t _from, uint32_t _to) const; // both
83 |
84 | ///
85 | void reset();
86 |
87 | const uint32_t m_size;
88 | uint32_t m_current;
89 | uint32_t m_write;
90 | uint32_t m_read;
91 | };
92 |
93 | ///
94 | template
95 | class ReadRingBufferT
96 | {
97 | BX_CLASS(ReadRingBufferT
98 | , NO_DEFAULT_CTOR
99 | , NO_COPY
100 | );
101 |
102 | public:
103 | ///
104 | ReadRingBufferT(ControlT& _control, const char* _buffer, uint32_t _size);
105 |
106 | ///
107 | ~ReadRingBufferT();
108 |
109 | ///
110 | void end();
111 |
112 | ///
113 | void read(char* _data, uint32_t _len);
114 |
115 | ///
116 | void skip(uint32_t _len);
117 |
118 | private:
119 | template
120 | friend class WriteRingBufferT;
121 |
122 | ControlT& m_control;
123 | uint32_t m_read;
124 | uint32_t m_end;
125 | const uint32_t m_size;
126 | const char* m_buffer;
127 | };
128 |
129 | ///
130 | typedef ReadRingBufferT ReadRingBuffer;
131 |
132 | ///
133 | typedef ReadRingBufferT SpScReadRingBuffer;
134 |
135 | ///
136 | template
137 | class WriteRingBufferT
138 | {
139 | BX_CLASS(WriteRingBufferT
140 | , NO_DEFAULT_CTOR
141 | , NO_COPY
142 | );
143 |
144 | public:
145 | ///
146 | WriteRingBufferT(ControlT& _control, char* _buffer, uint32_t _size);
147 |
148 | ///
149 | ~WriteRingBufferT();
150 |
151 | ///
152 | void end();
153 |
154 | ///
155 | void write(const char* _data, uint32_t _len);
156 |
157 | ///
158 | void write(ReadRingBufferT& _read, uint32_t _len);
159 |
160 | ///
161 | void skip(uint32_t _len);
162 |
163 | private:
164 | ControlT& m_control;
165 | uint32_t m_write;
166 | uint32_t m_end;
167 | const uint32_t m_size;
168 | char* m_buffer;
169 | };
170 |
171 | ///
172 | typedef WriteRingBufferT WriteRingBuffer;
173 |
174 | ///
175 | typedef WriteRingBufferT SpScWriteRingBuffer;
176 |
177 | } // namespace bx
178 |
179 | #include "inline/ringbuffer.inl"
180 |
181 | #endif // BX_RINGBUFFER_H_HEADER_GUARD
182 |
--------------------------------------------------------------------------------
/include/bx/rng.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_RNG_H_HEADER_GUARD
7 | #define BX_RNG_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 | #include "math.h"
11 | #include "uint32_t.h"
12 |
13 | namespace bx
14 | {
15 | /// George Marsaglia's MWC
16 | class RngMwc
17 | {
18 | public:
19 | ///
20 | RngMwc(uint32_t _z = 12345, uint32_t _w = 65435);
21 |
22 | ///
23 | void reset(uint32_t _z = 12345, uint32_t _w = 65435);
24 |
25 | ///
26 | uint32_t gen();
27 |
28 | private:
29 | uint32_t m_z;
30 | uint32_t m_w;
31 | };
32 |
33 | /// George Marsaglia's SHR3
34 | class RngShr3
35 | {
36 | public:
37 | ///
38 | RngShr3(uint32_t _jsr = 34221);
39 |
40 | ///
41 | void reset(uint32_t _jsr = 34221);
42 |
43 | ///
44 | uint32_t gen();
45 |
46 | private:
47 | uint32_t m_jsr;
48 | };
49 |
50 | /// Returns random number between 0.0f and 1.0f.
51 | template
52 | float frnd(Rng* _rng);
53 |
54 | /// Returns random number between -1.0f and 1.0f.
55 | template
56 | float frndh(Rng* _rng);
57 |
58 | /// Generate random point on unit circle.
59 | template
60 | Vec3 randUnitCircle(Rng* _rng);
61 |
62 | /// Generate random point on unit sphere.
63 | template
64 | Vec3 randUnitSphere(Rng* _rng);
65 |
66 | /// Generate random point on unit hemisphere.
67 | template
68 | Vec3 randUnitHemisphere(Ty* _rng, const Vec3& _normal);
69 |
70 | /// Sampling with Hammersley and Halton Points.
71 | void generateSphereHammersley(void* _data, uint32_t _stride, uint32_t _num, float _scale = 1.0f);
72 |
73 | /// Fisher-Yates shuffle.
74 | template
75 | void shuffle(Rng* _rng, Ty* _array, uint32_t _num);
76 |
77 | } // namespace bx
78 |
79 | #include "inline/rng.inl"
80 |
81 | #endif // BX_RNG_H_HEADER_GUARD
82 |
--------------------------------------------------------------------------------
/include/bx/semaphore.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_SEM_H_HEADER_GUARD
7 | #define BX_SEM_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | class Semaphore
15 | {
16 | BX_CLASS(Semaphore
17 | , NO_COPY
18 | );
19 |
20 | public:
21 | ///
22 | Semaphore();
23 |
24 | ///
25 | ~Semaphore();
26 |
27 | ///
28 | void post(uint32_t _count = 1);
29 |
30 | ///
31 | bool wait(int32_t _msecs = -1);
32 |
33 | private:
34 | BX_ALIGN_DECL(16, uint8_t) m_internal[128];
35 | };
36 |
37 | } // namespace bx
38 |
39 | #endif // BX_SEM_H_HEADER_GUARD
40 |
--------------------------------------------------------------------------------
/include/bx/settings.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_SETTINGS_H_HEADER_GUARD
7 | #define BX_SETTINGS_H_HEADER_GUARD
8 |
9 | #include "allocator.h"
10 | #include "readerwriter.h"
11 | #include "string.h"
12 |
13 | namespace bx
14 | {
15 | ///
16 | class Settings
17 | {
18 | public:
19 | ///
20 | Settings(AllocatorI* _allocator, const void* _data = NULL, uint32_t _len = 0);
21 |
22 | ///
23 | ~Settings();
24 |
25 | ///
26 | void clear();
27 |
28 | ///
29 | void load(const void* _data, uint32_t _len);
30 |
31 | ///
32 | StringView get(const StringView& _name) const;
33 |
34 | ///
35 | void set(const StringView& _name, const StringView& _value = "");
36 |
37 | ///
38 | void remove(const StringView& _name) const;
39 |
40 | ///
41 | int32_t read(ReaderSeekerI* _reader, Error* _err);
42 |
43 | ///
44 | int32_t write(WriterI* _writer, Error* _err) const;
45 |
46 | private:
47 | Settings();
48 |
49 | AllocatorI* m_allocator;
50 | void* m_ini;
51 | };
52 |
53 | ///
54 | int32_t read(ReaderSeekerI* _reader, Settings& _settings, Error* _err);
55 |
56 | ///
57 | int32_t write(WriterI* _writer, const Settings& _settings, Error* _err);
58 |
59 | } // namespace bx
60 |
61 | #endif // BX_SETTINGS_H_HEADER_GUARD
62 |
--------------------------------------------------------------------------------
/include/bx/spscqueue.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_SPSCQUEUE_H_HEADER_GUARD
7 | #define BX_SPSCQUEUE_H_HEADER_GUARD
8 |
9 | #include "allocator.h"
10 | #include "cpu.h"
11 | #include "semaphore.h"
12 |
13 | namespace bx
14 | {
15 | ///
16 | class SpScUnboundedQueue
17 | {
18 | BX_CLASS(SpScUnboundedQueue
19 | , NO_DEFAULT_CTOR
20 | , NO_COPY
21 | );
22 |
23 | public:
24 | ///
25 | SpScUnboundedQueue(AllocatorI* _allocator);
26 |
27 | ///
28 | ~SpScUnboundedQueue();
29 |
30 | ///
31 | void push(void* _ptr);
32 |
33 | ///
34 | void* peek();
35 |
36 | ///
37 | void* pop();
38 |
39 | private:
40 | struct Node
41 | {
42 | ///
43 | Node(void* _ptr);
44 |
45 | void* m_ptr;
46 | Node* m_next;
47 | };
48 |
49 | AllocatorI* m_allocator;
50 | Node* m_first;
51 | Node* m_divider;
52 | Node* m_last;
53 | };
54 |
55 | ///
56 | template
57 | class SpScUnboundedQueueT
58 | {
59 | BX_CLASS(SpScUnboundedQueueT
60 | , NO_DEFAULT_CTOR
61 | , NO_COPY
62 | );
63 |
64 | public:
65 | ///
66 | SpScUnboundedQueueT(AllocatorI* _allocator);
67 |
68 | ///
69 | ~SpScUnboundedQueueT();
70 |
71 | ///
72 | void push(Ty* _ptr);
73 |
74 | ///
75 | Ty* peek();
76 |
77 | ///
78 | Ty* pop();
79 |
80 | private:
81 | SpScUnboundedQueue m_queue;
82 | };
83 |
84 | #if BX_CONFIG_SUPPORTS_THREADING
85 | ///
86 | class SpScBlockingUnboundedQueue
87 | {
88 | BX_CLASS(SpScBlockingUnboundedQueue
89 | , NO_DEFAULT_CTOR
90 | , NO_COPY
91 | );
92 |
93 | public:
94 | ///
95 | SpScBlockingUnboundedQueue(AllocatorI* _allocator);
96 |
97 | ///
98 | ~SpScBlockingUnboundedQueue();
99 |
100 | ///
101 | void push(void* _ptr); // producer only
102 |
103 | ///
104 | void* peek(); // consumer only
105 |
106 | ///
107 | void* pop(int32_t _msecs = -1); // consumer only
108 |
109 | private:
110 | Semaphore m_count;
111 | SpScUnboundedQueue m_queue;
112 | };
113 |
114 | ///
115 | template
116 | class SpScBlockingUnboundedQueueT
117 | {
118 | BX_CLASS(SpScBlockingUnboundedQueueT
119 | , NO_DEFAULT_CTOR
120 | , NO_COPY
121 | );
122 |
123 | public:
124 | ///
125 | SpScBlockingUnboundedQueueT(AllocatorI* _allocator);
126 |
127 | ///
128 | ~SpScBlockingUnboundedQueueT();
129 |
130 | ///
131 | void push(Ty* _ptr); // producer only
132 |
133 | ///
134 | Ty* peek(); // consumer only
135 |
136 | ///
137 | Ty* pop(int32_t _msecs = -1); // consumer only
138 |
139 | private:
140 | SpScBlockingUnboundedQueue m_queue;
141 | };
142 | #endif // BX_CONFIG_SUPPORTS_THREADING
143 |
144 | } // namespace bx
145 |
146 | #include "inline/spscqueue.inl"
147 |
148 | #endif // BX_SPSCQUEUE_H_HEADER_GUARD
149 |
--------------------------------------------------------------------------------
/include/bx/thread.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_THREAD_H_HEADER_GUARD
7 | #define BX_THREAD_H_HEADER_GUARD
8 |
9 | #include "allocator.h"
10 | #include "mpscqueue.h"
11 |
12 | #if BX_CONFIG_SUPPORTS_THREADING
13 |
14 | namespace bx
15 | {
16 | ///
17 | typedef int32_t (*ThreadFn)(class Thread* _self, void* _userData);
18 |
19 | ///
20 | class Thread
21 | {
22 | BX_CLASS(Thread
23 | , NO_COPY
24 | );
25 |
26 | public:
27 | ///
28 | Thread();
29 |
30 | ///
31 | virtual ~Thread();
32 |
33 | /// Create and initialize thread.
34 | ///
35 | /// @param[in] _fn Thread function.
36 | /// @param[in] _userData User data passed to thread function.
37 | /// @param[in] _stackSize Stack size, if zero is passed it will use OS default thread stack
38 | /// size.
39 | /// @param[in] _name Thread name used by debugger.
40 | /// @returns True if thread is created, otherwise returns false.
41 | ///
42 | bool init(ThreadFn _fn, void* _userData = NULL, uint32_t _stackSize = 0, const char* _name = NULL);
43 |
44 | ///
45 | void shutdown();
46 |
47 | ///
48 | bool isRunning() const;
49 |
50 | ///
51 | int32_t getExitCode() const;
52 |
53 | ///
54 | void setThreadName(const char* _name);
55 |
56 | ///
57 | void push(void* _ptr);
58 |
59 | ///
60 | void* pop();
61 |
62 | private:
63 | friend struct ThreadInternal;
64 | int32_t entry();
65 |
66 | BX_ALIGN_DECL(16, uint8_t) m_internal[64];
67 |
68 | ThreadFn m_fn;
69 | void* m_userData;
70 | MpScUnboundedBlockingQueue m_queue;
71 | Semaphore m_sem;
72 | uint32_t m_stackSize;
73 | int32_t m_exitCode;
74 | bool m_running;
75 | char m_name[64];
76 | };
77 |
78 | ///
79 | class TlsData
80 | {
81 | public:
82 | ///
83 | TlsData();
84 |
85 | ///
86 | ~TlsData();
87 |
88 | ///
89 | void* get() const;
90 |
91 | ///
92 | void set(void* _ptr);
93 |
94 | private:
95 | BX_ALIGN_DECL(16, uint8_t) m_internal[64];
96 | };
97 |
98 | } // namespace bx
99 |
100 | #endif
101 |
102 | #endif // BX_THREAD_H_HEADER_GUARD
103 |
--------------------------------------------------------------------------------
/include/bx/timer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_TIMER_H_HEADER_GUARD
7 | #define BX_TIMER_H_HEADER_GUARD
8 |
9 | #include "bx.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | int64_t getHPCounter();
15 |
16 | ///
17 | int64_t getHPFrequency();
18 |
19 | } // namespace bx
20 |
21 | #endif // BX_TIMER_H_HEADER_GUARD
22 |
--------------------------------------------------------------------------------
/include/bx/url.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef BX_URL_H_HEADER_GUARD
7 | #define BX_URL_H_HEADER_GUARD
8 |
9 | #include "string.h"
10 |
11 | namespace bx
12 | {
13 | ///
14 | class UrlView
15 | {
16 | public:
17 | enum Enum
18 | {
19 | Scheme,
20 | UserName,
21 | Password,
22 | Host,
23 | Port,
24 | Path,
25 | Query,
26 | Fragment,
27 |
28 | Count
29 | };
30 |
31 | ///
32 | UrlView();
33 |
34 | ///
35 | void clear();
36 |
37 | ///
38 | bool parse(const StringView& _url);
39 |
40 | ///
41 | const StringView& get(Enum _token) const;
42 |
43 | private:
44 | StringView m_tokens[Count];
45 | };
46 |
47 | ///
48 | void urlEncode(char* _out, uint32_t _max, const StringView& _str);
49 |
50 | } // namespace bx
51 |
52 | #endif // BX_URL_H_HEADER_GUARD
53 |
--------------------------------------------------------------------------------
/include/compat/freebsd/dirent.h:
--------------------------------------------------------------------------------
1 | #include
2 |
--------------------------------------------------------------------------------
/include/compat/freebsd/malloc.h:
--------------------------------------------------------------------------------
1 | #include
2 |
--------------------------------------------------------------------------------
/include/compat/freebsd/signal.h:
--------------------------------------------------------------------------------
1 | #if defined(__GLIBC__)
2 | # include_next
3 | #else
4 | # include
5 | #endif
6 |
--------------------------------------------------------------------------------
/include/compat/ios/malloc.h:
--------------------------------------------------------------------------------
1 | #include
2 |
--------------------------------------------------------------------------------
/include/compat/linux/sal.h:
--------------------------------------------------------------------------------
1 | #include "../mingw/salieri.h"
2 |
--------------------------------------------------------------------------------
/include/compat/mingw/dirent.h:
--------------------------------------------------------------------------------
1 | // BK - MinGW dirent is super broken, using MSVC compatibility one...
2 | #ifndef _DIRENT_H_
3 | # define _DIRENT_H_
4 | # include "../msvc/dirent.h"
5 | #endif // _DIRENT_H_
6 |
--------------------------------------------------------------------------------
/include/compat/mingw/sal.h:
--------------------------------------------------------------------------------
1 | #include "salieri.h"
2 |
--------------------------------------------------------------------------------
/include/compat/mingw/specstrings_strict.h:
--------------------------------------------------------------------------------
1 | #define __reserved
2 |
--------------------------------------------------------------------------------
/include/compat/mingw/specstrings_undef.h:
--------------------------------------------------------------------------------
1 | #undef __reserved
2 |
3 |
--------------------------------------------------------------------------------
/include/compat/osx/malloc.h:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
--------------------------------------------------------------------------------
/include/tinystl/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2012-2018 Matthew Endsley
2 | All rights reserved
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted providing that the following conditions
6 | are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
22 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23 | POSSIBILITY OF SUCH DAMAGE.
24 |
--------------------------------------------------------------------------------
/include/tinystl/allocator.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2012-2018 Matthew Endsley
3 | * All rights reserved
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted providing that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | * POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #ifndef TINYSTL_ALLOCATOR_H
28 | #define TINYSTL_ALLOCATOR_H
29 |
30 | #include
31 |
32 | namespace tinystl {
33 |
34 | struct allocator {
35 | static void* static_allocate(size_t bytes) {
36 | return operator new(bytes);
37 | }
38 |
39 | static void static_deallocate(void* ptr, size_t /*bytes*/) {
40 | operator delete(ptr);
41 | }
42 | };
43 | }
44 |
45 | #ifndef TINYSTL_ALLOCATOR
46 | # define TINYSTL_ALLOCATOR ::tinystl::allocator
47 | #endif
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/include/tinystl/hash.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2012-2018 Matthew Endsley
3 | * All rights reserved
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted providing that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | * POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #ifndef TINYSTL_STRINGHASH_H
28 | #define TINYSTL_STRINGHASH_H
29 |
30 | #include
31 |
32 | namespace tinystl {
33 |
34 | static inline size_t hash_string(const char* str, size_t len) {
35 | // Implementation of sdbm a public domain string hash from Ozan Yigit
36 | // see: http://www.eecs.harvard.edu/margo/papers/usenix91/paper.ps
37 |
38 | size_t hash = 0;
39 | typedef const char* pointer;
40 | for (pointer it = str, end = str + len; it != end; ++it)
41 | hash = *it + (hash << 6) + (hash << 16) - hash;
42 |
43 | return hash;
44 | }
45 |
46 | template
47 | inline size_t hash(const T& value) {
48 | const size_t asint = (size_t)value;
49 | return hash_string((const char*)&asint, sizeof(asint));
50 | }
51 | }
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/include/tinystl/new.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2012-2018 Matthew Endsley
3 | * All rights reserved
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted providing that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | * POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #ifndef TINYSTL_NEW_H
28 | #define TINYSTL_NEW_H
29 |
30 | #include
31 |
32 | namespace tinystl {
33 |
34 | struct placeholder {};
35 | }
36 |
37 | inline void* operator new(size_t, tinystl::placeholder, void* ptr) {
38 | return ptr;
39 | }
40 |
41 | inline void operator delete(void*, tinystl::placeholder, void*) throw() {}
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/include/tinystl/stddef.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2012-2018 Matthew Endsley
3 | * All rights reserved
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted providing that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | * POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #ifndef TINYSTL_STDDEF_H
28 | #define TINYSTL_STDDEF_H
29 |
30 | #if defined(_WIN64)
31 | typedef long long unsigned int size_t;
32 | typedef long long int ptrdiff_t;
33 | #elif defined(_WIN32)
34 | typedef unsigned int size_t;
35 | typedef int ptrdiff_t;
36 | #elif defined (__linux__) && defined(__SIZE_TYPE__) && defined(__PTRDIFF_TYPE__)
37 | typedef __SIZE_TYPE__ size_t;
38 | typedef __PTRDIFF_TYPE__ ptrdiff_t;
39 | #else
40 | # include
41 | #endif
42 |
43 | #endif
44 |
--------------------------------------------------------------------------------
/include/tinystl/string_view.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2012-1017 Matthew Endsley
3 | * All rights reserved
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted providing that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | * POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #ifndef TINYSTL_STRING_VIEW_H
28 | #define TINYSTL_STRING_VIEW_H
29 |
30 | #include
31 |
32 | namespace tinystl {
33 |
34 | class string_view
35 | {
36 | public:
37 | typedef char value_type;
38 | typedef char* pointer;
39 | typedef const char* const_pointer;
40 | typedef char& reference;
41 | typedef const char& const_reference;
42 | typedef const_pointer iterator;
43 | typedef const_pointer const_iterator;
44 | typedef size_t size_type;
45 | typedef ptrdiff_t difference_type;
46 |
47 | static constexpr size_type npos = size_type(-1);
48 |
49 | constexpr string_view();
50 | constexpr string_view(const char* s, size_type count);
51 | constexpr string_view(const char* s);
52 | constexpr string_view(const string_view&) = default;
53 | string_view& operator=(const string_view&) = default;
54 |
55 | constexpr const char* data() const;
56 | constexpr char operator[](size_type pos) const;
57 | constexpr size_type size() const;
58 | constexpr bool empty() const;
59 | constexpr iterator begin() const;
60 | constexpr const_iterator cbegin() const;
61 | constexpr iterator end() const;
62 | constexpr const_iterator cend() const;
63 | constexpr string_view substr(size_type pos = 0, size_type count = npos) const;
64 | constexpr void swap(string_view& v);
65 |
66 | private:
67 | string_view(decltype(nullptr)) = delete;
68 |
69 | static constexpr size_type strlen(const char*);
70 |
71 | const char* m_str;
72 | size_type m_size;
73 | };
74 |
75 | constexpr string_view::string_view()
76 | : m_str(nullptr)
77 | , m_size(0)
78 | {
79 | }
80 |
81 | constexpr string_view::string_view(const char* s, size_type count)
82 | : m_str(s)
83 | , m_size(count)
84 | {
85 | }
86 |
87 | constexpr string_view::string_view(const char* s)
88 | : m_str(s)
89 | , m_size(strlen(s))
90 | {
91 | }
92 |
93 | constexpr const char* string_view::data() const {
94 | return m_str;
95 | }
96 |
97 | constexpr char string_view::operator[](size_type pos) const {
98 | return m_str[pos];
99 | }
100 |
101 | constexpr string_view::size_type string_view::size() const {
102 | return m_size;
103 | }
104 |
105 | constexpr bool string_view::empty() const {
106 | return 0 == m_size;
107 | }
108 |
109 | constexpr string_view::iterator string_view::begin() const {
110 | return m_str;
111 | }
112 |
113 | constexpr string_view::const_iterator string_view::cbegin() const {
114 | return m_str;
115 | }
116 |
117 | constexpr string_view::iterator string_view::end() const {
118 | return m_str + m_size;
119 | }
120 |
121 | constexpr string_view::const_iterator string_view::cend() const {
122 | return m_str + m_size;
123 | }
124 |
125 | constexpr string_view string_view::substr(size_type pos, size_type count) const {
126 | return string_view(m_str + pos, npos == count ? m_size - pos : count);
127 | }
128 |
129 | constexpr void string_view::swap(string_view& v) {
130 | const char* strtmp = m_str;
131 | size_type sizetmp = m_size;
132 | m_str = v.m_str;
133 | m_size = v.m_size;
134 | v.m_str = strtmp;
135 | v.m_size = sizetmp;
136 | }
137 |
138 | constexpr string_view::size_type string_view::strlen(const char* s) {
139 | for (size_t len = 0; ; ++len) {
140 | if (0 == s[len]) {
141 | return len;
142 | }
143 | }
144 | }
145 | }
146 |
147 | #endif // TINYSTL_STRING_VIEW_H
148 |
--------------------------------------------------------------------------------
/include/tinystl/traits.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright 2012-2018 Matthew Endsley
3 | * All rights reserved
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted providing that the following conditions
7 | * are met:
8 | * 1. Redistributions of source code must retain the above copyright
9 | * notice, this list of conditions and the following disclaimer.
10 | * 2. Redistributions in binary form must reproduce the above copyright
11 | * notice, this list of conditions and the following disclaimer in the
12 | * documentation and/or other materials provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 | * POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #ifndef TINYSTL_TRAITS_H
28 | #define TINYSTL_TRAITS_H
29 |
30 | #include
31 |
32 | #if defined(__GNUC__)
33 | # define TINYSTL_TRY_POD_OPTIMIZATION(t) __is_pod(t)
34 | #elif defined(_MSC_VER)
35 | # define TINYSTL_TRY_POD_OPTIMIZATION(t) (!__is_class(t) || __is_pod(t))
36 | #else
37 | # define TINYSTL_TRY_POD_OPTIMIZATION(t) false
38 | #endif
39 |
40 | namespace tinystl {
41 | template struct pod_traits {};
42 |
43 | template struct swap_holder;
44 |
45 | template
46 | static inline void move_impl(T& a, T& b, ...) {
47 | a = b;
48 | }
49 |
50 | template
51 | static inline void move_impl(T& a, T& b, T*, swap_holder* = 0) {
52 | a.swap(b);
53 | }
54 |
55 | template
56 | static inline void move(T& a, T&b) {
57 | move_impl(a, b, (T*)0);
58 | }
59 |
60 | template
61 | static inline void move_construct_impl(T* a, T& b, ...) {
62 | new(placeholder(), a) T(b);
63 | }
64 |
65 | template
66 | static inline void move_construct_impl(T* a, T& b, void*, swap_holder* = 0) {
67 | // If your type T does not have a default constructor, simply insert:
68 | // struct tinystl_nomove_construct;
69 | // in the class definition
70 | new(placeholder(), a) T;
71 | a->swap(b);
72 | }
73 |
74 | template
75 | static inline void move_construct_impl(T* a, T& b, T*, typename T::tinystl_nomove_construct* = 0) {
76 | new(placeholder(), a) T(b);
77 | }
78 |
79 | template
80 | static inline void move_construct(T* a, T& b) {
81 | move_construct_impl(a, b, (T*)0);
82 | }
83 |
84 | template
85 | struct remove_reference {
86 | typedef T type;
87 | };
88 |
89 | template
90 | struct remove_reference {
91 | typedef T type;
92 | };
93 |
94 | template
95 | struct remove_reference {
96 | typedef T type;
97 | };
98 |
99 | template
100 | struct remove_const {
101 | typedef T type;
102 | };
103 |
104 | template
105 | struct remove_const {
106 | typedef T type;
107 | };
108 |
109 | template
110 | struct remove_const {
111 | typedef T& type;
112 | };
113 |
114 | template
115 | struct remove_const {
116 | typedef T&& type;
117 | };
118 |
119 | template
120 | struct remove_const_reference {
121 | typedef typename remove_reference::type>::type type;
122 | };
123 | }
124 |
125 | #endif
126 |
--------------------------------------------------------------------------------
/scripts/bin2c.lua:
--------------------------------------------------------------------------------
1 | --
2 | -- Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | -- License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | --
5 |
6 | project "bin2c"
7 | kind "ConsoleApp"
8 |
9 | files {
10 | "../tools/bin2c/**.cpp",
11 | "../tools/bin2c/**.h",
12 | }
13 |
14 | using_bx()
15 |
16 | configuration { "mingw-*" }
17 | targetextension ".exe"
18 |
19 | configuration { "linux-*" }
20 | links {
21 | "pthread",
22 | }
23 | configuration { "osx-*" }
24 | linkoptions {
25 | "-framework Foundation"
26 | }
27 |
28 | configuration { "vs20* or mingw*" }
29 | links {
30 | "psapi",
31 | }
32 |
33 | configuration {}
34 |
35 | strip()
36 |
--------------------------------------------------------------------------------
/scripts/bx.lua:
--------------------------------------------------------------------------------
1 | --
2 | -- Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | -- License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | --
5 |
6 | local function userdefines()
7 | local defines = {}
8 | local BX_CONFIG = os.getenv("BX_CONFIG")
9 | if BX_CONFIG then
10 | for def in BX_CONFIG:gmatch "[^%s:]+" do
11 | table.insert(defines, "BX_CONFIG_" .. def)
12 | end
13 | end
14 |
15 | return defines
16 | end
17 |
18 | function using_bx()
19 | includedirs {
20 | path.join(BX_DIR, "include"),
21 | }
22 |
23 | links {
24 | "bx",
25 | }
26 |
27 | configuration { "Debug" }
28 | defines {
29 | "BX_CONFIG_DEBUG=1",
30 | }
31 |
32 | configuration { "Release" }
33 | defines {
34 | "BX_CONFIG_DEBUG=0",
35 | }
36 |
37 | configuration {}
38 | end
39 |
40 | project "bx"
41 | kind "StaticLib"
42 |
43 | includedirs {
44 | path.join(BX_DIR, "include"),
45 | path.join(BX_DIR, "3rdparty"),
46 | }
47 |
48 | files {
49 | path.join(BX_DIR, "include/**.h"),
50 | path.join(BX_DIR, "include/**.inl"),
51 | path.join(BX_DIR, "src/**.cpp"),
52 | path.join(BX_DIR, "scripts/**.natvis"),
53 | }
54 |
55 | defines (userdefines())
56 |
57 | configuration { "linux-*" }
58 | buildoptions {
59 | "-fPIC",
60 | }
61 |
62 | configuration {}
63 |
64 | if _OPTIONS["with-amalgamated"] then
65 | excludes {
66 | path.join(BX_DIR, "src/allocator.cpp"),
67 | path.join(BX_DIR, "src/bounds.cpp"),
68 | path.join(BX_DIR, "src/bx.cpp"),
69 | path.join(BX_DIR, "src/commandline.cpp"),
70 | path.join(BX_DIR, "src/crtnone.cpp"),
71 | path.join(BX_DIR, "src/debug.cpp"),
72 | path.join(BX_DIR, "src/dtoa.cpp"),
73 | path.join(BX_DIR, "src/easing.cpp"),
74 | path.join(BX_DIR, "src/file.cpp"),
75 | path.join(BX_DIR, "src/filepath.cpp"),
76 | path.join(BX_DIR, "src/hash.cpp"),
77 | path.join(BX_DIR, "src/math.cpp"),
78 | path.join(BX_DIR, "src/mutex.cpp"),
79 | path.join(BX_DIR, "src/os.cpp"),
80 | path.join(BX_DIR, "src/process.cpp"),
81 | path.join(BX_DIR, "src/semaphore.cpp"),
82 | path.join(BX_DIR, "src/settings.cpp"),
83 | path.join(BX_DIR, "src/sort.cpp"),
84 | path.join(BX_DIR, "src/string.cpp"),
85 | path.join(BX_DIR, "src/thread.cpp"),
86 | path.join(BX_DIR, "src/timer.cpp"),
87 | path.join(BX_DIR, "src/url.cpp"),
88 | }
89 | else
90 | excludes {
91 | path.join(BX_DIR, "src/amalgamated.**"),
92 | }
93 | end
94 |
95 | configuration { "Debug" }
96 | defines {
97 | "BX_CONFIG_DEBUG=1",
98 | }
99 |
100 | configuration { "Release" }
101 | defines {
102 | "BX_CONFIG_DEBUG=0",
103 | }
104 |
105 | configuration {}
106 |
--------------------------------------------------------------------------------
/scripts/bx.natvis:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {m_ptr,[m_len]s8}
5 | m_ptr,[m_len]s8
6 |
7 | m_ptr,[m_len]
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/scripts/genie.lua:
--------------------------------------------------------------------------------
1 | --
2 | -- Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | -- License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | --
5 |
6 | newoption {
7 | trigger = "with-amalgamated",
8 | description = "Enable amalgamated build.",
9 | }
10 |
11 | newoption {
12 | trigger = "with-crtnone",
13 | description = "Enable build without CRT.",
14 | }
15 |
16 | solution "bx"
17 | configurations {
18 | "Debug",
19 | "Release",
20 | }
21 |
22 | platforms {
23 | "x32",
24 | "x64",
25 | "Native", -- for targets where bitness is not specified
26 | }
27 |
28 | language "C++"
29 |
30 | BX_DIR = path.getabsolute("..")
31 | BX_BUILD_DIR = path.join(BX_DIR, ".build")
32 | BX_THIRD_PARTY_DIR = path.join(BX_DIR, "3rdparty")
33 |
34 | dofile "toolchain.lua"
35 | toolchain(BX_BUILD_DIR, BX_THIRD_PARTY_DIR)
36 |
37 | function copyLib()
38 | end
39 |
40 | dofile "bx.lua"
41 | dofile "bin2c.lua"
42 |
43 | project "bx.test"
44 | kind "ConsoleApp"
45 |
46 | debugdir (path.join(BX_DIR, "tests"))
47 |
48 | flags {
49 | -- "FatalWarnings",
50 | }
51 |
52 | removeflags {
53 | "NoExceptions",
54 | }
55 |
56 | includedirs {
57 | BX_THIRD_PARTY_DIR,
58 | }
59 |
60 | files {
61 | path.join(BX_DIR, "3rdparty/catch/catch_amalgamated.cpp"),
62 | path.join(BX_DIR, "tests/*_test.cpp"),
63 | path.join(BX_DIR, "tests/*.h"),
64 | path.join(BX_DIR, "tests/dbg.*"),
65 | }
66 |
67 | using_bx()
68 |
69 | defines {
70 | "CATCH_AMALGAMATED_CUSTOM_MAIN",
71 | }
72 |
73 | configuration { "vs* or mingw*" }
74 | links {
75 | "psapi",
76 | }
77 |
78 | configuration { "android*" }
79 | targetextension ".so"
80 | linkoptions {
81 | "-shared",
82 | }
83 |
84 | configuration { "linux-*" }
85 | links {
86 | "pthread",
87 | }
88 |
89 | configuration { "ios*" }
90 | linkoptions {
91 | "-framework CoreFoundation",
92 | "-framework Foundation",
93 | }
94 |
95 | configuration { "osx*" }
96 | links {
97 | "Cocoa.framework",
98 | }
99 |
100 | configuration { "wasm" }
101 | buildoptions {
102 | "-fwasm-exceptions",
103 | }
104 | linkoptions {
105 | "-fwasm-exceptions",
106 | "-s STACK_SIZE=262144",
107 | }
108 |
109 | configuration {}
110 |
111 | strip()
112 |
113 | project "bx.bench"
114 | kind "ConsoleApp"
115 |
116 | debugdir (path.join(BX_DIR, "tests"))
117 |
118 | includedirs {
119 | path.join(BX_DIR, "include"),
120 | BX_THIRD_PARTY_DIR,
121 | }
122 |
123 | files {
124 | path.join(BX_DIR, "tests/*_bench.cpp"),
125 | path.join(BX_DIR, "tests/*_bench.h"),
126 | path.join(BX_DIR, "tests/dbg.*"),
127 | }
128 |
129 | using_bx()
130 |
131 | configuration { "vs* or mingw*" }
132 | links {
133 | "psapi",
134 | }
135 |
136 | configuration { "android*" }
137 | targetextension ".so"
138 | linkoptions {
139 | "-shared",
140 | }
141 |
142 | configuration { "linux-*" }
143 | links {
144 | "pthread",
145 | }
146 |
147 | configuration { "osx*" }
148 | links {
149 | "Cocoa.framework",
150 | }
151 |
152 | configuration {}
153 |
154 | strip()
155 |
--------------------------------------------------------------------------------
/scripts/tinystl.natvis:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ size={last - first} }}
5 |
6 | - last - first
7 | - capacity - first
8 |
9 | last - first
10 | first
11 |
12 |
13 |
14 |
15 |
16 | {{ size={m_buffer.last - m_buffer.first} }}
17 |
18 | m_buffer
19 |
20 |
21 |
22 |
23 | {{ size={m_size} }}
24 |
25 | - m_size
26 | - m_buckets.last - m_buckets.first
27 |
28 | *m_buckets.first
29 | next
30 | first
31 |
32 |
33 |
34 |
35 |
36 | {{ size={m_size} }}
37 |
38 | - m_size
39 | - m_buckets.last - m_buckets.first
40 |
41 | *m_buckets.first
42 | next
43 | second
44 |
45 |
46 |
47 |
48 |
49 | {m_first,[m_last - m_first]na}
50 | m_first,[m_last - m_first]na
51 |
52 | - m_last - m_first
53 | - m_capacity - m_first
54 |
55 | m_last - m_first
56 | m_first
57 |
58 |
59 |
60 |
61 |
62 | {m_str,[m_size]na}
63 | m_str,[m_size]na
64 |
65 | - m_size
66 |
67 | m_size
68 | m_str
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/scripts/update_tinystl.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -eux
2 |
3 | if [ $# != 1 ]; then
4 | echo "Usage: $0 "
5 | exit 1
6 | fi
7 |
8 | SRC_DIR=$1
9 | DST_DIR="include/tinystl"
10 |
11 | pushd $(dirname $0)/..
12 |
13 | cp $SRC_DIR/include/TINYSTL/*.h $DST_DIR/
14 | find $DST_DIR -iname "*.h" -exec sed --in-place 's/
7 |
8 | #include
9 |
10 | #ifndef BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT
11 | # define BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT 8
12 | #endif // BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT
13 |
14 | namespace bx
15 | {
16 | DefaultAllocator::DefaultAllocator()
17 | {
18 | }
19 |
20 | DefaultAllocator::~DefaultAllocator()
21 | {
22 | }
23 |
24 | void* DefaultAllocator::realloc(void* _ptr, size_t _size, size_t _align, const char* _filePath, uint32_t _line)
25 | {
26 | if (0 == _size)
27 | {
28 | if (NULL != _ptr)
29 | {
30 | if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align)
31 | {
32 | ::free(_ptr);
33 | return NULL;
34 | }
35 |
36 | # if BX_COMPILER_MSVC
37 | BX_UNUSED(_filePath, _line);
38 | _aligned_free(_ptr);
39 | # else
40 | alignedFree(this, _ptr, _align, Location(_filePath, _line) );
41 | # endif // BX_
42 | }
43 |
44 | return NULL;
45 | }
46 | else if (NULL == _ptr)
47 | {
48 | if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align)
49 | {
50 | return ::malloc(_size);
51 | }
52 |
53 | # if BX_COMPILER_MSVC
54 | BX_UNUSED(_filePath, _line);
55 | return _aligned_malloc(_size, _align);
56 | # else
57 | return alignedAlloc(this, _size, _align, Location(_filePath, _line) );
58 | # endif // BX_
59 | }
60 |
61 | if (BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT >= _align)
62 | {
63 | return ::realloc(_ptr, _size);
64 | }
65 |
66 | # if BX_COMPILER_MSVC
67 | BX_UNUSED(_filePath, _line);
68 | return _aligned_realloc(_ptr, _size, _align);
69 | # else
70 | return alignedRealloc(this, _ptr, _size, _align, Location(_filePath, _line) );
71 | # endif // BX_
72 | }
73 |
74 | } // namespace bx
75 |
--------------------------------------------------------------------------------
/src/amalgamated.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "allocator.cpp"
7 | #include "bounds.cpp"
8 | #include "bx.cpp"
9 | #include "commandline.cpp"
10 | #include "crtnone.cpp"
11 | #include "debug.cpp"
12 | #include "dtoa.cpp"
13 | #include "easing.cpp"
14 | #include "file.cpp"
15 | #include "filepath.cpp"
16 | #include "hash.cpp"
17 | #include "math.cpp"
18 | #include "mutex.cpp"
19 | #include "os.cpp"
20 | #include "process.cpp"
21 | #include "semaphore.cpp"
22 | #include "settings.cpp"
23 | #include "sort.cpp"
24 | #include "string.cpp"
25 | #include "thread.cpp"
26 | #include "timer.cpp"
27 | #include "url.cpp"
28 |
--------------------------------------------------------------------------------
/src/easing.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include
7 |
8 | namespace bx
9 | {
10 | static const EaseFn s_easeFunc[] =
11 | {
12 | easeLinear,
13 | easeStep,
14 | easeSmoothStep,
15 | easeInQuad,
16 | easeOutQuad,
17 | easeInOutQuad,
18 | easeOutInQuad,
19 | easeInCubic,
20 | easeOutCubic,
21 | easeInOutCubic,
22 | easeOutInCubic,
23 | easeInQuart,
24 | easeOutQuart,
25 | easeInOutQuart,
26 | easeOutInQuart,
27 | easeInQuint,
28 | easeOutQuint,
29 | easeInOutQuint,
30 | easeOutInQuint,
31 | easeInSine,
32 | easeOutSine,
33 | easeInOutSine,
34 | easeOutInSine,
35 | easeInExpo,
36 | easeOutExpo,
37 | easeInOutExpo,
38 | easeOutInExpo,
39 | easeInCirc,
40 | easeOutCirc,
41 | easeInOutCirc,
42 | easeOutInCirc,
43 | easeInElastic,
44 | easeOutElastic,
45 | easeInOutElastic,
46 | easeOutInElastic,
47 | easeInBack,
48 | easeOutBack,
49 | easeInOutBack,
50 | easeOutInBack,
51 | easeInBounce,
52 | easeOutBounce,
53 | easeInOutBounce,
54 | easeOutInBounce,
55 | };
56 | static_assert(BX_COUNTOF(s_easeFunc) == Easing::Count);
57 |
58 | EaseFn getEaseFunc(Easing::Enum _enum)
59 | {
60 | return s_easeFunc[_enum];
61 | }
62 |
63 | } // namespace bx
64 |
--------------------------------------------------------------------------------
/src/mutex.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include
7 |
8 | #if BX_CONFIG_SUPPORTS_THREADING
9 |
10 | #if BX_CRT_NONE
11 | # include
12 | # include
13 | #elif BX_PLATFORM_ANDROID \
14 | || BX_PLATFORM_LINUX \
15 | || BX_PLATFORM_IOS \
16 | || BX_PLATFORM_OSX \
17 | || BX_PLATFORM_PS4 \
18 | || BX_PLATFORM_RPI \
19 | || BX_PLATFORM_NX \
20 | || BX_PLATFORM_VISIONOS
21 | # include
22 | #elif BX_PLATFORM_WINDOWS \
23 | || BX_PLATFORM_WINRT \
24 | || BX_PLATFORM_XBOXONE
25 | # ifndef WIN32_LEAN_AND_MEAN
26 | # define WIN32_LEAN_AND_MEAN
27 | # endif // WIN32_LEAN_AND_MEAN
28 | # include
29 | # include
30 | #endif // BX_PLATFORM_
31 |
32 | namespace bx
33 | {
34 | #if BX_CRT_NONE
35 | struct State
36 | {
37 | enum Enum
38 | {
39 | Unlocked,
40 | Locked,
41 | Contested,
42 | };
43 | };
44 |
45 | Mutex::Mutex()
46 | {
47 | static_assert(sizeof(int32_t) <= sizeof(m_internal) );
48 |
49 | uint32_t* futex = (uint32_t*)m_internal;
50 | *futex = State::Unlocked;
51 | }
52 |
53 | Mutex::~Mutex()
54 | {
55 | }
56 |
57 | void Mutex::lock()
58 | {
59 | uint32_t* futex = (uint32_t*)m_internal;
60 |
61 | if (State::Unlocked == atomicCompareAndSwap(futex, State::Unlocked, State::Locked) )
62 | {
63 | return;
64 | }
65 |
66 | while (State::Unlocked != atomicCompareAndSwap(futex, State::Locked, State::Contested) )
67 | {
68 | crt0::futexWait(futex, State::Contested);
69 | }
70 | }
71 |
72 | void Mutex::unlock()
73 | {
74 | uint32_t* futex = (uint32_t*)m_internal;
75 |
76 | if (State::Contested == atomicCompareAndSwap(futex, State::Locked, State::Unlocked) )
77 | {
78 | crt0::futexWake(futex, State::Locked);
79 | }
80 | }
81 |
82 | #else
83 |
84 | # if BX_PLATFORM_WINDOWS \
85 | || BX_PLATFORM_XBOXONE \
86 | || BX_PLATFORM_WINRT
87 | typedef CRITICAL_SECTION pthread_mutex_t;
88 | typedef unsigned pthread_mutexattr_t;
89 |
90 | inline int pthread_mutex_lock(pthread_mutex_t* _mutex)
91 | {
92 | EnterCriticalSection(_mutex);
93 | return 0;
94 | }
95 |
96 | inline int pthread_mutex_unlock(pthread_mutex_t* _mutex)
97 | {
98 | LeaveCriticalSection(_mutex);
99 | return 0;
100 | }
101 |
102 | inline int pthread_mutex_trylock(pthread_mutex_t* _mutex)
103 | {
104 | return TryEnterCriticalSection(_mutex) ? 0 : EBUSY;
105 | }
106 |
107 | inline int pthread_mutex_init(pthread_mutex_t* _mutex, pthread_mutexattr_t* /*_attr*/)
108 | {
109 | # if BX_PLATFORM_WINRT
110 | InitializeCriticalSectionEx(_mutex, 4000, 0); // docs recommend 4000 spincount as sane default
111 | # else
112 | InitializeCriticalSection(_mutex);
113 | # endif // BX_PLATFORM_
114 | return 0;
115 | }
116 |
117 | inline int pthread_mutex_destroy(pthread_mutex_t* _mutex)
118 | {
119 | DeleteCriticalSection(_mutex);
120 | return 0;
121 | }
122 | # endif // BX_PLATFORM_
123 |
124 | Mutex::Mutex()
125 | {
126 | static_assert(sizeof(pthread_mutex_t) <= sizeof(m_internal) );
127 |
128 | pthread_mutexattr_t attr;
129 |
130 | # if BX_PLATFORM_WINDOWS \
131 | || BX_PLATFORM_XBOXONE \
132 | || BX_PLATFORM_WINRT
133 | # else
134 | pthread_mutexattr_init(&attr);
135 | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
136 | # endif // BX_PLATFORM_
137 |
138 | pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
139 | pthread_mutex_init(handle, &attr);
140 | }
141 |
142 | Mutex::~Mutex()
143 | {
144 | pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
145 | pthread_mutex_destroy(handle);
146 | }
147 |
148 | void Mutex::lock()
149 | {
150 | pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
151 | pthread_mutex_lock(handle);
152 | }
153 |
154 | void Mutex::unlock()
155 | {
156 | pthread_mutex_t* handle = (pthread_mutex_t*)m_internal;
157 | pthread_mutex_unlock(handle);
158 | }
159 | #endif // BX_CRT_NONE
160 |
161 | } // namespace bx
162 |
163 | #else
164 |
165 | namespace bx
166 | {
167 | Mutex::Mutex()
168 | {
169 | }
170 |
171 | Mutex::~Mutex()
172 | {
173 | }
174 |
175 | void Mutex::lock()
176 | {
177 | }
178 |
179 | void Mutex::unlock()
180 | {
181 | }
182 |
183 | } // namespace bx
184 |
185 | #endif // BX_CONFIG_SUPPORTS_THREADING
186 |
--------------------------------------------------------------------------------
/src/process.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include
7 |
8 | #include
9 |
10 | #ifndef BX_CONFIG_CRT_PROCESS
11 | # define BX_CONFIG_CRT_PROCESS !(0 \
12 | || BX_CRT_NONE \
13 | || BX_PLATFORM_EMSCRIPTEN \
14 | || BX_PLATFORM_PS4 \
15 | || BX_PLATFORM_WINRT \
16 | || BX_PLATFORM_XBOXONE \
17 | )
18 | #endif // BX_CONFIG_CRT_PROCESS
19 |
20 | namespace bx
21 | {
22 | #if BX_CONFIG_CRT_PROCESS
23 |
24 | #if BX_CRT_MSVC
25 | # define popen _popen
26 | # define pclose _pclose
27 | #endif // BX_CRT_MSVC
28 |
29 | ProcessReader::ProcessReader()
30 | : m_file(NULL)
31 | {
32 | }
33 |
34 | ProcessReader::~ProcessReader()
35 | {
36 | BX_ASSERT(NULL == m_file, "Process not closed!");
37 | }
38 |
39 | bool ProcessReader::open(const FilePath& _filePath, const StringView& _args, Error* _err)
40 | {
41 | BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
42 |
43 | if (NULL != m_file)
44 | {
45 | BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "ProcessReader: File is already open.");
46 | return false;
47 | }
48 |
49 | char tmp[kMaxFilePath*2] = "\"";
50 | strCat(tmp, BX_COUNTOF(tmp), _filePath);
51 | strCat(tmp, BX_COUNTOF(tmp), "\" ");
52 | strCat(tmp, BX_COUNTOF(tmp), _args);
53 |
54 | m_file = popen(tmp, "r");
55 | if (NULL == m_file)
56 | {
57 | BX_ERROR_SET(_err, kErrorReaderWriterOpen, "ProcessReader: Failed to open process.");
58 | return false;
59 | }
60 |
61 | return true;
62 | }
63 |
64 | void ProcessReader::close()
65 | {
66 | BX_ASSERT(NULL != m_file, "Process not open!");
67 | FILE* file = (FILE*)m_file;
68 | m_exitCode = pclose(file);
69 | m_file = NULL;
70 | }
71 |
72 | int32_t ProcessReader::read(void* _data, int32_t _size, Error* _err)
73 | {
74 | BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err);
75 |
76 | FILE* file = (FILE*)m_file;
77 | int32_t size = (int32_t)fread(_data, 1, _size, file);
78 | if (size != _size)
79 | {
80 | if (0 != feof(file) )
81 | {
82 | BX_ERROR_SET(_err, kErrorReaderWriterEof, "ProcessReader: EOF.");
83 | }
84 | else if (0 != ferror(file) )
85 | {
86 | BX_ERROR_SET(_err, kErrorReaderWriterRead, "ProcessReader: read error.");
87 | }
88 |
89 | return size >= 0 ? size : 0;
90 | }
91 |
92 | return size;
93 | }
94 |
95 | int32_t ProcessReader::getExitCode() const
96 | {
97 | return m_exitCode;
98 | }
99 |
100 | ProcessWriter::ProcessWriter()
101 | : m_file(NULL)
102 | {
103 | }
104 |
105 | ProcessWriter::~ProcessWriter()
106 | {
107 | BX_ASSERT(NULL == m_file, "Process not closed!");
108 | }
109 |
110 | bool ProcessWriter::open(const FilePath& _filePath, const StringView& _args, Error* _err)
111 | {
112 | BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors.");
113 |
114 | if (NULL != m_file)
115 | {
116 | BX_ERROR_SET(_err, kErrorReaderWriterAlreadyOpen, "ProcessWriter: File is already open.");
117 | return false;
118 | }
119 |
120 | char tmp[kMaxFilePath*2] = "\"";
121 | strCat(tmp, BX_COUNTOF(tmp), _filePath);
122 | strCat(tmp, BX_COUNTOF(tmp), "\" ");
123 | strCat(tmp, BX_COUNTOF(tmp), _args);
124 |
125 | m_file = popen(tmp, "w");
126 | if (NULL == m_file)
127 | {
128 | BX_ERROR_SET(_err, kErrorReaderWriterOpen, "ProcessWriter: Failed to open process.");
129 | return false;
130 | }
131 |
132 | return true;
133 | }
134 |
135 | void ProcessWriter::close()
136 | {
137 | BX_ASSERT(NULL != m_file, "Process not open!");
138 | FILE* file = (FILE*)m_file;
139 | m_exitCode = pclose(file);
140 | m_file = NULL;
141 | }
142 |
143 | int32_t ProcessWriter::write(const void* _data, int32_t _size, Error* _err)
144 | {
145 | BX_ASSERT(NULL != _err, "Reader/Writer interface calling functions must handle errors."); BX_UNUSED(_err);
146 |
147 | FILE* file = (FILE*)m_file;
148 | int32_t size = (int32_t)fwrite(_data, 1, _size, file);
149 | if (size != _size)
150 | {
151 | if (0 != ferror(file) )
152 | {
153 | BX_ERROR_SET(_err, kErrorReaderWriterWrite, "ProcessWriter: write error.");
154 | }
155 |
156 | return size >= 0 ? size : 0;
157 | }
158 |
159 | return size;
160 | }
161 |
162 | int32_t ProcessWriter::getExitCode() const
163 | {
164 | return m_exitCode;
165 | }
166 | #endif // BX_CONFIG_CRT_PROCESS
167 |
168 | } // namespace bx
169 |
--------------------------------------------------------------------------------
/src/sort.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include
7 |
8 | namespace bx
9 | {
10 | static void quickSortR(void* _pivot, void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
11 | {
12 | if (2 > _num)
13 | {
14 | return;
15 | }
16 |
17 | memCopy(_pivot, _data, _stride);
18 |
19 | uint8_t* data = (uint8_t*)_data;
20 |
21 | uint32_t ll = 0;
22 | uint32_t gg = 1;
23 |
24 | for (uint32_t ii = 1; ii < _num;)
25 | {
26 | int32_t result = _fn(&data[ii*_stride], _pivot);
27 | if (0 > result)
28 | {
29 | swap(&data[ll*_stride], &data[ii*_stride], _stride);
30 | ++ll;
31 | }
32 | else if (0 == result)
33 | {
34 | swap(&data[gg*_stride], &data[ii*_stride], _stride);
35 | ++gg;
36 | ++ii;
37 | }
38 | else
39 | {
40 | ++ii;
41 | }
42 | }
43 |
44 | quickSortR(_pivot, &data[0 ], ll, _stride, _fn);
45 | quickSortR(_pivot, &data[gg*_stride], _num-gg, _stride, _fn);
46 | }
47 |
48 | void quickSort(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
49 | {
50 | uint8_t* pivot = (uint8_t*)BX_STACK_ALLOC(_stride);
51 | quickSortR(pivot, _data, _num, _stride, _fn);
52 | }
53 |
54 | bool isSorted(const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
55 | {
56 | const uint8_t* data = (uint8_t*)_data;
57 |
58 | for (uint32_t ii = 1; ii < _num; ++ii)
59 | {
60 | int32_t result = _fn(&data[(ii-1)*_stride], &data[ii*_stride]);
61 |
62 | if (0 < result)
63 | {
64 | return false;
65 | }
66 | }
67 |
68 | return true;
69 | }
70 |
71 | uint32_t unique(void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
72 | {
73 | if (0 == _num)
74 | {
75 | return 0;
76 | }
77 |
78 | uint8_t* data = (uint8_t*)_data;
79 |
80 | uint32_t last = 0;
81 |
82 | for (uint32_t ii = 1; ii < _num; ++ii)
83 | {
84 | int32_t result = _fn(&data[last*_stride], &data[ii*_stride]);
85 | BX_ASSERT(0 >= result, "Performing unique on non-sorted array (ii %d, last %d)!", ii, last);
86 |
87 | if (0 > result)
88 | {
89 | last++;
90 | swap(&data[last*_stride], &data[ii*_stride], _stride);
91 | }
92 | }
93 |
94 | return last+1;
95 | }
96 |
97 | uint32_t lowerBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
98 | {
99 | uint32_t offset = 0;
100 | const uint8_t* data = (uint8_t*)_data;
101 |
102 | for (uint32_t ll = _num; offset < ll;)
103 | {
104 | const uint32_t idx = (offset + ll) / 2;
105 |
106 | int32_t result = _fn(_key, &data[idx * _stride]);
107 |
108 | if (result <= 0)
109 | {
110 | ll = idx;
111 | }
112 | else
113 | {
114 | offset = idx + 1;
115 | }
116 | }
117 |
118 | return offset;
119 | }
120 |
121 | uint32_t upperBound(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
122 | {
123 | uint32_t offset = 0;
124 | const uint8_t* data = (uint8_t*)_data;
125 |
126 | for (uint32_t ll = _num; offset < ll;)
127 | {
128 | const uint32_t idx = (offset + ll) / 2;
129 |
130 | int32_t result = _fn(_key, &data[idx * _stride]);
131 |
132 | if (result < 0)
133 | {
134 | ll = idx;
135 | }
136 | else
137 | {
138 | offset = idx + 1;
139 | }
140 | }
141 |
142 | return offset;
143 | }
144 |
145 | int32_t binarySearch(const void* _key, const void* _data, uint32_t _num, uint32_t _stride, const ComparisonFn _fn)
146 | {
147 | uint32_t offset = 0;
148 | const uint8_t* data = (uint8_t*)_data;
149 |
150 | for (uint32_t ll = _num; offset < ll;)
151 | {
152 | const uint32_t idx = (offset + ll) / 2;
153 |
154 | int32_t result = _fn(_key, &data[idx * _stride]);
155 |
156 | if (result < 0)
157 | {
158 | ll = idx;
159 | }
160 | else if (result > 0)
161 | {
162 | offset = idx + 1;
163 | }
164 | else
165 | {
166 | return idx;
167 | }
168 | }
169 |
170 | return ~offset;
171 | }
172 |
173 | } // namespace bx
174 |
175 |
--------------------------------------------------------------------------------
/src/timer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include
7 |
8 | #if BX_CRT_NONE
9 | # include
10 | #elif BX_PLATFORM_ANDROID
11 | # include // clock, clock_gettime
12 | #elif BX_PLATFORM_EMSCRIPTEN
13 | # include
14 | #elif BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT
15 | # ifndef WIN32_LEAN_AND_MEAN
16 | # define WIN32_LEAN_AND_MEAN
17 | # endif // WIN32_LEAN_AND_MEAN
18 | # include
19 | #else
20 | # include // gettimeofday
21 | #endif // BX_PLATFORM_
22 |
23 | namespace bx
24 | {
25 | int64_t getHPCounter()
26 | {
27 | #if BX_CRT_NONE
28 | int64_t i64 = crt0::getHPCounter();
29 | #elif BX_PLATFORM_WINDOWS \
30 | || BX_PLATFORM_XBOXONE \
31 | || BX_PLATFORM_WINRT
32 | LARGE_INTEGER li;
33 | QueryPerformanceCounter(&li);
34 | int64_t i64 = li.QuadPart;
35 | #elif BX_PLATFORM_ANDROID
36 | struct timespec now;
37 | clock_gettime(CLOCK_MONOTONIC, &now);
38 | int64_t i64 = now.tv_sec*INT64_C(1000000000) + now.tv_nsec;
39 | #elif BX_PLATFORM_EMSCRIPTEN
40 | int64_t i64 = int64_t(1000.0f * emscripten_get_now() );
41 | #elif !BX_PLATFORM_NONE
42 | struct timeval now;
43 | gettimeofday(&now, NULL);
44 | int64_t i64 = now.tv_sec*INT64_C(1000000) + now.tv_usec;
45 | #else
46 | BX_ASSERT(false, "Not implemented!");
47 | int64_t i64 = UINT64_MAX;
48 | #endif // BX_PLATFORM_
49 | return i64;
50 | }
51 |
52 | int64_t getHPFrequency()
53 | {
54 | #if BX_CRT_NONE
55 | return INT64_C(1000000000);
56 | #elif BX_PLATFORM_WINDOWS \
57 | || BX_PLATFORM_XBOXONE \
58 | || BX_PLATFORM_WINRT
59 | LARGE_INTEGER li;
60 | QueryPerformanceFrequency(&li);
61 | return li.QuadPart;
62 | #elif BX_PLATFORM_ANDROID
63 | return INT64_C(1000000000);
64 | #elif BX_PLATFORM_EMSCRIPTEN
65 | return INT64_C(1000000);
66 | #else
67 | return INT64_C(1000000);
68 | #endif // BX_PLATFORM_
69 | }
70 |
71 | } // namespace bx
72 |
--------------------------------------------------------------------------------
/src/url.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bnet#license-bsd-2-clause
4 | */
5 |
6 | #include
7 |
8 | namespace bx
9 | {
10 | UrlView::UrlView()
11 | {
12 | }
13 |
14 | void UrlView::clear()
15 | {
16 | for (uint32_t ii = 0; ii < Count; ++ii)
17 | {
18 | m_tokens[ii].clear();
19 | }
20 | }
21 |
22 | bool UrlView::parse(const StringView& _url)
23 | {
24 | clear();
25 |
26 | const char* term = _url.getTerm();
27 | StringView schemeEnd = strFind(_url, "://");
28 | const char* hostStart = !schemeEnd.isEmpty() ? schemeEnd.getTerm() : _url.getPtr();
29 | StringView path = strFind(StringView(hostStart, term), '/');
30 |
31 | if (schemeEnd.isEmpty()
32 | && path.isEmpty() )
33 | {
34 | return false;
35 | }
36 |
37 | if (!schemeEnd.isEmpty()
38 | && (path.isEmpty() || path.getPtr() > schemeEnd.getPtr() ) )
39 | {
40 | const StringView scheme(_url.getPtr(), schemeEnd.getPtr() );
41 |
42 | if (!isAlpha(scheme) )
43 | {
44 | return false;
45 | }
46 |
47 | m_tokens[Scheme].set(scheme);
48 | }
49 |
50 | if (!path.isEmpty() )
51 | {
52 | path.set(path.getPtr(), term);
53 | const StringView query = strFind(path, '?');
54 | const StringView fragment = strFind(path, '#');
55 |
56 | if (!fragment.isEmpty()
57 | && fragment.getPtr() < query.getPtr() )
58 | {
59 | return false;
60 | }
61 |
62 | m_tokens[Path].set(path.getPtr()
63 | , !query.isEmpty() ? query.getPtr()
64 | : !fragment.isEmpty() ? fragment.getPtr()
65 | : term
66 | );
67 |
68 | if (!query.isEmpty() )
69 | {
70 | m_tokens[Query].set(query.getPtr()+1
71 | , !fragment.isEmpty() ? fragment.getPtr()
72 | : term
73 | );
74 | }
75 |
76 | if (!fragment.isEmpty() )
77 | {
78 | m_tokens[Fragment].set(fragment.getPtr()+1, term);
79 | }
80 |
81 | term = path.getPtr();
82 | }
83 |
84 | const StringView userPassEnd = strFind(StringView(hostStart, term), '@');
85 | const char* userPassStart = !userPassEnd.isEmpty() ? hostStart : NULL;
86 | hostStart = !userPassEnd.isEmpty() ? userPassEnd.getPtr()+1 : hostStart;
87 | const StringView portStart = strFind(StringView(hostStart, term), ':');
88 |
89 | m_tokens[Host].set(hostStart, !portStart.isEmpty() ? portStart.getPtr() : term);
90 |
91 | if (!portStart.isEmpty())
92 | {
93 | m_tokens[Port].set(portStart.getPtr()+1, term);
94 | }
95 |
96 | if (NULL != userPassStart)
97 | {
98 | StringView passStart = strFind(StringView(userPassStart, userPassEnd.getPtr() ), ':');
99 |
100 | m_tokens[UserName].set(userPassStart
101 | , !passStart.isEmpty() ? passStart.getPtr()
102 | : userPassEnd.getPtr()
103 | );
104 |
105 | if (!passStart.isEmpty() )
106 | {
107 | m_tokens[Password].set(passStart.getPtr()+1, userPassEnd.getPtr() );
108 | }
109 | }
110 |
111 | return true;
112 | }
113 |
114 | const StringView& UrlView::get(Enum _token) const
115 | {
116 | return m_tokens[_token];
117 | }
118 |
119 | static char toHex(char _nible)
120 | {
121 | return "0123456789ABCDEF"[_nible&0xf];
122 | }
123 |
124 | // https://secure.wikimedia.org/wikipedia/en/wiki/URL_encoding
125 | void urlEncode(char* _out, uint32_t _max, const StringView& _str)
126 | {
127 | _max--; // need space for zero terminator
128 |
129 | const char* str = _str.getPtr();
130 | const char* term = _str.getTerm();
131 |
132 | uint32_t ii = 0;
133 | for (char ch = *str++
134 | ; str <= term && ii < _max
135 | ; ch = *str++
136 | )
137 | {
138 | if (isAlphaNum(ch)
139 | || ch == '-'
140 | || ch == '_'
141 | || ch == '.'
142 | || ch == '~')
143 | {
144 | _out[ii++] = ch;
145 | }
146 | else if (ii+3 < _max)
147 | {
148 | _out[ii++] = '%';
149 | _out[ii++] = toHex(ch>>4);
150 | _out[ii++] = toHex(ch);
151 | }
152 | }
153 |
154 | _out[ii] = '\0';
155 | }
156 |
157 | } // namespace bx
158 |
--------------------------------------------------------------------------------
/tests/allocator_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "test.h"
7 |
8 | #include
9 |
10 | struct MockNonFreeingAllocator : public bx::AllocatorI
11 | {
12 | MockNonFreeingAllocator()
13 | : m_sbrk(1)
14 | {
15 | }
16 |
17 | ~MockNonFreeingAllocator() override
18 | {
19 | }
20 |
21 | void* realloc(void* _ptr, size_t _size, size_t _align, const char* _file, uint32_t _line) override
22 | {
23 | BX_ASSERT(_ptr == NULL, "MockNonFreeingAllocator can't realloc or free.");
24 | BX_ASSERT(m_sbrk + _size < BX_COUNTOF(m_storage), "");
25 | BX_UNUSED(_ptr, _file, _line);
26 |
27 | const uintptr_t sbrk = bx::alignUp(m_sbrk, bx::max(int32_t(_align), 1) );
28 | m_sbrk = sbrk + _size;
29 |
30 | return &m_storage[sbrk];
31 | }
32 |
33 | uintptr_t m_sbrk;
34 | BX_ALIGN_DECL(256, uint8_t) m_storage[0x10000];
35 | };
36 |
37 | bool testAlignment(size_t _expected, void* _ptr)
38 | {
39 | bool aligned = bx::isAligned(_ptr, int32_t(_expected) );
40 | // BX_TRACE("%p, %d", _ptr, _expected);
41 | BX_WARN(aligned, "%p not aligned to %d bytes.", _ptr, _expected);
42 | return aligned;
43 | }
44 |
45 | TEST_CASE("Allocator", "")
46 | {
47 | MockNonFreeingAllocator mnfa;
48 |
49 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
50 | REQUIRE(testAlignment(2, bx::alloc (&mnfa, 1, 2 ) ) );
51 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
52 | REQUIRE(testAlignment(4, bx::alloc (&mnfa, 1, 4 ) ) );
53 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
54 | REQUIRE(testAlignment(8, bx::alloc (&mnfa, 1, 8 ) ) );
55 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
56 | REQUIRE(testAlignment(16, bx::alloc (&mnfa, 1, 16 ) ) );
57 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
58 | REQUIRE(testAlignment(32, bx::alloc (&mnfa, 1, 32 ) ) );
59 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
60 | REQUIRE(testAlignment(64, bx::alloc (&mnfa, 1, 64 ) ) );
61 | REQUIRE(testAlignment(1, bx::alloc (&mnfa, 1, 1 ) ) );
62 | REQUIRE(testAlignment(128, bx::alloc (&mnfa, 1, 128) ) );
63 |
64 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
65 | REQUIRE(testAlignment(2, bx::alignedAlloc(&mnfa, 1, 2 ) ) );
66 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
67 | REQUIRE(testAlignment(4, bx::alignedAlloc(&mnfa, 1, 4 ) ) );
68 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
69 | REQUIRE(testAlignment(8, bx::alignedAlloc(&mnfa, 1, 8 ) ) );
70 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
71 | REQUIRE(testAlignment(16, bx::alignedAlloc(&mnfa, 1, 16 ) ) );
72 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
73 | REQUIRE(testAlignment(32, bx::alignedAlloc(&mnfa, 1, 32 ) ) );
74 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
75 | REQUIRE(testAlignment(64, bx::alignedAlloc(&mnfa, 1, 64 ) ) );
76 | REQUIRE(testAlignment(1, bx::alignedAlloc(&mnfa, 1, 1 ) ) );
77 | REQUIRE(testAlignment(128, bx::alignedAlloc(&mnfa, 1, 128) ) );
78 | }
79 |
--------------------------------------------------------------------------------
/tests/atomic_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "test.h"
7 | #include
8 |
9 | TEST_CASE("atomic", "")
10 | {
11 | uint32_t test = 1337;
12 | uint32_t fetched;
13 |
14 | fetched = bx::atomicFetchAndAdd(&test, 52u);
15 | REQUIRE(fetched == 1337);
16 | REQUIRE(test == 1389);
17 |
18 | fetched = bx::atomicAddAndFetch(&test, 64u);
19 | REQUIRE(fetched == 1453);
20 | REQUIRE(test == 1453);
21 |
22 | fetched = bx::atomicFetchAndSub(&test, 64u);
23 | REQUIRE(fetched == 1453);
24 | REQUIRE(test == 1389);
25 |
26 | fetched = bx::atomicSubAndFetch(&test, 52u);
27 | REQUIRE(fetched == 1337);
28 | REQUIRE(test == 1337);
29 |
30 | fetched = bx::atomicFetchAndAddsat(&test, 52u, 1453u);
31 | REQUIRE(fetched == 1337);
32 | REQUIRE(test == 1389);
33 |
34 | fetched = bx::atomicFetchAndAddsat(&test, 1000u, 1453u);
35 | REQUIRE(fetched == 1389);
36 | REQUIRE(test == 1453);
37 |
38 | fetched = bx::atomicFetchAndSubsat(&test, 64u, 1337u);
39 | REQUIRE(fetched == 1453);
40 | REQUIRE(test == 1389);
41 |
42 | fetched = bx::atomicFetchAndSubsat(&test, 1000u, 1337u);
43 | REQUIRE(fetched == 1389);
44 | REQUIRE(test == 1337);
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/tests/cast_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "test.h"
7 | #include
8 |
9 | TEST_CASE("Bit cast", "[cast]")
10 | {
11 | STATIC_REQUIRE(0x4172f58bc0000000ull == bx::bitCast(19880124.0) );
12 | STATIC_REQUIRE(0x3fe9000000000000ull == bx::bitCast(0.781250) );
13 | STATIC_REQUIRE(19880124.0 == bx::bitCast(0x4172f58bc0000000ull) );
14 | STATIC_REQUIRE(0.781250 == bx::bitCast(0x3fe9000000000000ull) );
15 | }
16 |
17 | TEST_CASE("Narrow cast", "[cast]")
18 | {
19 | REQUIRE(127 == bx::narrowCast(int32_t(127) ) );
20 | REQUIRE_ASSERTS(bx::narrowCast(int32_t(128) ) );
21 | REQUIRE_ASSERTS(bx::narrowCast(uint32_t(128) ) );
22 | REQUIRE(128 == bx::narrowCast(int32_t(128) ) );
23 | }
24 |
--------------------------------------------------------------------------------
/tests/crt_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "test.h"
7 |
8 | TEST_CASE("memSet", "")
9 | {
10 | char temp[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
11 |
12 | bx::memSet(temp, 0, 0);
13 | REQUIRE(temp[0] == 1);
14 |
15 | bx::memSet(temp, 0, 5);
16 | REQUIRE(temp[0] == 0);
17 | REQUIRE(temp[1] == 0);
18 | REQUIRE(temp[2] == 0);
19 | REQUIRE(temp[3] == 0);
20 | REQUIRE(temp[4] == 0);
21 | REQUIRE(temp[5] == 6);
22 | }
23 |
24 | TEST_CASE("memMove", "")
25 | {
26 | const char* original = "xxxxabvgd";
27 | char str[] = { 'x', 'x', 'x', 'x', 'a', 'b', 'v', 'g', 'd' };
28 |
29 | bx::memMove(&str[4], &str[4], 0);
30 | REQUIRE(0 == bx::memCmp(str, original, 9) );
31 |
32 | bx::memMove(&str[4], &str[4], 5);
33 | REQUIRE(0 == bx::memCmp(str, original, 9) );
34 |
35 | bx::memMove(str, &str[4], 5);
36 | REQUIRE(0 == bx::memCmp(str, "abvgd", 5) );
37 |
38 | bx::memMove(&str[4], str, 5);
39 | REQUIRE(str[4] == 'a' );
40 |
41 | bx::memSet(str, 'x', 4);
42 | REQUIRE(0 == bx::memCmp(str, original, 9) );
43 | }
44 |
45 | TEST_CASE("scatter/gather", "")
46 | {
47 | const char* str = "a\0b\0v\0g\0d";
48 |
49 | char tmp0[64];
50 | bx::gather(tmp0, str, 2, 1, 5);
51 | REQUIRE(0 == bx::memCmp(tmp0, "abvgd", 5) );
52 |
53 | char tmp1[64];
54 | bx::scatter(tmp1, 2, tmp0, 1, 5);
55 | bx::memSet(&tmp1[1], 2, 0, 1, 5);
56 | REQUIRE(0 == bx::memCmp(tmp1, str, 5) );
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/tests/dbg.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #ifndef DBG_H_HEADER_GUARD
7 | #define DBG_H_HEADER_GUARD
8 |
9 | #include
10 |
11 | #define DBG_STRINGIZE(_x) DBG_STRINGIZE_(_x)
12 | #define DBG_STRINGIZE_(_x) #_x
13 | #define DBG_FILE_LINE_LITERAL "" __FILE__ "(" DBG_STRINGIZE(__LINE__) "): "
14 | #define DBG(_format, ...) bx::debugPrintf(DBG_FILE_LINE_LITERAL "" _format "\n", ##__VA_ARGS__)
15 |
16 | #endif // DBG_H_HEADER_GUARD
17 |
--------------------------------------------------------------------------------
/tests/easing_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "test.h"
7 |
8 | #include
9 | #include
10 |
11 | TEST_CASE("easing", "")
12 | {
13 | bx::WriterI* writer = bx::getNullOut();
14 | bx::Error err;
15 |
16 | for (uint32_t ee = 0; ee < bx::Easing::Count; ++ee)
17 | {
18 | bx::write(writer, &err, "\n\n%d\n", ee);
19 |
20 | const bx::EaseFn easing = bx::getEaseFunc(bx::Easing::Enum(ee) );
21 |
22 | const int32_t nx = 64;
23 | const int32_t ny = 10;
24 |
25 | bx::write(writer, &err, "\t/// ^\n");
26 |
27 | for (int32_t yy = ny+4; yy >= -5; --yy)
28 | {
29 | const float ys = float(yy )/float(ny);
30 | const float ye = float(yy+1.0)/float(ny);
31 |
32 | bx::write(writer, &err, "\t/// %c", yy != 0 ? '|' : '+');
33 |
34 | for (int32_t xx = 0; xx < nx; ++xx)
35 | {
36 | int32_t jj = 0;
37 | for (; jj < 10; ++jj)
38 | {
39 | const float tt = float(xx*10+jj)/10.0f/float(nx);
40 | const float vv = easing(tt);
41 |
42 | if (vv >= ys
43 | && vv < ye)
44 | {
45 | bx::write(writer, &err, "*");
46 | break;
47 | }
48 | }
49 |
50 | if (jj == 10)
51 | {
52 | bx::write(writer, &err, "%c", yy != 0 ? ' ' : '-');
53 | }
54 | }
55 |
56 | bx::write(writer, &err, "%s\n", yy != 0 ? "" : ">");
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/tests/filepath_test.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include "test.h"
7 | #include
8 |
9 | struct FilePathTest
10 | {
11 | const char* filePath;
12 | const char* expected;
13 | };
14 |
15 | FilePathTest s_filePathTest[] =
16 | {
17 | // Already clean
18 | {"", "."},
19 | {"abc", "abc"},
20 | {"abc/def", "abc/def"},
21 | {"a/b/c", "a/b/c"},
22 | {".", "."},
23 | {"..", ".."},
24 | {"../..", "../.."},
25 | {"../../abc", "../../abc"},
26 | {"/abc", "/abc"},
27 | {"/", "/"},
28 |
29 | // Do not remove trailing slash
30 | {"abc/", "abc/"},
31 | {"abc/def/", "abc/def/"},
32 | {"a/b/c/", "a/b/c/"},
33 | {"./", "./"},
34 | {"../", "../"},
35 | {"../../", "../../"},
36 | {"/abc/", "/abc/"},
37 |
38 | // Remove doubled slash
39 | {"abc//def//ghi", "abc/def/ghi"},
40 | {"//abc", "/abc"},
41 | {"///abc", "/abc"},
42 | {"//abc//", "/abc/"},
43 | {"abc//", "abc/"},
44 |
45 | // Remove . elements
46 | {"abc/./def", "abc/def"},
47 | {"/./abc/def", "/abc/def"},
48 | {"abc/.", "abc"},
49 |
50 | // Remove .. elements
51 | {"abc/def/ghi/../jkl", "abc/def/jkl"},
52 | {"abc/def/../ghi/../jkl", "abc/jkl"},
53 | {"abc/def/..", "abc"},
54 | {"abc/def/../..", "."},
55 | {"/abc/def/../..", "/"},
56 | {"abc/def/../../..", ".."},
57 | {"/abc/def/../../..", "/"},
58 | {"abc/def/../../../ghi/jkl/../../../mno", "../../mno"},
59 |
60 | // Combinations
61 | {"abc/./../def", "def"},
62 | {"abc//./../def", "def"},
63 | {"abc/../../././../def", "../../def"},
64 |
65 | {"abc\\/../..\\/././../def", "../../def"},
66 | {"\\abc/def\\../..\\..", "/"},
67 | };
68 |
69 | struct FilePathSplit
70 | {
71 | const char* filePath;
72 | bool absolute;
73 | const char* path;
74 | const char* fileName;
75 | const char* baseName;
76 | const char* extension;
77 | };
78 |
79 | static const FilePathSplit s_filePathSplit[] =
80 | {
81 | { "\\abc/def\\../..\\../test.txt", true, "/", "test.txt", "test", ".txt" },
82 | { "/abv/gd/555/333/pod.mac", true, "/abv/gd/555/333/", "pod.mac", "pod", ".mac" },
83 | { "archive.tar.gz", false, "", "archive.tar.gz", "archive", ".tar.gz" },
84 | { "tmp/archive.tar.gz", false, "tmp/", "archive.tar.gz", "archive", ".tar.gz" },
85 | { "/tmp/archive.tar.gz", true, "/tmp/", "archive.tar.gz", "archive", ".tar.gz" },
86 | { "d:/tmp/archive.tar.gz", true, "D:/tmp/", "archive.tar.gz", "archive", ".tar.gz" },
87 | { "/tmp/abv/gd", true, "/tmp/abv/", "gd", "gd", "" },
88 | { "/tmp/abv/gd/", true, "/tmp/abv/gd/", "", "", "" },
89 | };
90 |
91 | TEST_CASE("FilePath", "[filepath][string]")
92 | {
93 | bx::FilePath fp;
94 | for (uint32_t ii = 0; ii < BX_COUNTOF(s_filePathTest); ++ii)
95 | {
96 | const FilePathTest& test = s_filePathTest[ii];
97 |
98 | fp.set(test.filePath);
99 |
100 | REQUIRE(0 == bx::strCmp(test.expected, fp) );
101 | }
102 |
103 | for (uint32_t ii = 0; ii < BX_COUNTOF(s_filePathSplit); ++ii)
104 | {
105 | const FilePathSplit& test = s_filePathSplit[ii];
106 |
107 | fp.set(test.filePath);
108 | const bx::StringView path = fp.getPath();
109 | const bx::StringView fileName = fp.getFileName();
110 | const bx::StringView baseName = fp.getBaseName();
111 | const bx::StringView ext = fp.getExt();
112 |
113 | REQUIRE(0 == bx::strCmp(test.path, path) );
114 | REQUIRE(0 == bx::strCmp(test.fileName, fileName) );
115 | REQUIRE(0 == bx::strCmp(test.baseName, baseName) );
116 | REQUIRE(0 == bx::strCmp(test.extension, ext) );
117 | REQUIRE(test.absolute == fp.isAbsolute() );
118 | };
119 | }
120 |
121 | TEST_CASE("FilePath temp", "[filepath]")
122 | {
123 | bx::FilePath tmp(bx::Dir::Temp);
124 | REQUIRE(0 != bx::strCmp(".", tmp.getPath().getPtr() ) );
125 |
126 | tmp.set(bx::Dir::Temp);
127 | tmp.join("bx.test");
128 | bx::removeAll(tmp, bx::ErrorIgnore{});
129 |
130 | tmp.join("bx.test/abvgd/555333/test");
131 | REQUIRE(bx::makeAll(tmp, bx::ErrorAssert{}) );
132 |
133 | if (BX_ENABLED(BX_PLATFORM_EMSCRIPTEN) )
134 | {
135 | SKIP("Not supported by wasm.");
136 | }
137 |
138 | tmp.set(bx::Dir::Temp);
139 | tmp.join("bx.test");
140 | REQUIRE(bx::removeAll(tmp, bx::ErrorAssert{}) );
141 | }
142 |
143 | TEST_CASE("FilePath special", "[filepath]")
144 | {
145 | {
146 | bx::FilePath tmp(bx::Dir::Current);
147 | bx::StringView sv(tmp);
148 | DBG("%S", &sv);
149 | }
150 |
151 | {
152 | bx::FilePath tmp(bx::Dir::Executable);
153 | bx::StringView sv(tmp);
154 | DBG("%S", &sv);
155 | }
156 |
157 | {
158 | bx::FilePath tmp(bx::Dir::Home);
159 | bx::StringView sv(tmp);
160 | DBG("%S", &sv);
161 | }
162 |
163 | {
164 | bx::FilePath tmp(bx::Dir::Temp);
165 | bx::StringView sv(tmp);
166 | DBG("%S", &sv);
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/tests/handle_bench.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010-2025 Branimir Karadzic. All rights reserved.
3 | * License: https://github.com/bkaradzic/bx/blob/master/LICENSE
4 | */
5 |
6 | #include
7 | #include
8 |
9 | #include
10 | #include