Compare commits

...

1227 Commits

Author SHA1 Message Date
gingerBill 1676c643df Change MAX_STORE_SIZE 2022-06-30 15:47:19 +01:00
gingerBill e2bfb024de Merge branch 'master' of https://github.com/odin-lang/Odin 2022-06-30 15:42:11 +01:00
gingerBill 4d06a54c0c Use memmove if possible when emitting store over a certain size 2022-06-30 15:42:02 +01:00
Jeroen van Rijn 04ae87eaef Merge pull request #1868 from Skytrias/skytrias-ease-flux-fixes
math ease fixed flux map key deletion and generic in `flux_to`
2022-06-28 18:35:18 +02:00
Michael Kutowski b313d09c2c flux fixed key deletion and generic in flux_to 2022-06-28 18:27:52 +02:00
gingerBill c0d2359a91 Merge pull request #1826 from englerj/windows-bindings
Added additional Windows bindings.
2022-06-28 13:14:35 +01:00
gingerBill 51a2f09032 Merge pull request #1863 from OrigamiDev-Pete/master
Correct error reporting for Win32 file operations
2022-06-28 13:12:41 +01:00
gingerBill f60e8031f2 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-06-28 11:27:57 +01:00
gingerBill ea42613fec Improve error message with suggestion for #1866 2022-06-28 11:27:50 +01:00
gingerBill 2cbb3d5a24 Merge pull request #1864 from JimmyLefevre/master
Change LPCSTR to LPCWSTR in windows _W procedures
2022-06-27 22:20:20 +01:00
Jimmy "Keeba" Lefevre 9e288b7ce8 Change LPCSTR to LPCWSTR in windows _W procedures 2022-06-27 21:48:02 +02:00
gingerBill 776b48c10d Fix GetEventState 2022-06-27 11:02:40 +01:00
gingerBill 199dae6cd5 Make SDL.*Event procedures return booleans instead of an integer where appropriate 2022-06-27 11:02:20 +01:00
Peter DV e58f45bef7 Correct error reporting 2022-06-27 11:26:34 +10:00
gingerBill abe122ecb7 Implement #1859 2022-06-26 13:13:07 +01:00
gingerBill f8744d87b0 Add shorthand flag to determine_type_from_polymorphic 2022-06-24 15:12:15 +01:00
Jeroen van Rijn 3e7f6b8751 Merge pull request #1857 from Pablo96/fix-core-lib-odin-parser-file-docs
Fix issue 1856
2022-06-23 23:22:36 +02:00
Pablo Narvaja 6ffe814ca7 assign package docs to file docs 2022-06-23 18:13:34 -03:00
Jeroen van Rijn eec9be71f6 Merge pull request #1854 from Kelimion/dll-entry-point
Add runtime.dll_forward_reason for Windows DLLs.
2022-06-21 18:02:47 +02:00
Jeroen van Rijn 888913c739 Add runtime.dll_forward_reason for Windows DLLs. 2022-06-21 17:29:55 +02:00
gingerBill 33d96fd28a Correct debug information of #simd vectors 2022-06-20 16:00:17 +01:00
gingerBill f1e8738af2 Merge pull request #1851 from DaseinPhaos/patch-1
Add missing field for `TEXTURE_COPY_LOCATION`
2022-06-19 16:21:21 +01:00
gingerBill 9c52a11b1b Merge pull request #1850 from ftphikari/master
sys/windows: add RegSetKeyValueW
2022-06-19 16:21:00 +01:00
Luxko d89c4606bd Add missing field for TEXTURE_COPY_LOCATION
Add missing anonymous union field for [D3D12_TEXTURE_COPY_LOCATION ](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_texture_copy_location):
```C
union {
    D3D12_PLACED_SUBRESOURCE_FOOTPRINT PlacedFootprint;
    UINT                               SubresourceIndex;
  };
```
2022-06-19 19:06:31 +08:00
hikari c6903fbcd5 sys/windows: add constants and macro 2022-06-17 15:14:21 +03:00
ftphikari 13c8149046 Merge branch 'odin-lang:master' into master 2022-06-16 22:55:24 +03:00
hikari 665db0f778 sys/windows: add RegSetKeyValueW 2022-06-16 22:54:59 +03:00
gingerBill 173286de65 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-06-16 15:49:13 +01:00
gingerBill f2ecda8fec Rename to SJSON for the Simplified JSON notation variant 2022-06-16 15:49:08 +01:00
Jeroen van Rijn 6f1222e9bf Update strings.prefix_length to handle partial UTF-8 runes. 2022-06-16 16:12:15 +02:00
gingerBill 84a424f21e Add numerous procedure groups decode_rune, decode_last_rune, rune_count, full_rune 2022-06-16 15:07:07 +01:00
Jeroen van Rijn 9b7710488b Merge pull request #1849 from Kelimion/prefix_length
Add `strings.prefix_length` & `slice.prefix_length`
2022-06-16 12:42:35 +02:00
Jeroen van Rijn 9f413862e9 Add strings.prefix_length & slice.prefix_length 2022-06-16 12:34:13 +02:00
gingerBill b8802d7df7 Merge pull request #1848 from Astavie/require-fix
fix require flag on higher optimization modes
2022-06-16 10:59:49 +01:00
Astavie b13dad02a4 fix require flag on higher optimization modes 2022-06-15 21:30:29 +02:00
Jeroen van Rijn f045f8d805 Merge pull request #1845 from hfr4/patch-1
wrong variable names in functions
2022-06-14 18:32:25 +02:00
hfr4 30b7c8ad66 wrong variable names in functions 2022-06-14 18:20:38 +02:00
gingerBill 21e637d2b3 Allow %q with enums 2022-06-13 23:30:10 +01:00
gingerBill 6c196931d2 Increase record_level on displaying map values 2022-06-13 14:46:03 +01:00
gingerBill d7195b0798 Add missing commas 2022-06-13 11:12:31 +01:00
gingerBill b40998de9e Improve -strict-style for foreign import 2022-06-13 11:11:51 +01:00
gingerBill 8c0c327df9 Improvements to -strict-style and trailing commas 2022-06-13 11:00:13 +01:00
Josh Engler 50cbb8a1fc Fix tab spacing. 2022-06-12 15:55:38 -04:00
gingerBill ff9d058392 Minor changes to core:slice/heap; add to examples/all 2022-06-12 17:25:42 +01:00
gingerBill 1acc8f438b Merge pull request #1830 from graphitemaster/dale/max_heap
add max heap implementation to slice package
2022-06-12 17:21:04 +01:00
gingerBill c53426fcb4 Merge pull request #1818 from IanLilleyT/reserve_exceed
Dynamic array append reserves more space when it exceeds capacity
2022-06-12 17:19:08 +01:00
gingerBill 5187db525f Minor style change 2022-06-12 17:17:59 +01:00
gingerBill a8bd340267 Merge pull request #1395 from hdooley/master
factor out alloca generation into a helper
2022-06-12 17:17:12 +01:00
gingerBill ca1f419dc2 Merge pull request #1819 from IanLilleyT/no_query_info
Allocator: tidying up Query_Info return values when not part of Query_Features
2022-06-12 17:15:08 +01:00
gingerBill fae60a6b88 Merge pull request #1829 from totoki-kei/dev/totoki-kei/patch-testing
[testing] Fixed `@(test)` always fails unless `testing.set_fail_timeout` is called
2022-06-12 17:15:02 +01:00
gingerBill 108558ddfc Merge pull request #1841 from hasenj/hack-objc-window-init
HACK work around for creating a cocoa window
2022-06-12 17:08:10 +01:00
gingerBill 65b8cfae82 Minor code clean up 2022-06-12 16:49:15 +01:00
gingerBill 4055c31cf0 Update utf-32 printing 2022-06-12 16:48:06 +01:00
gingerBill e88af4e458 Support UTF-16 printing with []u16 and [^]u16 related types 2022-06-12 16:36:55 +01:00
gingerBill 79eb7b52d9 Merge pull request #1828 from JungerBoyo/patch-2
front() and back()
2022-06-12 16:17:39 +01:00
gingerBill 83b2bf44c4 Merge pull request #1842 from ftphikari/master
sys/windows: add a couple of constants
2022-06-12 16:12:43 +01:00
gingerBill 670f18ad1b Minor change to shrink 2022-06-12 16:12:24 +01:00
gingerBill 9a81716936 Merge pull request #1820 from Tetralux/shrink
[runtime] Add builtin `shrink` for dynamic arrays and maps
2022-06-12 16:11:18 +01:00
gingerBill f013499eea Merge pull request #1827 from JungerBoyo/patch-1
unset function
2022-06-12 16:09:09 +01:00
gingerBill d04f732e68 Add fmt:"s,0" to allow arrays and multi-pointers to be printed with NUL termination 2022-06-12 13:07:43 +01:00
gingerBill 35fd8e7f68 Move trailing comma requirement in field lists to -strict-style 2022-06-12 12:20:00 +01:00
gingerBill 38ff2a3ed9 Minor fix 2022-06-11 15:57:56 +01:00
gingerBill bd502d16bc Correct distinction between indirection and record level 2022-06-11 15:24:35 +01:00
gingerBill a11e17fbc3 Disable again 2022-06-11 15:18:51 +01:00
gingerBill 8b3b659433 Re-enable string quoting within records 2022-06-11 15:16:17 +01:00
gingerBill f33228fd6e Merge branch 'master' of https://github.com/odin-lang/Odin 2022-06-11 15:13:13 +01:00
gingerBill df5b693de8 Refactor fmt_value 2022-06-11 15:13:07 +01:00
Jeroen van Rijn ab98108441 [image/png] Construct test paths differently. 2022-06-11 16:07:56 +02:00
Josh Engler 6f80174f84 Merge branch 'master' into windows-bindings 2022-06-11 09:48:28 -04:00
hikari 0ebe81fce2 sys/windows: add GetTextExtentPoint32W 2022-06-11 12:27:18 +03:00
gingerBill c75dd14308 Fix typo 2022-06-11 02:03:54 +01:00
gingerBill c166b6a21d Support optional length parameter on struct tags for multi-pointers 2022-06-11 01:40:58 +01:00
gingerBill 6ed5cbee12 Refactor to fmt_array 2022-06-11 01:38:14 +01:00
gingerBill 5b200ccdf8 Correct #soa printing 2022-06-11 01:32:52 +01:00
gingerBill cf0f0c4b31 Clean up trailing comma 2022-06-11 01:23:41 +01:00
gingerBill 1399ecb41c Refactor with fmt_struct 2022-06-11 01:22:18 +01:00
gingerBill 339d6cfd41 Check for in_bad 2022-06-11 01:17:33 +01:00
gingerBill 7bded4f189 Default to q for strings within structs 2022-06-11 01:09:42 +01:00
gingerBill c7269b9ef0 Allow for fmt:"s" and fmt:"s,field_length" 2022-06-11 01:06:47 +01:00
gingerBill 85688015aa Add fmt:"-" to ignore fields in a struct 2022-06-11 00:55:10 +01:00
hikari 3c6cc575c6 sys/windows: add a couple of constants 2022-06-10 21:17:27 +03:00
gingerBill 0564cb6483 Merge pull request #1824 from ftphikari/master
sys/windows: add registry functions and create winerror.odin
2022-06-10 14:31:48 +01:00
Hasen Judy 4be92c7eb8 HACK work around for creating a cocoa window
See #1825 for more details.

This does not fix the underlying issue; it's merely a work around for
this specific manifestation of the bug.
2022-06-10 17:10:00 +09:00
hikari 88e9eb7d0c sys/windows: add functions and constants 2022-06-09 17:44:51 +03:00
hikari d19fc54c3d sys/windows: add macro 2022-06-08 21:18:11 +03:00
ftphikari 5d4291d9fa Merge branch 'odin-lang:master' into master 2022-06-08 19:55:42 +03:00
hikari b70cd03e9e sys/windows: add interfaces from shobjidl_core.h 2022-06-08 19:38:12 +03:00
hikari e91e5e1fe9 sys/windows: fix formatting 2022-06-07 20:16:32 +03:00
hikari ae57a49915 sys/windows: fix file picker dialog 2022-06-07 17:59:15 +03:00
gingerBill bfcb527b42 Merge pull request #1831 from Despacito696969/master
Fixed `slice.is_sorted_cmp`
2022-06-07 13:23:01 +01:00
Despacito696969 a343fb171d Fixed slice.is_sorted_cmp 2022-06-07 14:07:19 +02:00
Tetralux fa2296a124 [runtime] Add builtin shrink for dynamic arrays and maps
Asks the allocator to shrink the backing allocation to the current __length__, or a capacity
of the user's choosing.

Returns `(did_shrink: bool, err: mem.Allocator_Error)`.

```
shrink(&array) // shrinks to len(array)
shrink(&array, N) // shrink to N capacity

shrink(&map) // shrinks down to len(map)
shrink(&map, N) // shrink to N capacity
```
2022-06-04 23:29:47 +00:00
Dale Weiler a996cfc536 fix 2022-06-04 04:47:52 -04:00
Dale Weiler c1d55b9296 add max heap implementation to slice package 2022-06-04 04:31:55 -04:00
Totoki Kei 5c18cca1ca [core:testing] add global_fail_timeout_thread nil check
Fixed an issue where test would always fail unless set_fail_timeout was called.
2022-06-04 12:21:20 +09:00
JungerBoyo 78e6cd0c60 front() and back()
based on pop_front(), pop_back()
2022-06-04 00:12:34 +02:00
hikari 176954a6d8 sys/windows: add several functions and constants 2022-06-03 22:12:43 +03:00
JungerBoyo ad6b3bd95f unset function
unset function, clear single bits
2022-06-03 15:53:14 +02:00
Josh Engler 762895bc45 - Added EnumDisplaySettingsW and friends.
- Added additional file access/security/sharing attributes
2022-06-03 07:40:45 -04:00
hikari 592e9afa5f sys/windows: add RegSetValueExW 2022-06-03 07:57:21 +03:00
hikari a2e0373934 sys/windows: add registry functions and create winerror.odin 2022-06-03 06:44:42 +03:00
gingerBill fb49841b1d Remove strings dependency from core:sys/windows 2022-06-02 13:02:16 +01:00
gingerBill 01ea0d6f1e Merge branch 'master' of https://github.com/odin-lang/Odin 2022-06-02 12:11:29 +01:00
gingerBill bb7f291f5f Remove simd_rem; Disallow simd_div for integers 2022-06-02 12:10:43 +01:00
gingerBill 174fa9b490 Merge pull request #1817 from IanLilleyT/arena_allocation
Improved arena allocation with alignment
2022-06-02 10:53:23 +01:00
Ian Lilley dda2ed290a tidying up Query_Info return value when not in query features 2022-06-01 22:40:39 -04:00
Ian Lilley ee9908b09e Reserve more space when exceeding, not meeting, capacity 2022-06-01 22:01:00 -04:00
Ian Lilley 66de1856e3 tighter allocation for arena allocator 2022-06-01 21:37:05 -04:00
gingerBill ba5f7c4e2a Deprecate a..b based ranges in favour of ..= 2022-06-01 11:08:19 +01:00
gingerBill 487bd3d942 Keep compiler happy 2022-06-01 11:07:58 +01:00
gingerBill 4fac7a8f27 Update wasm/README.md 2022-06-01 10:40:59 +01:00
gingerBill 25dae06b6a Remove loader.mjs 2022-06-01 10:32:24 +01:00
gingerBill a1f15c2c69 Merge pull request #1807 from odin-lang/simd-dev
Generic #simd type and intrinsics
2022-05-31 11:52:24 +01:00
gingerBill 516f6647b4 Fix intrinsics.non_temporal_{load, store} 2022-05-31 11:00:41 +01:00
gingerBill a7840d50e2 Correct documentation 2022-05-31 00:01:23 +01:00
gingerBill cb10af08cb Correct intrinsics.odin for documentation 2022-05-30 16:42:32 +01:00
gingerBill 4e49d24df9 Add enable_target_feature to ABM 2022-05-30 16:08:06 +01:00
gingerBill 68222cb8ab Add SSE4.2 2022-05-30 16:06:31 +01:00
gingerBill 912d29af83 Add @(require_results) to all appropriate procedures 2022-05-30 15:59:48 +01:00
gingerBill f3868ac932 Improve missing handled results for built in procedures 2022-05-30 15:57:26 +01:00
gingerBill 5b42dd7707 Correct @(require_results) on parapoly procedures 2022-05-30 15:27:09 +01:00
gingerBill 51707032d1 Add SSE4.1 2022-05-30 15:17:02 +01:00
gingerBill a0babefe55 Fix lb_build_builtin_simd_proc 2022-05-30 15:13:45 +01:00
gingerBill f3aefbc443 @(require_target_feature=<string>) @(enable_target_feature=<string>)
require_target_feature - required by the target micro-architecture
enable_target_feature - will be enabled for the specified procedure only
2022-05-30 14:53:12 +01:00
Jeroen van Rijn a6c779b50e Merge pull request #1815 from hasenj/patch-1
Missing lib imports for raylib on macOS
2022-05-30 15:32:46 +02:00
hasen 9fa41a97b9 Missing lib imports for raylib on macOS
The following frameworks are required for linking to work (due to dependency on glfw):

    Cocoa, OpenGL, IOKit
2022-05-30 22:27:13 +09:00
gingerBill cef022539e Rename to lanes_rotate_left, lanes_rotate_right, lanes_reverse 2022-05-29 15:13:14 +01:00
gingerBill f6dfa33697 Use single line attributes 2022-05-29 15:11:15 +01:00
gingerBill bc3bf939e0 Add sha.odin 2022-05-29 14:56:25 +01:00
gingerBill f5e5eac3b9 Add cmpxchg16b 2022-05-29 14:46:05 +01:00
Jeroen van Rijn d50786bd30 Merge pull request #1814 from Kelimion/sdk_detect_fix
Fix SDK detection if no SDK installed.
2022-05-29 14:55:10 +02:00
gingerBill 0ccbea17aa Add pclmulqdq.odin 2022-05-29 13:50:54 +01:00
Jeroen van Rijn 136d50a745 Fix SDK detection if no SDK installed. 2022-05-29 14:48:44 +02:00
gingerBill babfba5e8f Add rdtsc.odin 2022-05-29 13:48:20 +01:00
gingerBill 846f8377b2 Add fxsr.odin 2022-05-29 13:44:00 +01:00
gingerBill 77d4409549 Add adx.odin 2022-05-29 13:40:16 +01:00
gingerBill 7f3540b7f5 Add abm.odin 2022-05-29 13:36:55 +01:00
gingerBill 3ad2cde833 Add amd64 specific instructions 2022-05-29 13:34:59 +01:00
gingerBill 910799cc5f Add cpu_features for core:simd/x86 2022-05-28 15:54:41 +01:00
Jeroen van Rijn 6c0192083e Merge pull request #1812 from wjlroe/os-exists-for-darwin
[os] Darwin: Add os.exists()
2022-05-28 16:45:48 +02:00
gingerBill c60d7842cd Remove old code 2022-05-28 15:41:27 +01:00
gingerBill d7eaf0f87b Add intrinsics.x86_cpuid and intrinsics.x86_xgetbv 2022-05-28 15:41:11 +01:00
William Roe bb4329711c [os] Darwin: Add os.exists() 2022-05-28 15:21:07 +01:00
gingerBill 618d3bf62f Improve vector comparison == != for horizontal reduction 2022-05-28 13:42:58 +01:00
Jeroen van Rijn cf8a4b9812 Don't crash if SDK not found during ENV fallback. 2022-05-28 13:52:56 +02:00
gingerBill 4db533ff71 Add ssse3 support 2022-05-27 23:07:33 +01:00
Jeroen van Rijn f28e3276e7 One more change. 2022-05-28 00:02:49 +02:00
gingerBill 026540040d Add SSE3 support 2022-05-27 23:00:52 +01:00
gingerBill 8518d3b232 Rename to non_temporaral_* 2022-05-27 22:57:16 +01:00
gingerBill 1c1f5e2231 Complete SSE2 2022-05-27 22:56:11 +01:00
Jeroen van Rijn bdedfb1071 Merge pull request #1805 from WalterPlinge/find-vs-winsdk-env
Find MSVC compiler and Windows SDK using environment variables
2022-05-27 23:54:53 +02:00
Jeroen van Rijn 92ed9e0b94 Refactor Walter's PR. 2022-05-27 23:48:31 +02:00
gingerBill 5c10b35df7 Fix sqrt for simd 2022-05-27 22:26:04 +01:00
Jeroen van Rijn 0668811397 Merge branch 'master' into find-vs-winsdk-env 2022-05-27 21:37:36 +02:00
Jeroen van Rijn 6bb6344208 Merge pull request #1810 from Kelimion/ms_craziness
Additional cleanup of microsoft_craziness.h.
2022-05-27 21:05:10 +02:00
Jeroen van Rijn 2f7bd154a2 Additional cleanup of microsoft_craziness.h. 2022-05-27 20:59:46 +02:00
gingerBill 20c5033b38 Add pack and unpack 2022-05-27 17:07:48 +01:00
gingerBill 20fe6d102a Add load and stores and sets 2022-05-27 16:58:35 +01:00
gingerBill 4e30a64d9f Add more sse2 intrinsics 2022-05-27 16:49:52 +01:00
gingerBill c48ef7d70b Add shifts 2022-05-27 16:39:54 +01:00
gingerBill e079a7009d Begin work on sse2.odin 2022-05-27 16:09:31 +01:00
gingerBill f383bf3136 Add _mm_stream_ps 2022-05-27 14:59:09 +01:00
gingerBill 609ddf28b7 Add intrinsics nontemporal_store and nontemporal_load 2022-05-27 14:56:36 +01:00
Jeroen van Rijn 34f1bda57c Merge pull request #1809 from Kelimion/ms_craziness
Refactor ms_craziness.h
2022-05-27 15:53:49 +02:00
Jeroen van Rijn f137b927b6 Refactor ms_craziness.h 2022-05-27 15:47:29 +02:00
gingerBill 2185dada56 Change package name 2022-05-27 14:26:02 +01:00
gingerBill 0b08080119 Add core:simd/x86 SSE
Proof of Concept to show intrinsics specific to a certain target platform
2022-05-27 14:23:31 +01:00
gingerBill 432b2b19e9 Add intrinsics.simd_x86__MM_SHUFFLE 2022-05-27 12:54:28 +01:00
gingerBill 952f294bce Add loads of aliases of vector types 2022-05-27 12:20:48 +01:00
gingerBill c23274adb0 Remove useless check 2022-05-27 12:11:58 +01:00
gingerBill 833f9dd037 Minor change 2022-05-27 11:55:03 +01:00
gingerBill 1ff8b97dae Add prefix of lanes_ 2022-05-26 20:44:37 +01:00
gingerBill 70451f9335 Support reverse_bits for #simd 2022-05-26 20:40:48 +01:00
gingerBill 1f438d4e6c Merge intrinsics.simd_sqrt with intrinsics.sqrt 2022-05-26 18:09:59 +01:00
gingerBill 421d45a7a7 Add intrinsics.fused_mul_add 2022-05-26 18:06:26 +01:00
gingerBill 20e7b5c88a Support count_ones etc with #simd 2022-05-26 17:48:51 +01:00
gingerBill 7092273a8f Rename simd_eq etc to simd_lanes_eq 2022-05-26 17:36:13 +01:00
gingerBill d0e8a735ba Add arithmetic operator support for simd vectors; Add intrinsics.simd_and_not 2022-05-26 17:09:46 +01:00
gingerBill 208226dba2 Improve #simd literal support 2022-05-26 14:55:10 +01:00
gingerBill f308f37ba1 Remove need for simd.splat 2022-05-26 14:51:50 +01:00
gingerBill c2610cb75e Keep -vet happy 2022-05-26 13:56:35 +01:00
gingerBill 59e9df2609 simd.bit_not; simd.copysign 2022-05-26 13:49:27 +01:00
gingerBill 66b5a35ec3 Add simd_to_bits; correct fix typo causing issue with parapoly 2022-05-26 13:45:47 +01:00
gingerBill f3f6c12a7c Add simd_clamp 2022-05-26 11:58:55 +01:00
gingerBill e331b0647e Add simd_rotate_left simd_rotate_right` 2022-05-26 11:48:04 +01:00
gingerBill 35502816c7 Add simd_add_sat simd_sub_sat 2022-05-26 11:24:10 +01:00
gingerBill 7ec0236fbf Add simd_reverse 2022-05-26 11:14:22 +01:00
gingerBill 0fd43c1a0b Add simd.{sqrt, ceil, floor, trunc, nearest} 2022-05-26 11:02:02 +01:00
gingerBill 06337129d8 Remove intrinsics.odin.simd_vector in favour of #simd[N]T 2022-05-26 10:38:51 +01:00
gingerBill 337780497d Merge pull request #1806 from jasonKercher/virtual_linux_fix
fix mmap call in virtual_linux.odin
2022-05-26 09:33:42 +01:00
jason 10deb2e88b fix mmap call in virtual_linux.odin 2022-05-25 21:51:36 -04:00
gingerBill b95ca80f85 Fix simd_shuffle 2022-05-26 00:39:34 +01:00
gingerBill 83d880a94a Remove unneeded mask 2022-05-26 00:37:48 +01:00
gingerBill cde6a2f7a5 Make simd_shuffle act closer to swizzle 2022-05-26 00:36:24 +01:00
gingerBill c2f5cbdeb4 Allow integer vectors in select 2022-05-25 23:49:23 +01:00
gingerBill 8e57511ffa Minor clean up 2022-05-25 23:42:25 +01:00
gingerBill 12d19d21c4 Document simd stuff in intrinsics.odin 2022-05-25 23:40:59 +01:00
gingerBill 7002c94a63 Add intrinsics.simd_select 2022-05-25 23:34:41 +01:00
gingerBill 57e69ea392 Add comments 2022-05-25 23:24:42 +01:00
gingerBill 09f936b04d Correct casting between integer and boolean #simd 2022-05-25 23:24:32 +01:00
gingerBill 140c00aa0c intrinsics.simd_shuffle 2022-05-25 23:01:33 +01:00
gingerBill 808ea30b48 Allow booleans for #simd 2022-05-25 22:16:44 +01:00
gingerBill 63d6c08d90 Add raw_simd_data 2022-05-25 22:09:38 +01:00
gingerBill 10e4de3c01 Add intrinsics.simd_reduce_* 2022-05-25 22:04:47 +01:00
gingerBill 8ac12886ed Add core:simd 2022-05-25 21:30:10 +01:00
gingerBill 63cc8a80a0 Correct parapoly for #simd 2022-05-25 21:29:45 +01:00
gingerBill 1549d01bf7 Restrict swizzle to a power of two for #simd 2022-05-25 21:17:21 +01:00
gingerBill b168bf9460 Rename simd_insert to simd_replace 2022-05-25 21:00:00 +01:00
gingerBill 0203bb657e Allow for non-constant simd vector compound types 2022-05-25 20:39:22 +01:00
gingerBill 53f0c6ef1a Add ranges for simd compounds literals 2022-05-25 20:31:31 +01:00
gingerBill 4c4480104d Add simd_extract and simd_insert 2022-05-25 20:27:14 +01:00
gingerBill 5c72974167 Simplify transmute for #simd 2022-05-25 19:04:25 +01:00
gingerBill f21e9ee712 Allow basic casting of simd vectors 2022-05-25 18:59:47 +01:00
gingerBill 81dd727f75 Implement backend for simd intrinsics 2022-05-25 18:49:17 +01:00
gingerBill 3b54015e80 Mock out simd intrinsics 2022-05-25 17:54:05 +01:00
gingerBill b032d5af87 Make #simd an opaque type 2022-05-25 17:26:18 +01:00
WalterPlinge 209a155608 fix a double free bug 2022-05-25 14:51:37 +01:00
gingerBill d8e77cd738 Add #optional_ok to dynlib.symbol_address 2022-05-25 11:53:32 +01:00
gingerBill 95d4ce4aa3 Fix lib_unix.odin 2022-05-25 11:46:26 +01:00
gingerBill 39393cca92 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-25 11:44:05 +01:00
gingerBill acadbe050c Make core:dynlib use the private interface convention of other packages 2022-05-25 11:43:56 +01:00
WalterPlinge 8fcf2f5dca a little cleanup 2022-05-25 02:10:34 +01:00
WalterPlinge 831a86599e Add fallback build paths search using environment variables 2022-05-25 02:00:13 +01:00
Jeroen van Rijn 233b32fd3e Correct return value. 2022-05-25 00:47:29 +02:00
Jeroen van Rijn 3c5124ce68 Fix odin build examples\demo\ trailing slash handling. 2022-05-24 13:55:39 +02:00
Jeroen van Rijn a8d78660ee Merge pull request #1804 from wjlroe/consistent-os-get-env-across-unix
[os] Darwin,FreeBSD,OpenBSD: Rename os.getenv to os.get_env
2022-05-23 15:57:39 +02:00
Jeroen van Rijn cc1df9591f Merge pull request #1803 from cedric-h/master
Clear up Mismatched BE types error message
2022-05-23 15:48:24 +02:00
William Roe 54a326f046 [os] Darwin,FreeBSD,OpenBSD: Rename os.getenv to os.get_env
Make os.get_env consistent across Unixes

This matches the function name and API from env_windows.odin and os_linux.odin, which should be the same everywhere. Meaning:

* named get_env and not getenv
* return a string (empty if the environment variable is not found)
* accept a default value parameter for the allocator (defaulting to context.allocator)
* calls lookup_env which returns an extra found boolean value

This is so that you don't have to write platform/OS conditionals when getting environment variable values from the stdlib os.get_env/getenv function.
2022-05-23 13:48:55 +01:00
Cedric Hutchings 3d9d85121d Clear up Mismatched BE types error message 2022-05-23 08:14:05 -04:00
gingerBill a31d23a32a Merge pull request #1802 from odin-lang/remove-maybe-tag
Merge functionality of `#maybe` with the standard 'union' functionality
2022-05-23 12:35:06 +01:00
gingerBill 084f431aa5 Correct check_transmute operand logic 2022-05-23 12:19:33 +01:00
gingerBill 7002f0a7d7 Update demo.odin 2022-05-23 12:07:44 +01:00
gingerBill 3ec70c5517 Merge functionality of #maybe with the standard 'union' functionality 2022-05-23 12:04:19 +01:00
gingerBill d9f293b281 Add better error message for trying to dereference a multi-pointer 2022-05-23 11:50:05 +01:00
gingerBill 8c1499dbc2 Make raw_data return [^]T types 2022-05-23 11:48:05 +01:00
gingerBill 7d2eedee73 Unify raw_data in core:mem with core:runtime 2022-05-23 11:47:12 +01:00
gingerBill eba35a8f7d Allow multi pointers in intrinsics 2022-05-23 11:46:44 +01:00
gingerBill e967f2ca2c Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-23 11:34:00 +01:00
gingerBill 438713af20 Allow transmute on constant expressions 2022-05-23 11:33:52 +01:00
gingerBill 568869077e Merge pull request #1801 from cedric-h/master
Add enums for getting Scancodes from WM_KEYDOWN
2022-05-22 20:39:59 +01:00
Cedric Hutchings f25a3f2a7d Add enums for getting Scancodes from WM_KEYDOWN
https://docs.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input
2022-05-22 15:34:49 -04:00
gingerBill 5609221831 Merge pull request #1792 from jasonKercher/os2_linux
Os2 linux
2022-05-22 17:18:28 +01:00
gingerBill f3432e6bb5 Rename to CreateProgramFromStrings 2022-05-21 21:31:24 +01:00
gingerBill 43b350c590 Add more procedures for window related positions 2022-05-21 21:31:05 +01:00
gingerBill c2c66aad60 Add Context_Menu event kind; Fix event_prevent_default() 2022-05-21 17:29:19 +01:00
gingerBill d7681d5b06 Add utilities for Rects 2022-05-21 17:24:03 +01:00
gingerBill c902615192 Improve writeToConole logic for the console.log difference between stdout and stderr 2022-05-21 17:03:44 +01:00
gingerBill 2895830ce6 Add wasm/js/general.odin 2022-05-21 16:37:12 +01:00
gingerBill 1eef9552b4 Fix typo 2022-05-21 16:35:27 +01:00
gingerBill 577fa2d29b Update time procedures for js targets 2022-05-21 16:35:06 +01:00
gingerBill 72fcf16a39 Rename to writeToConsole 2022-05-21 16:15:20 +01:00
gingerBill b9d523e0b2 Add color when writing to stderr 2022-05-21 16:11:10 +01:00
gingerBill f3d225ca4f Improve addConsoleLine 2022-05-21 16:00:36 +01:00
gingerBill d84d2f85e8 Add WebGL helper (CreateProgramHelper) 2022-05-21 15:34:12 +01:00
gingerBill 10f1d8c604 Fix typo 2022-05-21 13:38:38 +01:00
gingerBill 184d1c57b1 Change atomic.wait32 and atomic.notify selection 2022-05-21 13:37:00 +01:00
gingerBill dfbe68bcfe Begin to add support for experimental wasm64 2022-05-21 13:30:43 +01:00
gingerBill 3049e07f72 Add mem.DEFAULT_PAGE_SIZE 2022-05-21 13:30:09 +01:00
gingerBill da54d0ec8c Fix typo 2022-05-21 13:18:11 +01:00
gingerBill b57edb89eb Unify abi for wasm32 and the future wasm64 2022-05-21 13:18:04 +01:00
gingerBill e43eccbb91 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-21 13:02:03 +01:00
gingerBill e48f41165c Begin work on Atomics for wasm32 (wait and notify intrinsics) 2022-05-21 12:58:48 +01:00
gingerBill 9eb4cbcbd2 Improve ABI design for wasm32 targets 2022-05-21 12:32:50 +01:00
gingerBill 2612f241c9 Minor clean up 2022-05-21 12:14:12 +01:00
gingerBill 0f1153fae2 Add page_alloc and page_allocator 2022-05-21 12:11:22 +01:00
Jeroen van Rijn b84561f2b8 Merge pull request #1800 from DaseinPhaos/master
add constants for DXGI_ERROR and DXGI_STATUS
2022-05-21 13:03:35 +02:00
Jeroen van Rijn f7e78e2671 Merge pull request #1799 from cedric-h/master
Fix typo.
2022-05-21 12:59:48 +02:00
Jeroen van Rijn d10a2bc5d5 Format DXGI constants 2022-05-21 12:59:16 +02:00
gingerBill 94fda3d48d Rename to runWasm 2022-05-21 11:41:50 +01:00
gingerBill 5cf4f565d6 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-21 11:39:47 +01:00
gingerBill c20b5cbd10 Change wasm/js/runtime.mjs to a normal .js file; Add interfaces and functions to a global odin variable 2022-05-21 11:39:35 +01:00
gingerBill 115612620f Merge pull request #1798 from Tetralux/filepath-patch
[path/filepath] Change join() to take a []string instead of varargs
2022-05-21 08:50:27 +01:00
Luxko a5bf3b0bc5 add dxgi HRESULT constants 2022-05-21 15:53:20 +09:00
Cedric Hutchings 5c647e2f61 Fix typo. 2022-05-21 01:50:59 -04:00
Tetralux 06884da42b [path/filepath] Change join() to take a []string instead of varargs
This makes passing an allocator easier, as you no longer have to resort to
named arguments:
Before:
  `join(a, b, c)` became `join(elems={a, b, c}, allocator=ally)`
After:
  `join({a, b, c})` becomes `join({a, b, c}, ally)`
2022-05-21 04:48:06 +00:00
Jeroen van Rijn 6e7179d8f3 Merge pull request #1797 from Kelimion/libc_math
Fix is* proc in libc.
2022-05-20 20:05:44 +02:00
Jeroen van Rijn e85f1dd9fb Fix is* proc in libc. 2022-05-20 20:00:27 +02:00
Jeroen van Rijn 9ac94e621b Merge pull request #1796 from Kelimion/make_directory
Fix Windows os.make_directory.
2022-05-20 19:37:40 +02:00
Jeroen van Rijn db8d119cad Fix Windows os.make_directory. 2022-05-20 19:15:13 +02:00
gingerBill 836c325021 Merge pull request #1755 from bkrypt/update_miniaudio
Update `vendor/miniaudio` to v0.11.9
2022-05-19 20:53:19 +01:00
gingerBill 3bb31093fa Add documentation for CreateCurrentContextById and SetCurrentContextById 2022-05-18 13:08:31 +01:00
gingerBill 214b43974d Add WebGL ContextAttributes 2022-05-18 13:06:29 +01:00
gingerBill 55556aea77 Add WebGL runtime into the js/runtime.mjs; Allow for multiple WebGL contexts 2022-05-18 12:31:25 +01:00
gingerBill 223897d224 Fix typo 2022-05-18 12:30:44 +01:00
gingerBill 542e45de26 Increase minimum macOS version to 10.12.0 2022-05-18 12:30:26 +01:00
gingerBill 1fa9488a4d Merge pull request #1795 from Tetralux/os-patch
[os] Linux: os.unset_env()
2022-05-18 11:44:09 +01:00
gingerBill b1196bd659 Merge pull request #1794 from mollstam/fix/optnone-procs
Emit LLVM IR to never optimize/inline procs when building debug and -o:minimal
2022-05-18 10:27:16 +01:00
Tetralux 57167be2a6 [os] Linux: os.unset_env() 2022-05-18 07:12:30 +00:00
Tobias Mollstam 846930a07f emit optnone and noinline for all procs when opt set to minimal 2022-05-18 07:07:20 +02:00
gingerBill 0cc67ff5e3 Add a return value to mem.zero_item and mem.zero_slice which is the same as the input 2022-05-17 22:42:37 +01:00
gingerBill a86574da84 Use RtlWaitOnAddress to allow for a i64 sized duration rather than u32 2022-05-17 22:24:18 +01:00
jason 5a6836ab99 match user.odin and env.odin to master 2022-05-16 15:28:56 -04:00
jason 43432f92ec fix git dummy move 2022-05-16 15:21:36 -04:00
jason d1499f3f78 make -vet happy 2022-05-16 13:57:12 -04:00
jason fff23e2bbb merge from upstream and convert to ^File types 2022-05-16 13:49:57 -04:00
gingerBill 33895b6d92 Convert all uses of *_from_slice to *_from_bytes where appropriate 2022-05-16 01:43:43 +01:00
gingerBill e10105a780 Correct logic for tracking allocator proc for freeing a nil pointer 2022-05-15 23:50:51 +01:00
gingerBill 5451c9672d Fix dynamic_pool_destroy 2022-05-15 23:48:11 +01:00
gingerBill 4eba2bb8d9 Add _system_random for Darwin 2022-05-15 23:46:32 +01:00
gingerBill 2a58bceb56 Add rand.init_as_system to allow for system-level based random number generation 2022-05-15 23:43:20 +01:00
gingerBill fdcf08410c Add Gompertz Distribution 2022-05-15 23:03:01 +01:00
gingerBill 5142955f00 Add more distributions 2022-05-15 22:58:39 +01:00
gingerBill 500150b12a Correct log normal 2022-05-15 22:52:11 +01:00
gingerBill 50ddd8dd26 Fix typo 2022-05-15 22:45:05 +01:00
gingerBill 6c6de2a07d Move distributions to a separate file 2022-05-15 22:20:25 +01:00
gingerBill 01912b6ba5 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-15 21:53:21 +01:00
gingerBill be2c7b5c9b Add numerous different random distribution procedures 2022-05-15 21:53:16 +01:00
gingerBill ed60ed3bae Merge pull request #1789 from Tetralux/os-patch
[os] Linux: Add os.exists(), os.get_env(), os.lookup_env(), os.set_env()
2022-05-15 20:49:55 +01:00
gingerBill 23cb96de02 Commit import _ changes 2022-05-15 16:37:05 +01:00
gingerBill a2c771876e Merge pull request #1788 from odin-lang/image-general-loader
Generalized `core:image` loader
2022-05-15 13:04:26 +01:00
Tetralux b5b329378f [os] Linux: Add os.exists(), os.get_env(), os.lookup_env(), os.set_env()
exists() does the access() syscall.

Renames getenv() to get_env() to match Windows.
2022-05-14 20:14:10 +00:00
gingerBill f7b18cd86e Add DjVu 2022-05-14 15:32:28 +01:00
gingerBill d74e4b427d Remove bool return on image.destroy 2022-05-14 15:16:56 +01:00
gingerBill 22dc020647 Destroy pixel buffer 2022-05-14 15:16:14 +01:00
gingerBill e8485ee7e7 Correction to image.destroy 2022-05-14 15:15:04 +01:00
gingerBill c516fb947f Add image.destroy 2022-05-14 15:11:23 +01:00
gingerBill 3aa0a733f3 Add destroy with loader 2022-05-14 15:06:55 +01:00
gingerBill 4e080057fb Rename load_from_buffer to load_from_bytes 2022-05-14 15:01:17 +01:00
gingerBill 9c1f270bd5 Rename load_from_slice to load_from_bytes across core 2022-05-14 14:55:15 +01:00
gingerBill e46d87b221 Fix type and keep -vet happy 2022-05-14 14:47:58 +01:00
gingerBill 5bc866e420 Allow for import _ "foo" to allow for @(init) procedures; Remove using import code 2022-05-14 14:44:24 +01:00
gingerBill 5af7004f44 Add image packages to examples/all 2022-05-14 14:43:50 +01:00
gingerBill 01e8e682c0 Generalized core:image loader
```odin
import "core:image"
import "core:image/png"

...

img, err := image.load_from_file("path.png")
```
2022-05-14 14:38:26 +01:00
gingerBill 2ef6544ca2 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-14 14:26:50 +01:00
gingerBill 9921ac01cc Add more NetPBM variants 2022-05-14 14:26:11 +01:00
Jeroen van Rijn 7057f5fc11 Add PAM and PFM to format detection. 2022-05-14 15:17:37 +02:00
gingerBill f17a9dd5e7 Add even more file formats 2022-05-14 13:59:49 +01:00
gingerBill ec3394b8da Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-14 13:46:15 +01:00
gingerBill 0cca42a1f4 Add image.which file format testing procedures 2022-05-14 13:46:10 +01:00
Jeroen van Rijn 85edcf9cc2 Revert. 2022-05-14 13:34:52 +02:00
gingerBill 3b842ffe29 Remove semicolons 2022-05-14 12:27:21 +01:00
Jeroen van Rijn 6c0e2e2a53 pool_join should look at .Done. 2022-05-14 13:18:38 +02:00
Jeroen van Rijn 42371f7aea Fix fix. 2022-05-13 15:25:20 +02:00
Jeroen van Rijn 286f782e5e Merge pull request #1786 from Kelimion/thread_fix
Fix thread pool join.
2022-05-13 15:17:08 +02:00
Jeroen van Rijn 58fc305b11 Do a bit less work for pool_join. 2022-05-13 15:11:33 +02:00
Jeroen van Rijn 7e0c359f99 Fix thread pool join. 2022-05-13 15:03:40 +02:00
Jeroen van Rijn f50399e394 Merge pull request #1785 from Kelimion/csv
Allow CSV/TSV reader to read multi-line fields.
2022-05-13 14:33:25 +02:00
Jeroen van Rijn 7bc21c6691 Allow CSV/TSV reader to read multi-line fields. 2022-05-13 14:19:04 +02:00
gingerBill dd56c85e55 Merge pull request #1784 from yay/os-darwin-fixes
os_darwin.odin fixes
2022-05-13 10:10:05 +01:00
Vitaly Kravchenko 9e2a847ebc Typo fix 2022-05-13 09:32:04 +01:00
Vitaly Kravchenko daef39a206 os_darwin.odin fixes 2022-05-13 09:27:15 +01:00
gingerBill 5d496cdcda Merge pull request #1783 from AaronGlazer/master
core:sys/windows - Add flag values for FormatMessageW and LocalAlloc/etc.
2022-05-13 09:21:04 +01:00
gingerBill f27f595549 Add core:encoding/endian 2022-05-12 19:35:07 +01:00
Aaron Glazer 536e0a8c29 Adding flag values for FormatMessageW and LocalAlloc/etc. 2022-05-12 08:22:51 -07:00
gingerBill bc18310107 Correct xml test 2022-05-12 16:01:15 +01:00
gingerBill 3fdb3dd767 Minor style change in leb128.odin 2022-05-12 15:59:15 +01:00
gingerBill d224679619 Minor name changes within core:encoding/xml for consistency 2022-05-12 15:57:03 +01:00
gingerBill 2dd181e663 Remove duplication 2022-05-12 15:48:27 +01:00
gingerBill f002857edc Clean up core:time to be consistent across all platforms 2022-05-12 15:47:24 +01:00
gingerBill 97739da85a Remove core:sys/win32 2022-05-12 14:33:03 +01:00
gingerBill 6c14586fff Add GetAddrInfoExW 2022-05-12 14:27:46 +01:00
gingerBill 0c45a46aab Remove A calls in favour of W calls 2022-05-12 14:21:25 +01:00
gingerBill d1fc9d3073 Add more libraries 2022-05-12 13:54:40 +01:00
gingerBill 2fb351bf04 Update sys/windows to be closer to the soon to be deleted sys/win32 2022-05-12 13:45:17 +01:00
gingerBill dc832ad49f Minor fix 2022-05-12 13:20:55 +01:00
gingerBill eef44b11f3 Make the utf16 conversion procedures in core:sys/windows safer by checking for memory leaks 2022-05-12 13:17:58 +01:00
gingerBill bb4f108487 Update error handling for os2 on windows 2022-05-12 12:54:27 +01:00
gingerBill ccb38c3dc6 Add _safe versions 2022-05-12 12:54:14 +01:00
gingerBill cc81057d21 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-12 11:33:08 +01:00
gingerBill 8b4b81fdeb Fill in most of os2/file_windows.odin 2022-05-12 11:33:01 +01:00
Jeroen van Rijn 4cb46f5631 Merge pull request #1781 from Kelimion/thread_fix
Disable thread.terminate on Darwin for now.
2022-05-11 16:23:56 +02:00
Jeroen van Rijn f4ad4c7aa6 Disable thread.terminate on Darwin for now. 2022-05-11 16:17:35 +02:00
Jeroen van Rijn 37dda30c49 Merge pull request #1780 from Kelimion/thread_fix
Implement `pthread_cancel`.
2022-05-11 15:58:42 +02:00
Jeroen van Rijn 8fb718245a Implement pthread_cancel. 2022-05-11 15:52:04 +02:00
Jeroen van Rijn a4cb6f96ea Merge pull request #1779 from Kelimion/thread_fix
Fix join on *nix.
2022-05-11 13:52:51 +02:00
Jeroen van Rijn 56e3b7cb7d Fix join on *nix. 2022-05-11 13:43:29 +02:00
Jeroen van Rijn ae1f5d2181 Merge pull request #1778 from Thimilius/fix-join_multiple-typo
Fix join_multiple typo
2022-05-11 13:28:12 +02:00
gingerBill b4df272eb5 Improve -vet shadowing to allow x := x if cond else y etc 2022-05-11 12:15:37 +01:00
gingerBill dca2fbccff Improve ternary if type inference 2022-05-11 12:15:10 +01:00
Thimilius d48d3bfa87 Fix join_multiple typo 2022-05-11 13:12:56 +02:00
Jeroen van Rijn 8559790bd8 Fix ; typo. 2022-05-10 20:02:39 +02:00
gingerBill 37c6279031 Add ggpo to examples/all/all_vendor.odin 2022-05-09 23:33:00 +01:00
gingerBill 0d4e710b96 Add vendor:ggpo 2022-05-09 23:32:23 +01:00
gingerBill 205aa10b88 Improve events handling 2022-05-09 22:08:14 +01:00
gingerBill 6f1cc3946b Begin work on Event System for js_wasm32 target 2022-05-09 16:58:34 +01:00
Jeroen van Rijn 253ecd55a0 Merge pull request #1776 from AaronGlazer/master
core:sys/windows: Add some proc bindings, struct definitions, and constant values.
2022-05-08 12:30:01 +02:00
Aaron Glazer c9e31dc90d Adding some proc bindings, struct definitions, and constant values. 2022-05-08 02:34:10 -07:00
Jeroen van Rijn 3d06322d4a Merge pull request #1775 from Kelimion/ctrl_c
Ctrl-C handler on Windows.
2022-05-08 10:45:58 +02:00
Jeroen van Rijn 85e6efdf16 Ctrl-C handler on Windows. 2022-05-08 10:39:03 +02:00
Jeroen van Rijn 6b89ff43ea Merge pull request #1770 from ftphikari/master
sys/windows: fix RGB macro
2022-05-06 17:28:21 +02:00
hikari 4cdc55af91 sys/windows: fix RGB macro again 2022-05-06 18:23:52 +03:00
hikari 4b289f904c sys/win32: fix RGB macro 2022-05-06 13:58:00 +03:00
gingerBill 53c70da0b8 Correct foreign import prefix behaviour for wasm 2022-05-06 11:16:24 +01:00
gingerBill 6f20b5bb59 Add mock for _yield 2022-05-06 10:59:55 +01:00
gingerBill 96ab17ecfc Begin mocking os2 for windows out more 2022-05-05 18:01:44 +01:00
gingerBill 18bde22b26 Go to a File based approach over Handle based 2022-05-05 16:15:03 +01:00
gingerBill e61aad925b Merge branch 'master' of https://github.com/odin-lang/Odin 2022-05-05 15:30:14 +01:00
gingerBill 5d190b15d7 Minor improvements to io and os 2022-05-05 15:30:07 +01:00
Jeroen van Rijn fe442d7c0c [mem] Fix Dynamic_Pool. 2022-05-05 10:45:15 +02:00
jason 97d1a67871 make vet happy, thread_local heap 2022-05-04 18:45:39 -04:00
jason bac96cf2ad fix mmap_to_region 2022-05-04 18:32:14 -04:00
jason 7e0cc0af25 heap_linux.odin 2022-05-04 17:55:15 -04:00
Jeroen van Rijn 1d29d9be25 Merge pull request #1769 from zhibog/fix_1761
Fix issue #1761. Added the test vector to the core and vendor tests
2022-05-04 22:21:55 +02:00
zhibog 0e91e63043 Fix issue 1761. Added the test vector to the core and vendor tests 2022-05-04 22:13:50 +02:00
gingerBill 0cf37bde8b Update foreign import for OpenEXRCore for non-windows platforms 2022-05-04 17:51:36 +01:00
gingerBill 173799527a Merge pull request #1768 from odin-lang/link-order
Make the link order of foreign imports deterministic
2022-05-04 17:04:18 +01:00
gingerBill 5931e2383b Remove unneeded #if defined 2022-05-04 16:58:40 +01:00
gingerBill e4743b15b1 Add @(priority_index=<int>) for foreign import 2022-05-04 16:40:12 +01:00
gingerBill 9f95d6fa65 Minor move around for path sets 2022-05-04 16:17:24 +01:00
gingerBill 982a1aebb3 Remove stray line 2022-05-04 16:14:42 +01:00
gingerBill cec049b7d3 Make the link order of foreign imports deterministic 2022-05-04 16:04:26 +01:00
Jeroen van Rijn dc323cfa1d Small fix to deprecation warning. 2022-05-04 13:29:52 +02:00
gingerBill 0afa226a93 Merge pull request #1766 from odin-lang/vendor-openexr
`vendor:OpenEXRCore`
2022-05-03 15:28:28 +01:00
gingerBill 1146604344 Add LICENSE.md 2022-05-03 14:52:09 +01:00
gingerBill 89c2e1a5fa Add vendor:OpenEXRCore to examples/all 2022-05-03 14:22:25 +01:00
gingerBill 971d498e79 Change path 2022-05-03 14:21:24 +01:00
gingerBill 6e7a50c02f Add .lib for vendor:openexr 2022-05-03 14:11:26 +01:00
Jeroen van Rijn 6aaab4988e Merge pull request #1765 from Kelimion/more_opt_handling
Handle negative integer flags, add deprecation warnings.
2022-05-03 14:01:22 +02:00
Jeroen van Rijn d9b0c05acf Typo. 2022-05-03 13:47:13 +02:00
Jeroen van Rijn 47f637d23b Add deprecation warnings for -opt and flag=value insted of flag:value. 2022-05-03 13:37:07 +02:00
Jeroen van Rijn 59f55a2119 Make big_int_from_string return an error if not an integer. 2022-05-03 13:15:49 +02:00
Jeroen van Rijn 8bac82320f Fix -opt: parsing. 2022-05-03 11:44:55 +02:00
Jeroen van Rijn 14bf20320a Merge pull request #1764 from Kelimion/xxh3_tests
[xxhash] For the streaming tests, randomly select the size to use.
2022-05-02 19:30:40 +02:00
Jeroen van Rijn b99940f33a [xxhash] For the streaming tests, randomly select the size to use.
Randomize size used with `update`.

It'll print "Using user-selected seed {18109872483301276539,2000259725719371} for update size randomness."

If a streaming test then fails, you can repeat it using:
`odin run . -define:RAND_STATE=18109872483301276539 -define:RAND_INC=2000259725719371`
2022-05-02 19:20:25 +02:00
Jeroen van Rijn 81495068b9 Merge pull request #1763 from Kelimion/xxh3_tests
[xxhash] Add tests for large inputs
2022-05-02 17:57:48 +02:00
Jeroen van Rijn 6985181961 [xxhash] Add tests for large inputs
Test XXH32, XXH64, XXH3-64 and XXH3-128 for large inputs, with both all-at-once and streaming APIs.

XXH32_create_state and XXH64_create_state now implicitly call their "reset state" variants to simplify the streaming API to 3 steps:
- create state / defer destroy
- update
- digest (finalize)

These are tested with an array of 1, 2, 4, 8 and 16 megabytes worth of zeroes.
All return the same hashes as do both the one-shot version, as well as that of the official xxhsum tool.

3778/3778 tests successful.
2022-05-02 17:51:39 +02:00
gingerBill 97717d65ef Add vendor:openexr
No foreign library yet
2022-05-02 16:09:09 +01:00
gingerBill 8023c8abc7 Fix @(disable=...) 2022-05-02 14:10:02 +01:00
gingerBill 2d3f59d9a7 Merge pull request #1758 from ftphikari/master
sys/windows: add a couple procedures and tons of constants
2022-05-02 13:11:25 +01:00
gingerBill be8de4a1ff Update arch enum 2022-05-01 23:52:55 +01:00
gingerBill 18ad6c33ef Implement syscall for arm32 2022-05-01 23:32:31 +01:00
gingerBill 0e27b27b81 Fix building issues with arm32 2022-05-01 23:28:32 +01:00
gingerBill 10a311092b Add basic arm32 ABI support (linux_arm32) 2022-05-01 23:15:06 +01:00
Jeroen van Rijn 18463d68d4 Merge pull request #1762 from WalterPlinge/netpbm-doc-fix
Fixed incorrect values in the docs for the Netpbm package
2022-05-01 22:39:15 +02:00
WalterPlinge 74d3bcec05 Fixed the depth values in the doc file, made some info more clear 2022-05-01 21:29:09 +01:00
Jeroen van Rijn df233aee94 Merge pull request #1760 from Kelimion/xxh3_fix
[xxh3] Fix flaws in streaming implementation
2022-05-01 12:54:20 +02:00
Jeroen van Rijn 335b724209 [xxh3] Fix flaws in streaming implementation 2022-05-01 12:47:05 +02:00
hikari b2fdb881eb sys/windows: remove A variant for one SystemParametersInfoW 2022-05-01 13:21:28 +03:00
Jeroen van Rijn 6ade9acc4d [pbm] Remove stray comment. 2022-04-30 22:54:53 +02:00
Jeroen van Rijn 2081f8fcd6 [tests/core/image] Remove old crappy PPM writer. 2022-04-30 22:04:47 +02:00
Jeroen van Rijn 964ab4814c Merge pull request #1726 from WalterPlinge/image-netpbm
Add Netpbm image format support
2022-04-30 22:01:22 +02:00
Jeroen van Rijn 7a032cf9f9 [pbm] Also test PFM formats. 2022-04-30 21:57:14 +02:00
Jeroen van Rijn 694c13fe86 Merge branch 'master' into pr/1726 2022-04-30 21:01:04 +02:00
Jeroen van Rijn 8bd16c32f3 [pbm] Fixes. 2022-04-30 21:00:32 +02:00
bkrypt be9b935953 Fix indentation 2022-04-30 20:43:22 +02:00
bkrypt 9e69452327 Remove unnecessary value (count) from enum 2022-04-30 20:42:42 +02:00
Jeroen van Rijn 234d529867 [pbm] WIP unit tests. part deux. 2022-04-30 19:25:16 +02:00
Jeroen van Rijn dd8b71e353 [pbm] WIP unit tests. 2022-04-30 17:52:23 +02:00
hikari d24bebdb9e sys/windows: add a couple procedures and tons of constants 2022-04-30 16:55:37 +03:00
Jeroen van Rijn 41a18f078d Merge pull request #1757 from Kelimion/xml
[xml] Add `parse_from_string` overload.
2022-04-30 14:51:46 +02:00
Jeroen van Rijn 3978e7e1ca [xml] Add parse_from_string overload.
`parse` now takes either a `[]u8` slice or a string.
`load_from_file` takes a path string.
2022-04-30 14:43:58 +02:00
gingerBill b758c696f2 Merge pull request #1746 from odin-lang/sync-cond-futex
`core:sync` Improvements
2022-04-30 13:34:16 +01:00
Jeroen van Rijn d6a8216ce4 [pbm] Normalize some errors, correct .depth 2022-04-30 14:34:07 +02:00
gingerBill 2720f64c06 Remove unused imports 2022-04-30 13:28:45 +01:00
gingerBill de2ebdd5cc Merge pull request #1753 from awwdev/master
Fixing some typos in vendor:OpenGL
2022-04-30 13:28:02 +01:00
gingerBill 4e39629a9a Unify implementation for *nix platforms 2022-04-30 13:09:24 +01:00
gingerBill 78a8da5fea Add sync.Parker 2022-04-30 12:37:39 +01:00
gingerBill d5886c1572 Remove the wait group based semaphore implementation
It was a misuse of the data structure
2022-04-30 12:37:14 +01:00
Jeroen van Rijn 7cc759a855 Merge pull request #1756 from ftphikari/master
sys/windows: add a couple of procedures and types
2022-04-30 12:46:11 +02:00
gingerBill dd6337224f Correct explicit atomic orderings 2022-04-30 11:42:28 +01:00
hikari d2bac0c35e sys/windows: fix build issues 2022-04-30 13:40:38 +03:00
hikari 8c7f3fd1e6 sys/windows: change macro and add comment 2022-04-30 13:34:11 +03:00
Jeroen van Rijn ae3deea153 Merge branch 'master' into pr/1726 2022-04-30 12:29:28 +02:00
hikari 40bea95fb0 sys/windows: add GetDCBrushColor 2022-04-30 12:41:04 +03:00
hikari 0ad448f1c7 sys/windows: add a couple of procedures and types 2022-04-30 11:21:37 +03:00
bkrypt 4911df9f99 Remove unneeded semicolons 2022-04-29 21:39:10 +02:00
bkrypt a223340c44 Update vendor/miniaudio to v0.11.9 2022-04-29 21:13:25 +02:00
Jeroen van Rijn 9c9c2b483c [i18n] Enable *nix tests again. 2022-04-29 18:41:21 +02:00
Jeroen van Rijn 819345caa6 Disable i18n test for *nix for now. 2022-04-29 18:28:42 +02:00
Jeroen van Rijn 11ceb3973d Merge pull request #1754 from Kelimion/i18n
[i18n] Fix segfault on cleanup on Linux
2022-04-29 18:20:54 +02:00
Jeroen van Rijn 36263399a0 [i18n] Enable i18n test on Linux. 2022-04-29 18:13:46 +02:00
Jeroen van Rijn ff0f0c447f [i18n] Fix segfault on destroy on Linux
Forgot to intern the section string in QT TS loader.
2022-04-29 18:10:13 +02:00
Jeroen van Rijn aa681932a9 Merge pull request #1336 from Kelimion/i18n
[i18n] Initial i18n support.
2022-04-29 16:27:28 +02:00
Jeroen van Rijn 09e1c0fa27 [i18n] Add tests. 2022-04-29 16:19:13 +02:00
Jeroen van Rijn 957ef8e8fe [i18n/xml] Move I18N XML files to their own assets directory. 2022-04-29 13:16:30 +02:00
Jeroen van Rijn 2e11a8da5b [i18n] Move to core:text/i18n. 2022-04-29 13:02:40 +02:00
awwdev e9cfcf9ecc fix typo in TexImage3D 2022-04-29 11:26:57 +02:00
awwdev 789ab99c4d replaced a few [^]u8 with cstring 2022-04-29 11:21:23 +02:00
Jeroen van Rijn 0297db6f2e Merge pull request #1752 from sduman/patch-1
Add missing result parameter names
2022-04-29 01:21:35 +02:00
sduman 9ce64916e6 Add missing result parameter names
This adds some missing result parameters names back to pop_front_safe.

Currently it the procedure won't compile since it's referencing missing variable names.
2022-04-28 17:08:48 -06:00
Jeroen van Rijn 1289c96e2c [i18n] QT Linguist TS reader. 2022-04-29 00:29:55 +02:00
Jeroen van Rijn ba23bfb7b9 [i18n] Allow multiple sections. 2022-04-28 20:12:32 +02:00
Jeroen van Rijn 2fae6eda23 [i18n] Initial i18n support.
- Add initial GetText .MO parser
- Add translation struct and helpers
- Pluralized lookup

 TODO:
- Support for more translation catalog file formats.
2022-04-28 18:58:49 +02:00
Jeroen van Rijn e53ba3b116 Allow -error-pos-style:default as an alias for odin 2022-04-28 18:18:25 +02:00
Jeroen van Rijn 1ed84a064b Make -error-pos-style case-insensitive. 2022-04-28 18:12:55 +02:00
Jeroen van Rijn 79019c7a09 Merge pull request #1751 from Kelimion/error-pos-style
Fix -error-pos-style:unix
2022-04-28 17:52:47 +02:00
Jeroen van Rijn a1002e6960 Fix -error-pos-style:unix 2022-04-28 17:46:36 +02:00
Jeroen van Rijn 62139cb5a4 Merge pull request #1342 from Kelimion/xml
Initial version of `core:encoding/xml`.
2022-04-28 15:54:28 +02:00
Jeroen van Rijn 127b0ba65e [xml] Enable tests. 2022-04-28 15:46:36 +02:00
Jeroen van Rijn 80878264b6 [xml] Speedup. 2022-04-28 15:29:00 +02:00
gingerBill 9fcba99ca2 Merge pull request #1749 from karl-zylinski/d3d12-binding-fixes
D3D12 binding fixes
2022-04-27 22:16:24 +01:00
Karl Zylinski 03c9212600 Added some additional IID versions of Direct3D 12 UUIDs that I missed during my first pass. All are accounted for now. 2022-04-27 22:30:28 +02:00
Karl Zylinski 5650087aa3 Merge remote-tracking branch 'origin/master' into d3d12-binding-fixes 2022-04-27 20:50:54 +02:00
Karl Zylinski 67689ecb21 Typo fix in d3d12.odin 2022-04-27 20:47:05 +02:00
Karl Zylinski cd13dedb36 D3D12 binding fixes: Added dxgi.IID versions of all the UUIDs in d3d12.odin so that the IIDs can be used to fetch interfaces properly. Also fixed an issue where GetDesc, GetCPUDescriptorHandleForHeapStart and GetGPUDescriptorHandleForHeapStart had the wrong signature due to an old D3D12 header bug, more info: https://stackoverflow.com/questions/34118929/getcpudescriptorhandleforheapstart-stack-corruption 2022-04-27 20:12:44 +02:00
gingerBill 10cd294cf2 Use Acquire semantics for the futex_wait load shortcut 2022-04-27 15:57:47 +01:00
gingerBill d6cfb60506 Remove prev from Atomic_Cond 2022-04-27 15:29:21 +01:00
gingerBill df0df73540 Merge branch 'master' into sync-cond-futex 2022-04-27 15:26:21 +01:00
gingerBill 33f1418dec Merge branch 'master' of https://github.com/odin-lang/Odin 2022-04-27 15:26:02 +01:00
gingerBill 305510bea0 Update intrinsics.odin 2022-04-27 15:25:56 +01:00
gingerBill beb698f31d Merge branch 'master' into sync-cond-futex 2022-04-27 15:21:18 +01:00
Jeroen van Rijn 6df21d6a9f Merge branch 'master' into xml 2022-04-27 16:13:47 +02:00
Jeroen van Rijn c5982e52d5 Merge pull request #1748 from Kelimion/test-assets
Move Odin CI test assets over to its own repository.
2022-04-27 16:04:15 +02:00
gingerBill bd73b2845b Unify default Sema and Atomic_Sema behaviour 2022-04-27 15:03:48 +01:00
Jeroen van Rijn da0f722aad Move Odin CI test assets over to its own repository. 2022-04-27 15:56:45 +02:00
gingerBill 904f0407f8 Add intrinsics.type_is_multi_pointer 2022-04-27 14:53:26 +01:00
gingerBill fbbb0d7610 Update intrinsics.odin for documentation 2022-04-27 14:51:04 +01:00
gingerBill 3a9b0a22e7 Add core:container/intrusive/list 2022-04-27 14:27:33 +01:00
Jeroen van Rijn c4e0d1efa1 Merge branch 'master' into xml 2022-04-27 14:37:15 +02:00
gingerBill 9349dfba8f Add new builtin container_of 2022-04-27 12:39:45 +01:00
gingerBill 9692496989 Add intrinsics.type_field_type 2022-04-27 12:27:53 +01:00
CiD- 5bc8164274 add mremap + flags 2022-04-26 17:11:30 -04:00
gingerBill a6cef2e50e Update LICENSE 2022-04-26 21:47:45 +01:00
Jeroen van Rijn d262eda91c Update Makefile 2022-04-26 15:10:31 +02:00
Jeroen van Rijn 40f0f5ad8d Update CI for math library. 2022-04-26 15:01:09 +02:00
Jeroen van Rijn 1c03e68057 Update CI. 2022-04-26 14:56:28 +02:00
Jeroen van Rijn f1c1cfb6d2 Merge pull request #1747 from Kelimion/filename-merge
Filename generation
2022-04-26 14:52:58 +02:00
Jeroen van Rijn ba5e33bc35 Update CI workflow. 2022-04-26 14:51:16 +02:00
gingerBill 80df9fbc65 Merge pull request #1745 from eisbehr/patch-1
Make allocator in pool_add_task() explicit
2022-04-26 13:49:44 +01:00
Jeroen van Rijn b68ab0dd6d Merge branch 'master' into filename-merge 2022-04-26 14:45:00 +02:00
gingerBill 9cf7a31068 Implement _Sema with Atomic_Sema 2022-04-26 13:44:32 +01:00
Jeroen van Rijn 5e11ad2e1e Update test paths. 2022-04-26 14:23:23 +02:00
gingerBill 07d1a42768 Simplify Atomic_Sema implementation 2022-04-26 13:11:34 +01:00
gingerBill ec8221cb5d Simplify Atomic_Cond implementation 2022-04-26 13:04:50 +01:00
Jeroen van Rijn a5342a0126 Address edge cases. 2022-04-26 13:14:09 +02:00
gingerBill c81fd2e5dd Fix #1644 2022-04-26 11:45:46 +01:00
gingerBill 3bd7122959 Fix #1720 2022-04-26 11:42:01 +01:00
gingerBill 530401e5ee Fix #1729 2022-04-26 11:38:32 +01:00
gingerBill a412d34574 Fix #1740 2022-04-26 11:35:34 +01:00
Florian Behr ee67a0b9a1 reorder procedure parameters to make sure the optional argument in pool_add_task() is last, and the argument order is consistent with pool_init() 2022-04-25 14:08:09 +02:00
Florian Behr ca6a1db757 fix doc comment for pool_init 2022-04-25 13:41:39 +02:00
Florian Behr 1fb76ad768 change usage in demo.odin 2022-04-25 13:41:19 +02:00
Florian Behr e01662c139 Make allocator in pool_add_task() explicit 2022-04-25 13:23:05 +02:00
Jeroen van Rijn 63331ef731 Revert "Merge pull request #1702 from Kelimion/filename_generation"
This reverts commit a40a53b104, reversing
changes made to 5422a3b17e.
2022-04-24 19:53:36 +02:00
Jeroen van Rijn a40a53b104 Merge pull request #1702 from Kelimion/filename_generation
Compiler: Add early error for output path being a directory.
2022-04-24 15:15:51 +02:00
Jeroen van Rijn 9f8d90f466 Update CI paths for issue tests. 2022-04-24 14:28:00 +02:00
Jeroen van Rijn 3d2856db31 Update tests to use new filename generation code. 2022-04-24 14:19:25 +02:00
Jeroen van Rijn f4723aea4c Remove redundant bit for non-Windows. 2022-04-24 13:37:26 +02:00
Jeroen van Rijn 76d48b38d3 Compiler: Allow -out: to not have an extension on *nix for executables (only). 2022-04-24 13:37:26 +02:00
Jeroen van Rijn 3cab2592c3 Compiler: Add early error for output path being a directory.
- Introduce new `Path` type and an array of build paths on the build context.
- Resolve input and output paths/files early (before parsing).
- Error early if inputs are missing or outputs are directories.
- Plumb new file path generation into linker stage instead of its adhoc method.

TODO:
- Remove more adhoc file path generation in parser and linker stage.
- Make intermediate object file generation use new path system.
- Round out and robustify Path helper functions.
2022-04-24 13:37:26 +02:00
Jeroen van Rijn 5422a3b17e Merge pull request #1743 from Tetralux/filepath-stems
[path/filepath] Add file stem and long-extension procedures
2022-04-23 22:33:31 +02:00
Tetralux b44b6e7e50 [path/filepath] Add file stem and long-extension procedures
Adds stem(), short_stem(), and long_ext(); also adds doc-comments to base() and ext().

The 'stem' is usually 'the name' of the file; the basename without the file extension.
To this end, this adds stem(), which is such that:

	stem(path) + ext(path) = base(path)

However, 'file extension' has two different meanings to what constitutes it!

 > What is the extension of: 'name.tar.gz' ?

Colloquially, you would likely think of it as 'a tarball' - which you might think is '.tar.gz'.
But, if you're writing code to process a file of this type, you would first treat it
as a Gzip file, and then treat the result as a TAR file - i.e: '.gz' ... _followed by_ '.tar'.

ext() returns '.gz' here, since that is the most-immediate format that you would need to use
to decode it; it would be a Gzip stream.

Sometimes though, you do actually want to consider these longer file extensions.

Perhaps you're extracting a tarball, and what to know what to call the intermediate tar file;
perhaps you want to check to see if this file is a tarball, or just a Gzip file;
or maybe you just want 'the name' of the file, and not this "strange 'name-and-part-of-the-extension' thing".

So, this also adds short_stem() and long_ext(), such that:

	short_stem(path) + long_ext(path) = base(path)

Thus, we can use either, but the most immediately-useful one is the easiest to reach for:

      stem('name.tar.gz') -> 'name.tar'
       ext('name.tar.gz') -> '.gz'

short_stem('name.tar.gz') -> 'name'
  long_ext('name.tar.gz') -> '.tar.gz'

These procedures are identical to their counterparts when the path only has a simple extension:

      stem('name.txt') -> 'name'
       ext('name.txt') -> '.txt'

short_stem('name.txt') -> 'name'
  long_ext('name.txt') -> '.txt'
2022-04-23 20:25:59 +00:00
Jeroen van Rijn 849efff070 Merge pull request #1741 from Kelimion/shoco
Add Shoco short string compression.
2022-04-22 18:06:31 +02:00
Jeroen van Rijn b022167df1 Remove unused fmt. 2022-04-22 17:56:34 +02:00
Jeroen van Rijn ac9a358c65 [shoco] Replace 2D slices in model with 1D slices. 2022-04-22 17:52:38 +02:00
Jeroen van Rijn e799476f90 [compress/shoco] Add short string compressor. 2022-04-22 16:55:47 +02:00
Jeroen van Rijn b4f8efcbe6 Merge pull request #1739 from ftphikari/master
strings: add levenshtein_distance procedure
2022-04-21 20:31:11 +02:00
hikari f026753692 strings: levenshtein_distance: remove do 2022-04-21 21:19:43 +03:00
hikari 71b1cce517 strings: levenshtein_distance: 64 is actually faster than 256 2022-04-21 21:19:11 +03:00
hikari d8f0da164b strings: levenshtein_distance: improve potential caching 2022-04-21 21:15:11 +03:00
hikari 591732f347 strings: levenshtein_distance: remove costs calculation for default array 2022-04-21 20:58:50 +03:00
hikari eee97f7f62 strings: add levenshtein_distance procedure 2022-04-21 20:49:32 +03:00
Jeroen van Rijn 3dd9da1b66 Merge pull request #1733 from ftphikari/master
sys/windows: add some procedures
2022-04-19 20:41:32 +02:00
Jeroen van Rijn e8c0be23f2 Merge pull request #1737 from Kelimion/fix_json_unmarshal
[json/unmarshal] Fix quoted strings.
2022-04-19 20:40:40 +02:00
Jeroen van Rijn a30b9b17b3 [json/unmarshal] Fix quoted strings. 2022-04-19 20:32:22 +02:00
Jeroen van Rijn 29b2c04766 Revert "Fix unmarshal for escaped strings."
This reverts commit 581255bf23.
2022-04-19 20:11:02 +02:00
Jeroen van Rijn d869ba7bcd Merge pull request #1736 from Kelimion/fix_json_unmarshal
Fix unmarshal for escaped strings.
2022-04-19 20:05:04 +02:00
Jeroen van Rijn 581255bf23 Fix unmarshal for escaped strings. 2022-04-19 20:04:38 +02:00
Jeroen van Rijn b51358a01c Merge pull request #1734 from hanabi1224/lru-alloc-fix
[core:container/lru] Avoid unnecessary allocations
2022-04-19 15:04:49 +02:00
Jeroen van Rijn 323e7a2d02 Add JSON unmarshal test. 2022-04-19 15:03:09 +02:00
Jeroen van Rijn 7654afc2db Revert "Update mem.nil_allocator to match the same in runtime"
The change broke JSON unmarshaling.

This reverts commit 4484a3433d.
2022-04-19 15:01:54 +02:00
hanabi1224 ded8342f3f Reduce allocations 2022-04-19 20:46:33 +08:00
ftphikari 240fb9b953 Merge branch 'odin-lang:master' into master 2022-04-19 06:00:30 +03:00
hikari 4997a43763 Merge remote-tracking branch 'origin/master' 2022-04-19 05:59:42 +03:00
hikari aa4eb35671 sys/windows: add some procedures 2022-04-19 05:58:22 +03:00
Jeroen van Rijn d99ba9c073 Merge pull request #1731 from Kelimion/targa
[image/tga] Writer for RGB(A) 8-bit images.
2022-04-18 23:36:45 +02:00
Jeroen van Rijn fdd24f787f [image/tga] Writer for RGB(A) 8-bit images. 2022-04-18 23:28:34 +02:00
WalterPlinge b6abd691f4 Image: Fix implicit enum error 2022-04-18 20:42:50 +01:00
WalterPlinge 8d370fabdd Added initial Netpbm image format support 2022-04-18 20:29:37 +01:00
Jeroen van Rijn df4a0c62ad Delete accidentally added test artefact. 2022-04-18 19:10:53 +02:00
Jeroen van Rijn e3e3309a9b Merge pull request #1728 from Tetralux/more-slice-helpers
Duplicate some basic slice procedures from core:mem into core:slice
2022-04-18 19:05:20 +02:00
Tetralux 7428e52264 Duplicate some basic slice procedures from core:mem into core:slice 2022-04-18 16:56:45 +00:00
Jeroen van Rijn 20b70c3b7b Merge pull request #1727 from hanabi1224/fix-lru
Fix bugs in core:container/lru
2022-04-18 13:39:23 +02:00
hanabi1224 4247ba67ed Fix bugs in core:container/lru 2022-04-18 15:24:54 +08:00
Jeroen van Rijn e738e93da0 Merge pull request #1723 from ftphikari/master
sys/windows: add timeEndPeriod
2022-04-17 18:27:07 +02:00
hikari b78f3a8069 sys/windows: add timeEndPeriod 2022-04-17 19:17:38 +03:00
Jeroen van Rijn 939973acd7 [QOI] Add to examples/all. 2022-04-17 12:35:34 +02:00
gingerBill ed4cb72b19 Merge pull request #1696 from Despacito696969/master
Fix for `slice_to_components` compilation error
2022-04-16 21:56:13 +01:00
Jeroen van Rijn 70cbffd58b Merge pull request #1722 from Kelimion/varint_streamed
[LEB128] Add byte-at-a-time ILEB decoder.
2022-04-16 18:19:38 +02:00
Jeroen van Rijn 6d0ba8d189 [LEB128] Add byte-at-a-time ILEB decoder. 2022-04-16 18:14:01 +02:00
Jeroen van Rijn b6f3fa6ee1 Merge pull request #1719 from ftphikari/precise_sleep
time: add accurate sleep procedure
2022-04-16 16:52:46 +02:00
Jeroen van Rijn 91037766d2 Update time.odin
Add caveats.
2022-04-16 16:48:08 +02:00
hikari 8bf73950fa time: remove unnecessary yield 2022-04-16 14:36:48 +03:00
hikari 4f4793817c time: fix unix build 2022-04-16 14:35:49 +03:00
hikari 0a0440a6e8 time: yield accurate_sleep instead of relaxing the cpu 2022-04-16 14:08:37 +03:00
hikari b9dc81d808 runtime: update comment description 2022-04-16 13:46:36 +03:00
Jeroen van Rijn 8e7ddccf00 Merge pull request #1717 from ftphikari/master
sys/windows: add procedures and types
2022-04-16 12:38:39 +02:00
Jeroen van Rijn a5773f1657 Merge pull request #1718 from Kelimion/varint_streamed
Add uleb128 byte-at-a-time decoder.
2022-04-16 02:20:07 +02:00
Jeroen van Rijn 44316401c9 Add uleb128 byte-at-a-time decoder. 2022-04-16 02:07:57 +02:00
hikari b05fbaacda time: add accurate sleep procedure 2022-04-16 00:32:17 +03:00
hikari 1b4d5b73ab sys/windows: add some constants 2022-04-15 22:04:34 +03:00
hikari d3fbf36df7 sys/windows: add winmm bindings file 2022-04-15 19:18:22 +03:00
ftphikari de819cff94 Merge branch 'odin-lang:master' into master 2022-04-15 19:16:52 +03:00
hikari cfae39c29d sys/windows: add procedures and types 2022-04-15 19:16:31 +03:00
gingerBill 989641a616 Update Vulkan generation and package 2022-04-15 12:14:12 +01:00
gingerBill fc3f62e3ed Minor rearrangement 2022-04-15 11:50:08 +01:00
gingerBill 6b7c04e046 Improve utilities 2022-04-15 11:33:28 +01:00
gingerBill cfeb16f917 Add more proc groups 2022-04-15 11:20:42 +01:00
gingerBill 9a2d9002e6 Minor fixes and add use of proc groups where better suited 2022-04-15 11:14:59 +01:00
gingerBill ea0b02d9b9 Add Buffer contentsAsSlice and contentsAsType 2022-04-14 16:42:24 +01:00
gingerBill 0d621511e5 Correct signature types 2022-04-14 16:16:53 +01:00
gingerBill e53c858855 Add NS.Block to allow for the creation of block-like lambdas in Odin 2022-04-14 15:47:49 +01:00
gingerBill 8a9f7fc684 Fix #1713 2022-04-14 15:09:03 +01:00
gingerBill 51db46551e Add MetalKit; Add NSApplication NSMenu NSMenuItem; Improve Metal classes 2022-04-14 15:03:47 +01:00
gingerBill 600b79276a Merge pull request #1709 from ap29600/quicksort_fix
Fix tail recursion in `_quick_sort_general`
2022-04-13 11:20:46 +01:00
Andrea Piseri a040be957f Fix tail recursion in _quick_sort_general
The `if` statement should have been a `for` loop, in order to allow recursively
sorting the subarrays with quicksort, and not resort to shell sort after
one step.
2022-04-13 10:55:16 +02:00
Jeroen van Rijn f6fa553572 Merge pull request #1708 from Kelimion/varint_doc
[varint] Clear up doc.odin.
2022-04-13 00:03:58 +02:00
Jeroen van Rijn 8310436350 [varint] Clear up doc.odin. 2022-04-13 00:03:36 +02:00
Jeroen van Rijn f92ffe60e7 Merge pull request #1699 from ftphikari/master
mem: replace size procedures with constants
2022-04-12 20:12:05 +02:00
Jeroen van Rijn de72754d7a Merge pull request #1707 from Kelimion/qoi
[image] Add QOI load/save.
2022-04-12 19:33:11 +02:00
Jeroen van Rijn bf712e9355 [QOI] Add support for RGB images (previously loader always output RGBA).
Also add QOI to CI test suite by roundtripping 8-bit RGB(A) through QOI and checking the hashes match.
2022-04-12 19:23:48 +02:00
Jeroen van Rijn ab9457346d [PNG] Remove debug printf. 2022-04-12 18:26:10 +02:00
Jeroen van Rijn 15b440c4f1 [image] Add QOI load/save.
Additionally:
- Firm up PNG loader with some additional checks.
- Add helper functions to `core:image` to expand grayscale to RGB(A), and so on.

TODO: Possibly replace PNG's post-processing steps with calls to the new helper functions.
2022-04-12 18:14:09 +02:00
CiD- 1a2c36e482 whoops 2022-04-08 13:52:36 -04:00
CiD- 56737c1431 merge upstream/master 2022-04-08 13:50:06 -04:00
CiD- 9ae566adcc commit before fetching upstream/master 2022-04-08 13:45:19 -04:00
gingerBill f2f1330238 Add https://github.com/odin-lang/examples 2022-04-08 10:29:23 +01:00
hikari c4a7739d13 sys/windows: add a couple macros 2022-04-07 19:28:24 +03:00
Mikkel Hjortshøj 8a8b5c753f Update README.md 2022-04-07 16:48:34 +02:00
hikari ad90f416a5 runtime: fix typo 2022-04-07 12:24:53 +03:00
hikari 698fcb7813 mem: replace size procedures with constants 2022-04-06 18:44:43 +03:00
CiD- aadb4db211 avoid temp_allocator on stupidly long paths 2022-04-06 10:53:46 -04:00
gingerBill 426a6a9528 Update nightly.yml to build the directory 2022-04-05 21:10:24 +01:00
Jeroen van Rijn 50b9c48609 Merge pull request #1697 from Kelimion/build_file
Give build/run/check/test/doc a `-file` flag.
2022-04-05 20:52:28 +02:00
Jeroen van Rijn 767ed21bfe -file for tests\issues. 2022-04-05 20:47:37 +02:00
Jeroen van Rijn bb9165edd2 Add -help to CI tests. 2022-04-05 20:45:00 +02:00
Jeroen van Rijn ad0a413b40 Give build/run/check/test/doc a -file flag.
A package has canonically always been a directory, but odin allowing you to build a single-file package confused newcomers who didn't understand why they could then not access variables and procedures from another file in the same directory.

This change disallows building single-file packages by default, requiring the `-file` flag to acknowledge you understand the nuance.

`-help` for these commands also clarifies the difference.

```
W:\Odin>odin build -help
odin is a tool for managing Odin source code
Usage:
        odin build [arguments]

        build   Compile directory of .odin files as an executable.
                One must contain the program's entry point, all must be in the same package.
                Use `-file` to build a single file instead.
                Examples:
                        odin build .                    # Build package in current directory
                        odin build <dir>                # Build package in <dir>
                        odin build filename.odin -file  # Build single-file package, must contain entry point.

        Flags

        -file
                Tells `odin build` to treat the given file as a self-contained package.
                This means that `<dir>/a.odin` won't have access to `<dir>/b.odin`'s contents.
```

```
W:\Odin>odin run examples\demo\demo.odin
ERROR: `odin run` takes a package as its first argument.
Did you mean `odin run examples\demo\demo.odin -file`?
The `-file` flag tells it to treat a file as a self-contained package.
```
2022-04-05 20:26:18 +02:00
Despacito696969 7f6c6945ae Fix for slice_to_components
Using `slice_to_components` wouldn't compile because `s.data` is type of `rawptr` and return type is `^T`
2022-04-05 20:17:47 +02:00
gingerBill ca549939f3 Update README.md 2022-04-05 13:33:25 +01:00
gingerBill cdb003bf23 Add Packages and Nightly Builds to README.md 2022-04-05 13:32:06 +01:00
gingerBill a4d2ff05a9 Merge pull request #1688 from bkrypt/fix_file_windows_open_create_append_order
os/file_windows: Fix "create or append" file open behavior
2022-04-05 12:29:20 +01:00
gingerBill 48012ec73c Merge pull request #1679 from Tetralux/fix-std-handle
Have get_std_handle() no longer make the handles uninheritable
2022-04-05 12:15:14 +01:00
Jeroen van Rijn e7dc00b758 Merge pull request #1695 from ftphikari/master
sys/windows: add Dwmapi.lib binding
2022-04-05 13:10:52 +02:00
hikari ef1fbbbce6 Merge branch 'master' of github.com:ftphikari/Odin 2022-04-05 14:04:03 +03:00
hikari 2a59aebe5b sys/windows: add Dwmapi.lib binding 2022-04-05 14:03:29 +03:00
gingerBill 59025b75ba Merge branch 'master' of https://github.com/odin-lang/Odin 2022-04-04 17:04:12 +01:00
gingerBill 2289b7a33d Remove #caller_location from certain calls in core:container/small_array 2022-04-04 17:04:05 +01:00
Jeroen van Rijn 79ec172797 Merge pull request #1694 from Kelimion/define_help
Add extra help line for define/config.
2022-04-03 21:11:19 +02:00
Jeroen van Rijn 2e6ad2a711 Add extra help line for define/config. 2022-04-03 21:06:06 +02:00
Jeroen van Rijn 6be05f315d Merge pull request #1693 from Skytrias/skytrias-strings-documentation-rest
documentation for the rest of the strings library
2022-04-03 19:54:19 +02:00
Michael Kutowski b5aa50aaa4 documentation for the rest of the strings library 2022-04-03 19:37:54 +02:00
Jeroen van Rijn ab91fa6ad5 Merge pull request #1692 from Kelimion/easy_font
[vendor:easy_font] API improvements.
2022-04-03 19:08:18 +02:00
Jeroen van Rijn 376327c87b [vendor:easy_font] API improvements.
Add `print(x, y, text, color, quad_buffer)` version that takes `[]quad`.
		(Same internal memory layout as []u8 API, but more convenient for the caller.)
Add optional `scale := f32(1.0)` param to `print` to embiggen the glyph quads.

```odin
	// Example for use with vendor:raylib

	quads: [999]easy_font.Quad = ---

	color := rl.GREEN
	c     := transmute(easy_font.Color)color
	num_quads := easy_font.print(10, 60, TEXT, c, quads[:])

	for q in quads[:num_quads] {
		tl    := q.tl.v
		br    := q.br.v
		color  = transmute(rl.Color)q.tl.c

		r := rl.Rectangle{x = tl.x, y = tl.y, width = br.x - tl.x, height = br.y - tl.y}

		// Yes, we could just use the `color` from above, but this shows how to get it back from the vertex.
		// And in practice this code will likely not live as close to the `easy_font` call.
		rl.DrawRectangleRec(r, color)
	}
```
2022-04-03 18:53:27 +02:00
Jeroen van Rijn f8f91e52e0 Merge pull request #1691 from eisbehr/stb_easy_font_fix
Fixes for stb_easy_font
2022-04-03 15:30:52 +02:00
Florian Behr f4daf46ff4 Fixes for stb_easy_font 2022-04-03 15:18:01 +02:00
bkrypt e80bee6867 Change order of O_CREATE & O_APPEND checks 2022-04-02 21:55:01 +02:00
gingerBill d10d54710c Merge pull request #1686 from Kelimion/compile-time-assert
Allow optional message for `#assert`.
2022-04-02 15:02:46 +01:00
gingerBill 1ec997461d Add extra checks to atomic intrinsics 2022-04-02 15:00:28 +01:00
gingerBill ec5fc10988 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-04-02 14:38:51 +01:00
gingerBill a232c0888c intrinsics.atomic_type_is_lock_free 2022-04-02 14:38:42 +01:00
Jeroen van Rijn cb5a6b531a Allow optional message for #assert. 2022-04-02 15:31:50 +02:00
Jeroen van Rijn c930a3b4c8 Merge pull request #1685 from ftphikari/master
sys/windows: add a couple of procedures and types
2022-04-02 12:55:51 +02:00
hikari 4c14e92952 sys/windows: add several procedures and macros 2022-04-02 08:23:12 +03:00
hikari 850d4a1e1b sys/windows: add a couple of procedures and types 2022-04-02 07:38:11 +03:00
CiD- 88de3a1c06 add _chtimes 2022-04-01 22:41:35 -04:00
Jeroen van Rijn dc012ed6dd Merge pull request #1682 from ftphikari/master
sys/windows: add intrinsics.constant_utf16_cstring
2022-04-02 03:27:58 +02:00
Jeroen van Rijn c21c993646 [strings] fix. 2022-04-02 01:54:35 +02:00
gingerBill c3a292a8c7 Remove hms2019 files 2022-04-02 00:36:26 +01:00
Jeroen van Rijn 4044a577cc Merge pull request #1683 from Kelimion/big_nails
[math/big] Tell Python test runner how many nails we use.
2022-04-01 16:33:30 +02:00
Jeroen van Rijn 581d53b96b [math/big] Tell Python test runner how many nails we use.
`_DIGIT_NAILS` is defined as 4, meaning that we use 60 out of every 64 bits.
We can use as few as 1 nail, using 63 bits out of every 64, and all tests will still pass.

However, it needs more testing to see if that's a worthwhile change to make.

For the tests to work properly when changing the nails, Python needs to know about it as well.

In addition, compile the big math code with `-o:speed` going forward.
2022-04-01 16:24:27 +02:00
gingerBill 2bc89260f1 Add explicit memory ordering for the internal Sema implementation 2022-04-01 15:08:58 +01:00
gingerBill c78b83f142 Fix _Sema 2022-04-01 14:51:51 +01:00
hikari e28525e28c sys/windows: fix some procedure definitions and types 2022-04-01 07:28:18 +03:00
hikari 73f9d12d47 sys/windows: add various procedures 2022-04-01 06:22:27 +03:00
hikari b21cf05d44 sys/windows: move L into util.odin 2022-04-01 02:25:10 +03:00
hikari 107bede9fd sys/windows: fix building error 2022-04-01 02:23:44 +03:00
hikari 75cbb09744 sys/windows: add intrinsics.constant_utf16_cstring 2022-04-01 02:11:41 +03:00
Jeroen van Rijn 76cf667a29 Merge pull request #1681 from colrdavidson/fix-nightly
only install the right version of llvm
2022-03-31 22:47:37 +02:00
Colin Davidson 78ee97ec74 only install the right version of llvm 2022-03-31 13:40:28 -07:00
Tetralux c686133172 Have get_std_handle() no longer make the handles uninheritable
This caused all handles returned by GetStdHandle() to also not be inheritable,
which prevents you from handing them to child processes that you might create.

This fixes that.
2022-03-31 17:03:12 +00:00
gingerBill bfcd7a35bf Merge pull request #1621 from colrdavidson/build_freebsd
Core out Makefile, add freebsd building
2022-03-31 16:25:37 +01:00
gingerBill 4484a3433d Update mem.nil_allocator to match the same in runtime 2022-03-31 15:03:56 +01:00
gingerBill 0c4f905d82 Merge pull request #1673 from odin-lang/new-sync
Brand New `package sync` and Atomics Intrinsics
2022-03-31 14:06:00 +01:00
gingerBill 77de7ebde5 Remove code deduplication 2022-03-31 13:26:10 +01:00
gingerBill 2ec3fa93b4 Remove pthreads dependency 2022-03-31 13:10:15 +01:00
gingerBill 9f2d710c35 Change intrinsics.Atomic_Memory_Order fields to use Ada_Case rather than snake_case 2022-03-31 12:57:24 +01:00
gingerBill 22b961ea53 Update Thread Pool in core:thread
Thanks to the work of eisbehr
2022-03-31 11:55:46 +01:00
Jeroen van Rijn 9ea45d35db [ease] Fix flux_stop. 2022-03-31 12:53:04 +02:00
gingerBill 06e8476efc Correct ordering in auto_reset_event_signal 2022-03-31 10:55:18 +01:00
gingerBill 94dbac9a64 Disable thread pool in demo 2022-03-31 01:13:43 +01:00
gingerBill 97a183f412 Clean up thread_windows.odin 2022-03-31 01:13:29 +01:00
gingerBill b2f5b73532 Rename package name to sync 2022-03-31 01:05:50 +01:00
gingerBill 1eac3482a6 Add checks for memory ordering on fences 2022-03-31 01:01:51 +01:00
gingerBill 6636376a81 Correct weak handling 2022-03-31 00:58:01 +01:00
gingerBill ed6bf28004 Update the intrinsics for documentation on atomics 2022-03-31 00:53:34 +01:00
gingerBill 6bc0c611ab Enforce success failure pairings of compare_exchange_*_explicit at compile time 2022-03-31 00:49:53 +01:00
gingerBill ba1930eb01 Update core to use new atomic intrinsics 2022-03-31 00:22:54 +01:00
gingerBill 203382461b Replace the atomic intrinsics
Matching C11 in style
2022-03-31 00:14:49 +01:00
CiD- 6456618891 finish up stat, lstat and fstat 2022-03-30 16:54:29 -04:00
gingerBill 4eb4ae6305 Replace sync with sync2 2022-03-30 17:42:44 +01:00
gingerBill 72ae061769 Add intrinsics.wasm_memory_grow intrinsics.wasm_memory_size 2022-03-30 17:29:37 +01:00
gingerBill 46161f7e19 threading_example allow on Darwin 2022-03-30 16:28:16 +01:00
gingerBill 0c55596f0f Merge pull request #1612 from graphitemaster/fix_thread_data_races
fix thread data races
2022-03-30 16:26:37 +01:00
gingerBill 5f3bfa66c5 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-03-30 16:15:54 +01:00
gingerBill 561b725b0e Improve spin lock for atomic_mutex_lock 2022-03-30 16:15:48 +01:00
gingerBill 3a4630e6b4 Correct atomic_cxchg_* atomic_cxchgweak_* intrinsics behaviour to monotonic on failure for acq, rel, and acqrel 2022-03-30 16:15:23 +01:00
gingerBill abf0fd7efc Merge pull request #1671 from colrdavidson/add_nocrt
Make no crt work on Linux
2022-03-30 12:58:12 +01:00
Colin Davidson a632db3618 Make no crt work on Linux 2022-03-30 04:45:22 -07:00
Jeroen van Rijn a3c81374be Merge pull request #1670 from ftphikari/master
sys/windows: add WM_SYSCOMMAND related constants
2022-03-29 22:11:16 +02:00
hikari 6a3ec5eb36 sys/windows: add WM_SYSCOMMAND related constants 2022-03-29 22:59:45 +03:00
Jeroen van Rijn 740ba6ad47 Merge pull request #1669 from Kelimion/fix_glob_leak
[windows] Fix leak in `glob`.
2022-03-29 16:27:27 +02:00
Jeroen van Rijn df32b5b46c [windows] Fix leak in glob. 2022-03-29 16:13:17 +02:00
Jeroen van Rijn 085fa199ea Merge pull request #1668 from ftphikari/master
sys/windows: add SetTimer() and KillTimer() procedures
2022-03-29 10:09:49 +02:00
hikari 412c9a99d5 sys/windows: add SetTimer() and KillTimer() procedures 2022-03-29 08:56:05 +03:00
Jeroen van Rijn 6e701ef36d Merge pull request #1666 from Kelimion/improve_string_cut
[strings] Improve `cut`, add tests for it.
2022-03-27 22:19:24 +02:00
Jeroen van Rijn 24c48d22bc [strings] Improve cut, add tests for it. 2022-03-27 22:13:26 +02:00
Jeroen van Rijn 3cb8bb6672 Merge pull request #1665 from Kelimion/flux_fixups
[ease] Flux fixups.
2022-03-27 16:55:42 +02:00
Jeroen van Rijn b1c2c0ea7a [ease] Flux fixups. 2022-03-27 16:49:22 +02:00
Jeroen van Rijn 2c498c132e Merge pull request #1663 from Skytrias/skytrias-math-ease
add math easing package
2022-03-27 16:39:25 +02:00
Michael Kutowski 880d330cca update delay to use deltatime, add time left 2022-03-27 16:34:00 +02:00
Jeroen van Rijn a2a503847a Merge pull request #1664 from Skytrias/skytrias-strings-documentation
add string documentation & examples, fix & cleanup string_multi
2022-03-27 13:59:33 +02:00
Michael Kutowski 58f4d533b7 add string documentation & examples, fix & cleanup string_multi 2022-03-27 11:39:17 +02:00
Michael Kutowski d2ff6f424d add math easing package 2022-03-27 11:32:46 +02:00
Jeroen van Rijn 92f985abd5 Merge pull request #1662 from ftphikari/master
sys/windows: add GetSystemMetrics
2022-03-27 03:23:12 +02:00
hikari 3ce17607c6 sys/windows: add AdjustWindowRect and GetWindowRect 2022-03-27 04:17:07 +03:00
hikari 76277f83c1 sys/windows: add GetSystemMetrics 2022-03-27 02:23:40 +02:00
Jeroen van Rijn 2b7529977e Merge pull request #1661 from ftphikari/master
sys/windows: add ClientToScreen
2022-03-27 00:54:44 +01:00
hikari f4125d2d88 sys/windows: add ClientToScreen 2022-03-27 01:42:46 +02:00
Jeroen van Rijn 87e50e5e4d Merge pull request #1660 from Kelimion/hwnd_fix
HWND_TOPMOST, HWND_NOTOPMOST constants
2022-03-26 19:46:28 +01:00
Jeroen van Rijn 86a1c34c3a HWND_TOPMOST, HWND_NOTOPMOST constants 2022-03-26 19:33:53 +01:00
Jeroen van Rijn 3f3cc342b4 Update strings.odin
Fix from Walter.
2022-03-26 18:38:10 +01:00
Jeroen van Rijn 3bf820cf99 Merge pull request #1658 from gitlost/odin_run_unix_exit_code_WEXITSTATUS
Use `WIFEXITED()` and `WEXITSTATUS()` on Unix `system()` exit code
2022-03-26 17:41:41 +01:00
Jeroen van Rijn f2b4087d80 Merge pull request #1656 from ftphikari/master
sys/windows: fix gdi32 raw pointer types
2022-03-26 17:40:00 +01:00
Jeroen van Rijn 3b6d72bb94 Merge pull request #1659 from WalterPlinge/field-iterator
Add fields_iterator procedure
2022-03-25 21:55:43 +01:00
WalterPlinge 9080fa4a9d Update fields_iterator comment
Added ticks for identifiers
2022-03-25 20:51:04 +00:00
WalterPlinge 5616ff9a40 Add fields_iterator proc
Adds a `fields_iterator` proc to `core:strings`
2022-03-25 20:03:39 +00:00
hikari 73b81184fa sys/windows: add MessageBox procedures 2022-03-25 20:53:17 +02:00
hikari f8d3f86d8b sys/windows: fix build 2022-03-25 16:17:53 +02:00
hikari 2f9a410a45 sys/windows: add SetWindowPos() 2022-03-25 16:09:16 +02:00
gitlost 8661457512 Use WIFEXITED() and WEXITSTATUS() on Unix system() exit code
(ensures Odin run returns correct exit code of built executable)
Adds test "tests/core/os/test_core_os_exit.odin" (Unix only)
2022-03-24 19:31:46 +00:00
hikari 5d7b92d391 sys/windows: add mouse states masks 2022-03-24 18:40:23 +02:00
hikari 1d8bc3e917 sys/windows: fix gdi32 raw pointer types 2022-03-24 17:32:11 +02:00
gingerBill a2ad16b609 Merge pull request #1655 from ftphikari/master
sys/windows: add basic Gdi32.lib support
2022-03-24 15:28:24 +00:00
hikari a3b1ac3133 sys/windows: add basic Gdi32.lib support 2022-03-24 17:27:05 +02:00
gingerBill e7b96cf286 Merge pull request #1654 from ftphikari/master
sys/windows: add GetKeyState functions
2022-03-24 14:19:29 +00:00
hikari 01181517dc sys/windows: add GetKeyState functions 2022-03-24 16:04:27 +02:00
gingerBill f702c782f1 Make constant string backing structures use PrivateLinkage compared to InternalLinkage 2022-03-24 12:18:17 +00:00
gingerBill 7203560b06 Fix test 2022-03-24 12:15:03 +00:00
gingerBill 1baeb9406f Utilize union #shared_nil in more places 2022-03-24 12:11:31 +00:00
gingerBill 17e36bd5e1 Utilize union #shared_nil to core:image Error 2022-03-24 12:06:18 +00:00
gingerBill b6b3377786 Remove unneeded semicolons 2022-03-24 12:02:50 +00:00
gingerBill 13cb894b30 Update core:odin for union #shared_nil 2022-03-24 12:00:27 +00:00
gingerBill 3f935bea25 union #shared_nil
This adds a feature to `union` which requires all the variants to have a `nil` value and on assign to the union, checks whether that value is `nil` or not. If the value is `nil`, the union will be `nil` (thus sharing the `nil` value)
2022-03-24 11:55:03 +00:00
gingerBill 3e66eec735 Merge pull request #1653 from ftphikari/master
sys/windows: add virtual keycodes and a couple of constants
2022-03-24 11:29:28 +00:00
gingerBill 277e0ac124 Merge pull request #1651 from gitlost/filepath.split_list_trailing_separator_#1537
Fix issue #1537 "filepath.split_list requires a trailing separator to work"
2022-03-24 11:29:18 +00:00
hikari 2ccfaa7d4e sys/windows: add virtual keycodes 2022-03-23 23:39:26 +02:00
hikari 4bd5de34ea sys/windows: add several of constants 2022-03-23 23:39:09 +02:00
gitlost 374e71e9b0 Fix issue #1537 "filepath.split_list requires a trailing separator"
Does `make()` with `count + 1` and appends final component (note a
  trailing separator will now result in an empty final component)
Adds test "tests/core/path/filepath/test_core_filepath.odin"
2022-03-23 17:44:35 +00:00
gingerBill 07bb93bb5d Merge pull request #1650 from ftphikari/master
sys/windows: fixed calling conventions, added several bindings
2022-03-23 16:27:50 +00:00
CiD- e252d3bedf add os2.name 2022-03-23 11:49:19 -04:00
hikari b9efd09d17 sys/windows: fixed calling conventions, added several bindings 2022-03-23 17:37:38 +02:00
gingerBill 507b718cb3 Merge pull request #1646 from weshardee/master
Add foreign imports for Darwin to vendor:stb
2022-03-23 15:11:13 +00:00
gingerBill 82f9cbecf8 Merge pull request #1649 from gitlost/maps_with_procedure_values_#829
Fix issue #829 "Compiler crashes when declaring maps with procedure"
2022-03-23 15:10:58 +00:00
gingerBill a8ac59a6e7 Merge pull request #1642 from themole/master
Add user32.odin with most basic procedures to core:sys/windows
2022-03-23 15:03:29 +00:00
Holger Lindner 3d389ee028 sys/windows: Add icon resource constants 2022-03-23 15:02:01 +01:00
gitlost 10c5825715 Fix issue #829 "Compiler crashes when declaring maps with procedure"
Inits `o->value` in `check_expr_base_internal()` so doesn't accidentally
  use last (the proc lit was being set to that of previous string)
Adds test to "tests/issues" and changes CI to use new "run" shells
2022-03-23 12:56:37 +00:00
Wes Hardee f89ebce807 Add foreign imports for Darwin to vendor:stb 2022-03-22 15:55:37 -05:00
Holger Lindner 64601ac439 Merge remote-tracking branch 'origin/master' 2022-03-22 17:24:40 +01:00
Holger Lindner edce27812f Nixify line endings 2022-03-22 16:41:07 +01:00
Holger Lindner 193822b45d Merge remote-tracking branch 'ftphikari/master' 2022-03-22 16:36:50 +01:00
Holger Lindner 43640a8b59 Add SendMessageA/W to sys/windows/user32.odin 2022-03-22 16:23:38 +01:00
gingerBill 0446d9721b Merge pull request #1626 from gitlost/hxa_fixes
Fix some core:encoding/hxa stuff (error handling, header, max -> min)
2022-03-22 15:21:40 +00:00
Holger Lindner bae13b6387 Fix incorrect type for wndproc callback procedure 2022-03-21 20:06:50 +01:00
hikari e48c0eee74 sys/windows: added rudimentary User32.lib bindings 2022-03-21 18:44:31 +02:00
Holger Lindner 47e9857eb7 Add user32.odin with most basic procedures to core:sys/windows 2022-03-21 17:20:43 +01:00
gingerBill 559fcfa291 Merge pull request #1632 from gitlost/const_in_if_#1592
Fix issue #1592 "LLVM code gen error when using a constant in an if"
2022-03-21 11:16:59 +00:00
gingerBill 84cee5d9d5 Merge pull request #1640 from Lperlind/split-iterator-byte
Add split_iterator_byte
2022-03-21 10:49:21 +00:00
Lucas Perlind 6d354524e2 * Add split_by_byte_iterator. It functions exactly like split_iterator but takes in a byte seperator rather than a string seperator.
The intention is to provide a faster split parsing if the seperator is known to be byte size.
2022-03-21 21:39:30 +11:00
gingerBill ae6441182d Add core:unicode/utf8/utf8string to examples/all 2022-03-18 23:32:37 +00:00
gingerBill a68f0b2d72 Improve procedure group selection based on the minimum number of arguments 2022-03-18 22:18:12 +00:00
gitlost fdbbf24271 Fix issue #1592 "LLVM code gen error when using a constant in an if"
Changes lb_build_if_stmt() to return null lbValue if condition is
  cmpAnd, cmpOr or non-const neg and check in lb_build_if_stmt()
  to avoid short circuiting if that's the case
Adds test to "tests/issues" and adds step in CI to check this dir
2022-03-18 13:57:22 +00:00
Jeroen van Rijn df233f72a9 Merge pull request #1629 from Lperlind/more-window-bindings
Add unregister_class_a and unregister_class_w for windows bindings
2022-03-18 13:29:53 +01:00
gingerBill bff5a67f79 Merge pull request #1631 from Tetralux/fix
Remove incorrect #packed from sys/windows.STARTUPINFO
2022-03-18 11:52:05 +00:00
Tetralux 4f9df50dc1 Remove incorrect #packed from sys/windows.STARTUPINFO 2022-03-18 11:42:25 +00:00
Lucas Perlind 34187424b8 Add unregister_class_a and unregister_class_w for windows bindings 2022-03-18 19:35:36 +11:00
Jeroen van Rijn 50503cb405 Merge pull request #1628 from StanislavNikolov/fix-math-cumsum-inplace
Fix #1627: Remove wrong return type in cumsum_inplace
2022-03-17 03:35:17 +01:00
Stanislav Ch. Nikolov 5e04ddd653 Fix #1627: Remove wrong return type in cumsum_inplace 2022-03-17 04:20:39 +02:00
gitlost 4f5203e661 Fix some core:encoding/hxa stuff (error handling, header, max -> min)
Also add missing f16 case to core:reflect as_u64 & as_f64
Add tests for above & add previous tests missing from test/core/build.bat
2022-03-16 19:12:00 +00:00
gingerBill d9ca4eb4d6 Add nil check on ast.walk 2022-03-16 11:59:28 +00:00
Jeroen van Rijn 5534c031b3 Merge pull request #1624 from Kelimion/insert_at_fix
[runtime] fix `insert_at` procedure group.
2022-03-15 19:44:05 +01:00
Jeroen van Rijn 19dc84e300 Reinstate NBC. 2022-03-15 19:37:04 +01:00
Jeroen van Rijn a932168f50 [runtime] fix insert_at procedure group. 2022-03-15 19:35:00 +01:00
CiD- 36c22393a4 fix memory leak 2022-03-15 11:47:35 -04:00
CiD- 6d6e840bc2 mkdir_all: WHOOPS 2022-03-14 15:56:41 -04:00
CiD- 4b1822ade8 mkdir_all: close last open file 2022-03-14 15:48:47 -04:00
CiD- b21e7e4518 rewrite mkdir_all 2022-03-14 15:44:34 -04:00
CiD- 1f4e5e919f merge upstream/master 2022-03-14 13:36:22 -04:00
CiD- c293e88f2e commit to merge upstream/master 2022-03-14 13:34:06 -04:00
gingerBill 1d147ba993 Fix typo 2022-03-14 12:44:35 +00:00
gingerBill 6ea9ba16e7 Fix #1610 2022-03-14 12:38:56 +00:00
gingerBill 286549693e Fix #1609 2022-03-14 12:28:28 +00:00
Colin Davidson 34727f99e3 oops, fix report 2022-03-14 05:27:08 -07:00
gingerBill ffe6d81ecd Remove comments 2022-03-14 12:24:10 +00:00
Colin Davidson 8605833781 core out Makefile, add freebsd building 2022-03-14 05:23:48 -07:00
gingerBill 4474144c24 Merge pull request #1505 from jasonKercher/fix_odin_test
fix `odin test`
2022-03-14 12:09:39 +00:00
Jeroen van Rijn ef3f448861 Remove accidentally committed test binary. 2022-03-14 13:06:50 +01:00
gingerBill a882260db6 Merge pull request #1605 from colrdavidson/linux_build
Make llvm-config build more general for linux
2022-03-14 11:39:03 +00:00
gingerBill 633157f4f8 Merge pull request #1613 from semarie/linux_arm64
fix Linux arm64 support
2022-03-14 11:37:45 +00:00
gingerBill 9fa69c3d3b Merge pull request #1599 from gitlost/fract_trunc_classify_#1574
Fix for trunc_f16/32/64 (#1574)
2022-03-14 11:37:11 +00:00
gingerBill 743a461aa9 Merge pull request #1614 from semarie/openbsd-fpos_t
use distinct type for fpos_t on OpenBSD
2022-03-14 11:11:29 +00:00
gingerBill fc0291d745 Merge pull request #1526 from odin-lang/freestanding_amd64
Freestanding target for amd64
2022-03-14 11:09:52 +00:00
gingerBill 77eaf8e1e4 Merge pull request #1617 from semarie/freebsd
freebsd_amd64 support
2022-03-14 11:04:58 +00:00
gingerBill a7adb2fb6e Merge branch 'master' into freestanding_amd64 2022-03-14 11:02:59 +00:00
Sébastien Marie 036900da51 fix mode_t on darwin
- fix mkdir() prototype (mode_t is u16)
- remove explicit cast
2022-03-13 12:41:03 +00:00
Sébastien Marie ed4c9335db enable freebsd_amd64 inside CI 2022-03-13 11:43:36 +00:00
Sébastien Marie ca67cf032c freebsd_amd64 support 2022-03-13 11:42:42 +00:00
gingerBill f907516cbd #Fix 1615 Replace llvm.readcyclecounter with cntvct_el0 on arm64 2022-03-12 10:48:31 +00:00
gingerBill c12c7d5370 Remove tag 2022-03-12 10:47:52 +00:00
Sébastien Marie f7c8b40ea2 use distinct type for fpos_t on OpenBSD 2022-03-12 09:40:55 +00:00
Sébastien Marie 15f9795ab0 enable linux_arm64 check in CI 2022-03-12 09:21:46 +00:00
Sébastien Marie 8982ae34e3 fix linux_arm64
- SYS_fork doesn't exist, uses SYS_clone
- properly cast AT_FDCWD to uintptr
2022-03-12 09:19:52 +00:00
gingerBill e6d3e893a5 Merge pull request #1602 from hoanga/freebsd-build-support
update to build for freebsd
2022-03-12 08:45:53 +00:00
U-JSM\jkercher e008b5a160 build os2 test on windows 2022-03-11 10:47:59 -05:00
Dale Weiler 3da8fa9b27 can use sync.guard here 2022-03-11 08:41:03 -05:00
Dale Weiler 32ba5e7ad2 formatting 2022-03-11 08:36:04 -05:00
Dale Weiler 52df80dccd fix for mac & use atomic store on write side to avoid race 2022-03-11 08:35:23 -05:00
Dale Weiler 7f845bb165 fix for spurious wakeups 2022-03-11 08:30:03 -05:00
Dale Weiler 0e6de5673b fix thread data races 2022-03-11 08:06:23 -05:00
Jeroen van Rijn 7a7b87181d [examples] Add core:encoding/varint to examples/all. 2022-03-11 11:09:58 +01:00
gingerBill c6dc517004 Correct: murmur32 2022-03-11 08:52:16 +00:00
Jason Kercher 0b61215f7b getting tests to run 2022-03-10 11:12:06 -05:00
Jason Kercher b91c0ec715 Merge remote-tracking branch 'upstream/master' into os2_linux 2022-03-10 09:34:48 -05:00
CiD- bad295cf69 add test directory... 2022-03-10 09:23:33 -05:00
Jason Kercher d2bc41a2df Merge remote-tracking branch 'upstream/master' into fix_odin_test 2022-03-09 17:17:40 -05:00
gitlost 7dbcaf792d Merge branch 'master' into fract_trunc_classify_#1574
Resolve conflicts with [9848e88] & sameify Makefile & tests/common/common.odin
2022-03-09 16:09:04 +00:00
Colin Davidson 2652c2d7a5 normalize version parser 2022-03-09 07:42:38 -08:00
Colin Davidson a2250a5d49 lower minimum llvm version 2022-03-09 07:24:49 -08:00
Colin Davidson 7f8a9587e0 more build tweaks? 2022-03-09 07:22:48 -08:00
Colin Davidson 1306c53fb1 more build tweaks? 2022-03-09 07:21:19 -08:00
Colin Davidson 3bd1ac4c82 test adjusting apt arg order 2022-03-09 07:18:41 -08:00
gingerBill dc8d28c383 Fix #1607 2022-03-09 15:15:30 +00:00
Colin Davidson 7adaa4dc2b refix make, adjust build for CI weirdness 2022-03-09 07:15:08 -08:00
gingerBill 6d1a91f5b3 Fix typo 2022-03-09 15:11:38 +00:00
gingerBill 17eebf338c Fix #1606 (Call runtime._cleanup_runtime_contextless() for os.exit) 2022-03-09 15:05:51 +00:00
Colin Davidson c543ecd64c Try to find llvm-config-11 on goofy misconfigured CI box 2022-03-09 06:57:59 -08:00
Colin Davidson 34a9f55f37 Update ci to use build script 2022-03-09 06:52:22 -08:00
Colin Davidson 9aea990184 clean up osx semver handling in build 2022-03-09 06:49:52 -08:00
Colin Davidson d5b0632e4f add handling for too many args 2022-03-09 06:27:52 -08:00
Colin Davidson db169a4334 Cleanup build mode selection 2022-03-09 06:26:25 -08:00
Colin Davidson f5cc8bd7bf only build odin for report when necessary 2022-03-09 06:14:30 -08:00
Colin Davidson 005d52cab7 more spacing issues 2022-03-09 06:08:48 -08:00
Colin Davidson d1477bcfa7 Fix wonky copied space issues 2022-03-09 06:07:19 -08:00
Colin Davidson 3092fb2ff3 Add initial cut of build script 2022-03-09 06:01:40 -08:00
Colin Davidson 5eebdebec8 Make llvm-config build more general for linux 2022-03-09 05:09:39 -08:00
gingerBill 8e4d6b3e5d Fix typo 2022-03-09 11:24:36 +00:00
gingerBill ea9c2fed57 Update .gitignore 2022-03-09 10:52:37 +00:00
gingerBill ba412fd87b Fix typo 2022-03-09 09:36:21 +00:00
Al Hoang 0278ac85a0 update to build for FreeBSD 2022-03-08 23:48:25 -06:00
gingerBill ff60b752bd Replace #if with if where possible 2022-03-08 22:35:10 +00:00
CiD- 832003dd4b os2 tests 2022-03-08 17:15:45 -05:00
gingerBill 9848e883c7 Merge pull request #1598 from Kelimion/varint
Add `core:encoding/varint` with LEB128 encoding, decoding and tests.
2022-03-08 20:46:31 +00:00
Jeroen van Rijn 64705ddd1d [varint] Add doc.odin 2022-03-08 20:08:56 +01:00
Jeroen van Rijn 2a41814985 [varint] Tighten max input bounds. 2022-03-08 19:56:42 +01:00
Jeroen van Rijn 26ffec845b [crypto] Remove unused mem import for siphash. 2022-03-08 19:38:36 +01:00
Jeroen van Rijn 52e60526ef tabs. 2022-03-08 19:32:30 +01:00
Jeroen van Rijn 76b10b5f5d [varint] Add additional LEB128 tests. 2022-03-08 19:28:55 +01:00
gitlost b94a7a87fa Fix issue #1574 "fract in linalg/glm is broken" by fixing
trunc_f16/32/64 in "math.odin" (~ typos on expressions)
Fix classify_f16 Inf test (would fail for subnormal 0h0001)
  by changing multiplier 0.5 -> 0.25
Add some useful consts to "math.odin" (INF_F16 etc)
Add comment to "demo.odin" mentioning that -0.0 must be used
  to specify negative zero
2022-03-08 18:06:25 +00:00
gingerBill 2b43387a9d Merge pull request #1597 from odin-lang/nix-linker-flags-improvement
Refactor link flag creation for nix systems
2022-03-08 17:12:28 +00:00
Jeroen van Rijn e76a5d8e12 [varint] Add signed LEB128 encoding. 2022-03-08 18:07:16 +01:00
Jeroen van Rijn 6d7217f37a [varint] Add LEB128 decoding + tests
Also make tests in general less spammy: Don't print [PASS] for each successful test, only report failures and progress.
2022-03-08 15:40:00 +01:00
gingerBill 17dab04422 Refactor link flag creation for nix systems 2022-03-08 11:13:59 +00:00
gingerBill 29e660b16f Add more things to package slice
min_max
any_of(_proc)
none_of(_proc)
all_of(_proc)
count(_proc)
2022-03-08 10:02:40 +00:00
gingerBill 31959b0751 Correct cleanpath_from_handle for os.fstat 2022-03-08 10:01:44 +00:00
jasonkercher 1f19610fd6 added _remove_all 2022-03-07 17:16:03 -05:00
gingerBill 8f897de267 Merge pull request #1584 from WalterPlinge/vulkan-proc-loader-functions
update vulkan generator and procedure file
2022-03-07 18:54:26 +00:00
Jeroen van Rijn 2855ff6df3 Merge pull request #1591 from Kelimion/unaligned_load
[intrinsics] Add existing `unaligned_load` and `unaligned_store`.
2022-03-06 14:59:24 +01:00
Jeroen van Rijn deed20dea6 [intrinsics] Add unaligned_store. 2022-03-06 14:53:06 +01:00
Jeroen van Rijn a6c5143993 [intrinsics] Add existing unaligned_load. 2022-03-06 14:46:20 +01:00
Jeroen van Rijn 758d1e2a03 Merge pull request #1589 from Kelimion/fix_bit_array_leak
[bit_array] Really fix the leak.
2022-03-06 12:38:08 +01:00
Jeroen van Rijn ce057ff755 [bit_array] Really fix the leak. 2022-03-06 12:29:17 +01:00
gingerBill ad719e7c3a Merge pull request #1588 from ap29600/master
Fix leak in `core:container/bit_array`
2022-03-06 09:43:12 +00:00
Andrea Piseri bff3426d25 Fix leak in core:container/bit_array
calling `clear` on a `bit_array` no longer leaks the previous
allocation, instead it sets all bits to `false` preserving the same
backing dynamic array.
2022-03-06 10:21:46 +01:00
gingerBill 4315033220 Merge pull request #1585 from kstrb/foreign-import-object
Linux: allow 'foreign import' of object files
2022-03-05 20:29:39 +00:00
kstrb 1cd89b2da3 Linux: allow 'foreign import' of object files 2022-03-05 17:28:34 +01:00
jasonkercher 658a605c75 compiles 2022-03-04 17:11:53 -05:00
WalterPlinge 7e8b9862b9 update vulkan generator
change procedure file generation
- group procedure types together
- sort groups by procedure names
- overload function `load_proc_addresses`
    - kept original as `custom`
    - added `global`, `instance`, and `device` variants for simpler loading
    - added `device_vtable` variant to support multiple devices
2022-03-04 16:16:31 +00:00
gingerBill 07062324d7 Merge pull request #1575 from jockus/fix_relative_slice_len
Add relative slice to type checks for built in len
2022-03-04 11:48:29 +00:00
gingerBill 2e8f2e6dbc Merge pull request #1476 from odin-lang/odin-ast-changes
Replace `any` with `union` for subtyping in `core:odin/ast`
2022-03-04 10:39:38 +00:00
gingerBill 1abd95094d Add reflect.deref 2022-03-03 23:25:22 +00:00
gingerBill 913d802e33 Fix ast.clone_node 2022-03-03 23:10:38 +00:00
Jeroen van Rijn bee475c38a Merge pull request #1582 from semarie/more-ci
CI: add linux i386, Darwin arm64 and Windows 386
2022-03-03 17:07:40 +01:00
Jeroen van Rijn b4ca99ead9 Merge pull request #1583 from semarie/semi-colons-eof
Semi colons and EOF
2022-03-03 17:06:13 +01:00
Sébastien Marie dfe2c0a600 remove some leftover semi-colons before EOF 2022-03-03 15:57:55 +00:00
Sébastien Marie fad851d80c check for semi-colon before EOF too 2022-03-03 15:57:51 +00:00
Sébastien Marie 832961d539 semi-colons are deprecated in core 2022-03-03 15:36:04 +00:00
Sébastien Marie 499c657ffa rename architecture from 386 to i386 2022-03-03 15:28:18 +00:00
CiD- e51bb4ef12 os2 linux begin 2022-03-03 10:16:36 -05:00
Sébastien Marie 8c6f39a68d CI: add linux i386, Darwin arm64 and Windows 386 2022-03-03 15:08:34 +00:00
gingerBill 09f5713cf8 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-03-03 14:31:45 +00:00
Jeroen van Rijn 26c0c6a525 Merge pull request #1581 from Kelimion/32-bit-fixes
32 bit fixes
2022-03-03 15:26:42 +01:00
Jeroen van Rijn 6d9f84ba03 [tests] Make test runners exit with errorlevel 1 if a test fails. 2022-03-03 15:16:16 +01:00
Jeroen van Rijn 8af08f2153 [compress] 32-bit cleanness. 2022-03-03 15:10:19 +01:00
gingerBill 2944969ca0 Correct clone_node 2022-03-03 14:01:37 +00:00
gingerBill bd1b54e0db Fix #1503 2022-03-03 13:58:22 +00:00
gingerBill fcab5508be Merge branch 'master' into odin-ast-changes 2022-03-03 13:56:34 +00:00
gingerBill 0b05650366 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-03-03 13:54:31 +00:00
gingerBill 96e36c7c39 Minor fix to strconv.unquote_string 2022-03-03 13:54:23 +00:00
gingerBill 16c6dbcbe5 Merge pull request #1579 from semarie/vendors
Vendors libraries portability and examples/all splitting
2022-03-03 12:09:46 +00:00
gingerBill 92a78c83d9 Merge pull request #1571 from SrMordred/patch-4
Fixing bindings
2022-03-03 12:08:17 +00:00
gingerBill 6b2302fa8b Merge pull request #1572 from Lperlind/better-fmt
Improve core:fmt formatting
2022-03-03 12:07:14 +00:00
gingerBill ee28945e09 Update FUNDING.yml 2022-03-03 11:19:12 +00:00
Sébastien Marie 3dcea60f5b vendor: ENet: follow strict-style and remove optional semi-colon 2022-03-03 09:27:10 +00:00
Sébastien Marie f126e05034 stb, miniaudio: use default builtin variables of make for CC and AR 2022-03-03 07:36:47 +00:00
gingerBill 68b74eb7c7 Merge pull request #1577 from zhibog/crypto_rand_windows
Added rand_bytes for Windows in core:crypto
2022-03-02 23:10:31 +00:00
zhibog 3b4199a669 Added rand_bytes for Windows in core:crypto 2022-03-02 21:22:56 +01:00
Sébastien Marie 562901aedf split all_vendor.odin
create 3 files:
- all_vendor.odin : no specific OS
- all_vendor_directx.odin : directx vendor, windows-only
- all_vendor_stb.odin : stb vendor, windows and linux only

stb could technically be used on others OS. but it is shipped upstream as set of c-files without unified library name.
2022-03-02 19:21:22 +00:00
Sébastien Marie 793117ed63 vendor: sdl2: simplify foreign import 2022-03-02 18:50:37 +00:00
Sébastien Marie 5b783d6376 vendor: raylib: simplify foreign import 2022-03-02 18:44:29 +00:00
Sébastien Marie d3f3528d1d vendor: portmidi: simplify foreign import 2022-03-02 18:43:17 +00:00
Sébastien Marie 3145935d6b miniaudio
- simplify foreign
- enable SUPPORT_SNDIO on OpenBSD
- correct ptr type for SUPPORT_PULSEAUDIO (Linux) and SUPPORT_COREAUDIO (Darwin)
2022-03-02 18:35:13 +00:00
Sébastien Marie 25430333ba vendor: glfw: simplify foreign import 2022-03-02 18:25:22 +00:00
Sébastien Marie 2ca2b32dd0 vendor: botan: simplify foreign import 2022-03-02 18:21:43 +00:00
Joakim Hentula a5dde78f08 Add relative slice to type checks for built in len 2022-03-02 16:44:33 +00:00
gingerBill fd415f0b45 Merge pull request #1573 from semarie/openbsd-vendor
Openbsd vendor
2022-03-02 12:56:12 +00:00
Lucas Perlind 507722954c Improve core:fmt formatting
* Strings will respect widths smaller than the string's length
* Strings are right justified by default like integers
* Strings accept '-' flag to be left justified
* Booleans will be formatted like strings
* Enums will be formatted like strings
2022-03-02 16:22:16 +11:00
Patric Dexheimer 524d23d45d Update raylib.odin 2022-03-01 16:55:34 -03:00
Patric Dexheimer e9ee6f5291 Fixing bindings
https://github.com/raysan5/raylib/blob/master/src/raylib.h#L1179
2022-03-01 16:00:18 -03:00
gingerBill 7e5342f41f Use contextless where possible 2022-03-01 15:52:14 +00:00
gingerBill 18607e53cb Correct alloc_from_memory_block 2022-03-01 15:38:04 +00:00
gingerBill ed933b3f21 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-03-01 14:49:11 +00:00
gingerBill 49fecbdc5e Improve error message when there is "no field" found for a large anonymous struct 2022-03-01 14:49:05 +00:00
Jeroen van Rijn f971126183 [mem] Add missing \n to tracking allocator example. 2022-03-01 13:51:41 +01:00
gingerBill d4ccb69ccc Check if directory exists with the same target executable name when building a directory 2022-02-28 21:49:19 +00:00
Sébastien Marie 37b4e0de6c sdl2: add openbsd support 2022-02-28 16:17:15 +00:00
Sébastien Marie 737f440c7f glfw: add openbsd support 2022-02-28 16:17:14 +00:00
Sébastien Marie cba3f1e374 ENet: add openbsd support 2022-02-28 16:17:14 +00:00
gingerBill a70dde34da Merge pull request #1565 from semarie/openbsd-pie
openbsd: defaults to PIE executable
2022-02-28 16:11:59 +00:00
gingerBill 410b85b5c7 Disallow @(thread_local) on wasm targets 2022-02-28 15:40:00 +00:00
gingerBill 0ae012ba08 Correct comment 2022-02-28 15:37:15 +00:00
gingerBill fc4eb4152c Correct calling convention for _startup_runtime 2022-02-28 15:35:10 +00:00
gingerBill 4f3b5d8dcb Clean up generate_minimum_dependency_set code 2022-02-28 15:29:08 +00:00
Sébastien Marie f76f70c7cf openbsd: defaults to PIE executable
OpenBSD uses PIE code by default to allow the system to load the binary at a random location.

don't pass -no-pie to preserve this behaviour, and build objects with -fPIC (LLVMRelocPIC).
2022-02-28 15:24:22 +00:00
gingerBill 15d783e920 Enforce -no-entry-point on freestanding targets 2022-02-28 15:13:41 +00:00
gingerBill 09e4fff5b1 -target-features:<string>
This just passes a string directly to the LLVM features string
2022-02-28 15:08:50 +00:00
gingerBill 2d89faa17c Add extra checks for -disallow-rtti 2022-02-28 14:35:38 +00:00
gingerBill dd9843aa21 Merge pull request #1557 from semarie/openbsd-support
initial OpenBSD support
2022-02-28 14:23:56 +00:00
gingerBill 882116e358 Only allow -disallow-rtti on freestanding targets 2022-02-28 14:00:44 +00:00
gingerBill f3adbae1ed Merge branch 'freestanding_amd64' of https://github.com/odin-lang/Odin into freestanding_amd64 2022-02-28 13:40:06 +00:00
gingerBill 278e239973 Commit rest of code for -disallow-rtti 2022-02-28 13:40:01 +00:00
gingerBill fda803b46a Commit rest of code for -disable-rtti 2022-02-28 13:39:27 +00:00
gingerBill 01162e08b5 Add -disallow-rtti 2022-02-28 13:35:29 +00:00
gingerBill a7ae197a55 Merge branch 'master' into freestanding_amd64 2022-02-28 13:02:31 +00:00
gingerBill 3c72cb67d3 Remove context.user_data 2022-02-28 13:00:32 +00:00
gingerBill 37bba4c0a6 Reorganize error check procedures 2022-02-28 12:45:19 +00:00
gingerBill ab9d1f99fd Change #c_vararg checking to only disallow odin calling conventions 2022-02-28 12:36:21 +00:00
gingerBill 45124e4d5c Merge branch 'master' into freestanding_amd64 2022-02-28 12:32:51 +00:00
gingerBill 7681c43b14 Show error message when something like this is done test: proc() : {} 2022-02-28 12:12:04 +00:00
gingerBill 7e43cd7d97 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-28 12:06:42 +00:00
gingerBill c223fc1766 Correct debug information for local variables 2022-02-28 12:06:35 +00:00
Sébastien Marie 04297bb680 ci: add check for OpenBSD amd64 2022-02-26 14:18:37 +00:00
Sébastien Marie 553292ffd0 vendor: botan: add OpenBSD support 2022-02-26 08:47:58 +00:00
Sébastien Marie 57862846a2 tests/vendor: pass extra linker flags
on OpenBSD, botan library is third-party and live in /usr/local which isn't a path included by default in linker.
2022-02-26 08:21:46 +00:00
Sébastien Marie 8e270d3a99 openbsd: poor man implementation for getting executable path
it tries to get executable path from argv[0]. it is unreliable and unsecure, but should be fine enough for the considered use-case. it still doesn't address all possible cases.
2022-02-26 08:19:41 +00:00
Sébastien Marie ae5cb09041 internal_odin_root_dir: readlink could fail 2022-02-25 17:59:57 +00:00
gingerBill 093b2288c3 Merge pull request #1320 from mohd-akram/custom-llvm-config
Allow custom LLVM_CONFIG
2022-02-25 15:57:53 +00:00
Mohamed Akram ffe17a471d Allow custom LLVM_CONFIG 2022-02-25 19:40:42 +04:00
gingerBill e9f901b82d Keep -vet happy 2022-02-25 15:30:24 +00:00
gingerBill ed3004f8a0 Correct read_console reading 2022-02-25 15:30:05 +00:00
gingerBill d97df080f9 Revert change 2022-02-25 15:08:02 +00:00
gingerBill 0e5c7e08fc Change < to <= 2022-02-25 14:54:35 +00:00
Sébastien Marie 83523badb7 pass -ldl only on Darwin and Linux 2022-02-25 13:02:12 +00:00
Sébastien Marie 0a90994403 provide a simple gb_file_copy() implementation
permit to not require sendfile(2) syscall for gb_file_copy()
2022-02-25 12:32:34 +00:00
gingerBill 376906e0ae Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-25 12:02:49 +00:00
gingerBill 47c79a2f25 Correct os.read on windows for os.stdin 2022-02-25 12:02:41 +00:00
gingerBill 32988b0363 Correct internals for os.read on windows (read_console) for os.stdin (Fix #1556) 2022-02-25 12:01:53 +00:00
Sébastien Marie 00c138ce9f add RAM information inside report 2022-02-25 09:28:04 +00:00
Sébastien Marie 5676c9e7eb initial OpenBSD support 2022-02-25 08:49:25 +00:00
Jeroen van Rijn 3a469dc13e Merge pull request #1549 from semarie/clone_to_cstring-leak
delete allocated memory with clone_to_cstring
2022-02-24 12:42:15 +01:00
Sébastien Marie d3c70f2206 remove the optional ; in os_freebsd.odin 2022-02-24 11:30:33 +00:00
Sébastien Marie 14f1793b3e use context.temp_allocator instead of general allocation + delete()
where clone_to_cstring is used with foreign code, it is prefered to use `context.temp_allocator` instead of using the general allocator and manually delete the memory after use.
2022-02-24 11:28:42 +00:00
Jeroen van Rijn 8cecb6b9f5 Merge pull request #1548 from colrdavidson/darwin_docs
Add make_directory so darwin can build html docs
2022-02-24 11:51:20 +01:00
Jeroen van Rijn 4a66c3c420 Merge pull request #1546 from zacharycarter/patch-2
adding `is_16_bit_from_memory` to stbi
2022-02-24 11:49:08 +01:00
gingerBill c3c88633a5 Merge pull request #1545 from AquaGeneral/master
Added options to help, and improved wording
2022-02-24 10:15:13 +00:00
Colin Davidson aeaf1199ec Add make_directory so darwin can build html docs 2022-02-24 01:13:51 -08:00
Tail Wag Games d4f62f52db adding is_16_bit_from_memory to stbi 2022-02-24 00:20:15 -06:00
Jesse Stiller 384fb76a1b Added options to help, and improved wording 2022-02-24 12:59:06 +10:00
gingerBill 4a04a32e0a Change target name to freestanding_amd64_sysv 2022-02-23 11:33:28 +00:00
gingerBill 196bd735d4 Replace local @(no_red_zone) with global -disable-red-zone 2022-02-23 11:29:36 +00:00
gingerBill 493bc653b5 Add @(no_red_zone) for procedures 2022-02-23 11:23:27 +00:00
gingerBill 3d209798c9 Add help docs for -reloc-mode:<string> 2022-02-23 11:19:51 +00:00
Jeroen van Rijn dd0d61e97c Merge pull request #1528 from Tetralux/split-docs
Add doc comments to strings.split() and strings.split_n()
2022-02-23 12:13:29 +01:00
gingerBill 4b9324ff76 Merge branch 'master' into freestanding_amd64 2022-02-23 11:03:48 +00:00
gingerBill e81ed9a960 Add "Did you mean" to Objective-C fields 2022-02-22 23:19:49 +00:00
gingerBill 83f7a887b7 Move comment 2022-02-22 23:03:04 +00:00
gingerBill ad2f1ac24e Improve union_tag_size 2022-02-22 23:01:28 +00:00
gingerBill 62d232d798 Correct ExactValue_Pointer 2022-02-22 22:59:00 +00:00
gingerBill 8906a0120c Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-22 22:53:19 +00:00
gingerBill cad753e398 Simplify parse_binary_expr 2022-02-22 22:53:13 +00:00
Jeroen van Rijn fd627dc13b Merge pull request #1535 from zhibog/add-siphash
Added SipHash + tests and fixed remaining semicolons in vendor/botan
2022-02-22 20:34:50 +01:00
zhibog 70e8d97ee1 Fix procedure 2022-02-22 20:13:49 +01:00
zhibog cdecb0ccc3 Fix Odin_OS_Type 2022-02-22 20:10:35 +01:00
zhibog 460b5149af Added missing constants 2022-02-22 20:06:52 +01:00
zhibog b6dc253d8b Add generic procedure for default SipHash 2-4 2022-02-22 20:02:34 +01:00
zhibog e7be9493ba Added SipHash + tests and fixed remaining semicolons in vendor/botan 2022-02-22 19:56:07 +01:00
Jeroen van Rijn ea34f321ed Merge pull request #1533 from odin-lang/bug_report
[report] Fix `odin report` crash if `/usr/lib/os-release` doesn't exist.
2022-02-22 17:14:24 +01:00
Jeroen van Rijn 2b5bc1d558 [report] Fix odin report crash if /usr/lib/os-release doesn't exist. 2022-02-22 17:08:57 +01:00
gingerBill e6a7b85da4 Correct types 2022-02-21 20:49:59 +00:00
gingerBill 6145185478 Add missing return types 2022-02-21 16:04:56 +00:00
gingerBill 6630d703f8 Clean up ok or error handling 2022-02-21 13:42:29 +00:00
gingerBill 9c3cdc4620 Start filling in the file_windows.odin procedures 2022-02-21 13:38:25 +00:00
gingerBill 345032f804 Get env stuff working on Windows 2022-02-21 12:35:52 +00:00
Tetralux 2abba6e057 Don't use leading asterisks 2022-02-21 09:51:03 +00:00
Tetralux db5a1b0c78 Add doc comments to strings.split() and strings.split_n() 2022-02-21 09:23:45 +00:00
gingerBill 14cb19c2df Update fmt to record the bytes written in the fmt.Info 2022-02-20 22:31:13 +00:00
gingerBill 46bcd18946 Merge pull request #1519 from colrdavidson/hyperspeed_file_size
Maintain a running count printed, so fprintf returns correct sizes for non-files
2022-02-20 22:16:27 +00:00
gingerBill 3e5c60f746 Add -reloc-mode:<string> 2022-02-20 14:48:12 +00:00
gingerBill 0fa487f468 Add -foreign-error-procedures 2022-02-20 14:27:44 +00:00
gingerBill 1bec9e5331 Add freestanding_amd64_gnu 2022-02-20 14:19:52 +00:00
gingerBill ba61d911da Remove dead code 2022-02-20 13:26:27 +00:00
Jeroen van Rijn 3b69c6b204 Merge pull request #1521 from SrMordred/patch-3
Memory Leak
2022-02-20 11:54:31 +01:00
Patric Dexheimer d7eabf571c Memory Leak
`dir` will leak memory if u use it with allocators that don´t care in freeing the memory at the end ( like arenas or the temp_allocator ) , because `strings.clone` and `strings.concatenate` are not using the passed allocator.
2022-02-20 02:10:34 -03:00
Colin Davidson ddf9c4a65b switch to passing total_size to the io.writers 2022-02-19 16:38:33 -08:00
Colin Davidson b3d797598e fprintf tweaked to avoid calling file_size 2022-02-19 15:51:11 -08:00
gingerBill 31c7945444 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-19 15:45:08 +00:00
gingerBill 276e014d18 Update comment in demo.odin 2022-02-19 15:45:01 +00:00
Jeroen van Rijn 27f206784c Merge pull request #1514 from colrdavidson/fast_file_size
Use the _unix_fstat pointer to avoid 144B copies on fileIO
2022-02-19 12:17:03 +01:00
Colin Davidson 54a6637d38 Use the _unix_fstat pointer to avoid 144B copies on fileIO 2022-02-18 20:50:49 -08:00
gingerBill 23be56af59 Remove prefixes from D3D12 constants 2022-02-18 21:45:20 +00:00
gingerBill 71df46456a Minimize memory usage by having an arena per thread rather than an arena per file 2022-02-18 21:30:25 +00:00
gingerBill cd89d8a3c4 Add better error message for compiler when OOM happens 2022-02-18 16:24:08 +00:00
gingerBill 4c62a32b04 Keep -vet happy 2022-02-18 16:13:52 +00:00
gingerBill 5f8137025d Use try_to_add_package_dependency 2022-02-18 16:12:21 +00:00
gingerBill 1843d52217 Fix typo 2022-02-18 16:07:06 +00:00
gingerBill 454c92dc64 Allow objc intrinsics within odin check and odin docs but disallow for odin build 2022-02-18 16:05:26 +00:00
gingerBill 7e33a86d54 Remove unneeded semicolon 2022-02-18 16:01:11 +00:00
gingerBill 197b832992 Add vendor:directx and vendor:darwin packages for documentation generation 2022-02-18 15:56:53 +00:00
gingerBill 8f13724a4b Merge pull request #1504 from odin-lang/directx-packages
DirectX Package Support
2022-02-17 23:15:38 +00:00
gingerBill 746d5fc322 Correct D3D packages 2022-02-17 20:48:50 +00:00
gingerBill ffc45e8cc2 Add intrinsics.constant_utf16_cstring 2022-02-17 20:48:37 +00:00
CiD- bea2f36443 improve entry point check logic 2022-02-17 10:48:30 -05:00
gingerBill f138f71fa6 Add UUID pointer values 2022-02-17 13:14:21 +00:00
Jeroen van Rijn 89b7a3f7ac Merge pull request #1506 from zacharycarter/patch-1
Adding capture procedures to user32
2022-02-17 13:59:52 +01:00
gingerBill 75e15b05b0 Correct alias 2022-02-17 12:46:04 +00:00
Tail Wag Games 78eb388110 Adding capture procedures to user32
Adding `GetCapture`, `SetCapture` and `ReleaseCapture` functions - https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setcapture
2022-02-17 00:58:38 -06:00
CiD- df23cf47c6 fix odin test 2022-02-16 22:08:39 -05:00
gingerBill 002ac6a1b7 Add vendor:directx packages: dxgi, d3d11, and d3d12
TODO: enums marked with `bit_set` may need conversions
2022-02-16 21:26:34 +00:00
Jeroen van Rijn 40e4536887 Merge pull request #1502 from colrdavidson/mainline-fast
avoid memset on stats
2022-02-16 17:24:29 +01:00
Colin Davidson 536bf61323 avoid memset on stats 2022-02-16 08:14:11 -08:00
gingerBill c76bdced55 Merge branch 'master' into directx-packages 2022-02-16 16:05:46 +00:00
gingerBill 459ea5f4f6 Fix typo 2022-02-16 16:05:28 +00:00
gingerBill 8e8a075a22 Merge branch 'master' into directx-packages 2022-02-16 16:04:20 +00:00
gingerBill db6bd9b358 Allow sysv and win64 calling conventions to be used on any platform on amd64 2022-02-16 16:03:49 +00:00
gingerBill 42ad54c28e Improve metadata for context 2022-02-16 15:18:22 +00:00
gingerBill 1857bc7b02 Improve slice bounds checking runtime error messages 2022-02-16 14:51:54 +00:00
gingerBill e011d812ca Improve debug information for direct procedure parmaters 2022-02-16 14:39:08 +00:00
gingerBill 0738822dda Change how parameter and variables are given debug values 2022-02-16 13:25:31 +00:00
gingerBill 2213722776 Change debug declare to value 2022-02-16 12:37:22 +00:00
gingerBill 65dedbb1ca Add #subtype struct field prefix, required to have a COM interface hierarchy 2022-02-16 11:54:15 +00:00
gingerBill 0e69993d39 Add init and copy to all Objects 2022-02-16 00:17:07 +00:00
gingerBill 135091ddbe Correct import paths 2022-02-16 00:14:16 +00:00
gingerBill d64e3b672c Add darwin build tags 2022-02-16 00:12:31 +00:00
gingerBill a3bcacee27 Move Objective-C libraries located in core:sys/darwin/* to vendor:darwin/* 2022-02-16 00:06:25 +00:00
Jeroen van Rijn 855e7beab1 Merge pull request #1488 from colrdavidson/master
Add fork and personality
2022-02-15 21:04:09 +01:00
gingerBill edc13c29df Merge pull request #1331 from DanielGavin/parser-fault-recovery
Recover from closing brace not found in field list
2022-02-15 16:26:16 +00:00
gingerBill 21864d8d51 Improve BAD ENUM VALUE message in fmt #1496 2022-02-15 16:25:28 +00:00
gingerBill d45ff0694d Merge pull request #1438 from odin-lang/odin-global-constants-as-enums
Odin global constants as enums
2022-02-15 16:18:07 +00:00
gingerBill d695a8a526 Update os_darwin.odin 2022-02-15 16:02:14 +00:00
gingerBill 0380a288a9 Minor fix for -vet 2022-02-15 15:58:44 +00:00
gingerBill 1d4d0a3e1a Strip unneeded semicolons 2022-02-15 15:56:11 +00:00
gingerBill 9e98494fff Merge pull request #1482 from odin-lang/objc-intrinsics
Improve support Objective-C code through intrinsics and Metal API
2022-02-15 15:48:56 +00:00
gingerBill 86d334282c Merge pull request #1445 from Platin21/feature/darwin_systemcalls
Feature/darwin svc/syscall wrappers+id's
2022-02-15 15:48:20 +00:00
gingerBill 9cf937fef0 Merge pull request #1430 from DanielGavin/parser-fix
Fix return stmt when it's one lined(check for close brace).
2022-02-15 15:47:40 +00:00
gingerBill f5697dd7f2 Merge branch 'master' into odin-global-constants-as-enums 2022-02-15 15:47:24 +00:00
gingerBill a23ee1edc1 Merge pull request #1500 from thePHTest/master
Add 'odin run -help' info for specifying args
2022-02-15 15:46:27 +00:00
gingerBill 9dcb5c075a Merge pull request #1474 from Kelimion/tracking-example
mem: Add `doc.odin` with `Tracking_Allocator` example.
2022-02-15 15:46:19 +00:00
gingerBill 803648be89 Minor aesthetic clean ups of Foundation 2022-02-15 15:34:07 +00:00
gingerBill 3ab5db8297 Add README.md 2022-02-15 15:17:21 +00:00
gingerBill 3380ece4a1 Add utility calls for creating buffers from slices 2022-02-15 15:16:48 +00:00
gingerBill 0e5928ff39 Correct pseudo selector code generation 2022-02-15 15:16:30 +00:00
Phil H e6e04fc6c8 Add 'odin run -help' info for specifying args 2022-02-14 22:15:55 -08:00
gingerBill 753cceea82 Minor changes to method names on NS.String 2022-02-14 18:34:55 +00:00
gingerBill 32c7e81745 Use objc_allocateClassPair for intrinsics.objc_register_class 2022-02-14 18:32:10 +00:00
gingerBill 03aec70287 Change objc_class_name to objc_name with objc_is_class_method 2022-02-14 17:31:55 +00:00
gingerBill e69738c079 Minor style change 2022-02-14 17:23:14 +00:00
gingerBill 1afa7967f2 Fix method names 2022-02-14 17:09:30 +00:00
gingerBill 643e36b87b Improve Texture method names 2022-02-14 17:07:18 +00:00
gingerBill 3d2405ac2c Correct more method types 2022-02-14 17:02:05 +00:00
gingerBill 7392a3047a Add RenderPipeline missing types and methods 2022-02-14 16:58:56 +00:00
gingerBill 60f4d8f1ec Correct Render Pass types 2022-02-14 16:46:27 +00:00
gingerBill 7b42cbea20 Improve draw method names on RenderCommandEncoder 2022-02-14 16:42:53 +00:00
gingerBill 4cc597f4df RasterizationRate improvements 2022-02-14 16:32:54 +00:00
gingerBill 934e66ab3b More improvements 2022-02-14 16:26:42 +00:00
gingerBill b755609438 Improve Library related stuff 2022-02-14 16:25:20 +00:00
gingerBill 83d63e572a Improve indirect stuff 2022-02-14 16:21:00 +00:00
gingerBill 5212f62f54 Improve many methods with WithDescriptor suffixes 2022-02-14 16:18:23 +00:00
gingerBill 4d0fd4cf19 Correct device() usage 2022-02-14 15:56:32 +00:00
gingerBill e47953f7ca Improve procedure signature and names 2022-02-14 15:45:02 +00:00
gingerBill 47f3773146 Correct Depth classes 2022-02-14 15:18:38 +00:00
gingerBill 31c6ecad34 Correct Counter classes 2022-02-14 15:15:32 +00:00
gingerBill af6e53c05c Improve Compute classes 2022-02-14 15:14:41 +00:00
gingerBill 153140eb8f Improve ComputeCommandEncoder 2022-02-14 14:43:50 +00:00
gingerBill 6fef44c041 Improve CommandEncoder 2022-02-14 14:33:50 +00:00
gingerBill a88d149903 Improve CommandBuffer 2022-02-14 14:33:02 +00:00
gingerBill f9fc488399 Correct CaptureScope 2022-02-14 14:26:35 +00:00
gingerBill bef806bef4 Update Capture Manager classes 2022-02-14 14:24:36 +00:00
gingerBill 95e9bbf99f Improve Buffer 2022-02-14 12:52:30 +00:00
gingerBill 5936fa8871 Correct Blit Pass 2022-02-14 12:46:46 +00:00
gingerBill 02646b789c Correct typo 2022-02-14 12:44:57 +00:00
gingerBill 09e9dca869 Improve BlitCommandEncoder 2022-02-14 12:43:01 +00:00
gingerBill 9a43c0672e Correct BinaryArchive 2022-02-14 12:36:28 +00:00
gingerBill 83a6169463 Update ArgumentEncoder 2022-02-14 12:32:45 +00:00
gingerBill debe2de5fe Correct Acceleration Structure Types 2022-02-14 12:12:23 +00:00
gingerBill ff7d591ebf Correct AccelerationStructure classes 2022-02-14 11:55:59 +00:00
gingerBill 7386ca9272 Add new objc intrinsics: objc_(register|find)_(selector|class) 2022-02-14 11:21:21 +00:00
gingerBill fd8b2e0b88 Merge branch 'master' into objc-intrinsics 2022-02-14 11:04:36 +00:00
gingerBill c34ae884ad Change to "object" 2022-02-14 11:04:29 +00:00
gingerBill 2e7157ae9c Correct bytes._split_iterator 2022-02-14 11:01:34 +00:00
gingerBill 441365b388 Set the macOS minimum version to 12 for ARM CPUs 2022-02-14 10:58:01 +00:00
gingerBill f561147190 Correct _split_iterator 2022-02-14 10:57:29 +00:00
gingerBill 2958c1d6aa Add new shorthand 2022-02-13 16:56:27 +00:00
gingerBill 9dc83bc1b3 Add more methods 2022-02-13 16:32:31 +00:00
gingerBill 88b1b2c629 Correct types 2022-02-13 15:11:45 +00:00
gingerBill 23bc643a81 Merge branch 'objc-intrinsics' of https://github.com/odin-lang/Odin into objc-intrinsics 2022-02-13 12:01:19 +00:00
gingerBill 41854bacf5 Add utility classes for dealing with Windows
Most for GLFW and SDL only
2022-02-13 11:54:40 +00:00
gingerBill cf528431f5 Merge pull request #1495 from FancyKillerPanda/master
Updated vendor/sdl2/ttf LIB and DLL.
2022-02-12 23:46:44 +00:00
FancyKillerPanda e59064dd59 Updated vendor/sdl2/ttf LIB and DLL. 2022-02-13 10:33:48 +11:00
gingerBill 8966294823 Correct method name 2022-02-12 22:03:15 +00:00
gingerBill b8479ea79d Merge branch 'master' into objc-intrinsics 2022-02-12 21:49:48 +00:00
gingerBill e2aa8f426d Improve type hierarchy and method names 2022-02-12 21:45:34 +00:00
gingerBill 39a0f8c96a Use distinct array types 2022-02-12 21:28:56 +00:00
gingerBill b647b45ba5 Remove temp file 2022-02-12 21:25:20 +00:00
gingerBill 5fe9aa919b Correct types in methods 2022-02-12 21:24:28 +00:00
gingerBill ff5d6a994b Move vendor:Metal to core:sys/darwin/Metal 2022-02-12 17:59:40 +00:00
gingerBill ae3b95b194 #force_inline procedures and move foreign procedures to a separate file 2022-02-12 17:46:19 +00:00
gingerBill acaae1357c Update Metal for the full API
Methods need better names
2022-02-12 17:30:32 +00:00
gingerBill f8afda3b22 Add more objc attributes 2022-02-11 22:54:51 +00:00
Colin Davidson 31f544c258 Merge branch 'odin-lang:master' into master 2022-02-11 08:25:17 -08:00
Mikkel Hjortshøj 1c57d1c019 Update nightly.yml 2022-02-11 17:22:33 +01:00
Mikkel Hjortshøj 251edf7bc7 Update ci.yml 2022-02-11 17:22:14 +01:00
Colin Davidson f77cd5533d Add fork and personality 2022-02-11 08:10:48 -08:00
gingerBill 416413bebf Begin work on Metal 2022-02-10 14:35:10 +00:00
gingerBill c3809d7b84 Fix typo 2022-02-09 21:46:26 +00:00
gingerBill 42a1c58a80 Update Foundation linking 2022-02-09 21:42:20 +00:00
gingerBill b6abaf739c Add missing calls for Object; Add scoped_autoreleasepool 2022-02-09 12:29:52 +00:00
gingerBill ef98e92e8d Remove unneeded file 2022-02-09 12:23:41 +00:00
gingerBill 768c2684d0 Add NSBundle, NSError, NSEnumerator 2022-02-09 12:19:59 +00:00
gingerBill 5f2514db63 Add NSNumber and NSURL 2022-02-09 11:50:11 +00:00
gingerBill b95ade40c0 Begin work on core:sys/darwin/Foundation 2022-02-09 00:19:20 +00:00
gingerBill 340838c878 Add procs_darwin.odin 2022-02-08 23:00:00 +00:00
gingerBill c5d348515d Add intrinsics.type_is_subtype_of; intrinsics.objc_selector_name 2022-02-08 22:59:37 +00:00
gingerBill 05dd3d490d Correct objc_class propagation for parapoly structs 2022-02-08 17:33:55 +00:00
gingerBill 0cc40db565 Begin work on support objc intrinsics 2022-02-08 17:04:55 +00:00
Jeroen van Rijn 546faab0cb Merge pull request #1481 from jasonKercher/vet_fix
fix `-vet` for `filepath/match.odin`
2022-02-08 15:27:51 +01:00
CiD- 83e9a6b417 fix -vet for filepath/match.odin 2022-02-08 09:21:43 -05:00
gingerBill 30bb2382aa Correct simple boolean intrinsics 2022-02-08 11:48:59 +00:00
gingerBill 61a0b4ec5a Merge pull request #1480 from NoahR02/opensimplex2_noise
Adds OpenSimplex Noise to Odin.
2022-02-08 11:42:17 +00:00
NoahR02 accb35506f Ports OpenSimplex2 from https://github.com/KdotJPG/OpenSimplex2 to Odin. Adds tests for the noise procedures. 2022-02-08 06:25:07 -05:00
NoahR02 817bc7434d Ports OpenSimplex2 from https://github.com/KdotJPG/OpenSimplex2 to Odin. Adds tests for the noise procedures. 2022-02-08 06:16:10 -05:00
gingerBill 3c2ed3bb69 Correct //+private file bug 2022-02-07 11:37:13 +00:00
gingerBill 9cbf46e689 Fix constant multi pointer declarations through integers 2022-02-07 11:00:38 +00:00
gingerBill ad6ea3d6aa Replace any with union for subtyping in core:odin/ast 2022-02-06 13:31:16 +00:00
gingerBill cda9fd5271 Add tag to ast.Comp_Lit 2022-02-06 11:59:12 +00:00
gingerBill 0c16f27814 Update parser for #sparse 2022-02-06 11:50:27 +00:00
gingerBill 19aec13a10 Support rank-2 arrays (matrix-like) for transpose 2022-02-06 11:42:59 +00:00
Jeroen van Rijn e896956275 Merge pull request #1475 from Platin21/feature/fix-odin-fmt
Feature/fix odin fmt
2022-02-05 23:22:07 +01:00
Platin21 c59c6e98a5 Merge branch 'odin-lang:master' into feature/fix-odin-fmt 2022-02-05 23:14:44 +01:00
Platin21 8b1100bf2b os.open does r/d as default which makes a call to open a dir invalid this should fix this problem 2022-02-05 23:12:55 +01:00
Jeroen van Rijn a3d99765cc mem: Add doc.odin with Tracking_Allocator example. 2022-02-05 22:18:22 +01:00
Platin21 a724573bb3 Fixes fopendir and readdir_r for arm64 or seemingly doing so 2022-02-05 21:16:58 +01:00
Jeroen van Rijn 25769f139a Merge pull request #1471 from Platin21/feature/fix-odin-fmt
Feature/fix odin fmt
2022-02-05 21:00:52 +01:00
Platin21 3edf638cc6 Fixed Typo 2022-02-05 20:54:27 +01:00
Platin21 de7e612186 Ignores DS_Store files which MacOS uses for Indexing or some crap 2022-02-05 20:45:55 +01:00
Platin21 a571153458 Adds missing calls for os 2022-02-05 20:45:32 +01:00
Jeroen van Rijn ada58c66fa Merge pull request #1469 from ap29600/bit_iterator
add `iterator` to `core:container/bit_array`
2022-02-05 18:50:33 +01:00
ap29600 697f8c7ee6 replace a branch with max in core:container/bit_array.set 2022-02-05 18:46:25 +01:00
Andrea Piseri b6ebfe4b2c rename iterator procedures 2022-02-05 18:11:48 +01:00
Andrea Piseri bccbdefde9 Update interface to allow more modes of iteration
It's now possible to iterate over:
- all keys in the range min_value ..= max_value, with `iterate_all`
- all set keys in the bit array, with `iterate_set`
- all unset keys in the range min_value ..= max_value, with `iterate_unset`

`Bit_Array` now stores the `max_value` provided during construction, and
updates it when a key that was previously out of range is set.
2022-02-05 18:00:59 +01:00
gingerBill 445ca70521 Correct implicit union cast 2022-02-05 16:11:48 +00:00
gingerBill c6ab8f82c8 Code refactor to aid development 2022-02-05 15:17:47 +00:00
gingerBill 67ce0ec29f Improve printing for unhandled cases by adding a new line before the cases 2022-02-05 14:58:13 +00:00
gingerBill 23c3573c30 Minor correction to error message suggestion 2022-02-05 14:56:06 +00:00
gingerBill a4308e7246 Improve union variant assignment determination 2022-02-05 14:45:59 +00:00
gingerBill 3439139b1c Minor clean up 2022-02-05 14:34:29 +00:00
gingerBill cf246f65ff Add check for variables which are both shadowing and unused by default 2022-02-05 14:31:22 +00:00
gingerBill dd84b61cc8 Correct add_to_seen_map logic 2022-02-05 14:07:17 +00:00
gingerBill b8c4bf2afb Add #partial [Enum]Type{...} support to check for missing enumerated array fields 2022-02-05 14:02:21 +00:00
gingerBill e870041fe6 Fix #sparse usage 2022-02-05 13:11:41 +00:00
gingerBill 6418ec3b21 Correct #sparse usage and error messages 2022-02-05 13:09:16 +00:00
gingerBill 2bcc7b0064 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-05 13:01:21 +00:00
gingerBill 97be867103 Rename #partial[Enum]Type to #sparse[Enum]Type for non-contiguous enum fields 2022-02-05 13:01:15 +00:00
gingerBill fb710f8cbf Merge pull request #1376 from jasonKercher/master
Added zeroing to new memory regions from _unix_realloc
2022-02-05 12:26:10 +00:00
gingerBill 1553137c23 Change behaviour of A :: distinct Enum_Type to be more intuitive 2022-02-05 00:04:02 +00:00
gingerBill d5384c5aa4 Only check idents in the alias (of alias)+ problem 2022-02-04 22:45:13 +00:00
gingerBill 3a81f2ab89 Correct the type aliasing problem, caused by aliases (of aliases)+ 2022-02-04 22:40:15 +00:00
ap29600 b54fc96b1e rename iterator proc to next, add named return values 2022-02-04 22:39:47 +01:00
Andrea Piseri 48af78e469 add iterator to core:container/bit_array 2022-02-04 22:12:07 +01:00
gingerBill abb26e0bea Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-04 12:08:24 +00:00
gingerBill 76edfae0e0 core:container/topological_sort 2022-02-04 12:08:20 +00:00
gingerBill a5298e17ec Merge pull request #1467 from ap29600/u128_endian_swap
fix logic in bswap_128
2022-02-03 15:06:12 +00:00
Andrea Piseri cf9f3d5e2d fix logic in bswap_128 2022-02-03 15:50:39 +01:00
gingerBill 35c90fe124 Fix type alias declaration evaluation problem (#854 #1439) 2022-02-03 13:34:31 +00:00
gingerBill df8bdac33f Initialize the global_rand with the intrinsics.read_cycle_counter() value 2022-02-03 00:31:36 +00:00
gingerBill b4f7a527c2 Merge branch 'master' of https://github.com/odin-lang/Odin 2022-02-02 23:38:40 +00:00
gingerBill 35533a7baa Update core:container/lru to support clear and take a boolean to indicate whether or not to call the on_remove procedure on clear or destroy 2022-02-02 23:38:32 +00:00
gingerBill 2c9ed7464f Merge pull request #1465 from ap29600/reflect_is_nil_fix
Fix logic in `is_nil` procedure
2022-02-02 19:36:25 +00:00
Andrea Piseri e190c024fd Fix logic in is_nil procedure: a non_nil slice means there is data to check. 2022-02-02 20:07:38 +01:00
gingerBill e250475bf9 Merge pull request #1457 from DanielGavin/parser-inline
Fix core:odin/parser not setting the inline flag correctly.
2022-02-02 16:32:09 +00:00
gingerBill 5db603ded2 Minor sanity clean up 2022-02-02 15:39:41 +00:00
gingerBill 78815778ee Add //+private file to complement //+private (//+private package) 2022-02-02 15:28:49 +00:00
Daniel Gavin ff5e036773 Trim whitespaces 2022-01-27 14:27:26 +01:00
Daniel Gavin 4dc29d141f Fix core:odin/parser not setting the inline flag correctly. 2022-01-27 14:24:33 +01:00
Daniel Gavin 8ecee32e1c Merge remote-tracking branch 'upstream/master' into parser-fix 2022-01-27 13:58:41 +01:00
Daniel Gavin 6a7d821fcc Merge remote-tracking branch 'upstream/master' into parser-fix 2022-01-24 16:58:39 +01:00
Platin21 1243b1a58c Fixed cyclic imports which where not needed 2022-01-23 23:16:57 +01:00
Platin21 ab3bae5c02 Fixed package name 2022-01-23 23:14:46 +01:00
Platin21 540c5400a0 Adds several system calls and the beginning of odin wrappers for them
This also adds all systemcall numbers from the xnu kernel / and additional helpers for some of the calls to make it easier to call them from odin
2022-01-23 23:13:32 +01:00
Daniel Gavin 01e29bf27e Merge remote-tracking branch 'upstream/master' into parser-fix 2022-01-23 01:38:15 +01:00
gingerBill 6223f48c3f Update tests 2022-01-20 20:08:24 +00:00
gingerBill f2f20def37 Update demo.odin 2022-01-20 20:02:41 +00:00
gingerBill 77b91352ae Add Odin_OS_Type and Odin_Arch_Type to core:runtime 2022-01-20 19:58:35 +00:00
gingerBill 3d7d347192 Convert ODIN_OS and ODIN_ARCH to use enums rather than use strings 2022-01-20 19:56:05 +00:00
CiD- e5868e3205 add zeroing regardless of ODIN_OS 2022-01-20 10:17:47 -05:00
Daniel Gavin 96d7c4ffdf Merge remote-tracking branch 'upstream/master' into parser-fix 2022-01-17 13:15:44 +01:00
Daniel Gavin f19325cbe0 Merge remote-tracking branch 'upstream/master' into parser-fix 2022-01-16 13:54:22 +01:00
Daniel Gavin d57ec4a11d Fix return stmt when it's one lined(check for close brace). 2022-01-16 13:20:12 +01:00
Henry Dooley 865d88dd56 review feedback 2021-12-28 10:50:34 -06:00
Henry Dooley 069c05669f cast isize to unsigned int for llvm api, add defaulted name parameter to helper. 2021-12-25 16:46:02 -06:00
Henry Dooley 516065d7c2 factor out alloca generation into a helper 2021-12-25 16:28:09 -06:00
CiD- ebdb3ab43a added notes about _unix_alloc 2021-12-17 12:04:05 -05:00
CiD- 29ca6ee420 add zeroing to new region from realloc 2021-12-17 10:41:49 -05:00
Jeroen van Rijn 6e61abc7d0 [xml] Initial optimization. 2021-12-06 12:04:59 +01:00
Jeroen van Rijn 7ec88d2430 [xml] Add option. 2021-12-05 21:06:33 +01:00
Jeroen van Rijn d7200f6144 Improve tests in general.
Less spammy core tests: They don't print PASSes now, only logs and failures.

`core:image` and `core:encoding/xml` tests also find their assets relative to `ODIN_ROOT` now.
2021-12-05 02:53:09 +01:00
Jeroen van Rijn d65d6edb0e [xml] Improve XML tests, test core:encoding/entity. 2021-12-05 02:52:23 +01:00
Jeroen van Rijn 3d72e80ccf [xml] Implement optional unboxing of CDATA and decoding of tag values. 2021-12-05 02:52:23 +01:00
Jeroen van Rijn 2dd67dba89 [core:encoding/entity] Add new package to decode &<entity>; entities.
Includes generator to generate a lookup for named entitiess.
2021-12-05 02:52:23 +01:00
Jeroen van Rijn 5807214406 [xml] Improvements. 2021-12-05 02:52:23 +01:00
Jeroen van Rijn 23baf56c87 [xml] Improve CDATA + comment handling in tag body. 2021-12-05 02:52:23 +01:00
Jeroen van Rijn beff90e1d1 [xml] Slight optimization.
About a 5% speed bump.

More rigorous optimization later.
2021-12-05 02:52:23 +01:00
Jeroen van Rijn ec63d0bbd2 [xml] Robustness improvement.
Can now parse  https://www.w3.org/2003/entities/2007xml/unicode.xml no problem.
2021-12-05 02:52:22 +01:00
Jeroen van Rijn 32eab04d66 [xml] Allow multi-line bodies w/o CDATA. Strip trailing whitespace. 2021-12-05 02:52:22 +01:00
Jeroen van Rijn 682783a2aa [xml] Tab indentation in debug printer. 2021-12-05 02:52:22 +01:00
Jeroen van Rijn 46a4927aca [xml] Use io.Writer for xml.print(doc). 2021-12-05 02:52:22 +01:00
Jeroen van Rijn 9b2e67df67 [xml] Small cleanup. 2021-12-05 02:52:22 +01:00
Jeroen van Rijn b5c828fe4e [xml] Initial implementation of core:encoding/xml.
A from-scratch XML implementation, loosely modeled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816).

Features:
		- Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage.
		- Simple to understand and use. Small.

Caveats:
		- We do NOT support HTML in this package, as that may or may not be valid XML.
		  If it works, great. If it doesn't, that's not considered a bug.

		- We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences.
		- <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options.

TODO:
- Optional CDATA unboxing.
- Optional `&gt;`, `&#32;`, `&#x20;` and other escape substitution in tag bodies.
- Test suite

MAYBE:
- XML writer?
- Serialize/deserialize Odin types?
2021-12-05 02:52:22 +01:00
Daniel Gavin a4ba91a554 Check for non inserted semicolon in *expect_closing_brace_of_field_list* 2021-11-25 18:47:58 +01:00
Daniel Gavin cf390bf8b9 Recover from closing brace not found in field list 2021-11-24 21:20:46 +01:00
577 changed files with 120180 additions and 29331 deletions
+1
View File
@@ -1,3 +1,4 @@
# These are supported funding model platforms
github: odin-lang
patreon: gingerbill
+42 -4
View File
@@ -7,9 +7,9 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: Download LLVM, botan
run: sudo apt-get install llvm-11 clang-11 llvm libbotan-2-dev botan
run: sudo apt-get install llvm-11 clang-11 libbotan-2-dev botan
- name: build odin
run: make release
run: ./build_odin.sh release
- name: Odin version
run: ./odin version
timeout-minutes: 1
@@ -38,6 +38,20 @@ jobs:
cd tests/vendor
make
timeout-minutes: 10
- name: Odin issues tests
run: |
cd tests/issues
./run.sh
timeout-minutes: 10
- name: Odin check examples/all for Linux i386
run: ./odin check examples/all -vet -strict-style -target:linux_i386
timeout-minutes: 10
- name: Odin check examples/all for FreeBSD amd64
run: ./odin check examples/all -vet -strict-style -target:freebsd_amd64
timeout-minutes: 10
- name: Odin check examples/all for OpenBSD amd64
run: ./odin check examples/all -vet -strict-style -target:openbsd_amd64
timeout-minutes: 10
build_macOS:
runs-on: macos-latest
steps:
@@ -49,7 +63,7 @@ jobs:
TMP_PATH=$(xcrun --show-sdk-path)/user/include
echo "CPATH=$TMP_PATH" >> $GITHUB_ENV
- name: build odin
run: make release
run: ./build_odin.sh release
- name: Odin version
run: ./odin version
timeout-minutes: 1
@@ -78,8 +92,19 @@ jobs:
cd tests/vendor
make
timeout-minutes: 10
- name: Odin issues tests
run: |
cd tests/issues
./run.sh
timeout-minutes: 10
- name: Odin check examples/all for Darwin arm64
run: ./odin check examples/all -vet -strict-style -target:darwin_arm64
timeout-minutes: 10
- name: Odin check examples/all for Linux arm64
run: ./odin check examples/all -vet -strict-style -target:linux_arm64
timeout-minutes: 10
build_windows:
runs-on: windows-latest
runs-on: windows-2019
steps:
- uses: actions/checkout@v1
- name: build Odin
@@ -138,3 +163,16 @@ jobs:
cd tests\core\math\big
call build.bat
timeout-minutes: 10
- name: Odin issues tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\issues
call run.bat
timeout-minutes: 10
- name: Odin check examples/all for Windows 32bits
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style -target:windows_i386
timeout-minutes: 10
+7 -7
View File
@@ -7,7 +7,7 @@ on:
jobs:
build_windows:
runs-on: windows-latest
runs-on: windows-2019
steps:
- uses: actions/checkout@v1
- name: build Odin
@@ -19,7 +19,7 @@ jobs:
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo/demo.odin
odin run examples/demo
- name: Copy artifacts
run: |
rm bin/llvm/windows/LLVM-C.lib
@@ -41,11 +41,11 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: (Linux) Download LLVM
run: sudo apt-get install llvm-11 clang-11 llvm
run: sudo apt-get install llvm-11 clang-11
- name: build odin
run: make nightly
- name: Odin run
run: ./odin run examples/demo/demo.odin
run: ./odin run examples/demo
- name: Copy artifacts
run: |
mkdir dist
@@ -72,7 +72,7 @@ jobs:
- name: build odin
run: make nightly
- name: Odin run
run: ./odin run examples/demo/demo.odin
run: ./odin run examples/demo
- name: Copy artifacts
run: |
mkdir dist
@@ -129,7 +129,7 @@ jobs:
run: |
echo Authorizing B2 account
b2 authorize-account "$APPID" "$APPKEY"
echo Uploading artifcates to B2
chmod +x ./ci/upload_create_nightly.sh
./ci/upload_create_nightly.sh "$BUCKET" windows-amd64 windows_artifacts/
@@ -141,7 +141,7 @@ jobs:
echo Creating nightly.json
python3 ci/create_nightly_json.py "$BUCKET" > nightly.json
echo Uploading nightly.json
b2 upload-file "$BUCKET" nightly.json nightly.json
+7
View File
@@ -7,6 +7,9 @@
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# For macOS
.DS_Store
# Build results
[Dd]ebug/
[Dd]ebugPublic/
@@ -266,6 +269,8 @@ bin/
# - Linux/MacOS
odin
odin.dSYM
*.bin
demo.bin
# shared collection
shared/
@@ -276,3 +281,5 @@ shared/
*.ll
*.sublime-workspace
examples/bug/
build.sh
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2016-2021 Ginger Bill. All rights reserved.
Copyright (c) 2016-2022 Ginger Bill. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
+6 -67
View File
@@ -1,80 +1,19 @@
GIT_SHA=$(shell git rev-parse --short HEAD)
DISABLED_WARNINGS=-Wno-switch -Wno-macro-redefined -Wno-unused-value
LDFLAGS=-pthread -ldl -lm -lstdc++
CFLAGS=-std=c++14 -DGIT_SHA=\"$(GIT_SHA)\"
CFLAGS:=$(CFLAGS) -DODIN_VERSION_RAW=\"dev-$(shell date +"%Y-%m")\"
CC=clang
OS=$(shell uname)
ifeq ($(OS), Darwin)
ARCH=$(shell uname -m)
LLVM_CONFIG=
# allow for arm only llvm's with version 13
ifeq ($(ARCH), arm64)
LLVM_VERSIONS = "13.%.%"
else
# allow for x86 / amd64 all llvm versions begining from 11
LLVM_VERSIONS = "13.%.%" "12.0.1" "11.1.0"
endif
LLVM_VERSION_PATTERN_SEPERATOR = )|(
LLVM_VERSION_PATTERNS_ESCAPED_DOT = $(subst .,\.,$(LLVM_VERSIONS))
LLVM_VERSION_PATTERNS_REPLACE_PERCENT = $(subst %,.*,$(LLVM_VERSION_PATTERNS_ESCAPED_DOT))
LLVM_VERSION_PATTERN_REMOVE_ELEMENTS = $(subst " ",$(LLVM_VERSION_PATTERN_SEPERATOR),$(LLVM_VERSION_PATTERNS_REPLACE_PERCENT))
LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS))
LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))"
ifneq ($(shell llvm-config --version | grep -E $(LLVM_VERSION_PATTERN)),)
LLVM_CONFIG=llvm-config
else
ifeq ($(ARCH), arm64)
$(error "Requirement: llvm-config must be base version 13 for arm64")
else
$(error "Requirement: llvm-config must be base version greater than 11 for amd64/x86")
endif
endif
LDFLAGS:=$(LDFLAGS) -liconv
CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags)
LDFLAGS:=$(LDFLAGS) -lLLVM-C
endif
ifeq ($(OS), Linux)
LLVM_CONFIG=llvm-config-11
ifneq ($(shell which llvm-config-11 2>/dev/null),)
LLVM_CONFIG=llvm-config-11
else ifneq ($(shell which llvm-config-11-64 2>/dev/null),)
LLVM_CONFIG=llvm-config-11-64
else
ifneq ($(shell llvm-config --version | grep '^11\.'),)
LLVM_CONFIG=llvm-config
else
$(error "Requirement: llvm-config must be version 11")
endif
endif
CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags)
LDFLAGS:=$(LDFLAGS) $(shell $(LLVM_CONFIG) --libs core native --system-libs)
endif
all: debug demo
all: debug
demo:
./odin run examples/demo/demo.odin
./odin run examples/demo/demo.odin -file
report:
./odin report
debug:
$(CC) src/main.cpp src/libtommath.cpp $(DISABLED_WARNINGS) $(CFLAGS) -g $(LDFLAGS) -o odin
./build_odin.sh debug
release:
$(CC) src/main.cpp src/libtommath.cpp $(DISABLED_WARNINGS) $(CFLAGS) -O3 $(LDFLAGS) -o odin
./build_odin.sh release
release_native:
$(CC) src/main.cpp src/libtommath.cpp $(DISABLED_WARNINGS) $(CFLAGS) -O3 -march=native $(LDFLAGS) -o odin
./build_odin.sh release-native
nightly:
$(CC) src/main.cpp src/libtommath.cpp $(DISABLED_WARNINGS) $(CFLAGS) -DNIGHTLY -O3 $(LDFLAGS) -o odin
./build_odin.sh nightly
+9 -7
View File
@@ -11,7 +11,7 @@
<img src="https://img.shields.io/badge/platforms-Windows%20|%20Linux%20|%20macOS-green.svg">
</a>
<br>
<a href="https://discord.gg/hnwN2Rj">
<a href="https://discord.gg/odinlang">
<img src="https://img.shields.io/discord/568138951836172421?logo=discord">
</a>
<a href="https://github.com/odin-lang/odin/actions">
@@ -58,6 +58,10 @@ main :: proc() {
Instructions for downloading and installing the Odin compiler and libraries.
#### [Nightly Builds](https://odin-lang.org/docs/nightly/)
Get the latest nightly builds of Odin.
### Learning Odin
#### [Overview of Odin](https://odin-lang.org/docs/overview)
@@ -68,6 +72,10 @@ An overview of the Odin programming language.
Answers to common questions about Odin.
#### [Packages](https://pkg.odin-lang.org/)
Documentation for all the official packages part of the [core](https://pkg.odin-lang.org/core/) and [vendor](https://pkg.odin-lang.org/vendor/) library collections.
#### [The Odin Wiki](https://github.com/odin-lang/Odin/wiki)
A wiki maintained by the Odin community.
@@ -76,12 +84,6 @@ A wiki maintained by the Odin community.
Get live support and talk with other odiners on the Odin Discord.
### References
#### [Language Specification](https://odin-lang.org/docs/spec/)
The official Odin Language specification.
### Articles
#### [The Odin Blog](https://odin-lang.org/news/)
Executable
+150
View File
@@ -0,0 +1,150 @@
#!/bin/bash
set -eu
GIT_SHA=$(git rev-parse --short HEAD)
DISABLED_WARNINGS="-Wno-switch -Wno-macro-redefined -Wno-unused-value"
LDFLAGS="-pthread -lm -lstdc++"
CFLAGS="-std=c++14 -DGIT_SHA=\"$GIT_SHA\""
CFLAGS="$CFLAGS -DODIN_VERSION_RAW=\"dev-$(date +"%Y-%m")\""
CC=clang
OS=$(uname)
panic() {
printf "%s\n" "$1"
exit 1
}
version() { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
config_darwin() {
ARCH=$(uname -m)
LLVM_CONFIG=llvm-config
# allow for arm only llvm's with version 13
if [ ARCH == arm64 ]; then
MIN_LLVM_VERSION=("13.0.0")
else
# allow for x86 / amd64 all llvm versions begining from 11
MIN_LLVM_VERSION=("11.1.0")
fi
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
if [ ARCH == arm64 ]; then
panic "Requirement: llvm-config must be base version 13 for arm64"
else
panic "Requirement: llvm-config must be base version greater than 11 for amd64/x86"
fi
fi
LDFLAGS="$LDFLAGS -liconv -ldl"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS -lLLVM-C"
}
config_freebsd() {
LLVM_CONFIG=/usr/local/bin/llvm-config11
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
config_openbsd() {
LLVM_CONFIG=/usr/local/bin/llvm-config
LDFLAGS="$LDFLAGS -liconv"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
config_linux() {
if which llvm-config > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config
elif which llvm-config-11 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11
elif which llvm-config-11-64 > /dev/null 2>&1; then
LLVM_CONFIG=llvm-config-11-64
else
panic "Unable to find LLVM-config"
fi
MIN_LLVM_VERSION=("11.0.0")
if [ $(version $($LLVM_CONFIG --version)) -lt $(version $MIN_LLVM_VERSION) ]; then
echo "Tried to use " $(which $LLVM_CONFIG) "version" $($LLVM_CONFIG --version)
panic "Requirement: llvm-config must be base version greater than 11"
fi
LDFLAGS="$LDFLAGS -ldl"
CFLAGS="$CFLAGS $($LLVM_CONFIG --cxxflags --ldflags)"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
}
build_odin() {
case $1 in
debug)
EXTRAFLAGS="-g"
;;
release)
EXTRAFLAGS="-O3"
;;
release-native)
EXTRAFLAGS="-O3 -march=native"
;;
nightly)
EXTRAFLAGS="-DNIGHTLY -O3"
;;
*)
panic "Build mode unsupported!"
esac
set -x
$CC src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CFLAGS $EXTRAFLAGS $LDFLAGS -o odin
set +x
}
run_demo() {
./odin run examples/demo/demo.odin -file
}
case $OS in
Linux)
config_linux
;;
Darwin)
config_darwin
;;
OpenBSD)
config_openbsd
;;
FreeBSD)
config_freebsd
;;
*)
panic "Platform unsupported!"
esac
if [[ $# -eq 0 ]]; then
build_odin debug
run_demo
exit 0
fi
if [[ $# -eq 1 ]]; then
case $1 in
report)
if [[ ! -f "./odin" ]]; then
build_odin debug
fi
./odin report
exit 0
;;
*)
build_odin $1
;;
esac
run_demo
exit 0
else
panic "Too many arguments!"
fi
+3 -6
View File
@@ -8,6 +8,7 @@ import "core:intrinsics"
// Extra errors returns by scanning procedures
Scanner_Extra_Error :: enum i32 {
None,
Negative_Advance,
Advanced_Too_Far,
Bad_Read_Count,
@@ -15,7 +16,7 @@ Scanner_Extra_Error :: enum i32 {
Too_Short,
}
Scanner_Error :: union {
Scanner_Error :: union #shared_nil {
io.Error,
Scanner_Extra_Error,
}
@@ -68,7 +69,7 @@ scanner_destroy :: proc(s: ^Scanner) {
// Returns the first non-EOF error that was encounted by the scanner
scanner_error :: proc(s: ^Scanner) -> Scanner_Error {
switch s._err {
case .EOF, .None:
case .EOF, nil:
return nil
}
return s._err
@@ -93,10 +94,6 @@ scanner_text :: proc(s: ^Scanner) -> string {
// scanner_scan advances the scanner
scanner_scan :: proc(s: ^Scanner) -> bool {
set_err :: proc(s: ^Scanner, err: Scanner_Error) {
err := err
if err == .None {
err = nil
}
switch s._err {
case nil, .EOF:
s._err = err
+66 -66
View File
@@ -1,90 +1,90 @@
// This is purely for documentation
package builtin
nil :: nil;
false :: 0!=0;
true :: 0==0;
nil :: nil
false :: 0!=0
true :: 0==0
ODIN_OS :: ODIN_OS;
ODIN_ARCH :: ODIN_ARCH;
ODIN_ENDIAN :: ODIN_ENDIAN;
ODIN_VENDOR :: ODIN_VENDOR;
ODIN_VERSION :: ODIN_VERSION;
ODIN_ROOT :: ODIN_ROOT;
ODIN_DEBUG :: ODIN_DEBUG;
ODIN_OS :: ODIN_OS
ODIN_ARCH :: ODIN_ARCH
ODIN_ENDIAN :: ODIN_ENDIAN
ODIN_VENDOR :: ODIN_VENDOR
ODIN_VERSION :: ODIN_VERSION
ODIN_ROOT :: ODIN_ROOT
ODIN_DEBUG :: ODIN_DEBUG
byte :: u8; // alias
byte :: u8 // alias
bool :: bool;
b8 :: b8;
b16 :: b16;
b32 :: b32;
b64 :: b64;
bool :: bool
b8 :: b8
b16 :: b16
b32 :: b32
b64 :: b64
i8 :: i8;
u8 :: u8;
i16 :: i16;
u16 :: u16;
i32 :: i32;
u32 :: u32;
i64 :: i64;
u64 :: u64;
i8 :: i8
u8 :: u8
i16 :: i16
u16 :: u16
i32 :: i32
u32 :: u32
i64 :: i64
u64 :: u64
i128 :: i128;
u128 :: u128;
i128 :: i128
u128 :: u128
rune :: rune;
rune :: rune
f16 :: f16;
f32 :: f32;
f64 :: f64;
f16 :: f16
f32 :: f32
f64 :: f64
complex32 :: complex32;
complex64 :: complex64;
complex128 :: complex128;
complex32 :: complex32
complex64 :: complex64
complex128 :: complex128
quaternion64 :: quaternion64;
quaternion128 :: quaternion128;
quaternion256 :: quaternion256;
quaternion64 :: quaternion64
quaternion128 :: quaternion128
quaternion256 :: quaternion256
int :: int;
uint :: uint;
uintptr :: uintptr;
int :: int
uint :: uint
uintptr :: uintptr
rawptr :: rawptr;
string :: string;
cstring :: cstring;
any :: any;
rawptr :: rawptr
string :: string
cstring :: cstring
any :: any
typeid :: typeid;
typeid :: typeid
// Endian Specific Types
i16le :: i16le;
u16le :: u16le;
i32le :: i32le;
u32le :: u32le;
i64le :: i64le;
u64le :: u64le;
i128le :: i128le;
u128le :: u128le;
i16le :: i16le
u16le :: u16le
i32le :: i32le
u32le :: u32le
i64le :: i64le
u64le :: u64le
i128le :: i128le
u128le :: u128le
i16be :: i16be;
u16be :: u16be;
i32be :: i32be;
u32be :: u32be;
i64be :: i64be;
u64be :: u64be;
i128be :: i128be;
u128be :: u128be;
i16be :: i16be
u16be :: u16be
i32be :: i32be
u32be :: u32be
i64be :: i64be
u64be :: u64be
i128be :: i128be
u128be :: u128be
f16le :: f16le;
f32le :: f32le;
f64le :: f64le;
f16le :: f16le
f32le :: f32le
f64le :: f64le
f16be :: f16be;
f32be :: f32be;
f64be :: f64be;
f16be :: f16be
f32be :: f32be
f64be :: f64be
+56 -36
View File
@@ -10,7 +10,14 @@ clone :: proc(s: []byte, allocator := context.allocator, loc := #caller_location
return c[:len(s)]
}
ptr_from_slice :: proc(str: []byte) -> ^byte {
clone_safe :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> (data: []byte, err: mem.Allocator_Error) {
c := make([]byte, len(s), allocator, loc) or_return
copy(c, s)
return c[:len(s)], nil
}
ptr_from_slice :: ptr_from_bytes
ptr_from_bytes :: proc(str: []byte) -> ^byte {
d := transmute(mem.Raw_String)str
return d.data
}
@@ -134,6 +141,25 @@ join :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> []byte
return b
}
join_safe :: proc(a: [][]byte, sep: []byte, allocator := context.allocator) -> (data: []byte, err: mem.Allocator_Error) {
if len(a) == 0 {
return nil, nil
}
n := len(sep) * (len(a) - 1)
for s in a {
n += len(s)
}
b := make([]byte, n, allocator) or_return
i := copy(b, a[0])
for s in a[1:] {
i += copy(b[i:], sep)
i += copy(b[i:], s)
}
return b, nil
}
concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte {
if len(a) == 0 {
return nil
@@ -151,6 +177,24 @@ concatenate :: proc(a: [][]byte, allocator := context.allocator) -> []byte {
return b
}
concatenate_safe :: proc(a: [][]byte, allocator := context.allocator) -> (data: []byte, err: mem.Allocator_Error) {
if len(a) == 0 {
return nil, nil
}
n := 0
for s in a {
n += len(s)
}
b := make([]byte, n, allocator) or_return
i := 0
for s in a {
i += copy(b[i:], s)
}
return b, nil
}
@private
_split :: proc(s, sep: []byte, sep_save, n: int, allocator := context.allocator) -> [][]byte {
s, n := s, n
@@ -218,61 +262,37 @@ split_after_n :: proc(s, sep: []byte, n: int, allocator := context.allocator) ->
@private
_split_iterator :: proc(s: ^[]byte, sep: []byte, sep_save, n: int) -> (res: []byte, ok: bool) {
s, n := s, n
if n == 0 {
return
}
if sep == nil {
_split_iterator :: proc(s: ^[]byte, sep: []byte, sep_save: int) -> (res: []byte, ok: bool) {
if len(sep) == 0 {
res = s[:]
ok = true
s^ = s[len(s):]
return
}
if n < 0 {
n = count(s^, sep) + 1
}
n -= 1
i := 0
for ; i < n; i += 1 {
m := index(s^, sep)
if m < 0 {
break
}
m := index(s^, sep)
if m < 0 {
// not found
res = s[:]
ok = len(res) != 0
s^ = s[len(s):]
} else {
res = s[:m+sep_save]
ok = true
s^ = s[m+len(sep):]
return
}
res = s[:]
ok = res != nil
s^ = s[len(s):]
return
}
split_iterator :: proc(s: ^[]byte, sep: []byte) -> ([]byte, bool) {
return _split_iterator(s, sep, 0, -1)
}
split_n_iterator :: proc(s: ^[]byte, sep: []byte, n: int) -> ([]byte, bool) {
return _split_iterator(s, sep, 0, n)
return _split_iterator(s, sep, 0)
}
split_after_iterator :: proc(s: ^[]byte, sep: []byte) -> ([]byte, bool) {
return _split_iterator(s, sep, len(sep), -1)
return _split_iterator(s, sep, len(sep))
}
split_after_n_iterator :: proc(s: ^[]byte, sep: []byte, n: int) -> ([]byte, bool) {
return _split_iterator(s, sep, len(sep), n)
}
index_byte :: proc(s: []byte, c: byte) -> int {
for i := 0; i < len(s); i += 1 {
+4 -4
View File
@@ -7,20 +7,20 @@ char :: builtin.u8 // assuming -funsigned-char
schar :: builtin.i8
short :: builtin.i16
int :: builtin.i32
long :: builtin.i32 when (ODIN_OS == "windows" || size_of(builtin.rawptr) == 4) else builtin.i64
long :: builtin.i32 when (ODIN_OS == .Windows || size_of(builtin.rawptr) == 4) else builtin.i64
longlong :: builtin.i64
uchar :: builtin.u8
ushort :: builtin.u16
uint :: builtin.u32
ulong :: builtin.u32 when (ODIN_OS == "windows" || size_of(builtin.rawptr) == 4) else builtin.u64
ulong :: builtin.u32 when (ODIN_OS == .Windows || size_of(builtin.rawptr) == 4) else builtin.u64
ulonglong :: builtin.u64
bool :: builtin.bool
size_t :: builtin.uint
ssize_t :: builtin.int
wchar_t :: builtin.u16 when (ODIN_OS == "windows") else builtin.u32
wchar_t :: builtin.u16 when (ODIN_OS == .Windows) else builtin.u32
float :: builtin.f32
double :: builtin.f64
@@ -48,7 +48,7 @@ int_least64_t :: builtin.i64
uint_least64_t :: builtin.u64
// Same on Windows, Linux, and FreeBSD
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
int_fast8_t :: builtin.i8
uint_fast8_t :: builtin.u8
int_fast16_t :: builtin.i32
+1 -1
View File
@@ -1276,7 +1276,7 @@ preprocess_internal :: proc(cpp: ^Preprocessor, tok: ^Token) -> ^Token {
if start.file != nil {
dir = filepath.dir(start.file.name)
}
path := filepath.join(dir, filename)
path := filepath.join({dir, filename})
if os.exists(path) {
tok = include_file(cpp, tok, path, start.next.next)
continue
+2 -2
View File
@@ -2,9 +2,9 @@ package libc
// 7.3 Complex arithmetic
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
+2 -2
View File
@@ -1,8 +1,8 @@
package libc
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
+18 -5
View File
@@ -2,9 +2,9 @@ package libc
// 7.5 Errors
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
@@ -14,7 +14,7 @@ when ODIN_OS == "windows" {
// EDOM,
// EILSEQ
// ERANGE
when ODIN_OS == "linux" || ODIN_OS == "freebsd" {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@@ -27,7 +27,20 @@ when ODIN_OS == "linux" || ODIN_OS == "freebsd" {
ERANGE :: 34
}
when ODIN_OS == "windows" {
when ODIN_OS == .OpenBSD {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@(link_name="__errno")
_get_errno :: proc() -> ^int ---
}
EDOM :: 33
EILSEQ :: 84
ERANGE :: 34
}
when ODIN_OS == .Windows {
@(private="file")
@(default_calling_convention="c")
foreign libc {
@@ -40,7 +53,7 @@ when ODIN_OS == "windows" {
ERANGE :: 34
}
when ODIN_OS == "darwin" {
when ODIN_OS == .Darwin {
@(private="file")
@(default_calling_convention="c")
foreign libc {
+12 -12
View File
@@ -4,9 +4,9 @@ package libc
import "core:intrinsics"
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
@@ -211,19 +211,19 @@ _signbitf :: #force_inline proc(x: float) -> int {
return int(transmute(uint32_t)x >> 31)
}
isfinite :: #force_inline proc(x: $T) where intrinsics.type_is_float(T) {
isfinite :: #force_inline proc(x: $T) -> bool where intrinsics.type_is_float(T) {
return fpclassify(x) == FP_INFINITE
}
isinf :: #force_inline proc(x: $T) where intrinsics.type_is_float(T) {
isinf :: #force_inline proc(x: $T) -> bool where intrinsics.type_is_float(T) {
return fpclassify(x) > FP_INFINITE
}
isnan :: #force_inline proc(x: $T) where intrinsics.type_is_float(T) {
isnan :: #force_inline proc(x: $T) -> bool where intrinsics.type_is_float(T) {
return fpclassify(x) == FP_NAN
}
isnormal :: #force_inline proc(x: $T) where intrinsics.type_is_float(T) {
isnormal :: #force_inline proc(x: $T) -> bool where intrinsics.type_is_float(T) {
return fpclassify(x) == FP_NORMAL
}
@@ -231,27 +231,27 @@ isnormal :: #force_inline proc(x: $T) where intrinsics.type_is_float(T) {
// implemented as the relational comparisons, as that would produce an invalid
// "sticky" state that propagates and affects maths results. These need
// to be implemented natively in Odin assuming isunordered to prevent that.
isgreater :: #force_inline proc(x, y: $T) where intrinsics.type_is_float(T) {
isgreater :: #force_inline proc(x, y: $T) -> bool where intrinsics.type_is_float(T) {
return !isunordered(x, y) && x > y
}
isgreaterequal :: #force_inline proc(x, y: $T) where intrinsics.type_is_float(T) {
isgreaterequal :: #force_inline proc(x, y: $T) -> bool where intrinsics.type_is_float(T) {
return !isunordered(x, y) && x >= y
}
isless :: #force_inline proc(x, y: $T) where intrinsics.type_is_float(T) {
isless :: #force_inline proc(x, y: $T) -> bool where intrinsics.type_is_float(T) {
return !isunordered(x, y) && x < y
}
islessequal :: #force_inline proc(x, y: $T) where intrinsics.type_is_float(T) {
islessequal :: #force_inline proc(x, y: $T) -> bool where intrinsics.type_is_float(T) {
return !isunordered(x, y) && x <= y
}
islessgreater :: #force_inline proc(x, y: $T) where intrinsics.type_is_float(T) {
islessgreater :: #force_inline proc(x, y: $T) -> bool where intrinsics.type_is_float(T) {
return !isunordered(x, y) && x <= y
}
isunordered :: #force_inline proc(x, y: $T) where intrinsics.type_is_float(T) {
isunordered :: #force_inline proc(x, y: $T) -> bool where intrinsics.type_is_float(T) {
if isnan(x) {
// Force evaluation of y to propagate exceptions for ordering semantics.
// To ensure correct semantics of IEEE 754 this cannot be compiled away.
+3 -3
View File
@@ -2,14 +2,14 @@ package libc
// 7.13 Nonlocal jumps
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
}
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
@(default_calling_convention="c")
foreign libc {
// 7.13.1 Save calling environment
+5 -5
View File
@@ -2,9 +2,9 @@ package libc
// 7.14 Signal handling
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
@@ -21,7 +21,7 @@ foreign libc {
raise :: proc(sig: int) -> int ---
}
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
SIG_ERR :: rawptr(~uintptr(0))
SIG_DFL :: rawptr(uintptr(0))
SIG_IGN :: rawptr(uintptr(1))
@@ -34,7 +34,7 @@ when ODIN_OS == "windows" {
SIGTERM :: 15
}
when ODIN_OS == "linux" || ODIN_OS == "freebsd" {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD {
SIG_ERR :: rawptr(~uintptr(0))
SIG_DFL :: rawptr(uintptr(0))
SIG_IGN :: rawptr(uintptr(1))
@@ -47,7 +47,7 @@ when ODIN_OS == "linux" || ODIN_OS == "freebsd" {
SIGTERM :: 15
}
when ODIN_OS == "darwin" {
when ODIN_OS == .Darwin {
SIG_ERR :: rawptr(~uintptr(0))
SIG_DFL :: rawptr(uintptr(0))
SIG_IGN :: rawptr(uintptr(1))
+111 -146
View File
@@ -47,29 +47,30 @@ kill_dependency :: #force_inline proc(value: $T) -> T {
// 7.17.4 Fences
atomic_thread_fence :: #force_inline proc(order: memory_order) {
switch (order) {
case .relaxed:
return
case .consume:
intrinsics.atomic_fence_acq()
case .acquire:
intrinsics.atomic_fence_acq()
case .release:
intrinsics.atomic_fence_rel()
case .acq_rel:
intrinsics.atomic_fence_acqrel()
case .seq_cst:
intrinsics.atomic_fence_acqrel()
assert(order != .relaxed)
assert(order != .consume)
#partial switch order {
case .acquire: intrinsics.atomic_thread_fence(.Acquire)
case .release: intrinsics.atomic_thread_fence(.Release)
case .acq_rel: intrinsics.atomic_thread_fence(.Acq_Rel)
case .seq_cst: intrinsics.atomic_thread_fence(.Seq_Cst)
}
}
atomic_signal_fence :: #force_inline proc(order: memory_order) {
atomic_thread_fence(order)
assert(order != .relaxed)
assert(order != .consume)
#partial switch order {
case .acquire: intrinsics.atomic_signal_fence(.Acquire)
case .release: intrinsics.atomic_signal_fence(.Release)
case .acq_rel: intrinsics.atomic_signal_fence(.Acq_Rel)
case .seq_cst: intrinsics.atomic_signal_fence(.Seq_Cst)
}
}
// 7.17.5 Lock-free property
atomic_is_lock_free :: #force_inline proc(obj: ^$T) -> bool {
return size_of(T) <= 8 && (intrinsics.type_is_integer(T) || intrinsics.type_is_pointer(T))
return intrinsics.atomic_type_is_lock_free(T)
}
// 7.17.6 Atomic integer types
@@ -121,13 +122,10 @@ atomic_store_explicit :: #force_inline proc(object: ^$T, desired: T, order: memo
assert(order != .acquire)
assert(order != .acq_rel)
#partial switch (order) {
case .relaxed:
intrinsics.atomic_store_relaxed(object, desired)
case .release:
intrinsics.atomic_store_rel(object, desired)
case .seq_cst:
intrinsics.atomic_store(object, desired)
#partial switch order {
case .relaxed: intrinsics.atomic_store_explicit(object, desired, .Relaxed)
case .release: intrinsics.atomic_store_explicit(object, desired, .Release)
case .seq_cst: intrinsics.atomic_store_explicit(object, desired, .Seq_Cst)
}
}
@@ -139,36 +137,26 @@ atomic_load_explicit :: #force_inline proc(object: ^$T, order: memory_order) {
assert(order != .release)
assert(order != .acq_rel)
#partial switch (order) {
case .relaxed:
return intrinsics.atomic_load_relaxed(object)
case .consume:
return intrinsics.atomic_load_acq(object)
case .acquire:
return intrinsics.atomic_load_acq(object)
case .seq_cst:
return intrinsics.atomic_load(object)
#partial switch order {
case .relaxed: return intrinsics.atomic_load_explicit(object, .Relaxed)
case .consume: return intrinsics.atomic_load_explicit(object, .Consume)
case .acquire: return intrinsics.atomic_load_explicit(object, .Acquire)
case .seq_cst: return intrinsics.atomic_load_explicit(object, .Seq_Cst)
}
}
atomic_exchange :: #force_inline proc(object: ^$T, desired: T) -> T {
return intrinsics.atomic_xchg(object, desired)
return intrinsics.atomic_exchange(object, desired)
}
atomic_exchange_explicit :: #force_inline proc(object: ^$T, desired: T, order: memory_order) -> T {
switch (order) {
case .relaxed:
return intrinsics.atomic_xchg_relaxed(object, desired)
case .consume:
return intrinsics.atomic_xchg_acq(object, desired)
case .acquire:
return intrinsics.atomic_xchg_acq(object, desired)
case .release:
return intrinsics.atomic_xchg_rel(object, desired)
case .acq_rel:
return intrinsics.atomic_xchg_acqrel(object, desired)
case .seq_cst:
return intrinsics.atomic_xchg(object, desired)
switch order {
case .relaxed: return intrinsics.atomic_exchange_explicit(object, desired, .Relaxed)
case .consume: return intrinsics.atomic_exchange_explicit(object, desired, .Consume)
case .acquire: return intrinsics.atomic_exchange_explicit(object, desired, .Acquire)
case .release: return intrinsics.atomic_exchange_explicit(object, desired, .Release)
case .acq_rel: return intrinsics.atomic_exchange_explicit(object, desired, .Acq_Rel)
case .seq_cst: return intrinsics.atomic_exchange_explicit(object, desired, .Seq_Cst)
}
return false
}
@@ -189,102 +177,104 @@ atomic_exchange_explicit :: #force_inline proc(object: ^$T, desired: T, order: m
// [success = seq_cst, failure = acquire] => failacq
// [success = acquire, failure = relaxed] => acq_failrelaxed
// [success = acq_rel, failure = relaxed] => acqrel_failrelaxed
atomic_compare_exchange_strong :: #force_inline proc(object, expected: ^$T, desired: T) {
value, ok := intrinsics.atomic_cxchg(object, expected^, desired)
atomic_compare_exchange_strong :: #force_inline proc(object, expected: ^$T, desired: T) -> bool {
value, ok := intrinsics.atomic_compare_exchange_strong(object, expected^, desired)
if !ok { expected^ = value }
return ok
}
atomic_compare_exchange_strong_explicit :: #force_inline proc(object, expected: ^$T, desired: T, success, failure: memory_order) {
atomic_compare_exchange_strong_explicit :: #force_inline proc(object, expected: ^$T, desired: T, success, failure: memory_order) -> bool {
assert(failure != .release)
assert(failure != .acq_rel)
value: T; ok: bool
#partial switch (failure) {
#partial switch failure {
case .seq_cst:
assert(success != .relaxed)
#partial switch (success) {
#partial switch success {
case .seq_cst:
value, ok := intrinsics.atomic_cxchg(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Seq_Cst)
case .acquire:
value, ok := intrinsics.atomic_cxchg_acq(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acquire, .Seq_Cst)
case .consume:
value, ok := intrinsics.atomic_cxchg_acq(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Consume, .Seq_Cst)
case .release:
value, ok := intrinsics.atomic_cxchg_rel(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Release, .Seq_Cst)
case .acq_rel:
value, ok := intrinsics.atomic_cxchg_acqrel(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acq_Rel, .Seq_Cst)
}
case .relaxed:
assert(success != .release)
#partial switch (success) {
#partial switch success {
case .relaxed:
value, ok := intrinsics.atomic_cxchg_relaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Relaxed, .Relaxed)
case .seq_cst:
value, ok := intrinsics.atomic_cxchg_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Relaxed)
case .acquire:
value, ok := intrinsics.atomic_cxchg_acq_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acquire, .Relaxed)
case .consume:
value, ok := intrinsics.atomic_cxchg_acq_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Consume, .Relaxed)
case .acq_rel:
value, ok := intrinsics.atomic_cxchg_acqrel_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Acq_Rel, .Relaxed)
}
case .consume:
fallthrough
assert(success == .seq_cst)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Consume)
case .acquire:
assert(success == .seq_cst)
value, ok := intrinsics.atomic_cxchg_failacq(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_strong_explicit(object, expected^, desired, .Seq_Cst, .Acquire)
}
if !ok { expected^ = value }
return ok
}
atomic_compare_exchange_weak :: #force_inline proc(object, expected: ^$T, desired: T) {
value, ok := intrinsics.atomic_cxchgweak(object, expected^, desired)
atomic_compare_exchange_weak :: #force_inline proc(object, expected: ^$T, desired: T) -> bool {
value, ok := intrinsics.atomic_compare_exchange_weak(object, expected^, desired)
if !ok { expected^ = value }
return ok
}
atomic_compare_exchange_weak_explicit :: #force_inline proc(object, expected: ^$T, desited: T, success, failure: memory_order) {
atomic_compare_exchange_weak_explicit :: #force_inline proc(object, expected: ^$T, desited: T, success, failure: memory_order) -> bool {
assert(failure != .release)
assert(failure != .acq_rel)
value: T; ok: bool
#partial switch (failure) {
#partial switch failure {
case .seq_cst:
assert(success != .relaxed)
#partial switch (success) {
#partial switch success {
case .seq_cst:
value, ok := intrinsics.atomic_cxchgweak(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Seq_Cst)
case .acquire:
value, ok := intrinsics.atomic_cxchgweak_acq(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acquire, .Seq_Cst)
case .consume:
value, ok := intrinsics.atomic_cxchgweak_acq(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Consume, .Seq_Cst)
case .release:
value, ok := intrinsics.atomic_cxchgweak_rel(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Release, .Seq_Cst)
case .acq_rel:
value, ok := intrinsics.atomic_cxchgweak_acqrel(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acq_Rel, .Seq_Cst)
}
case .relaxed:
assert(success != .release)
#partial switch (success) {
#partial switch success {
case .relaxed:
value, ok := intrinsics.atomic_cxchgweak_relaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Relaxed, .Relaxed)
case .seq_cst:
value, ok := intrinsics.atomic_cxchgweak_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Relaxed)
case .acquire:
value, ok := intrinsics.atomic_cxchgweak_acq_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acquire, .Relaxed)
case .consume:
value, ok := intrinsics.atomic_cxchgweak_acq_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Consume, .Relaxed)
case .acq_rel:
value, ok := intrinsics.atomic_cxchgweak_acqrel_failrelaxed(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Acq_Rel, .Relaxed)
}
case .consume:
fallthrough
assert(success == .seq_cst)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Consume)
case .acquire:
assert(success == .seq_cst)
value, ok := intrinsics.atomic_cxchgweak_failacq(object, expected^, desired)
value, ok = intrinsics.atomic_compare_exchange_weak_explicit(object, expected^, desired, .Seq_Cst, .Acquire)
}
if !ok { expected^ = value }
@@ -297,19 +287,14 @@ atomic_fetch_add :: #force_inline proc(object: ^$T, operand: T) -> T {
}
atomic_fetch_add_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T {
switch (order) {
case .relaxed:
return intrinsics.atomic_add_relaxed(object, operand)
case .consume:
return intrinsics.atomic_add_acq(object, operand)
case .acquire:
return intrinsics.atomic_add_acq(object, operand)
case .release:
return intrinsics.atomic_add_rel(object, operand)
case .acq_rel:
return intrinsics.atomic_add_acqrel(object, operand)
case .seq_cst:
return intrinsics.atomic_add(object, operand)
switch order {
case .relaxed: return intrinsics.atomic_add_explicit(object, operand, .Relaxed)
case .consume: return intrinsics.atomic_add_explicit(object, operand, .Consume)
case .acquire: return intrinsics.atomic_add_explicit(object, operand, .Acquire)
case .release: return intrinsics.atomic_add_explicit(object, operand, .Release)
case .acq_rel: return intrinsics.atomic_add_explicit(object, operand, .Acq_Rel)
case: fallthrough
case .seq_cst: return intrinsics.atomic_add_explicit(object, operand, .Seq_Cst)
}
}
@@ -318,19 +303,14 @@ atomic_fetch_sub :: #force_inline proc(object: ^$T, operand: T) -> T {
}
atomic_fetch_sub_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T {
switch (order) {
case .relaxed:
return intrinsics.atomic_sub_relaxed(object, operand)
case .consume:
return intrinsics.atomic_sub_acq(object, operand)
case .acquire:
return intrinsics.atomic_sub_acq(object, operand)
case .release:
return intrinsics.atomic_sub_rel(object, operand)
case .acq_rel:
return intrinsics.atomic_sub_acqrel(object, operand)
case .seq_cst:
return intrinsics.atomic_sub(object, operand)
switch order {
case .relaxed: return intrinsics.atomic_sub_explicit(object, operand, .Relaxed)
case .consume: return intrinsics.atomic_sub_explicit(object, operand, .Consume)
case .acquire: return intrinsics.atomic_sub_explicit(object, operand, .Acquire)
case .release: return intrinsics.atomic_sub_explicit(object, operand, .Release)
case .acq_rel: return intrinsics.atomic_sub_explicit(object, operand, .Acq_Rel)
case: fallthrough
case .seq_cst: return intrinsics.atomic_sub_explicit(object, operand, .Seq_Cst)
}
}
@@ -339,19 +319,14 @@ atomic_fetch_or :: #force_inline proc(object: ^$T, operand: T) -> T {
}
atomic_fetch_or_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T {
switch (order) {
case .relaxed:
return intrinsics.atomic_or_relaxed(object, operand)
case .consume:
return intrinsics.atomic_or_acq(object, operand)
case .acquire:
return intrinsics.atomic_or_acq(object, operand)
case .release:
return intrinsics.atomic_or_rel(object, operand)
case .acq_rel:
return intrinsics.atomic_or_acqrel(object, operand)
case .seq_cst:
return intrinsics.atomic_or(object, operand)
switch order {
case .relaxed: return intrinsics.atomic_or_explicit(object, operand, .Relaxed)
case .consume: return intrinsics.atomic_or_explicit(object, operand, .Consume)
case .acquire: return intrinsics.atomic_or_explicit(object, operand, .Acquire)
case .release: return intrinsics.atomic_or_explicit(object, operand, .Release)
case .acq_rel: return intrinsics.atomic_or_explicit(object, operand, .Acq_Rel)
case: fallthrough
case .seq_cst: return intrinsics.atomic_or_explicit(object, operand, .Seq_Cst)
}
}
@@ -360,19 +335,14 @@ atomic_fetch_xor :: #force_inline proc(object: ^$T, operand: T) -> T {
}
atomic_fetch_xor_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T {
switch (order) {
case .relaxed:
return intrinsics.atomic_xor_relaxed(object, operand)
case .consume:
return intrinsics.atomic_xor_acq(object, operand)
case .acquire:
return intrinsics.atomic_xor_acq(object, operand)
case .release:
return intrinsics.atomic_xor_rel(object, operand)
case .acq_rel:
return intrinsics.atomic_xor_acqrel(object, operand)
case .seq_cst:
return intrinsics.atomic_xor(object, operand)
switch order {
case .relaxed: return intrinsics.atomic_xor_explicit(object, operand, .Relaxed)
case .consume: return intrinsics.atomic_xor_explicit(object, operand, .Consume)
case .acquire: return intrinsics.atomic_xor_explicit(object, operand, .Acquire)
case .release: return intrinsics.atomic_xor_explicit(object, operand, .Release)
case .acq_rel: return intrinsics.atomic_xor_explicit(object, operand, .Acq_Rel)
case: fallthrough
case .seq_cst: return intrinsics.atomic_xor_explicit(object, operand, .Seq_Cst)
}
}
@@ -380,19 +350,14 @@ atomic_fetch_and :: #force_inline proc(object: ^$T, operand: T) -> T {
return intrinsics.atomic_and(object, operand)
}
atomic_fetch_and_explicit :: #force_inline proc(object: ^$T, operand: T, order: memory_order) -> T {
switch (order) {
case .relaxed:
return intrinsics.atomic_and_relaxed(object, operand)
case .consume:
return intrinsics.atomic_and_acq(object, operand)
case .acquire:
return intrinsics.atomic_and_acq(object, operand)
case .release:
return intrinsics.atomic_and_rel(object, operand)
case .acq_rel:
return intrinsics.atomic_and_acqrel(object, operand)
case .seq_cst:
return intrinsics.atomic_and(object, operand)
switch order {
case .relaxed: return intrinsics.atomic_and_explicit(object, operand, .Relaxed)
case .consume: return intrinsics.atomic_and_explicit(object, operand, .Consume)
case .acquire: return intrinsics.atomic_and_explicit(object, operand, .Acquire)
case .release: return intrinsics.atomic_and_explicit(object, operand, .Release)
case .acq_rel: return intrinsics.atomic_and_explicit(object, operand, .Acq_Rel)
case: fallthrough
case .seq_cst: return intrinsics.atomic_and_explicit(object, operand, .Seq_Cst)
}
}
+55 -5
View File
@@ -1,8 +1,8 @@
package libc
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
@@ -13,7 +13,7 @@ when ODIN_OS == "windows" {
FILE :: struct {}
// MSVCRT compatible.
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
_IOFBF :: 0x0000
_IONBF :: 0x0004
_IOLBF :: 0x0040
@@ -48,7 +48,7 @@ when ODIN_OS == "windows" {
}
// GLIBC and MUSL compatible.
when ODIN_OS == "linux" {
when ODIN_OS == .Linux {
fpos_t :: struct #raw_union { _: [16]char, _: longlong, _: double, }
_IOFBF :: 0
@@ -78,7 +78,57 @@ when ODIN_OS == "linux" {
}
}
when ODIN_OS == "darwin" {
when ODIN_OS == .OpenBSD {
fpos_t :: distinct i64
_IOFBF :: 0
_IOLBF :: 1
_IONBF :: 1
BUFSIZ :: 1024
EOF :: int(-1)
FOPEN_MAX :: 20
FILENAME_MAX :: 1024
SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
foreign libc {
stderr: ^FILE
stdin: ^FILE
stdout: ^FILE
}
}
when ODIN_OS == .FreeBSD {
fpos_t :: distinct i64
_IOFBF :: 0
_IOLBF :: 1
_IONBF :: 1
BUFSIZ :: 1024
EOF :: int(-1)
FOPEN_MAX :: 20
FILENAME_MAX :: 1024
SEEK_SET :: 0
SEEK_CUR :: 1
SEEK_END :: 2
foreign libc {
stderr: ^FILE
stdin: ^FILE
stdout: ^FILE
}
}
when ODIN_OS == .Darwin {
fpos_t :: distinct i64
_IOFBF :: 0
+5 -5
View File
@@ -2,15 +2,15 @@ package libc
// 7.22 General utilities
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
}
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
RAND_MAX :: 0x7fff
@(private="file")
@@ -24,7 +24,7 @@ when ODIN_OS == "windows" {
}
}
when ODIN_OS == "linux" {
when ODIN_OS == .Linux {
RAND_MAX :: 0x7fffffff
// GLIBC and MUSL only
@@ -40,7 +40,7 @@ when ODIN_OS == "linux" {
}
when ODIN_OS == "darwin" {
when ODIN_OS == .Darwin {
RAND_MAX :: 0x7fffffff
// GLIBC and MUSL only
+2 -2
View File
@@ -4,9 +4,9 @@ import "core:runtime"
// 7.24 String handling
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
+5 -5
View File
@@ -5,10 +5,10 @@ package libc
thrd_start_t :: proc "c" (rawptr) -> int
tss_dtor_t :: proc "c" (rawptr)
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc {
"system:libucrt.lib",
"system:msvcprt.lib"
"system:msvcprt.lib",
}
thrd_success :: 0 // _Thrd_success
@@ -74,10 +74,10 @@ when ODIN_OS == "windows" {
}
// GLIBC and MUSL compatible constants and types.
when ODIN_OS == "linux" {
when ODIN_OS == .Linux {
foreign import libc {
"system:c",
"system:pthread"
"system:pthread",
}
thrd_success :: 0
@@ -138,6 +138,6 @@ when ODIN_OS == "linux" {
}
when ODIN_OS == "darwin" {
when ODIN_OS == .Darwin {
// TODO: find out what this is meant to be!
}
+10 -5
View File
@@ -2,9 +2,9 @@ package libc
// 7.27 Date and time
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
@@ -12,7 +12,7 @@ when ODIN_OS == "windows" {
// We enforce 64-bit time_t and timespec as there is no reason to use 32-bit as
// we approach the 2038 problem. Windows has defaulted to this since VC8 (2005).
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign libc {
// 7.27.2 Time manipulation functions
clock :: proc() -> clock_t ---
@@ -45,7 +45,7 @@ when ODIN_OS == "windows" {
}
}
when ODIN_OS == "linux" || ODIN_OS == "freebsd" || ODIN_OS == "darwin" {
when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
@(default_calling_convention="c")
foreign libc {
// 7.27.2 Time manipulation functions
@@ -63,7 +63,12 @@ when ODIN_OS == "linux" || ODIN_OS == "freebsd" || ODIN_OS == "darwin" {
strftime :: proc(s: [^]char, maxsize: size_t, format: cstring, timeptr: ^tm) -> size_t ---
}
CLOCKS_PER_SEC :: 1000000
when ODIN_OS == .OpenBSD {
CLOCKS_PER_SEC :: 100
} else {
CLOCKS_PER_SEC :: 1000000
}
TIME_UTC :: 1
time_t :: distinct i64
+2 -2
View File
@@ -2,9 +2,9 @@ package libc
// 7.28 Unicode utilities
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
+2 -2
View File
@@ -2,9 +2,9 @@ package libc
// 7.29 Extended multibyte and wide character utilities
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
+14 -7
View File
@@ -2,27 +2,34 @@ package libc
// 7.30 Wide character classification and mapping utilities
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib"
} else when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework"
} else {
foreign import libc "system:c"
}
when ODIN_OS == "windows" {
when ODIN_OS == .Windows {
wctrans_t :: distinct wchar_t
wctype_t :: distinct ushort
}
when ODIN_OS == "linux" {
} else when ODIN_OS == .Linux {
wctrans_t :: distinct intptr_t
wctype_t :: distinct ulong
}
when ODIN_OS == "darwin" {
} else when ODIN_OS == .Darwin {
wctrans_t :: distinct int
wctype_t :: distinct u32
} else when ODIN_OS == .OpenBSD {
wctrans_t :: distinct rawptr
wctype_t :: distinct rawptr
} else when ODIN_OS == .FreeBSD {
wctrans_t :: distinct int
wctype_t :: distinct ulong
}
@(default_calling_convention="c")
+13 -6
View File
@@ -47,7 +47,7 @@ when size_of(uintptr) == 8 {
}
Error :: union {
Error :: union #shared_nil {
General_Error,
Deflate_Error,
ZLIB_Error,
@@ -58,6 +58,7 @@ Error :: union {
}
General_Error :: enum {
None = 0,
File_Not_Found,
Cannot_Open_File,
File_Too_Short,
@@ -76,6 +77,7 @@ General_Error :: enum {
}
GZIP_Error :: enum {
None = 0,
Invalid_GZIP_Signature,
Reserved_Flag_Set,
Invalid_Extra_Data,
@@ -100,6 +102,7 @@ GZIP_Error :: enum {
}
ZIP_Error :: enum {
None = 0,
Invalid_ZIP_File_Signature,
Unexpected_Signature,
Insert_Next_Disk,
@@ -107,6 +110,7 @@ ZIP_Error :: enum {
}
ZLIB_Error :: enum {
None = 0,
Unsupported_Window_Size,
FDICT_Unsupported,
Unsupported_Compression_Level,
@@ -114,6 +118,7 @@ ZLIB_Error :: enum {
}
Deflate_Error :: enum {
None = 0,
Huffman_Bad_Sizes,
Huffman_Bad_Code_Lengths,
Inflate_Error,
@@ -123,7 +128,6 @@ Deflate_Error :: enum {
BType_3,
}
// General I/O context for ZLIB, LZW, etc.
Context_Memory_Input :: struct #packed {
input_data: []u8,
@@ -139,7 +143,12 @@ Context_Memory_Input :: struct #packed {
size_packed: i64,
size_unpacked: i64,
}
#assert(size_of(Context_Memory_Input) == 64)
when size_of(rawptr) == 8 {
#assert(size_of(Context_Memory_Input) == 64)
} else {
// e.g. `-target:windows_i386`
#assert(size_of(Context_Memory_Input) == 52)
}
Context_Stream_Input :: struct #packed {
input_data: []u8,
@@ -174,8 +183,6 @@ Context_Stream_Input :: struct #packed {
This simplifies end-of-stream handling where bits may be left in the bit buffer.
*/
// TODO: Make these return compress.Error errors.
input_size_from_memory :: proc(z: ^Context_Memory_Input) -> (res: i64, err: Error) {
return i64(len(z.input_data)), nil
}
@@ -473,4 +480,4 @@ discard_to_next_byte_lsb_from_stream :: proc(z: ^Context_Stream_Input) {
consume_bits_lsb(z, discard)
}
discard_to_next_byte_lsb :: proc{discard_to_next_byte_lsb_from_memory, discard_to_next_byte_lsb_from_stream};
discard_to_next_byte_lsb :: proc{discard_to_next_byte_lsb_from_memory, discard_to_next_byte_lsb_from_stream}
+1 -1
View File
@@ -45,7 +45,7 @@ main :: proc() {
if len(args) < 2 {
stderr("No input file specified.\n")
err := load(slice=TEST, buf=&buf, known_gzip_size=len(TEST))
err := load(data=TEST, buf=&buf, known_gzip_size=len(TEST))
if err == nil {
stdout("Displaying test vector: ")
stdout(bytes.buffer_to_string(&buf))
+8 -7
View File
@@ -66,7 +66,8 @@ OS :: enum u8 {
_Unknown = 14,
Unknown = 255,
}
OS_Name :: #partial [OS]string{
OS_Name :: #sparse[OS]string{
._Unknown = "",
.FAT = "FAT",
.Amiga = "Amiga",
.VMS = "VMS/OpenVMS",
@@ -99,9 +100,9 @@ E_GZIP :: compress.GZIP_Error
E_ZLIB :: compress.ZLIB_Error
E_Deflate :: compress.Deflate_Error
GZIP_MAX_PAYLOAD_SIZE :: int(max(u32le))
GZIP_MAX_PAYLOAD_SIZE :: i64(max(u32le))
load :: proc{load_from_slice, load_from_file, load_from_context}
load :: proc{load_from_bytes, load_from_file, load_from_context}
load_from_file :: proc(filename: string, buf: ^bytes.Buffer, expected_output_size := -1, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator
@@ -111,16 +112,16 @@ load_from_file :: proc(filename: string, buf: ^bytes.Buffer, expected_output_siz
err = E_General.File_Not_Found
if ok {
err = load_from_slice(data, buf, len(data), expected_output_size)
err = load_from_bytes(data, buf, len(data), expected_output_size)
}
return
}
load_from_slice :: proc(slice: []u8, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) {
load_from_bytes :: proc(data: []byte, buf: ^bytes.Buffer, known_gzip_size := -1, expected_output_size := -1, allocator := context.allocator) -> (err: Error) {
buf := buf
z := &compress.Context_Memory_Input{
input_data = slice,
input_data = data,
output = buf,
}
return load_from_context(z, buf, known_gzip_size, expected_output_size, allocator)
@@ -135,7 +136,7 @@ load_from_context :: proc(z: ^$C, buf: ^bytes.Buffer, known_gzip_size := -1, exp
z.output = buf
if expected_output_size > GZIP_MAX_PAYLOAD_SIZE {
if i64(expected_output_size) > i64(GZIP_MAX_PAYLOAD_SIZE) {
return E_GZIP.Payload_Size_Exceeds_Max_Payload
}
+148
View File
@@ -0,0 +1,148 @@
/*
This file was generated, so don't edit this by hand.
Transliterated from https://github.com/Ed-von-Schleck/shoco/blob/master/shoco_model.h,
which is an English word model.
*/
// package shoco is an implementation of the shoco short string compressor
package shoco
DEFAULT_MODEL :: Shoco_Model {
min_char = 39,
max_char = 122,
characters_by_id = {
'e', 'a', 'i', 'o', 't', 'h', 'n', 'r', 's', 'l', 'u', 'c', 'w', 'm', 'd', 'b', 'p', 'f', 'g', 'v', 'y', 'k', '-', 'H', 'M', 'T', '\'', 'B', 'x', 'I', 'W', 'L',
},
ids_by_character = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, 23, 29, -1, -1, 31, 24, -1, -1, -1, -1, -1, -1, 25, -1, -1, 30, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 15, 11, 14, 0, 17, 18, 5, 2, -1, 21, 9, 13, 6, 3, 16, -1, 7, 8, 4, 10, 19, 12, 28, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
},
successors_by_bigram = {
7, 4, 12, -1, 6, -1, 1, 0, 3, 5, -1, 9, -1, 8, 2, -1, 15, 14, -1, 10, 11, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1,
1, -1, 6, -1, 1, -1, 0, 3, 2, 4, 15, 11, -1, 9, 5, 10, 13, -1, 12, 8, 7, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
9, 11, -1, 4, 2, -1, 0, 8, 1, 5, -1, 6, -1, 3, 7, 15, -1, 12, 10, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 14, 7, 5, -1, 1, 2, 8, 9, 0, 15, 6, 4, 11, -1, 12, 3, -1, 10, -1, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2, 4, 3, 1, 5, 0, -1, 6, 10, 9, 7, 12, 11, -1, -1, -1, -1, 13, -1, -1, 8, -1, 15, -1, -1, -1, 14, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, -1, -1, 5, 9, 10, 6, -1, -1, 8, 15, 11, -1, 14, -1, -1, 7, -1, 13, -1, -1, -1, 12, -1, -1, -1, -1, -1,
2, 8, 7, 4, 3, -1, 9, -1, 6, 11, -1, 5, -1, -1, 0, -1, -1, 14, 1, 15, 10, 12, -1, -1, -1, -1, 13, -1, -1, -1, -1, -1,
0, 3, 1, 2, 6, -1, 9, 8, 4, 12, 13, 10, -1, 11, 7, -1, -1, 15, 14, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 6, 3, 4, 1, 2, -1, -1, 5, 10, 7, 9, 11, 12, -1, -1, 8, 14, -1, -1, 15, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 6, 2, 5, 9, -1, -1, -1, 10, 1, 8, -1, 12, 14, 4, -1, 15, 7, -1, 13, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
8, 10, 9, 15, 1, -1, 4, 0, 3, 2, -1, 6, -1, 12, 11, 13, 7, 14, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1, 3, 6, 0, 4, 2, -1, 7, 13, 8, 9, 11, -1, -1, 15, -1, -1, -1, -1, -1, 10, 5, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3, 0, 1, 4, -1, 2, 5, 6, 7, 8, -1, 14, -1, -1, 9, 15, -1, 12, -1, -1, -1, 10, 11, -1, -1, -1, 13, -1, -1, -1, -1, -1,
0, 1, 3, 2, 15, -1, 12, -1, 7, 14, 4, -1, -1, 9, -1, 8, 5, 10, -1, -1, 6, -1, 13, -1, -1, -1, 11, -1, -1, -1, -1, -1,
0, 3, 1, 2, -1, -1, 12, 6, 4, 9, 7, -1, -1, 14, 8, -1, -1, 15, 11, 13, 5, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 5, 7, 2, 10, 13, -1, 6, 8, 1, 3, -1, -1, 14, 15, 11, -1, -1, -1, 12, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 2, 6, 3, 7, 10, -1, 1, 9, 4, 8, -1, -1, 15, -1, 12, 5, -1, -1, -1, 11, -1, 13, -1, -1, -1, 14, -1, -1, -1, -1, -1,
1, 3, 4, 0, 7, -1, 12, 2, 11, 8, 6, 13, -1, -1, -1, -1, -1, 5, -1, -1, 10, 15, 9, -1, -1, -1, 14, -1, -1, -1, -1, -1,
1, 3, 5, 2, 13, 0, 9, 4, 7, 6, 8, -1, -1, 15, -1, 11, -1, -1, 10, -1, 14, -1, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 2, 1, 3, -1, -1, -1, 6, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1, 11, 4, 0, 3, -1, 13, 12, 2, 7, -1, -1, 15, 10, 5, 8, 14, -1, -1, -1, -1, -1, 9, -1, -1, -1, 6, -1, -1, -1, -1, -1,
0, 9, 2, 14, 15, 4, 1, 13, 3, 5, -1, -1, 10, -1, -1, -1, -1, 6, 12, -1, 7, -1, 8, -1, -1, -1, 11, -1, -1, -1, -1, -1,
-1, 2, 14, -1, 1, 5, 8, 7, 4, 12, -1, 6, 9, 11, 13, 3, 10, 15, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0, 1, 3, 2, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
4, 3, 1, 5, -1, -1, -1, 0, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2, 8, 4, 1, -1, 0, -1, 6, -1, -1, 5, -1, 7, -1, -1, -1, -1, -1, -1, -1, 10, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1,
12, 5, -1, -1, 1, -1, -1, 7, 0, 3, -1, 2, -1, 4, 6, -1, -1, -1, -1, 8, -1, -1, 15, -1, 13, 9, -1, -1, -1, -1, -1, 11,
1, 3, 2, 4, -1, -1, -1, 5, -1, 7, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, -1,
5, 3, 4, 12, 1, 6, -1, -1, -1, -1, 8, 2, -1, -1, -1, -1, 0, 9, -1, -1, 11, -1, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 0, -1, 1, 12, 3, -1, -1, -1, -1, 5, -1, -1, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 6, -1, 10,
2, 3, 1, 4, -1, 0, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1,
5, 1, 3, 0, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2, -1, -1, -1, -1, -1, 9, -1, -1, 6, -1, 7,
},
successors_reversed = {
's', 't', 'c', 'l', 'm', 'a', 'd', 'r', 'v', 'T', 'A', 'L', 'e', 'M', 'Y', '-',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'-', 't', 'a', 'b', 's', 'h', 'c', 'r', 'n', 'w', 'p', 'm', 'l', 'd', 'i', 'f',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'u', 'e', 'i', 'a', 'o', 'r', 'y', 'l', 'I', 'E', 'R', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'e', 'a', 'o', 'i', 'u', 'A', 'y', 'E', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
't', 'n', 'f', 's', '\'', 'm', 'I', 'N', 'A', 'E', 'L', 'Z', 'r', 'V', 'R', 'C',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'o', 'a', 'y', 'i', 'u', 'e', 'I', 'L', 'D', '\'', 'E', 'Y', '\x00', '\x00', '\x00', '\x00',
'r', 'i', 'y', 'a', 'e', 'o', 'u', 'Y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'h', 'o', 'e', 'E', 'i', 'u', 'r', 'w', 'a', 'H', 'y', 'R', 'Z', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'h', 'i', 'e', 'a', 'o', 'r', 'I', 'y', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'n', 't', 's', 'r', 'l', 'd', 'i', 'y', 'v', 'm', 'b', 'c', 'g', 'p', 'k', 'u',
'e', 'l', 'o', 'u', 'y', 'a', 'r', 'i', 's', 'j', 't', 'b', 'v', 'h', 'm', 'd',
'o', 'e', 'h', 'a', 't', 'k', 'i', 'r', 'l', 'u', 'y', 'c', 'q', 's', '-', 'd',
'e', 'i', 'o', 'a', 's', 'y', 'r', 'u', 'd', 'l', '-', 'g', 'n', 'v', 'm', 'f',
'r', 'n', 'd', 's', 'a', 'l', 't', 'e', 'm', 'c', 'v', 'y', 'i', 'x', 'f', 'p',
'o', 'e', 'r', 'a', 'i', 'f', 'u', 't', 'l', '-', 'y', 's', 'n', 'c', '\'', 'k',
'h', 'e', 'o', 'a', 'r', 'i', 'l', 's', 'u', 'n', 'g', 'b', '-', 't', 'y', 'm',
'e', 'a', 'i', 'o', 't', 'r', 'u', 'y', 'm', 's', 'l', 'b', '\'', '-', 'f', 'd',
'n', 's', 't', 'm', 'o', 'l', 'c', 'd', 'r', 'e', 'g', 'a', 'f', 'v', 'z', 'b',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'e', 'n', 'i', 's', 'h', 'l', 'f', 'y', '-', 'a', 'w', '\'', 'g', 'r', 'o', 't',
'e', 'l', 'i', 'y', 'd', 'o', 'a', 'f', 'u', 't', 's', 'k', 'w', 'v', 'm', 'p',
'e', 'a', 'o', 'i', 'u', 'p', 'y', 's', 'b', 'm', 'f', '\'', 'n', '-', 'l', 't',
'd', 'g', 'e', 't', 'o', 'c', 's', 'i', 'a', 'n', 'y', 'l', 'k', '\'', 'f', 'v',
'u', 'n', 'r', 'f', 'm', 't', 'w', 'o', 's', 'l', 'v', 'd', 'p', 'k', 'i', 'c',
'e', 'r', 'a', 'o', 'l', 'p', 'i', 't', 'u', 's', 'h', 'y', 'b', '-', '\'', 'm',
'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'e', 'i', 'o', 'a', 's', 'y', 't', 'd', 'r', 'n', 'c', 'm', 'l', 'u', 'g', 'f',
'e', 't', 'h', 'i', 'o', 's', 'a', 'u', 'p', 'c', 'l', 'w', 'm', 'k', 'f', 'y',
'h', 'o', 'e', 'i', 'a', 't', 'r', 'u', 'y', 'l', 's', 'w', 'c', 'f', '\'', '-',
'r', 't', 'l', 's', 'n', 'g', 'c', 'p', 'e', 'i', 'a', 'd', 'm', 'b', 'f', 'o',
'e', 'i', 'a', 'o', 'y', 'u', 'r', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00',
'a', 'i', 'h', 'e', 'o', 'n', 'r', 's', 'l', 'd', 'k', '-', 'f', '\'', 'c', 'b',
'p', 't', 'c', 'a', 'i', 'e', 'h', 'q', 'u', 'f', '-', 'y', 'o', '\x00', '\x00', '\x00',
'o', 'e', 's', 't', 'i', 'd', '\'', 'l', 'b', '-', 'm', 'a', 'r', 'n', 'p', 'w',
},
character_count = 32,
successor_count = 16,
max_successor_n = 7,
packs = {
{ 0x80000000, 1, 2, { 26, 24, 24, 24, 24, 24, 24, 24 }, { 15, 3, 0, 0, 0, 0, 0, 0 }, 0xc0, 0x80 },
{ 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 },
},
}
+318
View File
@@ -0,0 +1,318 @@
/*
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
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
import "core:intrinsics"
import "core:compress"
Shoco_Pack :: struct {
word: u32,
bytes_packed: i8,
bytes_unpacked: i8,
offsets: [8]u16,
masks: [8]i16,
header_mask: u8,
header: u8,
}
Shoco_Model :: struct {
min_char: u8,
max_char: u8,
characters_by_id: []u8,
ids_by_character: [256]i16,
successors_by_bigram: []i8,
successors_reversed: []u8,
character_count: u8,
successor_count: u8,
max_successor_n: i8,
packs: []Shoco_Pack,
}
compress_bound :: proc(uncompressed_size: int) -> (worst_case_compressed_size: int) {
// Worst case compression happens when input is non-ASCII (128-255)
// Encoded as 0x00 + the byte in question.
return uncompressed_size * 2
}
decompress_bound :: proc(compressed_size: int, model := DEFAULT_MODEL) -> (maximum_decompressed_size: int) {
// Best case compression is 2:1
most: f64
for pack in model.packs {
val := f64(compressed_size) / f64(pack.bytes_packed) * f64(pack.bytes_unpacked)
most = max(most, val)
}
return int(most)
}
find_best_encoding :: proc(indices: []i16, n_consecutive: i8, model := DEFAULT_MODEL) -> (res: int) {
for p := len(model.packs); p > 0; p -= 1 {
pack := model.packs[p - 1]
if n_consecutive >= pack.bytes_unpacked {
have_index := true
for i := 0; i < int(pack.bytes_unpacked); i += 1 {
if indices[i] > pack.masks[i] {
have_index = false
break
}
}
if have_index {
return p - 1
}
}
}
return -1
}
validate_model :: proc(model: Shoco_Model) -> (int, compress.Error) {
if len(model.characters_by_id) != int(model.character_count) {
return 0, .Unknown_Compression_Method
}
if len(model.successors_by_bigram) != int(model.character_count) * int(model.character_count) {
return 0, .Unknown_Compression_Method
}
if len(model.successors_reversed) != int(model.successor_count) * int(model.max_char - model.min_char) {
return 0, .Unknown_Compression_Method
}
// Model seems legit.
return 0, nil
}
// Decompresses into provided buffer.
decompress_slice_to_output_buffer :: proc(input: []u8, output: []u8, model := DEFAULT_MODEL) -> (size: int, err: compress.Error) {
inp, inp_end := 0, len(input)
out, out_end := 0, len(output)
validate_model(model) or_return
for inp < inp_end {
val := transmute(i8)input[inp]
mark := int(-1)
for val < 0 {
val <<= 1
mark += 1
}
if mark > len(model.packs) {
return out, .Unknown_Compression_Method
}
if mark < 0 {
if out >= out_end {
return out, .Output_Too_Short
}
// Ignore the sentinel value for non-ASCII chars
if input[inp] == 0x00 {
inp += 1
if inp >= inp_end {
return out, .Stream_Too_Short
}
}
output[out] = input[inp]
inp, out = inp + 1, out + 1
} else {
pack := model.packs[mark]
if out + int(pack.bytes_unpacked) > out_end {
return out, .Output_Too_Short
} else if inp + int(pack.bytes_packed) > inp_end {
return out, .Stream_Too_Short
}
code := intrinsics.unaligned_load((^u32)(&input[inp]))
when ODIN_ENDIAN == .Little {
code = intrinsics.byte_swap(code)
}
// Unpack the leading char
offset := pack.offsets[0]
mask := pack.masks[0]
last_chr := model.characters_by_id[(code >> offset) & u32(mask)]
output[out] = last_chr
// Unpack the successor chars
for i := 1; i < int(pack.bytes_unpacked); i += 1 {
offset = pack.offsets[i]
mask = pack.masks[i]
index_major := u32(last_chr - model.min_char) * u32(model.successor_count)
index_minor := (code >> offset) & u32(mask)
last_chr = model.successors_reversed[index_major + index_minor]
output[out + i] = last_chr
}
out += int(pack.bytes_unpacked)
inp += int(pack.bytes_packed)
}
}
return out, nil
}
decompress_slice_to_string :: proc(input: []u8, model := DEFAULT_MODEL, allocator := context.allocator) -> (res: string, err: compress.Error) {
context.allocator = allocator
if len(input) == 0 {
return "", .Stream_Too_Short
}
max_output_size := decompress_bound(len(input), model)
buf: [dynamic]u8
if !resize(&buf, max_output_size) {
return "", .Out_Of_Memory
}
length, result := decompress_slice_to_output_buffer(input, buf[:])
resize(&buf, length)
return string(buf[:]), result
}
decompress :: proc{decompress_slice_to_output_buffer, decompress_slice_to_string}
compress_string_to_buffer :: proc(input: string, output: []u8, model := DEFAULT_MODEL, allocator := context.allocator) -> (size: int, err: compress.Error) {
inp, inp_end := 0, len(input)
out, out_end := 0, len(output)
output := output
validate_model(model) or_return
indices := make([]i16, model.max_successor_n + 1)
defer delete(indices)
last_resort := false
encode: for inp < inp_end {
if last_resort {
last_resort = false
if input[inp] & 0x80 == 0x80 {
// Non-ASCII case
if out + 2 > out_end {
return out, .Output_Too_Short
}
// Put in a sentinel byte
output[out] = 0x00
out += 1
} else {
// An ASCII byte
if out + 1 > out_end {
return out, .Output_Too_Short
}
}
output[out] = input[inp]
out, inp = out + 1, inp + 1
} else {
// Find the longest string of known successors
indices[0] = model.ids_by_character[input[inp]]
last_chr_index := indices[0]
if last_chr_index < 0 {
last_resort = true
continue encode
}
rest := inp_end - inp
n_consecutive: i8 = 1
for ; n_consecutive <= model.max_successor_n; n_consecutive += 1 {
if inp_end > 0 && int(n_consecutive) == rest {
break
}
current_index := model.ids_by_character[input[inp + int(n_consecutive)]]
if current_index < 0 { // '\0' is always -1
break
}
successor_index := model.successors_by_bigram[last_chr_index * i16(model.character_count) + current_index]
if successor_index < 0 {
break
}
indices[n_consecutive] = i16(successor_index)
last_chr_index = current_index
}
if n_consecutive < 2 {
last_resort = true
continue encode
}
pack_n := find_best_encoding(indices, n_consecutive)
if pack_n >= 0 {
if out + int(model.packs[pack_n].bytes_packed) > out_end {
return out, .Output_Too_Short
}
pack := model.packs[pack_n]
code := pack.word
for i := 0; i < int(pack.bytes_unpacked); i += 1 {
code |= u32(indices[i]) << pack.offsets[i]
}
// In the little-endian world, we need to swap what's in the register to match the memory representation.
when ODIN_ENDIAN == .Little {
code = intrinsics.byte_swap(code)
}
out_ptr := raw_data(output[out:])
switch pack.bytes_packed {
case 4:
intrinsics.unaligned_store(transmute(^u32)out_ptr, code)
case 2:
intrinsics.unaligned_store(transmute(^u16)out_ptr, u16(code))
case 1:
intrinsics.unaligned_store(transmute(^u8)out_ptr, u8(code))
case:
return out, .Unknown_Compression_Method
}
out += int(pack.bytes_packed)
inp += int(pack.bytes_unpacked)
} else {
last_resort = true
continue encode
}
}
}
return out, nil
}
compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := context.allocator) -> (output: []u8, err: compress.Error) {
context.allocator = allocator
if len(input) == 0 {
return {}, .Stream_Too_Short
}
max_output_size := compress_bound(len(input))
buf: [dynamic]u8
if !resize(&buf, max_output_size) {
return {}, .Out_Of_Memory
}
length, result := compress_string_to_buffer(input, buf[:])
resize(&buf, length)
return buf[:length], result
}
compress :: proc{compress_string_to_buffer, compress_string}
+30 -30
View File
@@ -47,10 +47,10 @@ Options :: struct {
level: u8,
}
Error :: compress.Error
E_General :: compress.General_Error
E_ZLIB :: compress.ZLIB_Error
E_Deflate :: compress.Deflate_Error
Error :: compress.Error
General_Error :: compress.General_Error
ZLIB_Error :: compress.ZLIB_Error
Deflate_Error :: compress.Deflate_Error
DEFLATE_MAX_CHUNK_SIZE :: 65535
DEFLATE_MAX_LITERAL_SIZE :: 65535
@@ -258,7 +258,7 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
for i in 1 ..< HUFFMAN_MAX_BITS {
if sizes[i] > (1 << uint(i)) {
return E_Deflate.Huffman_Bad_Sizes
return .Huffman_Bad_Sizes
}
}
code := int(0)
@@ -270,7 +270,7 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
code = code + sizes[i]
if sizes[i] != 0 {
if code - 1 >= (1 << u16(i)) {
return E_Deflate.Huffman_Bad_Code_Lengths
return .Huffman_Bad_Code_Lengths
}
}
z.maxcode[i] = code << (HUFFMAN_MAX_BITS - uint(i))
@@ -314,15 +314,15 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro
s += 1
}
if s >= 16 {
return 0, E_Deflate.Bad_Huffman_Code
return 0, .Bad_Huffman_Code
}
// code size is s, so:
b := (k >> (16-s)) - int(t.firstcode[s]) + int(t.firstsymbol[s])
if b >= size_of(t.size) {
return 0, E_Deflate.Bad_Huffman_Code
return 0, .Bad_Huffman_Code
}
if t.size[b] != s {
return 0, E_Deflate.Bad_Huffman_Code
return 0, .Bad_Huffman_Code
}
compress.consume_bits_lsb(z, s)
@@ -335,11 +335,11 @@ decode_huffman_slowpath :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Erro
decode_huffman :: proc(z: ^$C, t: ^Huffman_Table) -> (r: u16, err: Error) #no_bounds_check {
if z.num_bits < 16 {
if z.num_bits > 63 {
return 0, E_ZLIB.Code_Buffer_Malformed
return 0, .Code_Buffer_Malformed
}
compress.refill_lsb(z)
if z.num_bits > 63 {
return 0, E_General.Stream_Too_Short
return 0, .Stream_Too_Short
}
}
#no_bounds_check b := t.fast[z.code_buffer & ZFAST_MASK]
@@ -361,7 +361,7 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err:
if value < 256 {
e := write_byte(z, u8(value))
if e != .None {
return E_General.Output_Too_Short
return .Output_Too_Short
}
} else {
if value == 256 {
@@ -377,7 +377,7 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err:
value, e = decode_huffman(z, z_offset)
if e != nil {
return E_Deflate.Bad_Huffman_Code
return .Bad_Huffman_Code
}
distance := Z_DIST_BASE[value]
@@ -387,7 +387,7 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err:
if z.bytes_written < i64(distance) {
// Distance is longer than we've decoded so far.
return E_Deflate.Bad_Distance
return .Bad_Distance
}
/*
@@ -405,14 +405,14 @@ parse_huffman_block :: proc(z: ^$C, z_repeat, z_offset: ^Huffman_Table) -> (err:
c := z.output.buf[z.bytes_written - i64(distance)]
e := repl_byte(z, length, c)
if e != .None {
return E_General.Output_Too_Short
return .Output_Too_Short
}
}
} else {
if length > 0 {
e := repl_bytes(z, length, distance)
if e != .None {
return E_General.Output_Too_Short
return .Output_Too_Short
}
}
}
@@ -432,25 +432,25 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
if !raw {
size, size_err := compress.input_size(ctx)
if size < 6 || size_err != nil {
return E_General.Stream_Too_Short
return .Stream_Too_Short
}
cmf, _ := compress.read_u8(ctx)
method := Compression_Method(cmf & 0xf)
if method != .DEFLATE {
return E_General.Unknown_Compression_Method
return .Unknown_Compression_Method
}
if cinfo := (cmf >> 4) & 0xf; cinfo > 7 {
return E_ZLIB.Unsupported_Window_Size
return .Unsupported_Window_Size
}
flg, _ := compress.read_u8(ctx)
fcheck := flg & 0x1f
fcheck_computed := (cmf << 8 | flg) & 0x1f
if fcheck != fcheck_computed {
return E_General.Checksum_Failed
return .Checksum_Failed
}
/*
@@ -458,7 +458,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
They're application specific and PNG doesn't use them.
*/
if fdict := (flg >> 5) & 1; fdict != 0 {
return E_ZLIB.FDICT_Unsupported
return .FDICT_Unsupported
}
// flevel := Compression_Level((flg >> 6) & 3);
@@ -485,7 +485,7 @@ inflate_from_context :: proc(using ctx: ^compress.Context_Memory_Input, raw := f
output_hash := hash.adler32(ctx.output.buf[:])
if output_hash != u32(adler) {
return E_General.Checksum_Failed
return .Checksum_Failed
}
}
return nil
@@ -555,7 +555,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
if ~uncompressed_len != length_check {
return E_Deflate.Len_Nlen_Mismatch
return .Len_Nlen_Mismatch
}
/*
@@ -571,7 +571,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
assert(uncompressed_len == 0)
case 3:
return E_Deflate.BType_3
return .BType_3
case:
// fmt.printf("Err: %v | Final: %v | Type: %v\n", err, final, type)
if type == 1 {
@@ -604,7 +604,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
c = decode_huffman(z, codelength_ht) or_return
if c < 0 || c >= 19 {
return E_Deflate.Huffman_Bad_Code_Lengths
return .Huffman_Bad_Code_Lengths
}
if c < 16 {
lencodes[n] = u8(c)
@@ -616,7 +616,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
case 16:
c = u16(compress.read_bits_no_refill_lsb(z, 2) + 3)
if n == 0 {
return E_Deflate.Huffman_Bad_Code_Lengths
return .Huffman_Bad_Code_Lengths
}
fill = lencodes[n - 1]
case 17:
@@ -624,11 +624,11 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
case 18:
c = u16(compress.read_bits_no_refill_lsb(z, 7) + 11)
case:
return E_Deflate.Huffman_Bad_Code_Lengths
return .Huffman_Bad_Code_Lengths
}
if ntot - n < u32(c) {
return E_Deflate.Huffman_Bad_Code_Lengths
return .Huffman_Bad_Code_Lengths
}
nc := n + u32(c)
@@ -639,7 +639,7 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
}
if n != ntot {
return E_Deflate.Huffman_Bad_Code_Lengths
return .Huffman_Bad_Code_Lengths
}
build_huffman(z_repeat, lencodes[:hlit]) or_return
@@ -677,4 +677,4 @@ inflate_from_byte_array_raw :: proc(input: []u8, buf: ^bytes.Buffer, raw := fals
return inflate_raw(z=&ctx, expected_output_size=expected_output_size)
}
inflate :: proc{inflate_from_context, inflate_from_byte_array};
inflate :: proc{inflate_from_context, inflate_from_byte_array}
+151 -9
View File
@@ -1,6 +1,7 @@
package dynamic_bit_array
import "core:intrinsics"
import "core:mem"
/*
Note that these constants are dependent on the backing being a u64.
@@ -11,11 +12,120 @@ INDEX_SHIFT :: 6
@(private="file")
INDEX_MASK :: 63
@(private="file")
NUM_BITS :: 64
Bit_Array :: struct {
bits: [dynamic]u64,
bias: int,
bits: [dynamic]u64,
bias: int,
max_index: int,
free_pointer: bool,
}
Bit_Array_Iterator :: struct {
array: ^Bit_Array,
word_idx: int,
bit_idx: uint,
}
/*
In:
- ba: ^Bit_Array - the array to iterate over
Out:
- it: ^Bit_Array_Iterator - the iterator that holds iteration state
*/
make_iterator :: proc (ba: ^Bit_Array) -> (it: Bit_Array_Iterator) {
return Bit_Array_Iterator { array = ba }
}
/*
In:
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
Out:
- set: bool - the state of the bit at `index`
- index: int - the next bit of the Bit_Array referenced by `it`.
- ok: bool - `true` if the iterator returned a valid index,
`false` if there were no more bits
*/
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 }
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
set = (word >> it.bit_idx & 1) == 1
it.bit_idx += 1
if it.bit_idx >= NUM_BITS {
it.bit_idx = 0
it.word_idx += 1
}
return set, index, true
}
/*
In:
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
Out:
- index: int - the next set bit of the Bit_Array referenced by `it`.
- ok: bool - `true` if the iterator returned a valid index,
`false` if there were no more bits set
*/
iterate_by_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
return iterate_internal_(it, true)
}
/*
In:
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
Out:
- index: int - the next unset bit of the Bit_Array referenced by `it`.
- ok: bool - `true` if the iterator returned a valid index,
`false` if there were no more unset bits
*/
iterate_by_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
return iterate_internal_(it, false)
}
@(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
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 {
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
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) {
return 0, false
}
}
// reaching here means that the word has some set bits
it.bit_idx += uint(intrinsics.count_trailing_zeros(word >> it.bit_idx))
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
it.bit_idx += 1
if it.bit_idx >= NUM_BITS {
it.bit_idx = 0
it.word_idx += 1
}
return index, index <= it.array.max_index
}
/*
In:
- ba: ^Bit_Array - a pointer to the Bit Array
@@ -70,14 +180,42 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator
resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index)
ba.bits[leg_index] |= 1 << uint(bit_index)
return true
}
/*
In:
- ba: ^Bit_Array - a pointer to the Bit Array
- index: The bit index. Can be an enum member.
Out:
- ok: Whether or not we managed to unset requested bit.
`unset` automatically resizes the Bit Array to accommodate the requested index if needed.
*/
unset :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
idx := int(index) - ba.bias
if ba == nil || int(index) < ba.bias { return false }
context.allocator = allocator
leg_index := idx >> INDEX_SHIFT
bit_index := idx & INDEX_MASK
resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index)
ba.bits[leg_index] &= ~(1 << uint(bit_index))
return true
}
/*
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
*/
create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -> (res: Bit_Array, ok: bool) #optional_ok {
create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -> (res: ^Bit_Array, ok: bool) #optional_ok {
context.allocator = allocator
size_in_bits := max_index - min_index
@@ -85,10 +223,11 @@ create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -
legs := size_in_bits >> INDEX_SHIFT
res = Bit_Array{
bias = min_index,
}
return res, resize_if_needed(&res, legs)
res = new(Bit_Array)
res.bias = min_index
res.max_index = max_index
res.free_pointer = true
return res, resize_if_needed(res, legs)
}
/*
@@ -96,7 +235,7 @@ create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -
*/
clear :: proc(ba: ^Bit_Array) {
if ba == nil { return }
ba.bits = {}
mem.zero_slice(ba.bits[:])
}
/*
@@ -105,6 +244,9 @@ clear :: proc(ba: ^Bit_Array) {
destroy :: proc(ba: ^Bit_Array) {
if ba == nil { return }
delete(ba.bits)
if ba.free_pointer { // Only free if this Bit_Array was created using `create`, not when on the stack.
free(ba)
}
}
/*
@@ -121,4 +263,4 @@ resize_if_needed :: proc(ba: ^Bit_Array, legs: int, allocator := context.allocat
resize(&ba.bits, legs + 1)
}
return len(ba.bits) > legs
}
}
+7 -6
View File
@@ -21,6 +21,7 @@ package dynamic_bit_array
// returns `false`, `false`, because this Bit Array wasn't created to allow negative indices.
was_set, was_retrieved := get(&bits, -1)
fmt.println(was_set, was_retrieved)
destroy(&bits)
}
-- A Bit Array can optionally allow for negative indices, if the mininum value was given during creation:
@@ -40,13 +41,13 @@ package dynamic_bit_array
using bit_array
bits := create(int(max(Foo)), int(min(Foo)))
defer destroy(&bits)
defer destroy(bits)
fmt.printf("Set(Bar): %v\n", set(&bits, Foo.Bar))
fmt.printf("Get(Bar): %v, %v\n", get(&bits, Foo.Bar))
fmt.printf("Set(Negative_Test): %v\n", set(&bits, Foo.Negative_Test))
fmt.printf("Get(Leaves): %v, %v\n", get(&bits, Foo.Leaves))
fmt.printf("Get(Negative_Test): %v, %v\n", get(&bits, Foo.Negative_Test))
fmt.printf("Set(Bar): %v\n", set(bits, Foo.Bar))
fmt.printf("Get(Bar): %v, %v\n", get(bits, Foo.Bar))
fmt.printf("Set(Negative_Test): %v\n", set(bits, Foo.Negative_Test))
fmt.printf("Get(Leaves): %v, %v\n", get(bits, Foo.Leaves))
fmt.printf("Get(Negative_Test): %v, %v\n", get(bits, Foo.Negative_Test))
fmt.printf("Freed.\n")
}
*/
@@ -0,0 +1,173 @@
package container_intrusive_list
import "core:intrinsics"
// An intrusive doubly-linked list
//
// As this is an intrusive container, a `Node` must be embedded in your own
// structure which is conventionally called a "link". The use of `push_front`
// and `push_back` take the address of this node. Retrieving the data
// associated with the node requires finding the relative offset of the node
// of the parent structure. The parent type and field name are given to
// `iterator_*` procedures, or to the built-in `container_of` procedure.
//
// This data structure is two-pointers in size:
// 8 bytes on 32-bit platforms and 16 bytes on 64-bit platforms
List :: struct {
head: ^Node,
tail: ^Node,
}
Node :: struct {
next, prev: ^Node,
}
push_front :: proc(list: ^List, node: ^Node) {
if list.head != nil {
list.head.prev = node
node.prev, node.next = nil, list.head
list.head = node
} else {
list.head, list.tail = node, node
node.prev, node.next = nil, nil
}
}
push_back :: proc(list: ^List, node: ^Node) {
if list.tail != nil {
list.tail.next = node
node.prev, node.next = list.tail, nil
list.tail = node
} else {
list.head, list.tail = node, node
node.prev, node.next = nil, nil
}
}
remove :: proc(list: ^List, node: ^Node) {
if node != nil {
if node.next != nil {
node.next.prev = node.prev
}
if node.prev != nil {
node.prev.next = node.next
}
if list.head == node {
list.head = node.next
}
if list.tail == node {
list.tail = node.prev
}
}
}
remove_by_proc :: proc(list: ^List, to_erase: proc(^Node) -> bool) {
for node := list.head; node != nil; {
next := node.next
if to_erase(node) {
if node.next != nil {
node.next.prev = node.prev
}
if node.prev != nil {
node.prev.next = node.next
}
if list.head == node {
list.head = node.next
}
if list.tail == node {
list.tail = node.prev
}
}
node = next
}
}
is_empty :: proc(list: ^List) -> bool {
return list.head == nil
}
pop_front :: proc(list: ^List) -> ^Node {
link := list.head
if link == nil {
return nil
}
if link.next != nil {
link.next.prev = link.prev
}
if link.prev != nil {
link.prev.next = link.next
}
if link == list.head {
list.head = link.next
}
if link == list.tail {
list.tail = link.prev
}
return link
}
pop_back :: proc(list: ^List) -> ^Node {
link := list.tail
if link == nil {
return nil
}
if link.next != nil {
link.next.prev = link.prev
}
if link.prev != nil {
link.prev.next = link.next
}
if link == list.head {
list.head = link.next
}
if link == list.tail {
list.tail = link.prev
}
return link
}
Iterator :: struct($T: typeid) {
curr: ^Node,
offset: uintptr,
}
iterator_head :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.head, offset_of_by_string(T, field_name)}
}
iterator_tail :: proc(list: List, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {list.tail, offset_of_by_string(T, field_name)}
}
iterator_from_node :: proc(node: ^Node, $T: typeid, $field_name: string) -> Iterator(T)
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Node {
return {node, offset_of_by_string(T, field_name)}
}
iterate_next :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
return nil, false
}
it.curr = node.next
return (^T)(uintptr(node) - it.offset), true
}
iterate_prev :: proc(it: ^Iterator($T)) -> (ptr: ^T, ok: bool) {
node := it.curr
if node == nil {
return nil, false
}
it.curr = node.prev
return (^T)(uintptr(node) - it.offset), true
}
+43 -25
View File
@@ -1,9 +1,9 @@
package container_lru
import "core:runtime"
import "core:intrinsics"
import "core:mem"
_ :: runtime
_ :: intrinsics
_ :: mem
Node :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
prev, next: ^Node(Key, Value),
@@ -23,11 +23,10 @@ Cache :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key
count: int,
capacity: int,
node_allocator: mem.Allocator,
node_allocator: runtime.Allocator,
on_remove: proc(key: Key, value: Value, user_data: rawptr),
on_remove_user_data: rawptr,
call_on_remove_on_destroy: bool,
}
// init initializes a Cache
@@ -37,38 +36,51 @@ init :: proc(c: ^$C/Cache($Key, $Value), capacity: int, entries_allocator := con
c.capacity = capacity
}
// destroy deinitializes a Cache
destroy :: proc(c: ^$C/Cache($Key, $Value)) {
// destroy deinitializes a Cachem
destroy :: proc(c: ^$C/Cache($Key, $Value), call_on_remove: bool) {
clear(c, call_on_remove)
delete(c.entries)
}
// clear the contents of a Cache
clear :: proc(c: ^$C/Cache($Key, $Value), call_on_remove: bool) {
for _, node in c.entries {
if c.call_on_remove_on_destroy && c.on_remove != nil {
c.on_remove(node.key, node.value, c.on_remove_user_data)
if call_on_remove {
_call_on_remove(c, node)
}
free(node, c.node_allocator)
}
clear(&c.entries)
delete(c.entries)
runtime.clear(&c.entries)
c.head = nil
c.tail = nil
c.count = 0
}
// set the given key value pair. This operation updates the recent usage of the item.
set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> mem.Allocator_Error {
set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> runtime.Allocator_Error {
if e, ok := c.entries[key]; ok {
e.value = value
_pop_node(c, e)
_push_front_node(c, e)
return nil
}
e := new(Node(Key, Value), c.node_allocator) or_return
e.key = key
e.value = value
_push_front_node(c, e)
if c.count > c.capacity {
_remove_node(c, c.tail)
e : ^Node(Key, Value) = nil
assert(c.count <= c.capacity)
if c.count == c.capacity {
e = c.tail
_remove_node(c, e)
}
else {
c.count += 1
e = new(Node(Key, Value), c.node_allocator) or_return
}
e.key = key
e.value = value
_push_front_node(c, e)
c.entries[key] = e
return nil
}
@@ -118,6 +130,8 @@ remove :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
return false
}
_remove_node(c, e)
free(node, c.node_allocator)
c.count -= 1
return true
}
@@ -139,16 +153,16 @@ _remove_node :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) {
node.prev = nil
node.next = nil
c.count -= 1
delete_key(&c.entries, node.key)
_call_on_remove(c, node)
}
@(private)
_call_on_remove :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) {
if c.on_remove != nil {
c.on_remove(node.key, node.value, c.on_remove_user_data)
}
free(node, c.node_allocator)
}
@(private)
@@ -162,8 +176,6 @@ _push_front_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
c.tail = e
}
e.prev = nil
c.count += 1
}
@(private)
@@ -171,6 +183,12 @@ _pop_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
if e == nil {
return
}
if c.head == e {
c.head = e.next
}
if c.tail == e {
c.tail = e.prev
}
if e.prev != nil {
e.prev.next = e.next
}
+10
View File
@@ -69,6 +69,16 @@ get :: proc(q: ^$Q/Queue($T), #any_int i: int, loc := #caller_location) -> T {
idx := (uint(i)+q.offset)%builtin.len(q.data)
return q.data[idx]
}
front :: proc(q: ^$Q/Queue($T)) -> T {
return q.data[q.offset]
}
back :: proc(q: ^$Q/Queue($T)) -> T {
idx := (q.offset+uint(q.len))%builtin.len(q.data)
return q.data[idx]
}
set :: proc(q: ^$Q/Queue($T), #any_int i: int, val: T, loc := #caller_location) {
runtime.bounds_check_error_loc(loc, i, builtin.len(q.data))
+5 -5
View File
@@ -25,14 +25,14 @@ slice :: proc(a: ^$A/Small_Array($N, $T)) -> []T {
}
get :: proc(a: $A/Small_Array($N, $T), index: int, loc := #caller_location) -> T {
get :: proc(a: $A/Small_Array($N, $T), index: int) -> T {
return a.data[index]
}
get_ptr :: proc(a: $A/Small_Array($N, $T), index: int, loc := #caller_location) -> ^T {
get_ptr :: proc(a: ^$A/Small_Array($N, $T), index: int) -> ^T {
return &a.data[index]
}
set :: proc(a: ^$A/Small_Array($N, $T), index: int, item: T, loc := #caller_location) {
set :: proc(a: ^$A/Small_Array($N, $T), index: int, item: T) {
a.data[index] = item
}
@@ -86,7 +86,7 @@ pop_back_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) {
return
}
pop_front_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (T, bool) {
pop_front_safe :: proc(a: ^$A/Small_Array($N, $T)) -> (item: T, ok: bool) {
if N > 0 && a.len > 0 {
item = a.data[0]
s := slice(a)
@@ -114,4 +114,4 @@ push_back_elems :: proc(a: ^$A/Small_Array($N, $T), items: ..T) {
append_elem :: push_back
append_elems :: push_back_elems
push :: proc{push_back, push_back_elems}
append :: proc{push_back, push_back_elems}
append :: proc{push_back, push_back_elems}
@@ -0,0 +1,98 @@
// The following is a generic O(V+E) topological sorter implementation.
// This is the fastest known method for topological sorting and Odin's
// map type is being used to accelerate lookups.
package container_topological_sort
import "core:intrinsics"
import "core:runtime"
_ :: intrinsics
_ :: runtime
Relations :: struct($K: typeid) where intrinsics.type_is_valid_map_key(K) {
dependents: map[K]bool,
dependencies: int,
}
Sorter :: struct(K: typeid) where intrinsics.type_is_valid_map_key(K) {
relations: map[K]Relations(K),
dependents_allocator: runtime.Allocator,
}
@(private="file")
make_relations :: proc(sorter: ^$S/Sorter($K)) -> (r: Relations(K)) {
r.dependents.allocator = sorter.dependents_allocator
return
}
init :: proc(sorter: ^$S/Sorter($K)) {
sorter.relations = make(map[K]Relations(K))
sorter.dependents_allocator = context.allocator
}
destroy :: proc(sorter: ^$S/Sorter($K)) {
for _, v in &sorter.relations {
delete(v.dependents)
}
delete(sorter.relations)
}
add_key :: proc(sorter: ^$S/Sorter($K), key: K) -> bool {
if key in sorter.relations {
return false
}
sorter.relations[key] = make_relations(sorter)
return true
}
add_dependency :: proc(sorter: ^$S/Sorter($K), key, dependency: K) -> bool {
if key == dependency {
return false
}
find := &sorter.relations[dependency]
if find == nil {
find = map_insert(&sorter.relations, dependency, make_relations(sorter))
}
if find.dependents[key] {
return true
}
find.dependents[key] = true
find = &sorter.relations[key]
if find == nil {
find = map_insert(&sorter.relations, key, make_relations(sorter))
}
find.dependencies += 1
return true
}
sort :: proc(sorter: ^$S/Sorter($K)) -> (sorted, cycled: [dynamic]K) {
relations := &sorter.relations
for k, v in relations {
if v.dependencies == 0 {
append(&sorted, k)
}
}
for root in &sorted do for k, _ in relations[root].dependents {
relation := &relations[k]
relation.dependencies -= 1
if relation.dependencies == 0 {
append(&sorted, k)
}
}
for k, v in relations {
if v.dependencies != 0 {
append(&cycled, k)
}
}
return
}
+1 -1
View File
@@ -22,7 +22,7 @@ fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, a
assert(len(arg1) == 16)
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
// While it may be unwise to do deserialization here on our
// own when fiat-crypto provides equivalent functionality,
// doing it this way provides a little under 3x performance
+1 -1
View File
@@ -346,7 +346,7 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
// Until dedicated assembly can be written leverage the fact that
// the callers of this routine ensure that src/dst are valid.
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
// util.PUT_U32_LE/util.U32_LE are not required on little-endian
// systems that also happen to not be strict about aligned
// memory access.
+1 -1
View File
@@ -1,6 +1,6 @@
package crypto
when ODIN_OS != "linux" {
when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows {
_rand_bytes :: proc (dst: []byte) {
unimplemented("crypto: rand_bytes not supported on this OS")
}
+12
View File
@@ -0,0 +1,12 @@
package crypto
import "core:c"
foreign import libc "system:c"
foreign libc {
arc4random_buf :: proc "c" (buf: rawptr, nbytes: c.size_t) ---
}
_rand_bytes :: proc (dst: []byte) {
arc4random_buf(raw_data(dst), len(dst))
}
+23
View File
@@ -0,0 +1,23 @@
package crypto
import win32 "core:sys/windows"
import "core:os"
import "core:fmt"
_rand_bytes :: proc(dst: []byte) {
ret := (os.Errno)(win32.BCryptGenRandom(nil, raw_data(dst), u32(len(dst)), win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG))
if ret != os.ERROR_NONE {
switch ret {
case os.ERROR_INVALID_HANDLE:
// The handle to the first parameter is invalid.
// This should not happen here, since we explicitly pass nil to it
panic("crypto: BCryptGenRandom Invalid handle for hAlgorithm")
case os.ERROR_INVALID_PARAMETER:
// One of the parameters was invalid
panic("crypto: BCryptGenRandom Invalid parameter")
case:
// Unknown error
panic(fmt.tprintf("crypto: BCryptGenRandom failed: %d\n", ret))
}
}
}
+4 -2
View File
@@ -419,8 +419,10 @@ update :: proc(ctx: ^$T, data: []byte) {
sha2_transf(ctx, shifted_message, block_nb)
rem_len = new_len % CURR_BLOCK_SIZE
when T == Sha256_Context {copy(ctx.block[:], shifted_message[block_nb << 6:rem_len])}
else when T == Sha512_Context {copy(ctx.block[:], shifted_message[block_nb << 7:rem_len])}
if rem_len > 0 {
when T == Sha256_Context {copy(ctx.block[:], shifted_message[block_nb << 6:rem_len])}
else when T == Sha512_Context {copy(ctx.block[:], shifted_message[block_nb << 7:rem_len])}
}
ctx.length = rem_len
when T == Sha256_Context {ctx.tot_len += (block_nb + 1) << 6}
+335
View File
@@ -0,0 +1,335 @@
package siphash
/*
Copyright 2022 zhibog
Made available under the BSD-3 license.
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"
import "core:crypto/util"
/*
High level API
*/
KEY_SIZE :: 16
DIGEST_SIZE :: 8
// sum_string_1_3 will hash the given message with the key and return
// the computed hash as a u64
sum_string_1_3 :: proc(msg, key: string) -> u64 {
return sum_bytes_1_3(transmute([]byte)(msg), transmute([]byte)(key))
}
// sum_bytes_1_3 will hash the given message with the key and return
// the computed hash as a u64
sum_bytes_1_3 :: proc (msg, key: []byte) -> u64 {
ctx: Context
hash: u64
init(&ctx, key, 1, 3)
update(&ctx, msg)
final(&ctx, &hash)
return hash
}
// sum_string_to_buffer_1_3 will hash the given message with the key and write
// the computed hash into the provided destination buffer
sum_string_to_buffer_1_3 :: proc(msg, key: string, dst: []byte) {
sum_bytes_to_buffer_1_3(transmute([]byte)(msg), transmute([]byte)(key), dst)
}
// sum_bytes_to_buffer_1_3 will hash the given message with the key and write
// the computed hash into the provided destination buffer
sum_bytes_to_buffer_1_3 :: proc(msg, key, dst: []byte) {
assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8")
hash := sum_bytes_1_3(msg, key)
_collect_output(dst[:], hash)
}
sum_1_3 :: proc {
sum_string_1_3,
sum_bytes_1_3,
sum_string_to_buffer_1_3,
sum_bytes_to_buffer_1_3,
}
// verify_u64_1_3 will check if the supplied tag matches with the output you
// will get from the provided message and key
verify_u64_1_3 :: proc (tag: u64 msg, key: []byte) -> bool {
return sum_bytes_1_3(msg, key) == tag
}
// verify_bytes will check if the supplied tag matches with the output you
// will get from the provided message and key
verify_bytes_1_3 :: proc (tag, msg, key: []byte) -> bool {
derived_tag: [8]byte
sum_bytes_to_buffer_1_3(msg, key, derived_tag[:])
return crypto.compare_constant_time(derived_tag[:], tag) == 1
}
verify_1_3 :: proc {
verify_bytes_1_3,
verify_u64_1_3,
}
// sum_string_2_4 will hash the given message with the key and return
// the computed hash as a u64
sum_string_2_4 :: proc(msg, key: string) -> u64 {
return sum_bytes_2_4(transmute([]byte)(msg), transmute([]byte)(key))
}
// sum_bytes_2_4 will hash the given message with the key and return
// the computed hash as a u64
sum_bytes_2_4 :: proc (msg, key: []byte) -> u64 {
ctx: Context
hash: u64
init(&ctx, key, 2, 4)
update(&ctx, msg)
final(&ctx, &hash)
return hash
}
// sum_string_to_buffer_2_4 will hash the given message with the key and write
// the computed hash into the provided destination buffer
sum_string_to_buffer_2_4 :: proc(msg, key: string, dst: []byte) {
sum_bytes_to_buffer_2_4(transmute([]byte)(msg), transmute([]byte)(key), dst)
}
// sum_bytes_to_buffer_2_4 will hash the given message with the key and write
// the computed hash into the provided destination buffer
sum_bytes_to_buffer_2_4 :: proc(msg, key, dst: []byte) {
assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8")
hash := sum_bytes_2_4(msg, key)
_collect_output(dst[:], hash)
}
sum_2_4 :: proc {
sum_string_2_4,
sum_bytes_2_4,
sum_string_to_buffer_2_4,
sum_bytes_to_buffer_2_4,
}
sum_string :: sum_string_2_4
sum_bytes :: sum_bytes_2_4
sum_string_to_buffer :: sum_string_to_buffer_2_4
sum_bytes_to_buffer :: sum_bytes_to_buffer_2_4
sum :: proc {
sum_string,
sum_bytes,
sum_string_to_buffer,
sum_bytes_to_buffer,
}
// verify_u64_2_4 will check if the supplied tag matches with the output you
// will get from the provided message and key
verify_u64_2_4 :: proc (tag: u64 msg, key: []byte) -> bool {
return sum_bytes_2_4(msg, key) == tag
}
// verify_bytes will check if the supplied tag matches with the output you
// will get from the provided message and key
verify_bytes_2_4 :: proc (tag, msg, key: []byte) -> bool {
derived_tag: [8]byte
sum_bytes_to_buffer_2_4(msg, key, derived_tag[:])
return crypto.compare_constant_time(derived_tag[:], tag) == 1
}
verify_2_4 :: proc {
verify_bytes_2_4,
verify_u64_2_4,
}
verify_bytes :: verify_bytes_2_4
verify_u64 :: verify_u64_2_4
verify :: proc {
verify_bytes,
verify_u64,
}
// sum_string_4_8 will hash the given message with the key and return
// the computed hash as a u64
sum_string_4_8 :: proc(msg, key: string) -> u64 {
return sum_bytes_4_8(transmute([]byte)(msg), transmute([]byte)(key))
}
// sum_bytes_4_8 will hash the given message with the key and return
// the computed hash as a u64
sum_bytes_4_8 :: proc (msg, key: []byte) -> u64 {
ctx: Context
hash: u64
init(&ctx, key, 4, 8)
update(&ctx, msg)
final(&ctx, &hash)
return hash
}
// sum_string_to_buffer_4_8 will hash the given message with the key and write
// the computed hash into the provided destination buffer
sum_string_to_buffer_4_8 :: proc(msg, key: string, dst: []byte) {
sum_bytes_to_buffer_4_8(transmute([]byte)(msg), transmute([]byte)(key), dst)
}
// sum_bytes_to_buffer_4_8 will hash the given message with the key and write
// the computed hash into the provided destination buffer
sum_bytes_to_buffer_4_8 :: proc(msg, key, dst: []byte) {
assert(len(dst) >= DIGEST_SIZE, "crypto/siphash: Destination buffer needs to be at least of size 8")
hash := sum_bytes_4_8(msg, key)
_collect_output(dst[:], hash)
}
sum_4_8 :: proc {
sum_string_4_8,
sum_bytes_4_8,
sum_string_to_buffer_4_8,
sum_bytes_to_buffer_4_8,
}
// verify_u64_4_8 will check if the supplied tag matches with the output you
// will get from the provided message and key
verify_u64_4_8 :: proc (tag: u64 msg, key: []byte) -> bool {
return sum_bytes_4_8(msg, key) == tag
}
// verify_bytes will check if the supplied tag matches with the output you
// will get from the provided message and key
verify_bytes_4_8 :: proc (tag, msg, key: []byte) -> bool {
derived_tag: [8]byte
sum_bytes_to_buffer_4_8(msg, key, derived_tag[:])
return crypto.compare_constant_time(derived_tag[:], tag) == 1
}
verify_4_8 :: proc {
verify_bytes_4_8,
verify_u64_4_8,
}
/*
Low level API
*/
init :: proc(ctx: ^Context, key: []byte, c_rounds, d_rounds: int) {
assert(len(key) == KEY_SIZE, "crypto/siphash: Invalid key size, want 16")
ctx.c_rounds = c_rounds
ctx.d_rounds = d_rounds
is_valid_setting := (ctx.c_rounds == 1 && ctx.d_rounds == 3) ||
(ctx.c_rounds == 2 && ctx.d_rounds == 4) ||
(ctx.c_rounds == 4 && ctx.d_rounds == 8)
assert(is_valid_setting, "crypto/siphash: Incorrect rounds set up. Valid pairs are (1,3), (2,4) and (4,8)")
ctx.k0 = util.U64_LE(key[:8])
ctx.k1 = util.U64_LE(key[8:])
ctx.v0 = 0x736f6d6570736575 ~ ctx.k0
ctx.v1 = 0x646f72616e646f6d ~ ctx.k1
ctx.v2 = 0x6c7967656e657261 ~ ctx.k0
ctx.v3 = 0x7465646279746573 ~ ctx.k1
ctx.is_initialized = true
}
update :: proc(ctx: ^Context, data: []byte) {
assert(ctx.is_initialized, "crypto/siphash: Context is not initalized")
ctx.last_block = len(data) / 8 * 8
ctx.buf = data
i := 0
m: u64
for i < ctx.last_block {
m = u64(ctx.buf[i] & 0xff)
i += 1
for r in u64(1)..<8 {
m |= u64(ctx.buf[i] & 0xff) << (r * 8)
i += 1
}
ctx.v3 ~= m
for _ in 0..<ctx.c_rounds {
_compress(ctx)
}
ctx.v0 ~= m
}
}
final :: proc(ctx: ^Context, dst: ^u64) {
m: u64
for i := len(ctx.buf) - 1; i >= ctx.last_block; i -= 1 {
m <<= 8
m |= u64(ctx.buf[i] & 0xff)
}
m |= u64(len(ctx.buf) << 56)
ctx.v3 ~= m
for _ in 0..<ctx.c_rounds {
_compress(ctx)
}
ctx.v0 ~= m
ctx.v2 ~= 0xff
for _ in 0..<ctx.d_rounds {
_compress(ctx)
}
dst^ = ctx.v0 ~ ctx.v1 ~ ctx.v2 ~ ctx.v3
reset(ctx)
}
reset :: proc(ctx: ^Context) {
ctx.k0, ctx.k1 = 0, 0
ctx.v0, ctx.v1 = 0, 0
ctx.v2, ctx.v3 = 0, 0
ctx.last_block = 0
ctx.c_rounds = 0
ctx.d_rounds = 0
ctx.is_initialized = false
}
Context :: struct {
v0, v1, v2, v3: u64, // State values
k0, k1: u64, // Split key
c_rounds: int, // Number of message rounds
d_rounds: int, // Number of finalization rounds
buf: []byte, // Provided data
last_block: int, // Offset from the last block
is_initialized: bool,
}
_get_byte :: #force_inline proc "contextless" (byte_num: byte, into: u64) -> byte {
return byte(into >> (((~byte_num) & (size_of(u64) - 1)) << 3))
}
_collect_output :: #force_inline proc "contextless" (dst: []byte, hash: u64) {
dst[0] = _get_byte(7, hash)
dst[1] = _get_byte(6, hash)
dst[2] = _get_byte(5, hash)
dst[3] = _get_byte(4, hash)
dst[4] = _get_byte(3, hash)
dst[5] = _get_byte(2, hash)
dst[6] = _get_byte(1, hash)
dst[7] = _get_byte(0, hash)
}
_compress :: #force_inline proc "contextless" (ctx: ^Context) {
ctx.v0 += ctx.v1
ctx.v1 = util.ROTL64(ctx.v1, 13)
ctx.v1 ~= ctx.v0
ctx.v0 = util.ROTL64(ctx.v0, 32)
ctx.v2 += ctx.v3
ctx.v3 = util.ROTL64(ctx.v3, 16)
ctx.v3 ~= ctx.v2
ctx.v0 += ctx.v3
ctx.v3 = util.ROTL64(ctx.v3, 21)
ctx.v3 ~= ctx.v0
ctx.v2 += ctx.v1
ctx.v1 = util.ROTL64(ctx.v1, 17)
ctx.v1 ~= ctx.v2
ctx.v2 = util.ROTL64(ctx.v2, 32)
}
+12
View File
@@ -1,3 +1,15 @@
package dynlib
Library :: distinct rawptr
load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
return _load_library(path, global_symbols)
}
unload_library :: proc(library: Library) -> bool {
return _unload_library(library)
}
symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) #optional_ok {
return _symbol_address(library, symbol)
}
+15 -14
View File
@@ -1,23 +1,24 @@
// +build linux, darwin, freebsd
//+build linux, darwin, freebsd, openbsd
//+private
package dynlib
import "core:os"
load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
flags := os.RTLD_NOW
if global_symbols {
flags |= os.RTLD_GLOBAL
}
lib := os.dlopen(path, flags)
return Library(lib), lib != nil
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
flags := os.RTLD_NOW
if global_symbols {
flags |= os.RTLD_GLOBAL
}
lib := os.dlopen(path, flags)
return Library(lib), lib != nil
}
unload_library :: proc(library: Library) {
os.dlclose(rawptr(library))
_unload_library :: proc(library: Library) -> bool {
return os.dlclose(rawptr(library))
}
symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
ptr = os.dlsym(rawptr(library), symbol)
found = ptr != nil
return
_symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
ptr = os.dlsym(rawptr(library), symbol)
found = ptr != nil
return
}
+5 -4
View File
@@ -1,10 +1,11 @@
// +build windows
//+build windows
//+private
package dynlib
import win32 "core:sys/windows"
import "core:strings"
load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
// NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL
wide_path := win32.utf8_to_wstring(path, context.temp_allocator)
@@ -12,12 +13,12 @@ load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
return handle, handle != nil
}
unload_library :: proc(library: Library) -> bool {
_unload_library :: proc(library: Library) -> bool {
ok := win32.FreeLibrary(cast(win32.HMODULE)library)
return bool(ok)
}
symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
_symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) {
c_str := strings.clone_to_cstring(symbol, context.temp_allocator)
ptr = win32.GetProcAddress(cast(win32.HMODULE)library, c_str)
found = ptr != nil
+65 -21
View File
@@ -34,6 +34,10 @@ Reader :: struct {
// If lazy_quotes is true, a quote may appear in an unquoted field and a non-doubled quote may appear in a quoted field
lazy_quotes: bool,
// multiline_fields, when set to true, will treat a field starting with a " as a multiline string
// therefore, instead of reading until the next \n, it'll read until the next "
multiline_fields: bool,
// reuse_record controls whether calls to 'read' may return a slice using the backing buffer
// for performance
// By default, each call to 'read' returns a newly allocated slice
@@ -194,32 +198,72 @@ is_valid_delim :: proc(r: rune) -> bool {
@private
_read_record :: proc(r: ^Reader, dst: ^[dynamic]string, allocator := context.allocator) -> ([]string, Error) {
read_line :: proc(r: ^Reader) -> ([]byte, io.Error) {
line, err := bufio.reader_read_slice(&r.r, '\n')
if err == .Buffer_Full {
clear(&r.raw_buffer)
append(&r.raw_buffer, ..line)
for err == .Buffer_Full {
line, err = bufio.reader_read_slice(&r.r, '\n')
if !r.multiline_fields {
line, err := bufio.reader_read_slice(&r.r, '\n')
if err == .Buffer_Full {
clear(&r.raw_buffer)
append(&r.raw_buffer, ..line)
for err == .Buffer_Full {
line, err = bufio.reader_read_slice(&r.r, '\n')
append(&r.raw_buffer, ..line)
}
line = r.raw_buffer[:]
}
line = r.raw_buffer[:]
}
if len(line) > 0 && err == .EOF {
err = nil
if line[len(line)-1] == '\r' {
line = line[:len(line)-1]
if len(line) > 0 && err == .EOF {
err = nil
if line[len(line)-1] == '\r' {
line = line[:len(line)-1]
}
}
}
r.line_count += 1
r.line_count += 1
// normalize \r\n to \n
n := len(line)
for n >= 2 && string(line[n-2:]) == "\r\n" {
line[n-2] = '\n'
line = line[:n-1]
}
// normalize \r\n to \n
n := len(line)
for n >= 2 && string(line[n-2:]) == "\r\n" {
line[n-2] = '\n'
line = line[:n-1]
}
return line, err
return line, err
} else {
// Reading a "line" that can possibly contain multiline fields.
// Unfortunately, this means we need to read a character at a time.
err: io.Error
cur: rune
is_quoted: bool
field_length := 0
clear(&r.raw_buffer)
read_loop: for err == .None {
cur, _, err = bufio.reader_read_rune(&r.r)
if err != .None { break read_loop }
switch cur {
case '"':
is_quoted = field_length == 0
field_length += 1
case '\n', '\r':
if !is_quoted { break read_loop }
case r.comma:
field_length = 0
case:
field_length += 1
}
rune_buf, rune_len := utf8.encode_rune(cur)
append(&r.raw_buffer, ..rune_buf[:rune_len])
}
return r.raw_buffer[:], err
}
unreachable()
}
length_newline :: proc(b: []byte) -> int {
+23
View File
@@ -0,0 +1,23 @@
/*
Package endian implements sa simple translation between bytes and numbers with
specific endian encodings.
buf: [100]u8
put_u16(buf[:], .Little, 16) or_return
You may ask yourself, why isn't `byte_order` platform Endianness by default, so we can write:
put_u16(buf[:], 16) or_return
The answer is that very few file formats are written in native/platform endianness. Most of them specify the endianness of
each of their fields, or use a header field which specifies it for the entire file.
e.g. a file which specifies it at the top for all fields could do this:
file_order := .Little if buf[0] == 0 else .Big
field := get_u16(buf[1:], file_order) or_return
If on the other hand a field is *always* Big-Endian, you're wise to explicitly state it for the benefit of the reader,
be that your future self or someone else.
field := get_u16(buf[:], .Big) or_return
*/
package encoding_endian
+153
View File
@@ -0,0 +1,153 @@
package encoding_endian
Byte_Order :: enum u8 {
Little,
Big,
}
PLATFORM_BYTE_ORDER :: Byte_Order.Little when ODIN_ENDIAN == .Little else Byte_Order.Big
get_u16 :: proc(b: []byte, order: Byte_Order) -> (v: u16, ok: bool) {
if len(b) < 2 {
return 0, false
}
#no_bounds_check if order == .Little {
v = u16(b[0]) | u16(b[1])<<8
} else {
v = u16(b[1]) | u16(b[0])<<8
}
return v, true
}
get_u32 :: proc(b: []byte, order: Byte_Order) -> (v: u32, ok: bool) {
if len(b) < 4 {
return 0, false
}
#no_bounds_check if order == .Little {
v = u32(b[0]) | u32(b[1])<<8 | u32(b[2])<<16 | u32(b[3])<<24
} else {
v = u32(b[3]) | u32(b[2])<<8 | u32(b[1])<<16 | u32(b[0])<<24
}
return v, true
}
get_u64 :: proc(b: []byte, order: Byte_Order) -> (v: u64, ok: bool) {
if len(b) < 8 {
return 0, false
}
#no_bounds_check if order == .Little {
v = u64(b[0]) | u64(b[1])<<8 | u64(b[2])<<16 | u64(b[3])<<24 |
u64(b[4])<<32 | u64(b[5])<<40 | u64(b[6])<<48 | u64(b[7])<<56
} else {
v = u64(b[7]) | u64(b[6])<<8 | u64(b[5])<<16 | u64(b[4])<<24 |
u64(b[3])<<32 | u64(b[2])<<40 | u64(b[1])<<48 | u64(b[0])<<56
}
return v, true
}
get_i16 :: proc(b: []byte, order: Byte_Order) -> (i16, bool) {
v, ok := get_u16(b, order)
return i16(v), ok
}
get_i32 :: proc(b: []byte, order: Byte_Order) -> (i32, bool) {
v, ok := get_u32(b, order)
return i32(v), ok
}
get_i64 :: proc(b: []byte, order: Byte_Order) -> (i64, bool) {
v, ok := get_u64(b, order)
return i64(v), ok
}
get_f16 :: proc(b: []byte, order: Byte_Order) -> (f16, bool) {
v, ok := get_u16(b, order)
return transmute(f16)v, ok
}
get_f32 :: proc(b: []byte, order: Byte_Order) -> (f32, bool) {
v, ok := get_u32(b, order)
return transmute(f32)v, ok
}
get_f64 :: proc(b: []byte, order: Byte_Order) -> (f64, bool) {
v, ok := get_u64(b, order)
return transmute(f64)v, ok
}
put_u16 :: proc(b: []byte, order: Byte_Order, v: u16) -> bool {
if len(b) < 2 {
return false
}
#no_bounds_check if order == .Little {
b[0] = byte(v)
b[1] = byte(v >> 8)
} else {
b[0] = byte(v >> 8)
b[1] = byte(v)
}
return true
}
put_u32 :: proc(b: []byte, order: Byte_Order, v: u32) -> bool {
if len(b) < 4 {
return false
}
#no_bounds_check if order == .Little {
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
} else {
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
b[3] = byte(v)
}
return true
}
put_u64 :: proc(b: []byte, order: Byte_Order, v: u64) -> bool {
if len(b) < 8 {
return false
}
#no_bounds_check if order == .Little {
b[0] = byte(v >> 0)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
b[3] = byte(v >> 24)
b[4] = byte(v >> 32)
b[5] = byte(v >> 40)
b[6] = byte(v >> 48)
b[7] = byte(v >> 56)
} else {
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
b[3] = byte(v >> 32)
b[4] = byte(v >> 24)
b[5] = byte(v >> 16)
b[6] = byte(v >> 8)
b[7] = byte(v)
}
return true
}
put_i16 :: proc(b: []byte, order: Byte_Order, v: i16) -> bool {
return put_u16(b, order, u16(v))
}
put_i32 :: proc(b: []byte, order: Byte_Order, v: i32) -> bool {
return put_u32(b, order, u32(v))
}
put_i64 :: proc(b: []byte, order: Byte_Order, v: i64) -> bool {
return put_u64(b, order, u64(v))
}
put_f16 :: proc(b: []byte, order: Byte_Order, v: f16) -> bool {
return put_u16(b, order, transmute(u16)v)
}
put_f32 :: proc(b: []byte, order: Byte_Order, v: f32) -> bool {
return put_u32(b, order, transmute(u32)v)
}
put_f64 :: proc(b: []byte, order: Byte_Order, v: f64) -> bool {
return put_u64(b, order, transmute(u64)v)
}
+21
View File
@@ -0,0 +1,21 @@
# License
By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions.
Permission to copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications:
The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, the W3C Software Short Notice should be included (hypertext is preferred, text is permitted) within the body of any redistributed or derivative code.
Notice of any changes or modifications to the files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)
# Disclaimers
THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
# Notes
This version: http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+374
View File
@@ -0,0 +1,374 @@
package unicode_entity
/*
A unicode entity encoder/decoder
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
This code has several procedures to map unicode runes to/from different textual encodings.
- SGML/XML/HTML entity
-- &#<decimal>;
-- &#x<hexadecimal>;
-- &<entity name>; (If the lookup tables are compiled in).
Reference: https://www.w3.org/2003/entities/2007xml/unicode.xml
- URL encode / decode %hex entity
Reference: https://datatracker.ietf.org/doc/html/rfc3986/#section-2.1
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
import "core:unicode/utf8"
import "core:unicode"
import "core:strings"
MAX_RUNE_CODEPOINT :: int(unicode.MAX_RUNE)
write_rune :: strings.write_rune_builder
write_string :: strings.write_string_builder
Error :: enum u8 {
None = 0,
Tokenizer_Is_Nil,
Illegal_NUL_Character,
Illegal_UTF_Encoding,
Illegal_BOM,
CDATA_Not_Terminated,
Comment_Not_Terminated,
Invalid_Entity_Encoding,
}
Tokenizer :: struct {
r: rune,
w: int,
src: string,
offset: int,
read_offset: int,
}
CDATA_START :: "<![CDATA["
CDATA_END :: "]]>"
COMMENT_START :: "<!--"
COMMENT_END :: "-->"
/*
Default: CDATA and comments are passed through unchanged.
*/
XML_Decode_Option :: enum u8 {
/*
Do not decode & entities. It decodes by default.
If given, overrides `Decode_CDATA`.
*/
No_Entity_Decode,
/*
CDATA is unboxed.
*/
Unbox_CDATA,
/*
Unboxed CDATA is decoded as well.
Ignored if `.Unbox_CDATA` is not given.
*/
Decode_CDATA,
/*
Comments are stripped.
*/
Comment_Strip,
}
XML_Decode_Options :: bit_set[XML_Decode_Option; u8]
/*
Decode a string that may include SGML/XML/HTML entities.
The caller has to free the result.
*/
decode_xml :: proc(input: string, options := XML_Decode_Options{}, allocator := context.allocator) -> (decoded: string, err: Error) {
context.allocator = allocator
l := len(input)
if l == 0 { return "", .None }
builder := strings.make_builder()
defer strings.destroy_builder(&builder)
t := Tokenizer{src=input}
in_data := false
loop: for {
advance(&t) or_return
if t.r < 0 { break loop }
/*
Below here we're never inside a CDATA tag.
At most we'll see the start of one, but that doesn't affect the logic.
*/
switch t.r {
case '<':
/*
Might be the start of a CDATA tag or comment.
We don't need to check if we need to write a `<`, because if it isn't CDATA or a comment,
it couldn't have been part of an XML tag body to be decoded here.
Keep in mind that we could already *be* inside a CDATA tag.
If so, write `>` as a literal and continue.
*/
if in_data {
write_rune(&builder, '<')
continue
}
in_data = _handle_xml_special(&t, &builder, options) or_return
case ']':
/*
If we're unboxing _and_ decoding CDATA, we'll have to check for the end tag.
*/
if in_data {
if t.read_offset + len(CDATA_END) < len(t.src) {
if string(t.src[t.offset:][:len(CDATA_END)]) == CDATA_END {
in_data = false
t.read_offset += len(CDATA_END) - 1
}
}
continue
} else {
write_rune(&builder, ']')
}
case:
if in_data && .Decode_CDATA not_in options {
/*
Unboxed, but undecoded.
*/
write_rune(&builder, t.r)
continue
}
if t.r == '&' {
if entity, entity_err := _extract_xml_entity(&t); entity_err != .None {
/*
We read to the end of the string without closing the entity.
Pass through as-is.
*/
write_string(&builder, entity)
} else {
if .No_Entity_Decode not_in options {
if decoded, ok := xml_decode_entity(entity); ok {
write_rune(&builder, decoded)
continue
}
}
/*
Literal passthrough because the decode failed or we want entities not decoded.
*/
write_string(&builder, "&")
write_string(&builder, entity)
write_string(&builder, ";")
}
} else {
write_rune(&builder, t.r)
}
}
}
return strings.clone(strings.to_string(builder), allocator), err
}
advance :: proc(t: ^Tokenizer) -> (err: Error) {
if t == nil { return .Tokenizer_Is_Nil }
using t
#no_bounds_check {
if read_offset < len(src) {
offset = read_offset
r, w = rune(src[read_offset]), 1
switch {
case r == 0:
return .Illegal_NUL_Character
case r >= utf8.RUNE_SELF:
r, w = utf8.decode_rune_in_string(src[read_offset:])
if r == utf8.RUNE_ERROR && w == 1 {
return .Illegal_UTF_Encoding
} else if r == utf8.RUNE_BOM && offset > 0 {
return .Illegal_BOM
}
}
read_offset += w
return .None
} else {
offset = len(src)
r = -1
return
}
}
}
xml_decode_entity :: proc(entity: string) -> (decoded: rune, ok: bool) {
entity := entity
if len(entity) == 0 { return -1, false }
switch entity[0] {
case '#':
base := 10
val := 0
entity = entity[1:]
if len(entity) == 0 { return -1, false }
if entity[0] == 'x' || entity[0] == 'X' {
base = 16
entity = entity[1:]
}
for len(entity) > 0 {
r := entity[0]
switch r {
case '0'..='9':
val *= base
val += int(r - '0')
case 'a'..='f':
if base == 10 { return -1, false }
val *= base
val += int(r - 'a' + 10)
case 'A'..='F':
if base == 10 { return -1, false }
val *= base
val += int(r - 'A' + 10)
case:
return -1, false
}
if val > MAX_RUNE_CODEPOINT { return -1, false }
entity = entity[1:]
}
return rune(val), true
case:
/*
Named entity.
*/
return named_xml_entity_to_rune(entity)
}
}
/*
Private XML helper to extract `&<stuff>;` entity.
*/
@(private="file")
_extract_xml_entity :: proc(t: ^Tokenizer) -> (entity: string, err: Error) {
assert(t != nil && t.r == '&')
/*
All of these would be in the ASCII range.
Even if one is not, it doesn't matter. All characters we need to compare to extract are.
*/
using t
length := len(t.src)
found := false
#no_bounds_check {
for read_offset < length {
if src[read_offset] == ';' {
found = true
read_offset += 1
break
}
read_offset += 1
}
}
if found {
return string(src[offset + 1 : read_offset - 1]), .None
}
return string(src[offset : read_offset]), .Invalid_Entity_Encoding
}
/*
Private XML helper for CDATA and comments.
*/
@(private="file")
_handle_xml_special :: proc(t: ^Tokenizer, builder: ^strings.Builder, options: XML_Decode_Options) -> (in_data: bool, err: Error) {
assert(t != nil && t.r == '<')
if t.read_offset + len(CDATA_START) >= len(t.src) { return false, .None }
if string(t.src[t.offset:][:len(CDATA_START)]) == CDATA_START {
t.read_offset += len(CDATA_START) - 1
if .Unbox_CDATA in options && .Decode_CDATA in options {
/*
We're unboxing _and_ decoding CDATA
*/
return true, .None
}
/*
CDATA is passed through.
*/
offset := t.offset
/*
Scan until end of CDATA.
*/
for {
advance(t) or_return
if t.r < 0 { return true, .CDATA_Not_Terminated }
if t.read_offset + len(CDATA_END) < len(t.src) {
if string(t.src[t.offset:][:len(CDATA_END)]) == CDATA_END {
t.read_offset += len(CDATA_END) - 1
cdata := string(t.src[offset : t.read_offset])
if .Unbox_CDATA in options {
cdata = cdata[len(CDATA_START):]
cdata = cdata[:len(cdata) - len(CDATA_END)]
}
write_string(builder, cdata)
return false, .None
}
}
}
} else if string(t.src[t.offset:][:len(COMMENT_START)]) == COMMENT_START {
t.read_offset += len(COMMENT_START)
/*
Comment is passed through by default.
*/
offset := t.offset
/*
Scan until end of Comment.
*/
for {
advance(t) or_return
if t.r < 0 { return true, .Comment_Not_Terminated }
if t.read_offset + len(COMMENT_END) < len(t.src) {
if string(t.src[t.offset:][:len(COMMENT_END)]) == COMMENT_END {
t.read_offset += len(COMMENT_END) - 1
if .Comment_Strip not_in options {
comment := string(t.src[offset : t.read_offset])
write_string(builder, comment)
}
return false, .None
}
}
}
}
return false, .None
}
@@ -0,0 +1,76 @@
package unicode_entity_example
import "core:encoding/xml"
import "core:strings"
import "core:mem"
import "core:fmt"
import "core:time"
doc_print :: proc(doc: ^xml.Document) {
buf: strings.Builder
defer strings.destroy_builder(&buf)
w := strings.to_writer(&buf)
xml.print(w, doc)
fmt.println(strings.to_string(buf))
}
_entities :: proc() {
doc: ^xml.Document
err: xml.Error
DOC :: #load("../../../../tests/core/assets/XML/unicode.xml")
OPTIONS :: xml.Options{
flags = {
.Ignore_Unsupported, .Intern_Comments,
},
expected_doctype = "",
}
parse_duration: time.Duration
{
time.SCOPED_TICK_DURATION(&parse_duration)
doc, err = xml.parse(DOC, OPTIONS)
}
defer xml.destroy(doc)
doc_print(doc)
ms := time.duration_milliseconds(parse_duration)
speed := (f64(1000.0) / ms) * f64(len(DOC)) / 1_024.0 / 1_024.0
fmt.printf("Parse time: %.2f ms (%.2f MiB/s).\n", ms, speed)
fmt.printf("Error: %v\n", err)
}
_main :: proc() {
using fmt
options := xml.Options{ flags = { .Ignore_Unsupported, .Intern_Comments, .Unbox_CDATA, .Decode_SGML_Entities }}
doc, _ := xml.parse(#load("test.html"), options)
defer xml.destroy(doc)
doc_print(doc)
}
main :: proc() {
using fmt
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
// _main()
_entities()
if len(track.allocation_map) > 0 {
println()
for _, v in track.allocation_map {
printf("%v Leaked %v bytes.\n", v.location, v.size)
}
}
}
+28
View File
@@ -0,0 +1,28 @@
<html>
<head>
<title>Entity Reference Test</title>
<style>
body {
background: #000; color: #eee;
width: 40%;
margin-left: auto;
margin-right: auto;
font-size: 14pt;
}
</style>
</head>
<body>
<h1>Entity Reference Test</h1>
<div id="test_cdata_in_comment" foo="">
Foozle]!&#32;&copy;&#x20;<!-- <![CDATA[&#32;&reg;&#x20;]]> -->42&;1234&
</div>
<!-- EXPECTED: Foozle]! © 42&;1234& -->
<div id="test_cdata_unwrap_and_passthrough">
Foozle]!&#32;&copy;&#x20;<![CDATA[BOX&#32;&reg;&#x20;/BOX]]>42&;1234&
</div>
<!-- EXPECTED: Foozle]! © BOX ® /BOX42&;1234& -->
<div>
&verbar; &vert; &VerticalLine; &fjlig; &grave; &bsol; &reg; &rhov; &CounterClockwiseContourIntegral; &bsemi;
</div>
</body>
</html>
File diff suppressed because it is too large Load Diff
+25 -4
View File
@@ -39,6 +39,9 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
read_value :: proc(r: ^Reader, $T: typeid) -> (value: T, err: Read_Error) {
remaining := len(r.data) - r.offset
if remaining < size_of(T) {
if r.print_error {
fmt.eprintf("file '%s' failed to read value at offset %v\n", r.filename, r.offset)
}
err = .Short_Read
return
}
@@ -51,6 +54,10 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
read_array :: proc(r: ^Reader, $T: typeid, count: int) -> (value: []T, err: Read_Error) {
remaining := len(r.data) - r.offset
if remaining < size_of(T)*count {
if r.print_error {
fmt.eprintf("file '%s' failed to read array of %d elements at offset %v\n",
r.filename, count, r.offset)
}
err = .Short_Read
return
}
@@ -82,7 +89,8 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
type := read_value(r, Meta_Value_Type) or_return
if type > max(Meta_Value_Type) {
if r.print_error {
fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is ", r.filename, u8(type), u8(max(Meta_Value_Type)))
fmt.eprintf("HxA Error: file '%s' has meta value type %d. Maximum value is %d\n",
r.filename, u8(type), u8(max(Meta_Value_Type)))
}
err = .Invalid_Data
return
@@ -114,7 +122,8 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
type := read_value(r, Layer_Data_Type) or_return
if type > max(type) {
if r.print_error {
fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is ", r.filename, u8(type), u8(max(Layer_Data_Type)))
fmt.eprintf("HxA Error: file '%s' has layer data type %d. Maximum value is %d\n",
r.filename, u8(type), u8(max(Layer_Data_Type)))
}
err = .Invalid_Data
return
@@ -134,13 +143,23 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
}
if len(data) < size_of(Header) {
if print_error {
fmt.eprintf("HxA Error: file '%s' has no header\n", filename)
}
err = .Short_Read
return
}
context.allocator = allocator
header := cast(^Header)raw_data(data)
assert(header.magic_number == MAGIC_NUMBER)
if (header.magic_number != MAGIC_NUMBER) {
if print_error {
fmt.eprintf("HxA Error: file '%s' has invalid magic number 0x%x\n", filename, header.magic_number)
}
err = .Invalid_Data
return
}
r := &Reader{
filename = filename,
@@ -150,6 +169,7 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
}
node_count := 0
file.header = header^
file.nodes = make([]Node, header.internal_node_count)
defer if err != nil {
nodes_destroy(file.nodes)
@@ -162,7 +182,8 @@ read :: proc(data: []byte, filename := "<input>", print_error := false, allocato
type := read_value(r, Node_Type) or_return
if type > max(Node_Type) {
if r.print_error {
fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is ", r.filename, u8(type), u8(max(Node_Type)))
fmt.eprintf("HxA Error: file '%s' has node type %d. Maximum value is %d\n",
r.filename, u8(type), u8(max(Node_Type)))
}
err = .Invalid_Data
return
+3 -3
View File
@@ -84,7 +84,7 @@ write_internal :: proc(w: ^Writer, file: File) {
write_metadata :: proc(w: ^Writer, meta_data: []Meta) {
for m in meta_data {
name_len := max(len(m.name), 255)
name_len := min(len(m.name), 255)
write_value(w, u8(name_len))
write_string(w, m.name[:name_len])
@@ -127,7 +127,7 @@ write_internal :: proc(w: ^Writer, file: File) {
write_layer_stack :: proc(w: ^Writer, layers: Layer_Stack) {
write_value(w, u32(len(layers)))
for layer in layers {
name_len := max(len(layer.name), 255)
name_len := min(len(layer.name), 255)
write_value(w, u8(name_len))
write_string(w, layer .name[:name_len])
@@ -152,7 +152,7 @@ write_internal :: proc(w: ^Writer, file: File) {
return
}
write_value(w, &Header{
write_value(w, Header{
magic_number = MAGIC_NUMBER,
version = LATEST_VERSION,
internal_node_count = u32le(len(file.nodes)),
+5 -4
View File
@@ -8,17 +8,18 @@ import "core:strings"
import "core:io"
Marshal_Data_Error :: enum {
None,
Unsupported_Type,
}
Marshal_Error :: union {
Marshal_Error :: union #shared_nil {
Marshal_Data_Error,
io.Error,
}
marshal :: proc(v: any, allocator := context.allocator) -> (data: []byte, err: Marshal_Error) {
b := strings.make_builder(allocator)
defer if err != .None {
defer if err != nil {
strings.destroy_builder(&b)
}
@@ -27,7 +28,7 @@ marshal :: proc(v: any, allocator := context.allocator) -> (data: []byte, err: M
if len(b.buf) != 0 {
data = b.buf[:]
}
return data, .None
return data, nil
}
marshal_to_builder :: proc(b: ^strings.Builder, v: any) -> Marshal_Error {
@@ -48,7 +49,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any) -> (err: Marshal_Error) {
unreachable()
case runtime.Type_Info_Integer:
buf: [21]byte
buf: [40]byte
u: u128
switch i in a {
case i8: u = u128(i)
+7 -1
View File
@@ -40,7 +40,7 @@ parse_string :: proc(data: string, spec := DEFAULT_SPECIFICATION, parse_integers
return parse_object(&p)
case .JSON5:
return parse_value(&p)
case .MJSON:
case .SJSON:
#partial switch p.curr_token.kind {
case .Ident, .String:
return parse_object_body(&p, .EOF)
@@ -354,6 +354,12 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
b := bytes_make(len(s) + 2*utf8.UTF_MAX, 1, allocator) or_return
w := copy(b, s[0:i])
if len(b) == 0 && allocator.data == nil {
// `unmarshal_count_array` calls us with a nil allocator
return string(b[:w]), nil
}
loop: for i < len(s) {
c := s[i]
switch {
+3 -2
View File
@@ -33,8 +33,9 @@ package json
Specification :: enum {
JSON,
JSON5, // https://json5.org/
MJSON, // https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html
Bitsquid = MJSON,
SJSON, // https://bitsquid.blogspot.com/2009/10/simplified-json-notation.html
Bitsquid = SJSON,
MJSON = SJSON,
}
+1 -1
View File
@@ -209,7 +209,7 @@ unmarshal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
variant := u.variants[0]
v.id = variant.id
ti = reflect.type_info_base(variant)
if !(u.maybe && reflect.is_pointer(variant)) {
if !reflect.is_pointer_internally(variant) {
tag := any{rawptr(uintptr(v.data) + u.tag_offset), u.tag_type.id}
assign_int(tag, 1)
}
+28
View File
@@ -0,0 +1,28 @@
/*
Implementation of the LEB128 variable integer encoding as used by DWARF encoding and DEX files, among others.
Author of this Odin package: Jeroen van Rijn
Example:
```odin
import "core:encoding/varint"
import "core:fmt"
main :: proc() {
buf: [varint.LEB128_MAX_BYTES]u8
value := u128(42)
encode_size, encode_err := varint.encode_uleb128(buf[:], value)
assert(encode_size == 1 && encode_err == .None)
fmt.printf("Encoded as %v\n", buf[:encode_size])
decoded_val, decode_size, decode_err := varint.decode_uleb128(buf[:])
assert(decoded_val == value && decode_size == encode_size && decode_err == .None)
fmt.printf("Decoded as %v, using %v byte%v\n", decoded_val, decode_size, "" if decode_size == 1 else "s")
}
```
*/
package varint
+163
View File
@@ -0,0 +1,163 @@
/*
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
// package varint implements variable length integer encoding and decoding using
// the LEB128 format as used by DWARF debug info, Android .dex and other file formats.
package varint
// In theory we should use the bigint package. In practice, varints bigger than this indicate a corrupted file.
// Instead we'll set limits on the values we'll encode/decode
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be `0b0000_0011`.
LEB128_MAX_BYTES :: 19
Error :: enum {
None = 0,
Buffer_Too_Small = 1,
Value_Too_Large = 2,
}
// Decode a slice of bytes encoding an unsigned LEB128 integer into value and number of bytes used.
// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
decode_uleb128_buffer :: proc(buf: []u8) -> (val: u128, size: int, err: Error) {
if len(buf) == 0 {
return 0, 0, .Buffer_Too_Small
}
for v in buf {
val, size, err = decode_uleb128_byte(v, size, val)
if err != .Buffer_Too_Small {
return
}
}
if err == .Buffer_Too_Small {
val, size = 0, 0
}
return
}
// Decodes an unsigned LEB128 integer into value a byte at a time.
// Returns `.None` when decoded properly, `.Value_Too_Large` when they value
// exceeds the limits of a u128, and `.Buffer_Too_Small` when it's not yet fully decoded.
decode_uleb128_byte :: proc(input: u8, offset: int, accumulator: u128) -> (val: u128, size: int, err: Error) {
size = offset + 1
// 18 * 7 bits = 126, which means that a possible 19th byte may at most be 0b0000_0011.
if size > LEB128_MAX_BYTES || size == LEB128_MAX_BYTES && input > 0b0000_0011 {
return 0, 0, .Value_Too_Large
}
val = accumulator | u128(input & 0x7f) << uint(offset * 7)
if input < 128 {
// We're done
return
}
// If the buffer runs out before the number ends, return an error.
return val, size, .Buffer_Too_Small
}
decode_uleb128 :: proc {decode_uleb128_buffer, decode_uleb128_byte}
// Decode a slice of bytes encoding a signed LEB128 integer into value and number of bytes used.
// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
decode_ileb128_buffer :: proc(buf: []u8) -> (val: i128, size: int, err: Error) {
if len(buf) == 0 {
return 0, 0, .Buffer_Too_Small
}
for v in buf {
val, size, err = decode_ileb128_byte(v, size, val)
if err != .Buffer_Too_Small {
return
}
}
if err == .Buffer_Too_Small {
val, size = 0, 0
}
return
}
// Decode a a signed LEB128 integer into value and number of bytes used, one byte at a time.
// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
decode_ileb128_byte :: proc(input: u8, offset: int, accumulator: i128) -> (val: i128, size: int, err: Error) {
size = offset + 1
shift := uint(offset * 7)
// 18 * 7 bits = 126, which including sign means we can have a 19th byte.
if size > LEB128_MAX_BYTES || size == LEB128_MAX_BYTES && input > 0x7f {
return 0, 0, .Value_Too_Large
}
val = accumulator | i128(input & 0x7f) << shift
if input < 128 {
if input & 0x40 == 0x40 {
val |= max(i128) << (shift + 7)
}
return val, size, .None
}
return val, size, .Buffer_Too_Small
}
decode_ileb128 :: proc{decode_ileb128_buffer, decode_ileb128_byte}
// Encode `val` into `buf` as an unsigned LEB128 encoded series of bytes.
// `buf` must be appropriately sized.
encode_uleb128 :: proc(buf: []u8, val: u128) -> (size: int, err: Error) {
val := val
for {
size += 1
if size > len(buf) {
return 0, .Buffer_Too_Small
}
low := val & 0x7f
val >>= 7
if val > 0 {
low |= 0x80 // more bytes to follow
}
buf[size - 1] = u8(low)
if val == 0 { break }
}
return
}
// Encode `val` into `buf` as a signed LEB128 encoded series of bytes.
// `buf` must be appropriately sized.
encode_ileb128 :: proc(buf: []u8, val: i128) -> (size: int, err: Error) {
SIGN_MASK :: i128(1) << 121 // sign extend mask
val, more := val, true
for more {
size += 1
if size > len(buf) {
return 0, .Buffer_Too_Small
}
low := val & 0x7f
val >>= 7
low = (low ~ SIGN_MASK) - SIGN_MASK
if (val == 0 && low & 0x40 != 0x40) || (val == -1 && low & 0x40 == 0x40) {
more = false
} else {
low |= 0x80
}
buf[size - 1] = u8(low)
}
return
}
+86
View File
@@ -0,0 +1,86 @@
/*
An XML 1.0 / 1.1 parser
Copyright 2021-2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
A from-scratch XML implementation, loosely modeled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816).
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xml
import "core:io"
import "core:fmt"
/*
Just for debug purposes.
*/
print :: proc(writer: io.Writer, doc: ^Document) -> (written: int, err: io.Error) {
if doc == nil { return }
using fmt
written += wprintf(writer, "[XML Prolog]\n")
for attr in doc.prologue {
written += wprintf(writer, "\t%v: %v\n", attr.key, attr.val)
}
written += wprintf(writer, "[Encoding] %v\n", doc.encoding)
if len(doc.doctype.ident) > 0 {
written += wprintf(writer, "[DOCTYPE] %v\n", doc.doctype.ident)
if len(doc.doctype.rest) > 0 {
wprintf(writer, "\t%v\n", doc.doctype.rest)
}
}
for comment in doc.comments {
written += wprintf(writer, "[Pre-root comment] %v\n", comment)
}
if len(doc.elements) > 0 {
wprintln(writer, " --- ")
print_element(writer, doc, 0)
wprintln(writer, " --- ")
}
return written, .None
}
print_element :: proc(writer: io.Writer, doc: ^Document, element_id: Element_ID, indent := 0) -> (written: int, err: io.Error) {
using fmt
tab :: proc(writer: io.Writer, indent: int) {
for _ in 0..=indent {
wprintf(writer, "\t")
}
}
tab(writer, indent)
element := doc.elements[element_id]
if element.kind == .Element {
wprintf(writer, "<%v>\n", element.ident)
if len(element.value) > 0 {
tab(writer, indent + 1)
wprintf(writer, "[Value] %v\n", element.value)
}
for attr in element.attribs {
tab(writer, indent + 1)
wprintf(writer, "[Attr] %v: %v\n", attr.key, attr.val)
}
for child in element.children {
print_element(writer, doc, child, indent + 1)
}
} else if element.kind == .Comment {
wprintf(writer, "[COMMENT] %v\n", element.value)
}
return written, .None
}
+112
View File
@@ -0,0 +1,112 @@
package xml_example
import "core:encoding/xml"
import "core:mem"
import "core:fmt"
import "core:time"
import "core:strings"
import "core:hash"
N :: 1
example :: proc() {
using fmt
docs: [N]^xml.Document
errs: [N]xml.Error
times: [N]time.Duration
defer for round in 0..<N {
xml.destroy(docs[round])
}
DOC :: #load("../../../../tests/core/assets/XML/unicode.xml")
input := DOC
for round in 0..<N {
start := time.tick_now()
docs[round], errs[round] = xml.parse(input, xml.Options{
flags={.Ignore_Unsupported},
expected_doctype = "",
})
end := time.tick_now()
times[round] = time.tick_diff(start, end)
}
fastest := max(time.Duration)
slowest := time.Duration(0)
total := time.Duration(0)
for round in 0..<N {
fastest = min(fastest, times[round])
slowest = max(slowest, times[round])
total += times[round]
}
fastest_ms := time.duration_milliseconds(fastest)
slowest_ms := time.duration_milliseconds(slowest)
average_ms := time.duration_milliseconds(time.Duration(f64(total) / f64(N)))
fastest_speed := (f64(1000.0) / fastest_ms) * f64(len(DOC)) / 1_024.0 / 1_024.0
slowest_speed := (f64(1000.0) / slowest_ms) * f64(len(DOC)) / 1_024.0 / 1_024.0
average_speed := (f64(1000.0) / average_ms) * f64(len(DOC)) / 1_024.0 / 1_024.0
fmt.printf("N = %v\n", N)
fmt.printf("[Fastest]: %v bytes in %.2f ms (%.2f MiB/s).\n", len(input), fastest_ms, fastest_speed)
fmt.printf("[Slowest]: %v bytes in %.2f ms (%.2f MiB/s).\n", len(input), slowest_ms, slowest_speed)
fmt.printf("[Average]: %v bytes in %.2f ms (%.2f MiB/s).\n", len(input), average_ms, average_speed)
if errs[0] != .None {
printf("Load/Parse error: %v\n", errs[0])
if errs[0] == .File_Error {
println("\"unicode.xml\" not found. Did you run \"tests\\download_assets.py\"?")
}
return
}
charlist, charlist_ok := xml.find_child_by_ident(docs[0], 0, "charlist")
if !charlist_ok {
eprintln("Could not locate top-level `<charlist>` tag.")
return
}
printf("Found `<charlist>` with %v children, %v elements total\n", len(docs[0].elements[charlist].children), docs[0].element_count)
crc32 := doc_hash(docs[0])
printf("[%v] CRC32: 0x%08x\n", "🎉" if crc32 == 0xcaa042b9 else "🤬", crc32)
for round in 0..<N {
defer xml.destroy(docs[round])
}
}
doc_hash :: proc(doc: ^xml.Document, print := false) -> (crc32: u32) {
buf: strings.Builder
defer strings.destroy_builder(&buf)
w := strings.to_writer(&buf)
xml.print(w, doc)
tree := strings.to_string(buf)
if print { fmt.println(tree) }
return hash.crc32(transmute([]u8)tree)
}
main :: proc() {
using fmt
track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator)
context.allocator = mem.tracking_allocator(&track)
example()
if len(track.allocation_map) > 0 {
println()
for _, v in track.allocation_map {
printf("%v Leaked %v bytes.\n", v.location, v.size)
}
}
println("Done and cleaned up!")
}
+45
View File
@@ -0,0 +1,45 @@
/*
An XML 1.0 / 1.1 parser
Copyright 2021-2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
This file contains helper functions.
*/
package xml
// Find parent's nth child with a given ident.
find_child_by_ident :: proc(doc: ^Document, parent_id: Element_ID, ident: string, nth := 0) -> (res: Element_ID, found: bool) {
tag := doc.elements[parent_id]
count := 0
for child_id in tag.children {
child := doc.elements[child_id]
/*
Skip commments. They have no name.
*/
if child.kind != .Element { continue }
/*
If the ident matches and it's the nth such child, return it.
*/
if child.ident == ident {
if count == nth { return child_id, true }
count += 1
}
}
return 0, false
}
// Find an attribute by key.
find_attribute_val_by_key :: proc(doc: ^Document, parent_id: Element_ID, key: string) -> (val: string, found: bool) {
tag := doc.elements[parent_id]
for attr in tag.attribs {
/*
If the ident matches, we're done. There can only ever be one attribute with the same name.
*/
if attr.key == key { return attr.val, true }
}
return "", false
}
+436
View File
@@ -0,0 +1,436 @@
/*
An XML 1.0 / 1.1 parser
Copyright 2021-2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
A from-scratch XML implementation, loosely modeled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816).
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xml
import "core:fmt"
import "core:unicode"
import "core:unicode/utf8"
Error_Handler :: #type proc(pos: Pos, fmt: string, args: ..any)
Token :: struct {
kind: Token_Kind,
text: string,
pos: Pos,
}
Pos :: struct {
file: string,
offset: int, // starting at 0
line: int, // starting at 1
column: int, // starting at 1
}
Token_Kind :: enum {
Invalid,
Ident,
Literal,
Rune,
String,
Double_Quote, // "
Single_Quote, // '
Colon, // :
Eq, // =
Lt, // <
Gt, // >
Exclaim, // !
Question, // ?
Hash, // #
Slash, // /
Dash, // -
Open_Bracket, // [
Close_Bracket, // ]
EOF,
}
CDATA_START :: "<![CDATA["
CDATA_END :: "]]>"
COMMENT_START :: "<!--"
COMMENT_END :: "-->"
Tokenizer :: struct {
// Immutable data
path: string,
src: string,
err: Error_Handler,
// Tokenizing state
ch: rune,
offset: int,
read_offset: int,
line_offset: int,
line_count: int,
// Mutable data
error_count: int,
}
init :: proc(t: ^Tokenizer, src: string, path: string, err: Error_Handler = default_error_handler) {
t.src = src
t.err = err
t.ch = ' '
t.offset = 0
t.read_offset = 0
t.line_offset = 0
t.line_count = len(src) > 0 ? 1 : 0
t.error_count = 0
t.path = path
advance_rune(t)
if t.ch == utf8.RUNE_BOM {
advance_rune(t)
}
}
@(private)
offset_to_pos :: proc(t: ^Tokenizer, offset: int) -> Pos {
line := t.line_count
column := offset - t.line_offset + 1
return Pos {
file = t.path,
offset = offset,
line = line,
column = column,
}
}
default_error_handler :: proc(pos: Pos, msg: string, args: ..any) {
fmt.eprintf("%s(%d:%d) ", pos.file, pos.line, pos.column)
fmt.eprintf(msg, ..args)
fmt.eprintf("\n")
}
error :: proc(t: ^Tokenizer, offset: int, msg: string, args: ..any) {
pos := offset_to_pos(t, offset)
if t.err != nil {
t.err(pos, msg, ..args)
}
t.error_count += 1
}
@(optimization_mode="speed")
advance_rune :: proc(using t: ^Tokenizer) {
#no_bounds_check {
/*
Already bounds-checked here.
*/
if read_offset < len(src) {
offset = read_offset
if ch == '\n' {
line_offset = offset
line_count += 1
}
r, w := rune(src[read_offset]), 1
switch {
case r == 0:
error(t, t.offset, "illegal character NUL")
case r >= utf8.RUNE_SELF:
r, w = #force_inline utf8.decode_rune_in_string(src[read_offset:])
if r == utf8.RUNE_ERROR && w == 1 {
error(t, t.offset, "illegal UTF-8 encoding")
} else if r == utf8.RUNE_BOM && offset > 0 {
error(t, t.offset, "illegal byte order mark")
}
}
read_offset += w
ch = r
} else {
offset = len(src)
if ch == '\n' {
line_offset = offset
line_count += 1
}
ch = -1
}
}
}
peek_byte :: proc(t: ^Tokenizer, offset := 0) -> byte {
if t.read_offset+offset < len(t.src) {
#no_bounds_check return t.src[t.read_offset+offset]
}
return 0
}
@(optimization_mode="speed")
skip_whitespace :: proc(t: ^Tokenizer) {
for {
switch t.ch {
case ' ', '\t', '\r', '\n':
advance_rune(t)
case:
return
}
}
}
@(optimization_mode="speed")
is_letter :: proc(r: rune) -> bool {
if r < utf8.RUNE_SELF {
switch r {
case '_':
return true
case 'A'..='Z', 'a'..='z':
return true
}
}
return unicode.is_letter(r)
}
is_valid_identifier_rune :: proc(r: rune) -> bool {
if r < utf8.RUNE_SELF {
switch r {
case '_', '-', ':': return true
case 'A'..='Z', 'a'..='z': return true
case '0'..='9': return true
case -1: return false
}
}
if unicode.is_letter(r) || unicode.is_digit(r) {
return true
}
return false
}
scan_identifier :: proc(t: ^Tokenizer) -> string {
offset := t.offset
namespaced := false
for is_valid_identifier_rune(t.ch) {
advance_rune(t)
if t.ch == ':' {
/*
A namespaced attr can have at most two parts, `namespace:ident`.
*/
if namespaced {
break
}
namespaced = true
}
}
return string(t.src[offset : t.offset])
}
/*
A comment ends when we see -->, preceded by a character that's not a dash.
"For compatibility, the string "--" (double-hyphen) must not occur within comments."
See: https://www.w3.org/TR/2006/REC-xml11-20060816/#dt-comment
Thanks to the length (4) of the comment start, we also have enough lookback,
and the peek at the next byte asserts that there's at least one more character
that's a `>`.
*/
scan_comment :: proc(t: ^Tokenizer) -> (comment: string, err: Error) {
offset := t.offset
for {
advance_rune(t)
ch := t.ch
if ch < 0 {
error(t, offset, "[parse] Comment was not terminated\n")
return "", .Unclosed_Comment
}
if string(t.src[t.offset - 1:][:2]) == "--" {
if peek_byte(t) == '>' {
break
} else {
error(t, t.offset - 1, "Invalid -- sequence in comment.\n")
return "", .Invalid_Sequence_In_Comment
}
}
}
expect(t, .Dash)
expect(t, .Gt)
return string(t.src[offset : t.offset - 1]), .None
}
/*
Skip CDATA
*/
skip_cdata :: proc(t: ^Tokenizer) -> (err: Error) {
if t.read_offset + len(CDATA_START) >= len(t.src) {
/*
Can't be the start of a CDATA tag.
*/
return .None
}
if string(t.src[t.offset:][:len(CDATA_START)]) == CDATA_START {
t.read_offset += len(CDATA_START)
offset := t.offset
cdata_scan: for {
advance_rune(t)
if t.ch < 0 {
error(t, offset, "[scan_string] CDATA was not terminated\n")
return .Premature_EOF
}
/*
Scan until the end of a CDATA tag.
*/
if t.read_offset + len(CDATA_END) < len(t.src) {
if string(t.src[t.offset:][:len(CDATA_END)]) == CDATA_END {
t.read_offset += len(CDATA_END)
break cdata_scan
}
}
}
}
return
}
@(optimization_mode="speed")
scan_string :: proc(t: ^Tokenizer, offset: int, close: rune = '<', consume_close := false, multiline := true) -> (value: string, err: Error) {
err = .None
loop: for {
ch := t.ch
switch ch {
case -1:
error(t, t.offset, "[scan_string] Premature end of file.\n")
return "", .Premature_EOF
case '<':
if peek_byte(t) == '!' {
if peek_byte(t, 1) == '[' {
/*
Might be the start of a CDATA tag.
*/
skip_cdata(t) or_return
} else if peek_byte(t, 1) == '-' && peek_byte(t, 2) == '-' {
/*
Comment start. Eat comment.
*/
t.read_offset += 3
_ = scan_comment(t) or_return
}
}
case '\n':
if !multiline {
error(t, offset, string(t.src[offset : t.offset]))
error(t, offset, "[scan_string] Not terminated\n")
err = .Invalid_Tag_Value
break loop
}
}
if t.ch == close {
/*
If it's not a CDATA or comment, it's the end of this body.
*/
break loop
}
advance_rune(t)
}
/*
Strip trailing whitespace.
*/
lit := string(t.src[offset : t.offset])
end := len(lit)
eat: for ; end > 0; end -= 1 {
ch := lit[end - 1]
switch ch {
case ' ', '\t', '\r', '\n':
case:
break eat
}
}
lit = lit[:end]
if consume_close {
advance_rune(t)
}
/*
TODO: Handle decoding escape characters and unboxing CDATA.
*/
return lit, err
}
peek :: proc(t: ^Tokenizer) -> (token: Token) {
old := t^
token = scan(t)
t^ = old
return token
}
scan :: proc(t: ^Tokenizer) -> Token {
skip_whitespace(t)
offset := t.offset
kind: Token_Kind
err: Error
lit: string
pos := offset_to_pos(t, offset)
switch ch := t.ch; true {
case is_letter(ch):
lit = scan_identifier(t)
kind = .Ident
case:
advance_rune(t)
switch ch {
case -1:
kind = .EOF
case '<': kind = .Lt
case '>': kind = .Gt
case '!': kind = .Exclaim
case '?': kind = .Question
case '=': kind = .Eq
case '#': kind = .Hash
case '/': kind = .Slash
case '-': kind = .Dash
case ':': kind = .Colon
case '"', '\'':
kind = .Invalid
lit, err = scan_string(t, t.offset, ch, true, false)
if err == .None {
kind = .String
}
case '\n':
lit = "\n"
case:
kind = .Invalid
}
}
if kind != .String && lit == "" {
lit = string(t.src[offset : t.offset])
}
return Token{kind, lit, pos}
}
+713
View File
@@ -0,0 +1,713 @@
/*
An XML 1.0 / 1.1 parser
Copyright 2021-2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
A from-scratch XML implementation, loosely modelled on the [spec](https://www.w3.org/TR/2006/REC-xml11-20060816).
Features:
- Supports enough of the XML 1.0/1.1 spec to handle the 99.9% of XML documents in common current usage.
- Simple to understand and use. Small.
Caveats:
- We do NOT support HTML in this package, as that may or may not be valid XML.
If it works, great. If it doesn't, that's not considered a bug.
- We do NOT support UTF-16. If you have a UTF-16 XML file, please convert it to UTF-8 first. Also, our condolences.
- <[!ELEMENT and <[!ATTLIST are not supported, and will be either ignored or return an error depending on the parser options.
MAYBE:
- XML writer?
- Serialize/deserialize Odin types?
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
package xml
// An XML 1.0 / 1.1 parser
import "core:bytes"
import "core:encoding/entity"
import "core:intrinsics"
import "core:mem"
import "core:os"
import "core:strings"
likely :: intrinsics.expect
DEFAULT_OPTIONS :: Options{
flags = {.Ignore_Unsupported},
expected_doctype = "",
}
Option_Flag :: enum {
/*
If the caller says that input may be modified, we can perform in-situ parsing.
If this flag isn't provided, the XML parser first duplicates the input so that it can.
*/
Input_May_Be_Modified,
/*
Document MUST start with `<?xml` prologue.
*/
Must_Have_Prolog,
/*
Document MUST have a `<!DOCTYPE`.
*/
Must_Have_DocType,
/*
By default we skip comments. Use this option to intern a comment on a parented Element.
*/
Intern_Comments,
/*
How to handle unsupported parts of the specification, like <! other than <!DOCTYPE and <![CDATA[
*/
Error_on_Unsupported,
Ignore_Unsupported,
/*
By default CDATA tags are passed-through as-is.
This option unwraps them when encountered.
*/
Unbox_CDATA,
/*
By default SGML entities like `&gt;`, `&#32;` and `&#x20;` are passed-through as-is.
This option decodes them when encountered.
*/
Decode_SGML_Entities,
/*
If a tag body has a comment, it will be stripped unless this option is given.
*/
Keep_Tag_Body_Comments,
}
Option_Flags :: bit_set[Option_Flag; u16]
Document :: struct {
elements: [dynamic]Element,
element_count: Element_ID,
prologue: Attributes,
encoding: Encoding,
doctype: struct {
/*
We only scan the <!DOCTYPE IDENT part and skip the rest.
*/
ident: string,
rest: string,
},
/*
If we encounter comments before the root node, and the option to intern comments is given, this is where they'll live.
Otherwise they'll be in the element tree.
*/
comments: [dynamic]string,
/*
Internal
*/
tokenizer: ^Tokenizer,
allocator: mem.Allocator,
/*
Input. Either the original buffer, or a copy if `.Input_May_Be_Modified` isn't specified.
*/
input: []u8,
strings_to_free: [dynamic]string,
}
Element :: struct {
ident: string,
value: string,
attribs: Attributes,
kind: enum {
Element = 0,
Comment,
},
parent: Element_ID,
children: [dynamic]Element_ID,
}
Attribute :: struct {
key: string,
val: string,
}
Attributes :: [dynamic]Attribute
Options :: struct {
flags: Option_Flags,
expected_doctype: string,
}
Encoding :: enum {
Unknown,
UTF_8,
ISO_8859_1,
/*
Aliases
*/
LATIN_1 = ISO_8859_1,
}
Error :: enum {
/*
General return values.
*/
None = 0,
General_Error,
Unexpected_Token,
Invalid_Token,
/*
Couldn't find, open or read file.
*/
File_Error,
/*
File too short.
*/
Premature_EOF,
/*
XML-specific errors.
*/
No_Prolog,
Invalid_Prolog,
Too_Many_Prologs,
No_DocType,
Too_Many_DocTypes,
DocType_Must_Preceed_Elements,
/*
If a DOCTYPE is present _or_ the caller
asked for a specific DOCTYPE and the DOCTYPE
and root tag don't match, we return `.Invalid_DocType`.
*/
Invalid_DocType,
Invalid_Tag_Value,
Mismatched_Closing_Tag,
Unclosed_Comment,
Comment_Before_Root_Element,
Invalid_Sequence_In_Comment,
Unsupported_Version,
Unsupported_Encoding,
/*
<!FOO are usually skipped.
*/
Unhandled_Bang,
Duplicate_Attribute,
Conflicting_Options,
}
/*
Implementation starts here.
*/
parse_bytes :: proc(data: []u8, options := DEFAULT_OPTIONS, path := "", error_handler := default_error_handler, allocator := context.allocator) -> (doc: ^Document, err: Error) {
data := data
context.allocator = allocator
opts := validate_options(options) or_return
/*
If `.Input_May_Be_Modified` is not specified, we duplicate the input so that we can modify it in-place.
*/
if .Input_May_Be_Modified not_in opts.flags {
data = bytes.clone(data)
}
t := &Tokenizer{}
init(t, string(data), path, error_handler)
doc = new(Document)
doc.allocator = allocator
doc.tokenizer = t
doc.input = data
doc.elements = make([dynamic]Element, 1024, 1024, allocator)
// strings.intern_init(&doc.intern, allocator, allocator)
err = .Unexpected_Token
element, parent: Element_ID
tag_is_open := false
first_element := true
open: Token
/*
If a DOCTYPE is present, the root tag has to match.
If an expected DOCTYPE is given in options (i.e. it's non-empty), the DOCTYPE (if present) and root tag have to match.
*/
expected_doctype := options.expected_doctype
loop: for {
skip_whitespace(t)
// NOTE(Jeroen): This is faster as a switch.
switch t.ch {
case '<':
/*
Consume peeked `<`
*/
advance_rune(t)
open = scan(t)
// NOTE(Jeroen): We're not using a switch because this if-else chain ordered by likelihood is 2.5% faster at -o:size and -o:speed.
if likely(open.kind, Token_Kind.Ident) == .Ident {
/*
e.g. <odin - Start of new element.
*/
element = new_element(doc)
tag_is_open = true
if first_element {
/*
First element.
*/
parent = element
first_element = false
} else {
append(&doc.elements[parent].children, element)
}
doc.elements[element].parent = parent
doc.elements[element].ident = open.text
parse_attributes(doc, &doc.elements[element].attribs) or_return
/*
If a DOCTYPE is present _or_ the caller
asked for a specific DOCTYPE and the DOCTYPE
and root tag don't match, we return .Invalid_Root_Tag.
*/
if element == 0 { // Root tag?
if len(expected_doctype) > 0 && expected_doctype != open.text {
error(t, t.offset, "Root Tag doesn't match DOCTYPE. Expected: %v, got: %v\n", expected_doctype, open.text)
return doc, .Invalid_DocType
}
}
/*
One of these should follow:
- `>`, which means we've just opened this tag and expect a later element to close it.
- `/>`, which means this is an 'empty' or self-closing tag.
*/
end_token := scan(t)
#partial switch end_token.kind {
case .Gt:
/*
We're now the new parent.
*/
parent = element
case .Slash:
/*
Empty tag. Close it.
*/
expect(t, .Gt) or_return
parent = doc.elements[element].parent
element = parent
tag_is_open = false
case:
error(t, t.offset, "Expected close tag, got: %#v\n", end_token)
return
}
} else if open.kind == .Slash {
/*
Close tag.
*/
ident := expect(t, .Ident) or_return
_ = expect(t, .Gt) or_return
if doc.elements[element].ident != ident.text {
error(t, t.offset, "Mismatched Closing Tag. Expected %v, got %v\n", doc.elements[element].ident, ident.text)
return doc, .Mismatched_Closing_Tag
}
parent = doc.elements[element].parent
element = parent
tag_is_open = false
} else if open.kind == .Exclaim {
/*
<!
*/
next := scan(t)
#partial switch next.kind {
case .Ident:
switch next.text {
case "DOCTYPE":
if len(doc.doctype.ident) > 0 {
return doc, .Too_Many_DocTypes
}
if doc.element_count > 0 {
return doc, .DocType_Must_Preceed_Elements
}
parse_doctype(doc) or_return
if len(expected_doctype) > 0 && expected_doctype != doc.doctype.ident {
error(t, t.offset, "Invalid DOCTYPE. Expected: %v, got: %v\n", expected_doctype, doc.doctype.ident)
return doc, .Invalid_DocType
}
expected_doctype = doc.doctype.ident
case:
if .Error_on_Unsupported in opts.flags {
error(t, t.offset, "Unhandled: <!%v\n", next.text)
return doc, .Unhandled_Bang
}
skip_element(t) or_return
}
case .Dash:
/*
Comment: <!-- -->.
The grammar does not allow a comment to end in --->
*/
expect(t, .Dash)
comment := scan_comment(t) or_return
if .Intern_Comments in opts.flags {
if len(doc.elements) == 0 {
append(&doc.comments, comment)
} else {
el := new_element(doc)
doc.elements[el].parent = element
doc.elements[el].kind = .Comment
doc.elements[el].value = comment
append(&doc.elements[element].children, el)
}
}
case:
error(t, t.offset, "Invalid Token after <!. Expected .Ident, got %#v\n", next)
return
}
} else if open.kind == .Question {
/*
<?xml
*/
next := scan(t)
#partial switch next.kind {
case .Ident:
if len(next.text) == 3 && strings.to_lower(next.text, context.temp_allocator) == "xml" {
parse_prologue(doc) or_return
} else if len(doc.prologue) > 0 {
/*
We've already seen a prologue.
*/
return doc, .Too_Many_Prologs
} else {
/*
Could be `<?xml-stylesheet`, etc. Ignore it.
*/
skip_element(t) or_return
}
case:
error(t, t.offset, "Expected \"<?xml\", got \"<?%v\".", next.text)
return
}
} else {
error(t, t.offset, "Invalid Token after <: %#v\n", open)
return
}
case -1:
/*
End of file.
*/
if tag_is_open {
return doc, .Premature_EOF
}
break loop
case:
/*
This should be a tag's body text.
*/
body_text := scan_string(t, t.offset) or_return
needs_processing := .Unbox_CDATA in opts.flags
needs_processing |= .Decode_SGML_Entities in opts.flags
if !needs_processing {
doc.elements[element].value = body_text
continue
}
decode_opts := entity.XML_Decode_Options{}
if .Keep_Tag_Body_Comments not_in opts.flags {
decode_opts += { .Comment_Strip }
}
if .Decode_SGML_Entities not_in opts.flags {
decode_opts += { .No_Entity_Decode }
}
if .Unbox_CDATA in opts.flags {
decode_opts += { .Unbox_CDATA }
if .Decode_SGML_Entities in opts.flags {
decode_opts += { .Decode_CDATA }
}
}
decoded, decode_err := entity.decode_xml(body_text, decode_opts)
if decode_err == .None {
doc.elements[element].value = decoded
append(&doc.strings_to_free, decoded)
} else {
doc.elements[element].value = body_text
}
}
}
if .Must_Have_Prolog in opts.flags && len(doc.prologue) == 0 {
return doc, .No_Prolog
}
if .Must_Have_DocType in opts.flags && len(doc.doctype.ident) == 0 {
return doc, .No_DocType
}
resize(&doc.elements, int(doc.element_count))
return doc, .None
}
parse_string :: proc(data: string, options := DEFAULT_OPTIONS, path := "", error_handler := default_error_handler, allocator := context.allocator) -> (doc: ^Document, err: Error) {
_data := transmute([]u8)data
return parse_bytes(_data, options, path, error_handler, allocator)
}
parse :: proc { parse_string, parse_bytes }
// Load an XML file
load_from_file :: proc(filename: string, options := DEFAULT_OPTIONS, error_handler := default_error_handler, allocator := context.allocator) -> (doc: ^Document, err: Error) {
context.allocator = allocator
options := options
data, data_ok := os.read_entire_file(filename)
if !data_ok { return {}, .File_Error }
options.flags += { .Input_May_Be_Modified }
return parse_bytes(data, options, filename, error_handler, allocator)
}
destroy :: proc(doc: ^Document) {
if doc == nil { return }
for el in doc.elements {
delete(el.attribs)
delete(el.children)
}
delete(doc.elements)
delete(doc.prologue)
delete(doc.comments)
delete(doc.input)
for s in doc.strings_to_free {
delete(s)
}
delete(doc.strings_to_free)
free(doc)
}
/*
Helpers.
*/
validate_options :: proc(options: Options) -> (validated: Options, err: Error) {
validated = options
if .Error_on_Unsupported in validated.flags && .Ignore_Unsupported in validated.flags {
return options, .Conflicting_Options
}
return validated, .None
}
expect :: proc(t: ^Tokenizer, kind: Token_Kind) -> (tok: Token, err: Error) {
tok = scan(t)
if tok.kind == kind { return tok, .None }
error(t, t.offset, "Expected \"%v\", got \"%v\".", kind, tok.kind)
return tok, .Unexpected_Token
}
parse_attribute :: proc(doc: ^Document) -> (attr: Attribute, offset: int, err: Error) {
assert(doc != nil)
context.allocator = doc.allocator
t := doc.tokenizer
key := expect(t, .Ident) or_return
offset = t.offset - len(key.text)
_ = expect(t, .Eq) or_return
value := expect(t, .String) or_return
attr.key = key.text
attr.val = value.text
err = .None
return
}
check_duplicate_attributes :: proc(t: ^Tokenizer, attribs: Attributes, attr: Attribute, offset: int) -> (err: Error) {
for a in attribs {
if attr.key == a.key {
error(t, offset, "Duplicate attribute: %v\n", attr.key)
return .Duplicate_Attribute
}
}
return .None
}
parse_attributes :: proc(doc: ^Document, attribs: ^Attributes) -> (err: Error) {
assert(doc != nil)
context.allocator = doc.allocator
t := doc.tokenizer
for peek(t).kind == .Ident {
attr, offset := parse_attribute(doc) or_return
check_duplicate_attributes(t, attribs^, attr, offset) or_return
append(attribs, attr)
}
skip_whitespace(t)
return .None
}
parse_prologue :: proc(doc: ^Document) -> (err: Error) {
assert(doc != nil)
context.allocator = doc.allocator
t := doc.tokenizer
offset := t.offset
parse_attributes(doc, &doc.prologue) or_return
for attr in doc.prologue {
switch attr.key {
case "version":
switch attr.val {
case "1.0", "1.1":
case:
error(t, offset, "[parse_prologue] Warning: Unhandled XML version: %v\n", attr.val)
}
case "encoding":
switch strings.to_lower(attr.val, context.temp_allocator) {
case "utf-8", "utf8":
doc.encoding = .UTF_8
case "latin-1", "latin1", "iso-8859-1":
doc.encoding = .LATIN_1
case:
/*
Unrecognized encoding, assume UTF-8.
*/
error(t, offset, "[parse_prologue] Warning: Unrecognized encoding: %v\n", attr.val)
}
case:
// Ignored.
}
}
_ = expect(t, .Question) or_return
_ = expect(t, .Gt) or_return
return .None
}
skip_element :: proc(t: ^Tokenizer) -> (err: Error) {
close := 1
loop: for {
tok := scan(t)
#partial switch tok.kind {
case .EOF:
error(t, t.offset, "[skip_element] Premature EOF\n")
return .Premature_EOF
case .Lt:
close += 1
case .Gt:
close -= 1
if close == 0 {
break loop
}
case:
}
}
return .None
}
parse_doctype :: proc(doc: ^Document) -> (err: Error) {
/*
<!DOCTYPE greeting SYSTEM "hello.dtd">
<!DOCTYPE greeting [
<!ELEMENT greeting (#PCDATA)>
]>
*/
assert(doc != nil)
context.allocator = doc.allocator
t := doc.tokenizer
tok := expect(t, .Ident) or_return
doc.doctype.ident = tok.text
skip_whitespace(t)
offset := t.offset
skip_element(t) or_return
/*
-1 because the current offset is that of the closing tag, so the rest of the DOCTYPE tag ends just before it.
*/
doc.doctype.rest = string(t.src[offset : t.offset - 1])
return .None
}
Element_ID :: u32
new_element :: proc(doc: ^Document) -> (id: Element_ID) {
element_space := len(doc.elements)
// Need to resize
if int(doc.element_count) + 1 > element_space {
if element_space < 65536 {
element_space *= 2
} else {
element_space += 65536
}
resize(&doc.elements, element_space)
}
cur := doc.element_count
doc.element_count += 1
return cur
}
+768 -627
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -9,8 +9,8 @@ crc32 :: proc(data: []byte, seed := u32(0)) -> u32 #no_bounds_check {
length := len(data)
for length != 0 && uintptr(buffer) & 7 != 0 {
crc = crc32_table[0][byte(crc) ~ buffer^] ~ (crc >> 8)
buffer = intrinsics.ptr_offset(buffer, 1)
crc = crc32_table[0][byte(crc) ~ buffer[0]] ~ (crc >> 8)
buffer = buffer[1:]
length -= 1
}
@@ -28,14 +28,14 @@ crc32 :: proc(data: []byte, seed := u32(0)) -> u32 #no_bounds_check {
crc32_table[1][buf[6]] ~
crc32_table[0][buf[7]]
buffer = intrinsics.ptr_offset(buffer, 8)
buffer = buffer[8:]
length -= 8
}
for length != 0 {
crc = crc32_table[0][byte(crc) ~ buffer^] ~ (crc >> 8)
buffer = intrinsics.ptr_offset(buffer, 1)
crc = crc32_table[0][byte(crc) ~ buffer[0]] ~ (crc >> 8)
buffer = buffer[1:]
length -= 1
}
+4 -4
View File
@@ -15,7 +15,7 @@ adler32 :: proc(data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
for len(buf) != 0 && uintptr(buffer) & 7 != 0 {
a = (a + u64(buf[0]))
b = (b + a)
buffer = intrinsics.ptr_offset(buffer, 1)
buffer = buffer[1:]
buf = buf[1:]
}
@@ -130,9 +130,9 @@ murmur32 :: proc(data: []byte, seed := u32(0)) -> u32 {
h1: u32 = seed
nblocks := len(data)/4
p := raw_data(data)
p1 := mem.ptr_offset(p, 4*nblocks)
p1 := p[4*nblocks:]
for ; p < p1; p = mem.ptr_offset(p, 4) {
for ; p < p1; p = p[4:] {
k1 := (cast(^u32)p)^
k1 *= c1_32
@@ -151,7 +151,7 @@ murmur32 :: proc(data: []byte, seed := u32(0)) -> u32 {
k1 ~= u32(tail[2]) << 16
fallthrough
case 2:
k1 ~= u32(tail[2]) << 8
k1 ~= u32(tail[1]) << 8
fallthrough
case 1:
k1 ~= u32(tail[0])
+7 -5
View File
@@ -52,9 +52,6 @@ XXH3_128_reset_with_seed :: proc(state: ^XXH3_state, seed: XXH64_hash) -> (err:
XXH3_64_reset_with_seed :: XXH3_128_reset_with_seed
XXH3_128_update :: proc(state: ^XXH3_state, input: []u8) -> (err: Error) {
if len(input) < XXH3_MIDSIZE_MAX {
return .Error
}
return XXH3_update(state, input, XXH3_accumulate_512, XXH3_scramble_accumulator)
}
XXH3_64_update :: XXH3_128_update
@@ -127,6 +124,7 @@ XXH3_create_state :: proc(allocator := context.allocator) -> (res: ^XXH3_state,
err = nil if mem_error == nil else .Error
XXH3_init_state(state)
XXH3_128_reset(state)
return state, nil
}
@@ -213,7 +211,9 @@ XXH3_update :: #force_inline proc(
length := len(input)
secret := state.custom_secret[:] if len(state.external_secret) == 0 else state.external_secret[:]
assert(len(input) > 0)
if len(input) == 0 {
return
}
state.total_length += u64(length)
assert(state.buffered_size <= XXH3_INTERNAL_BUFFER_SIZE)
@@ -234,7 +234,9 @@ XXH3_update :: #force_inline proc(
*/
if state.buffered_size > 0 {
load_size := int(XXH3_INTERNAL_BUFFER_SIZE - state.buffered_size)
mem_copy(&state.buffer[state.buffered_size], &input[0], load_size)
state_ptr := rawptr(uintptr(raw_data(state.buffer[:])) + uintptr(state.buffered_size))
mem_copy(state_ptr, raw_data(input), load_size)
input = input[load_size:]
XXH3_consume_stripes(
+2 -1
View File
@@ -197,6 +197,7 @@ XXH32 :: proc(input: []u8, seed := XXH32_DEFAULT_SEED) -> (digest: XXH32_hash) {
*/
XXH32_create_state :: proc(allocator := context.allocator) -> (res: ^XXH32_state, err: Error) {
state := new(XXH32_state, allocator)
XXH32_reset_state(state)
return state, .None if state != nil else .Error
}
@@ -258,7 +259,7 @@ XXH32_update :: proc(state: ^XXH32_state, input: []u8) -> (err: Error) {
v3 := state.v3
v4 := state.v4
for len(buf) >= 15 {
for len(buf) >= 16 {
#no_bounds_check v1 = XXH32_round(v1, XXH32_read32(buf, .Unaligned)); buf = buf[4:]
#no_bounds_check v2 = XXH32_round(v2, XXH32_read32(buf, .Unaligned)); buf = buf[4:]
#no_bounds_check v3 = XXH32_round(v3, XXH32_read32(buf, .Unaligned)); buf = buf[4:]
+1
View File
@@ -163,6 +163,7 @@ XXH64 :: proc(input: []u8, seed := XXH64_DEFAULT_SEED) -> (digest: XXH64_hash) {
*/
XXH64_create_state :: proc(allocator := context.allocator) -> (res: ^XXH64_state, err: Error) {
state := new(XXH64_state, allocator)
XXH64_reset_state(state)
return state, .None if state != nil else .Error
}
+887 -24
View File
File diff suppressed because it is too large Load Diff
+61
View File
@@ -0,0 +1,61 @@
package image
import "core:mem"
import "core:os"
import "core:bytes"
Loader_Proc :: #type proc(data: []byte, options: Options, allocator: mem.Allocator) -> (img: ^Image, err: Error)
Destroy_Proc :: #type proc(img: ^Image)
@(private)
_internal_loaders: [Which_File_Type]Loader_Proc
_internal_destroyers: [Which_File_Type]Destroy_Proc
register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) {
assert(loader != nil)
assert(destroyer != nil)
assert(_internal_loaders[kind] == nil)
_internal_loaders[kind] = loader
assert(_internal_destroyers[kind] == nil)
_internal_destroyers[kind] = destroyer
}
load :: proc{
load_from_bytes,
load_from_file,
}
load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
loader := _internal_loaders[which(data)]
if loader == nil {
return nil, .Unsupported_Format
}
return loader(data, options, allocator)
}
load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
data, ok := os.read_entire_file(filename, allocator)
defer delete(data, allocator)
if ok {
return load_from_bytes(data, options, allocator)
} else {
return nil, .Unable_To_Read_File
}
}
destroy :: proc(img: ^Image, allocator := context.allocator) {
if img == nil {
return
}
context.allocator = allocator
destroyer := _internal_destroyers[img.which]
if destroyer != nil {
destroyer(img)
} else {
assert(img.metadata == nil)
bytes.buffer_destroy(&img.pixels)
free(img)
}
}
+33
View File
@@ -0,0 +1,33 @@
/*
Formats:
PBM (P1, P4): Portable Bit Map, stores black and white images (1 channel)
PGM (P2, P5): Portable Gray Map, stores greyscale images (1 channel, 1 or 2 bytes per value)
PPM (P3, P6): Portable Pixel Map, stores colour images (3 channel, 1 or 2 bytes per value)
PAM (P7 ): Portable Arbitrary Map, stores arbitrary channel images (1 or 2 bytes per value)
PFM (Pf, PF): Portable Float Map, stores floating-point images (Pf: 1 channel, PF: 3 channel)
Reading:
All formats fill out header fields `format`, `width`, `height`, `channels`, `depth`
Specific formats use more fields
PGM, PPM, and PAM set `maxval` (maximum of 65535)
PAM sets `tupltype` if there is one, and can set `channels` to any value (not just 1 or 3)
PFM sets `scale` (float equivalent of `maxval`) and `little_endian` (endianness of stored floats)
Currently doesn't support reading multiple images from one binary-format file
Writing:
You can use your own `Netpbm_Info` struct to control how images are written
All formats require the header field `format` to be specified
Additional header fields are required for specific formats
PGM, PPM, and PAM require `maxval` (maximum of 65535)
PAM also uses `tupltype`, though it may be left as default (empty or nil string)
PFM requires `scale`, and optionally `little_endian`
Some syntax differences from the specifications:
`channels` stores the number of values per pixel, what the PAM specification calls `depth`
`depth` instead is the number of bits for a single value (32 for PFM, 16 or 8 otherwise)
`scale` and `little_endian` are separated, so the `header` will always store a positive `scale`
`little_endian` will only be true for a negative `scale` PFM, every other format will be false
`little_endian` only describes the netpbm data being read/written, the image buffer will be native
*/
package netpbm
+27
View File
@@ -0,0 +1,27 @@
package netpbm
import "core:bytes"
import "core:image"
destroy :: proc(img: ^image.Image) -> bool {
if img == nil do return false
defer free(img)
bytes.buffer_destroy(&img.pixels)
info, ok := img.metadata.(^image.Netpbm_Info)
if !ok do return false
header_destroy(&info.header)
free(info)
img.metadata = nil
return true
}
header_destroy :: proc(using header: ^Header) {
if format == .P7 && tupltype != "" {
delete(tupltype)
tupltype = ""
}
}
+763
View File
@@ -0,0 +1,763 @@
package netpbm
import "core:bytes"
import "core:fmt"
import "core:image"
import "core:mem"
import "core:os"
import "core:strconv"
import "core:strings"
import "core:unicode"
Image :: image.Image
Format :: image.Netpbm_Format
Header :: image.Netpbm_Header
Info :: image.Netpbm_Info
Error :: image.Error
Format_Error :: image.Netpbm_Error
Formats :: bit_set[Format]
PBM :: Formats{.P1, .P4}
PGM :: Formats{.P2, .P5}
PPM :: Formats{.P3, .P6}
PNM :: PBM + PGM + PPM
PAM :: Formats{.P7}
PFM :: Formats{.Pf, .PF}
ASCII :: Formats{.P1, .P2, .P3}
BINARY :: Formats{.P4, .P5, .P6} + PAM + PFM
load :: proc {
load_from_file,
load_from_bytes,
}
load_from_file :: proc(filename: string, allocator := context.allocator) -> (img: ^Image, err: Error) {
context.allocator = allocator
data, ok := os.read_entire_file(filename); defer delete(data)
if !ok {
err = .Unable_To_Read_File
return
}
return load_from_bytes(data)
}
load_from_bytes :: proc(data: []byte, allocator := context.allocator) -> (img: ^Image, err: Error) {
context.allocator = allocator
img = new(Image)
img.which = .NetPBM
header: Header; defer header_destroy(&header)
header_size: int
header, header_size = parse_header(data) or_return
img_data := data[header_size:]
decode_image(img, header, img_data) or_return
info := new(Info)
info.header = header
if header.format == .P7 && header.tupltype != "" {
info.header.tupltype = strings.clone(header.tupltype)
}
img.metadata = info
return img, nil
}
save :: proc {
save_to_file,
save_to_buffer,
}
save_to_file :: proc(filename: string, img: ^Image, custom_info: Info = {}, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator
data: []byte; defer delete(data)
data = save_to_buffer(img, custom_info) or_return
if ok := os.write_entire_file(filename, data); !ok {
return .Unable_To_Write_File
}
return Format_Error.None
}
save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context.allocator) -> (buffer: []byte, err: Error) {
context.allocator = allocator
info: Info = {}
if custom_info.header.width > 0 {
// Custom info has been set, use it.
info = custom_info
} else {
img_info, ok := img.metadata.(^image.Netpbm_Info)
if !ok {
// image doesn't have .Netpbm info, guess it
auto_info, auto_info_found := autoselect_pbm_format_from_image(img)
if auto_info_found {
info = auto_info
} else {
return {}, .Invalid_Input_Image
}
} else {
// use info as stored on image
info = img_info^
}
}
// using info so we can just talk about the header
using info
// validation
if header.format in (PBM + PGM + Formats{.Pf}) && img.channels != 1 \
|| header.format in (PPM + Formats{.PF}) && img.channels != 3 {
err = .Invalid_Number_Of_Channels
return
}
if header.format in (PNM + PAM) {
if header.maxval <= int(max(u8)) && img.depth != 8 \
|| header.maxval > int(max(u8)) && header.maxval <= int(max(u16)) && img.depth != 16 {
err = .Invalid_Image_Depth
return
}
} else if header.format in PFM && img.depth != 32 {
err = .Invalid_Image_Depth
return
}
// we will write to a string builder
data: strings.Builder
strings.init_builder(&data)
// all PNM headers start with the format
fmt.sbprintf(&data, "%s\n", header.format)
if header.format in PNM {
fmt.sbprintf(&data, "%i %i\n", img.width, img.height)
if header.format not_in PBM {
fmt.sbprintf(&data, "%i\n", header.maxval)
}
} else if header.format in PAM {
if len(header.tupltype) > 0 {
fmt.sbprintf(&data, "WIDTH %i\nHEIGHT %i\nMAXVAL %i\nDEPTH %i\nTUPLTYPE %s\nENDHDR\n",
img.width, img.height, header.maxval, img.channels, header.tupltype)
} else {
fmt.sbprintf(&data, "WIDTH %i\nHEIGHT %i\nMAXVAL %i\nDEPTH %i\nENDHDR\n",
img.width, img.height, header.maxval, img.channels)
}
} else if header.format in PFM {
scale := -header.scale if header.little_endian else header.scale
fmt.sbprintf(&data, "%i %i\n%f\n", img.width, img.height, scale)
}
switch header.format {
// Compressed binary
case .P4:
header_buf := data.buf[:]
pixels := img.pixels.buf[:]
p4_buffer_size := (img.width / 8 + 1) * img.height
reserve(&data.buf, len(header_buf) + p4_buffer_size)
// we build up a byte value until it is completely filled
// or we reach the end the row
for y in 0 ..< img.height {
b: byte
for x in 0 ..< img.width {
i := y * img.width + x
bit := byte(7 - (x % 8))
v : byte = 0 if pixels[i] == 0 else 1
b |= (v << bit)
if bit == 0 {
append(&data.buf, b)
b = 0
}
}
if b != 0 {
append(&data.buf, b)
b = 0
}
}
// Simple binary
case .P5, .P6, .P7, .Pf, .PF:
header_buf := data.buf[:]
pixels := img.pixels.buf[:]
resize(&data.buf, len(header_buf) + len(pixels))
mem.copy(raw_data(data.buf[len(header_buf):]), raw_data(pixels), len(pixels))
// convert from native endianness
if img.depth == 16 {
pixels := mem.slice_data_cast([]u16be, data.buf[len(header_buf):])
for p in &pixels {
p = u16be(transmute(u16) p)
}
} else if header.format in PFM {
if header.little_endian {
pixels := mem.slice_data_cast([]f32le, data.buf[len(header_buf):])
for p in &pixels {
p = f32le(transmute(f32) p)
}
} else {
pixels := mem.slice_data_cast([]f32be, data.buf[len(header_buf):])
for p in &pixels {
p = f32be(transmute(f32) p)
}
}
}
// If-it-looks-like-a-bitmap ASCII
case .P1:
pixels := img.pixels.buf[:]
for y in 0 ..< img.height {
for x in 0 ..< img.width {
i := y * img.width + x
append(&data.buf, '0' if pixels[i] == 0 else '1')
}
append(&data.buf, '\n')
}
// Token ASCII
case .P2, .P3:
switch img.depth {
case 8:
pixels := img.pixels.buf[:]
for y in 0 ..< img.height {
for x in 0 ..< img.width {
i := y * img.width + x
for c in 0 ..< img.channels {
i := i * img.channels + c
fmt.sbprintf(&data, "%i ", pixels[i])
}
fmt.sbprint(&data, "\n")
}
fmt.sbprint(&data, "\n")
}
case 16:
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
for y in 0 ..< img.height {
for x in 0 ..< img.width {
i := y * img.width + x
for c in 0 ..< img.channels {
i := i * img.channels + c
fmt.sbprintf(&data, "%i ", pixels[i])
}
fmt.sbprint(&data, "\n")
}
fmt.sbprint(&data, "\n")
}
case:
return data.buf[:], .Invalid_Image_Depth
}
case:
return data.buf[:], .Invalid_Format
}
return data.buf[:], Format_Error.None
}
parse_header :: proc(data: []byte, allocator := context.allocator) -> (header: Header, length: int, err: Error) {
context.allocator = allocator
// we need the signature and a space
if len(data) < 3 {
err = Format_Error.Incomplete_Header
return
}
if data[0] == 'P' {
switch data[1] {
case '1' ..= '6':
return _parse_header_pnm(data)
case '7':
return _parse_header_pam(data, allocator)
case 'F', 'f':
return _parse_header_pfm(data)
}
}
err = .Invalid_Signature
return
}
@(private)
_parse_header_pnm :: proc(data: []byte) -> (header: Header, length: int, err: Error) {
SIG_LENGTH :: 2
{
header_formats := []Format{.P1, .P2, .P3, .P4, .P5, .P6}
header.format = header_formats[data[1] - '0' - 1]
}
// have a list of fielda for easy iteration
header_fields: []^int
if header.format in PBM {
header_fields = {&header.width, &header.height}
header.maxval = 1 // we know maxval for a bitmap
} else {
header_fields = {&header.width, &header.height, &header.maxval}
}
// we're keeping track of the header byte length
length = SIG_LENGTH
// loop state
in_comment := false
already_in_space := true
current_field := 0
current_value := header_fields[0]
parse_loop: for d, i in data[SIG_LENGTH:] {
length += 1
// handle comments
if in_comment {
switch d {
// comments only go up to next carriage return or line feed
case '\r', '\n':
in_comment = false
}
continue
} else if d == '#' {
in_comment = true
continue
}
// handle whitespace
in_space := unicode.is_white_space(rune(d))
if in_space {
if already_in_space {
continue
}
already_in_space = true
// switch to next value
current_field += 1
if current_field == len(header_fields) {
// header byte length is 1-index so we'll increment again
length += 1
break parse_loop
}
current_value = header_fields[current_field]
} else {
already_in_space = false
if !unicode.is_digit(rune(d)) {
err = Format_Error.Invalid_Header_Token_Character
return
}
val := int(d - '0')
current_value^ = current_value^ * 10 + val
}
}
// set extra info
header.channels = 3 if header.format in PPM else 1
header.depth = 16 if header.maxval > int(max(u8)) else 8
// limit checking
if current_field < len(header_fields) {
err = Format_Error.Incomplete_Header
return
}
if header.width < 1 \
|| header.height < 1 \
|| header.maxval < 1 || header.maxval > int(max(u16)) {
fmt.printf("[pnm] Header: {{width = %v, height = %v, maxval: %v}}\n", header.width, header.height, header.maxval)
err = .Invalid_Header_Value
return
}
length -= 1
err = Format_Error.None
return
}
@(private)
_parse_header_pam :: proc(data: []byte, allocator := context.allocator) -> (header: Header, length: int, err: Error) {
context.allocator = allocator
// the spec needs the newline apparently
if string(data[0:3]) != "P7\n" {
err = .Invalid_Signature
return
}
header.format = .P7
SIGNATURE_LENGTH :: 3
HEADER_END :: "ENDHDR\n"
// we can already work out the size of the header
header_end_index := strings.index(string(data), HEADER_END)
if header_end_index == -1 {
err = Format_Error.Incomplete_Header
return
}
length = header_end_index + len(HEADER_END)
// string buffer for the tupltype
tupltype: strings.Builder
strings.init_builder(&tupltype, context.temp_allocator); defer strings.destroy_builder(&tupltype)
fmt.sbprint(&tupltype, "")
// PAM uses actual lines, so we can iterate easily
line_iterator := string(data[SIGNATURE_LENGTH : header_end_index])
parse_loop: for line in strings.split_lines_iterator(&line_iterator) {
line := line
if len(line) == 0 || line[0] == '#' {
continue
}
field, ok := strings.fields_iterator(&line)
value := strings.trim_space(line)
// the field will change, but the logic stays the same
current_field: ^int
switch field {
case "WIDTH": current_field = &header.width
case "HEIGHT": current_field = &header.height
case "DEPTH": current_field = &header.channels
case "MAXVAL": current_field = &header.maxval
case "TUPLTYPE":
if len(value) == 0 {
err = .Invalid_Header_Value
return
}
if len(tupltype.buf) == 0 {
fmt.sbprint(&tupltype, value)
} else {
fmt.sbprint(&tupltype, "", value)
}
continue
case:
continue
}
if current_field^ != 0 {
err = Format_Error.Duplicate_Header_Field
return
}
current_field^, ok = strconv.parse_int(value)
if !ok {
err = Format_Error.Invalid_Header_Value
return
}
}
// extra info
header.depth = 16 if header.maxval > int(max(u8)) else 8
// limit checking
if header.width < 1 \
|| header.height < 1 \
|| header.maxval < 1 \
|| header.maxval > int(max(u16)) {
fmt.printf("[pam] Header: {{width = %v, height = %v, maxval: %v}}\n", header.width, header.height, header.maxval)
err = Format_Error.Invalid_Header_Value
return
}
header.tupltype = strings.clone(strings.to_string(tupltype))
err = Format_Error.None
return
}
@(private)
_parse_header_pfm :: proc(data: []byte) -> (header: Header, length: int, err: Error) {
// we can just cycle through tokens for PFM
field_iterator := string(data)
field, ok := strings.fields_iterator(&field_iterator)
switch field {
case "Pf":
header.format = .Pf
header.channels = 1
case "PF":
header.format = .PF
header.channels = 3
case:
err = .Invalid_Signature
return
}
// floating point
header.depth = 32
// width
field, ok = strings.fields_iterator(&field_iterator)
if !ok {
err = Format_Error.Incomplete_Header
return
}
header.width, ok = strconv.parse_int(field)
if !ok {
err = Format_Error.Invalid_Header_Value
return
}
// height
field, ok = strings.fields_iterator(&field_iterator)
if !ok {
err = Format_Error.Incomplete_Header
return
}
header.height, ok = strconv.parse_int(field)
if !ok {
err = Format_Error.Invalid_Header_Value
return
}
// scale (sign is endianness)
field, ok = strings.fields_iterator(&field_iterator)
if !ok {
err = Format_Error.Incomplete_Header
return
}
header.scale, ok = strconv.parse_f32(field)
if !ok {
err = Format_Error.Invalid_Header_Value
return
}
if header.scale < 0.0 {
header.little_endian = true
header.scale = -header.scale
}
// pointer math to get header size
length = int((uintptr(raw_data(field_iterator)) + 1) - uintptr(raw_data(data)))
// limit checking
if header.width < 1 \
|| header.height < 1 \
|| header.scale == 0.0 {
fmt.printf("[pfm] Header: {{width = %v, height = %v, scale: %v}}\n", header.width, header.height, header.scale)
err = .Invalid_Header_Value
return
}
err = Format_Error.None
return
}
decode_image :: proc(img: ^Image, header: Header, data: []byte, allocator := context.allocator) -> (err: Error) {
assert(img != nil)
context.allocator = allocator
img.width = header.width
img.height = header.height
img.channels = header.channels
img.depth = header.depth
buffer_size := image.compute_buffer_size(img.width, img.height, img.channels, img.depth)
// we can check data size for binary formats
if header.format in BINARY {
if len(data) < buffer_size {
fmt.printf("len(data): %v, buffer size: %v\n", len(data), buffer_size)
return .Buffer_Too_Small
}
}
// for ASCII and P4, we use length for the termination condition, so start at 0
// BINARY will be a simple memcopy so the buffer length should also be initialised
if header.format in ASCII || header.format == .P4 {
bytes.buffer_init_allocator(&img.pixels, 0, buffer_size)
} else {
bytes.buffer_init_allocator(&img.pixels, buffer_size, buffer_size)
}
switch header.format {
// Compressed binary
case .P4:
for d in data {
for b in 1 ..= 8 {
bit := byte(8 - b)
pix := (d >> bit) & 1
bytes.buffer_write_byte(&img.pixels, pix)
if len(img.pixels.buf) % img.width == 0 {
break
}
}
if len(img.pixels.buf) == cap(img.pixels.buf) {
break
}
}
// Simple binary
case .P5, .P6, .P7, .Pf, .PF:
copy(img.pixels.buf[:], data[:])
// convert to native endianness
if header.format in PFM {
pixels := mem.slice_data_cast([]f32, img.pixels.buf[:])
if header.little_endian {
for p in &pixels {
p = f32(transmute(f32le) p)
}
} else {
for p in &pixels {
p = f32(transmute(f32be) p)
}
}
} else {
if img.depth == 16 {
pixels := mem.slice_data_cast([]u16, img.pixels.buf[:])
for p in &pixels {
p = u16(transmute(u16be) p)
}
}
}
// If-it-looks-like-a-bitmap ASCII
case .P1:
for c in data {
switch c {
case '0', '1':
bytes.buffer_write_byte(&img.pixels, c - '0')
}
if len(img.pixels.buf) == cap(img.pixels.buf) {
break
}
}
if len(img.pixels.buf) < cap(img.pixels.buf) {
err = Format_Error.Buffer_Too_Small
return
}
// Token ASCII
case .P2, .P3:
field_iterator := string(data)
for field in strings.fields_iterator(&field_iterator) {
value, ok := strconv.parse_int(field)
if !ok {
err = Format_Error.Invalid_Buffer_ASCII_Token
return
}
//? do we want to enforce the maxval, the limit, or neither
if value > int(max(u16)) /*header.maxval*/ {
err = Format_Error.Invalid_Buffer_Value
return
}
switch img.depth {
case 8:
bytes.buffer_write_byte(&img.pixels, u8(value))
case 16:
vb := transmute([2]u8) u16(value)
bytes.buffer_write(&img.pixels, vb[:])
}
if len(img.pixels.buf) == cap(img.pixels.buf) {
break
}
}
if len(img.pixels.buf) < cap(img.pixels.buf) {
err = Format_Error.Buffer_Too_Small
return
}
}
err = Format_Error.None
return
}
// Automatically try to select an appropriate format to save to based on `img.channel` and `img.depth`
autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, force_black_and_white := false, pfm_scale := f32(1.0)) -> (res: Info, ok: bool) {
/*
PBM (P1, P4): Portable Bit Map, stores black and white images (1 channel)
PGM (P2, P5): Portable Gray Map, stores greyscale images (1 channel, 1 or 2 bytes per value)
PPM (P3, P6): Portable Pixel Map, stores colour images (3 channel, 1 or 2 bytes per value)
PAM (P7 ): Portable Arbitrary Map, stores arbitrary channel images (1 or 2 bytes per value)
PFM (Pf, PF): Portable Float Map, stores floating-point images (Pf: 1 channel, PF: 3 channel)
ASCII :: Formats{.P1, .P2, .P3}
*/
using res.header
width = img.width
height = img.height
channels = img.channels
depth = img.depth
maxval = 255 if img.depth == 8 else 65535
little_endian = true if ODIN_ENDIAN == .Little else false
// Assume we'll find a suitable format
ok = true
switch img.channels {
case 1:
// Must be Portable Float Map
if img.depth == 32 {
format = .Pf
return
}
if force_black_and_white {
// Portable Bit Map
format = .P4 if prefer_binary else .P1
maxval = 1
return
} else {
// Portable Gray Map
format = .P5 if prefer_binary else .P2
return
}
case 3:
// Must be Portable Float Map
if img.depth == 32 {
format = .PF
return
}
// Portable Pixel Map
format = .P6 if prefer_binary else .P3
return
case:
// Portable Arbitrary Map
if img.depth == 8 || img.depth == 16 {
format = .P7
scale = pfm_scale
return
}
}
// We couldn't find a suitable format
return {}, false
}
@(init, private)
_register :: proc() {
loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) {
return load_from_bytes(data, allocator)
}
destroyer :: proc(img: ^Image) {
_ = destroy(img)
}
image.register(.NetPBM, loader, destroyer)
}
+1 -1
View File
@@ -207,7 +207,7 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b
}
mode: int = 0
when ODIN_OS == "linux" || ODIN_OS == "darwin" {
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
// NOTE(justasd): 644 (owner read, write; group read; others read)
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
}
+10 -11
View File
@@ -242,17 +242,16 @@ srgb :: proc(c: image.PNG_Chunk) -> (res: sRGB, ok: bool) {
}
plte :: proc(c: image.PNG_Chunk) -> (res: PLTE, ok: bool) {
if c.header.type != .PLTE {
if c.header.type != .PLTE || c.header.length % 3 != 0 || c.header.length > 768 {
return {}, false
}
i := 0; j := 0; ok = true
for j < int(c.header.length) {
res.entries[i] = {c.data[j], c.data[j+1], c.data[j+2]}
i += 1; j += 3
plte := mem.slice_data_cast([]image.RGB_Pixel, c.data[:])
for color, i in plte {
res.entries[i] = color
}
res.used = u16(i)
return
res.used = u16(len(plte))
return res, true
}
splt :: proc(c: image.PNG_Chunk) -> (res: sPLT, ok: bool) {
@@ -439,18 +438,18 @@ when false {
flags: int = O_WRONLY|O_CREATE|O_TRUNC
if len(image.pixels) == 0 || len(image.pixels) < image.width * image.height * int(image.channels) {
return E_PNG.Invalid_Image_Dimensions
return .Invalid_Image_Dimensions
}
mode: int = 0
when ODIN_OS == "linux" || ODIN_OS == "darwin" {
when ODIN_OS == .Linux || ODIN_OS == .Darwin {
// NOTE(justasd): 644 (owner read, write; group read; others read)
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
}
fd, fderr := open(filename, flags, mode)
if fderr != 0 {
return E_General.Cannot_Open_File
return .Cannot_Open_File
}
defer close(fd)
@@ -473,7 +472,7 @@ when false {
case 3: ihdr.color_type = Color_Type{.Color}
case 4: ihdr.color_type = Color_Type{.Color, .Alpha}
case:// Unhandled
return E_PNG.Unknown_Color_Type
return .Unknown_Color_Type
}
h := make_chunk(ihdr, .IHDR)
write_chunk(fd, h)
+59 -46
View File
@@ -18,23 +18,16 @@ import "core:compress/zlib"
import "core:image"
import "core:os"
import "core:strings"
import "core:hash"
import "core:bytes"
import "core:io"
import "core:mem"
import "core:intrinsics"
/*
67_108_864 pixels max by default.
Maximum allowed dimensions are capped at 65535 * 65535.
*/
MAX_DIMENSIONS :: min(#config(PNG_MAX_DIMENSIONS, 8192 * 8192), 65535 * 65535)
// Limit chunk sizes.
// By default: IDAT = 8k x 8k x 16-bits + 8k filter bytes.
// The total number of pixels defaults to 64 Megapixel and can be tuned in image/common.odin.
/*
Limit chunk sizes.
By default: IDAT = 8k x 8k x 16-bits + 8k filter bytes.
*/
_MAX_IDAT_DEFAULT :: ( 8192 /* Width */ * 8192 /* Height */ * 2 /* 16-bit */) + 8192 /* Filter bytes */
_MAX_IDAT :: (65535 /* Width */ * 65535 /* Height */ * 2 /* 16-bit */) + 65535 /* Filter bytes */
@@ -64,7 +57,7 @@ Row_Filter :: enum u8 {
Paeth = 4,
}
PLTE_Entry :: [3]u8
PLTE_Entry :: image.RGB_Pixel
PLTE :: struct #packed {
entries: [256]PLTE_Entry,
@@ -244,7 +237,7 @@ append_chunk :: proc(list: ^[dynamic]image.PNG_Chunk, src: image.PNG_Chunk, allo
append(list, c)
if len(list) != length + 1 {
// Resize during append failed.
return mem.Allocator_Error.Out_Of_Memory
return .Unable_To_Allocate_Or_Resize
}
return
@@ -259,7 +252,7 @@ read_header :: proc(ctx: ^$C) -> (image.PNG_IHDR, Error) {
header := (^image.PNG_IHDR)(raw_data(c.data))^
// Validate IHDR
using header
if width == 0 || height == 0 || u128(width) * u128(height) > MAX_DIMENSIONS {
if width == 0 || height == 0 || u128(width) * u128(height) > image.MAX_DIMENSIONS {
return {}, .Invalid_Image_Dimensions
}
@@ -324,13 +317,12 @@ read_header :: proc(ctx: ^$C) -> (image.PNG_IHDR, Error) {
}
chunk_type_to_name :: proc(type: ^image.PNG_Chunk_Type) -> string {
t := transmute(^u8)type
return strings.string_from_ptr(t, 4)
return string(([^]u8)(type)[:4])
}
load_from_slice :: proc(slice: []u8, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
ctx := &compress.Context_Memory_Input{
input_data = slice,
input_data = data,
}
/*
@@ -350,10 +342,9 @@ load_from_file :: proc(filename: string, options := Options{}, allocator := cont
defer delete(data)
if ok {
return load_from_slice(data, options)
return load_from_bytes(data, options)
} else {
img = new(Image)
return img, compress.General_Error.File_Not_Found
return nil, .Unable_To_Read_File
}
}
@@ -366,6 +357,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
options -= {.info}
}
if .return_header in options && .return_metadata in options {
options -= {.return_header}
}
if .alpha_drop_if_present in options && .alpha_add_if_missing in options {
return {}, compress.General_Error.Incompatible_Options
}
@@ -377,13 +372,14 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
if img == nil {
img = new(Image)
}
img.which = .PNG
info := new(image.PNG_Info)
img.metadata = info
signature, io_error := compress.read_data(ctx, Signature)
if io_error != .None || signature != .PNG {
return img, .Invalid_PNG_Signature
return img, .Invalid_Signature
}
idat: []u8
@@ -392,7 +388,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
idat_length := u64(0)
c: image.PNG_Chunk
c: image.PNG_Chunk
ch: image.PNG_Chunk_Header
e: io.Error
@@ -473,6 +469,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
}
info.header = h
if .return_header in options && .return_metadata not_in options && .do_not_decompress_image not_in options {
return img, nil
}
case .PLTE:
seen_plte = true
// PLTE must appear before IDAT and can't appear for color types 0, 4.
@@ -540,9 +540,6 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
seen_iend = true
case .bKGD:
// TODO: Make sure that 16-bit bKGD + tRNS chunks return u16 instead of u16be
c = read_chunk(ctx) or_return
seen_bkgd = true
if .return_metadata in options {
@@ -594,23 +591,36 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
*/
final_image_channels += 1
seen_trns = true
if .Paletted in header.color_type {
if len(c.data) > 256 {
return img, .TNRS_Invalid_Length
}
} else if .Color in header.color_type {
if len(c.data) != 6 {
return img, .TNRS_Invalid_Length
}
} else if len(c.data) != 2 {
return img, .TNRS_Invalid_Length
}
if info.header.bit_depth < 8 && .Paletted not_in info.header.color_type {
// Rescale tRNS data so key matches intensity
dsc := depth_scale_table
dsc := depth_scale_table
scale := dsc[info.header.bit_depth]
if scale != 1 {
key := mem.slice_data_cast([]u16be, c.data)[0] * u16be(scale)
c.data = []u8{0, u8(key & 255)}
}
}
trns = c
case .iDOT, .CbGI:
case .iDOT, .CgBI:
/*
iPhone PNG bastardization that doesn't adhere to spec with broken IDAT chunk.
We're not going to add support for it. If you have the misfortunte of coming
We're not going to add support for it. If you have the misfortune of coming
across one of these files, use a utility to defry it.
*/
return img, .Image_Does_Not_Adhere_to_Spec
@@ -635,6 +645,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, .IDAT_Missing
}
if .Paletted in header.color_type && !seen_plte {
return img, .PLTE_Missing
}
/*
Calculate the expected output size, to help `inflate` make better decisions about the output buffer.
We'll also use it to check the returned buffer size is what we expected it to be.
@@ -683,15 +697,6 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return {}, defilter_error
}
/*
Now we'll handle the relocoring of paletted images, handling of tRNS chunks,
and we'll expand grayscale images to RGB(A).
For the sake of convenience we return only RGB(A) images. In the future we
may supply an option to return Gray/Gray+Alpha as-is, in which case RGB(A)
will become the default.
*/
if .Paletted in header.color_type && .do_not_expand_indexed in options {
return img, nil
}
@@ -699,7 +704,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, nil
}
/*
Now we're going to optionally apply various post-processing stages,
to for example expand grayscale, apply a palette, premultiply alpha, etc.
*/
raw_image_channels := img.channels
out_image_channels := 3
@@ -737,7 +745,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) {
return {}, mem.Allocator_Error.Out_Of_Memory
return {}, .Unable_To_Allocate_Or_Resize
}
i := 0; j := 0
@@ -818,7 +826,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16)
t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) {
return {}, mem.Allocator_Error.Out_Of_Memory
return {}, .Unable_To_Allocate_Or_Resize
}
p16 := mem.slice_data_cast([]u16, temp.buf[:])
@@ -1017,7 +1025,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) {
return {}, mem.Allocator_Error.Out_Of_Memory
return {}, .Unable_To_Allocate_Or_Resize
}
p := mem.slice_data_cast([]u8, temp.buf[:])
@@ -1204,7 +1212,6 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, nil
}
filter_paeth :: #force_inline proc(left, up, up_left: u8) -> u8 {
aa, bb, cc := i16(left), i16(up), i16(up_left)
p := aa + bb - cc
@@ -1526,7 +1533,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8)
if !resize(&img.pixels.buf, num_bytes) {
return mem.Allocator_Error.Out_Of_Memory
return .Unable_To_Allocate_Or_Resize
}
filter_ok: bool
@@ -1568,7 +1575,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
temp: bytes.Buffer
temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8)
if !resize(&temp.buf, temp_len) {
return mem.Allocator_Error.Out_Of_Memory
return .Unable_To_Allocate_Or_Resize
}
params := Filter_Params{
@@ -1630,4 +1637,10 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
return nil
}
load :: proc{load_from_file, load_from_slice, load_from_context}
load :: proc{load_from_file, load_from_bytes, load_from_context}
@(init, private)
_register :: proc() {
image.register(.PNG, load_from_bytes, destroy)
}
+411
View File
@@ -0,0 +1,411 @@
/*
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
// package qoi implements a QOI image reader
//
// The QOI specification is at https://qoiformat.org.
package qoi
import "core:image"
import "core:compress"
import "core:bytes"
import "core:os"
Error :: image.Error
Image :: image.Image
Options :: image.Options
RGB_Pixel :: image.RGB_Pixel
RGBA_Pixel :: image.RGBA_Pixel
save_to_memory :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator
if img == nil {
return .Invalid_Input_Image
}
if output == nil {
return .Invalid_Output
}
pixels := img.width * img.height
if pixels == 0 || pixels > image.MAX_DIMENSIONS {
return .Invalid_Input_Image
}
// QOI supports only 8-bit images with 3 or 4 channels.
if img.depth != 8 || img.channels < 3 || img.channels > 4 {
return .Invalid_Input_Image
}
if img.channels * pixels != len(img.pixels.buf) {
return .Invalid_Input_Image
}
written := 0
// Calculate and allocate maximum size. We'll reclaim space to actually written output at the end.
max_size := pixels * (img.channels + 1) + size_of(image.QOI_Header) + size_of(u64be)
if !resize(&output.buf, max_size) {
return .Unable_To_Allocate_Or_Resize
}
header := image.QOI_Header{
magic = image.QOI_Magic,
width = u32be(img.width),
height = u32be(img.height),
channels = u8(img.channels),
color_space = .Linear if .qoi_all_channels_linear in options else .sRGB,
}
header_bytes := transmute([size_of(image.QOI_Header)]u8)header
copy(output.buf[written:], header_bytes[:])
written += size_of(image.QOI_Header)
/*
Encode loop starts here.
*/
seen: [64]RGBA_Pixel
pix := RGBA_Pixel{0, 0, 0, 255}
prev := pix
seen[qoi_hash(pix)] = pix
input := img.pixels.buf[:]
run := u8(0)
for len(input) > 0 {
if img.channels == 4 {
pix = (^RGBA_Pixel)(raw_data(input))^
} else {
pix.rgb = (^RGB_Pixel)(raw_data(input))^
}
input = input[img.channels:]
if pix == prev {
run += 1
// As long as the pixel matches the last one, accumulate the run total.
// If we reach the max run length or the end of the image, write the run.
if run == 62 || len(input) == 0 {
// Encode and write run
output.buf[written] = u8(QOI_Opcode_Tag.RUN) | (run - 1)
written += 1
run = 0
}
} else {
if run > 0 {
// The pixel differs from the previous one, but we still need to write the pending run.
// Encode and write run
output.buf[written] = u8(QOI_Opcode_Tag.RUN) | (run - 1)
written += 1
run = 0
}
index := qoi_hash(pix)
if seen[index] == pix {
// Write indexed pixel
output.buf[written] = u8(QOI_Opcode_Tag.INDEX) | index
written += 1
} else {
// Add pixel to index
seen[index] = pix
// If the alpha matches the previous pixel's alpha, we don't need to write a full RGBA literal.
if pix.a == prev.a {
// Delta
d := pix.rgb - prev.rgb
// DIFF, biased and modulo 256
_d := d + 2
// LUMA, biased and modulo 256
_l := RGB_Pixel{ d.r - d.g + 8, d.g + 32, d.b - d.g + 8 }
if _d.r < 4 && _d.g < 4 && _d.b < 4 {
// Delta is between -2 and 1 inclusive
output.buf[written] = u8(QOI_Opcode_Tag.DIFF) | _d.r << 4 | _d.g << 2 | _d.b
written += 1
} else if _l.r < 16 && _l.g < 64 && _l.b < 16 {
// Biased luma is between {-8..7, -32..31, -8..7}
output.buf[written ] = u8(QOI_Opcode_Tag.LUMA) | _l.g
output.buf[written + 1] = _l.r << 4 | _l.b
written += 2
} else {
// Write RGB literal
output.buf[written] = u8(QOI_Opcode_Tag.RGB)
pix_bytes := transmute([4]u8)pix
copy(output.buf[written + 1:], pix_bytes[:3])
written += 4
}
} else {
// Write RGBA literal
output.buf[written] = u8(QOI_Opcode_Tag.RGBA)
pix_bytes := transmute([4]u8)pix
copy(output.buf[written + 1:], pix_bytes[:])
written += 5
}
}
}
prev = pix
}
trailer := []u8{0, 0, 0, 0, 0, 0, 0, 1}
copy(output.buf[written:], trailer[:])
written += len(trailer)
resize(&output.buf, written)
return nil
}
save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator
out := &bytes.Buffer{}
defer bytes.buffer_destroy(out)
save_to_memory(out, img, options) or_return
write_ok := os.write_entire_file(output, out.buf[:])
return nil if write_ok else .Unable_To_Write_File
}
save :: proc{save_to_memory, save_to_file}
load_from_bytes :: proc(data: []byte, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
ctx := &compress.Context_Memory_Input{
input_data = data,
}
img, err = load_from_context(ctx, options, allocator)
return img, err
}
load_from_file :: proc(filename: string, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
context.allocator = allocator
data, ok := os.read_entire_file(filename)
defer delete(data)
if ok {
return load_from_bytes(data, options)
} else {
return nil, .Unable_To_Read_File
}
}
@(optimization_mode="speed")
load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.allocator) -> (img: ^Image, err: Error) {
context.allocator = allocator
options := options
if .info in options {
options |= {.return_metadata, .do_not_decompress_image}
options -= {.info}
}
if .return_header in options && .return_metadata in options {
options -= {.return_header}
}
header := image.read_data(ctx, image.QOI_Header) or_return
if header.magic != image.QOI_Magic {
return img, .Invalid_Signature
}
if img == nil {
img = new(Image)
}
img.which = .QOI
if .return_metadata in options {
info := new(image.QOI_Info)
info.header = header
img.metadata = info
}
if header.channels != 3 && header.channels != 4 {
return img, .Invalid_Number_Of_Channels
}
if header.color_space != .sRGB && header.color_space != .Linear {
return img, .Invalid_Color_Space
}
if header.width == 0 || header.height == 0 {
return img, .Invalid_Image_Dimensions
}
total_pixels := header.width * header.height
if total_pixels > image.MAX_DIMENSIONS {
return img, .Image_Dimensions_Too_Large
}
img.width = int(header.width)
img.height = int(header.height)
img.channels = 4 if .alpha_add_if_missing in options else int(header.channels)
img.depth = 8
if .do_not_decompress_image in options {
img.channels = int(header.channels)
return
}
bytes_needed := image.compute_buffer_size(int(header.width), int(header.height), img.channels, 8)
if !resize(&img.pixels.buf, bytes_needed) {
return img, .Unable_To_Allocate_Or_Resize
}
/*
Decode loop starts here.
*/
seen: [64]RGBA_Pixel
pix := RGBA_Pixel{0, 0, 0, 255}
seen[qoi_hash(pix)] = pix
pixels := img.pixels.buf[:]
decode: for len(pixels) > 0 {
data := image.read_u8(ctx) or_return
tag := QOI_Opcode_Tag(data)
#partial switch tag {
case .RGB:
pix.rgb = image.read_data(ctx, RGB_Pixel) or_return
#no_bounds_check {
seen[qoi_hash(pix)] = pix
}
case .RGBA:
pix = image.read_data(ctx, RGBA_Pixel) or_return
#no_bounds_check {
seen[qoi_hash(pix)] = pix
}
case:
// 2-bit tag
tag = QOI_Opcode_Tag(data & QOI_Opcode_Mask)
#partial switch tag {
case .INDEX:
pix = seen[data & 63]
case .DIFF:
diff_r := ((data >> 4) & 3) - 2
diff_g := ((data >> 2) & 3) - 2
diff_b := ((data >> 0) & 3) - 2
pix += {diff_r, diff_g, diff_b, 0}
#no_bounds_check {
seen[qoi_hash(pix)] = pix
}
case .LUMA:
data2 := image.read_u8(ctx) or_return
diff_g := (data & 63) - 32
diff_r := diff_g - 8 + ((data2 >> 4) & 15)
diff_b := diff_g - 8 + (data2 & 15)
pix += {diff_r, diff_g, diff_b, 0}
#no_bounds_check {
seen[qoi_hash(pix)] = pix
}
case .RUN:
if length := int(data & 63) + 1; (length * img.channels) > len(pixels) {
return img, .Corrupt
} else {
#no_bounds_check for in 0..<length {
copy(pixels, pix[:img.channels])
pixels = pixels[img.channels:]
}
}
continue decode
case:
unreachable()
}
}
#no_bounds_check {
copy(pixels, pix[:img.channels])
pixels = pixels[img.channels:]
}
}
// The byte stream's end is marked with 7 0x00 bytes followed by a single 0x01 byte.
trailer, trailer_err := compress.read_data(ctx, u64be)
if trailer_err != nil || trailer != 0x1 {
return img, .Missing_Or_Corrupt_Trailer
}
if .alpha_premultiply in options && !image.alpha_drop_if_present(img, options) {
return img, .Post_Processing_Error
}
return
}
load :: proc{load_from_file, load_from_bytes, load_from_context}
/*
Cleanup of image-specific data.
*/
destroy :: proc(img: ^Image) {
if img == nil {
/*
Nothing to do.
Load must've returned with an error.
*/
return
}
bytes.buffer_destroy(&img.pixels)
if v, ok := img.metadata.(^image.QOI_Info); ok {
free(v)
}
free(img)
}
QOI_Opcode_Tag :: enum u8 {
// 2-bit tags
INDEX = 0b0000_0000, // 6-bit index into color array follows
DIFF = 0b0100_0000, // 3x (RGB) 2-bit difference follows (-2..1), bias of 2.
LUMA = 0b1000_0000, // Luma difference
RUN = 0b1100_0000, // Run length encoding, bias -1
// 8-bit tags
RGB = 0b1111_1110, // Raw RGB pixel follows
RGBA = 0b1111_1111, // Raw RGBA pixel follows
}
QOI_Opcode_Mask :: 0b1100_0000
QOI_Data_Mask :: 0b0011_1111
qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) {
i1 := u16(pixel.r) * 3
i2 := u16(pixel.g) * 5
i3 := u16(pixel.b) * 7
i4 := u16(pixel.a) * 11
return u8((i1 + i2 + i3 + i4) & 63)
}
@(init, private)
_register :: proc() {
image.register(.QOI, load_from_bytes, destroy)
}
+101
View File
@@ -0,0 +1,101 @@
/*
Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
Made available under Odin's BSD-3 license.
List of contributors:
Jeroen van Rijn: Initial implementation.
*/
// package tga implements a TGA image writer for 8-bit RGB and RGBA images.
package tga
import "core:mem"
import "core:image"
import "core:bytes"
import "core:os"
Error :: image.Error
Image :: image.Image
Options :: image.Options
RGB_Pixel :: image.RGB_Pixel
RGBA_Pixel :: image.RGBA_Pixel
save_to_memory :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator
if img == nil {
return .Invalid_Input_Image
}
if output == nil {
return .Invalid_Output
}
pixels := img.width * img.height
if pixels == 0 || pixels > image.MAX_DIMENSIONS || img.width > 65535 || img.height > 65535 {
return .Invalid_Input_Image
}
// Our TGA writer supports only 8-bit images with 3 or 4 channels.
if img.depth != 8 || img.channels < 3 || img.channels > 4 {
return .Invalid_Input_Image
}
if img.channels * pixels != len(img.pixels.buf) {
return .Invalid_Input_Image
}
written := 0
// Calculate and allocate necessary space.
necessary := pixels * img.channels + size_of(image.TGA_Header)
if !resize(&output.buf, necessary) {
return .Unable_To_Allocate_Or_Resize
}
header := image.TGA_Header{
data_type_code = 0x02, // Color, uncompressed.
dimensions = {u16le(img.width), u16le(img.height)},
bits_per_pixel = u8(img.depth * img.channels),
image_descriptor = 1 << 5, // Origin is top left.
}
header_bytes := transmute([size_of(image.TGA_Header)]u8)header
copy(output.buf[written:], header_bytes[:])
written += size_of(image.TGA_Header)
/*
Encode loop starts here.
*/
if img.channels == 3 {
pix := mem.slice_data_cast([]RGB_Pixel, img.pixels.buf[:])
out := mem.slice_data_cast([]RGB_Pixel, output.buf[written:])
for p, i in pix {
out[i] = p.bgr
}
} else if img.channels == 4 {
pix := mem.slice_data_cast([]RGBA_Pixel, img.pixels.buf[:])
out := mem.slice_data_cast([]RGBA_Pixel, output.buf[written:])
for p, i in pix {
out[i] = p.bgra
}
}
return nil
}
save_to_file :: proc(output: string, img: ^Image, options := Options{}, allocator := context.allocator) -> (err: Error) {
context.allocator = allocator
out := &bytes.Buffer{}
defer bytes.buffer_destroy(out)
save_to_memory(out, img, options) or_return
write_ok := os.write_entire_file(output, out.buf[:])
return nil if write_ok else .Unable_To_Write_File
}
save :: proc{save_to_memory, save_to_file}
+179
View File
@@ -0,0 +1,179 @@
package image
import "core:os"
Which_File_Type :: enum {
Unknown,
BMP,
DjVu, // AT&T DjVu file format
EXR,
FLIF,
GIF,
HDR, // Radiance RGBE HDR
ICNS, // Apple Icon Image
JPEG,
JPEG_2000,
JPEG_XL,
NetPBM, // NetPBM family
PIC, // Softimage PIC
PNG, // Portable Network Graphics
PSD, // Photoshop PSD
QOI, // Quite Okay Image
SGI_RGB, // Silicon Graphics Image RGB file format
Sun_Rast, // Sun Raster Graphic
TGA, // Targa Truevision
TIFF, // Tagged Image File Format
WebP,
XBM, // X BitMap
}
which :: proc{
which_bytes,
which_file,
}
which_bytes :: proc(data: []byte) -> Which_File_Type {
test_tga :: proc(s: string) -> bool {
get8 :: #force_inline proc(s: ^string) -> u8 {
v := s[0]
s^ = s[1:]
return v
}
get16le :: #force_inline proc(s: ^string) -> u16 {
v := u16(s[0]) | u16(s[1])<<16
s^ = s[2:]
return v
}
s := s
s = s[1:] // skip offset
color_type := get8(&s)
if color_type > 1 {
return false
}
image_type := get8(&s) // image type
if color_type == 1 { // Colormap (Paletted) Image
if image_type != 1 && image_type != 9 { // color type requires 1 or 9
return false
}
s = s[4:] // skip index of first colormap
bpcme := get8(&s) // check bits per colormap entry
if bpcme != 8 && bpcme != 15 && bpcme != 16 && bpcme != 24 && bpcme != 32 {
return false
}
s = s[4:] // skip image origin (x, y)
} else { // Normal image without colormap
if image_type != 2 && image_type != 3 && image_type != 10 && image_type != 11 {
return false
}
s = s[9:] // skip colormap specification
}
if get16le(&s) < 1 || get16le(&s) < 1 { // test width and height
return false
}
bpp := get8(&s) // bits per pixel
if color_type == 1 && bpp != 8 && bpp != 16 {
return false
}
if bpp != 8 && bpp != 15 && bpp != 16 && bpp != 24 && bpp != 32 {
return false
}
return true
}
header: [128]byte
copy(header[:], data)
s := string(header[:])
switch {
case s[:2] == "BM":
return .BMP
case s[:8] == "AT&TFORM":
switch s[12:16] {
case "DJVU", "DJVM":
return .DjVu
}
case s[:4] == "\x76\x2f\x31\x01":
return .EXR
case s[:6] == "GIF87a", s[:6] == "GIF89a":
return .GIF
case s[6:10] == "JFIF", s[6:10] == "Exif":
return .JPEG
case s[:3] == "\xff\xd8\xff":
switch s[4] {
case 0xdb, 0xee, 0xe1, 0xe0:
return .JPEG
}
switch {
case s[:12] == "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01":
return .JPEG
}
case s[:4] == "\xff\x4f\xff\x51", s[:12] == "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a":
return .JPEG_2000
case s[:12] == "\x00\x00\x00\x0c\x4a\x58\x4c\x20\x0d\x0a\x87\x0a":
return .JPEG_XL
case s[0] == 'P':
switch s[2] {
case '\t', '\n', '\r':
switch s[1] {
case '1', '4': // PBM
return .NetPBM
case '2', '5': // PGM
return .NetPBM
case '3', '6': // PPM
return .NetPBM
case '7': // PAM
return .NetPBM
case 'F', 'f': // PFM
return .NetPBM
}
}
case s[:8] == "\x89PNG\r\n\x1a\n":
return .PNG
case s[:4] == "qoif":
return .QOI
case s[:2] == "\x01\xda":
return .SGI_RGB
case s[:4] == "\x59\xA6\x6A\x95":
return .Sun_Rast
case s[:4] == "MM\x2a\x00", s[:4] == "II\x00\x2A":
return .TIFF
case s[:4] == "RIFF" && s[8:12] == "WEBP":
return .WebP
case s[:8] == "#define ":
return .XBM
case s[:11] == "#?RADIANCE\n", s[:7] == "#?RGBE\n":
return .HDR
case s[:4] == "\x38\x42\x50\x53":
return .PSD
case s[:4] != "\x53\x80\xF6\x34" && s[88:92] == "PICT":
return .PIC
case s[:4] == "\x69\x63\x6e\x73":
return .ICNS
case s[:4] == "\x46\x4c\x49\x46":
return .FLIF
case:
// More complex formats
if test_tga(s) {
return .TGA
}
}
return .Unknown
}
which_file :: proc(path: string) -> Which_File_Type {
f, err := os.open(path)
if err != 0 {
return .Unknown
}
header: [128]byte
os.read(f, header[:])
file_type := which_bytes(header[:])
os.close(f)
return file_type
}
+182 -86
View File
@@ -6,12 +6,14 @@ package intrinsics
is_package_imported :: proc(package_name: string) -> bool ---
// Types
simd_vector :: proc($N: int, $T: typeid) -> type/#simd[N]T
soa_struct :: proc($N: int, $T: typeid) -> type/#soa[N]T
// Volatile
volatile_load :: proc(dst: ^$T) -> T ---
volatile_store :: proc(dst: ^$T, val: T) -> T ---
volatile_store :: proc(dst: ^$T, val: T) ---
non_temporal_load :: proc(dst: ^$T) -> T ---
non_temporal_store :: proc(dst: ^$T, val: T) ---
// Trapping
debug_trap :: proc() ---
@@ -23,24 +25,32 @@ alloca :: proc(size, align: int) -> [^]u8 ---
cpu_relax :: proc() ---
read_cycle_counter :: proc() -> i64 ---
count_ones :: proc(x: $T) -> T where type_is_integer(T) ---
count_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) ---
count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) ---
overflow_add :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
sqrt :: proc(x: $T) -> T where type_is_float(T) ---
sqrt :: proc(x: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
fused_mul_add :: proc(a, b, c: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
mem_copy :: proc(dst, src: rawptr, len: int) ---
mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) ---
mem_zero :: proc(ptr: rawptr, len: int) ---
mem_zero_volatile :: proc(ptr: rawptr, len: int) ---
// prefer [^]T operations if possible
ptr_offset :: proc(ptr: ^$T, offset: int) -> ^T ---
ptr_sub :: proc(a, b: ^$T) -> int ---
unaligned_load :: proc(src: ^$T) -> T ---
unaligned_store :: proc(dst: ^$T, val: T) -> T ---
fixed_point_mul :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
fixed_point_div :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
@@ -60,77 +70,47 @@ syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
// Atomics
atomic_fence :: proc() ---
atomic_fence_acq :: proc() ---
atomic_fence_rel :: proc() ---
atomic_fence_acqrel :: proc() ---
Atomic_Memory_Order :: enum {
Relaxed = 0, // Unordered
Consume = 1, // Monotonic
Acquire = 2,
Release = 3,
Acq_Rel = 4,
Seq_Cst = 5,
}
atomic_store :: proc(dst: ^$T, val: T) ---
atomic_store_rel :: proc(dst: ^$T, val: T) ---
atomic_store_relaxed :: proc(dst: ^$T, val: T) ---
atomic_store_unordered :: proc(dst: ^$T, val: T) ---
atomic_type_is_lock_free :: proc($T: typeid) -> bool ---
atomic_thread_fence :: proc(order: Atomic_Memory_Order) ---
atomic_signal_fence :: proc(order: Atomic_Memory_Order) ---
atomic_store :: proc(dst: ^$T, val: T) ---
atomic_store_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) ---
atomic_load :: proc(dst: ^$T) -> T ---
atomic_load_acq :: proc(dst: ^$T) -> T ---
atomic_load_relaxed :: proc(dst: ^$T) -> T ---
atomic_load_unordered :: proc(dst: ^$T) -> T ---
atomic_load_explicit :: proc(dst: ^$T, order: Atomic_Memory_Order) -> T ---
atomic_add :: proc(dst; ^$T, val: T) -> T ---
atomic_add_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_add_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_add_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_add_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_sub :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_sub_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_and :: proc(dst; ^$T, val: T) -> T ---
atomic_and_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_and_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_and_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_and_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_nand :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_nand_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_or :: proc(dst; ^$T, val: T) -> T ---
atomic_or_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_or_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_or_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_or_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_xor :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_xor_relaxed :: proc(dst; ^$T, val: T) -> T ---
// fetch then operator
atomic_add :: proc(dst: ^$T, val: T) -> T ---
atomic_add_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_sub :: proc(dst: ^$T, val: T) -> T ---
atomic_sub_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_and :: proc(dst: ^$T, val: T) -> T ---
atomic_and_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_nand :: proc(dst: ^$T, val: T) -> T ---
atomic_nand_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_or :: proc(dst: ^$T, val: T) -> T ---
atomic_or_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_xor :: proc(dst: ^$T, val: T) -> T ---
atomic_xor_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_exchange :: proc(dst: ^$T, val: T) -> T ---
atomic_exchange_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
atomic_xchg :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_acq :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_rel :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_acqrel :: proc(dst; ^$T, val: T) -> T ---
atomic_xchg_relaxed :: proc(dst; ^$T, val: T) -> T ---
atomic_compare_exchange_strong :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_compare_exchange_strong_explicit :: proc(dst: ^$T, old, new: T, success, failure: Atomic_Memory_Order) -> (T, bool) #optional_ok ---
atomic_compare_exchange_weak :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_compare_exchange_weak_explicit :: proc(dst: ^$T, old, new: T, success, failure: Atomic_Memory_Order) -> (T, bool) #optional_ok ---
atomic_cxchg :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_acq :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_rel :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_acqrel :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_relaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_failacq :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_acq_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchg_acqrel_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_acq :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_rel :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_acqrel :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_relaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_failacq :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_acq_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
atomic_cxchgweak_acqrel_failrelaxed :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
// Constant type tests
@@ -148,22 +128,24 @@ type_is_string :: proc($T: typeid) -> bool ---
type_is_typeid :: proc($T: typeid) -> bool ---
type_is_any :: proc($T: typeid) -> bool ---
type_is_endian_platform :: proc($T: typeid) -> bool ---
type_is_endian_little :: proc($T: typeid) -> bool ---
type_is_endian_big :: proc($T: typeid) -> bool ---
type_is_unsigned :: proc($T: typeid) -> bool ---
type_is_numeric :: proc($T: typeid) -> bool ---
type_is_ordered :: proc($T: typeid) -> bool ---
type_is_ordered_numeric :: proc($T: typeid) -> bool ---
type_is_indexable :: proc($T: typeid) -> bool ---
type_is_sliceable :: proc($T: typeid) -> bool ---
type_is_comparable :: proc($T: typeid) -> bool ---
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
type_is_dereferenceable :: proc($T: typeid) -> bool ---
type_is_valid_map_key :: proc($T: typeid) -> bool ---
type_is_endian_platform :: proc($T: typeid) -> bool ---
type_is_endian_little :: proc($T: typeid) -> bool ---
type_is_endian_big :: proc($T: typeid) -> bool ---
type_is_unsigned :: proc($T: typeid) -> bool ---
type_is_numeric :: proc($T: typeid) -> bool ---
type_is_ordered :: proc($T: typeid) -> bool ---
type_is_ordered_numeric :: proc($T: typeid) -> bool ---
type_is_indexable :: proc($T: typeid) -> bool ---
type_is_sliceable :: proc($T: typeid) -> bool ---
type_is_comparable :: proc($T: typeid) -> bool ---
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
type_is_dereferenceable :: proc($T: typeid) -> bool ---
type_is_valid_map_key :: proc($T: typeid) -> bool ---
type_is_valid_matrix_elements :: proc($T: typeid) -> bool ---
type_is_named :: proc($T: typeid) -> bool ---
type_is_pointer :: proc($T: typeid) -> bool ---
type_is_multi_pointer :: proc($T: typeid) -> bool ---
type_is_array :: proc($T: typeid) -> bool ---
type_is_enumerated_array :: proc($T: typeid) -> bool ---
type_is_slice :: proc($T: typeid) -> bool ---
@@ -175,6 +157,7 @@ type_is_enum :: proc($T: typeid) -> bool ---
type_is_proc :: proc($T: typeid) -> bool ---
type_is_bit_set :: proc($T: typeid) -> bool ---
type_is_simd_vector :: proc($T: typeid) -> bool ---
type_is_matrix :: proc($T: typeid) -> bool ---
type_has_nil :: proc($T: typeid) -> bool ---
@@ -182,6 +165,7 @@ type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
type_has_field :: proc($T: typeid, $name: string) -> bool ---
type_field_type :: proc($T: typeid, $name: string) -> typeid ---
type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) ---
type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
@@ -189,15 +173,127 @@ type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---
type_is_specialized_polymorphic_record :: proc($T: typeid) -> bool ---
type_is_unspecialized_polymorphic_record :: proc($T: typeid) -> bool ---
type_is_subtype_of :: proc($T, $U: typeid) -> bool ---
type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
// SIMD related
simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_mul :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_div :: proc(a, b: #simd[N]T) -> #simd[N]T where type_is_float(T) ---
// Keeps Odin's Behaviour
// (x << y) if y <= mask else 0
simd_shl :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_shr :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
// Similar to C's Behaviour
// x << (y & mask)
simd_shl_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_shr_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_add_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_and_not :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_neg :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_abs :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_min :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_max :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_clamp :: proc(v, min, max: #simd[N]T) -> #simd[N]T ---
// Return an unsigned integer of the same size as the input type
// NOT A BOOLEAN
// element-wise:
// false => 0x00...00
// true => 0xff...ff
simd_lanes_eq :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_ne :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_lt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_le :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_gt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_ge :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_extract :: proc(a: #simd[N]T, idx: uint) -> T ---
simd_replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T ---
simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T ---
simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T ---
simd_reduce_min :: proc(a: #simd[N]T) -> T ---
simd_reduce_max :: proc(a: #simd[N]T) -> T ---
simd_reduce_and :: proc(a: #simd[N]T) -> T ---
simd_reduce_or :: proc(a: #simd[N]T) -> T ---
simd_reduce_xor :: proc(a: #simd[N]T) -> T ---
simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T ---
simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T ---
// Lane-wise operations
simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_floor :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_trunc :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
// rounding to the nearest integral value; if two values are equally near, rounds to the even one
simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
// equivalent a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
simd_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
simd_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
// WASM targets only
wasm_memory_grow :: proc(index, delta: uintptr) -> int ---
wasm_memory_size :: proc(index: uintptr) -> int ---
// `timeout_ns` is maximum number of nanoseconds the calling thread will be blocked for
// A negative value will be blocked forever
// Return value:
// 0 - indicates that the thread blocked and then was woken up
// 1 - the loaded value from `ptr` did not match `expected`, the thread did not block
// 2 - the thread blocked, but the timeout
wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -> u32 ---
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
// x86 Targets (i386, amd64)
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) ---
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
// Darwin targets only
objc_object :: struct{}
objc_selector :: struct{}
objc_class :: struct{}
objc_id :: ^objc_object
objc_SEL :: ^objc_selector
objc_Class :: ^objc_class
objc_find_selector :: proc($name: string) -> objc_SEL ---
objc_register_selector :: proc($name: string) -> objc_SEL ---
objc_find_class :: proc($name: string) -> objc_Class ---
objc_register_class :: proc($name: string) -> objc_Class ---
// Internal compiler use only
+2 -7
View File
@@ -4,7 +4,6 @@
package io
import "core:intrinsics"
import "core:runtime"
import "core:unicode/utf8"
// Seek whence values
@@ -254,11 +253,7 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n:
return 0, .Empty
}
curr_offset: i64
curr_offset, err = r->impl_seek(offset, .Current)
if err != nil {
return 0, err
}
curr_offset := r->impl_seek(offset, .Current) or_return
n, err = r->impl_read(p)
_, err1 := r->impl_seek(curr_offset, .Start)
@@ -552,7 +547,7 @@ _copy_buffer :: proc(dst: Writer, src: Reader, buf: []byte) -> (written: i64, er
}
}
// NOTE(bill): alloca is fine here
buf = transmute([]byte)runtime.Raw_Slice{intrinsics.alloca(size, 2*align_of(rawptr)), size}
buf = intrinsics.alloca(size, 2*align_of(rawptr))[:size]
}
for {
nr, er := read(src, buf)
+1 -1
View File
@@ -67,7 +67,7 @@ file_console_logger_proc :: proc(logger_data: rawptr, level: Level, text: string
h = data.file_handle
}
backing: [1024]byte //NOTE(Hoej): 1024 might be too much for a header backing, unless somebody has really long paths.
buf := strings.builder_from_slice(backing[:])
buf := strings.builder_from_bytes(backing[:])
do_level_header(options, level, &buf)
+2 -1
View File
@@ -172,7 +172,7 @@ Error :: enum int {
Unimplemented = 127,
}
Error_String :: #partial [Error]string{
Error_String :: #sparse[Error]string{
.Okay = "Okay",
.Out_Of_Memory = "Out of memory",
.Invalid_Pointer = "Invalid pointer",
@@ -182,6 +182,7 @@ Error_String :: #partial [Error]string{
.Max_Iterations_Reached = "Max iterations reached",
.Buffer_Overflow = "Buffer overflow",
.Integer_Overflow = "Integer overflow",
.Integer_Underflow = "Integer underflow",
.Division_by_Zero = "Division by zero",
.Math_Domain_Error = "Math domain error",
+495
View File
@@ -0,0 +1,495 @@
// easing procedures and flux easing used for animations
package ease
import "core:math"
import "core:intrinsics"
import "core:time"
@(private) PI_2 :: math.PI / 2
// converted to odin from https://github.com/warrenm/AHEasing
// with additional enum based call
// Modeled after the parabola y = x^2
quadratic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p
}
// Modeled after the parabola y = -x^2 + 2x
quadratic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return -(p * (p - 2))
}
// Modeled after the piecewise quadratic
// y = (1/2)((2x)^2) ; [0, 0.5)
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
quadratic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 2 * p * p
} else {
return (-2 * p * p) + (4 * p) - 1
}
}
// Modeled after the cubic y = x^3
cubic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p
}
// Modeled after the cubic y = (x - 1)^3 + 1
cubic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1
return f * f * f + 1
}
// Modeled after the piecewise cubic
// y = (1/2)((2x)^3) ; [0, 0.5)
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
cubic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 4 * p * p * p
} else {
f := (2 * p) - 2
return 0.5 * f * f * f + 1
}
}
// Modeled after the quartic x^4
quartic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p * p
}
// Modeled after the quartic y = 1 - (x - 1)^4
quartic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1
return f * f * f * (1 - p) + 1
}
// Modeled after the piecewise quartic
// y = (1/2)((2x)^4) ; [0, 0.5)
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
quartic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 8 * p * p * p * p
} else {
f := p - 1
return -8 * f * f * f * f + 1
}
}
// Modeled after the quintic y = x^5
quintic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p * p * p
}
// Modeled after the quintic y = (x - 1)^5 + 1
quintic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1
return f * f * f * f * f + 1
}
// Modeled after the piecewise quintic
// y = (1/2)((2x)^5) ; [0, 0.5)
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
quintic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 16 * p * p * p * p * p
} else {
f := (2 * p) - 2
return 0.5 * f * f * f * f * f + 1
}
}
// Modeled after quarter-cycle of sine wave
sine_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin((p - 1) * PI_2) + 1
}
// Modeled after quarter-cycle of sine wave (different phase)
sine_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(p * PI_2)
}
// Modeled after half sine wave
sine_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 0.5 * (1 - math.cos(p * math.PI))
}
// Modeled after shifted quadrant IV of unit circle
circular_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 1 - math.sqrt(1 - (p * p))
}
// Modeled after shifted quadrant II of unit circle
circular_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sqrt((2 - p) * p)
}
// Modeled after the piecewise circular function
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
circular_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 0.5 * (1 - math.sqrt(1 - 4 * (p * p)))
} else {
return 0.5 * (math.sqrt(-((2 * p) - 3) * ((2 * p) - 1)) + 1)
}
}
// Modeled after the exponential function y = 2^(10(x - 1))
exponential_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p == 0.0 ? p : math.pow(2, 10 * (p - 1))
}
// Modeled after the exponential function y = -2^(-10x) + 1
exponential_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p == 1.0 ? p : 1 - math.pow(2, -10 * p)
}
// Modeled after the piecewise exponential
// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p == 0.0 || p == 1.0 {
return p
}
if p < 0.5 {
return 0.5 * math.pow(2, (20 * p) - 10)
} else {
return -0.5 * math.pow(2, (-20 * p) + 10) + 1
}
}
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
elastic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(13 * PI_2 * p) * math.pow(2, 10 * (p - 1))
}
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1
elastic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(-13 * PI_2 * (p + 1)) * math.pow(2, -10 * p) + 1
}
// Modeled after the piecewise exponentially-damped sine wave:
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
elastic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 0.5 * math.sin(13 * PI_2 * (2 * p)) * math.pow(2, 10 * ((2 * p) - 1))
} else {
return 0.5 * (math.sin(-13 * PI_2 * ((2 * p - 1) + 1)) * math.pow(2, -10 * (2 * p - 1)) + 2)
}
}
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
back_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p - p * math.sin(p * math.PI)
}
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
back_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := 1 - p
return 1 - (f * f * f - f * math.sin(f * math.PI))
}
// Modeled after the piecewise overshooting cubic function:
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
back_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
f := 2 * p
return 0.5 * (f * f * f - f * math.sin(f * math.PI))
} else {
f := (1 - (2*p - 1))
return 0.5 * (1 - (f * f * f - f * math.sin(f * math.PI))) + 0.5
}
}
bounce_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 1 - bounce_out(1 - p)
}
bounce_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 4/11.0 {
return (121 * p * p)/16.0
} else if p < 8/11.0 {
return (363/40.0 * p * p) - (99/10.0 * p) + 17/5.0
} else if p < 9/10.0 {
return (4356/361.0 * p * p) - (35442/1805.0 * p) + 16061/1805.0
} else {
return (54/5.0 * p * p) - (513/25.0 * p) + 268/25.0
}
}
bounce_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 0.5 * bounce_in(p*2)
} else {
return 0.5 * bounce_out(p * 2 - 1) + 0.5
}
}
// additional enum variant
Ease :: enum {
Linear,
Quadratic_In,
Quadratic_Out,
Quadratic_In_Out,
Cubic_In,
Cubic_Out,
Cubic_In_Out,
Quartic_In,
Quartic_Out,
Quartic_In_Out,
Quintic_In,
Quintic_Out,
Quintic_In_Out,
Sine_In,
Sine_Out,
Sine_In_Out,
Circular_In,
Circular_Out,
Circular_In_Out,
Exponential_In,
Exponential_Out,
Exponential_In_Out,
Elastic_In,
Elastic_Out,
Elastic_In_Out,
Back_In,
Back_Out,
Back_In_Out,
Bounce_In,
Bounce_Out,
Bounce_In_Out,
}
ease :: proc "contextless" (type: Ease, p: $T) -> T
where intrinsics.type_is_float(T) {
switch type {
case .Linear: return p
case .Quadratic_In: return quadratic_in(p)
case .Quadratic_Out: return quadratic_out(p)
case .Quadratic_In_Out: return quadratic_in_out(p)
case .Cubic_In: return cubic_in(p)
case .Cubic_Out: return cubic_out(p)
case .Cubic_In_Out: return cubic_in_out(p)
case .Quartic_In: return quartic_in(p)
case .Quartic_Out: return quartic_out(p)
case .Quartic_In_Out: return quartic_in_out(p)
case .Quintic_In: return quintic_in(p)
case .Quintic_Out: return quintic_out(p)
case .Quintic_In_Out: return quintic_in_out(p)
case .Sine_In: return sine_in(p)
case .Sine_Out: return sine_out(p)
case .Sine_In_Out: return sine_in_out(p)
case .Circular_In: return circular_in(p)
case .Circular_Out: return circular_out(p)
case .Circular_In_Out: return circular_in_out(p)
case .Exponential_In: return exponential_in(p)
case .Exponential_Out: return exponential_out(p)
case .Exponential_In_Out: return exponential_in_out(p)
case .Elastic_In: return elastic_in(p)
case .Elastic_Out: return elastic_out(p)
case .Elastic_In_Out: return elastic_in_out(p)
case .Back_In: return back_in(p)
case .Back_Out: return back_out(p)
case .Back_In_Out: return back_in_out(p)
case .Bounce_In: return bounce_in(p)
case .Bounce_Out: return bounce_out(p)
case .Bounce_In_Out: return bounce_in_out(p)
}
// in case type was invalid
return 0
}
Flux_Map :: struct($T: typeid) {
values: map[^T]Flux_Tween(T),
keys_to_be_deleted: [dynamic]^T,
}
Flux_Tween :: struct($T: typeid) {
value: ^T,
start: T,
diff: T,
goal: T,
delay: f64, // in seconds
duration: time.Duration,
progress: f64,
rate: f64,
type: Ease,
inited: bool,
// callbacks, data can be set, will be pushed to callback
data: rawptr, // by default gets set to value input
on_start: proc(flux: ^Flux_Map(T), data: rawptr),
on_update: proc(flux: ^Flux_Map(T), data: rawptr),
on_complete: proc(flux: ^Flux_Map(T), data: rawptr),
}
// init flux map to a float type and a wanted cap
flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) {
return {
values = make(map[^T]Flux_Tween(T), value_capacity),
keys_to_be_deleted = make([dynamic]^T, 0, value_capacity)
}
}
// delete map content
flux_destroy :: proc(flux: Flux_Map($T)) where intrinsics.type_is_float(T) {
delete(flux.values)
delete(flux.keys_to_be_deleted)
}
// clear map content, stops all animations
flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) {
clear(&flux.values)
}
// append / overwrite existing tween value to parameters
// rest is initialized in flux_tween_init, inside update
// return value can be used to set callbacks
flux_to :: proc(
flux: ^Flux_Map($T),
value: ^T,
goal: T,
type: Ease = .Quadratic_Out,
duration: time.Duration = time.Second,
delay: f64 = 0,
) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) {
if res, ok := &flux.values[value]; ok {
tween = res
} else {
flux.values[value] = {}
tween = &flux.values[value]
}
tween^ = {
value = value,
goal = goal,
duration = duration,
delay = delay,
type = type,
data = value,
}
return
}
// init internal properties
flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where intrinsics.type_is_float(T) {
tween.inited = true
tween.start = tween.value^
tween.diff = tween.goal - tween.value^
s := time.duration_seconds(duration)
tween.rate = duration > 0 ? 1.0 / s : 0
tween.progress = duration > 0 ? 0 : 1
}
// update all tweens, wait for their delay if one exists
// calls callbacks in all stages, when they're filled
// deletes tween from the map after completion
flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) {
clear(&flux.keys_to_be_deleted)
for key, tween in &flux.values {
delay_remainder := f64(0)
// Update delay if necessary.
if tween.delay > 0 {
tween.delay -= dt
if tween.delay < 0 {
// We finished the delay, but in doing so consumed part of this frame's `dt` budget.
// Keep track of it so we can apply it to this tween without affecting others.
delay_remainder = tween.delay
// We're done with this delay.
tween.delay = 0
}
}
// We either had no delay, or the delay has been consumed.
if tween.delay <= 0 {
if !tween.inited {
flux_tween_init(&tween, tween.duration)
if tween.on_start != nil {
tween.on_start(flux, tween.data)
}
}
// If part of the `dt` budget was consumed this frame, then `delay_remainder` will be
// that remainder, a negative value. Adding it to `dt` applies what's left of the `dt`
// to the tween so it advances properly, instead of too much or little.
tween.progress += tween.rate * (dt + delay_remainder)
x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress)
tween.value^ = tween.start + tween.diff * T(x)
if tween.on_update != nil {
tween.on_update(flux, tween.data)
}
if tween.progress >= 1 {
// append keys to array that will be deleted after the loop
append(&flux.keys_to_be_deleted, key)
if tween.on_complete != nil {
tween.on_complete(flux, tween.data)
}
}
}
}
// loop through keys that should be deleted from the map
if len(flux.keys_to_be_deleted) != 0 {
for key in flux.keys_to_be_deleted {
delete_key(&flux.values, key)
}
}
}
// stop a specific key inside the map
// returns true when it successfully removed the key
flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) {
if key in flux.values {
delete_key(&flux.values, key)
return true
}
return false
}
// returns the amount of time left for the tween animation, if the key exists in the map
// returns 0 if the tween doesnt exist on the map
flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 {
if tween, ok := flux.values[key]; ok {
return ((1 - tween.progress) * tween.rate) + tween.delay
} else {
return 0
}
}
+5 -5
View File
@@ -426,14 +426,14 @@ distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) {
}
reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
b := n * (2 * dot(n, i))
return i - b
b := N * (2 * dot(N, I))
return I - b
}
refract :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
dv := dot(n, i)
dv := dot(N, I)
k := 1 - eta*eta - (1 - dv*dv)
a := i * eta
b := n * eta*dv*math.sqrt(k)
a := I * eta
b := N * eta*dv*math.sqrt(k)
return (a - b) * E(int(k >= 0))
}
+3 -3
View File
@@ -479,21 +479,21 @@ angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2
}
return math.cos(q.x) * 2
return math.acos(q.w) * 2
}
angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2
}
return math.cos(q.x) * 2
return math.acos(q.w) * 2
}
angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
if abs(q.w) > math.SQRT_THREE*0.5 {
return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2
}
return math.cos(q.x) * 2
return math.acos(q.w) * 2
}
angle_from_quaternion :: proc{
angle_from_quaternion_f16,
+27 -6
View File
@@ -396,7 +396,7 @@ trunc_f16 :: proc "contextless" (x: f16) -> f16 {
e := (x >> shift) & mask - bias
if e < shift {
x &= ~(1 << (shift-e)) - 1
x &~= 1 << (shift-e) - 1
}
return transmute(f16)x
}
@@ -428,7 +428,7 @@ trunc_f32 :: proc "contextless" (x: f32) -> f32 {
e := (x >> shift) & mask - bias
if e < shift {
x &= ~(1 << (shift-e)) - 1
x &~= 1 << (shift-e) - 1
}
return transmute(f32)x
}
@@ -460,7 +460,7 @@ trunc_f64 :: proc "contextless" (x: f64) -> f64 {
e := (x >> shift) & mask - bias
if e < shift {
x &= ~(1 << (shift-e)) - 1
x &~= 1 << (shift-e) - 1
}
return transmute(f64)x
}
@@ -473,6 +473,7 @@ trunc_f64 :: proc "contextless" (x: f64) -> f64 {
}
trunc_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(trunc_f64(f64(x))) }
trunc_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(trunc_f64(f64(x))) }
// Removes the fractional part of the value, i.e. rounds towards zero.
trunc :: proc{
trunc_f16, trunc_f16le, trunc_f16be,
trunc_f32, trunc_f32le, trunc_f32be,
@@ -958,7 +959,7 @@ classify_f16 :: proc "contextless" (x: f16) -> Float_Class {
return .Neg_Zero
}
return .Zero
case x*0.5 == x:
case x*0.25 == x:
if x < 0 {
return .Neg_Inf
}
@@ -1027,6 +1028,8 @@ classify_f64 :: proc "contextless" (x: f64) -> Float_Class {
}
classify_f64le :: proc "contextless" (x: f64le) -> Float_Class { return #force_inline classify_f64(f64(x)) }
classify_f64be :: proc "contextless" (x: f64be) -> Float_Class { return #force_inline classify_f64(f64(x)) }
// Returns the `Float_Class` of the value, i.e. whether normal, subnormal, zero, negative zero, NaN, infinity or
// negative infinity.
classify :: proc{
classify_f16, classify_f16le, classify_f16be,
classify_f32, classify_f32le, classify_f32be,
@@ -1203,7 +1206,7 @@ prod :: proc "contextless" (x: $T/[]$E) -> (res: E)
return
}
cumsum_inplace :: proc "contextless" (x: $T/[]$E) -> T
cumsum_inplace :: proc "contextless" (x: $T/[]$E)
where intrinsics.type_is_numeric(E) {
for i in 1..<len(x) {
x[i] = x[i-1] + x[i]
@@ -1715,4 +1718,22 @@ F32_BIAS :: 0x7f
F64_MASK :: 0x7ff
F64_SHIFT :: 64 - 12
F64_BIAS :: 0x3ff
F64_BIAS :: 0x3ff
INF_F16 :f16: 0h7C00
NEG_INF_F16 :f16: 0hFC00
SNAN_F16 :f16: 0h7C01
QNAN_F16 :f16: 0h7E01
INF_F32 :f32: 0h7F80_0000
NEG_INF_F32 :f32: 0hFF80_0000
SNAN_F32 :f32: 0hFF80_0001
QNAN_F32 :f32: 0hFFC0_0001
INF_F64 :f64: 0h7FF0_0000_0000_0000
NEG_INF_F64 :f64: 0hFFF0_0000_0000_0000
SNAN_F64 :f64: 0h7FF0_0000_0000_0001
QNAN_F64 :f64: 0h7FF8_0000_0000_0001
+734
View File
@@ -0,0 +1,734 @@
/*
OpenSimplex2 noise implementation.
Ported from https://github.com/KdotJPG/OpenSimplex2.
Copyright 2022 Yuki2 (https://github.com/NoahR02)
*/
//+private
package math_noise
/*
Private implementation details follow.
*/
PRIME_X :: i64(0x5205402B9270C86F)
PRIME_Y :: i64(0x598CD327003817B5)
PRIME_Z :: i64(0x5BCC226E9FA0BACB)
PRIME_W :: i64(0x56CC5227E58F554B)
HASH_MULTIPLIER :: i64(0x53A3F72DEEC546F5)
SEED_FLIP_3D :: i64(-0x52D547B2E96ED629)
SEED_OFFSET_4D :: i64(0xE83DC3E0DA7164D)
ROOT_2_OVER_2 :: f64(0.7071067811865476)
SKEW_2D :: f64(0.366025403784439)
UNSKEW_2D :: f64(-0.21132486540518713)
ROOT_3_OVER_3 :: f64(0.577350269189626)
FALLBACK_ROTATE_3D :: f64(2.0) / f64(3.0)
ROTATE_3D_ORTHOGONALIZER :: f64(UNSKEW_2D)
SKEW_4D :: f32(0hbe0d8369)
UNSKEW_4D :: f32(0.309016994374947)
LATTICE_STEP_4D :: f32(0.2)
N_GRADS_2D_EXPONENT :: 7
N_GRADS_3D_EXPONENT :: 8
N_GRADS_4D_EXPONENT :: 9
N_GRADS_2D :: 1 << N_GRADS_2D_EXPONENT
N_GRADS_3D :: 1 << N_GRADS_3D_EXPONENT
N_GRADS_4D :: 1 << N_GRADS_4D_EXPONENT
NORMALIZER_2D :: f64(0.01001634121365712)
NORMALIZER_3D :: f64(0.07969837668935331)
NORMALIZER_4D :: f64(0.0220065933241897)
RSQUARED_2D :: f32(0.5)
RSQUARED_3D :: f32(0.6)
RSQUARED_4D :: f32(0.6)
GRADIENTS_2D := [N_GRADS_2D * 2]f32{
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
0h4150804d, 0h42c5f72a, 0h42731b78, 0h429e696c, 0h429e696c, 0h42731b78, 0h42c5f72a, 0h4150804d,
0h42c5f72a, 0hc150804d, 0h429e696c, 0hc2731b78, 0h42731b78, 0hc29e696c, 0h4150804d, 0hc2c5f72a,
0hc150804d, 0hc2c5f72a, 0hc2731b78, 0hc29e696c, 0hc29e696c, 0hc2731b78, 0hc2c5f72a, 0hc150804d,
0hc2c5f72a, 0h4150804d, 0hc29e696c, 0h42731b78, 0hc2731b78, 0h429e696c, 0hc150804d, 0h42c5f72a,
0h4218d2da, 0h42b87975, 0h42b87975, 0h4218d2da, 0h42b87975, 0hc218d2da, 0h4218d2da, 0hc2b87975,
0hc218d2da, 0hc2b87975, 0hc2b87975, 0hc218d2da, 0hc2b87975, 0h4218d2da, 0hc218d2da, 0h42b87975,
}
GRADIENTS_3D := [N_GRADS_3D * 4]f32{
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
0hc1df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0hc16b5146, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc21ae5b8, 0h00000000, 0hc16b5146, 0h00000000,
0hc1df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0hc1df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0hc21ae5b8, 0h00000000, 0h416b5146, 0h00000000, 0hc16b5146, 0h00000000, 0h421ae5b8, 0h00000000,
0hc148c1c5, 0h41df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0hc1df5103, 0h00000000,
0h00000000, 0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000,
0hc148c1c5, 0h41df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0h41df5103, 0h41df5103, 0h00000000,
0h00000000, 0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000,
0h41df5103, 0hc1df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0hc1df5103, 0h4148c1c5, 0h00000000,
0h416b5146, 0hc21ae5b8, 0h00000000, 0h00000000, 0h421ae5b8, 0hc16b5146, 0h00000000, 0h00000000,
0h41df5103, 0hc148c1c5, 0hc1df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0hc1df5103, 0h00000000,
0h421ae5b8, 0h00000000, 0hc16b5146, 0h00000000, 0h416b5146, 0h00000000, 0hc21ae5b8, 0h00000000,
0h41df5103, 0hc148c1c5, 0h41df5103, 0h00000000, 0h41df5103, 0h4148c1c5, 0h41df5103, 0h00000000,
0h416b5146, 0h00000000, 0h421ae5b8, 0h00000000, 0h421ae5b8, 0h00000000, 0h416b5146, 0h00000000,
0h41df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0h41df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0h421ae5b8, 0h416b5146, 0h00000000, 0h00000000, 0h416b5146, 0h421ae5b8, 0h00000000, 0h00000000,
0hc1df5103, 0h41df5103, 0hc148c1c5, 0h00000000, 0hc1df5103, 0h41df5103, 0h4148c1c5, 0h00000000,
0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000, 0h00000000,
0hc148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0hc1df5103, 0h00000000,
0h00000000, 0hc21ae5b8, 0hc16b5146, 0h00000000, 0h00000000, 0hc16b5146, 0hc21ae5b8, 0h00000000,
0hc148c1c5, 0hc1df5103, 0h41df5103, 0h00000000, 0h4148c1c5, 0hc1df5103, 0h41df5103, 0h00000000,
0h00000000, 0hc16b5146, 0h421ae5b8, 0h00000000, 0h00000000, 0hc21ae5b8, 0h416b5146, 0h00000000,
}
GRADIENTS_4D := [N_GRADS_4D * 4]f32{
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee, 0h40b05c85,
0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee,
0hc21c1252, 0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d,
0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc235739c, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564,
0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85,
0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee,
0hc1b8e69d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0h40024b8d,
0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0hbfc4b564, 0hc235739c, 0hbfc4b564, 0hbfc4b564,
0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85,
0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee,
0hc1b8e69d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0h40024b8d,
0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0hbfc4b564, 0hbfc4b564, 0hc235739c, 0hbfc4b564,
0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc19d18ee, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a,
0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a,
0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d, 0hc21c1252,
0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564, 0hc235739c,
0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc19194b0, 0hc208695c, 0h40de6d7d, 0h41b6d966,
0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h406d72bf, 0hc22076c5, 0h406d72bf, 0h41a58418,
0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc0de6d7d, 0hc1b6d966, 0h419194b0, 0h4208695c,
0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h416b8e00, 0hc1d2a716, 0h416b8e00, 0h41f50507,
0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc19194b0, 0h40de6d7d, 0hc208695c, 0h41b6d966,
0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h406d72bf, 0h406d72bf, 0hc22076c5, 0h41a58418,
0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc0de6d7d, 0h419194b0, 0hc1b6d966, 0h4208695c,
0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h416b8e00, 0h416b8e00, 0hc1d2a716, 0h41f50507,
0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h40de6d7d,
0h40de6d7d, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h406d72bf, 0hc22076c5, 0h41a58418, 0h406d72bf,
0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h419194b0,
0h419194b0, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h416b8e00, 0hc1d2a716, 0h41f50507, 0h416b8e00,
0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc19194b0, 0h40de6d7d, 0h41b6d966, 0hc208695c,
0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h406d72bf, 0h406d72bf, 0h41a58418, 0hc22076c5,
0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc0de6d7d, 0h419194b0, 0h4208695c, 0hc1b6d966,
0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h416b8e00, 0h416b8e00, 0h41f50507, 0hc1d2a716,
0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h40de6d7d,
0h40de6d7d, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h406d72bf, 0h41a58418, 0hc22076c5, 0h406d72bf,
0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h419194b0,
0h419194b0, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h416b8e00, 0h41f50507, 0hc1d2a716, 0h416b8e00,
0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc19194b0, 0h41b6d966, 0h40de6d7d, 0hc208695c,
0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h406d72bf, 0h41a58418, 0h406d72bf, 0hc22076c5,
0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc0de6d7d, 0h4208695c, 0h419194b0, 0hc1b6d966,
0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h416b8e00, 0h41f50507, 0h416b8e00, 0hc1d2a716,
0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h40de6d7d,
0h41b6d966, 0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41a58418, 0h406d72bf, 0hc22076c5, 0h406d72bf,
0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h419194b0,
0h4208695c, 0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h41f50507, 0h416b8e00, 0hc1d2a716, 0h416b8e00,
0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41b6d966, 0hc19194b0, 0h40de6d7d, 0hc208695c,
0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41a58418, 0h406d72bf, 0h406d72bf, 0hc22076c5,
0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h4208695c, 0hc0de6d7d, 0h419194b0, 0hc1b6d966,
0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h41f50507, 0h416b8e00, 0h416b8e00, 0hc1d2a716,
0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h4235739c, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d, 0h421c1252,
0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0b05c85, 0h419d18ee, 0h419d18ee, 0h420e2b7a,
0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h421c1252, 0h419d18ee, 0hc0b05c85, 0h419d18ee, 0h420e2b7a,
0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h418a0670, 0h418a0670, 0h418a0670, 0h4208ee18,
0h3fc4b564, 0h3fc4b564, 0h4235739c, 0h3fc4b564, 0hc0024b8d, 0h40024b8d, 0h421c1252, 0h41b8e69d,
0hc0024b8d, 0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0b05c85, 0h419d18ee, 0h420e2b7a, 0h419d18ee,
0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h419d18ee,
0h419d18ee, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h418a0670, 0h418a0670, 0h4208ee18, 0h418a0670,
0h3fc4b564, 0h4235739c, 0h3fc4b564, 0h3fc4b564, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h41b8e69d,
0hc0024b8d, 0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0b05c85, 0h420e2b7a, 0h419d18ee, 0h419d18ee,
0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h419d18ee,
0h419d18ee, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h418a0670, 0h4208ee18, 0h418a0670, 0h418a0670,
0h4235739c, 0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d,
0h421c1252, 0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h420e2b7a, 0hc0b05c85, 0h419d18ee, 0h419d18ee,
0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h419d18ee,
0h420e2b7a, 0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h4208ee18, 0h418a0670, 0h418a0670, 0h418a0670,
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee, 0h40b05c85,
0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee,
0hc21c1252, 0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d,
0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc235739c, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564,
0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85,
0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee,
0hc1b8e69d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0h40024b8d,
0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0hbfc4b564, 0hc235739c, 0hbfc4b564, 0hbfc4b564,
0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85,
0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee,
0hc1b8e69d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0h40024b8d,
0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0hbfc4b564, 0hbfc4b564, 0hc235739c, 0hbfc4b564,
0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc19d18ee, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a,
0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a,
0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d, 0hc21c1252,
0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564, 0hc235739c,
0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc19194b0, 0hc208695c, 0h40de6d7d, 0h41b6d966,
0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h406d72bf, 0hc22076c5, 0h406d72bf, 0h41a58418,
0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc0de6d7d, 0hc1b6d966, 0h419194b0, 0h4208695c,
0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h416b8e00, 0hc1d2a716, 0h416b8e00, 0h41f50507,
0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc19194b0, 0h40de6d7d, 0hc208695c, 0h41b6d966,
0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h406d72bf, 0h406d72bf, 0hc22076c5, 0h41a58418,
0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc0de6d7d, 0h419194b0, 0hc1b6d966, 0h4208695c,
0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h416b8e00, 0h416b8e00, 0hc1d2a716, 0h41f50507,
0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h40de6d7d,
0h40de6d7d, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h406d72bf, 0hc22076c5, 0h41a58418, 0h406d72bf,
0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h419194b0,
0h419194b0, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h416b8e00, 0hc1d2a716, 0h41f50507, 0h416b8e00,
0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc19194b0, 0h40de6d7d, 0h41b6d966, 0hc208695c,
0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h406d72bf, 0h406d72bf, 0h41a58418, 0hc22076c5,
0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc0de6d7d, 0h419194b0, 0h4208695c, 0hc1b6d966,
0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h416b8e00, 0h416b8e00, 0h41f50507, 0hc1d2a716,
0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h40de6d7d,
0h40de6d7d, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h406d72bf, 0h41a58418, 0hc22076c5, 0h406d72bf,
0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h419194b0,
0h419194b0, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h416b8e00, 0h41f50507, 0hc1d2a716, 0h416b8e00,
0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc19194b0, 0h41b6d966, 0h40de6d7d, 0hc208695c,
0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h406d72bf, 0h41a58418, 0h406d72bf, 0hc22076c5,
0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc0de6d7d, 0h4208695c, 0h419194b0, 0hc1b6d966,
0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h416b8e00, 0h41f50507, 0h416b8e00, 0hc1d2a716,
0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h40de6d7d,
0h41b6d966, 0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41a58418, 0h406d72bf, 0hc22076c5, 0h406d72bf,
0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h419194b0,
0h4208695c, 0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h41f50507, 0h416b8e00, 0hc1d2a716, 0h416b8e00,
0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41b6d966, 0hc19194b0, 0h40de6d7d, 0hc208695c,
0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41a58418, 0h406d72bf, 0h406d72bf, 0hc22076c5,
0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h4208695c, 0hc0de6d7d, 0h419194b0, 0hc1b6d966,
0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h41f50507, 0h416b8e00, 0h416b8e00, 0hc1d2a716,
0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h4235739c, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d, 0h421c1252,
0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0b05c85, 0h419d18ee, 0h419d18ee, 0h420e2b7a,
0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h421c1252, 0h419d18ee, 0hc0b05c85, 0h419d18ee, 0h420e2b7a,
0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h418a0670, 0h418a0670, 0h418a0670, 0h4208ee18,
0h3fc4b564, 0h3fc4b564, 0h4235739c, 0h3fc4b564, 0hc0024b8d, 0h40024b8d, 0h421c1252, 0h41b8e69d,
0hc0024b8d, 0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0b05c85, 0h419d18ee, 0h420e2b7a, 0h419d18ee,
0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h419d18ee,
0h419d18ee, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h418a0670, 0h418a0670, 0h4208ee18, 0h418a0670,
0h3fc4b564, 0h4235739c, 0h3fc4b564, 0h3fc4b564, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h41b8e69d,
0hc0024b8d, 0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0b05c85, 0h420e2b7a, 0h419d18ee, 0h419d18ee,
0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h419d18ee,
0h419d18ee, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h418a0670, 0h4208ee18, 0h418a0670, 0h418a0670,
0h4235739c, 0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d,
0h421c1252, 0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h420e2b7a, 0hc0b05c85, 0h419d18ee, 0h419d18ee,
0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h419d18ee,
0h420e2b7a, 0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h4208ee18, 0h418a0670, 0h418a0670, 0h418a0670,
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee, 0h40b05c85,
0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee,
0hc21c1252, 0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d,
0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc235739c, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564,
0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc18a0670, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85,
0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0hc19d18ee,
0hc1b8e69d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0h40024b8d,
0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0hbfc4b564, 0hc235739c, 0hbfc4b564, 0hbfc4b564,
0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc18a0670, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85,
0hc19d18ee, 0h40b05c85, 0hc20e2b7a, 0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0hc19d18ee,
0hc1b8e69d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0h40024b8d,
0h40024b8d, 0h40024b8d, 0hc21c1252, 0hc1b8e69d, 0hbfc4b564, 0hbfc4b564, 0hc235739c, 0hbfc4b564,
0hc18a0670, 0hc18a0670, 0hc18a0670, 0hc208ee18, 0hc19d18ee, 0hc19d18ee, 0h40b05c85, 0hc20e2b7a,
0hc19d18ee, 0h40b05c85, 0hc19d18ee, 0hc20e2b7a, 0h40b05c85, 0hc19d18ee, 0hc19d18ee, 0hc20e2b7a,
0hc1b8e69d, 0h40024b8d, 0h40024b8d, 0hc21c1252, 0h40024b8d, 0hc1b8e69d, 0h40024b8d, 0hc21c1252,
0h40024b8d, 0h40024b8d, 0hc1b8e69d, 0hc21c1252, 0hbfc4b564, 0hbfc4b564, 0hbfc4b564, 0hc235739c,
0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc19194b0, 0hc208695c, 0h40de6d7d, 0h41b6d966,
0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h406d72bf, 0hc22076c5, 0h406d72bf, 0h41a58418,
0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc0de6d7d, 0hc1b6d966, 0h419194b0, 0h4208695c,
0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h416b8e00, 0hc1d2a716, 0h416b8e00, 0h41f50507,
0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc19194b0, 0h40de6d7d, 0hc208695c, 0h41b6d966,
0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h406d72bf, 0h406d72bf, 0hc22076c5, 0h41a58418,
0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc0de6d7d, 0h419194b0, 0hc1b6d966, 0h4208695c,
0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h416b8e00, 0h416b8e00, 0hc1d2a716, 0h41f50507,
0hc16b8e00, 0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc19194b0, 0hc208695c, 0h41b6d966, 0h40de6d7d,
0h40de6d7d, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h406d72bf, 0hc22076c5, 0h41a58418, 0h406d72bf,
0hc06d72bf, 0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc0de6d7d, 0hc1b6d966, 0h4208695c, 0h419194b0,
0h419194b0, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h416b8e00, 0hc1d2a716, 0h41f50507, 0h416b8e00,
0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc19194b0, 0h40de6d7d, 0h41b6d966, 0hc208695c,
0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h406d72bf, 0h406d72bf, 0h41a58418, 0hc22076c5,
0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc0de6d7d, 0h419194b0, 0h4208695c, 0hc1b6d966,
0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h416b8e00, 0h416b8e00, 0h41f50507, 0hc1d2a716,
0hc16b8e00, 0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc19194b0, 0h41b6d966, 0hc208695c, 0h40de6d7d,
0h40de6d7d, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h406d72bf, 0h41a58418, 0hc22076c5, 0h406d72bf,
0hc06d72bf, 0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc0de6d7d, 0h4208695c, 0hc1b6d966, 0h419194b0,
0h419194b0, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h416b8e00, 0h41f50507, 0hc1d2a716, 0h416b8e00,
0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc19194b0, 0h41b6d966, 0h40de6d7d, 0hc208695c,
0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h406d72bf, 0h41a58418, 0h406d72bf, 0hc22076c5,
0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc0de6d7d, 0h4208695c, 0h419194b0, 0hc1b6d966,
0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h416b8e00, 0h41f50507, 0h416b8e00, 0hc1d2a716,
0h41d2a716, 0hc16b8e00, 0hc1f50507, 0hc16b8e00, 0h41b6d966, 0hc19194b0, 0hc208695c, 0h40de6d7d,
0h41b6d966, 0h40de6d7d, 0hc208695c, 0hc19194b0, 0h41a58418, 0h406d72bf, 0hc22076c5, 0h406d72bf,
0h422076c5, 0hc06d72bf, 0hc1a58418, 0hc06d72bf, 0h4208695c, 0hc0de6d7d, 0hc1b6d966, 0h419194b0,
0h4208695c, 0h419194b0, 0hc1b6d966, 0hc0de6d7d, 0h41f50507, 0h416b8e00, 0hc1d2a716, 0h416b8e00,
0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc1f50507, 0h41b6d966, 0hc19194b0, 0h40de6d7d, 0hc208695c,
0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc208695c, 0h41a58418, 0h406d72bf, 0h406d72bf, 0hc22076c5,
0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1a58418, 0h4208695c, 0hc0de6d7d, 0h419194b0, 0hc1b6d966,
0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1b6d966, 0h41f50507, 0h416b8e00, 0h416b8e00, 0hc1d2a716,
0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h4235739c, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d, 0h421c1252,
0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0b05c85, 0h419d18ee, 0h419d18ee, 0h420e2b7a,
0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h421c1252, 0h419d18ee, 0hc0b05c85, 0h419d18ee, 0h420e2b7a,
0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h418a0670, 0h418a0670, 0h418a0670, 0h4208ee18,
0h3fc4b564, 0h3fc4b564, 0h4235739c, 0h3fc4b564, 0hc0024b8d, 0h40024b8d, 0h421c1252, 0h41b8e69d,
0hc0024b8d, 0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0b05c85, 0h419d18ee, 0h420e2b7a, 0h419d18ee,
0h41b8e69d, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h419d18ee, 0hc0b05c85, 0h420e2b7a, 0h419d18ee,
0h419d18ee, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h418a0670, 0h418a0670, 0h4208ee18, 0h418a0670,
0h3fc4b564, 0h4235739c, 0h3fc4b564, 0h3fc4b564, 0hc0024b8d, 0h421c1252, 0hc0024b8d, 0h41b8e69d,
0hc0024b8d, 0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0b05c85, 0h420e2b7a, 0h419d18ee, 0h419d18ee,
0h41b8e69d, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h419d18ee, 0h420e2b7a, 0hc0b05c85, 0h419d18ee,
0h419d18ee, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h418a0670, 0h4208ee18, 0h418a0670, 0h418a0670,
0h4235739c, 0h3fc4b564, 0h3fc4b564, 0h3fc4b564, 0h421c1252, 0hc0024b8d, 0hc0024b8d, 0h41b8e69d,
0h421c1252, 0hc0024b8d, 0h41b8e69d, 0hc0024b8d, 0h420e2b7a, 0hc0b05c85, 0h419d18ee, 0h419d18ee,
0h421c1252, 0h41b8e69d, 0hc0024b8d, 0hc0024b8d, 0h420e2b7a, 0h419d18ee, 0hc0b05c85, 0h419d18ee,
0h420e2b7a, 0h419d18ee, 0h419d18ee, 0hc0b05c85, 0h4208ee18, 0h418a0670, 0h418a0670, 0h418a0670,
0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41d2a716, 0hc208695c, 0hc19194b0, 0h40de6d7d, 0h41b6d966,
0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41b6d966, 0hc22076c5, 0h406d72bf, 0h406d72bf, 0h41a58418,
0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h422076c5, 0hc1b6d966, 0hc0de6d7d, 0h419194b0, 0h4208695c,
0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h4208695c, 0hc1d2a716, 0h416b8e00, 0h416b8e00, 0h41f50507,
0hc1f50507, 0hc16b8e00, 0h41d2a716, 0hc16b8e00, 0hc208695c, 0hc19194b0, 0h41b6d966, 0h40de6d7d,
0hc208695c, 0h40de6d7d, 0h41b6d966, 0hc19194b0, 0hc22076c5, 0h406d72bf, 0h41a58418, 0h406d72bf,
0hc1a58418, 0hc06d72bf, 0h422076c5, 0hc06d72bf, 0hc1b6d966, 0hc0de6d7d, 0h4208695c, 0h419194b0,
0hc1b6d966, 0h419194b0, 0h4208695c, 0hc0de6d7d, 0hc1d2a716, 0h416b8e00, 0h41f50507, 0h416b8e00,
0hc1f50507, 0h41d2a716, 0hc16b8e00, 0hc16b8e00, 0hc208695c, 0h41b6d966, 0hc19194b0, 0h40de6d7d,
0hc208695c, 0h41b6d966, 0h40de6d7d, 0hc19194b0, 0hc22076c5, 0h41a58418, 0h406d72bf, 0h406d72bf,
0hc1a58418, 0h422076c5, 0hc06d72bf, 0hc06d72bf, 0hc1b6d966, 0h4208695c, 0hc0de6d7d, 0h419194b0,
0hc1b6d966, 0h4208695c, 0h419194b0, 0hc0de6d7d, 0hc1d2a716, 0h41f50507, 0h416b8e00, 0h416b8e00,
0h41d2a716, 0hc1f50507, 0hc16b8e00, 0hc16b8e00, 0h41b6d966, 0hc208695c, 0hc19194b0, 0h40de6d7d,
0h41b6d966, 0hc208695c, 0h40de6d7d, 0hc19194b0, 0h41a58418, 0hc22076c5, 0h406d72bf, 0h406d72bf,
0h422076c5, 0hc1a58418, 0hc06d72bf, 0hc06d72bf, 0h4208695c, 0hc1b6d966, 0hc0de6d7d, 0h419194b0,
0h4208695c, 0hc1b6d966, 0h419194b0, 0hc0de6d7d, 0h41f50507, 0hc1d2a716, 0h416b8e00, 0h416b8e00,
}
/*
2D Simplex noise base.
*/
_internal_noise_2d_unskewed_base :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Get base points and offsets.
base := [2]i64{fast_floor(coord.x), fast_floor(coord.y)}
i := [2]f32{f32(coord.x - f64(base.x)), f32(coord.y - f64(base.y))}
// Prime pre-multiplication for hash.
bp := base * [2]i64{PRIME_X, PRIME_Y}
// Unskew.
t := f32(i.x + i.y) * f32(UNSKEW_2D)
d0 := i + [2]f32{t, t}
// First vertex.
a0 := RSQUARED_2D - d0.x * d0.x - d0.y * d0.y
if a0 > 0 {
value = (a0 * a0) * (a0 * a0) * grad(seed, [2]i64{bp.x, bp.y}, d0)
}
// Second vertex.
a1 := f32(2 * (1 + 2 * UNSKEW_2D) * (1 / UNSKEW_2D + 2)) * t + f32(-2 * (1 + 2 * UNSKEW_2D) * (1 + 2 * UNSKEW_2D)) + a0
if a1 > 0 {
d1 := d0 - [2]f32{f32(1 + 2 * UNSKEW_2D), f32(1 + 2 * UNSKEW_2D)}
value += (a1 * a1) * (a1 * a1) * grad(seed, [2]i64{bp.x + PRIME_X, bp.y + PRIME_Y}, d1)
}
// Third vertex.
if d0.y > d0.x {
d2 := d0 - [2]f32{f32(UNSKEW_2D), f32(UNSKEW_2D + 1)}
a2 := RSQUARED_2D - d2.x * d2.x - d2.y * d2.y
if(a2 > 0) {
value += (a2 * a2) * (a2 * a2) * grad(seed, [2]i64{bp.x, bp.y + PRIME_Y}, d2)
}
} else {
d2 := d0 - [2]f32{f32(UNSKEW_2D + 1), f32(UNSKEW_2D)}
a2 := RSQUARED_2D - d2.x * d2.x - d2.y * d2.y
if(a2 > 0) {
value += (a2 * a2) * (a2 * a2) * grad(seed, [2]i64{bp.x + PRIME_X, bp.y}, d2)
}
}
return
}
/*
Generate overlapping cubic lattices for 3D OpenSimplex2 noise.
*/
_internal_noise_3d_unrotated_base :: proc(seed: i64, coord: Vec3) -> (value: f32) {
seed := seed
// Get base points and offsets.
// xr, yr, zr := coord.x, coord.y, coord.z
rb := [3]i64{fast_round(coord.x), fast_round(coord.y), fast_round(coord.z)}
ri := [3]f32{f32(coord.x - f64(rb.x)), f32(coord.y - f64(rb.y)), f32(coord.z - f64(rb.z))}
// -1 if positive, 1 if negative.
i_sign := [3]i64{i64(-1.0 - ri.x) | 1, i64(-1.0 - ri.y) | 1, i64(-1.0 - ri.z) | 1}
f_sign := [3]f32{f32(i_sign.x), f32(i_sign.y), f32(i_sign.z)}
// Compute absolute values, using the above as a shortcut. This was faster in my tests for some reason.
a0 := f_sign * -ri
// Prime pre-multiplication for hash.
rbp := rb * [3]i64{PRIME_X, PRIME_Y, PRIME_Z}
// Loop: Pick an edge on each lattice copy.
a := (RSQUARED_3D - ri.x * ri.x) - (ri.y * ri.y + ri.z * ri.z)
l := 0
for {
defer l += 1
// Closest point on cube.
if a > 0 {
a2 := a * a; a4 := a2 * a2
value += a4 * grad(seed, rbp, ri)
}
// Second-closest point.
if a0.x >= a0.y && a0.x >= a0.z {
b := a + a0.x + a0.x
if b > 1 {
b -= 1
b2 := b * b; b4 := b2 * b2
value += b4 * grad(seed, [3]i64{rbp.x - i_sign.x * PRIME_X, rbp.y, rbp.z}, [3]f32{ri.x + f_sign.x, ri.y, ri.z})
}
} else if a0.y > a0.x && a0.y >= a0.z {
b := a + a0.y + a0.y
if b > 1 {
b -= 1
b2 := b * b; b4 := b2 * b2
value += b4 * grad(seed, [3]i64{rbp.x, rbp.y - i_sign.y * PRIME_Y, rbp.z}, [3]f32{ri.x, ri.y + f_sign.y, ri.z})
}
} else {
b := a + a0.z + a0.z
if b > 1 {
b -= 1
b2 := b * b; b4 := b2 * b2
value += b4 * grad(seed, [3]i64{rbp.x, rbp.y, rbp.z - i_sign.z * PRIME_Z}, [3]f32{ri.x, ri.y, ri.z + f_sign.z})
}
}
// Break from loop if we're done, skipping updates below.
if l == 1 {
break
}
// Update absolute value.
a0 = 0.5 - a0
// Update relative coordinate.
ri = a0 * f_sign
// Update falloff.
a += (0.75 - a0.x) - (a0.y + a0.z)
// Update prime for hash.
rbp += [3]i64{i_sign.x >> 1, i_sign.y >> 1, i_sign.z >> 1} & {PRIME_X, PRIME_Y, PRIME_Z}
// Update the reverse sign indicators.
i_sign = -i_sign
f_sign = -f_sign
// And finally update the seed for the other lattice copy.
seed ~= SEED_FLIP_3D
}
return value
}
/*
4D OpenSimplex2 noise base.
*/
_internal_noise_4d_unskewed_base :: proc(seed: i64, coord: Vec4) -> (value: f32) {
seed := seed
// Get base points and offsets
base := [4]i64{fast_floor(coord.x), fast_floor(coord.y), fast_floor(coord.z), fast_floor(coord.w)}
si := [4]f32{f32(coord.x - f64(base.x)), f32(coord.y - f64(base.y)), f32(coord.z - f64(base.z)), f32(coord.w - f64(base.w))}
// Determine which lattice we can be confident has a contributing point its corresponding cell's base simplex.
// We only look at the spaces between the diagonal planes. This proved effective in all of my tests.
si_sum := (si.x + si.y) + (si.z + si.w)
starting_lattice := i64(si_sum * 1.25)
// Offset for seed based on first lattice copy.
seed += starting_lattice * SEED_OFFSET_4D
// Offset for lattice point relative positions (skewed)
starting_lattice_offset := f32(starting_lattice) * -LATTICE_STEP_4D
si += starting_lattice_offset
// Prep for vertex contributions.
ssi := (si_sum + starting_lattice_offset * 4) * UNSKEW_4D
// Prime pre-multiplication for hash.
svp := base * [4]i64{PRIME_X, PRIME_Y, PRIME_Z, PRIME_W}
// Five points to add, total, from five copies of the A4 lattice.
for i : i64 = 0; ; i += 1 {
// Next point is the closest vertex on the 4-simplex whose base vertex is the aforementioned vertex.
score := 1.0 + ssi * (-1.0 / UNSKEW_4D) // Seems slightly faster than 1.0-xsi-ysi-zsi-wsi
if si.x >= si.x && si.x >= si.z && si.x >= si.w && si.x >= score {
svp.x += PRIME_X
si.x -= 1
ssi -= UNSKEW_4D
}
else if si.y > si.x && si.y >= si.z && si.y >= si.w && si.y >= score {
svp.y += PRIME_Y
si.y -= 1
ssi -= UNSKEW_4D
}
else if si.z > si.x && si.z > si.y && si.z >= si.w && si.z >= score {
svp.z += PRIME_Z
si.z -= 1
ssi -= UNSKEW_4D
}
else if si.w > si.x && si.w > si.y && si.w > si.z && si.w >= score {
svp.w += PRIME_W
si.w -= 1
ssi -= UNSKEW_4D
}
// gradient contribution with falloff.
d := si + ssi
a := (d.x * d.x + d.y * d.y) + (d.z * d.z + d.w * d.w)
if a < RSQUARED_4D {
a -= RSQUARED_4D
a *= a; a4 := a * a
value += a4 * grad(seed, svp, d)
}
// Break from loop if we're done, skipping updates below.
if i == 4 {
break
}
// Update for next lattice copy shifted down by <-0.2, -0.2, -0.2, -0.2>.
si += LATTICE_STEP_4D
ssi += LATTICE_STEP_4D * 4 * UNSKEW_4D
seed -= SEED_OFFSET_4D
// Because we don't always start on the same lattice copy, there's a special reset case.
if i == starting_lattice {
svp -= {PRIME_X, PRIME_Y, PRIME_Z, PRIME_W}
seed += SEED_OFFSET_4D * 5
}
}
return
}
/*
Utility functions
*/
@(optimization_mode="speed")
grad_2d :: proc(seed: i64, svp: [2]i64, delta: [2]f32) -> (value: f32) {
hash := seed ~ svp.x ~ svp.y
hash *= HASH_MULTIPLIER
hash ~= hash >> (64 - N_GRADS_2D_EXPONENT + 1)
gi := hash & ((N_GRADS_2D - 1) << 1)
return GRADIENTS_2D[gi] * delta.x + GRADIENTS_2D[gi | 1] * delta.y
}
@(optimization_mode="speed")
grad_3d :: proc(seed: i64, rvp: [3]i64, delta: [3]f32) -> (value: f32) {
hash := (seed ~ rvp.x) ~ (rvp.y ~ rvp.z)
hash *= HASH_MULTIPLIER
hash ~= hash >> (64 - N_GRADS_3D_EXPONENT + 2)
gi := hash & ((N_GRADS_3D - 1) << 2)
return GRADIENTS_3D[gi] * delta.x + GRADIENTS_3D[gi | 1] * delta.y + GRADIENTS_3D[gi | 2] * delta.z
}
@(optimization_mode="speed")
grad_4d :: proc(seed: i64, svp: [4]i64, delta: [4]f32) -> (value: f32) {
hash := seed ~ (svp.x ~ svp.y) ~ (svp.z ~ svp.w)
hash *= HASH_MULTIPLIER
hash ~= hash >> (64 - N_GRADS_4D_EXPONENT + 2)
gi := hash & ((N_GRADS_4D - 1) << 2)
return (GRADIENTS_4D[gi] * delta.x + GRADIENTS_4D[gi | 1] * delta.y) + (GRADIENTS_4D[gi | 2] * delta.z + GRADIENTS_4D[gi | 3] * delta.w)
}
grad :: proc {grad_2d, grad_3d, grad_4d}
@(optimization_mode="speed")
fast_floor :: proc(x: f64) -> (floored: i64) {
xi := i64(x)
return x < f64(xi) ? xi - 1 : xi
}
@(optimization_mode="speed")
fast_round :: proc(x: f64) -> (rounded: i64) {
return x < 0 ? i64(x - 0.5) : i64(x + 0.5)
}
+171
View File
@@ -0,0 +1,171 @@
/*
OpenSimplex2 noise implementation.
Ported from https://github.com/KdotJPG/OpenSimplex2.
Copyright 2022 Yuki2 (https://github.com/NoahR02)
*/
package math_noise
/*
Input coordinate vectors
*/
Vec2 :: [2]f64
Vec3 :: [3]f64
Vec4 :: [4]f64
/*
Noise Evaluators
*/
/*
2D Simplex noise, standard lattice orientation.
*/
noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Get points for A2* lattice
skew := SKEW_2D * (coord.x + coord.y)
skewed := coord + skew
return _internal_noise_2d_unskewed_base(seed, skewed)
}
/*
2D Simplex noise, with Y pointing down the main diagonal.
Might be better for a 2D sandbox style game, where Y is vertical.
Probably slightly less optimal for heightmaps or continent maps,
unless your map is centered around an equator. It's a subtle
difference, but the option is here to make it an easy choice.
*/
noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Skew transform and rotation baked into one.
xx := coord.x * ROOT_2_OVER_2
yy := coord.y * (ROOT_2_OVER_2 * (1 + 2 * SKEW_2D))
return _internal_noise_2d_unskewed_base(seed, Vec2{yy + xx, yy - xx})
}
/*
3D OpenSimplex2 noise, with better visual isotropy in (X, Y).
Recommended for 3D terrain and time-varied animations.
The Z coordinate should always be the "different" coordinate in whatever your use case is.
If Y is vertical in world coordinates, call `noise_3d_improve_xz(x, z, Y)` or use `noise_3d_xz_before_y`.
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, y, Z)`.
For a time varied animation, call `noise_3d_improve_xz(x, y, T)`.
*/
noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/*
Re-orient the cubic lattices without skewing, so Z points up the main lattice diagonal,
and the planes formed by XY are moved far out of alignment with the cube faces.
Orthonormal rotation. Not a skew transform.
*/
xy := coord.x + coord.y
s2 := xy * ROTATE_3D_ORTHOGONALIZER
zz := coord.z * ROOT_3_OVER_3
r := Vec3{coord.x + s2 + zz, coord.y + s2 + zz, xy * -ROOT_3_OVER_3 + zz}
// Evaluate both lattices to form a BCC lattice.
return _internal_noise_3d_unrotated_base(seed, r)
}
/*
3D OpenSimplex2 noise, with better visual isotropy in (X, Z).
Recommended for 3D terrain and time-varied animations.
The Y coordinate should always be the "different" coordinate in whatever your use case is.
If Y is vertical in world coordinates, call `noise_3d_improve_xz(x, Y, z)`.
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, Z, y)` or use `noise_3d_improve_xy`.
For a time varied animation, call `noise_3d_improve_xz(x, T, y)` or use `noise_3d_improve_xy`.
*/
noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/*
Re-orient the cubic lattices without skewing, so Y points up the main lattice diagonal,
and the planes formed by XZ are moved far out of alignment with the cube faces.
Orthonormal rotation. Not a skew transform.
*/
xz := coord.x + coord.z
s2 := xz * ROTATE_3D_ORTHOGONALIZER
yy := coord.y * ROOT_3_OVER_3
r := Vec3{coord.x + s2 + yy, xz * -ROOT_3_OVER_3 + yy, coord.z + s2 + yy}
// Evaluate both lattices to form a BCC lattice.
return _internal_noise_3d_unrotated_base(seed, r)
}
/*
3D OpenSimplex2 noise, fallback rotation option
Use `noise_3d_improve_xy` or `noise_3d_improve_xz` instead, wherever appropriate.
They have less diagonal bias. This function's best use is as a fallback.
*/
noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/*
Re-orient the cubic lattices via rotation, to produce a familiar look.
Orthonormal rotation. Not a skew transform.
*/
bias := FALLBACK_ROTATE_3D * (coord.x + coord.y + coord.z)
biased := bias - coord
// Evaluate both lattices to form a BCC lattice.
return _internal_noise_3d_unrotated_base(seed, biased)
}
/*
4D OpenSimplex2 noise, with XYZ oriented like `noise_3d_improve_xy`
and W for an extra degree of freedom. W repeats eventually.
Recommended for time-varied animations which texture a 3D object (W=time)
in a space where Z is vertical.
*/
noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xy := coord.x + coord.y
s2 := xy * -0.21132486540518699998
zz := coord.z * 0.28867513459481294226
ww := coord.w * 0.2236067977499788
xr, yr : f64 = coord.x + (zz + ww + s2), coord.y + (zz + ww + s2)
zr : f64 = xy * -0.57735026918962599998 + (zz + ww)
wr : f64 = coord.z * -0.866025403784439 + ww
return _internal_noise_4d_unskewed_base(seed, Vec4{xr, yr, zr, wr})
}
/*
4D OpenSimplex2 noise, with XYZ oriented like `noise_3d_improve_xz`
and W for an extra degree of freedom. W repeats eventually.
Recommended for time-varied animations which texture a 3D object (W=time)
in a space where Y is vertical.
*/
noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xz := coord.x + coord.z
s2 := xz * -0.21132486540518699998
yy := coord.y * 0.28867513459481294226
ww := coord.w * 0.2236067977499788
xr, zr : f64 = coord.x + (yy + ww + s2), coord.z + (yy + ww + s2)
yr := xz * -0.57735026918962599998 + (yy + ww)
wr := coord.y * -0.866025403784439 + ww
return _internal_noise_4d_unskewed_base(seed, Vec4{xr, yr, zr, wr})
}
/*
4D OpenSimplex2 noise, with XYZ oriented like `noise_3d_fallback`
and W for an extra degree of freedom. W repeats eventually.
Recommended for time-varied animations which texture a 3D object (W=time)
where there isn't a clear distinction between horizontal and vertical
*/
noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xyz := coord.x + coord.y + coord.z
ww := coord.w * 0.2236067977499788
s2 := xyz * -0.16666666666666666 + ww
skewed := Vec4{coord.x + s2, coord.y + s2, coord.z + s2, -0.5 * xyz + ww}
return _internal_noise_4d_unskewed_base(seed, skewed)
}
/*
4D OpenSimplex2 noise, fallback lattice orientation.
*/
noise_4d_fallback :: proc(seed: i64, coord: Vec4) -> (value: f32) {
// Get points for A4 lattice
skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w)
return _internal_noise_4d_unskewed_base(seed, coord + skew)
}
+312
View File
@@ -0,0 +1,312 @@
package rand
import "core:math"
float64_uniform :: float64_range
float32_uniform :: float32_range
// Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution
float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64 {
if hi-lo == 0 {
return lo
}
lo, hi := lo, hi
u := float64(r)
c := f64(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
if u > c {
u = 1-u
c = 1-c
lo, hi = hi, lo
}
return lo + (hi - lo) * math.sqrt(u * c)
}
// Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution
float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32 {
if hi-lo == 0 {
return lo
}
lo, hi := lo, hi
u := float32(r)
c := f32(0.5) if mode == nil else clamp((mode.?-lo) / (hi-lo), 0, 1)
if u > c {
u = 1-u
c = 1-c
lo, hi = hi, lo
}
return lo + (hi - lo) * math.sqrt(u * c)
}
// Normal/Gaussian Distribution
float64_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
return norm_float64(r) * stddev + mean
}
// Normal/Gaussian Distribution
float32_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
return f32(float64_normal(f64(mean), f64(stddev), r))
}
// Log Normal Distribution
float64_log_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
return math.exp(float64_normal(mean, stddev, r))
}
// Log Normal Distribution
float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
return f32(float64_log_normal(f64(mean), f64(stddev), r))
}
// Exponential Distribution
// `lambda` is 1.0/(desired mean). It should be non-zero.
// Return values range from
// 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0
float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
return - math.ln(1 - float64(r)) / lambda
}
// Exponential Distribution
// `lambda` is 1.0/(desired mean). It should be non-zero.
// Return values range from
// 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0
float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
return f32(float64_exponential(f64(lambda), r))
}
// Gamma Distribution (NOT THE GAMMA FUNCTION)
//
// Required: alpha > 0 and beta > 0
//
// math.pow(x, alpha-1) * math.exp(-x / beta)
// pdf(x) = --------------------------------------------
// math.gamma(alpha) * math.pow(beta, alpha)
//
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0")
}
LOG4 :: 1.3862943611198906188344642429163531361510002687205105082413600189
SG_MAGIC_CONST :: 2.5040773967762740733732583523868748412194809812852436493487
switch {
case alpha > 1:
// R.C.H. Cheng, "The generation of Gamma variables with non-integral shape parameters", Applied Statistics, (1977), 26, No. 1, p71-74
ainv := math.sqrt(2 * alpha - 1)
bbb := alpha - LOG4
ccc := alpha + ainv
for {
u1 := float64(r)
if !(1e-7 < u1 && u1 < 0.9999999) {
continue
}
u2 := 1 - float64(r)
v := math.ln(u1 / (1 - u1)) / ainv
x := alpha * math.exp(v)
z := u1 * u1 * u2
t := bbb + ccc*v - x
if t + SG_MAGIC_CONST - 4.5 * z >= 0 || t >= math.ln(z) {
return x * beta
}
}
case alpha == 1:
// float64_exponential(1/beta)
return -math.ln(1 - float64(r)) * beta
case:
// ALGORITHM GS of Statistical Computing - Kennedy & Gentle
x: f64
for {
u := float64(r)
b := (math.e + alpha) / math.e
p := b * u
if p <= 1 {
x = math.pow(p, 1/alpha)
} else {
x = -math.ln((b - p) / alpha)
}
u1 := float64(r)
if p > 1 {
if u1 <= math.pow(x, alpha-1) {
break
}
} else if u1 <= math.exp(-x) {
break
}
}
return x * beta
}
}
// Gamma Distribution (NOT THE GAMMA FUNCTION)
//
// Required: alpha > 0 and beta > 0
//
// math.pow(x, alpha-1) * math.exp(-x / beta)
// pdf(x) = --------------------------------------------
// math.gamma(alpha) * math.pow(beta, alpha)
//
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_gamma(f64(alpha), f64(beta), r))
}
// Beta Distribution
//
// Required: alpha > 0 and beta > 0
//
// Return values range between 0 and 1
float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0")
}
// Knuth Vol 2 Ed 3 pg 134 "the beta distribution"
y := float64_gamma(alpha, 1.0, r)
if y != 0 {
return y / (y + float64_gamma(beta, 1.0, r))
}
return 0
}
// Beta Distribution
//
// Required: alpha > 0 and beta > 0
//
// Return values range between 0 and 1
float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_beta(f64(alpha), f64(beta), r))
}
// Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution
float64_pareto :: proc(alpha: f64, r: ^Rand = nil) -> f64 {
return math.pow(1 - float64(r), -1.0 / alpha)
}
// Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution
float32_pareto :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_pareto(f64(alpha), r))
}
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
float64_weibull :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
u := 1 - float64(r)
return alpha * math.pow(-math.ln(u), 1.0/beta)
}
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_weibull(f64(alpha), f64(beta), r))
}
// Circular Data (von Mises) Distribution
// `mean_angle` is the in mean angle between 0 and 2pi radians
// `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
// Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993.
mu := mean_angle
if kappa <= 1e-6 {
return math.TAU * float64(r)
}
s := 0.5 / kappa
t := s + math.sqrt(1 + s*s)
z: f64
for {
u1 := float64(r)
z = math.cos(math.TAU * 0.5 * u1)
d := z / (t + z)
u2 := float64(r)
if u2 < 1 - d*d || u2 <= (1-d)*math.exp(d) {
break
}
}
q := 1.0 / t
f := (q + z) / (1 + q*z)
u3 := float64(r)
if u3 > 0.5 {
return math.mod(mu + math.acos(f), math.TAU)
} else {
return math.mod(mu - math.acos(f), math.TAU)
}
}
// Circular Data (von Mises) Distribution
// `mean_angle` is the in mean angle between 0 and 2pi radians
// `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 {
return f32(float64_von_mises(f64(mean_angle), f64(kappa), r))
}
// Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
assert(gamma > 0)
// Calculated from the inverse CDF
return math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0
}
// Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), r))
}
// Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
float64_log_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
assert(gamma > 0)
return math.exp(math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0)
}
// Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), r))
}
// Laplace Distribution
// `b` is the scale where `b` > 0
float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 {
assert(b > 0)
p := float64(r)-0.5
return -math.sign(p)*math.ln(1 - 2*abs(p))*b + mean
}
// Laplace Distribution
// `b` is the scale where `b` > 0
float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
return f32(float64_laplace(f64(mean), f64(b), r))
}
// Gompertz Distribution
// `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0
float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 {
if eta <= 0 || b <= 0 {
panic(#procedure + ": eta and b must be > 0.0")
}
p := float64(r)
return math.ln(1 - math.ln(1 - p)/eta)/b
}
// Gompertz Distribution
// `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0
float32_gompertz :: proc(eta, b: f32, r: ^Rand = nil) -> f32 {
return f32(float64_gompertz(f64(eta), f64(b), r))
}

Some files were not shown because too many files have changed in this diff Show More