mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-04 09:44:40 +00:00
Merge branch 'master' into macharena
This commit is contained in:
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
@@ -32,9 +32,9 @@ jobs:
|
||||
gmake -C vendor/miniaudio/src
|
||||
./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_amd64
|
||||
./odin check examples/all -vet -strict-style -disallow-do -target:netbsd_arm64
|
||||
./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
(cd tests/issues; ./run.sh)
|
||||
build_freebsd:
|
||||
name: FreeBSD Build, Check, and Test
|
||||
@@ -60,9 +60,9 @@ jobs:
|
||||
gmake -C vendor/cgltf/src
|
||||
gmake -C vendor/miniaudio/src
|
||||
./odin check examples/all -vet -strict-style -disallow-do -target:freebsd_amd64
|
||||
./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/core/speed.odin -file -all-packages -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/core/speed.odin -file -all-packages -vet -strict-style -disallow-do -o:speed -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
(cd tests/issues; ./run.sh)
|
||||
ci:
|
||||
strategy:
|
||||
@@ -116,13 +116,13 @@ jobs:
|
||||
- name: Odin check examples/all
|
||||
run: ./odin check examples/all -strict-style
|
||||
- name: Normal Core library tests
|
||||
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Optimized Core library tests
|
||||
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Vendor library tests
|
||||
run: ./odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
run: ./odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Internals tests
|
||||
run: ./odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: GitHub Issue tests
|
||||
run: |
|
||||
cd tests/issues
|
||||
@@ -176,33 +176,33 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin run examples/demo -debug
|
||||
odin run examples/demo -debug -vet -strict-style -disallow-do
|
||||
- name: Odin check examples/all
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin check examples/all -strict-style
|
||||
odin check examples/all -vet -strict-style -disallow-do
|
||||
- name: Core library tests
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Optimized core library tests
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Vendor library tests
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
copy vendor\lua\5.4\windows\*.dll .
|
||||
odin test tests/vendor -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
odin test tests/vendor -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Odin internals tests
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||
odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
|
||||
- name: Odin documentation tests
|
||||
shell: cmd
|
||||
run: |
|
||||
@@ -257,16 +257,16 @@ jobs:
|
||||
run: sudo apt-get install -y qemu-user qemu-user-static gcc-12-riscv64-linux-gnu libc6-riscv64-cross
|
||||
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin run examples/demo -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Odin run -debug
|
||||
run: ./odin run examples/demo -debug -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin run examples/demo -debug -vet -strict-style -disallow-do -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Normal Core library tests
|
||||
run: ./odin test tests/core/normal.odin -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin test tests/core/normal.odin -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Optimized Core library tests
|
||||
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin test tests/core/speed.odin -o:speed -file -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
- name: Internals tests
|
||||
run: ./odin test tests/internal -all-packages -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static"
|
||||
run: ./odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true -target:linux_riscv64 -extra-linker-flags:"-fuse-ld=/usr/bin/riscv64-linux-gnu-gcc-12 -static -Wl,-static" -no-rpath
|
||||
|
||||
145
.github/workflows/nightly.yml
vendored
145
.github/workflows/nightly.yml
vendored
@@ -36,43 +36,54 @@ jobs:
|
||||
cp -r bin dist
|
||||
cp -r examples dist
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: windows_artifacts
|
||||
path: dist
|
||||
build_ubuntu:
|
||||
name: Ubuntu Build
|
||||
build_linux:
|
||||
name: Linux Build
|
||||
if: github.repository == 'odin-lang/Odin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: jirutka/setup-alpine@v1
|
||||
with:
|
||||
branch: v3.20
|
||||
- name: (Linux) Download LLVM
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 18
|
||||
echo "/usr/lib/llvm-18/bin" >> $GITHUB_PATH
|
||||
apk add --no-cache \
|
||||
musl-dev llvm18-dev clang18 git mold lz4 \
|
||||
libxml2-static llvm18-static zlib-static zstd-static \
|
||||
make
|
||||
shell: alpine.sh --root {0}
|
||||
- name: build odin
|
||||
run: make nightly
|
||||
# NOTE: this build does slow compile times because of musl
|
||||
run: ci/build_linux_static.sh
|
||||
shell: alpine.sh {0}
|
||||
- name: Odin run
|
||||
run: ./odin run examples/demo
|
||||
- name: Copy artifacts
|
||||
run: |
|
||||
mkdir dist
|
||||
cp odin dist
|
||||
cp LICENSE dist
|
||||
cp -r shared dist
|
||||
cp -r base dist
|
||||
cp -r core dist
|
||||
cp -r vendor dist
|
||||
cp -r examples dist
|
||||
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
|
||||
zip -r dist.zip dist
|
||||
FILE="odin-linux-amd64-nightly+$(date -I)"
|
||||
mkdir $FILE
|
||||
cp odin $FILE
|
||||
cp LICENSE $FILE
|
||||
cp -r shared $FILE
|
||||
cp -r base $FILE
|
||||
cp -r core $FILE
|
||||
cp -r vendor $FILE
|
||||
cp -r examples $FILE
|
||||
# Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
|
||||
tar -czvf dist.tar.gz $FILE
|
||||
- name: Odin run
|
||||
run: |
|
||||
FILE="odin-linux-amd64-nightly+$(date -I)"
|
||||
$FILE/odin run examples/demo
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ubuntu_artifacts
|
||||
path: dist.zip
|
||||
name: linux_artifacts
|
||||
path: dist.tar.gz
|
||||
build_macos:
|
||||
name: MacOS Build
|
||||
if: github.repository == 'odin-lang/Odin'
|
||||
@@ -89,24 +100,27 @@ jobs:
|
||||
run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly
|
||||
- name: Bundle
|
||||
run: |
|
||||
mkdir dist
|
||||
cp odin dist
|
||||
cp LICENSE dist
|
||||
cp -r shared dist
|
||||
cp -r base dist
|
||||
cp -r core dist
|
||||
cp -r vendor dist
|
||||
cp -r examples dist
|
||||
dylibbundler -b -x dist/odin -d dist/libs -od -p @executable_path/libs
|
||||
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
|
||||
zip -r dist.zip dist
|
||||
FILE="odin-macos-amd64-nightly+$(date -I)"
|
||||
mkdir $FILE
|
||||
cp odin $FILE
|
||||
cp LICENSE $FILE
|
||||
cp -r shared $FILE
|
||||
cp -r base $FILE
|
||||
cp -r core $FILE
|
||||
cp -r vendor $FILE
|
||||
cp -r examples $FILE
|
||||
dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs
|
||||
# Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
|
||||
tar -czvf dist.tar.gz $FILE
|
||||
- name: Odin run
|
||||
run: ./dist/odin run examples/demo
|
||||
run: |
|
||||
FILE="odin-macos-amd64-nightly+$(date -I)"
|
||||
$FILE/odin run examples/demo
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos_artifacts
|
||||
path: dist.zip
|
||||
path: dist.tar.gz
|
||||
build_macos_arm:
|
||||
name: MacOS ARM Build
|
||||
if: github.repository == 'odin-lang/Odin'
|
||||
@@ -123,30 +137,33 @@ jobs:
|
||||
run: CXXFLAGS="-L/usr/lib/system -L/usr/lib" make nightly
|
||||
- name: Bundle
|
||||
run: |
|
||||
mkdir dist
|
||||
cp odin dist
|
||||
cp LICENSE dist
|
||||
cp -r shared dist
|
||||
cp -r base dist
|
||||
cp -r core dist
|
||||
cp -r vendor dist
|
||||
cp -r examples dist
|
||||
dylibbundler -b -x dist/odin -d dist/libs -od -p @executable_path/libs
|
||||
# Zipping so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
|
||||
zip -r dist.zip dist
|
||||
FILE="odin-macos-arm64-nightly+$(date -I)"
|
||||
mkdir $FILE
|
||||
cp odin $FILE
|
||||
cp LICENSE $FILE
|
||||
cp -r shared $FILE
|
||||
cp -r base $FILE
|
||||
cp -r core $FILE
|
||||
cp -r vendor $FILE
|
||||
cp -r examples $FILE
|
||||
dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs
|
||||
# Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38
|
||||
tar -czvf dist.tar.gz $FILE
|
||||
- name: Odin run
|
||||
run: ./dist/odin run examples/demo
|
||||
run: |
|
||||
FILE="odin-macos-arm64-nightly+$(date -I)"
|
||||
$FILE/odin run examples/demo
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos_arm_artifacts
|
||||
path: dist.zip
|
||||
path: dist.tar.gz
|
||||
upload_b2:
|
||||
runs-on: [ubuntu-latest]
|
||||
needs: [build_windows, build_macos, build_macos_arm, build_ubuntu]
|
||||
needs: [build_windows, build_macos, build_macos_arm, build_linux]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.8.x'
|
||||
|
||||
@@ -160,24 +177,33 @@ jobs:
|
||||
run: python -c "import sys; print(sys.version)"
|
||||
|
||||
- name: Download Windows artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
name: windows_artifacts
|
||||
path: windows_artifacts
|
||||
|
||||
- name: Download Ubuntu artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
name: ubuntu_artifacts
|
||||
name: linux_artifacts
|
||||
path: linux_artifacts
|
||||
|
||||
- name: Download macOS artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
name: macos_artifacts
|
||||
path: macos_artifacts
|
||||
|
||||
- name: Download macOS arm artifacts
|
||||
uses: actions/download-artifact@v1
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
with:
|
||||
name: macos_arm_artifacts
|
||||
path: macos_arm_artifacts
|
||||
|
||||
- name: Debug
|
||||
run: |
|
||||
tree -L 2
|
||||
|
||||
- name: Create archives and upload
|
||||
shell: bash
|
||||
@@ -187,9 +213,10 @@ jobs:
|
||||
BUCKET: ${{ secrets.B2_BUCKET }}
|
||||
DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }}
|
||||
run: |
|
||||
file linux_artifacts/dist.tar.gz
|
||||
python3 ci/nightly.py artifact windows-amd64 windows_artifacts/
|
||||
python3 ci/nightly.py artifact ubuntu-amd64 ubuntu_artifacts/dist.zip
|
||||
python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.zip
|
||||
python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.zip
|
||||
python3 ci/nightly.py artifact linux-amd64 linux_artifacts/dist.tar.gz
|
||||
python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.tar.gz
|
||||
python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.tar.gz
|
||||
python3 ci/nightly.py prune
|
||||
python3 ci/nightly.py json
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This is purely for documentation
|
||||
//+build ignore
|
||||
#+build ignore
|
||||
package intrinsics
|
||||
|
||||
// Package-Related
|
||||
@@ -219,6 +219,8 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
|
||||
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
|
||||
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
|
||||
|
||||
type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
|
||||
|
||||
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
|
||||
|
||||
constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// This could change at a later date if the all these data structures are
|
||||
// implemented within the compiler rather than in this "preload" file
|
||||
//
|
||||
//+no-instrumentation
|
||||
#+no-instrumentation
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
@@ -546,10 +546,23 @@ Odin_OS_Type :: type_of(ODIN_OS)
|
||||
arm64,
|
||||
wasm32,
|
||||
wasm64p32,
|
||||
riscv64,
|
||||
}
|
||||
*/
|
||||
Odin_Arch_Type :: type_of(ODIN_ARCH)
|
||||
|
||||
Odin_Arch_Types :: bit_set[Odin_Arch_Type]
|
||||
|
||||
ALL_ODIN_ARCH_TYPES :: Odin_Arch_Types{
|
||||
.amd64,
|
||||
.i386,
|
||||
.arm32,
|
||||
.arm64,
|
||||
.wasm32,
|
||||
.wasm64p32,
|
||||
.riscv64,
|
||||
}
|
||||
|
||||
/*
|
||||
// Defined internally by the compiler
|
||||
Odin_Build_Mode_Type :: enum int {
|
||||
@@ -573,6 +586,22 @@ Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
|
||||
*/
|
||||
Odin_Endian_Type :: type_of(ODIN_ENDIAN)
|
||||
|
||||
Odin_OS_Types :: bit_set[Odin_OS_Type]
|
||||
|
||||
ALL_ODIN_OS_TYPES :: Odin_OS_Types{
|
||||
.Windows,
|
||||
.Darwin,
|
||||
.Linux,
|
||||
.Essence,
|
||||
.FreeBSD,
|
||||
.OpenBSD,
|
||||
.NetBSD,
|
||||
.Haiku,
|
||||
.WASI,
|
||||
.JS,
|
||||
.Orca,
|
||||
.Freestanding,
|
||||
}
|
||||
|
||||
/*
|
||||
// Defined internally by the compiler
|
||||
|
||||
@@ -68,7 +68,7 @@ copy :: proc{copy_slice, copy_from_string}
|
||||
// Note: If you want the elements to remain in their order, use `ordered_remove`.
|
||||
// Note: If the index is out of bounds, this procedure will panic.
|
||||
@builtin
|
||||
unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
|
||||
unordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check {
|
||||
bounds_check_error_loc(loc, index, len(array))
|
||||
n := len(array)-1
|
||||
if index != n {
|
||||
@@ -82,7 +82,7 @@ unordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_loca
|
||||
// Note: If the elements do not have to remain in their order, prefer `unordered_remove`.
|
||||
// Note: If the index is out of bounds, this procedure will panic.
|
||||
@builtin
|
||||
ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_location) #no_bounds_check {
|
||||
ordered_remove :: proc(array: ^$D/[dynamic]$T, #any_int index: int, loc := #caller_location) #no_bounds_check {
|
||||
bounds_check_error_loc(loc, index, len(array))
|
||||
if index+1 < len(array) {
|
||||
copy(array[index:], array[index+1:])
|
||||
@@ -95,7 +95,7 @@ ordered_remove :: proc(array: ^$D/[dynamic]$T, index: int, loc := #caller_locati
|
||||
// Note: This is an O(N) operation.
|
||||
// Note: If the range is out of bounds, this procedure will panic.
|
||||
@builtin
|
||||
remove_range :: proc(array: ^$D/[dynamic]$T, lo, hi: int, loc := #caller_location) #no_bounds_check {
|
||||
remove_range :: proc(array: ^$D/[dynamic]$T, #any_int lo, hi: int, loc := #caller_location) #no_bounds_check {
|
||||
slice_expr_error_lo_hi_loc(loc, lo, hi, len(array))
|
||||
n := max(hi-lo, 0)
|
||||
if n > 0 {
|
||||
@@ -602,7 +602,7 @@ append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: i
|
||||
|
||||
|
||||
@builtin
|
||||
inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
if array == nil {
|
||||
return
|
||||
}
|
||||
@@ -620,7 +620,7 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast arg: E,
|
||||
}
|
||||
|
||||
@builtin
|
||||
inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
if array == nil {
|
||||
return
|
||||
}
|
||||
@@ -643,7 +643,7 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args:
|
||||
}
|
||||
|
||||
@builtin
|
||||
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
if array == nil {
|
||||
return
|
||||
}
|
||||
@@ -668,7 +668,7 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
|
||||
|
||||
|
||||
@builtin
|
||||
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
if index < len(array) {
|
||||
array[index] = arg
|
||||
ok = true
|
||||
@@ -682,7 +682,7 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
|
||||
|
||||
|
||||
@builtin
|
||||
assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
new_size := index + len(args)
|
||||
if len(args) == 0 {
|
||||
ok = true
|
||||
@@ -699,7 +699,7 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, #no_broadcast args:
|
||||
|
||||
|
||||
@builtin
|
||||
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
new_size := index + len(arg)
|
||||
if len(arg) == 0 {
|
||||
ok = true
|
||||
@@ -838,7 +838,7 @@ non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: i
|
||||
|
||||
Note: Prefer the procedure group `shrink`
|
||||
*/
|
||||
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
||||
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
|
||||
return _shrink_dynamic_array((^Raw_Dynamic_Array)(array), size_of(E), align_of(E), new_cap, loc)
|
||||
}
|
||||
|
||||
@@ -913,7 +913,7 @@ card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
|
||||
|
||||
@builtin
|
||||
@(disabled=ODIN_DISABLE_ASSERT)
|
||||
assert :: proc(condition: bool, message := "", loc := #caller_location) {
|
||||
assert :: proc(condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
if !condition {
|
||||
// NOTE(bill): This is wrapped in a procedure call
|
||||
// to improve performance to make the CPU not
|
||||
@@ -952,7 +952,7 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! {
|
||||
|
||||
@builtin
|
||||
@(disabled=ODIN_DISABLE_ASSERT)
|
||||
assert_contextless :: proc "contextless" (condition: bool, message := "", loc := #caller_location) {
|
||||
assert_contextless :: proc "contextless" (condition: bool, message := #caller_expression(condition), loc := #caller_location) {
|
||||
if !condition {
|
||||
// NOTE(bill): This is wrapped in a procedure call
|
||||
// to improve performance to make the CPU not
|
||||
|
||||
@@ -76,7 +76,7 @@ raw_soa_footer :: proc{
|
||||
|
||||
|
||||
@(builtin, require_results)
|
||||
make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
if length <= 0 {
|
||||
return
|
||||
}
|
||||
@@ -135,7 +135,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
|
||||
}
|
||||
|
||||
@(builtin, require_results)
|
||||
make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
make_soa_slice :: proc($T: typeid/#soa[]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
return make_soa_aligned(T, length, align_of(E), allocator, loc)
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ make_soa :: proc{
|
||||
|
||||
|
||||
@builtin
|
||||
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
||||
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
||||
if array == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -183,7 +183,7 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_locat
|
||||
}
|
||||
|
||||
@builtin
|
||||
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
||||
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {
|
||||
if array == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -194,12 +194,12 @@ non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #cal
|
||||
}
|
||||
|
||||
@builtin
|
||||
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
return _reserve_soa(array, capacity, true, loc)
|
||||
}
|
||||
|
||||
@builtin
|
||||
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
return _reserve_soa(array, capacity, false, loc)
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ into_dynamic_soa :: proc(array: $T/#soa[]$E) -> #soa[dynamic]E {
|
||||
// Note: If you the elements to remain in their order, use `ordered_remove_soa`.
|
||||
// Note: If the index is out of bounds, this procedure will panic.
|
||||
@builtin
|
||||
unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #caller_location) #no_bounds_check {
|
||||
unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) #no_bounds_check {
|
||||
bounds_check_error_loc(loc, index, len(array))
|
||||
if index+1 < len(array) {
|
||||
ti := type_info_of(typeid_of(T))
|
||||
@@ -512,7 +512,7 @@ unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #cal
|
||||
// Note: If you the elements do not have to remain in their order, prefer `unordered_remove_soa`.
|
||||
// Note: If the index is out of bounds, this procedure will panic.
|
||||
@builtin
|
||||
ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, index: int, loc := #caller_location) #no_bounds_check {
|
||||
ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) #no_bounds_check {
|
||||
bounds_check_error_loc(loc, index, len(array))
|
||||
if index+1 < len(array) {
|
||||
ti := type_info_of(typeid_of(T))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package runtime
|
||||
|
||||
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
switch mode {
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
return nil, .Out_Of_Memory
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//+private
|
||||
//+build linux, darwin, freebsd, openbsd, netbsd, haiku
|
||||
//+no-instrumentation
|
||||
#+private
|
||||
#+build linux, darwin, freebsd, openbsd, netbsd, haiku
|
||||
#+no-instrumentation
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//+private
|
||||
//+build wasm32, wasm64p32
|
||||
//+no-instrumentation
|
||||
#+private
|
||||
#+build wasm32, wasm64p32
|
||||
#+no-instrumentation
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//+private
|
||||
//+build windows
|
||||
//+no-instrumentation
|
||||
#+private
|
||||
#+build windows
|
||||
#+no-instrumentation
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -20,25 +20,27 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
//
|
||||
|
||||
aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr, old_size: int, zero_memory := true) -> ([]byte, Allocator_Error) {
|
||||
// Not(flysand): We need to reserve enough space for alignment, which
|
||||
// includes the user data itself, the space to store the pointer to
|
||||
// allocation start, as well as the padding required to align both
|
||||
// the user data and the pointer.
|
||||
a := max(alignment, align_of(rawptr))
|
||||
space := size + a - 1
|
||||
|
||||
space := a-1 + size_of(rawptr) + size
|
||||
allocated_mem: rawptr
|
||||
|
||||
force_copy := old_ptr != nil && a > align_of(rawptr)
|
||||
force_copy := old_ptr != nil && alignment > align_of(rawptr)
|
||||
|
||||
if !force_copy && old_ptr != nil {
|
||||
if old_ptr != nil && !force_copy {
|
||||
original_old_ptr := ([^]rawptr)(old_ptr)[-1]
|
||||
allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr))
|
||||
allocated_mem = heap_resize(original_old_ptr, space)
|
||||
} else {
|
||||
allocated_mem = heap_alloc(space+size_of(rawptr), zero_memory)
|
||||
allocated_mem = heap_alloc(space, zero_memory)
|
||||
}
|
||||
aligned_mem := rawptr(([^]u8)(allocated_mem)[size_of(rawptr):])
|
||||
|
||||
ptr := uintptr(aligned_mem)
|
||||
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
|
||||
diff := int(aligned_ptr - ptr)
|
||||
if (size + diff) > space || allocated_mem == nil {
|
||||
aligned_ptr := (ptr + uintptr(a)-1) & ~(uintptr(a)-1)
|
||||
if allocated_mem == nil {
|
||||
aligned_free(old_ptr)
|
||||
aligned_free(allocated_mem)
|
||||
return nil, .Out_Of_Memory
|
||||
@@ -48,7 +50,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
([^]rawptr)(aligned_mem)[-1] = allocated_mem
|
||||
|
||||
if force_copy {
|
||||
mem_copy_non_overlapping(aligned_mem, old_ptr, old_size)
|
||||
mem_copy_non_overlapping(aligned_mem, old_ptr, min(old_size, size))
|
||||
aligned_free(old_ptr)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build orca
|
||||
//+private
|
||||
#+build orca
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build js, wasi, freestanding, essence
|
||||
//+private
|
||||
#+build js, wasi, freestanding, essence
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
_heap_alloc :: proc "contextless" (size: int, zero_memory := true) -> rawptr {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build linux, darwin, freebsd, openbsd, netbsd, haiku
|
||||
//+private
|
||||
#+build linux, darwin, freebsd, openbsd, netbsd, haiku
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
when ODIN_OS == .Darwin {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+vet !cast
|
||||
#+vet !cast
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
@@ -118,16 +118,15 @@ mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> r
|
||||
DEFAULT_ALIGNMENT :: 2*align_of(rawptr)
|
||||
|
||||
mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
if size == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if allocator.procedure == nil {
|
||||
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
|
||||
if size == 0 || allocator.procedure == nil{
|
||||
return nil, nil
|
||||
}
|
||||
return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc)
|
||||
}
|
||||
|
||||
mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
|
||||
if size == 0 || allocator.procedure == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -135,6 +134,7 @@ mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, a
|
||||
}
|
||||
|
||||
mem_alloc_non_zeroed :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
|
||||
if size == 0 || allocator.procedure == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -174,6 +174,7 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle
|
||||
}
|
||||
|
||||
_mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, should_zero: bool, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
|
||||
if allocator.procedure == nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -215,9 +216,11 @@ _mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignmen
|
||||
}
|
||||
|
||||
mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
|
||||
return _mem_resize(ptr, old_size, new_size, alignment, allocator, true, loc)
|
||||
}
|
||||
non_zero_mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: Allocator_Error) {
|
||||
assert(is_power_of_two_int(alignment), "Alignment must be a power of two", loc)
|
||||
return _mem_resize(ptr, old_size, new_size, alignment, allocator, false, loc)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build freebsd, openbsd, netbsd
|
||||
//+private
|
||||
#+build freebsd, openbsd, netbsd
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign import libc "system:c"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build darwin
|
||||
//+private
|
||||
#+build darwin
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build freestanding
|
||||
//+private
|
||||
#+build freestanding
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
// TODO(bill): reimplement `os.write`
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build haiku
|
||||
//+private
|
||||
#+build haiku
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign import libc "system:c"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build js
|
||||
//+private
|
||||
#+build js
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign import "odin_env"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+private
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build orca
|
||||
//+private
|
||||
#+build orca
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build wasi
|
||||
//+private
|
||||
#+build wasi
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign import wasi "wasi_snapshot_preview1"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build windows
|
||||
//+private
|
||||
#+build windows
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign import kernel32 "system:Kernel32.lib"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+private
|
||||
#+private
|
||||
package runtime
|
||||
|
||||
foreign import "system:Foundation.framework"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build js
|
||||
#+build js
|
||||
package runtime
|
||||
|
||||
init_default_context_for_js: Context
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
#+build wasm32, wasm64p32
|
||||
package runtime
|
||||
|
||||
@(private="file")
|
||||
@@ -14,33 +14,57 @@ ti_uint :: struct #raw_union {
|
||||
}
|
||||
|
||||
@(link_name="__ashlti3", linkage="strong")
|
||||
__ashlti3 :: proc "contextless" (la, ha: u64, b_: u32) -> i128 {
|
||||
bits_in_dword :: size_of(u32)*8
|
||||
b := u32(b_)
|
||||
__ashlti3 :: proc "contextless" (a: i128, b: u32) -> i128 {
|
||||
bits :: 64
|
||||
|
||||
input, result: ti_int
|
||||
input.lo, input.hi = la, ha
|
||||
if b & bits_in_dword != 0 {
|
||||
input: ti_int = ---
|
||||
result: ti_int = ---
|
||||
input.all = a
|
||||
if b & bits != 0 {
|
||||
result.lo = 0
|
||||
result.hi = input.lo << (b-bits_in_dword)
|
||||
result.hi = input.lo << (b-bits)
|
||||
} else {
|
||||
if b == 0 {
|
||||
return input.all
|
||||
return a
|
||||
}
|
||||
result.lo = input.lo<<b
|
||||
result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b))
|
||||
result.hi = (input.hi<<b) | (input.lo>>(bits-b))
|
||||
}
|
||||
return result.all
|
||||
}
|
||||
|
||||
__ashlti3_unsigned :: proc "contextless" (a: u128, b: u32) -> u128 {
|
||||
return cast(u128)__ashlti3(cast(i128)a, b)
|
||||
}
|
||||
|
||||
@(link_name="__mulddi3", linkage="strong")
|
||||
__mulddi3 :: proc "contextless" (a, b: u64) -> i128 {
|
||||
r: ti_int
|
||||
bits :: 32
|
||||
|
||||
mask :: ~u64(0) >> bits
|
||||
r.lo = (a & mask) * (b & mask)
|
||||
t := r.lo >> bits
|
||||
r.lo &= mask
|
||||
t += (a >> bits) * (b & mask)
|
||||
r.lo += (t & mask) << bits
|
||||
r.hi = t >> bits
|
||||
t = r.lo >> bits
|
||||
r.lo &= mask
|
||||
t += (b >> bits) * (a & mask)
|
||||
r.lo += (t & mask) << bits
|
||||
r.hi += t >> bits
|
||||
r.hi += (a >> bits) * (b >> bits)
|
||||
return r.all
|
||||
}
|
||||
|
||||
@(link_name="__multi3", linkage="strong")
|
||||
__multi3 :: proc "contextless" (la, ha, lb, hb: u64) -> i128 {
|
||||
__multi3 :: proc "contextless" (a, b: i128) -> i128 {
|
||||
x, y, r: ti_int
|
||||
|
||||
x.lo, x.hi = la, ha
|
||||
y.lo, y.hi = lb, hb
|
||||
r.all = i128(x.lo * y.lo) // TODO this is incorrect
|
||||
x.all = a
|
||||
y.all = b
|
||||
r.all = __mulddi3(x.lo, y.lo)
|
||||
r.hi += x.hi*y.lo + x.lo*y.hi
|
||||
return r.all
|
||||
}
|
||||
@@ -54,18 +78,16 @@ udivti3 :: proc "c" (la, ha, lb, hb: u64) -> u128 {
|
||||
}
|
||||
|
||||
@(link_name="__lshrti3", linkage="strong")
|
||||
__lshrti3 :: proc "c" (la, ha: u64, b: u32) -> i128 {
|
||||
bits :: size_of(u32)*8
|
||||
__lshrti3 :: proc "c" (a: i128, b: u32) -> i128 {
|
||||
bits :: 64
|
||||
|
||||
input, result: ti_int
|
||||
input.lo = la
|
||||
input.hi = ha
|
||||
|
||||
input.all = a
|
||||
if b & bits != 0 {
|
||||
result.hi = 0
|
||||
result.lo = input.hi >> (b - bits)
|
||||
} else if b == 0 {
|
||||
return input.all
|
||||
return a
|
||||
} else {
|
||||
result.hi = input.hi >> b
|
||||
result.lo = (input.hi << (bits - b)) | (input.lo >> b)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private
|
||||
//+no-instrumentation
|
||||
#+private
|
||||
#+no-instrumentation
|
||||
package runtime
|
||||
|
||||
foreign import kernel32 "system:Kernel32.lib"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private
|
||||
//+no-instrumentation
|
||||
#+private
|
||||
#+no-instrumentation
|
||||
package runtime
|
||||
|
||||
@require foreign import "system:int64.lib"
|
||||
|
||||
34
base/runtime/thread_management.odin
Normal file
34
base/runtime/thread_management.odin
Normal file
@@ -0,0 +1,34 @@
|
||||
package runtime
|
||||
|
||||
Thread_Local_Cleaner :: #type proc "odin" ()
|
||||
|
||||
@(private="file")
|
||||
thread_local_cleaners: [8]Thread_Local_Cleaner
|
||||
|
||||
// Add a procedure that will be run at the end of a thread for the purpose of
|
||||
// deallocating state marked as `thread_local`.
|
||||
//
|
||||
// Intended to be called in an `init` procedure of a package with
|
||||
// dynamically-allocated memory that is stored in `thread_local` variables.
|
||||
add_thread_local_cleaner :: proc "contextless" (p: Thread_Local_Cleaner) {
|
||||
for &v in thread_local_cleaners {
|
||||
if v == nil {
|
||||
v = p
|
||||
return
|
||||
}
|
||||
}
|
||||
panic_contextless("There are no more thread-local cleaner slots available.")
|
||||
}
|
||||
|
||||
// Run all of the thread-local cleaner procedures.
|
||||
//
|
||||
// Intended to be called by the internals of a threading API at the end of a
|
||||
// thread's lifetime.
|
||||
run_thread_local_cleaners :: proc "odin" () {
|
||||
for p in thread_local_cleaners {
|
||||
if p == nil {
|
||||
break
|
||||
}
|
||||
p()
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build wasm32, wasm64p32
|
||||
#+build wasm32, wasm64p32
|
||||
package runtime
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
19
ci/build_linux_static.sh
Executable file
19
ci/build_linux_static.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env sh
|
||||
# Intended for use in Alpine containers, see the "nightly" Github action for a list of dependencies
|
||||
|
||||
CXX="clang++-18"
|
||||
LLVM_CONFIG="llvm-config-18"
|
||||
|
||||
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
|
||||
|
||||
CPPFLAGS="-DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
|
||||
CXXFLAGS="-std=c++14 $($LLVM_CONFIG --cxxflags --ldflags)"
|
||||
|
||||
LDFLAGS="-static -lm -lzstd -lz -lffi -pthread -ldl -fuse-ld=mold"
|
||||
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --link-static --ldflags --libs --system-libs --libfiles)"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath=\$ORIGIN"
|
||||
|
||||
EXTRAFLAGS="-DNIGHTLY -O3"
|
||||
|
||||
set -x
|
||||
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
import sys
|
||||
from zipfile import ZipFile, ZIP_DEFLATED
|
||||
from b2sdk.v2 import InMemoryAccountInfo, B2Api
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
|
||||
UPLOAD_FOLDER = "nightly/"
|
||||
@@ -22,7 +22,7 @@ def auth() -> bool:
|
||||
pass # Not yet authenticated
|
||||
|
||||
err = b2_api.authorize_account("production", application_key_id, application_key)
|
||||
return err == None
|
||||
return err is None
|
||||
|
||||
def get_bucket():
|
||||
if not auth(): sys.exit(1)
|
||||
@@ -32,30 +32,35 @@ def remove_prefix(text: str, prefix: str) -> str:
|
||||
return text[text.startswith(prefix) and len(prefix):]
|
||||
|
||||
def create_and_upload_artifact_zip(platform: str, artifact: str) -> int:
|
||||
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
destination_zip_name = "odin-{}-nightly+{}.zip".format(platform, now.strftime("%Y-%m-%d"))
|
||||
now = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
source_zip_name = artifact
|
||||
if not artifact.endswith(".zip"):
|
||||
print(f"Creating archive {destination_zip_name} from {artifact} and uploading to {bucket_name}")
|
||||
source_archive: str
|
||||
destination_name = f'odin-{platform}-nightly+{now.strftime("%Y-%m-%d")}'
|
||||
|
||||
source_zip_name = destination_zip_name
|
||||
with ZipFile(source_zip_name, mode='w', compression=ZIP_DEFLATED, compresslevel=9) as z:
|
||||
if platform.startswith("linux") or platform.startswith("macos"):
|
||||
destination_name += ".tar.gz"
|
||||
source_archive = artifact
|
||||
else:
|
||||
destination_name += ".zip"
|
||||
source_archive = destination_name
|
||||
|
||||
print(f"Creating archive {destination_name} from {artifact} and uploading to {bucket_name}")
|
||||
with ZipFile(source_archive, mode='w', compression=ZIP_DEFLATED, compresslevel=9) as z:
|
||||
for root, directory, filenames in os.walk(artifact):
|
||||
for file in filenames:
|
||||
file_path = os.path.join(root, file)
|
||||
zip_path = os.path.join("dist", os.path.relpath(file_path, artifact))
|
||||
z.write(file_path, zip_path)
|
||||
|
||||
if not os.path.exists(source_zip_name):
|
||||
print(f"Error: Newly created ZIP archive {source_zip_name} not found.")
|
||||
return 1
|
||||
if not os.path.exists(source_archive):
|
||||
print(f"Error: archive {source_archive} not found.")
|
||||
return 1
|
||||
|
||||
print("Uploading {} to {}".format(source_zip_name, UPLOAD_FOLDER + destination_zip_name))
|
||||
print("Uploading {} to {}".format(source_archive, UPLOAD_FOLDER + destination_name))
|
||||
bucket = get_bucket()
|
||||
res = bucket.upload_local_file(
|
||||
source_zip_name, # Local file to upload
|
||||
"nightly/" + destination_zip_name, # B2 destination path
|
||||
source_archive, # Local file to upload
|
||||
"nightly/" + destination_name, # B2 destination path
|
||||
)
|
||||
return 0
|
||||
|
||||
@@ -65,8 +70,8 @@ def prune_artifacts():
|
||||
bucket = get_bucket()
|
||||
for file, _ in bucket.ls(UPLOAD_FOLDER, latest_only=False):
|
||||
# Timestamp is in milliseconds
|
||||
date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
now = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
date = datetime.fromtimestamp(file.upload_timestamp / 1_000.0, tz=timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
now = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
delta = now - date
|
||||
|
||||
if delta.days > int(days_to_keep):
|
||||
@@ -100,7 +105,7 @@ def update_nightly_json():
|
||||
'sizeInBytes': size,
|
||||
})
|
||||
|
||||
now = datetime.utcnow().isoformat()
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
nightly = json.dumps({
|
||||
'last_updated' : now,
|
||||
@@ -137,4 +142,4 @@ if __name__ == "__main__":
|
||||
|
||||
elif command == "json":
|
||||
res = update_nightly_json()
|
||||
sys.exit(res)
|
||||
sys.exit(res)
|
||||
|
||||
@@ -144,6 +144,9 @@ buffer_grow :: proc(b: ^Buffer, n: int, loc := #caller_location) {
|
||||
}
|
||||
|
||||
buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int, loc := #caller_location) -> (n: int, err: io.Error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
b.last_read = .Invalid
|
||||
if offset < 0 {
|
||||
err = .Invalid_Offset
|
||||
@@ -246,10 +249,13 @@ buffer_read_ptr :: proc(b: ^Buffer, ptr: rawptr, size: int) -> (n: int, err: io.
|
||||
}
|
||||
|
||||
buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
b.last_read = .Invalid
|
||||
|
||||
if uint(offset) >= len(b.buf) {
|
||||
err = .Invalid_Offset
|
||||
err = .EOF
|
||||
return
|
||||
}
|
||||
n = copy(p, b.buf[offset:])
|
||||
@@ -310,6 +316,27 @@ buffer_unread_rune :: proc(b: ^Buffer) -> io.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
buffer_seek :: proc(b: ^Buffer, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
|
||||
abs: i64
|
||||
switch whence {
|
||||
case .Start:
|
||||
abs = offset
|
||||
case .Current:
|
||||
abs = i64(b.off) + offset
|
||||
case .End:
|
||||
abs = i64(len(b.buf)) + offset
|
||||
case:
|
||||
return 0, .Invalid_Whence
|
||||
}
|
||||
|
||||
abs_int := int(abs)
|
||||
if abs_int < 0 {
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
b.last_read = .Invalid
|
||||
b.off = abs_int
|
||||
return abs, nil
|
||||
}
|
||||
|
||||
buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) {
|
||||
i := index_byte(b.buf[b.off:], delim)
|
||||
@@ -395,14 +422,17 @@ _buffer_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offse
|
||||
return io._i64_err(buffer_write(b, p))
|
||||
case .Write_At:
|
||||
return io._i64_err(buffer_write_at(b, p, int(offset)))
|
||||
case .Seek:
|
||||
n, err = buffer_seek(b, offset, whence)
|
||||
return
|
||||
case .Size:
|
||||
n = i64(buffer_capacity(b))
|
||||
n = i64(buffer_length(b))
|
||||
return
|
||||
case .Destroy:
|
||||
buffer_destroy(b)
|
||||
return
|
||||
case .Query:
|
||||
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Size, .Destroy})
|
||||
return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Destroy, .Query})
|
||||
}
|
||||
return 0, .Empty
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ Inputs:
|
||||
Returns:
|
||||
- index: The index of the byte `c`, or -1 if it was not found.
|
||||
*/
|
||||
index_byte :: proc(s: []byte, c: byte) -> (index: int) #no_bounds_check {
|
||||
index_byte :: proc "contextless" (s: []byte, c: byte) -> (index: int) #no_bounds_check {
|
||||
i, l := 0, len(s)
|
||||
|
||||
// Guard against small strings. On modern systems, it is ALWAYS
|
||||
@@ -469,18 +469,16 @@ Inputs:
|
||||
Returns:
|
||||
- index: The index of the byte `c`, or -1 if it was not found.
|
||||
*/
|
||||
last_index_byte :: proc(s: []byte, c: byte) -> int #no_bounds_check {
|
||||
last_index_byte :: proc "contextless" (s: []byte, c: byte) -> int #no_bounds_check {
|
||||
i := len(s)
|
||||
|
||||
// Guard against small strings. On modern systems, it is ALWAYS
|
||||
// worth vectorizing assuming there is a hardware vector unit, and
|
||||
// the data size is large enough.
|
||||
if i < SIMD_REG_SIZE_128 {
|
||||
if i > 0 { // Handle s == nil.
|
||||
for /**/; i >= 0; i -= 1 {
|
||||
if s[i] == c {
|
||||
return i
|
||||
}
|
||||
#reverse for ch, j in s {
|
||||
if ch == c {
|
||||
return j
|
||||
}
|
||||
}
|
||||
return -1
|
||||
|
||||
@@ -9,10 +9,11 @@ Reader :: struct {
|
||||
prev_rune: int, // previous reading index of rune or < 0
|
||||
}
|
||||
|
||||
reader_init :: proc(r: ^Reader, s: []byte) {
|
||||
reader_init :: proc(r: ^Reader, s: []byte) -> io.Stream {
|
||||
r.s = s
|
||||
r.i = 0
|
||||
r.prev_rune = -1
|
||||
return reader_to_stream(r)
|
||||
}
|
||||
|
||||
reader_to_stream :: proc(r: ^Reader) -> (s: io.Stream) {
|
||||
@@ -33,6 +34,9 @@ reader_size :: proc(r: ^Reader) -> i64 {
|
||||
}
|
||||
|
||||
reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if r.i >= i64(len(r.s)) {
|
||||
return 0, .EOF
|
||||
}
|
||||
@@ -42,6 +46,9 @@ reader_read :: proc(r: ^Reader, p: []byte) -> (n: int, err: io.Error) {
|
||||
return
|
||||
}
|
||||
reader_read_at :: proc(r: ^Reader, p: []byte, off: i64) -> (n: int, err: io.Error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if off < 0 {
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
@@ -97,7 +104,6 @@ reader_unread_rune :: proc(r: ^Reader) -> io.Error {
|
||||
return nil
|
||||
}
|
||||
reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
|
||||
r.prev_rune = -1
|
||||
abs: i64
|
||||
switch whence {
|
||||
case .Start:
|
||||
@@ -114,6 +120,7 @@ reader_seek :: proc(r: ^Reader, offset: i64, whence: io.Seek_From) -> (i64, io.E
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
r.i = abs
|
||||
r.prev_rune = -1
|
||||
return abs, nil
|
||||
}
|
||||
reader_write_to :: proc(r: ^Reader, w: io.Writer) -> (n: i64, err: io.Error) {
|
||||
|
||||
@@ -98,6 +98,14 @@ when ODIN_OS == .Haiku {
|
||||
ERANGE :: B_POSIX_ERROR_BASE + 17
|
||||
}
|
||||
|
||||
when ODIN_OS == .JS {
|
||||
_ :: libc
|
||||
_get_errno :: proc "c" () -> ^int {
|
||||
@(static) errno: int
|
||||
return &errno
|
||||
}
|
||||
}
|
||||
|
||||
// Odin has no way to make an identifier "errno" behave as a function call to
|
||||
// read the value, or to produce an lvalue such that you can assign a different
|
||||
// error value to errno. To work around this, just expose it as a function like
|
||||
|
||||
@@ -89,6 +89,30 @@ when ODIN_OS == .Linux {
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_OS == .JS {
|
||||
fpos_t :: struct #raw_union { _: [16]char, _: longlong, _: double, }
|
||||
|
||||
_IOFBF :: 0
|
||||
_IOLBF :: 1
|
||||
_IONBF :: 2
|
||||
|
||||
BUFSIZ :: 1024
|
||||
|
||||
EOF :: int(-1)
|
||||
|
||||
FOPEN_MAX :: 1000
|
||||
|
||||
FILENAME_MAX :: 4096
|
||||
|
||||
L_tmpnam :: 20
|
||||
|
||||
SEEK_SET :: 0
|
||||
SEEK_CUR :: 1
|
||||
SEEK_END :: 2
|
||||
|
||||
TMP_MAX :: 308915776
|
||||
}
|
||||
|
||||
when ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
|
||||
fpos_t :: distinct i64
|
||||
|
||||
@@ -368,7 +392,7 @@ to_stream :: proc(file: ^FILE) -> io.Stream {
|
||||
return 0, .Empty
|
||||
|
||||
case .Query:
|
||||
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size })
|
||||
return io.query_utility({ .Close, .Flush, .Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Query })
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ when ODIN_OS == .Windows {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@(require)
|
||||
import "base:runtime"
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
RAND_MAX :: 0x7fff
|
||||
|
||||
@@ -145,6 +148,10 @@ aligned_alloc :: #force_inline proc "c" (alignment, size: size_t) -> rawptr {
|
||||
_aligned_malloc :: proc(size, alignment: size_t) -> rawptr ---
|
||||
}
|
||||
return _aligned_malloc(size=size, alignment=alignment)
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
context = runtime.default_context()
|
||||
data, _ := runtime.mem_alloc_bytes(auto_cast size, auto_cast alignment)
|
||||
return raw_data(data)
|
||||
} else {
|
||||
foreign libc {
|
||||
aligned_alloc :: proc(alignment, size: size_t) -> rawptr ---
|
||||
@@ -160,6 +167,9 @@ aligned_free :: #force_inline proc "c" (ptr: rawptr) {
|
||||
_aligned_free :: proc(ptr: rawptr) ---
|
||||
}
|
||||
_aligned_free(ptr)
|
||||
} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 {
|
||||
context = runtime.default_context()
|
||||
runtime.mem_free(ptr)
|
||||
} else {
|
||||
free(ptr)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ when ODIN_OS == .Windows {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
// 7.24.2 Copying functions
|
||||
memcpy :: proc(s1, s2: rawptr, n: size_t) -> rawptr ---
|
||||
|
||||
@@ -45,7 +45,7 @@ when ODIN_OS == .Windows {
|
||||
}
|
||||
}
|
||||
|
||||
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
|
||||
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku || ODIN_OS == .JS {
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
// 7.27.2 Time manipulation functions
|
||||
@@ -79,7 +79,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS =
|
||||
} else {
|
||||
@(private) LDIFFTIME :: "difftime"
|
||||
@(private) LMKTIME :: "mktime"
|
||||
@(private) LTIME :: "ltime"
|
||||
@(private) LTIME :: "time"
|
||||
@(private) LCTIME :: "ctime"
|
||||
@(private) LGMTIME :: "gmtime"
|
||||
@(private) LLOCALTIME :: "localtime"
|
||||
|
||||
@@ -14,7 +14,7 @@ when ODIN_OS == .Windows {
|
||||
wctrans_t :: distinct wchar_t
|
||||
wctype_t :: distinct ushort
|
||||
|
||||
} else when ODIN_OS == .Linux {
|
||||
} else when ODIN_OS == .Linux || ODIN_OS == .JS {
|
||||
wctrans_t :: distinct intptr_t
|
||||
wctype_t :: distinct ulong
|
||||
|
||||
|
||||
90
core/compress/gzip/doc.odin
Normal file
90
core/compress/gzip/doc.odin
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-3 license.
|
||||
|
||||
List of contributors:
|
||||
Jeroen van Rijn: Initial implementation.
|
||||
Ginger Bill: Cosmetic changes.
|
||||
|
||||
A small GZIP implementation as an example.
|
||||
*/
|
||||
|
||||
/*
|
||||
Example:
|
||||
import "core:bytes"
|
||||
import "core:os"
|
||||
import "core:compress"
|
||||
import "core:fmt"
|
||||
|
||||
// Small GZIP file with fextra, fname and fcomment present.
|
||||
@private
|
||||
TEST: []u8 = {
|
||||
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
|
||||
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
|
||||
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
|
||||
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
|
||||
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
|
||||
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
// Set up output buffer.
|
||||
buf := bytes.Buffer{}
|
||||
|
||||
stdout :: proc(s: string) {
|
||||
os.write_string(os.stdout, s)
|
||||
}
|
||||
stderr :: proc(s: string) {
|
||||
os.write_string(os.stderr, s)
|
||||
}
|
||||
|
||||
args := os.args
|
||||
|
||||
if len(args) < 2 {
|
||||
stderr("No input file specified.\n")
|
||||
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
|
||||
if err == nil {
|
||||
stdout("Displaying test vector: ")
|
||||
stdout(bytes.buffer_to_string(&buf))
|
||||
stdout("\n")
|
||||
} else {
|
||||
fmt.printf("gzip.load returned %v\n", err)
|
||||
}
|
||||
bytes.buffer_destroy(&buf)
|
||||
os.exit(0)
|
||||
}
|
||||
|
||||
// The rest are all files.
|
||||
args = args[1:]
|
||||
err: Error
|
||||
|
||||
for file in args {
|
||||
if file == "-" {
|
||||
// Read from stdin
|
||||
s := os.stream_from_handle(os.stdin)
|
||||
ctx := &compress.Context_Stream_Input{
|
||||
input = s,
|
||||
}
|
||||
err = load(ctx, &buf)
|
||||
} else {
|
||||
err = load(file, &buf)
|
||||
}
|
||||
if err != nil {
|
||||
if err != E_General.File_Not_Found {
|
||||
stderr("File not found: ")
|
||||
stderr(file)
|
||||
stderr("\n")
|
||||
os.exit(1)
|
||||
}
|
||||
stderr("GZIP returned an error.\n")
|
||||
bytes.buffer_destroy(&buf)
|
||||
os.exit(2)
|
||||
}
|
||||
stdout(bytes.buffer_to_string(&buf))
|
||||
}
|
||||
bytes.buffer_destroy(&buf)
|
||||
}
|
||||
*/
|
||||
package compress_gzip
|
||||
@@ -1,89 +0,0 @@
|
||||
//+build ignore
|
||||
package compress_gzip
|
||||
|
||||
/*
|
||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-3 license.
|
||||
|
||||
List of contributors:
|
||||
Jeroen van Rijn: Initial implementation.
|
||||
Ginger Bill: Cosmetic changes.
|
||||
|
||||
A small GZIP implementation as an example.
|
||||
*/
|
||||
|
||||
import "core:bytes"
|
||||
import "core:os"
|
||||
import "core:compress"
|
||||
import "core:fmt"
|
||||
|
||||
// Small GZIP file with fextra, fname and fcomment present.
|
||||
@private
|
||||
TEST: []u8 = {
|
||||
0x1f, 0x8b, 0x08, 0x1c, 0xcb, 0x3b, 0x3a, 0x5a,
|
||||
0x02, 0x03, 0x07, 0x00, 0x61, 0x62, 0x03, 0x00,
|
||||
0x63, 0x64, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x00, 0x54, 0x68, 0x69, 0x73,
|
||||
0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x2b, 0x48,
|
||||
0xac, 0xcc, 0xc9, 0x4f, 0x4c, 0x01, 0x00, 0x15,
|
||||
0x6a, 0x2c, 0x42, 0x07, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
// Set up output buffer.
|
||||
buf := bytes.Buffer{}
|
||||
|
||||
stdout :: proc(s: string) {
|
||||
os.write_string(os.stdout, s)
|
||||
}
|
||||
stderr :: proc(s: string) {
|
||||
os.write_string(os.stderr, s)
|
||||
}
|
||||
|
||||
args := os.args
|
||||
|
||||
if len(args) < 2 {
|
||||
stderr("No input file specified.\n")
|
||||
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
|
||||
if err == nil {
|
||||
stdout("Displaying test vector: ")
|
||||
stdout(bytes.buffer_to_string(&buf))
|
||||
stdout("\n")
|
||||
} else {
|
||||
fmt.printf("gzip.load returned %v\n", err)
|
||||
}
|
||||
bytes.buffer_destroy(&buf)
|
||||
os.exit(0)
|
||||
}
|
||||
|
||||
// The rest are all files.
|
||||
args = args[1:]
|
||||
err: Error
|
||||
|
||||
for file in args {
|
||||
if file == "-" {
|
||||
// Read from stdin
|
||||
s := os.stream_from_handle(os.stdin)
|
||||
ctx := &compress.Context_Stream_Input{
|
||||
input = s,
|
||||
}
|
||||
err = load(ctx, &buf)
|
||||
} else {
|
||||
err = load(file, &buf)
|
||||
}
|
||||
if err != nil {
|
||||
if err != E_General.File_Not_Found {
|
||||
stderr("File not found: ")
|
||||
stderr(file)
|
||||
stderr("\n")
|
||||
os.exit(1)
|
||||
}
|
||||
stderr("GZIP returned an error.\n")
|
||||
bytes.buffer_destroy(&buf)
|
||||
os.exit(2)
|
||||
}
|
||||
stdout(bytes.buffer_to_string(&buf))
|
||||
}
|
||||
bytes.buffer_destroy(&buf)
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
which is an English word model.
|
||||
*/
|
||||
|
||||
// package shoco is an implementation of the shoco short string compressor
|
||||
package compress_shoco
|
||||
|
||||
DEFAULT_MODEL :: Shoco_Model {
|
||||
@@ -145,4 +144,4 @@ DEFAULT_MODEL :: Shoco_Model {
|
||||
{ 0xc0000000, 2, 4, { 25, 22, 19, 16, 16, 16, 16, 16 }, { 15, 7, 7, 7, 0, 0, 0, 0 }, 0xe0, 0xc0 },
|
||||
{ 0xe0000000, 4, 8, { 23, 19, 15, 11, 8, 5, 2, 0 }, { 31, 15, 15, 15, 7, 7, 7, 3 }, 0xf0, 0xe0 },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
An implementation of [shoco](https://github.com/Ed-von-Schleck/shoco) by Christian Schramm.
|
||||
*/
|
||||
|
||||
// package shoco is an implementation of the shoco short string compressor
|
||||
// package shoco is an implementation of the shoco short string compressor.
|
||||
package compress_shoco
|
||||
|
||||
import "base:intrinsics"
|
||||
@@ -308,4 +308,4 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
|
||||
resize(&buf, length) or_return
|
||||
return buf[:length], result
|
||||
}
|
||||
compress :: proc{compress_string_to_buffer, compress_string}
|
||||
compress :: proc{compress_string_to_buffer, compress_string}
|
||||
|
||||
50
core/compress/zlib/doc.odin
Normal file
50
core/compress/zlib/doc.odin
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-3 license.
|
||||
|
||||
List of contributors:
|
||||
Jeroen van Rijn: Initial implementation.
|
||||
|
||||
An example of how to use `zlib.inflate`.
|
||||
*/
|
||||
|
||||
/*
|
||||
Example:
|
||||
package main
|
||||
|
||||
import "core:bytes"
|
||||
import "core:fmt"
|
||||
|
||||
main :: proc() {
|
||||
ODIN_DEMO := []u8{
|
||||
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
|
||||
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
|
||||
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
|
||||
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
|
||||
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
|
||||
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
|
||||
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
|
||||
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
|
||||
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
|
||||
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
|
||||
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
|
||||
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
|
||||
159, 150, 133, 125,
|
||||
}
|
||||
OUTPUT_SIZE :: 432
|
||||
|
||||
buf: bytes.Buffer
|
||||
|
||||
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
|
||||
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
|
||||
defer bytes.buffer_destroy(&buf)
|
||||
|
||||
if err != nil {
|
||||
fmt.printf("\nError: %v\n", err)
|
||||
}
|
||||
s := bytes.buffer_to_string(&buf)
|
||||
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
|
||||
assert(len(s) == OUTPUT_SIZE)
|
||||
}
|
||||
*/
|
||||
package compress_zlib
|
||||
@@ -1,47 +0,0 @@
|
||||
//+build ignore
|
||||
package compress_zlib
|
||||
|
||||
/*
|
||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-3 license.
|
||||
|
||||
List of contributors:
|
||||
Jeroen van Rijn: Initial implementation.
|
||||
|
||||
An example of how to use `zlib.inflate`.
|
||||
*/
|
||||
|
||||
import "core:bytes"
|
||||
import "core:fmt"
|
||||
|
||||
main :: proc() {
|
||||
ODIN_DEMO := []u8{
|
||||
120, 218, 101, 144, 65, 110, 131, 48, 16, 69, 215, 246, 41, 190, 44, 69, 73, 32, 148, 182,
|
||||
75, 75, 28, 32, 251, 46, 217, 88, 238, 0, 86, 192, 32, 219, 36, 170, 170, 172, 122, 137,
|
||||
238, 122, 197, 30, 161, 70, 162, 20, 81, 203, 139, 25, 191, 255, 191, 60, 51, 40, 125, 81,
|
||||
53, 33, 144, 15, 156, 155, 110, 232, 93, 128, 208, 189, 35, 89, 117, 65, 112, 222, 41, 99,
|
||||
33, 37, 6, 215, 235, 195, 17, 239, 156, 197, 170, 118, 170, 131, 44, 32, 82, 164, 72, 240,
|
||||
253, 245, 249, 129, 12, 185, 224, 76, 105, 61, 118, 99, 171, 66, 239, 38, 193, 35, 103, 85,
|
||||
172, 66, 127, 33, 139, 24, 244, 235, 141, 49, 204, 223, 76, 208, 205, 204, 166, 7, 173, 60,
|
||||
97, 159, 238, 37, 214, 41, 105, 129, 167, 5, 102, 27, 152, 173, 97, 178, 129, 73, 129, 231,
|
||||
5, 230, 27, 152, 175, 225, 52, 192, 127, 243, 170, 157, 149, 18, 121, 142, 115, 109, 227, 122,
|
||||
64, 87, 114, 111, 161, 49, 182, 6, 181, 158, 162, 226, 206, 167, 27, 215, 246, 48, 56, 99,
|
||||
67, 117, 16, 47, 13, 45, 35, 151, 98, 231, 75, 1, 173, 90, 61, 101, 146, 71, 136, 244,
|
||||
170, 218, 145, 176, 123, 45, 173, 56, 113, 134, 191, 51, 219, 78, 235, 95, 28, 249, 253, 7,
|
||||
159, 150, 133, 125,
|
||||
}
|
||||
OUTPUT_SIZE :: 432
|
||||
|
||||
buf: bytes.Buffer
|
||||
|
||||
// We can pass ", true" to inflate a raw DEFLATE stream instead of a ZLIB wrapped one.
|
||||
err := inflate(input=ODIN_DEMO, buf=&buf, expected_output_size=OUTPUT_SIZE)
|
||||
defer bytes.buffer_destroy(&buf)
|
||||
|
||||
if err != nil {
|
||||
fmt.printf("\nError: %v\n", err)
|
||||
}
|
||||
s := bytes.buffer_to_string(&buf)
|
||||
fmt.printf("Input: %v bytes, output (%v bytes):\n%v\n", len(ODIN_DEMO), len(s), s)
|
||||
assert(len(s) == OUTPUT_SIZE)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
//+vet !using-param
|
||||
#+vet !using-param
|
||||
package compress_zlib
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package container_dynamic_bit_array
|
||||
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
|
||||
@@ -18,7 +19,7 @@ NUM_BITS :: 64
|
||||
Bit_Array :: struct {
|
||||
bits: [dynamic]u64,
|
||||
bias: int,
|
||||
max_index: int,
|
||||
length: int,
|
||||
free_pointer: bool,
|
||||
}
|
||||
|
||||
@@ -52,9 +53,9 @@ Returns:
|
||||
*/
|
||||
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
|
||||
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
|
||||
if index > it.array.max_index { return false, 0, false }
|
||||
if index >= it.array.length + it.array.bias { return false, 0, false }
|
||||
|
||||
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||
word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
|
||||
set = (word >> it.bit_idx & 1) == 1
|
||||
|
||||
it.bit_idx += 1
|
||||
@@ -106,22 +107,22 @@ Returns:
|
||||
*/
|
||||
@(private="file")
|
||||
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
|
||||
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||
word := it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
|
||||
when ! ITERATE_SET_BITS { word = ~word }
|
||||
|
||||
// If the word is empty or we have already gone over all the bits in it,
|
||||
// b.bit_idx is greater than the index of any set bit in the word,
|
||||
// meaning that word >> b.bit_idx == 0.
|
||||
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
|
||||
for it.word_idx < builtin.len(it.array.bits) && word >> it.bit_idx == 0 {
|
||||
it.word_idx += 1
|
||||
it.bit_idx = 0
|
||||
word = it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
|
||||
word = it.array.bits[it.word_idx] if builtin.len(it.array.bits) > it.word_idx else 0
|
||||
when ! ITERATE_SET_BITS { word = ~word }
|
||||
}
|
||||
|
||||
// If we are iterating the set bits, reaching the end of the array means we have no more bits to check
|
||||
when ITERATE_SET_BITS {
|
||||
if it.word_idx >= len(it.array.bits) {
|
||||
if it.word_idx >= builtin.len(it.array.bits) {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
@@ -135,7 +136,7 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
|
||||
it.bit_idx = 0
|
||||
it.word_idx += 1
|
||||
}
|
||||
return index, index <= it.array.max_index
|
||||
return index, index < it.array.length + it.array.bias
|
||||
}
|
||||
/*
|
||||
Gets the state of a bit in the bit-array
|
||||
@@ -160,7 +161,7 @@ get :: proc(ba: ^Bit_Array, #any_int index: uint) -> (res: bool, ok: bool) #opti
|
||||
If we `get` a bit that doesn't fit in the Bit Array, it's naturally `false`.
|
||||
This early-out prevents unnecessary resizing.
|
||||
*/
|
||||
if leg_index + 1 > len(ba.bits) { return false, true }
|
||||
if leg_index + 1 > builtin.len(ba.bits) { return false, true }
|
||||
|
||||
val := u64(1 << uint(bit_index))
|
||||
res = ba.bits[leg_index] & val == val
|
||||
@@ -208,7 +209,7 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator
|
||||
|
||||
resize_if_needed(ba, leg_index) or_return
|
||||
|
||||
ba.max_index = max(idx, ba.max_index)
|
||||
ba.length = max(1 + idx, ba.length)
|
||||
|
||||
if set_to {
|
||||
ba.bits[leg_index] |= 1 << uint(bit_index)
|
||||
@@ -261,6 +262,9 @@ unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
|
||||
/*
|
||||
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
|
||||
|
||||
The range of bits created by this procedure is `min_index..<max_index`, and the
|
||||
array will be able to expand beyond `max_index` if needed.
|
||||
|
||||
*Allocates (`new(Bit_Array) & make(ba.bits)`)*
|
||||
|
||||
Inputs:
|
||||
@@ -275,7 +279,7 @@ create :: proc(max_index: int, min_index: int = 0, allocator := context.allocato
|
||||
context.allocator = allocator
|
||||
size_in_bits := max_index - min_index
|
||||
|
||||
if size_in_bits < 1 { return {}, false }
|
||||
if size_in_bits < 0 { return {}, false }
|
||||
|
||||
legs := size_in_bits >> INDEX_SHIFT
|
||||
if size_in_bits & INDEX_MASK > 0 {legs+=1}
|
||||
@@ -284,7 +288,7 @@ create :: proc(max_index: int, min_index: int = 0, allocator := context.allocato
|
||||
res = new(Bit_Array)
|
||||
res.bits = bits
|
||||
res.bias = min_index
|
||||
res.max_index = max_index
|
||||
res.length = max_index - min_index
|
||||
res.free_pointer = true
|
||||
return
|
||||
}
|
||||
@@ -299,6 +303,48 @@ clear :: proc(ba: ^Bit_Array) {
|
||||
mem.zero_slice(ba.bits[:])
|
||||
}
|
||||
/*
|
||||
Gets the length of set and unset valid bits in the Bit_Array.
|
||||
|
||||
Inputs:
|
||||
- ba: The target Bit_Array
|
||||
|
||||
Returns:
|
||||
- length: The length of valid bits.
|
||||
*/
|
||||
len :: proc(ba: ^Bit_Array) -> (length: int) {
|
||||
if ba == nil { return }
|
||||
return ba.length
|
||||
}
|
||||
/*
|
||||
Shrinks the Bit_Array's backing storage to the smallest possible size.
|
||||
|
||||
Inputs:
|
||||
- ba: The target Bit_Array
|
||||
*/
|
||||
shrink :: proc(ba: ^Bit_Array) #no_bounds_check {
|
||||
if ba == nil { return }
|
||||
legs_needed := builtin.len(ba.bits)
|
||||
for i := legs_needed - 1; i >= 0; i -= 1 {
|
||||
if ba.bits[i] == 0 {
|
||||
legs_needed -= 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if legs_needed == builtin.len(ba.bits) {
|
||||
return
|
||||
}
|
||||
ba.length = 0
|
||||
if legs_needed > 0 {
|
||||
if legs_needed > 1 {
|
||||
ba.length = (legs_needed - 1) * NUM_BITS
|
||||
}
|
||||
ba.length += NUM_BITS - int(intrinsics.count_leading_zeros(ba.bits[legs_needed - 1]))
|
||||
}
|
||||
resize(&ba.bits, legs_needed)
|
||||
builtin.shrink(&ba.bits)
|
||||
}
|
||||
/*
|
||||
Deallocates the Bit_Array and its backing storage
|
||||
|
||||
Inputs:
|
||||
@@ -321,8 +367,8 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat
|
||||
|
||||
context.allocator = allocator
|
||||
|
||||
if legs + 1 > len(ba.bits) {
|
||||
if legs + 1 > builtin.len(ba.bits) {
|
||||
resize(&ba.bits, legs + 1)
|
||||
}
|
||||
return len(ba.bits) > legs
|
||||
return builtin.len(ba.bits) > legs
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
The Bit Array can be used in several ways:
|
||||
|
||||
- By default you don't need to instantiate a Bit Array:
|
||||
|
||||
By default you don't need to instantiate a Bit Array.
|
||||
Example:
|
||||
package test
|
||||
|
||||
import "core:fmt"
|
||||
@@ -22,8 +22,8 @@ The Bit Array can be used in several ways:
|
||||
destroy(&bits)
|
||||
}
|
||||
|
||||
- A Bit Array can optionally allow for negative indices, if the minimum value was given during creation:
|
||||
|
||||
A Bit Array can optionally allow for negative indices, if the minimum value was given during creation.
|
||||
Example:
|
||||
package test
|
||||
|
||||
import "core:fmt"
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
Package list implements an intrusive doubly-linked list.
|
||||
|
||||
An intrusive container requires a `Node` to be embedded in your own structure, like this:
|
||||
|
||||
An intrusive container requires a `Node` to be embedded in your own structure, like this.
|
||||
Example:
|
||||
My_String :: struct {
|
||||
node: list.Node,
|
||||
value: string,
|
||||
}
|
||||
|
||||
Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed:
|
||||
|
||||
Embedding the members of a `list.Node` in your structure with the `using` keyword is also allowed.
|
||||
Example:
|
||||
My_String :: struct {
|
||||
using node: list.Node,
|
||||
value: string,
|
||||
}
|
||||
|
||||
Here is a full example:
|
||||
|
||||
Here is a full example.
|
||||
Example:
|
||||
package test
|
||||
|
||||
import "core:fmt"
|
||||
@@ -42,5 +42,8 @@ Here is a full example:
|
||||
value: string,
|
||||
}
|
||||
|
||||
Output:
|
||||
Hello
|
||||
World
|
||||
*/
|
||||
package container_intrusive_list
|
||||
|
||||
@@ -139,9 +139,13 @@ clear :: proc "contextless" (a: ^$A/Small_Array($N, $T)) {
|
||||
resize(a, 0)
|
||||
}
|
||||
|
||||
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) {
|
||||
n := copy(a.data[a.len:], items[:])
|
||||
a.len += n
|
||||
push_back_elems :: proc "contextless" (a: ^$A/Small_Array($N, $T), items: ..T) -> bool {
|
||||
if a.len + builtin.len(items) <= cap(a^) {
|
||||
n := copy(a.data[a.len:], items[:])
|
||||
a.len += n
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
inject_at :: proc "contextless" (a: ^$A/Small_Array($N, $T), item: T, index: int) -> bool #no_bounds_check {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes_hw_intel
|
||||
|
||||
import "core:sys/info"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes_hw_intel
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes_hw_intel
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package chacha20_simd256
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build !amd64
|
||||
#+build !amd64
|
||||
package chacha20_simd256
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -10,49 +10,48 @@ algorithm.
|
||||
WARNING: Reusing the same key + iv to seal (encrypt) multiple messages
|
||||
results in catastrophic loss of security for most algorithms.
|
||||
|
||||
```odin
|
||||
package aead_example
|
||||
Example:
|
||||
package aead_example
|
||||
|
||||
import "core:bytes"
|
||||
import "core:crypto"
|
||||
import "core:crypto/aead"
|
||||
import "core:bytes"
|
||||
import "core:crypto"
|
||||
import "core:crypto/aead"
|
||||
|
||||
main :: proc() {
|
||||
algo := aead.Algorithm.XCHACHA20POLY1305
|
||||
main :: proc() {
|
||||
algo := aead.Algorithm.XCHACHA20POLY1305
|
||||
|
||||
// The example added associated data, and plaintext.
|
||||
aad_str := "Get your ass in gear boys."
|
||||
pt_str := "They're immanetizing the Eschaton."
|
||||
// The example added associated data, and plaintext.
|
||||
aad_str := "Get your ass in gear boys."
|
||||
pt_str := "They're immanetizing the Eschaton."
|
||||
|
||||
aad := transmute([]byte)aad_str
|
||||
plaintext := transmute([]byte)pt_str
|
||||
pt_len := len(plaintext)
|
||||
aad := transmute([]byte)aad_str
|
||||
plaintext := transmute([]byte)pt_str
|
||||
pt_len := len(plaintext)
|
||||
|
||||
// Generate a random key for the purposes of illustration.
|
||||
key := make([]byte, aead.KEY_SIZES[algo])
|
||||
defer delete(key)
|
||||
crypto.rand_bytes(key)
|
||||
// Generate a random key for the purposes of illustration.
|
||||
key := make([]byte, aead.KEY_SIZES[algo])
|
||||
defer delete(key)
|
||||
crypto.rand_bytes(key)
|
||||
|
||||
// `ciphertext || tag`, is a common way data is transmitted, so
|
||||
// demonstrate that.
|
||||
buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
|
||||
defer delete(buf)
|
||||
ciphertext, tag := buf[:pt_len], buf[pt_len:]
|
||||
// `ciphertext || tag`, is a common way data is transmitted, so
|
||||
// demonstrate that.
|
||||
buf := make([]byte, pt_len + aead.TAG_SIZES[algo])
|
||||
defer delete(buf)
|
||||
ciphertext, tag := buf[:pt_len], buf[pt_len:]
|
||||
|
||||
// Seal the AAD + Plaintext.
|
||||
iv := make([]byte, aead.IV_SIZES[algo])
|
||||
defer delete(iv)
|
||||
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
|
||||
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
|
||||
// Seal the AAD + Plaintext.
|
||||
iv := make([]byte, aead.IV_SIZES[algo])
|
||||
defer delete(iv)
|
||||
crypto.rand_bytes(iv) // Random IVs are safe with XChaCha20-Poly1305.
|
||||
aead.seal(algo, ciphertext, tag, key, iv, aad, plaintext)
|
||||
|
||||
// Open the AAD + Ciphertext.
|
||||
opened_pt := buf[:pt_len]
|
||||
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
|
||||
panic("aead example: failed to open")
|
||||
// Open the AAD + Ciphertext.
|
||||
opened_pt := buf[:pt_len]
|
||||
if ok := aead.open(algo, opened_pt, key, iv, aad, ciphertext, tag); !ok {
|
||||
panic("aead example: failed to open")
|
||||
}
|
||||
|
||||
assert(bytes.equal(opened_pt, plaintext))
|
||||
}
|
||||
|
||||
assert(bytes.equal(opened_pt, plaintext))
|
||||
}
|
||||
```
|
||||
*/
|
||||
package aead
|
||||
package aead
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
package aes implements the AES block cipher and some common modes.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf
|
||||
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf
|
||||
- https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf ]]
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf ]]
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf ]]
|
||||
*/
|
||||
package aes
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build !amd64
|
||||
#+build !amd64
|
||||
package aes
|
||||
|
||||
@(private = "file")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build amd64
|
||||
#+build amd64
|
||||
package aes
|
||||
|
||||
import "core:crypto/_aes/hw_intel"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
package blake2b implements the BLAKE2b hash algorithm.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/rfc7693
|
||||
- https://www.blake2.net
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
|
||||
- [[ https://www.blake2.net ]]
|
||||
*/
|
||||
package blake2b
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
package blake2s implements the BLAKE2s hash algorithm.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/rfc7693
|
||||
- https://www.blake2.net/
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc7693 ]]
|
||||
- [[ https://www.blake2.net/ ]]
|
||||
*/
|
||||
package blake2s
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
package chacha20 implements the ChaCha20 and XChaCha20 stream ciphers.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/rfc8439
|
||||
- https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
|
||||
- [[ https://datatracker.ietf.org/doc/draft-irtf-cfrg-xchacha/03/ ]]
|
||||
*/
|
||||
package chacha20
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ AEAD_XChaCha20_Poly1305 Authenticated Encryption with Additional Data
|
||||
algorithms.
|
||||
|
||||
See:
|
||||
- https://www.rfc-editor.org/rfc/rfc8439
|
||||
- https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03
|
||||
- [[ https://www.rfc-editor.org/rfc/rfc8439 ]]
|
||||
- [[ https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 ]]
|
||||
*/
|
||||
package chacha20poly1305
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
package ed25519 implements the Ed25519 EdDSA signature algorithm.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/rfc8032
|
||||
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
|
||||
- https://eprint.iacr.org/2020/1244.pdf
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc8032 ]]
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf ]]
|
||||
- [[ https://eprint.iacr.org/2020/1244.pdf ]]
|
||||
*/
|
||||
package ed25519
|
||||
|
||||
|
||||
@@ -17,46 +17,44 @@ accomplish common tasks.
|
||||
A third optional boolean parameter controls if the file is streamed
|
||||
(default), or or read at once.
|
||||
|
||||
```odin
|
||||
package hash_example
|
||||
Example:
|
||||
package hash_example
|
||||
|
||||
import "core:crypto/hash"
|
||||
import "core:crypto/hash"
|
||||
|
||||
main :: proc() {
|
||||
input := "Feed the fire."
|
||||
main :: proc() {
|
||||
input := "Feed the fire."
|
||||
|
||||
// Compute the digest, using the high level API.
|
||||
returned_digest := hash.hash(hash.Algorithm.SHA512_256, input)
|
||||
defer delete(returned_digest)
|
||||
// Compute the digest, using the high level API.
|
||||
returned_digest := hash.hash(hash.Algorithm.SHA512_256, input)
|
||||
defer delete(returned_digest)
|
||||
|
||||
// Variant that takes a destination buffer, instead of returning
|
||||
// the digest.
|
||||
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.BLAKE2B]) // @note: Destination buffer has to be at least as big as the digest size of the hash.
|
||||
defer delete(digest)
|
||||
hash.hash(hash.Algorithm.BLAKE2B, input, digest)
|
||||
}
|
||||
```
|
||||
// Variant that takes a destination buffer, instead of returning
|
||||
// the digest.
|
||||
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.BLAKE2B]) // @note: Destination buffer has to be at least as big as the digest size of the hash.
|
||||
defer delete(digest)
|
||||
hash.hash(hash.Algorithm.BLAKE2B, input, digest)
|
||||
}
|
||||
|
||||
A generic low level API is provided supporting the init/update/final interface
|
||||
that is typical with cryptographic hash function implementations.
|
||||
|
||||
```odin
|
||||
package hash_example
|
||||
Example:
|
||||
package hash_example
|
||||
|
||||
import "core:crypto/hash"
|
||||
import "core:crypto/hash"
|
||||
|
||||
main :: proc() {
|
||||
input := "Let the cinders burn."
|
||||
main :: proc() {
|
||||
input := "Let the cinders burn."
|
||||
|
||||
// Compute the digest, using the low level API.
|
||||
ctx: hash.Context
|
||||
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512])
|
||||
defer delete(digest)
|
||||
// Compute the digest, using the low level API.
|
||||
ctx: hash.Context
|
||||
digest := make([]byte, hash.DIGEST_SIZES[hash.Algorithm.SHA3_512])
|
||||
defer delete(digest)
|
||||
|
||||
hash.init(&ctx, hash.Algorithm.SHA3_512)
|
||||
hash.update(&ctx, transmute([]byte)input)
|
||||
hash.final(&ctx, digest)
|
||||
}
|
||||
```
|
||||
hash.init(&ctx, hash.Algorithm.SHA3_512)
|
||||
hash.update(&ctx, transmute([]byte)input)
|
||||
hash.final(&ctx, digest)
|
||||
}
|
||||
*/
|
||||
package crypto_hash
|
||||
package crypto_hash
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package crypto_hash
|
||||
|
||||
/*
|
||||
Copyright 2021 zhibog
|
||||
Made available under the BSD-3 license.
|
||||
Copyright 2021 zhibog
|
||||
Made available under the BSD-3 license.
|
||||
|
||||
List of contributors:
|
||||
zhibog, dotbmp: Initial implementation.
|
||||
List of contributors:
|
||||
zhibog, dotbmp: Initial implementation.
|
||||
*/
|
||||
|
||||
import "core:io"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
|
||||
// hash_bytes will hash the given input and return the computed digest
|
||||
// in a newly allocated slice.
|
||||
@@ -87,36 +86,3 @@ hash_stream :: proc(
|
||||
|
||||
return dst, io.Error.None
|
||||
}
|
||||
|
||||
// hash_file will read the file provided by the given handle and return the
|
||||
// computed digest in a newly allocated slice.
|
||||
hash_file :: proc(
|
||||
algorithm: Algorithm,
|
||||
hd: os.Handle,
|
||||
load_at_once := false,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
[]byte,
|
||||
io.Error,
|
||||
) {
|
||||
if !load_at_once {
|
||||
return hash_stream(algorithm, os.stream_from_handle(hd), allocator)
|
||||
}
|
||||
|
||||
buf, ok := os.read_entire_file(hd, allocator)
|
||||
if !ok {
|
||||
return nil, io.Error.Unknown
|
||||
}
|
||||
defer delete(buf, allocator)
|
||||
|
||||
return hash_bytes(algorithm, buf, allocator), io.Error.None
|
||||
}
|
||||
|
||||
hash :: proc {
|
||||
hash_stream,
|
||||
hash_file,
|
||||
hash_bytes,
|
||||
hash_string,
|
||||
hash_bytes_to_buffer,
|
||||
hash_string_to_buffer,
|
||||
}
|
||||
|
||||
10
core/crypto/hash/hash_freestanding.odin
Normal file
10
core/crypto/hash/hash_freestanding.odin
Normal file
@@ -0,0 +1,10 @@
|
||||
#+build freestanding
|
||||
package crypto_hash
|
||||
|
||||
hash :: proc {
|
||||
hash_stream,
|
||||
hash_bytes,
|
||||
hash_string,
|
||||
hash_bytes_to_buffer,
|
||||
hash_string_to_buffer,
|
||||
}
|
||||
38
core/crypto/hash/hash_os.odin
Normal file
38
core/crypto/hash/hash_os.odin
Normal file
@@ -0,0 +1,38 @@
|
||||
#+build !freestanding
|
||||
package crypto_hash
|
||||
|
||||
import "core:io"
|
||||
import "core:os"
|
||||
|
||||
// hash_file will read the file provided by the given handle and return the
|
||||
// computed digest in a newly allocated slice.
|
||||
hash_file :: proc(
|
||||
algorithm: Algorithm,
|
||||
hd: os.Handle,
|
||||
load_at_once := false,
|
||||
allocator := context.allocator,
|
||||
) -> (
|
||||
[]byte,
|
||||
io.Error,
|
||||
) {
|
||||
if !load_at_once {
|
||||
return hash_stream(algorithm, os.stream_from_handle(hd), allocator)
|
||||
}
|
||||
|
||||
buf, ok := os.read_entire_file(hd, allocator)
|
||||
if !ok {
|
||||
return nil, io.Error.Unknown
|
||||
}
|
||||
defer delete(buf, allocator)
|
||||
|
||||
return hash_bytes(algorithm, buf, allocator), io.Error.None
|
||||
}
|
||||
|
||||
hash :: proc {
|
||||
hash_stream,
|
||||
hash_file,
|
||||
hash_bytes,
|
||||
hash_string,
|
||||
hash_bytes_to_buffer,
|
||||
hash_string_to_buffer,
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
package hkdf implements the HKDF HMAC-based Extract-and-Expand Key
|
||||
Derivation Function.
|
||||
|
||||
See: https://www.rfc-editor.org/rfc/rfc5869
|
||||
See: [[ https://www.rfc-editor.org/rfc/rfc5869 ]]
|
||||
*/
|
||||
package hkdf
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package hmac implements the HMAC MAC algorithm.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.198-1.pdf ]]
|
||||
*/
|
||||
package hmac
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package kmac implements the KMAC MAC algorithm.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
||||
*/
|
||||
package kmac
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ WARNING: The MD5 algorithm is known to be insecure and should only be
|
||||
used for interoperating with legacy applications.
|
||||
|
||||
See:
|
||||
- https://eprint.iacr.org/2005/075
|
||||
- https://datatracker.ietf.org/doc/html/rfc1321
|
||||
- [[ https://eprint.iacr.org/2005/075 ]]
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc1321 ]]
|
||||
*/
|
||||
package md5
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ WARNING: The SHA1 algorithm is known to be insecure and should only be
|
||||
used for interoperating with legacy applications.
|
||||
|
||||
See:
|
||||
- https://eprint.iacr.org/2017/190
|
||||
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
|
||||
- https://datatracker.ietf.org/doc/html/rfc3174
|
||||
- [[ https://eprint.iacr.org/2017/190 ]]
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc3174 ]]
|
||||
*/
|
||||
package sha1
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
package pbkdf2 implements the PBKDF2 password-based key derivation function.
|
||||
|
||||
See: https://www.rfc-editor.org/rfc/rfc2898
|
||||
See: [[ https://www.rfc-editor.org/rfc/rfc2898 ]]
|
||||
*/
|
||||
package pbkdf2
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package poly1305 implements the Poly1305 one-time MAC algorithm.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/rfc8439
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc8439 ]]
|
||||
*/
|
||||
package poly1305
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build freebsd, openbsd, netbsd
|
||||
#+build freebsd, openbsd, netbsd
|
||||
package crypto
|
||||
|
||||
foreign import libc "system:c"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//+build !linux
|
||||
//+build !windows
|
||||
//+build !openbsd
|
||||
//+build !freebsd
|
||||
//+build !netbsd
|
||||
//+build !darwin
|
||||
//+build !js
|
||||
#+build !linux
|
||||
#+build !windows
|
||||
#+build !openbsd
|
||||
#+build !freebsd
|
||||
#+build !netbsd
|
||||
#+build !darwin
|
||||
#+build !js
|
||||
package crypto
|
||||
|
||||
HAS_RAND_BYTES :: false
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package ristretto255 implement the ristretto255 prime-order group.
|
||||
|
||||
See:
|
||||
- https://www.rfc-editor.org/rfc/rfc9496
|
||||
- [[ https://www.rfc-editor.org/rfc/rfc9496 ]]
|
||||
*/
|
||||
package ristretto255
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
package sha2 implements the SHA2 hash algorithm family.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
|
||||
- https://datatracker.ietf.org/doc/html/rfc3874
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf ]]
|
||||
- [[ https://datatracker.ietf.org/doc/html/rfc3874 ]]
|
||||
*/
|
||||
package sha2
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ pre-standardization Keccak algorithm is required, it can be found in
|
||||
crypto/legacy/keccak.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
|
||||
*/
|
||||
package sha3
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ package shake implements the SHAKE and cSHAKE XOF algorithm families.
|
||||
The SHA3 hash algorithm can be found in the crypto/sha3.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
|
||||
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf ]]
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
||||
*/
|
||||
package shake
|
||||
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
package siphash Implements the SipHash hashing algorithm.
|
||||
|
||||
Use the specific procedures for a certain setup. The generic procedures will default to Siphash 2-4.
|
||||
|
||||
See:
|
||||
- [[ https://github.com/veorq/SipHash ]]
|
||||
- [[ https://www.aumasson.jp/siphash/siphash.pdf ]]
|
||||
*/
|
||||
package siphash
|
||||
|
||||
/*
|
||||
@@ -6,10 +15,6 @@ package siphash
|
||||
|
||||
List of contributors:
|
||||
zhibog: Initial implementation.
|
||||
|
||||
Implementation of the SipHash hashing algorithm, as defined at <https://github.com/veorq/SipHash> and <https://www.aumasson.jp/siphash/siphash.pdf>
|
||||
|
||||
Use the specific procedures for a certain setup. The generic procdedures will default to Siphash 2-4
|
||||
*/
|
||||
|
||||
import "core:crypto"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package sm3 implements the SM3 hash algorithm.
|
||||
|
||||
See:
|
||||
- https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02
|
||||
- [[ https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3-02 ]]
|
||||
*/
|
||||
package sm3
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package tuplehash implements the TupleHash and TupleHashXOF algorithms.
|
||||
|
||||
See:
|
||||
- https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf
|
||||
- [[ https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf ]]
|
||||
*/
|
||||
package tuplehash
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package x25519 implements the X25519 (aka curve25519) Elliptic-Curve
|
||||
Diffie-Hellman key exchange protocol.
|
||||
|
||||
See:
|
||||
- https://www.rfc-editor.org/rfc/rfc7748
|
||||
- [[ https://www.rfc-editor.org/rfc/rfc7748 ]]
|
||||
*/
|
||||
package x25519
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private file
|
||||
//+build linux, darwin
|
||||
#+private file
|
||||
#+build linux, darwin
|
||||
package debug_trace
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
//+build !windows !linux !darwin
|
||||
#+build !windows
|
||||
#+build !linux
|
||||
#+build !darwin
|
||||
package debug_trace
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private
|
||||
//+build windows
|
||||
#+private
|
||||
#+build windows
|
||||
package debug_trace
|
||||
|
||||
import "base:intrinsics"
|
||||
|
||||
@@ -4,7 +4,6 @@ Package `core:dynlib` implements loading of shared libraries/DLLs and their symb
|
||||
The behaviour of dynamically loaded libraries is specific to the target platform of the program.
|
||||
For in depth detail on the underlying behaviour please refer to your target platform's documentation.
|
||||
|
||||
See `example` directory for an example library exporting 3 symbols and a host program loading them automatically
|
||||
by defining a symbol table struct.
|
||||
For a full example, see: [[ core/dynlib/example; https://github.com/odin-lang/Odin/tree/master/core/dynlib/example ]]
|
||||
*/
|
||||
package dynlib
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build js
|
||||
//+private
|
||||
#+build js
|
||||
#+private
|
||||
package dynlib
|
||||
|
||||
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build linux, darwin, freebsd, openbsd, netbsd
|
||||
//+private
|
||||
#+build linux, darwin, freebsd, openbsd, netbsd
|
||||
#+private
|
||||
package dynlib
|
||||
|
||||
import "core:os"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+build windows
|
||||
//+private
|
||||
#+build windows
|
||||
#+private
|
||||
package dynlib
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
@@ -13,8 +13,8 @@ If your terminal supports 24-bit true color mode, you can also do this:
|
||||
fmt.println(ansi.CSI + ansi.FG_COLOR_24_BIT + ";0;255;255" + ansi.SGR + "Hellope!" + ansi.CSI + ansi.RESET + ansi.SGR)
|
||||
|
||||
For more information, see:
|
||||
1. https://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
2. https://www.vt100.net/docs/vt102-ug/chapter5.html
|
||||
3. https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
- [[ https://en.wikipedia.org/wiki/ANSI_escape_code ]]
|
||||
- [[ https://www.vt100.net/docs/vt102-ug/chapter5.html ]]
|
||||
- [[ https://invisible-island.net/xterm/ctlseqs/ctlseqs.html ]]
|
||||
*/
|
||||
package ansi
|
||||
|
||||
@@ -675,10 +675,6 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
|
||||
return
|
||||
|
||||
case reflect.Type_Info_Map:
|
||||
if !reflect.is_string(t.key) {
|
||||
return _unsupported(v, hdr)
|
||||
}
|
||||
|
||||
raw_map := (^mem.Raw_Map)(v.data)
|
||||
if raw_map.allocator.procedure == nil {
|
||||
raw_map.allocator = context.allocator
|
||||
@@ -695,43 +691,31 @@ _unmarshal_map :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header,
|
||||
new_len := uintptr(min(scap, runtime.map_len(raw_map^)+length))
|
||||
runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return
|
||||
}
|
||||
|
||||
// Temporary memory to unmarshal keys into before inserting them into the map.
|
||||
|
||||
// Temporary memory to unmarshal values into before inserting them into the map.
|
||||
elem_backing := mem.alloc_bytes_non_zeroed(t.value.size, t.value.align, context.temp_allocator) or_return
|
||||
defer delete(elem_backing, context.temp_allocator)
|
||||
|
||||
map_backing_value := any{raw_data(elem_backing), t.value.id}
|
||||
|
||||
for idx := 0; unknown || idx < length; idx += 1 {
|
||||
// Decode key, keys can only be strings.
|
||||
key: string
|
||||
if keyv, kerr := decode_key(d, v); unknown && kerr == .Break {
|
||||
break
|
||||
} else if kerr != nil {
|
||||
err = kerr
|
||||
return
|
||||
} else {
|
||||
key = keyv
|
||||
}
|
||||
// Temporary memory to unmarshal keys into.
|
||||
key_backing := mem.alloc_bytes_non_zeroed(t.key.size, t.key.align, context.temp_allocator) or_return
|
||||
defer delete(key_backing, context.temp_allocator)
|
||||
key_backing_value := any{raw_data(key_backing), t.key.id}
|
||||
|
||||
for idx := 0; unknown || idx < length; idx += 1 {
|
||||
if unknown || idx > scap {
|
||||
// Reserve space for new element so we can return allocator errors.
|
||||
new_len := uintptr(runtime.map_len(raw_map^)+1)
|
||||
runtime.map_reserve_dynamic(raw_map, t.map_info, new_len) or_return
|
||||
}
|
||||
|
||||
mem.zero_slice(key_backing)
|
||||
_unmarshal_value(d, key_backing_value, _decode_header(r) or_return) or_return
|
||||
|
||||
mem.zero_slice(elem_backing)
|
||||
_unmarshal_value(d, map_backing_value, _decode_header(r) or_return) or_return
|
||||
|
||||
key_ptr := rawptr(&key)
|
||||
key_cstr: cstring
|
||||
if reflect.is_cstring(t.key) {
|
||||
assert_safe_for_cstring(key)
|
||||
key_cstr = cstring(raw_data(key))
|
||||
key_ptr = &key_cstr
|
||||
}
|
||||
|
||||
set_ptr := runtime.__dynamic_map_set_without_hash(raw_map, t.map_info, key_ptr, map_backing_value.data)
|
||||
set_ptr := runtime.__dynamic_map_set_without_hash(raw_map, t.map_info, key_backing_value.data, map_backing_value.data)
|
||||
// We already reserved space for it, so this shouldn't fail.
|
||||
assert(set_ptr != nil)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user